MCE Table Buttons - Version 3.2

Version Description

  • WordPress 4.0 support, including a much newer TinyMCE plugin, with many new features, including background color and horizontal alignment
  • Dramatically improved support for paragraphed content inside of a cell (paragraph breaks no longer disappear on save)
Download this release

Release Info

Developer jakemgold
Plugin Icon 128x128 MCE Table Buttons
Version 3.2
Comparing to
See all releases

Code changes from version 3.1 to 3.2

mce_table_buttons.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: MCE Table Buttons
4
  Plugin URI: http://10up.com/plugins-modules/wordpress-mce-table-buttons/
5
  Description: Add <strong>controls for table editing</strong> to the visual content editor with this <strong>light weight</strong> plug-in.
6
- Version: 3.1
7
  Author: Jake Goldman, 10up, Oomph
8
  Author URI: http://10up.com
9
  License: GPLv2 or later
@@ -39,7 +39,7 @@ class MCE_Table_Buttons {
39
  public static function _setup_plugin() {
40
  add_filter( 'mce_external_plugins', array( __CLASS__, 'mce_external_plugins' ) );
41
  add_filter( 'mce_buttons_2', array( __CLASS__, 'mce_buttons_2' ) );
42
- add_action( 'content_save_pre', array( __CLASS__, 'content_save_pre'), 100 );
43
  }
44
 
45
  /**
@@ -50,6 +50,7 @@ class MCE_Table_Buttons {
50
  */
51
  public static function mce_external_plugins( $plugin_array ) {
52
  global $tinymce_version;
 
53
 
54
  if ( version_compare( $tinymce_version, '400', '<' ) ) {
55
 
@@ -60,11 +61,14 @@ class MCE_Table_Buttons {
60
  $plugin_array['table'] = $plugin_dir_url . 'tinymce3-table/editor_plugin.js';
61
  $plugin_array['mcetablebuttons'] = $plugin_dir_url . 'tinymce3-assets/mce-table-buttons.js';
62
 
63
- } else {
64
 
65
- $variant = ( defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ) ? '' : '.min';
66
  $plugin_array['table'] = plugin_dir_url( __FILE__ ) . 'tinymce4-table/plugin' . $variant . '.js';
67
 
 
 
 
 
68
  }
69
 
70
  return $plugin_array;
@@ -116,8 +120,15 @@ class MCE_Table_Buttons {
116
  * @return string Editor content before WordPress massaging
117
  */
118
  public static function content_save_pre( $content ) {
119
- if ( substr( $content, -8 ) == '</table>' )
120
- $content .= "\n<br />";
 
 
 
 
 
 
 
121
 
122
  return $content;
123
  }
3
  Plugin Name: MCE Table Buttons
4
  Plugin URI: http://10up.com/plugins-modules/wordpress-mce-table-buttons/
5
  Description: Add <strong>controls for table editing</strong> to the visual content editor with this <strong>light weight</strong> plug-in.
6
+ Version: 3.2
7
  Author: Jake Goldman, 10up, Oomph
8
  Author URI: http://10up.com
9
  License: GPLv2 or later
39
  public static function _setup_plugin() {
40
  add_filter( 'mce_external_plugins', array( __CLASS__, 'mce_external_plugins' ) );
41
  add_filter( 'mce_buttons_2', array( __CLASS__, 'mce_buttons_2' ) );
42
+ add_filter( 'content_save_pre', array( __CLASS__, 'content_save_pre' ), 20 );
43
  }
44
 
45
  /**
50
  */
51
  public static function mce_external_plugins( $plugin_array ) {
52
  global $tinymce_version;
53
+ $variant = ( defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ) ? '' : '.min';
54
 
55
  if ( version_compare( $tinymce_version, '400', '<' ) ) {
56
 
61
  $plugin_array['table'] = $plugin_dir_url . 'tinymce3-table/editor_plugin.js';
62
  $plugin_array['mcetablebuttons'] = $plugin_dir_url . 'tinymce3-assets/mce-table-buttons.js';
63
 
64
+ } elseif ( version_compare( $tinymce_version, '4100', '<' ) ) {
65
 
 
66
  $plugin_array['table'] = plugin_dir_url( __FILE__ ) . 'tinymce4-table/plugin' . $variant . '.js';
67
 
68
+ } else {
69
+
70
+ $plugin_array['table'] = plugin_dir_url( __FILE__ ) . 'tinymce41-table/plugin' . $variant . '.js';
71
+
72
  }
73
 
74
  return $plugin_array;
120
  * @return string Editor content before WordPress massaging
121
  */
122
  public static function content_save_pre( $content ) {
123
+ if ( false !== strpos( $content, '<table' ) ) {
124
+ // paragraphed content inside of a td requires first paragraph to have extra line breaks (or else autop breaks)
125
+ $content = preg_replace( "/<td([^>]*)>(.+\r?\n\r?\n)/m", "<td$1>\n\n$2", $content );
126
+
127
+ // make sure there's space around the table
128
+ if ( substr( $content, -8 ) == '</table>' ) {
129
+ $content .= "\n<br />";
130
+ }
131
+ }
132
 
133
  return $content;
134
  }
readme.txt CHANGED
@@ -3,8 +3,8 @@ Contributors: jakemgold, 10up, thinkoomph
3
  Donate link: http://10up.com/plugins-modules/wordpress-mce-table-buttons/
4
  Tags: tables, table, editor, WYSIWYG, buttons, tinymce
5
  Requires at least: 3.4
6
- Tested up to: 3.9
7
- Stable tag: 3.1
8
 
9
  Adds table editing controls to the visual content editor (TinyMCE).
10
 
@@ -30,6 +30,10 @@ Note that the table controls are contained in the “kitchen sink” toolbar, to
30
 
31
  == Changelog ==
32
 
 
 
 
 
33
  = 3.1 =
34
  * Updated core TinyMCE table plugin from 4.0.20 to 4.0.21 in sync with WordPress - mostly bug and accessibility fixes
35
  * Refactored for compatibility with plugins like Advanced Custom Fields that do not use the_editor hook
3
  Donate link: http://10up.com/plugins-modules/wordpress-mce-table-buttons/
4
  Tags: tables, table, editor, WYSIWYG, buttons, tinymce
5
  Requires at least: 3.4
6
+ Tested up to: 4.0
7
+ Stable tag: 3.2
8
 
9
  Adds table editing controls to the visual content editor (TinyMCE).
10
 
30
 
31
  == Changelog ==
32
 
33
+ = 3.2 =
34
+ * WordPress 4.0 support, including a much newer TinyMCE plugin, with many new features, including background color and horizontal alignment
35
+ * Dramatically improved support for paragraphed content inside of a cell (paragraph breaks no longer disappear on save)
36
+
37
  = 3.1 =
38
  * Updated core TinyMCE table plugin from 4.0.20 to 4.0.21 in sync with WordPress - mostly bug and accessibility fixes
39
  * Refactored for compatibility with plugins like Advanced Custom Fields that do not use the_editor hook
tinymce41-table/plugin.js ADDED
@@ -0,0 +1,2680 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * Compiled inline version. (Library mode)
3
+ */
4
+
5
+ /*jshint smarttabs:true, undef:true, latedef:true, curly:true, bitwise:true, camelcase:true */
6
+ /*globals $code */
7
+
8
+ (function(exports, undefined) {
9
+ "use strict";
10
+
11
+ var modules = {};
12
+
13
+ function require(ids, callback) {
14
+ var module, defs = [];
15
+
16
+ for (var i = 0; i < ids.length; ++i) {
17
+ module = modules[ids[i]] || resolve(ids[i]);
18
+ if (!module) {
19
+ throw 'module definition dependecy not found: ' + ids[i];
20
+ }
21
+
22
+ defs.push(module);
23
+ }
24
+
25
+ callback.apply(null, defs);
26
+ }
27
+
28
+ function define(id, dependencies, definition) {
29
+ if (typeof id !== 'string') {
30
+ throw 'invalid module definition, module id must be defined and be a string';
31
+ }
32
+
33
+ if (dependencies === undefined) {
34
+ throw 'invalid module definition, dependencies must be specified';
35
+ }
36
+
37
+ if (definition === undefined) {
38
+ throw 'invalid module definition, definition function must be specified';
39
+ }
40
+
41
+ require(dependencies, function() {
42
+ modules[id] = definition.apply(null, arguments);
43
+ });
44
+ }
45
+
46
+ function defined(id) {
47
+ return !!modules[id];
48
+ }
49
+
50
+ function resolve(id) {
51
+ var target = exports;
52
+ var fragments = id.split(/[.\/]/);
53
+
54
+ for (var fi = 0; fi < fragments.length; ++fi) {
55
+ if (!target[fragments[fi]]) {
56
+ return;
57
+ }
58
+
59
+ target = target[fragments[fi]];
60
+ }
61
+
62
+ return target;
63
+ }
64
+
65
+ function expose(ids) {
66
+ for (var i = 0; i < ids.length; i++) {
67
+ var target = exports;
68
+ var id = ids[i];
69
+ var fragments = id.split(/[.\/]/);
70
+
71
+ for (var fi = 0; fi < fragments.length - 1; ++fi) {
72
+ if (target[fragments[fi]] === undefined) {
73
+ target[fragments[fi]] = {};
74
+ }
75
+
76
+ target = target[fragments[fi]];
77
+ }
78
+
79
+ target[fragments[fragments.length - 1]] = modules[id];
80
+ }
81
+ }
82
+
83
+ // Included from: js/tinymce/plugins/table/classes/TableGrid.js
84
+
85
+ /**
86
+ * TableGrid.js
87
+ *
88
+ * Copyright, Moxiecode Systems AB
89
+ * Released under LGPL License.
90
+ *
91
+ * License: http://www.tinymce.com/license
92
+ * Contributing: http://www.tinymce.com/contributing
93
+ */
94
+
95
+ /**
96
+ * This class creates a grid out of a table element. This
97
+ * makes it a whole lot easier to handle complex tables with
98
+ * col/row spans.
99
+ *
100
+ * @class tinymce.tableplugin.TableGrid
101
+ * @private
102
+ */
103
+ define("tinymce/tableplugin/TableGrid", [
104
+ "tinymce/util/Tools",
105
+ "tinymce/Env"
106
+ ], function(Tools, Env) {
107
+ var each = Tools.each;
108
+
109
+ function getSpanVal(td, name) {
110
+ return parseInt(td.getAttribute(name) || 1, 10);
111
+ }
112
+
113
+ return function(editor, table) {
114
+ var grid, gridWidth, startPos, endPos, selectedCell, selection = editor.selection, dom = selection.dom;
115
+
116
+ function buildGrid() {
117
+ var startY = 0;
118
+
119
+ grid = [];
120
+ gridWidth = 0;
121
+
122
+ each(['thead', 'tbody', 'tfoot'], function(part) {
123
+ var rows = dom.select('> ' + part + ' tr', table);
124
+
125
+ each(rows, function(tr, y) {
126
+ y += startY;
127
+
128
+ each(dom.select('> td, > th', tr), function(td, x) {
129
+ var x2, y2, rowspan, colspan;
130
+
131
+ // Skip over existing cells produced by rowspan
132
+ if (grid[y]) {
133
+ while (grid[y][x]) {
134
+ x++;
135
+ }
136
+ }
137
+
138
+ // Get col/rowspan from cell
139
+ rowspan = getSpanVal(td, 'rowspan');
140
+ colspan = getSpanVal(td, 'colspan');
141
+
142
+ // Fill out rowspan/colspan right and down
143
+ for (y2 = y; y2 < y + rowspan; y2++) {
144
+ if (!grid[y2]) {
145
+ grid[y2] = [];
146
+ }
147
+
148
+ for (x2 = x; x2 < x + colspan; x2++) {
149
+ grid[y2][x2] = {
150
+ part: part,
151
+ real: y2 == y && x2 == x,
152
+ elm: td,
153
+ rowspan: rowspan,
154
+ colspan: colspan
155
+ };
156
+ }
157
+ }
158
+
159
+ gridWidth = Math.max(gridWidth, x + 1);
160
+ });
161
+ });
162
+
163
+ startY += rows.length;
164
+ });
165
+ }
166
+
167
+ function cloneNode(node, children) {
168
+ node = node.cloneNode(children);
169
+ node.removeAttribute('id');
170
+
171
+ return node;
172
+ }
173
+
174
+ function getCell(x, y) {
175
+ var row;
176
+
177
+ row = grid[y];
178
+ if (row) {
179
+ return row[x];
180
+ }
181
+ }
182
+
183
+ function setSpanVal(td, name, val) {
184
+ if (td) {
185
+ val = parseInt(val, 10);
186
+
187
+ if (val === 1) {
188
+ td.removeAttribute(name, 1);
189
+ } else {
190
+ td.setAttribute(name, val, 1);
191
+ }
192
+ }
193
+ }
194
+
195
+ function isCellSelected(cell) {
196
+ return cell && (dom.hasClass(cell.elm, 'mce-item-selected') || cell == selectedCell);
197
+ }
198
+
199
+ function getSelectedRows() {
200
+ var rows = [];
201
+
202
+ each(table.rows, function(row) {
203
+ each(row.cells, function(cell) {
204
+ if (dom.hasClass(cell, 'mce-item-selected') || (selectedCell && cell == selectedCell.elm)) {
205
+ rows.push(row);
206
+ return false;
207
+ }
208
+ });
209
+ });
210
+
211
+ return rows;
212
+ }
213
+
214
+ function deleteTable() {
215
+ var rng = dom.createRng();
216
+
217
+ rng.setStartAfter(table);
218
+ rng.setEndAfter(table);
219
+
220
+ selection.setRng(rng);
221
+
222
+ dom.remove(table);
223
+ }
224
+
225
+ function cloneCell(cell) {
226
+ var formatNode, cloneFormats = {};
227
+
228
+ if (editor.settings.table_clone_elements !== false) {
229
+ cloneFormats = Tools.makeMap(
230
+ (editor.settings.table_clone_elements || 'strong em b i span font h1 h2 h3 h4 h5 h6 p div').toUpperCase(),
231
+ /[ ,]/
232
+ );
233
+ }
234
+
235
+ // Clone formats
236
+ Tools.walk(cell, function(node) {
237
+ var curNode;
238
+
239
+ if (node.nodeType == 3) {
240
+ each(dom.getParents(node.parentNode, null, cell).reverse(), function(node) {
241
+ if (!cloneFormats[node.nodeName]) {
242
+ return;
243
+ }
244
+
245
+ node = cloneNode(node, false);
246
+
247
+ if (!formatNode) {
248
+ formatNode = curNode = node;
249
+ } else if (curNode) {
250
+ curNode.appendChild(node);
251
+ }
252
+
253
+ curNode = node;
254
+ });
255
+
256
+ // Add something to the inner node
257
+ if (curNode) {
258
+ curNode.innerHTML = Env.ie ? '&nbsp;' : '<br data-mce-bogus="1" />';
259
+ }
260
+
261
+ return false;
262
+ }
263
+ }, 'childNodes');
264
+
265
+ cell = cloneNode(cell, false);
266
+ setSpanVal(cell, 'rowSpan', 1);
267
+ setSpanVal(cell, 'colSpan', 1);
268
+
269
+ if (formatNode) {
270
+ cell.appendChild(formatNode);
271
+ } else {
272
+ if (!Env.ie || Env.ie > 10) {
273
+ cell.innerHTML = '<br data-mce-bogus="1" />';
274
+ }
275
+ }
276
+
277
+ return cell;
278
+ }
279
+
280
+ function cleanup() {
281
+ var rng = dom.createRng(), row;
282
+
283
+ // Empty rows
284
+ each(dom.select('tr', table), function(tr) {
285
+ if (tr.cells.length === 0) {
286
+ dom.remove(tr);
287
+ }
288
+ });
289
+
290
+ // Empty table
291
+ if (dom.select('tr', table).length === 0) {
292
+ rng.setStartBefore(table);
293
+ rng.setEndBefore(table);
294
+ selection.setRng(rng);
295
+ dom.remove(table);
296
+ return;
297
+ }
298
+
299
+ // Empty header/body/footer
300
+ each(dom.select('thead,tbody,tfoot', table), function(part) {
301
+ if (part.rows.length === 0) {
302
+ dom.remove(part);
303
+ }
304
+ });
305
+
306
+ // Restore selection to start position if it still exists
307
+ buildGrid();
308
+
309
+ // If we have a valid startPos object
310
+ if (startPos) {
311
+ // Restore the selection to the closest table position
312
+ row = grid[Math.min(grid.length - 1, startPos.y)];
313
+ if (row) {
314
+ selection.select(row[Math.min(row.length - 1, startPos.x)].elm, true);
315
+ selection.collapse(true);
316
+ }
317
+ }
318
+ }
319
+
320
+ function fillLeftDown(x, y, rows, cols) {
321
+ var tr, x2, r, c, cell;
322
+
323
+ tr = grid[y][x].elm.parentNode;
324
+ for (r = 1; r <= rows; r++) {
325
+ tr = dom.getNext(tr, 'tr');
326
+
327
+ if (tr) {
328
+ // Loop left to find real cell
329
+ for (x2 = x; x2 >= 0; x2--) {
330
+ cell = grid[y + r][x2].elm;
331
+
332
+ if (cell.parentNode == tr) {
333
+ // Append clones after
334
+ for (c = 1; c <= cols; c++) {
335
+ dom.insertAfter(cloneCell(cell), cell);
336
+ }
337
+
338
+ break;
339
+ }
340
+ }
341
+
342
+ if (x2 == -1) {
343
+ // Insert nodes before first cell
344
+ for (c = 1; c <= cols; c++) {
345
+ tr.insertBefore(cloneCell(tr.cells[0]), tr.cells[0]);
346
+ }
347
+ }
348
+ }
349
+ }
350
+ }
351
+
352
+ function split() {
353
+ each(grid, function(row, y) {
354
+ each(row, function(cell, x) {
355
+ var colSpan, rowSpan, i;
356
+
357
+ if (isCellSelected(cell)) {
358
+ cell = cell.elm;
359
+ colSpan = getSpanVal(cell, 'colspan');
360
+ rowSpan = getSpanVal(cell, 'rowspan');
361
+
362
+ if (colSpan > 1 || rowSpan > 1) {
363
+ setSpanVal(cell, 'rowSpan', 1);
364
+ setSpanVal(cell, 'colSpan', 1);
365
+
366
+ // Insert cells right
367
+ for (i = 0; i < colSpan - 1; i++) {
368
+ dom.insertAfter(cloneCell(cell), cell);
369
+ }
370
+
371
+ fillLeftDown(x, y, rowSpan - 1, colSpan);
372
+ }
373
+ }
374
+ });
375
+ });
376
+ }
377
+
378
+ function merge(cell, cols, rows) {
379
+ var pos, startX, startY, endX, endY, x, y, startCell, endCell, children, count;
380
+
381
+ // Use specified cell and cols/rows
382
+ if (cell) {
383
+ pos = getPos(cell);
384
+ startX = pos.x;
385
+ startY = pos.y;
386
+ endX = startX + (cols - 1);
387
+ endY = startY + (rows - 1);
388
+ } else {
389
+ startPos = endPos = null;
390
+
391
+ // Calculate start/end pos by checking for selected cells in grid works better with context menu
392
+ each(grid, function(row, y) {
393
+ each(row, function(cell, x) {
394
+ if (isCellSelected(cell)) {
395
+ if (!startPos) {
396
+ startPos = {x: x, y: y};
397
+ }
398
+
399
+ endPos = {x: x, y: y};
400
+ }
401
+ });
402
+ });
403
+
404
+ // Use selection, but make sure startPos is valid before accessing
405
+ if (startPos) {
406
+ startX = startPos.x;
407
+ startY = startPos.y;
408
+ endX = endPos.x;
409
+ endY = endPos.y;
410
+ }
411
+ }
412
+
413
+ // Find start/end cells
414
+ startCell = getCell(startX, startY);
415
+ endCell = getCell(endX, endY);
416
+
417
+ // Check if the cells exists and if they are of the same part for example tbody = tbody
418
+ if (startCell && endCell && startCell.part == endCell.part) {
419
+ // Split and rebuild grid
420
+ split();
421
+ buildGrid();
422
+
423
+ // Set row/col span to start cell
424
+ startCell = getCell(startX, startY).elm;
425
+ setSpanVal(startCell, 'colSpan', (endX - startX) + 1);
426
+ setSpanVal(startCell, 'rowSpan', (endY - startY) + 1);
427
+
428
+ // Remove other cells and add it's contents to the start cell
429
+ for (y = startY; y <= endY; y++) {
430
+ for (x = startX; x <= endX; x++) {
431
+ if (!grid[y] || !grid[y][x]) {
432
+ continue;
433
+ }
434
+
435
+ cell = grid[y][x].elm;
436
+
437
+ /*jshint loopfunc:true */
438
+ /*eslint no-loop-func:0 */
439
+ if (cell != startCell) {
440
+ // Move children to startCell
441
+ children = Tools.grep(cell.childNodes);
442
+ each(children, function(node) {
443
+ startCell.appendChild(node);
444
+ });
445
+
446
+ // Remove bogus nodes if there is children in the target cell
447
+ if (children.length) {
448
+ children = Tools.grep(startCell.childNodes);
449
+ count = 0;
450
+ each(children, function(node) {
451
+ if (node.nodeName == 'BR' && dom.getAttrib(node, 'data-mce-bogus') && count++ < children.length - 1) {
452
+ startCell.removeChild(node);
453
+ }
454
+ });
455
+ }
456
+
457
+ dom.remove(cell);
458
+ }
459
+ }
460
+ }
461
+
462
+ // Remove empty rows etc and restore caret location
463
+ cleanup();
464
+ }
465
+ }
466
+
467
+ function insertRow(before) {
468
+ var posY, cell, lastCell, x, rowElm, newRow, newCell, otherCell, rowSpan;
469
+
470
+ // Find first/last row
471
+ each(grid, function(row, y) {
472
+ each(row, function(cell) {
473
+ if (isCellSelected(cell)) {
474
+ cell = cell.elm;
475
+ rowElm = cell.parentNode;
476
+ newRow = cloneNode(rowElm, false);
477
+ posY = y;
478
+
479
+ if (before) {
480
+ return false;
481
+ }
482
+ }
483
+ });
484
+
485
+ if (before) {
486
+ return !posY;
487
+ }
488
+ });
489
+
490
+ // If posY is undefined there is nothing for us to do here...just return to avoid crashing below
491
+ if (posY === undefined) {
492
+ return;
493
+ }
494
+
495
+ for (x = 0; x < grid[0].length; x++) {
496
+ // Cell not found could be because of an invalid table structure
497
+ if (!grid[posY][x]) {
498
+ continue;
499
+ }
500
+
501
+ cell = grid[posY][x].elm;
502
+
503
+ if (cell != lastCell) {
504
+ if (!before) {
505
+ rowSpan = getSpanVal(cell, 'rowspan');
506
+ if (rowSpan > 1) {
507
+ setSpanVal(cell, 'rowSpan', rowSpan + 1);
508
+ continue;
509
+ }
510
+ } else {
511
+ // Check if cell above can be expanded
512
+ if (posY > 0 && grid[posY - 1][x]) {
513
+ otherCell = grid[posY - 1][x].elm;
514
+ rowSpan = getSpanVal(otherCell, 'rowSpan');
515
+ if (rowSpan > 1) {
516
+ setSpanVal(otherCell, 'rowSpan', rowSpan + 1);
517
+ continue;
518
+ }
519
+ }
520
+ }
521
+
522
+ // Insert new cell into new row
523
+ newCell = cloneCell(cell);
524
+ setSpanVal(newCell, 'colSpan', cell.colSpan);
525
+
526
+ newRow.appendChild(newCell);
527
+
528
+ lastCell = cell;
529
+ }
530
+ }
531
+
532
+ if (newRow.hasChildNodes()) {
533
+ if (!before) {
534
+ dom.insertAfter(newRow, rowElm);
535
+ } else {
536
+ rowElm.parentNode.insertBefore(newRow, rowElm);
537
+ }
538
+ }
539
+ }
540
+
541
+ function insertCol(before) {
542
+ var posX, lastCell;
543
+
544
+ // Find first/last column
545
+ each(grid, function(row) {
546
+ each(row, function(cell, x) {
547
+ if (isCellSelected(cell)) {
548
+ posX = x;
549
+
550
+ if (before) {
551
+ return false;
552
+ }
553
+ }
554
+ });
555
+
556
+ if (before) {
557
+ return !posX;
558
+ }
559
+ });
560
+
561
+ each(grid, function(row, y) {
562
+ var cell, rowSpan, colSpan;
563
+
564
+ if (!row[posX]) {
565
+ return;
566
+ }
567
+
568
+ cell = row[posX].elm;
569
+ if (cell != lastCell) {
570
+ colSpan = getSpanVal(cell, 'colspan');
571
+ rowSpan = getSpanVal(cell, 'rowspan');
572
+
573
+ if (colSpan == 1) {
574
+ if (!before) {
575
+ dom.insertAfter(cloneCell(cell), cell);
576
+ fillLeftDown(posX, y, rowSpan - 1, colSpan);
577
+ } else {
578
+ cell.parentNode.insertBefore(cloneCell(cell), cell);
579
+ fillLeftDown(posX, y, rowSpan - 1, colSpan);
580
+ }
581
+ } else {
582
+ setSpanVal(cell, 'colSpan', cell.colSpan + 1);
583
+ }
584
+
585
+ lastCell = cell;
586
+ }
587
+ });
588
+ }
589
+
590
+ function deleteCols() {
591
+ var cols = [];
592
+
593
+ // Get selected column indexes
594
+ each(grid, function(row) {
595
+ each(row, function(cell, x) {
596
+ if (isCellSelected(cell) && Tools.inArray(cols, x) === -1) {
597
+ each(grid, function(row) {
598
+ var cell = row[x].elm, colSpan;
599
+
600
+ colSpan = getSpanVal(cell, 'colSpan');
601
+
602
+ if (colSpan > 1) {
603
+ setSpanVal(cell, 'colSpan', colSpan - 1);
604
+ } else {
605
+ dom.remove(cell);
606
+ }
607
+ });
608
+
609
+ cols.push(x);
610
+ }
611
+ });
612
+ });
613
+
614
+ cleanup();
615
+ }
616
+
617
+ function deleteRows() {
618
+ var rows;
619
+
620
+ function deleteRow(tr) {
621
+ var pos, lastCell;
622
+
623
+ // Move down row spanned cells
624
+ each(tr.cells, function(cell) {
625
+ var rowSpan = getSpanVal(cell, 'rowSpan');
626
+
627
+ if (rowSpan > 1) {
628
+ setSpanVal(cell, 'rowSpan', rowSpan - 1);
629
+ pos = getPos(cell);
630
+ fillLeftDown(pos.x, pos.y, 1, 1);
631
+ }
632
+ });
633
+
634
+ // Delete cells
635
+ pos = getPos(tr.cells[0]);
636
+ each(grid[pos.y], function(cell) {
637
+ var rowSpan;
638
+
639
+ cell = cell.elm;
640
+
641
+ if (cell != lastCell) {
642
+ rowSpan = getSpanVal(cell, 'rowSpan');
643
+
644
+ if (rowSpan <= 1) {
645
+ dom.remove(cell);
646
+ } else {
647
+ setSpanVal(cell, 'rowSpan', rowSpan - 1);
648
+ }
649
+
650
+ lastCell = cell;
651
+ }
652
+ });
653
+ }
654
+
655
+ // Get selected rows and move selection out of scope
656
+ rows = getSelectedRows();
657
+
658
+ // Delete all selected rows
659
+ each(rows.reverse(), function(tr) {
660
+ deleteRow(tr);
661
+ });
662
+
663
+ cleanup();
664
+ }
665
+
666
+ function cutRows() {
667
+ var rows = getSelectedRows();
668
+
669
+ dom.remove(rows);
670
+ cleanup();
671
+
672
+ return rows;
673
+ }
674
+
675
+ function copyRows() {
676
+ var rows = getSelectedRows();
677
+
678
+ each(rows, function(row, i) {
679
+ rows[i] = cloneNode(row, true);
680
+ });
681
+
682
+ return rows;
683
+ }
684
+
685
+ function pasteRows(rows, before) {
686
+ var selectedRows = getSelectedRows(),
687
+ targetRow = selectedRows[before ? 0 : selectedRows.length - 1],
688
+ targetCellCount = targetRow.cells.length;
689
+
690
+ // Nothing to paste
691
+ if (!rows) {
692
+ return;
693
+ }
694
+
695
+ // Calc target cell count
696
+ each(grid, function(row) {
697
+ var match;
698
+
699
+ targetCellCount = 0;
700
+ each(row, function(cell) {
701
+ if (cell.real) {
702
+ targetCellCount += cell.colspan;
703
+ }
704
+
705
+ if (cell.elm.parentNode == targetRow) {
706
+ match = 1;
707
+ }
708
+ });
709
+
710
+ if (match) {
711
+ return false;
712
+ }
713
+ });
714
+
715
+ if (!before) {
716
+ rows.reverse();
717
+ }
718
+
719
+ each(rows, function(row) {
720
+ var i, cellCount = row.cells.length, cell;
721
+
722
+ // Remove col/rowspans
723
+ for (i = 0; i < cellCount; i++) {
724
+ cell = row.cells[i];
725
+ setSpanVal(cell, 'colSpan', 1);
726
+ setSpanVal(cell, 'rowSpan', 1);
727
+ }
728
+
729
+ // Needs more cells
730
+ for (i = cellCount; i < targetCellCount; i++) {
731
+ row.appendChild(cloneCell(row.cells[cellCount - 1]));
732
+ }
733
+
734
+ // Needs less cells
735
+ for (i = targetCellCount; i < cellCount; i++) {
736
+ dom.remove(row.cells[i]);
737
+ }
738
+
739
+ // Add before/after
740
+ if (before) {
741
+ targetRow.parentNode.insertBefore(row, targetRow);
742
+ } else {
743
+ dom.insertAfter(row, targetRow);
744
+ }
745
+ });
746
+
747
+ // Remove current selection
748
+ dom.removeClass(dom.select('td.mce-item-selected,th.mce-item-selected'), 'mce-item-selected');
749
+ }
750
+
751
+ function getPos(target) {
752
+ var pos;
753
+
754
+ each(grid, function(row, y) {
755
+ each(row, function(cell, x) {
756
+ if (cell.elm == target) {
757
+ pos = {x : x, y : y};
758
+ return false;
759
+ }
760
+ });
761
+
762
+ return !pos;
763
+ });
764
+
765
+ return pos;
766
+ }
767
+
768
+ function setStartCell(cell) {
769
+ startPos = getPos(cell);
770
+ }
771
+
772
+ function findEndPos() {
773
+ var maxX, maxY;
774
+
775
+ maxX = maxY = 0;
776
+
777
+ each(grid, function(row, y) {
778
+ each(row, function(cell, x) {
779
+ var colSpan, rowSpan;
780
+
781
+ if (isCellSelected(cell)) {
782
+ cell = grid[y][x];
783
+
784
+ if (x > maxX) {
785
+ maxX = x;
786
+ }
787
+
788
+ if (y > maxY) {
789
+ maxY = y;
790
+ }
791
+
792
+ if (cell.real) {
793
+ colSpan = cell.colspan - 1;
794
+ rowSpan = cell.rowspan - 1;
795
+
796
+ if (colSpan) {
797
+ if (x + colSpan > maxX) {
798
+ maxX = x + colSpan;
799
+ }
800
+ }
801
+
802
+ if (rowSpan) {
803
+ if (y + rowSpan > maxY) {
804
+ maxY = y + rowSpan;
805
+ }
806
+ }
807
+ }
808
+ }
809
+ });
810
+ });
811
+
812
+ return {x : maxX, y : maxY};
813
+ }
814
+
815
+ function setEndCell(cell) {
816
+ var startX, startY, endX, endY, maxX, maxY, colSpan, rowSpan, x, y;
817
+
818
+ endPos = getPos(cell);
819
+
820
+ if (startPos && endPos) {
821
+ // Get start/end positions
822
+ startX = Math.min(startPos.x, endPos.x);
823
+ startY = Math.min(startPos.y, endPos.y);
824
+ endX = Math.max(startPos.x, endPos.x);
825
+ endY = Math.max(startPos.y, endPos.y);
826
+
827
+ // Expand end positon to include spans
828
+ maxX = endX;
829
+ maxY = endY;
830
+
831
+ // Expand startX
832
+ for (y = startY; y <= maxY; y++) {
833
+ cell = grid[y][startX];
834
+
835
+ if (!cell.real) {
836
+ if (startX - (cell.colspan - 1) < startX) {
837
+ startX -= cell.colspan - 1;
838
+ }
839
+ }
840
+ }
841
+
842
+ // Expand startY
843
+ for (x = startX; x <= maxX; x++) {
844
+ cell = grid[startY][x];
845
+
846
+ if (!cell.real) {
847
+ if (startY - (cell.rowspan - 1) < startY) {
848
+ startY -= cell.rowspan - 1;
849
+ }
850
+ }
851
+ }
852
+
853
+ // Find max X, Y
854
+ for (y = startY; y <= endY; y++) {
855
+ for (x = startX; x <= endX; x++) {
856
+ cell = grid[y][x];
857
+
858
+ if (cell.real) {
859
+ colSpan = cell.colspan - 1;
860
+ rowSpan = cell.rowspan - 1;
861
+
862
+ if (colSpan) {
863
+ if (x + colSpan > maxX) {
864
+ maxX = x + colSpan;
865
+ }
866
+ }
867
+
868
+ if (rowSpan) {
869
+ if (y + rowSpan > maxY) {
870
+ maxY = y + rowSpan;
871
+ }
872
+ }
873
+ }
874
+ }
875
+ }
876
+
877
+ // Remove current selection
878
+ dom.removeClass(dom.select('td.mce-item-selected,th.mce-item-selected'), 'mce-item-selected');
879
+
880
+ // Add new selection
881
+ for (y = startY; y <= maxY; y++) {
882
+ for (x = startX; x <= maxX; x++) {
883
+ if (grid[y][x]) {
884
+ dom.addClass(grid[y][x].elm, 'mce-item-selected');
885
+ }
886
+ }
887
+ }
888
+ }
889
+ }
890
+
891
+ function moveRelIdx(cellElm, delta) {
892
+ var pos, index, cell;
893
+
894
+ pos = getPos(cellElm);
895
+ index = pos.y * gridWidth + pos.x;
896
+
897
+ do {
898
+ index += delta;
899
+ cell = getCell(index % gridWidth, Math.floor(index / gridWidth));
900
+
901
+ if (!cell) {
902
+ break;
903
+ }
904
+
905
+ if (cell.elm != cellElm) {
906
+ selection.select(cell.elm, true);
907
+
908
+ if (dom.isEmpty(cell.elm)) {
909
+ selection.collapse(true);
910
+ }
911
+
912
+ return true;
913
+ }
914
+ } while (cell.elm == cellElm);
915
+
916
+ return false;
917
+ }
918
+
919
+ table = table || dom.getParent(selection.getStart(), 'table');
920
+
921
+ buildGrid();
922
+
923
+ selectedCell = dom.getParent(selection.getStart(), 'th,td');
924
+ if (selectedCell) {
925
+ startPos = getPos(selectedCell);
926
+ endPos = findEndPos();
927
+ selectedCell = getCell(startPos.x, startPos.y);
928
+ }
929
+
930
+ Tools.extend(this, {
931
+ deleteTable: deleteTable,
932
+ split: split,
933
+ merge: merge,
934
+ insertRow: insertRow,
935
+ insertCol: insertCol,
936
+ deleteCols: deleteCols,
937
+ deleteRows: deleteRows,
938
+ cutRows: cutRows,
939
+ copyRows: copyRows,
940
+ pasteRows: pasteRows,
941
+ getPos: getPos,
942
+ setStartCell: setStartCell,
943
+ setEndCell: setEndCell,
944
+ moveRelIdx: moveRelIdx,
945
+ refresh: buildGrid
946
+ });
947
+ };
948
+ });
949
+
950
+ // Included from: js/tinymce/plugins/table/classes/Quirks.js
951
+
952
+ /**
953
+ * Quirks.js
954
+ *
955
+ * Copyright, Moxiecode Systems AB
956
+ * Released under LGPL License.
957
+ *
958
+ * License: http://www.tinymce.com/license
959
+ * Contributing: http://www.tinymce.com/contributing
960
+ */
961
+
962
+ /**
963
+ * This class includes fixes for various browser quirks.
964
+ *
965
+ * @class tinymce.tableplugin.Quirks
966
+ * @private
967
+ */
968
+ define("tinymce/tableplugin/Quirks", [
969
+ "tinymce/util/VK",
970
+ "tinymce/Env",
971
+ "tinymce/util/Tools"
972
+ ], function(VK, Env, Tools) {
973
+ var each = Tools.each;
974
+
975
+ function getSpanVal(td, name) {
976
+ return parseInt(td.getAttribute(name) || 1, 10);
977
+ }
978
+
979
+ return function(editor) {
980
+ /**
981
+ * Fixed caret movement around tables on WebKit.
982
+ */
983
+ function moveWebKitSelection() {
984
+ function eventHandler(e) {
985
+ var key = e.keyCode;
986
+
987
+ function handle(upBool, sourceNode) {
988
+ var siblingDirection = upBool ? 'previousSibling' : 'nextSibling';
989
+ var currentRow = editor.dom.getParent(sourceNode, 'tr');
990
+ var siblingRow = currentRow[siblingDirection];
991
+
992
+ if (siblingRow) {
993
+ moveCursorToRow(editor, sourceNode, siblingRow, upBool);
994
+ e.preventDefault();
995
+ return true;
996
+ } else {
997
+ var tableNode = editor.dom.getParent(currentRow, 'table');
998
+ var middleNode = currentRow.parentNode;
999
+ var parentNodeName = middleNode.nodeName.toLowerCase();
1000
+ if (parentNodeName === 'tbody' || parentNodeName === (upBool ? 'tfoot' : 'thead')) {
1001
+ var targetParent = getTargetParent(upBool, tableNode, middleNode, 'tbody');
1002
+ if (targetParent !== null) {
1003
+ return moveToRowInTarget(upBool, targetParent, sourceNode);
1004
+ }
1005
+ }
1006
+ return escapeTable(upBool, currentRow, siblingDirection, tableNode);
1007
+ }
1008
+ }
1009
+
1010
+ function getTargetParent(upBool, topNode, secondNode, nodeName) {
1011
+ var tbodies = editor.dom.select('>' + nodeName, topNode);
1012
+ var position = tbodies.indexOf(secondNode);
1013
+ if (upBool && position === 0 || !upBool && position === tbodies.length - 1) {
1014
+ return getFirstHeadOrFoot(upBool, topNode);
1015
+ } else if (position === -1) {
1016
+ var topOrBottom = secondNode.tagName.toLowerCase() === 'thead' ? 0 : tbodies.length - 1;
1017
+ return tbodies[topOrBottom];
1018
+ } else {
1019
+ return tbodies[position + (upBool ? -1 : 1)];
1020
+ }
1021
+ }
1022
+
1023
+ function getFirstHeadOrFoot(upBool, parent) {
1024
+ var tagName = upBool ? 'thead' : 'tfoot';
1025
+ var headOrFoot = editor.dom.select('>' + tagName, parent);
1026
+ return headOrFoot.length !== 0 ? headOrFoot[0] : null;
1027
+ }
1028
+
1029
+ function moveToRowInTarget(upBool, targetParent, sourceNode) {
1030
+ var targetRow = getChildForDirection(targetParent, upBool);
1031
+
1032
+ if (targetRow) {
1033
+ moveCursorToRow(editor, sourceNode, targetRow, upBool);
1034
+ }
1035
+
1036
+ e.preventDefault();
1037
+ return true;
1038
+ }
1039
+
1040
+ function escapeTable(upBool, currentRow, siblingDirection, table) {
1041
+ var tableSibling = table[siblingDirection];
1042
+
1043
+ if (tableSibling) {
1044
+ moveCursorToStartOfElement(tableSibling);
1045
+ return true;
1046
+ } else {
1047
+ var parentCell = editor.dom.getParent(table, 'td,th');
1048
+ if (parentCell) {
1049
+ return handle(upBool, parentCell, e);
1050
+ } else {
1051
+ var backUpSibling = getChildForDirection(currentRow, !upBool);
1052
+ moveCursorToStartOfElement(backUpSibling);
1053
+ e.preventDefault();
1054
+ return false;
1055
+ }
1056
+ }
1057
+ }
1058
+
1059
+ function getChildForDirection(parent, up) {
1060
+ var child = parent && parent[up ? 'lastChild' : 'firstChild'];
1061
+ // BR is not a valid table child to return in this case we return the table cell
1062
+ return child && child.nodeName === 'BR' ? editor.dom.getParent(child, 'td,th') : child;
1063
+ }
1064
+
1065
+ function moveCursorToStartOfElement(n) {
1066
+ editor.selection.setCursorLocation(n, 0);
1067
+ }
1068
+
1069
+ function isVerticalMovement() {
1070
+ return key == VK.UP || key == VK.DOWN;
1071
+ }
1072
+
1073
+ function isInTable(editor) {
1074
+ var node = editor.selection.getNode();
1075
+ var currentRow = editor.dom.getParent(node, 'tr');
1076
+ return currentRow !== null;
1077
+ }
1078
+
1079
+ function columnIndex(column) {
1080
+ var colIndex = 0;
1081
+ var c = column;
1082
+ while (c.previousSibling) {
1083
+ c = c.previousSibling;
1084
+ colIndex = colIndex + getSpanVal(c, "colspan");
1085
+ }
1086
+ return colIndex;
1087
+ }
1088
+
1089
+ function findColumn(rowElement, columnIndex) {
1090
+ var c = 0, r = 0;
1091
+
1092
+ each(rowElement.children, function(cell, i) {
1093
+ c = c + getSpanVal(cell, "colspan");
1094
+ r = i;
1095
+ if (c > columnIndex) {
1096
+ return false;
1097
+ }
1098
+ });
1099
+ return r;
1100
+ }
1101
+
1102
+ function moveCursorToRow(ed, node, row, upBool) {
1103
+ var srcColumnIndex = columnIndex(editor.dom.getParent(node, 'td,th'));
1104
+ var tgtColumnIndex = findColumn(row, srcColumnIndex);
1105
+ var tgtNode = row.childNodes[tgtColumnIndex];
1106
+ var rowCellTarget = getChildForDirection(tgtNode, upBool);
1107
+ moveCursorToStartOfElement(rowCellTarget || tgtNode);
1108
+ }
1109
+
1110
+ function shouldFixCaret(preBrowserNode) {
1111
+ var newNode = editor.selection.getNode();
1112
+ var newParent = editor.dom.getParent(newNode, 'td,th');
1113
+ var oldParent = editor.dom.getParent(preBrowserNode, 'td,th');
1114
+
1115
+ return newParent && newParent !== oldParent && checkSameParentTable(newParent, oldParent);
1116
+ }
1117
+
1118
+ function checkSameParentTable(nodeOne, NodeTwo) {
1119
+ return editor.dom.getParent(nodeOne, 'TABLE') === editor.dom.getParent(NodeTwo, 'TABLE');
1120
+ }
1121
+
1122
+ if (isVerticalMovement() && isInTable(editor)) {
1123
+ var preBrowserNode = editor.selection.getNode();
1124
+ setTimeout(function() {
1125
+ if (shouldFixCaret(preBrowserNode)) {
1126
+ handle(!e.shiftKey && key === VK.UP, preBrowserNode, e);
1127
+ }
1128
+ }, 0);
1129
+ }
1130
+ }
1131
+
1132
+ editor.on('KeyDown', function(e) {
1133
+ eventHandler(e);
1134
+ });
1135
+ }
1136
+
1137
+ function fixBeforeTableCaretBug() {
1138
+ // Checks if the selection/caret is at the start of the specified block element
1139
+ function isAtStart(rng, par) {
1140
+ var doc = par.ownerDocument, rng2 = doc.createRange(), elm;
1141
+
1142
+ rng2.setStartBefore(par);
1143
+ rng2.setEnd(rng.endContainer, rng.endOffset);
1144
+
1145
+ elm = doc.createElement('body');
1146
+ elm.appendChild(rng2.cloneContents());
1147
+
1148
+ // Check for text characters of other elements that should be treated as content
1149
+ return elm.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi, '-').replace(/<[^>]+>/g, '').length === 0;
1150
+ }
1151
+
1152
+ // Fixes an bug where it's impossible to place the caret before a table in Gecko
1153
+ // this fix solves it by detecting when the caret is at the beginning of such a table
1154
+ // and then manually moves the caret infront of the table
1155
+ editor.on('KeyDown', function(e) {
1156
+ var rng, table, dom = editor.dom;
1157
+
1158
+ // On gecko it's not possible to place the caret before a table
1159
+ if (e.keyCode == 37 || e.keyCode == 38) {
1160
+ rng = editor.selection.getRng();
1161
+ table = dom.getParent(rng.startContainer, 'table');
1162
+
1163
+ if (table && editor.getBody().firstChild == table) {
1164
+ if (isAtStart(rng, table)) {
1165
+ rng = dom.createRng();
1166
+
1167
+ rng.setStartBefore(table);
1168
+ rng.setEndBefore(table);
1169
+
1170
+ editor.selection.setRng(rng);
1171
+
1172
+ e.preventDefault();
1173
+ }
1174
+ }
1175
+ }
1176
+ });
1177
+ }
1178
+
1179
+ // Fixes an issue on Gecko where it's impossible to place the caret behind a table
1180
+ // This fix will force a paragraph element after the table but only when the forced_root_block setting is enabled
1181
+ function fixTableCaretPos() {
1182
+ editor.on('KeyDown SetContent VisualAid', function() {
1183
+ var last;
1184
+
1185
+ // Skip empty text nodes from the end
1186
+ for (last = editor.getBody().lastChild; last; last = last.previousSibling) {
1187
+ if (last.nodeType == 3) {
1188
+ if (last.nodeValue.length > 0) {
1189
+ break;
1190
+ }
1191
+ } else if (last.nodeType == 1 && (last.tagName == 'BR' || !last.getAttribute('data-mce-bogus'))) {
1192
+ break;
1193
+ }
1194
+ }
1195
+
1196
+ if (last && last.nodeName == 'TABLE') {
1197
+ if (editor.settings.forced_root_block) {
1198
+ editor.dom.add(
1199
+ editor.getBody(),
1200
+ editor.settings.forced_root_block,
1201
+ editor.settings.forced_root_block_attrs,
1202
+ Env.ie && Env.ie < 11 ? '&nbsp;' : '<br data-mce-bogus="1" />'
1203
+ );
1204
+ } else {
1205
+ editor.dom.add(editor.getBody(), 'br', {'data-mce-bogus': '1'});
1206
+ }
1207
+ }
1208
+ });
1209
+
1210
+ editor.on('PreProcess', function(o) {
1211
+ var last = o.node.lastChild;
1212
+
1213
+ if (last && (last.nodeName == "BR" || (last.childNodes.length == 1 &&
1214
+ (last.firstChild.nodeName == 'BR' || last.firstChild.nodeValue == '\u00a0'))) &&
1215
+ last.previousSibling && last.previousSibling.nodeName == "TABLE") {
1216
+ editor.dom.remove(last);
1217
+ }
1218
+ });
1219
+ }
1220
+
1221
+ // this nasty hack is here to work around some WebKit selection bugs.
1222
+ function fixTableCellSelection() {
1223
+ function tableCellSelected(ed, rng, n, currentCell) {
1224
+ // The decision of when a table cell is selected is somewhat involved. The fact that this code is
1225
+ // required is actually a pointer to the root cause of this bug. A cell is selected when the start
1226
+ // and end offsets are 0, the start container is a text, and the selection node is either a TR (most cases)
1227
+ // or the parent of the table (in the case of the selection containing the last cell of a table).
1228
+ var TEXT_NODE = 3, table = ed.dom.getParent(rng.startContainer, 'TABLE');
1229
+ var tableParent, allOfCellSelected, tableCellSelection;
1230
+
1231
+ if (table) {
1232
+ tableParent = table.parentNode;
1233
+ }
1234
+
1235
+ allOfCellSelected = rng.startContainer.nodeType == TEXT_NODE &&
1236
+ rng.startOffset === 0 &&
1237
+ rng.endOffset === 0 &&
1238
+ currentCell &&
1239
+ (n.nodeName == "TR" || n == tableParent);
1240
+
1241
+ tableCellSelection = (n.nodeName == "TD" || n.nodeName == "TH") && !currentCell;
1242
+
1243
+ return allOfCellSelected || tableCellSelection;
1244
+ }
1245
+
1246
+ function fixSelection() {
1247
+ var rng = editor.selection.getRng();
1248
+ var n = editor.selection.getNode();
1249
+ var currentCell = editor.dom.getParent(rng.startContainer, 'TD,TH');
1250
+
1251
+ if (!tableCellSelected(editor, rng, n, currentCell)) {
1252
+ return;
1253
+ }
1254
+
1255
+ if (!currentCell) {
1256
+ currentCell = n;
1257
+ }
1258
+
1259
+ // Get the very last node inside the table cell
1260
+ var end = currentCell.lastChild;
1261
+ while (end.lastChild) {
1262
+ end = end.lastChild;
1263
+ }
1264
+
1265
+ // Select the entire table cell. Nothing outside of the table cell should be selected.
1266
+ if (end.nodeType == 3) {
1267
+ rng.setEnd(end, end.data.length);
1268
+ editor.selection.setRng(rng);
1269
+ }
1270
+ }
1271
+
1272
+ editor.on('KeyDown', function() {
1273
+ fixSelection();
1274
+ });
1275
+
1276
+ editor.on('MouseDown', function(e) {
1277
+ if (e.button != 2) {
1278
+ fixSelection();
1279
+ }
1280
+ });
1281
+ }
1282
+
1283
+ /**
1284
+ * Delete table if all cells are selected.
1285
+ */
1286
+ function deleteTable() {
1287
+ editor.on('keydown', function(e) {
1288
+ if ((e.keyCode == VK.DELETE || e.keyCode == VK.BACKSPACE) && !e.isDefaultPrevented()) {
1289
+ var table = editor.dom.getParent(editor.selection.getStart(), 'table');
1290
+
1291
+ if (table) {
1292
+ var cells = editor.dom.select('td,th', table), i = cells.length;
1293
+ while (i--) {
1294
+ if (!editor.dom.hasClass(cells[i], 'mce-item-selected')) {
1295
+ return;
1296
+ }
1297
+ }
1298
+
1299
+ e.preventDefault();
1300
+ editor.execCommand('mceTableDelete');
1301
+ }
1302
+ }
1303
+ });
1304
+ }
1305
+
1306
+ deleteTable();
1307
+
1308
+ if (Env.webkit) {
1309
+ moveWebKitSelection();
1310
+ fixTableCellSelection();
1311
+ }
1312
+
1313
+ if (Env.gecko) {
1314
+ fixBeforeTableCaretBug();
1315
+ fixTableCaretPos();
1316
+ }
1317
+
1318
+ if (Env.ie > 10) {
1319
+ fixBeforeTableCaretBug();
1320
+ fixTableCaretPos();
1321
+ }
1322
+ };
1323
+ });
1324
+
1325
+ // Included from: js/tinymce/plugins/table/classes/CellSelection.js
1326
+
1327
+ /**
1328
+ * CellSelection.js
1329
+ *
1330
+ * Copyright, Moxiecode Systems AB
1331
+ * Released under LGPL License.
1332
+ *
1333
+ * License: http://www.tinymce.com/license
1334
+ * Contributing: http://www.tinymce.com/contributing
1335
+ */
1336
+
1337
+ /**
1338
+ * This class handles table cell selection by faking it using a css class that gets applied
1339
+ * to cells when dragging the mouse from one cell to another.
1340
+ *
1341
+ * @class tinymce.tableplugin.CellSelection
1342
+ * @private
1343
+ */
1344
+ define("tinymce/tableplugin/CellSelection", [
1345
+ "tinymce/tableplugin/TableGrid",
1346
+ "tinymce/dom/TreeWalker",
1347
+ "tinymce/util/Tools"
1348
+ ], function(TableGrid, TreeWalker, Tools) {
1349
+ return function(editor) {
1350
+ var dom = editor.dom, tableGrid, startCell, startTable, hasCellSelection = true, resizing;
1351
+
1352
+ function clear(force) {
1353
+ // Restore selection possibilities
1354
+ editor.getBody().style.webkitUserSelect = '';
1355
+
1356
+ if (force || hasCellSelection) {
1357
+ editor.dom.removeClass(
1358
+ editor.dom.select('td.mce-item-selected,th.mce-item-selected'),
1359
+ 'mce-item-selected'
1360
+ );
1361
+
1362
+ hasCellSelection = false;
1363
+ }
1364
+ }
1365
+
1366
+ function cellSelectionHandler(e) {
1367
+ var sel, table, target = e.target;
1368
+
1369
+ if (resizing) {
1370
+ return;
1371
+ }
1372
+
1373
+ if (startCell && (tableGrid || target != startCell) && (target.nodeName == 'TD' || target.nodeName == 'TH')) {
1374
+ table = dom.getParent(target, 'table');
1375
+ if (table == startTable) {
1376
+ if (!tableGrid) {
1377
+ tableGrid = new TableGrid(editor, table);
1378
+ tableGrid.setStartCell(startCell);
1379
+
1380
+ editor.getBody().style.webkitUserSelect = 'none';
1381
+ }
1382
+
1383
+ tableGrid.setEndCell(target);
1384
+ hasCellSelection = true;
1385
+ }
1386
+
1387
+ // Remove current selection
1388
+ sel = editor.selection.getSel();
1389
+
1390
+ try {
1391
+ if (sel.removeAllRanges) {
1392
+ sel.removeAllRanges();
1393
+ } else {
1394
+ sel.empty();
1395
+ }
1396
+ } catch (ex) {
1397
+ // IE9 might throw errors here
1398
+ }
1399
+
1400
+ e.preventDefault();
1401
+ }
1402
+ }
1403
+
1404
+ // Add cell selection logic
1405
+ editor.on('MouseDown', function(e) {
1406
+ if (e.button != 2 && !resizing) {
1407
+ clear();
1408
+
1409
+ startCell = dom.getParent(e.target, 'td,th');
1410
+ startTable = dom.getParent(startCell, 'table');
1411
+ }
1412
+ });
1413
+
1414
+ editor.on('mouseover', cellSelectionHandler);
1415
+
1416
+ editor.on('remove', function() {
1417
+ dom.unbind(editor.getDoc(), 'mouseover', cellSelectionHandler);
1418
+ });
1419
+
1420
+ editor.on('MouseUp', function() {
1421
+ var rng, sel = editor.selection, selectedCells, walker, node, lastNode;
1422
+
1423
+ function setPoint(node, start) {
1424
+ var walker = new TreeWalker(node, node);
1425
+
1426
+ do {
1427
+ // Text node
1428
+ if (node.nodeType == 3 && Tools.trim(node.nodeValue).length !== 0) {
1429
+ if (start) {
1430
+ rng.setStart(node, 0);
1431
+ } else {
1432
+ rng.setEnd(node, node.nodeValue.length);
1433
+ }
1434
+
1435
+ return;
1436
+ }
1437
+
1438
+ // BR element
1439
+ if (node.nodeName == 'BR') {
1440
+ if (start) {
1441
+ rng.setStartBefore(node);
1442
+ } else {
1443
+ rng.setEndBefore(node);
1444
+ }
1445
+
1446
+ return;
1447
+ }
1448
+ } while ((node = (start ? walker.next() : walker.prev())));
1449
+ }
1450
+
1451
+ // Move selection to startCell
1452
+ if (startCell) {
1453
+ if (tableGrid) {
1454
+ editor.getBody().style.webkitUserSelect = '';
1455
+ }
1456
+
1457
+ // Try to expand text selection as much as we can only Gecko supports cell selection
1458
+ selectedCells = dom.select('td.mce-item-selected,th.mce-item-selected');
1459
+ if (selectedCells.length > 0) {
1460
+ rng = dom.createRng();
1461
+ node = selectedCells[0];
1462
+ rng.setStartBefore(node);
1463
+ rng.setEndAfter(node);
1464
+
1465
+ setPoint(node, 1);
1466
+ walker = new TreeWalker(node, dom.getParent(selectedCells[0], 'table'));
1467
+
1468
+ do {
1469
+ if (node.nodeName == 'TD' || node.nodeName == 'TH') {
1470
+ if (!dom.hasClass(node, 'mce-item-selected')) {
1471
+ break;
1472
+ }
1473
+
1474
+ lastNode = node;
1475
+ }
1476
+ } while ((node = walker.next()));
1477
+
1478
+ setPoint(lastNode);
1479
+
1480
+ sel.setRng(rng);
1481
+ }
1482
+
1483
+ editor.nodeChanged();
1484
+ startCell = tableGrid = startTable = null;
1485
+ }
1486
+ });
1487
+
1488
+ editor.on('KeyUp Drop SetContent', function(e) {
1489
+ clear(e.type == 'setcontent');
1490
+ startCell = tableGrid = startTable = null;
1491
+ resizing = false;
1492
+ });
1493
+
1494
+ editor.on('ObjectResizeStart ObjectResized', function(e) {
1495
+ resizing = e.type != 'objectresized';
1496
+ });
1497
+
1498
+ return {
1499
+ clear: clear
1500
+ };
1501
+ };
1502
+ });
1503
+
1504
+ // Included from: js/tinymce/plugins/table/classes/Dialogs.js
1505
+
1506
+ /**
1507
+ * Dialogs.js
1508
+ *
1509
+ * Copyright, Moxiecode Systems AB
1510
+ * Released under LGPL License.
1511
+ *
1512
+ * License: http://www.tinymce.com/license
1513
+ * Contributing: http://www.tinymce.com/contributing
1514
+ */
1515
+
1516
+ /**
1517
+ * ...
1518
+ *
1519
+ * @class tinymce.tableplugin.Dialogs
1520
+ * @private
1521
+ */
1522
+ define("tinymce/tableplugin/Dialogs", [
1523
+ "tinymce/util/Tools",
1524
+ "tinymce/Env"
1525
+ ], function(Tools, Env) {
1526
+ var each = Tools.each;
1527
+
1528
+ return function(editor) {
1529
+ var self = this;
1530
+
1531
+ function createColorPickAction() {
1532
+ var colorPickerCallback = editor.settings.color_picker_callback;
1533
+
1534
+ if (colorPickerCallback) {
1535
+ return function() {
1536
+ var self = this;
1537
+
1538
+ colorPickerCallback.call(
1539
+ editor,
1540
+ function(value) {
1541
+ self.value(value).fire('change');
1542
+ },
1543
+ self.value()
1544
+ );
1545
+ };
1546
+ }
1547
+ }
1548
+
1549
+ function createStyleForm(dom) {
1550
+ return {
1551
+ title: 'Advanced',
1552
+ type: 'form',
1553
+ defaults: {
1554
+ onchange: function() {
1555
+ updateStyle(dom, this.parents().reverse()[0], this.name() == "style");
1556
+ }
1557
+ },
1558
+ items: [
1559
+ {
1560
+ label: 'Style',
1561
+ name: 'style',
1562
+ type: 'textbox'
1563
+ },
1564
+
1565
+ {
1566
+ type: 'form',
1567
+ padding: 0,
1568
+ formItemDefaults: {
1569
+ layout: 'grid',
1570
+ alignH: ['start', 'right']
1571
+ },
1572
+ defaults: {
1573
+ size: 7
1574
+ },
1575
+ items: [
1576
+ {
1577
+ label: 'Border color',
1578
+ type: 'colorbox',
1579
+ name: 'borderColor',
1580
+ onaction: createColorPickAction()
1581
+ },
1582
+
1583
+ {
1584
+ label: 'Background color',
1585
+ type: 'colorbox',
1586
+ name: 'backgroundColor',
1587
+ onaction: createColorPickAction()
1588
+ }
1589
+ ]
1590
+ }
1591
+ ]
1592
+ };
1593
+ }
1594
+
1595
+ function removePxSuffix(size) {
1596
+ return size ? size.replace(/px$/, '') : "";
1597
+ }
1598
+
1599
+ function addSizeSuffix(size) {
1600
+ if (/^[0-9]+$/.test(size)) {
1601
+ size += "px";
1602
+ }
1603
+
1604
+ return size;
1605
+ }
1606
+
1607
+ function unApplyAlign(elm) {
1608
+ each('left center right'.split(' '), function(name) {
1609
+ editor.formatter.remove('align' + name, {}, elm);
1610
+ });
1611
+ }
1612
+
1613
+ function unApplyVAlign(elm) {
1614
+ each('top middle bottom'.split(' '), function(name) {
1615
+ editor.formatter.remove('valign' + name, {}, elm);
1616
+ });
1617
+ }
1618
+
1619
+ function buildListItems(inputList, itemCallback, startItems) {
1620
+ function appendItems(values, output) {
1621
+ output = output || [];
1622
+
1623
+ Tools.each(values, function(item) {
1624
+ var menuItem = {text: item.text || item.title};
1625
+
1626
+ if (item.menu) {
1627
+ menuItem.menu = appendItems(item.menu);
1628
+ } else {
1629
+ menuItem.value = item.value;
1630
+
1631
+ if (itemCallback) {
1632
+ itemCallback(menuItem);
1633
+ }
1634
+ }
1635
+
1636
+ output.push(menuItem);
1637
+ });
1638
+
1639
+ return output;
1640
+ }
1641
+
1642
+ return appendItems(inputList, startItems || []);
1643
+ }
1644
+
1645
+ function updateStyle(dom, win, isStyleCtrl) {
1646
+ var data = win.toJSON();
1647
+ var css = dom.parseStyle(data.style);
1648
+
1649
+ if (isStyleCtrl) {
1650
+ win.find('#borderColor').value(css["border-color"] || '')[0].fire('change');
1651
+ win.find('#backgroundColor').value(css["background-color"] || '')[0].fire('change');
1652
+ } else {
1653
+ css["border-color"] = data.borderColor;
1654
+ css["background-color"] = data.backgroundColor;
1655
+ }
1656
+
1657
+ win.find('#style').value(dom.serializeStyle(dom.parseStyle(dom.serializeStyle(css))));
1658
+ }
1659
+
1660
+ function appendStylesToData(dom, data, elm) {
1661
+ var css = dom.parseStyle(dom.getAttrib(elm, 'style'));
1662
+
1663
+ if (css["border-color"]) {
1664
+ data.borderColor = css["border-color"];
1665
+ }
1666
+
1667
+ if (css["background-color"]) {
1668
+ data.backgroundColor = css["background-color"];
1669
+ }
1670
+
1671
+ data.style = dom.serializeStyle(css);
1672
+ }
1673
+
1674
+ self.tableProps = function() {
1675
+ self.table(true);
1676
+ };
1677
+
1678
+ self.table = function(isProps) {
1679
+ var dom = editor.dom, tableElm, colsCtrl, rowsCtrl, classListCtrl, data = {}, generalTableForm;
1680
+
1681
+ function onSubmitTableForm() {
1682
+ var captionElm;
1683
+
1684
+ updateStyle(dom, this);
1685
+ data = Tools.extend(data, this.toJSON());
1686
+
1687
+ Tools.each('backgroundColor borderColor'.split(' '), function(name) {
1688
+ delete data[name];
1689
+ });
1690
+
1691
+ if (data["class"] === false) {
1692
+ delete data["class"];
1693
+ }
1694
+
1695
+ editor.undoManager.transact(function() {
1696
+ if (!tableElm) {
1697
+ tableElm = editor.plugins.table.insertTable(data.cols || 1, data.rows || 1);
1698
+ }
1699
+
1700
+ editor.dom.setAttribs(tableElm, {
1701
+ cellspacing: data.cellspacing,
1702
+ cellpadding: data.cellpadding,
1703
+ border: data.border,
1704
+ style: data.style,
1705
+ 'class': data['class']
1706
+ });
1707
+
1708
+ if (dom.getAttrib(tableElm, 'width')) {
1709
+ dom.setAttrib(tableElm, 'width', removePxSuffix(data.width));
1710
+ } else {
1711
+ dom.setStyle(tableElm, 'width', addSizeSuffix(data.width));
1712
+ }
1713
+
1714
+ dom.setStyle(tableElm, 'height', addSizeSuffix(data.height));
1715
+
1716
+ // Toggle caption on/off
1717
+ captionElm = dom.select('caption', tableElm)[0];
1718
+
1719
+ if (captionElm && !data.caption) {
1720
+ dom.remove(captionElm);
1721
+ }
1722
+
1723
+ if (!captionElm && data.caption) {
1724
+ captionElm = dom.create('caption');
1725
+ captionElm.innerHTML = !Env.ie ? '<br data-mce-bogus="1"/>' : '\u00a0';
1726
+ tableElm.insertBefore(captionElm, tableElm.firstChild);
1727
+ }
1728
+
1729
+ unApplyAlign(tableElm);
1730
+ if (data.align) {
1731
+ editor.formatter.apply('align' + data.align, {}, tableElm);
1732
+ }
1733
+
1734
+ editor.focus();
1735
+ editor.addVisual();
1736
+ });
1737
+ }
1738
+
1739
+ if (isProps === true) {
1740
+ tableElm = dom.getParent(editor.selection.getStart(), 'table');
1741
+
1742
+ if (tableElm) {
1743
+ data = {
1744
+ width: removePxSuffix(dom.getStyle(tableElm, 'width') || dom.getAttrib(tableElm, 'width')),
1745
+ height: removePxSuffix(dom.getStyle(tableElm, 'height') || dom.getAttrib(tableElm, 'height')),
1746
+ cellspacing: tableElm ? dom.getAttrib(tableElm, 'cellspacing') : '',
1747
+ cellpadding: tableElm ? dom.getAttrib(tableElm, 'cellpadding') : '',
1748
+ border: tableElm ? dom.getAttrib(tableElm, 'border') : '',
1749
+ caption: !!dom.select('caption', tableElm)[0],
1750
+ 'class': dom.getAttrib(tableElm, 'class')
1751
+ };
1752
+
1753
+ each('left center right'.split(' '), function(name) {
1754
+ if (editor.formatter.matchNode(tableElm, 'align' + name)) {
1755
+ data.align = name;
1756
+ }
1757
+ });
1758
+ }
1759
+ } else {
1760
+ colsCtrl = {label: 'Cols', name: 'cols'};
1761
+ rowsCtrl = {label: 'Rows', name: 'rows'};
1762
+ }
1763
+
1764
+ if (editor.settings.table_class_list) {
1765
+ if (data["class"]) {
1766
+ data["class"] = data["class"].replace(/\s*mce\-item\-table\s*/g, '');
1767
+ }
1768
+
1769
+ classListCtrl = {
1770
+ name: 'class',
1771
+ type: 'listbox',
1772
+ label: 'Class',
1773
+ values: buildListItems(
1774
+ editor.settings.table_class_list,
1775
+ function(item) {
1776
+ if (item.value) {
1777
+ item.textStyle = function() {
1778
+ return editor.formatter.getCssText({block: 'table', classes: [item.value]});
1779
+ };
1780
+ }
1781
+ }
1782
+ )
1783
+ };
1784
+ }
1785
+
1786
+ generalTableForm = {
1787
+ type: 'form',
1788
+ layout: 'flex',
1789
+ direction: 'column',
1790
+ labelGapCalc: 'children',
1791
+ padding: 0,
1792
+ items: [
1793
+ {
1794
+ type: 'form',
1795
+ labelGapCalc: false,
1796
+ padding: 0,
1797
+ layout: 'grid',
1798
+ columns: 2,
1799
+ defaults: {
1800
+ type: 'textbox',
1801
+ maxWidth: 50
1802
+ },
1803
+ items: [
1804
+ colsCtrl,
1805
+ rowsCtrl,
1806
+ {label: 'Width', name: 'width'},
1807
+ {label: 'Height', name: 'height'},
1808
+ {label: 'Cell spacing', name: 'cellspacing'},
1809
+ {label: 'Cell padding', name: 'cellpadding'},
1810
+ {label: 'Border', name: 'border'},
1811
+ {label: 'Caption', name: 'caption', type: 'checkbox'}
1812
+ ]
1813
+ },
1814
+
1815
+ {
1816
+ label: 'Alignment',
1817
+ name: 'align',
1818
+ type: 'listbox',
1819
+ text: 'None',
1820
+ values: [
1821
+ {text: 'None', value: ''},
1822
+ {text: 'Left', value: 'left'},
1823
+ {text: 'Center', value: 'center'},
1824
+ {text: 'Right', value: 'right'}
1825
+ ]
1826
+ },
1827
+
1828
+ classListCtrl
1829
+ ]
1830
+ };
1831
+
1832
+ if (editor.settings.table_advtab !== false) {
1833
+ appendStylesToData(dom, data, tableElm);
1834
+
1835
+ editor.windowManager.open({
1836
+ title: "Table properties",
1837
+ data: data,
1838
+ bodyType: 'tabpanel',
1839
+ body: [
1840
+ {
1841
+ title: 'General',
1842
+ type: 'form',
1843
+ items: generalTableForm
1844
+ },
1845
+ createStyleForm(dom)
1846
+ ],
1847
+
1848
+ onsubmit: onSubmitTableForm
1849
+ });
1850
+ } else {
1851
+ editor.windowManager.open({
1852
+ title: "Table properties",
1853
+ data: data,
1854
+ body: generalTableForm,
1855
+ onsubmit: onSubmitTableForm
1856
+ });
1857
+ }
1858
+ };
1859
+
1860
+ self.merge = function(grid, cell) {
1861
+ editor.windowManager.open({
1862
+ title: "Merge cells",
1863
+ body: [
1864
+ {label: 'Cols', name: 'cols', type: 'textbox', value: '1', size: 10},
1865
+ {label: 'Rows', name: 'rows', type: 'textbox', value: '1', size: 10}
1866
+ ],
1867
+ onsubmit: function() {
1868
+ var data = this.toJSON();
1869
+
1870
+ editor.undoManager.transact(function() {
1871
+ grid.merge(cell, data.cols, data.rows);
1872
+ });
1873
+ }
1874
+ });
1875
+ };
1876
+
1877
+ self.cell = function() {
1878
+ var dom = editor.dom, cellElm, data, classListCtrl, cells = [];
1879
+
1880
+ function onSubmitCellForm() {
1881
+ updateStyle(dom, this);
1882
+ data = Tools.extend(data, this.toJSON());
1883
+
1884
+ editor.undoManager.transact(function() {
1885
+ each(cells, function(cellElm) {
1886
+ editor.dom.setAttribs(cellElm, {
1887
+ scope: data.scope,
1888
+ style: data.style,
1889
+ 'class': data['class']
1890
+ });
1891
+
1892
+ editor.dom.setStyles(cellElm, {
1893
+ width: addSizeSuffix(data.width),
1894
+ height: addSizeSuffix(data.height)
1895
+ });
1896
+
1897
+ // Switch cell type
1898
+ if (data.type && cellElm.nodeName.toLowerCase() != data.type) {
1899
+ cellElm = dom.rename(cellElm, data.type);
1900
+ }
1901
+
1902
+ // Apply/remove alignment
1903
+ unApplyAlign(cellElm);
1904
+ if (data.align) {
1905
+ editor.formatter.apply('align' + data.align, {}, cellElm);
1906
+ }
1907
+
1908
+ // Apply/remove vertical alignment
1909
+ unApplyVAlign(cellElm);
1910
+ if (data.valign) {
1911
+ editor.formatter.apply('valign' + data.valign, {}, cellElm);
1912
+ }
1913
+ });
1914
+
1915
+ editor.focus();
1916
+ });
1917
+ }
1918
+
1919
+ // Get selected cells or the current cell
1920
+ cells = editor.dom.select('td.mce-item-selected,th.mce-item-selected');
1921
+ cellElm = editor.dom.getParent(editor.selection.getStart(), 'td,th');
1922
+ if (!cells.length && cellElm) {
1923
+ cells.push(cellElm);
1924
+ }
1925
+
1926
+ cellElm = cellElm || cells[0];
1927
+
1928
+ if (!cellElm) {
1929
+ // If this element is null, return now to avoid crashing.
1930
+ return;
1931
+ }
1932
+
1933
+ data = {
1934
+ width: removePxSuffix(dom.getStyle(cellElm, 'width') || dom.getAttrib(cellElm, 'width')),
1935
+ height: removePxSuffix(dom.getStyle(cellElm, 'height') || dom.getAttrib(cellElm, 'height')),
1936
+ scope: dom.getAttrib(cellElm, 'scope'),
1937
+ 'class': dom.getAttrib(cellElm, 'class')
1938
+ };
1939
+
1940
+ data.type = cellElm.nodeName.toLowerCase();
1941
+
1942
+ each('left center right'.split(' '), function(name) {
1943
+ if (editor.formatter.matchNode(cellElm, 'align' + name)) {
1944
+ data.align = name;
1945
+ }
1946
+ });
1947
+
1948
+ each('top middle bottom'.split(' '), function(name) {
1949
+ if (editor.formatter.matchNode(cellElm, 'valign' + name)) {
1950
+ data.valign = name;
1951
+ }
1952
+ });
1953
+
1954
+ if (editor.settings.table_cell_class_list) {
1955
+ classListCtrl = {
1956
+ name: 'class',
1957
+ type: 'listbox',
1958
+ label: 'Class',
1959
+ values: buildListItems(
1960
+ editor.settings.table_cell_class_list,
1961
+ function(item) {
1962
+ if (item.value) {
1963
+ item.textStyle = function() {
1964
+ return editor.formatter.getCssText({block: 'td', classes: [item.value]});
1965
+ };
1966
+ }
1967
+ }
1968
+ )
1969
+ };
1970
+ }
1971
+
1972
+ var generalCellForm = {
1973
+ type: 'form',
1974
+ layout: 'flex',
1975
+ direction: 'column',
1976
+ labelGapCalc: 'children',
1977
+ padding: 0,
1978
+ items: [
1979
+ {
1980
+ type: 'form',
1981
+ layout: 'grid',
1982
+ columns: 2,
1983
+ labelGapCalc: false,
1984
+ padding: 0,
1985
+ defaults: {
1986
+ type: 'textbox',
1987
+ maxWidth: 50
1988
+ },
1989
+ items: [
1990
+ {label: 'Width', name: 'width'},
1991
+ {label: 'Height', name: 'height'},
1992
+ {
1993
+ label: 'Cell type',
1994
+ name: 'type',
1995
+ type: 'listbox',
1996
+ text: 'None',
1997
+ minWidth: 90,
1998
+ maxWidth: null,
1999
+ values: [
2000
+ {text: 'Cell', value: 'td'},
2001
+ {text: 'Header cell', value: 'th'}
2002
+ ]
2003
+ },
2004
+ {
2005
+ label: 'Scope',
2006
+ name: 'scope',
2007
+ type: 'listbox',
2008
+ text: 'None',
2009
+ minWidth: 90,
2010
+ maxWidth: null,
2011
+ values: [
2012
+ {text: 'None', value: ''},
2013
+ {text: 'Row', value: 'row'},
2014
+ {text: 'Column', value: 'col'},
2015
+ {text: 'Row group', value: 'rowgroup'},
2016
+ {text: 'Column group', value: 'colgroup'}
2017
+ ]
2018
+ },
2019
+ {
2020
+ label: 'H Align',
2021
+ name: 'align',
2022
+ type: 'listbox',
2023
+ text: 'None',
2024
+ minWidth: 90,
2025
+ maxWidth: null,
2026
+ values: [
2027
+ {text: 'None', value: ''},
2028
+ {text: 'Left', value: 'left'},
2029
+ {text: 'Center', value: 'center'},
2030
+ {text: 'Right', value: 'right'}
2031
+ ]
2032
+ },
2033
+ {
2034
+ label: 'V Align',
2035
+ name: 'valign',
2036
+ type: 'listbox',
2037
+ text: 'None',
2038
+ minWidth: 90,
2039
+ maxWidth: null,
2040
+ values: [
2041
+ {text: 'None', value: ''},
2042
+ {text: 'Top', value: 'top'},
2043
+ {text: 'Middle', value: 'middle'},
2044
+ {text: 'Bottom', value: 'bottom'}
2045
+ ]
2046
+ }
2047
+ ]
2048
+ },
2049
+
2050
+ classListCtrl
2051
+ ]
2052
+ };
2053
+
2054
+ if (editor.settings.table_cell_advtab !== false) {
2055
+ appendStylesToData(dom, data, cellElm);
2056
+
2057
+ editor.windowManager.open({
2058
+ title: "Cell properties",
2059
+ bodyType: 'tabpanel',
2060
+ data: data,
2061
+ body: [
2062
+ {
2063
+ title: 'General',
2064
+ type: 'form',
2065
+ items: generalCellForm
2066
+ },
2067
+
2068
+ createStyleForm(dom)
2069
+ ],
2070
+
2071
+ onsubmit: onSubmitCellForm
2072
+ });
2073
+ } else {
2074
+ editor.windowManager.open({
2075
+ title: "Cell properties",
2076
+ data: data,
2077
+ body: generalCellForm,
2078
+ onsubmit: onSubmitCellForm
2079
+ });
2080
+ }
2081
+ };
2082
+
2083
+ self.row = function() {
2084
+ var dom = editor.dom, tableElm, cellElm, rowElm, classListCtrl, data, rows = [], generalRowForm;
2085
+
2086
+ function onSubmitRowForm() {
2087
+ var tableElm, oldParentElm, parentElm;
2088
+
2089
+ updateStyle(dom, this);
2090
+ data = Tools.extend(data, this.toJSON());
2091
+
2092
+ editor.undoManager.transact(function() {
2093
+ var toType = data.type;
2094
+
2095
+ each(rows, function(rowElm) {
2096
+ editor.dom.setAttribs(rowElm, {
2097
+ scope: data.scope,
2098
+ style: data.style,
2099
+ 'class': data['class']
2100
+ });
2101
+
2102
+ editor.dom.setStyles(rowElm, {
2103
+ height: addSizeSuffix(data.height)
2104
+ });
2105
+
2106
+ if (toType != rowElm.parentNode.nodeName.toLowerCase()) {
2107
+ tableElm = dom.getParent(rowElm, 'table');
2108
+
2109
+ oldParentElm = rowElm.parentNode;
2110
+ parentElm = dom.select(toType, tableElm)[0];
2111
+ if (!parentElm) {
2112
+ parentElm = dom.create(toType);
2113
+ if (tableElm.firstChild) {
2114
+ tableElm.insertBefore(parentElm, tableElm.firstChild);
2115
+ } else {
2116
+ tableElm.appendChild(parentElm);
2117
+ }
2118
+ }
2119
+
2120
+ parentElm.appendChild(rowElm);
2121
+
2122
+ if (!oldParentElm.hasChildNodes()) {
2123
+ dom.remove(oldParentElm);
2124
+ }
2125
+ }
2126
+
2127
+ // Apply/remove alignment
2128
+ unApplyAlign(rowElm);
2129
+ if (data.align) {
2130
+ editor.formatter.apply('align' + data.align, {}, rowElm);
2131
+ }
2132
+ });
2133
+
2134
+ editor.focus();
2135
+ });
2136
+ }
2137
+
2138
+ tableElm = editor.dom.getParent(editor.selection.getStart(), 'table');
2139
+ cellElm = editor.dom.getParent(editor.selection.getStart(), 'td,th');
2140
+
2141
+ each(tableElm.rows, function(row) {
2142
+ each(row.cells, function(cell) {
2143
+ if (dom.hasClass(cell, 'mce-item-selected') || cell == cellElm) {
2144
+ rows.push(row);
2145
+ return false;
2146
+ }
2147
+ });
2148
+ });
2149
+
2150
+ rowElm = rows[0];
2151
+ if (!rowElm) {
2152
+ // If this element is null, return now to avoid crashing.
2153
+ return;
2154
+ }
2155
+
2156
+ data = {
2157
+ height: removePxSuffix(dom.getStyle(rowElm, 'height') || dom.getAttrib(rowElm, 'height')),
2158
+ scope: dom.getAttrib(rowElm, 'scope'),
2159
+ 'class': dom.getAttrib(rowElm, 'class')
2160
+ };
2161
+
2162
+ data.type = rowElm.parentNode.nodeName.toLowerCase();
2163
+
2164
+ each('left center right'.split(' '), function(name) {
2165
+ if (editor.formatter.matchNode(rowElm, 'align' + name)) {
2166
+ data.align = name;
2167
+ }
2168
+ });
2169
+
2170
+ if (editor.settings.table_row_class_list) {
2171
+ classListCtrl = {
2172
+ name: 'class',
2173
+ type: 'listbox',
2174
+ label: 'Class',
2175
+ values: buildListItems(
2176
+ editor.settings.table_row_class_list,
2177
+ function(item) {
2178
+ if (item.value) {
2179
+ item.textStyle = function() {
2180
+ return editor.formatter.getCssText({block: 'tr', classes: [item.value]});
2181
+ };
2182
+ }
2183
+ }
2184
+ )
2185
+ };
2186
+ }
2187
+
2188
+ generalRowForm = {
2189
+ type: 'form',
2190
+ columns: 2,
2191
+ padding: 0,
2192
+ defaults: {
2193
+ type: 'textbox'
2194
+ },
2195
+ items: [
2196
+ {
2197
+ type: 'listbox',
2198
+ name: 'type',
2199
+ label: 'Row type',
2200
+ text: 'None',
2201
+ maxWidth: null,
2202
+ values: [
2203
+ {text: 'Header', value: 'thead'},
2204
+ {text: 'Body', value: 'tbody'},
2205
+ {text: 'Footer', value: 'tfoot'}
2206
+ ]
2207
+ },
2208
+ {
2209
+ type: 'listbox',
2210
+ name: 'align',
2211
+ label: 'Alignment',
2212
+ text: 'None',
2213
+ maxWidth: null,
2214
+ values: [
2215
+ {text: 'None', value: ''},
2216
+ {text: 'Left', value: 'left'},
2217
+ {text: 'Center', value: 'center'},
2218
+ {text: 'Right', value: 'right'}
2219
+ ]
2220
+ },
2221
+ {label: 'Height', name: 'height'},
2222
+ classListCtrl
2223
+ ]
2224
+ };
2225
+
2226
+ if (editor.settings.table_row_advtab !== false) {
2227
+ appendStylesToData(dom, data, rowElm);
2228
+
2229
+ editor.windowManager.open({
2230
+ title: "Row properties",
2231
+ data: data,
2232
+ bodyType: 'tabpanel',
2233
+ body: [
2234
+ {
2235
+ title: 'General',
2236
+ type: 'form',
2237
+ items: generalRowForm
2238
+ },
2239
+ createStyleForm(dom)
2240
+ ],
2241
+
2242
+ onsubmit: onSubmitRowForm
2243
+ });
2244
+ } else {
2245
+ editor.windowManager.open({
2246
+ title: "Row properties",
2247
+ data: data,
2248
+ body: generalRowForm,
2249
+ onsubmit: onSubmitRowForm
2250
+ });
2251
+ }
2252
+ };
2253
+ };
2254
+ });
2255
+
2256
+ // Included from: js/tinymce/plugins/table/classes/Plugin.js
2257
+
2258
+ /**
2259
+ * Plugin.js
2260
+ *
2261
+ * Copyright, Moxiecode Systems AB
2262
+ * Released under LGPL License.
2263
+ *
2264
+ * License: http://www.tinymce.com/license
2265
+ * Contributing: http://www.tinymce.com/contributing
2266
+ */
2267
+
2268
+ /**
2269
+ * This class contains all core logic for the table plugin.
2270
+ *
2271
+ * @class tinymce.tableplugin.Plugin
2272
+ * @private
2273
+ */
2274
+ define("tinymce/tableplugin/Plugin", [
2275
+ "tinymce/tableplugin/TableGrid",
2276
+ "tinymce/tableplugin/Quirks",
2277
+ "tinymce/tableplugin/CellSelection",
2278
+ "tinymce/tableplugin/Dialogs",
2279
+ "tinymce/util/Tools",
2280
+ "tinymce/dom/TreeWalker",
2281
+ "tinymce/Env",
2282
+ "tinymce/PluginManager"
2283
+ ], function(TableGrid, Quirks, CellSelection, Dialogs, Tools, TreeWalker, Env, PluginManager) {
2284
+ var each = Tools.each;
2285
+
2286
+ function Plugin(editor) {
2287
+ var clipboardRows, self = this, dialogs = new Dialogs(editor);
2288
+
2289
+ function cmd(command) {
2290
+ return function() {
2291
+ editor.execCommand(command);
2292
+ };
2293
+ }
2294
+
2295
+ function insertTable(cols, rows) {
2296
+ var y, x, html, tableElm;
2297
+
2298
+ html = '<table id="__mce"><tbody>';
2299
+
2300
+ for (y = 0; y < rows; y++) {
2301
+ html += '<tr>';
2302
+
2303
+ for (x = 0; x < cols; x++) {
2304
+ html += '<td>' + (Env.ie ? " " : '<br>') + '</td>';
2305
+ }
2306
+
2307
+ html += '</tr>';
2308
+ }
2309
+
2310
+ html += '</tbody></table>';
2311
+
2312
+ editor.undoManager.transact(function() {
2313
+ editor.insertContent(html);
2314
+
2315
+ tableElm = editor.dom.get('__mce');
2316
+ editor.dom.setAttrib(tableElm, 'id', null);
2317
+
2318
+ editor.dom.setAttribs(tableElm, editor.settings.table_default_attributes || {});
2319
+ editor.dom.setStyles(tableElm, editor.settings.table_default_styles || {});
2320
+ });
2321
+
2322
+ return tableElm;
2323
+ }
2324
+
2325
+ function handleDisabledState(ctrl, selector) {
2326
+ function bindStateListener() {
2327
+ ctrl.disabled(!editor.dom.getParent(editor.selection.getStart(), selector));
2328
+
2329
+ editor.selection.selectorChanged(selector, function(state) {
2330
+ ctrl.disabled(!state);
2331
+ });
2332
+ }
2333
+
2334
+ if (editor.initialized) {
2335
+ bindStateListener();
2336
+ } else {
2337
+ editor.on('init', bindStateListener);
2338
+ }
2339
+ }
2340
+
2341
+ function postRender() {
2342
+ /*jshint validthis:true*/
2343
+ handleDisabledState(this, 'table');
2344
+ }
2345
+
2346
+ function postRenderCell() {
2347
+ /*jshint validthis:true*/
2348
+ handleDisabledState(this, 'td,th');
2349
+ }
2350
+
2351
+ function generateTableGrid() {
2352
+ var html = '';
2353
+
2354
+ html = '<table role="grid" class="mce-grid mce-grid-border" aria-readonly="true">';
2355
+
2356
+ for (var y = 0; y < 10; y++) {
2357
+ html += '<tr>';
2358
+
2359
+ for (var x = 0; x < 10; x++) {
2360
+ html += '<td role="gridcell" tabindex="-1"><a id="mcegrid' + (y * 10 + x) + '" href="#" ' +
2361
+ 'data-mce-x="' + x + '" data-mce-y="' + y + '"></a></td>';
2362
+ }
2363
+
2364
+ html += '</tr>';
2365
+ }
2366
+
2367
+ html += '</table>';
2368
+
2369
+ html += '<div class="mce-text-center" role="presentation">1 x 1</div>';
2370
+
2371
+ return html;
2372
+ }
2373
+
2374
+ function selectGrid(tx, ty, control) {
2375
+ var table = control.getEl().getElementsByTagName('table')[0];
2376
+ var x, y, focusCell, cell, active;
2377
+ var rtl = control.isRtl() || control.parent().rel == 'tl-tr';
2378
+
2379
+ table.nextSibling.innerHTML = (tx + 1) + ' x ' + (ty + 1);
2380
+
2381
+ if (rtl) {
2382
+ tx = 9 - tx;
2383
+ }
2384
+
2385
+ for (y = 0; y < 10; y++) {
2386
+ for (x = 0; x < 10; x++) {
2387
+ cell = table.rows[y].childNodes[x].firstChild;
2388
+ active = (rtl ? x >= tx : x <= tx) && y <= ty;
2389
+
2390
+ editor.dom.toggleClass(cell, 'mce-active', active);
2391
+
2392
+ if (active) {
2393
+ focusCell = cell;
2394
+ }
2395
+ }
2396
+ }
2397
+
2398
+ return focusCell.parentNode;
2399
+ }
2400
+
2401
+ if (editor.settings.table_grid === false) {
2402
+ editor.addMenuItem('inserttable', {
2403
+ text: 'Insert table',
2404
+ icon: 'table',
2405
+ context: 'table',
2406
+ onclick: dialogs.table
2407
+ });
2408
+ } else {
2409
+ editor.addMenuItem('inserttable', {
2410
+ text: 'Insert table',
2411
+ icon: 'table',
2412
+ context: 'table',
2413
+ ariaHideMenu: true,
2414
+ onclick: function(e) {
2415
+ if (e.aria) {
2416
+ this.parent().hideAll();
2417
+ e.stopImmediatePropagation();
2418
+ dialogs.table();
2419
+ }
2420
+ },
2421
+ onshow: function() {
2422
+ selectGrid(0, 0, this.menu.items()[0]);
2423
+ },
2424
+ onhide: function() {
2425
+ var elements = this.menu.items()[0].getEl().getElementsByTagName('a');
2426
+ editor.dom.removeClass(elements, 'mce-active');
2427
+ editor.dom.addClass(elements[0], 'mce-active');
2428
+ },
2429
+ menu: [
2430
+ {
2431
+ type: 'container',
2432
+ html: generateTableGrid(),
2433
+
2434
+ onPostRender: function() {
2435
+ this.lastX = this.lastY = 0;
2436
+ },
2437
+
2438
+ onmousemove: function(e) {
2439
+ var target = e.target, x, y;
2440
+
2441
+ if (target.tagName.toUpperCase() == 'A') {
2442
+ x = parseInt(target.getAttribute('data-mce-x'), 10);
2443
+ y = parseInt(target.getAttribute('data-mce-y'), 10);
2444
+
2445
+ if (this.isRtl() || this.parent().rel == 'tl-tr') {
2446
+ x = 9 - x;
2447
+ }
2448
+
2449
+ if (x !== this.lastX || y !== this.lastY) {
2450
+ selectGrid(x, y, e.control);
2451
+
2452
+ this.lastX = x;
2453
+ this.lastY = y;
2454
+ }
2455
+ }
2456
+ },
2457
+
2458
+ onclick: function(e) {
2459
+ var self = this;
2460
+
2461
+ if (e.target.tagName.toUpperCase() == 'A') {
2462
+ e.preventDefault();
2463
+ e.stopPropagation();
2464
+ self.parent().cancel();
2465
+
2466
+ editor.undoManager.transact(function() {
2467
+ insertTable(self.lastX + 1, self.lastY + 1);
2468
+ });
2469
+
2470
+ editor.addVisual();
2471
+ }
2472
+ }
2473
+ }
2474
+ ]
2475
+ });
2476
+ }
2477
+
2478
+ editor.addMenuItem('tableprops', {
2479
+ text: 'Table properties',
2480
+ context: 'table',
2481
+ onPostRender: postRender,
2482
+ onclick: dialogs.tableProps
2483
+ });
2484
+
2485
+ editor.addMenuItem('deletetable', {
2486
+ text: 'Delete table',
2487
+ context: 'table',
2488
+ onPostRender: postRender,
2489
+ cmd: 'mceTableDelete'
2490
+ });
2491
+
2492
+ editor.addMenuItem('cell', {
2493
+ separator: 'before',
2494
+ text: 'Cell',
2495
+ context: 'table',
2496
+ menu: [
2497
+ {text: 'Cell properties', onclick: cmd('mceTableCellProps'), onPostRender: postRenderCell},
2498
+ {text: 'Merge cells', onclick: cmd('mceTableMergeCells'), onPostRender: postRenderCell},
2499
+ {text: 'Split cell', onclick: cmd('mceTableSplitCells'), onPostRender: postRenderCell}
2500
+ ]
2501
+ });
2502
+
2503
+ editor.addMenuItem('row', {
2504
+ text: 'Row',
2505
+ context: 'table',
2506
+ menu: [
2507
+ {text: 'Insert row before', onclick: cmd('mceTableInsertRowBefore'), onPostRender: postRenderCell},
2508
+ {text: 'Insert row after', onclick: cmd('mceTableInsertRowAfter'), onPostRender: postRenderCell},
2509
+ {text: 'Delete row', onclick: cmd('mceTableDeleteRow'), onPostRender: postRenderCell},
2510
+ {text: 'Row properties', onclick: cmd('mceTableRowProps'), onPostRender: postRenderCell},
2511
+ {text: '-'},
2512
+ {text: 'Cut row', onclick: cmd('mceTableCutRow'), onPostRender: postRenderCell},
2513
+ {text: 'Copy row', onclick: cmd('mceTableCopyRow'), onPostRender: postRenderCell},
2514
+ {text: 'Paste row before', onclick: cmd('mceTablePasteRowBefore'), onPostRender: postRenderCell},
2515
+ {text: 'Paste row after', onclick: cmd('mceTablePasteRowAfter'), onPostRender: postRenderCell}
2516
+ ]
2517
+ });
2518
+
2519
+ editor.addMenuItem('column', {
2520
+ text: 'Column',
2521
+ context: 'table',
2522
+ menu: [
2523
+ {text: 'Insert column before', onclick: cmd('mceTableInsertColBefore'), onPostRender: postRenderCell},
2524
+ {text: 'Insert column after', onclick: cmd('mceTableInsertColAfter'), onPostRender: postRenderCell},
2525
+ {text: 'Delete column', onclick: cmd('mceTableDeleteCol'), onPostRender: postRenderCell}
2526
+ ]
2527
+ });
2528
+
2529
+ var menuItems = [];
2530
+ each("inserttable tableprops deletetable | cell row column".split(' '), function(name) {
2531
+ if (name == '|') {
2532
+ menuItems.push({text: '-'});
2533
+ } else {
2534
+ menuItems.push(editor.menuItems[name]);
2535
+ }
2536
+ });
2537
+
2538
+ editor.addButton("table", {
2539
+ type: "menubutton",
2540
+ title: "Table",
2541
+ menu: menuItems
2542
+ });
2543
+
2544
+ // Select whole table is a table border is clicked
2545
+ if (!Env.isIE) {
2546
+ editor.on('click', function(e) {
2547
+ e = e.target;
2548
+
2549
+ if (e.nodeName === 'TABLE') {
2550
+ editor.selection.select(e);
2551
+ editor.nodeChanged();
2552
+ }
2553
+ });
2554
+ }
2555
+
2556
+ self.quirks = new Quirks(editor);
2557
+
2558
+ editor.on('Init', function() {
2559
+ self.cellSelection = new CellSelection(editor);
2560
+ });
2561
+
2562
+ // Register action commands
2563
+ each({
2564
+ mceTableSplitCells: function(grid) {
2565
+ grid.split();
2566
+ },
2567
+
2568
+ mceTableMergeCells: function(grid) {
2569
+ var cell;
2570
+
2571
+ cell = editor.dom.getParent(editor.selection.getStart(), 'th,td');
2572
+
2573
+ if (!editor.dom.select('td.mce-item-selected,th.mce-item-selected').length) {
2574
+ dialogs.merge(grid, cell);
2575
+ } else {
2576
+ grid.merge();
2577
+ }
2578
+ },
2579
+
2580
+ mceTableInsertRowBefore: function(grid) {
2581
+ grid.insertRow(true);
2582
+ },
2583
+
2584
+ mceTableInsertRowAfter: function(grid) {
2585
+ grid.insertRow();
2586
+ },
2587
+
2588
+ mceTableInsertColBefore: function(grid) {
2589
+ grid.insertCol(true);
2590
+ },
2591
+
2592
+ mceTableInsertColAfter: function(grid) {
2593
+ grid.insertCol();
2594
+ },
2595
+
2596
+ mceTableDeleteCol: function(grid) {
2597
+ grid.deleteCols();
2598
+ },
2599
+
2600
+ mceTableDeleteRow: function(grid) {
2601
+ grid.deleteRows();
2602
+ },
2603
+
2604
+ mceTableCutRow: function(grid) {
2605
+ clipboardRows = grid.cutRows();
2606
+ },
2607
+
2608
+ mceTableCopyRow: function(grid) {
2609
+ clipboardRows = grid.copyRows();
2610
+ },
2611
+
2612
+ mceTablePasteRowBefore: function(grid) {
2613
+ grid.pasteRows(clipboardRows, true);
2614
+ },
2615
+
2616
+ mceTablePasteRowAfter: function(grid) {
2617
+ grid.pasteRows(clipboardRows);
2618
+ },
2619
+
2620
+ mceTableDelete: function(grid) {
2621
+ grid.deleteTable();
2622
+ }
2623
+ }, function(func, name) {
2624
+ editor.addCommand(name, function() {
2625
+ var grid = new TableGrid(editor);
2626
+
2627
+ if (grid) {
2628
+ func(grid);
2629
+ editor.execCommand('mceRepaint');
2630
+ self.cellSelection.clear();
2631
+ }
2632
+ });
2633
+ });
2634
+
2635
+ // Register dialog commands
2636
+ each({
2637
+ mceInsertTable: dialogs.table,
2638
+ mceTableProps: function() {
2639
+ dialogs.table(true);
2640
+ },
2641
+ mceTableRowProps: dialogs.row,
2642
+ mceTableCellProps: dialogs.cell
2643
+ }, function(func, name) {
2644
+ editor.addCommand(name, function(ui, val) {
2645
+ func(val);
2646
+ });
2647
+ });
2648
+
2649
+ // Enable tab key cell navigation
2650
+ if (editor.settings.table_tab_navigation !== false) {
2651
+ editor.on('keydown', function(e) {
2652
+ var cellElm, grid, delta;
2653
+
2654
+ if (e.keyCode == 9) {
2655
+ cellElm = editor.dom.getParent(editor.selection.getStart(), 'th,td');
2656
+
2657
+ if (cellElm) {
2658
+ e.preventDefault();
2659
+
2660
+ grid = new TableGrid(editor);
2661
+ delta = e.shiftKey ? -1 : 1;
2662
+
2663
+ editor.undoManager.transact(function() {
2664
+ if (!grid.moveRelIdx(cellElm, delta) && delta > 0) {
2665
+ grid.insertRow();
2666
+ grid.refresh();
2667
+ grid.moveRelIdx(cellElm, delta);
2668
+ }
2669
+ });
2670
+ }
2671
+ }
2672
+ });
2673
+ }
2674
+
2675
+ self.insertTable = insertTable;
2676
+ }
2677
+
2678
+ PluginManager.add('table', Plugin);
2679
+ });
2680
+ })(this);
tinymce41-table/plugin.min.js ADDED
@@ -0,0 +1 @@
 
1
+ !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){for(var r=0;r<n.length;r++){for(var i=e,o=n[r],a=o.split(/[.\/]/),l=0;l<a.length-1;++l)i[a[l]]===t&&(i[a[l]]={}),i=i[a[l]];i[a[a.length-1]]=s[o]}}var s={},l="tinymce/tableplugin/TableGrid",c="tinymce/util/Tools",u="tinymce/Env",d="tinymce/tableplugin/Quirks",f="tinymce/util/VK",p="tinymce/tableplugin/CellSelection",m="tinymce/dom/TreeWalker",h="tinymce/tableplugin/Dialogs",g="tinymce/tableplugin/Plugin",v="tinymce/PluginManager";r(l,[c,u],function(e,n){function r(e,t){return parseInt(e.getAttribute(t)||1,10)}var i=e.each;return function(o,a){function s(){var e=0;B=[],D=0,i(["thead","tbody","tfoot"],function(t){var n=O.select("> "+t+" tr",a);i(n,function(n,o){o+=e,i(O.select("> td, > th",n),function(e,n){var i,a,s,l;if(B[o])for(;B[o][n];)n++;for(s=r(e,"rowspan"),l=r(e,"colspan"),a=o;o+s>a;a++)for(B[a]||(B[a]=[]),i=n;n+l>i;i++)B[a][i]={part:t,real:a==o&&i==n,elm:e,rowspan:s,colspan:l};D=Math.max(D,n+1)})}),e+=n.length})}function l(e,t){return e=e.cloneNode(t),e.removeAttribute("id"),e}function c(e,t){var n;return n=B[t],n?n[e]:void 0}function u(e,t,n){e&&(n=parseInt(n,10),1===n?e.removeAttribute(t,1):e.setAttribute(t,n,1))}function d(e){return e&&(O.hasClass(e.elm,"mce-item-selected")||e==H)}function f(){var e=[];return i(a.rows,function(t){i(t.cells,function(n){return O.hasClass(n,"mce-item-selected")||H&&n==H.elm?(e.push(t),!1):void 0})}),e}function p(){var e=O.createRng();e.setStartAfter(a),e.setEndAfter(a),L.setRng(e),O.remove(a)}function m(t){var r,a={};return o.settings.table_clone_elements!==!1&&(a=e.makeMap((o.settings.table_clone_elements||"strong em b i span font h1 h2 h3 h4 h5 h6 p div").toUpperCase(),/[ ,]/)),e.walk(t,function(e){var o;return 3==e.nodeType?(i(O.getParents(e.parentNode,null,t).reverse(),function(e){a[e.nodeName]&&(e=l(e,!1),r?o&&o.appendChild(e):r=o=e,o=e)}),o&&(o.innerHTML=n.ie?"&nbsp;":'<br data-mce-bogus="1" />'),!1):void 0},"childNodes"),t=l(t,!1),u(t,"rowSpan",1),u(t,"colSpan",1),r?t.appendChild(r):(!n.ie||n.ie>10)&&(t.innerHTML='<br data-mce-bogus="1" />'),t}function h(){var e=O.createRng(),t;return i(O.select("tr",a),function(e){0===e.cells.length&&O.remove(e)}),0===O.select("tr",a).length?(e.setStartBefore(a),e.setEndBefore(a),L.setRng(e),void O.remove(a)):(i(O.select("thead,tbody,tfoot",a),function(e){0===e.rows.length&&O.remove(e)}),s(),void(P&&(t=B[Math.min(B.length-1,P.y)],t&&(L.select(t[Math.min(t.length-1,P.x)].elm,!0),L.collapse(!0)))))}function g(e,t,n,r){var i,o,a,s,l;for(i=B[t][e].elm.parentNode,a=1;n>=a;a++)if(i=O.getNext(i,"tr")){for(o=e;o>=0;o--)if(l=B[t+a][o].elm,l.parentNode==i){for(s=1;r>=s;s++)O.insertAfter(m(l),l);break}if(-1==o)for(s=1;r>=s;s++)i.insertBefore(m(i.cells[0]),i.cells[0])}}function v(){i(B,function(e,t){i(e,function(e,n){var i,o,a;if(d(e)&&(e=e.elm,i=r(e,"colspan"),o=r(e,"rowspan"),i>1||o>1)){for(u(e,"rowSpan",1),u(e,"colSpan",1),a=0;i-1>a;a++)O.insertAfter(m(e),e);g(n,t,o-1,i)}})})}function y(t,n,r){var o,a,l,f,p,m,g,y,b,C,x;if(t?(o=k(t),a=o.x,l=o.y,f=a+(n-1),p=l+(r-1)):(P=M=null,i(B,function(e,t){i(e,function(e,n){d(e)&&(P||(P={x:n,y:t}),M={x:n,y:t})})}),P&&(a=P.x,l=P.y,f=M.x,p=M.y)),y=c(a,l),b=c(f,p),y&&b&&y.part==b.part){for(v(),s(),y=c(a,l).elm,u(y,"colSpan",f-a+1),u(y,"rowSpan",p-l+1),g=l;p>=g;g++)for(m=a;f>=m;m++)B[g]&&B[g][m]&&(t=B[g][m].elm,t!=y&&(C=e.grep(t.childNodes),i(C,function(e){y.appendChild(e)}),C.length&&(C=e.grep(y.childNodes),x=0,i(C,function(e){"BR"==e.nodeName&&O.getAttrib(e,"data-mce-bogus")&&x++<C.length-1&&y.removeChild(e)})),O.remove(t)));h()}}function b(e){var n,o,a,s,c,f,p,h,g;if(i(B,function(t,r){return i(t,function(t){return d(t)&&(t=t.elm,c=t.parentNode,f=l(c,!1),n=r,e)?!1:void 0}),e?!n:void 0}),n!==t){for(s=0;s<B[0].length;s++)if(B[n][s]&&(o=B[n][s].elm,o!=a)){if(e){if(n>0&&B[n-1][s]&&(h=B[n-1][s].elm,g=r(h,"rowSpan"),g>1)){u(h,"rowSpan",g+1);continue}}else if(g=r(o,"rowspan"),g>1){u(o,"rowSpan",g+1);continue}p=m(o),u(p,"colSpan",o.colSpan),f.appendChild(p),a=o}f.hasChildNodes()&&(e?c.parentNode.insertBefore(f,c):O.insertAfter(f,c))}}function C(e){var t,n;i(B,function(n){return i(n,function(n,r){return d(n)&&(t=r,e)?!1:void 0}),e?!t:void 0}),i(B,function(i,o){var a,s,l;i[t]&&(a=i[t].elm,a!=n&&(l=r(a,"colspan"),s=r(a,"rowspan"),1==l?e?(a.parentNode.insertBefore(m(a),a),g(t,o,s-1,l)):(O.insertAfter(m(a),a),g(t,o,s-1,l)):u(a,"colSpan",a.colSpan+1),n=a))})}function x(){var t=[];i(B,function(n){i(n,function(n,o){d(n)&&-1===e.inArray(t,o)&&(i(B,function(e){var t=e[o].elm,n;n=r(t,"colSpan"),n>1?u(t,"colSpan",n-1):O.remove(t)}),t.push(o))})}),h()}function w(){function e(e){var t,n;i(e.cells,function(e){var n=r(e,"rowSpan");n>1&&(u(e,"rowSpan",n-1),t=k(e),g(t.x,t.y,1,1))}),t=k(e.cells[0]),i(B[t.y],function(e){var t;e=e.elm,e!=n&&(t=r(e,"rowSpan"),1>=t?O.remove(e):u(e,"rowSpan",t-1),n=e)})}var t;t=f(),i(t.reverse(),function(t){e(t)}),h()}function _(){var e=f();return O.remove(e),h(),e}function E(){var e=f();return i(e,function(t,n){e[n]=l(t,!0)}),e}function N(e,t){var n=f(),r=n[t?0:n.length-1],o=r.cells.length;e&&(i(B,function(e){var t;return o=0,i(e,function(e){e.real&&(o+=e.colspan),e.elm.parentNode==r&&(t=1)}),t?!1:void 0}),t||e.reverse(),i(e,function(e){var n,i=e.cells.length,a;for(n=0;i>n;n++)a=e.cells[n],u(a,"colSpan",1),u(a,"rowSpan",1);for(n=i;o>n;n++)e.appendChild(m(e.cells[i-1]));for(n=o;i>n;n++)O.remove(e.cells[n]);t?r.parentNode.insertBefore(e,r):O.insertAfter(e,r)}),O.removeClass(O.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"))}function k(e){var t;return i(B,function(n,r){return i(n,function(n,i){return n.elm==e?(t={x:i,y:r},!1):void 0}),!t}),t}function S(e){P=k(e)}function T(){var e,t;return e=t=0,i(B,function(n,r){i(n,function(n,i){var o,a;d(n)&&(n=B[r][i],i>e&&(e=i),r>t&&(t=r),n.real&&(o=n.colspan-1,a=n.rowspan-1,o&&i+o>e&&(e=i+o),a&&r+a>t&&(t=r+a)))})}),{x:e,y:t}}function R(e){var t,n,r,i,o,a,s,l,c,u;if(M=k(e),P&&M){for(t=Math.min(P.x,M.x),n=Math.min(P.y,M.y),r=Math.max(P.x,M.x),i=Math.max(P.y,M.y),o=r,a=i,u=n;a>=u;u++)e=B[u][t],e.real||t-(e.colspan-1)<t&&(t-=e.colspan-1);for(c=t;o>=c;c++)e=B[n][c],e.real||n-(e.rowspan-1)<n&&(n-=e.rowspan-1);for(u=n;i>=u;u++)for(c=t;r>=c;c++)e=B[u][c],e.real&&(s=e.colspan-1,l=e.rowspan-1,s&&c+s>o&&(o=c+s),l&&u+l>a&&(a=u+l));for(O.removeClass(O.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),u=n;a>=u;u++)for(c=t;o>=c;c++)B[u][c]&&O.addClass(B[u][c].elm,"mce-item-selected")}}function A(e,t){var n,r,i;n=k(e),r=n.y*D+n.x;do{if(r+=t,i=c(r%D,Math.floor(r/D)),!i)break;if(i.elm!=e)return L.select(i.elm,!0),O.isEmpty(i.elm)&&L.collapse(!0),!0}while(i.elm==e);return!1}var B,D,P,M,H,L=o.selection,O=L.dom;a=a||O.getParent(L.getStart(),"table"),s(),H=O.getParent(L.getStart(),"th,td"),H&&(P=k(H),M=T(),H=c(P.x,P.y)),e.extend(this,{deleteTable:p,split:v,merge:y,insertRow:b,insertCol:C,deleteCols:x,deleteRows:w,cutRows:_,copyRows:E,pasteRows:N,getPos:k,setStartCell:S,setEndCell:R,moveRelIdx:A,refresh:s})}}),r(d,[f,u,c],function(e,t,n){function r(e,t){return parseInt(e.getAttribute(t)||1,10)}var i=n.each;return function(n){function o(){function t(t){function o(e,r){var i=e?"previousSibling":"nextSibling",o=n.dom.getParent(r,"tr"),s=o[i];if(s)return g(n,r,s,e),t.preventDefault(),!0;var u=n.dom.getParent(o,"table"),d=o.parentNode,f=d.nodeName.toLowerCase();if("tbody"===f||f===(e?"tfoot":"thead")){var p=a(e,u,d,"tbody");if(null!==p)return l(e,p,r)}return c(e,o,i,u)}function a(e,t,r,i){var o=n.dom.select(">"+i,t),a=o.indexOf(r);if(e&&0===a||!e&&a===o.length-1)return s(e,t);if(-1===a){var l="thead"===r.tagName.toLowerCase()?0:o.length-1;return o[l]}return o[a+(e?-1:1)]}function s(e,t){var r=e?"thead":"tfoot",i=n.dom.select(">"+r,t);return 0!==i.length?i[0]:null}function l(e,r,i){var o=u(r,e);return o&&g(n,i,o,e),t.preventDefault(),!0}function c(e,r,i,a){var s=a[i];if(s)return d(s),!0;var l=n.dom.getParent(a,"td,th");if(l)return o(e,l,t);var c=u(r,!e);return d(c),t.preventDefault(),!1}function u(e,t){var r=e&&e[t?"lastChild":"firstChild"];return r&&"BR"===r.nodeName?n.dom.getParent(r,"td,th"):r}function d(e){n.selection.setCursorLocation(e,0)}function f(){return b==e.UP||b==e.DOWN}function p(e){var t=e.selection.getNode(),n=e.dom.getParent(t,"tr");return null!==n}function m(e){for(var t=0,n=e;n.previousSibling;)n=n.previousSibling,t+=r(n,"colspan");return t}function h(e,t){var n=0,o=0;return i(e.children,function(e,i){return n+=r(e,"colspan"),o=i,n>t?!1:void 0}),o}function g(e,t,r,i){var o=m(n.dom.getParent(t,"td,th")),a=h(r,o),s=r.childNodes[a],l=u(s,i);d(l||s)}function v(e){var t=n.selection.getNode(),r=n.dom.getParent(t,"td,th"),i=n.dom.getParent(e,"td,th");return r&&r!==i&&y(r,i)}function y(e,t){return n.dom.getParent(e,"TABLE")===n.dom.getParent(t,"TABLE")}var b=t.keyCode;if(f()&&p(n)){var C=n.selection.getNode();setTimeout(function(){v(C)&&o(!t.shiftKey&&b===e.UP,C,t)},0)}}n.on("KeyDown",function(e){t(e)})}function a(){function e(e,t){var n=t.ownerDocument,r=n.createRange(),i;return r.setStartBefore(t),r.setEnd(e.endContainer,e.endOffset),i=n.createElement("body"),i.appendChild(r.cloneContents()),0===i.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length}n.on("KeyDown",function(t){var r,i,o=n.dom;(37==t.keyCode||38==t.keyCode)&&(r=n.selection.getRng(),i=o.getParent(r.startContainer,"table"),i&&n.getBody().firstChild==i&&e(r,i)&&(r=o.createRng(),r.setStartBefore(i),r.setEndBefore(i),n.selection.setRng(r),t.preventDefault()))})}function s(){n.on("KeyDown SetContent VisualAid",function(){var e;for(e=n.getBody().lastChild;e;e=e.previousSibling)if(3==e.nodeType){if(e.nodeValue.length>0)break}else if(1==e.nodeType&&("BR"==e.tagName||!e.getAttribute("data-mce-bogus")))break;e&&"TABLE"==e.nodeName&&(n.settings.forced_root_block?n.dom.add(n.getBody(),n.settings.forced_root_block,n.settings.forced_root_block_attrs,t.ie&&t.ie<11?"&nbsp;":'<br data-mce-bogus="1" />'):n.dom.add(n.getBody(),"br",{"data-mce-bogus":"1"}))}),n.on("PreProcess",function(e){var t=e.node.lastChild;t&&("BR"==t.nodeName||1==t.childNodes.length&&("BR"==t.firstChild.nodeName||"\xa0"==t.firstChild.nodeValue))&&t.previousSibling&&"TABLE"==t.previousSibling.nodeName&&n.dom.remove(t)})}function l(){function e(e,t,n,r){var i=3,o=e.dom.getParent(t.startContainer,"TABLE"),a,s,l;return o&&(a=o.parentNode),s=t.startContainer.nodeType==i&&0===t.startOffset&&0===t.endOffset&&r&&("TR"==n.nodeName||n==a),l=("TD"==n.nodeName||"TH"==n.nodeName)&&!r,s||l}function t(){var t=n.selection.getRng(),r=n.selection.getNode(),i=n.dom.getParent(t.startContainer,"TD,TH");if(e(n,t,r,i)){i||(i=r);for(var o=i.lastChild;o.lastChild;)o=o.lastChild;3==o.nodeType&&(t.setEnd(o,o.data.length),n.selection.setRng(t))}}n.on("KeyDown",function(){t()}),n.on("MouseDown",function(e){2!=e.button&&t()})}function c(){n.on("keydown",function(t){if((t.keyCode==e.DELETE||t.keyCode==e.BACKSPACE)&&!t.isDefaultPrevented()){var r=n.dom.getParent(n.selection.getStart(),"table");if(r){for(var i=n.dom.select("td,th",r),o=i.length;o--;)if(!n.dom.hasClass(i[o],"mce-item-selected"))return;t.preventDefault(),n.execCommand("mceTableDelete")}}})}c(),t.webkit&&(o(),l()),t.gecko&&(a(),s()),t.ie>10&&(a(),s())}}),r(p,[l,m,c],function(e,t,n){return function(r){function i(e){r.getBody().style.webkitUserSelect="",(e||u)&&(r.dom.removeClass(r.dom.select("td.mce-item-selected,th.mce-item-selected"),"mce-item-selected"),u=!1)}function o(t){var n,i,o=t.target;if(!d&&l&&(s||o!=l)&&("TD"==o.nodeName||"TH"==o.nodeName)){i=a.getParent(o,"table"),i==c&&(s||(s=new e(r,i),s.setStartCell(l),r.getBody().style.webkitUserSelect="none"),s.setEndCell(o),u=!0),n=r.selection.getSel();try{n.removeAllRanges?n.removeAllRanges():n.empty()}catch(f){}t.preventDefault()}}var a=r.dom,s,l,c,u=!0,d;return r.on("MouseDown",function(e){2==e.button||d||(i(),l=a.getParent(e.target,"td,th"),c=a.getParent(l,"table"))}),r.on("mouseover",o),r.on("remove",function(){a.unbind(r.getDoc(),"mouseover",o)}),r.on("MouseUp",function(){function e(e,r){var o=new t(e,e);do{if(3==e.nodeType&&0!==n.trim(e.nodeValue).length)return void(r?i.setStart(e,0):i.setEnd(e,e.nodeValue.length));if("BR"==e.nodeName)return void(r?i.setStartBefore(e):i.setEndBefore(e))}while(e=r?o.next():o.prev())}var i,o=r.selection,u,d,f,p;if(l){if(s&&(r.getBody().style.webkitUserSelect=""),u=a.select("td.mce-item-selected,th.mce-item-selected"),u.length>0){i=a.createRng(),f=u[0],i.setStartBefore(f),i.setEndAfter(f),e(f,1),d=new t(f,a.getParent(u[0],"table"));do if("TD"==f.nodeName||"TH"==f.nodeName){if(!a.hasClass(f,"mce-item-selected"))break;p=f}while(f=d.next());e(p),o.setRng(i)}r.nodeChanged(),l=s=c=null}}),r.on("KeyUp Drop SetContent",function(e){i("setcontent"==e.type),l=s=c=null,d=!1}),r.on("ObjectResizeStart ObjectResized",function(e){d="objectresized"!=e.type}),{clear:i}}}),r(h,[c,u],function(e,t){var n=e.each;return function(r){function i(){var e=r.settings.color_picker_callback;return e?function(){var t=this;e.call(r,function(e){t.value(e).fire("change")},t.value())}:void 0}function o(e){return{title:"Advanced",type:"form",defaults:{onchange:function(){d(e,this.parents().reverse()[0],"style"==this.name())}},items:[{label:"Style",name:"style",type:"textbox"},{type:"form",padding:0,formItemDefaults:{layout:"grid",alignH:["start","right"]},defaults:{size:7},items:[{label:"Border color",type:"colorbox",name:"borderColor",onaction:i()},{label:"Background color",type:"colorbox",name:"backgroundColor",onaction:i()}]}]}}function a(e){return e?e.replace(/px$/,""):""}function s(e){return/^[0-9]+$/.test(e)&&(e+="px"),e}function l(e){n("left center right".split(" "),function(t){r.formatter.remove("align"+t,{},e)})}function c(e){n("top middle bottom".split(" "),function(t){r.formatter.remove("valign"+t,{},e)})}function u(t,n,r){function i(t,r){return r=r||[],e.each(t,function(e){var t={text:e.text||e.title};e.menu?t.menu=i(e.menu):(t.value=e.value,n&&n(t)),r.push(t)}),r}return i(t,r||[])}function d(e,t,n){var r=t.toJSON(),i=e.parseStyle(r.style);n?(t.find("#borderColor").value(i["border-color"]||"")[0].fire("change"),t.find("#backgroundColor").value(i["background-color"]||"")[0].fire("change")):(i["border-color"]=r.borderColor,i["background-color"]=r.backgroundColor),t.find("#style").value(e.serializeStyle(e.parseStyle(e.serializeStyle(i))))}function f(e,t,n){var r=e.parseStyle(e.getAttrib(n,"style"));r["border-color"]&&(t.borderColor=r["border-color"]),r["background-color"]&&(t.backgroundColor=r["background-color"]),t.style=e.serializeStyle(r)}var p=this;p.tableProps=function(){p.table(!0)},p.table=function(i){function c(){var n;d(p,this),y=e.extend(y,this.toJSON()),e.each("backgroundColor borderColor".split(" "),function(e){delete y[e]}),y["class"]===!1&&delete y["class"],r.undoManager.transact(function(){m||(m=r.plugins.table.insertTable(y.cols||1,y.rows||1)),r.dom.setAttribs(m,{cellspacing:y.cellspacing,cellpadding:y.cellpadding,border:y.border,style:y.style,"class":y["class"]}),p.getAttrib(m,"width")?p.setAttrib(m,"width",a(y.width)):p.setStyle(m,"width",s(y.width)),p.setStyle(m,"height",s(y.height)),n=p.select("caption",m)[0],n&&!y.caption&&p.remove(n),!n&&y.caption&&(n=p.create("caption"),n.innerHTML=t.ie?"\xa0":'<br data-mce-bogus="1"/>',m.insertBefore(n,m.firstChild)),l(m),y.align&&r.formatter.apply("align"+y.align,{},m),r.focus(),r.addVisual()})}var p=r.dom,m,h,g,v,y={},b;i===!0?(m=p.getParent(r.selection.getStart(),"table"),m&&(y={width:a(p.getStyle(m,"width")||p.getAttrib(m,"width")),height:a(p.getStyle(m,"height")||p.getAttrib(m,"height")),cellspacing:m?p.getAttrib(m,"cellspacing"):"",cellpadding:m?p.getAttrib(m,"cellpadding"):"",border:m?p.getAttrib(m,"border"):"",caption:!!p.select("caption",m)[0],"class":p.getAttrib(m,"class")},n("left center right".split(" "),function(e){r.formatter.matchNode(m,"align"+e)&&(y.align=e)}))):(h={label:"Cols",name:"cols"},g={label:"Rows",name:"rows"}),r.settings.table_class_list&&(y["class"]&&(y["class"]=y["class"].replace(/\s*mce\-item\-table\s*/g,"")),v={name:"class",type:"listbox",label:"Class",values:u(r.settings.table_class_list,function(e){e.value&&(e.textStyle=function(){return r.formatter.getCssText({block:"table",classes:[e.value]})})})}),b={type:"form",layout:"flex",direction:"column",labelGapCalc:"children",padding:0,items:[{type:"form",labelGapCalc:!1,padding:0,layout:"grid",columns:2,defaults:{type:"textbox",maxWidth:50},items:[h,g,{label:"Width",name:"width"},{label:"Height",name:"height"},{label:"Cell spacing",name:"cellspacing"},{label:"Cell padding",name:"cellpadding"},{label:"Border",name:"border"},{label:"Caption",name:"caption",type:"checkbox"}]},{label:"Alignment",name:"align",type:"listbox",text:"None",values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]},v]},r.settings.table_advtab!==!1?(f(p,y,m),r.windowManager.open({title:"Table properties",data:y,bodyType:"tabpanel",body:[{title:"General",type:"form",items:b},o(p)],onsubmit:c})):r.windowManager.open({title:"Table properties",data:y,body:b,onsubmit:c})},p.merge=function(e,t){r.windowManager.open({title:"Merge cells",body:[{label:"Cols",name:"cols",type:"textbox",value:"1",size:10},{label:"Rows",name:"rows",type:"textbox",value:"1",size:10}],onsubmit:function(){var n=this.toJSON();r.undoManager.transact(function(){e.merge(t,n.cols,n.rows)})}})},p.cell=function(){function t(){d(i,this),m=e.extend(m,this.toJSON()),r.undoManager.transact(function(){n(g,function(e){r.dom.setAttribs(e,{scope:m.scope,style:m.style,"class":m["class"]}),r.dom.setStyles(e,{width:s(m.width),height:s(m.height)}),m.type&&e.nodeName.toLowerCase()!=m.type&&(e=i.rename(e,m.type)),l(e),m.align&&r.formatter.apply("align"+m.align,{},e),c(e),m.valign&&r.formatter.apply("valign"+m.valign,{},e)}),r.focus()})}var i=r.dom,p,m,h,g=[];if(g=r.dom.select("td.mce-item-selected,th.mce-item-selected"),p=r.dom.getParent(r.selection.getStart(),"td,th"),!g.length&&p&&g.push(p),p=p||g[0]){m={width:a(i.getStyle(p,"width")||i.getAttrib(p,"width")),height:a(i.getStyle(p,"height")||i.getAttrib(p,"height")),scope:i.getAttrib(p,"scope"),"class":i.getAttrib(p,"class")},m.type=p.nodeName.toLowerCase(),n("left center right".split(" "),function(e){r.formatter.matchNode(p,"align"+e)&&(m.align=e)}),n("top middle bottom".split(" "),function(e){r.formatter.matchNode(p,"valign"+e)&&(m.valign=e)}),r.settings.table_cell_class_list&&(h={name:"class",type:"listbox",label:"Class",values:u(r.settings.table_cell_class_list,function(e){e.value&&(e.textStyle=function(){return r.formatter.getCssText({block:"td",classes:[e.value]})})})});var v={type:"form",layout:"flex",direction:"column",labelGapCalc:"children",padding:0,items:[{type:"form",layout:"grid",columns:2,labelGapCalc:!1,padding:0,defaults:{type:"textbox",maxWidth:50},items:[{label:"Width",name:"width"},{label:"Height",name:"height"},{label:"Cell type",name:"type",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"Cell",value:"td"},{text:"Header cell",value:"th"}]},{label:"Scope",name:"scope",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Row",value:"row"},{text:"Column",value:"col"},{text:"Row group",value:"rowgroup"},{text:"Column group",value:"colgroup"}]},{label:"H Align",name:"align",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]},{label:"V Align",name:"valign",type:"listbox",text:"None",minWidth:90,maxWidth:null,values:[{text:"None",value:""},{text:"Top",value:"top"},{text:"Middle",value:"middle"},{text:"Bottom",value:"bottom"}]}]},h]};r.settings.table_cell_advtab!==!1?(f(i,m,p),r.windowManager.open({title:"Cell properties",bodyType:"tabpanel",data:m,body:[{title:"General",type:"form",items:v},o(i)],onsubmit:t})):r.windowManager.open({title:"Cell properties",data:m,body:v,onsubmit:t})}},p.row=function(){function t(){var t,o,a;d(i,this),g=e.extend(g,this.toJSON()),r.undoManager.transact(function(){var e=g.type;n(v,function(n){r.dom.setAttribs(n,{scope:g.scope,style:g.style,"class":g["class"]}),r.dom.setStyles(n,{height:s(g.height)}),e!=n.parentNode.nodeName.toLowerCase()&&(t=i.getParent(n,"table"),o=n.parentNode,a=i.select(e,t)[0],a||(a=i.create(e),t.firstChild?t.insertBefore(a,t.firstChild):t.appendChild(a)),a.appendChild(n),o.hasChildNodes()||i.remove(o)),l(n),g.align&&r.formatter.apply("align"+g.align,{},n)}),r.focus()})}var i=r.dom,c,p,m,h,g,v=[],y;c=r.dom.getParent(r.selection.getStart(),"table"),p=r.dom.getParent(r.selection.getStart(),"td,th"),n(c.rows,function(e){n(e.cells,function(t){return i.hasClass(t,"mce-item-selected")||t==p?(v.push(e),!1):void 0})}),m=v[0],m&&(g={height:a(i.getStyle(m,"height")||i.getAttrib(m,"height")),scope:i.getAttrib(m,"scope"),"class":i.getAttrib(m,"class")},g.type=m.parentNode.nodeName.toLowerCase(),n("left center right".split(" "),function(e){r.formatter.matchNode(m,"align"+e)&&(g.align=e)}),r.settings.table_row_class_list&&(h={name:"class",type:"listbox",label:"Class",values:u(r.settings.table_row_class_list,function(e){e.value&&(e.textStyle=function(){return r.formatter.getCssText({block:"tr",classes:[e.value]})})})}),y={type:"form",columns:2,padding:0,defaults:{type:"textbox"},items:[{type:"listbox",name:"type",label:"Row type",text:"None",maxWidth:null,values:[{text:"Header",value:"thead"},{text:"Body",value:"tbody"},{text:"Footer",value:"tfoot"}]},{type:"listbox",name:"align",label:"Alignment",text:"None",maxWidth:null,values:[{text:"None",value:""},{text:"Left",value:"left"},{text:"Center",value:"center"},{text:"Right",value:"right"}]},{label:"Height",name:"height"},h]},r.settings.table_row_advtab!==!1?(f(i,g,m),r.windowManager.open({title:"Row properties",data:g,bodyType:"tabpanel",body:[{title:"General",type:"form",items:y},o(i)],onsubmit:t})):r.windowManager.open({title:"Row properties",data:g,body:y,onsubmit:t}))}}}),r(g,[l,d,p,h,c,m,u,v],function(e,t,n,r,i,o,a,s){function l(i){function o(e){return function(){i.execCommand(e)}}function s(e,t){var n,r,o,s;for(o='<table id="__mce"><tbody>',n=0;t>n;n++){for(o+="<tr>",r=0;e>r;r++)o+="<td>"+(a.ie?" ":"<br>")+"</td>";o+="</tr>"}return o+="</tbody></table>",i.undoManager.transact(function(){i.insertContent(o),s=i.dom.get("__mce"),i.dom.setAttrib(s,"id",null),i.dom.setAttribs(s,i.settings.table_default_attributes||{}),i.dom.setStyles(s,i.settings.table_default_styles||{})}),s}function l(e,t){function n(){e.disabled(!i.dom.getParent(i.selection.getStart(),t)),i.selection.selectorChanged(t,function(t){e.disabled(!t)})}i.initialized?n():i.on("init",n)}function u(){l(this,"table")}function d(){l(this,"td,th")}function f(){var e="";e='<table role="grid" class="mce-grid mce-grid-border" aria-readonly="true">';for(var t=0;10>t;t++){e+="<tr>";for(var n=0;10>n;n++)e+='<td role="gridcell" tabindex="-1"><a id="mcegrid'+(10*t+n)+'" href="#" data-mce-x="'+n+'" data-mce-y="'+t+'"></a></td>';e+="</tr>"}return e+="</table>",e+='<div class="mce-text-center" role="presentation">1 x 1</div>'}function p(e,t,n){var r=n.getEl().getElementsByTagName("table")[0],o,a,s,l,c,u=n.isRtl()||"tl-tr"==n.parent().rel;for(r.nextSibling.innerHTML=e+1+" x "+(t+1),u&&(e=9-e),a=0;10>a;a++)for(o=0;10>o;o++)l=r.rows[a].childNodes[o].firstChild,c=(u?o>=e:e>=o)&&t>=a,i.dom.toggleClass(l,"mce-active",c),c&&(s=l);return s.parentNode}var m,h=this,g=new r(i);i.settings.table_grid===!1?i.addMenuItem("inserttable",{text:"Insert table",icon:"table",context:"table",onclick:g.table}):i.addMenuItem("inserttable",{text:"Insert table",icon:"table",context:"table",ariaHideMenu:!0,onclick:function(e){e.aria&&(this.parent().hideAll(),e.stopImmediatePropagation(),g.table())},onshow:function(){p(0,0,this.menu.items()[0])},onhide:function(){var e=this.menu.items()[0].getEl().getElementsByTagName("a");i.dom.removeClass(e,"mce-active"),i.dom.addClass(e[0],"mce-active")},menu:[{type:"container",html:f(),onPostRender:function(){this.lastX=this.lastY=0},onmousemove:function(e){var t=e.target,n,r;"A"==t.tagName.toUpperCase()&&(n=parseInt(t.getAttribute("data-mce-x"),10),r=parseInt(t.getAttribute("data-mce-y"),10),(this.isRtl()||"tl-tr"==this.parent().rel)&&(n=9-n),(n!==this.lastX||r!==this.lastY)&&(p(n,r,e.control),this.lastX=n,this.lastY=r))},onclick:function(e){var t=this;"A"==e.target.tagName.toUpperCase()&&(e.preventDefault(),e.stopPropagation(),t.parent().cancel(),i.undoManager.transact(function(){s(t.lastX+1,t.lastY+1)}),i.addVisual())}}]}),i.addMenuItem("tableprops",{text:"Table properties",context:"table",onPostRender:u,onclick:g.tableProps}),i.addMenuItem("deletetable",{text:"Delete table",context:"table",onPostRender:u,cmd:"mceTableDelete"}),i.addMenuItem("cell",{separator:"before",text:"Cell",context:"table",menu:[{text:"Cell properties",onclick:o("mceTableCellProps"),onPostRender:d},{text:"Merge cells",onclick:o("mceTableMergeCells"),onPostRender:d},{text:"Split cell",onclick:o("mceTableSplitCells"),onPostRender:d}]}),i.addMenuItem("row",{text:"Row",context:"table",menu:[{text:"Insert row before",onclick:o("mceTableInsertRowBefore"),onPostRender:d},{text:"Insert row after",onclick:o("mceTableInsertRowAfter"),onPostRender:d},{text:"Delete row",onclick:o("mceTableDeleteRow"),onPostRender:d},{text:"Row properties",onclick:o("mceTableRowProps"),onPostRender:d},{text:"-"},{text:"Cut row",onclick:o("mceTableCutRow"),onPostRender:d},{text:"Copy row",onclick:o("mceTableCopyRow"),onPostRender:d},{text:"Paste row before",onclick:o("mceTablePasteRowBefore"),onPostRender:d},{text:"Paste row after",onclick:o("mceTablePasteRowAfter"),onPostRender:d}]}),i.addMenuItem("column",{text:"Column",context:"table",menu:[{text:"Insert column before",onclick:o("mceTableInsertColBefore"),onPostRender:d},{text:"Insert column after",onclick:o("mceTableInsertColAfter"),onPostRender:d},{text:"Delete column",onclick:o("mceTableDeleteCol"),onPostRender:d}]});var v=[];c("inserttable tableprops deletetable | cell row column".split(" "),function(e){v.push("|"==e?{text:"-"}:i.menuItems[e])}),i.addButton("table",{type:"menubutton",title:"Table",menu:v}),a.isIE||i.on("click",function(e){e=e.target,"TABLE"===e.nodeName&&(i.selection.select(e),i.nodeChanged())}),h.quirks=new t(i),i.on("Init",function(){h.cellSelection=new n(i)}),c({mceTableSplitCells:function(e){e.split()},mceTableMergeCells:function(e){var t;t=i.dom.getParent(i.selection.getStart(),"th,td"),i.dom.select("td.mce-item-selected,th.mce-item-selected").length?e.merge():g.merge(e,t)},mceTableInsertRowBefore:function(e){e.insertRow(!0)},mceTableInsertRowAfter:function(e){e.insertRow()},mceTableInsertColBefore:function(e){e.insertCol(!0)},mceTableInsertColAfter:function(e){e.insertCol()},mceTableDeleteCol:function(e){e.deleteCols()},mceTableDeleteRow:function(e){e.deleteRows()},mceTableCutRow:function(e){m=e.cutRows()},mceTableCopyRow:function(e){m=e.copyRows()},mceTablePasteRowBefore:function(e){e.pasteRows(m,!0)},mceTablePasteRowAfter:function(e){e.pasteRows(m)},mceTableDelete:function(e){e.deleteTable()}},function(t,n){i.addCommand(n,function(){var n=new e(i);n&&(t(n),i.execCommand("mceRepaint"),h.cellSelection.clear())})}),c({mceInsertTable:g.table,mceTableProps:function(){g.table(!0)},mceTableRowProps:g.row,mceTableCellProps:g.cell},function(e,t){i.addCommand(t,function(t,n){e(n)})}),i.settings.table_tab_navigation!==!1&&i.on("keydown",function(t){var n,r,o;9==t.keyCode&&(n=i.dom.getParent(i.selection.getStart(),"th,td"),n&&(t.preventDefault(),r=new e(i),o=t.shiftKey?-1:1,i.undoManager.transact(function(){!r.moveRelIdx(n,o)&&o>0&&(r.insertRow(),r.refresh(),r.moveRelIdx(n,o))})))}),h.insertTable=s}var c=i.each;s.add("table",l)}),a([])}(this);