MCE Table Buttons - Version 2.0

Version Description

  • New button icons that better conform with WordPress's editor design
  • Retina (HiDPI) ready button icons!
  • Upgraded to latest version of TinyMCE tables plugin (fixes a lot of edge case bugs)
  • Rewrote code for hiding / display toolbar with kitchen sink (now a TinyMCE plug-in instead of a workaround) - the table buttons no longer briefly appear before page loading is finished
Download this release

Release Info

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

Code changes from version 1.5 to 2.0

assets/mce-table-buttons-2x.png ADDED
Binary file
assets/mce-table-buttons.css ADDED
@@ -0,0 +1,106 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .wp_themeSkin .mceButton span.mce_table,
2
+ .wp_themeSkin .mceButton span.mce_row_props,
3
+ .wp_themeSkin .mceButton span.mce_cell_props,
4
+ .wp_themeSkin .mceButton span.mce_row_before,
5
+ .wp_themeSkin .mceButton span.mce_row_after,
6
+ .wp_themeSkin .mceButton span.mce_delete_row,
7
+ .wp_themeSkin .mceButton span.mce_col_before,
8
+ .wp_themeSkin .mceButton span.mce_col_after,
9
+ .wp_themeSkin .mceButton span.mce_delete_col,
10
+ .wp_themeSkin .mceButton span.mce_split_cells,
11
+ .wp_themeSkin .mceButton span.mce_merge_cells {
12
+ background: url('mce-table-buttons.png') 2px -16px no-repeat;
13
+ }
14
+ .wp_themeSkin .mceButtonEnabled:hover span.mce_table, .wp_themeSkin .mceButtonActive span.mce_table {
15
+ background-position: 2px 2px;
16
+ }
17
+
18
+ .wp_themeSkin .mceButton span.mce_row_props {
19
+ background-position: -198px -16px;
20
+ }
21
+ .wp_themeSkin .mceButtonEnabled:hover span.mce_row_props, .wp_themeSkin .mceButtonActive span.mce_row_props {
22
+ background-position: -198px 2px;
23
+ }
24
+
25
+ .wp_themeSkin .mceButton span.mce_cell_props {
26
+ background-position: -18px -16px;
27
+ }
28
+ .wp_themeSkin .mceButtonEnabled:hover span.mce_cell_props, .wp_themeSkin .mceButtonActive span.mce_cell_props {
29
+ background-position: -18px 2px;
30
+ }
31
+
32
+ .wp_themeSkin .mceButton span.mce_row_before {
33
+ background-position: -158px -16px;
34
+ }
35
+ .wp_themeSkin .mceButtonEnabled:hover span.mce_row_before, .wp_themeSkin .mceButtonActive span.mce_row_before {
36
+ background-position: -158px 2px;
37
+ }
38
+
39
+ .wp_themeSkin .mceButton span.mce_row_after {
40
+ background-position: -138px -16px;
41
+ }
42
+ .wp_themeSkin .mceButtonEnabled:hover span.mce_row_after, .wp_themeSkin .mceButtonActive span.mce_row_after {
43
+ background-position: -138px 2px;
44
+ }
45
+
46
+ .wp_themeSkin .mceButton span.mce_delete_row {
47
+ background-position: -78px -16px;
48
+ }
49
+ .wp_themeSkin .mceButtonEnabled:hover span.mce_delete_row, .wp_themeSkin .mceButtonActive span.mce_delete_row {
50
+ background-position: -78px 2px;
51
+ }
52
+
53
+ .wp_themeSkin .mceButton span.mce_col_before {
54
+ background-position: -118px -16px;
55
+ }
56
+ .wp_themeSkin .mceButtonEnabled:hover span.mce_col_before, .wp_themeSkin .mceButtonActive span.mce_col_before {
57
+ background-position: -118px 2px;
58
+ }
59
+
60
+ .wp_themeSkin .mceButton span.mce_col_after {
61
+ background-position: -98px -16px;
62
+ }
63
+ .wp_themeSkin .mceButtonEnabled:hover span.mce_col_after, .wp_themeSkin .mceButtonActive span.mce_col_after {
64
+ background-position: -98px 2px;
65
+ }
66
+
67
+ .wp_themeSkin .mceButton span.mce_delete_col {
68
+ background-position: -58px -16px;
69
+ }
70
+ .wp_themeSkin .mceButtonEnabled:hover span.mce_delete_col, .wp_themeSkin .mceButtonActive span.mce_delete_col {
71
+ background-position: -58px 2px;
72
+ }
73
+
74
+ .wp_themeSkin .mceButton span.mce_split_cells {
75
+ background-position: -218px -16px;
76
+ }
77
+ .wp_themeSkin .mceButtonEnabled:hover span.mce_split_cells, .wp_themeSkin .mceButtonActive span.mce_split_cells {
78
+ background-position: -218px 2px;
79
+ }
80
+
81
+ .wp_themeSkin .mceButton span.mce_merge_cells {
82
+ background-position: -178px -16px;
83
+ }
84
+ .wp_themeSkin .mceButtonEnabled:hover span.mce_merge_cells, .wp_themeSkin .mceButtonActive span.mce_merge_cells {
85
+ background-position: -178px 2px;
86
+ }
87
+
88
+ @media print,
89
+ (-o-min-device-pixel-ratio: 5/4),
90
+ (-webkit-min-device-pixel-ratio: 1.25),
91
+ (min-resolution: 120dpi) {
92
+ .wp_themeSkin .mceButton span.mce_table,
93
+ .wp_themeSkin .mceButton span.mce_row_props,
94
+ .wp_themeSkin .mceButton span.mce_cell_props,
95
+ .wp_themeSkin .mceButton span.mce_row_before,
96
+ .wp_themeSkin .mceButton span.mce_row_after,
97
+ .wp_themeSkin .mceButton span.mce_delete_row,
98
+ .wp_themeSkin .mceButton span.mce_col_before,
99
+ .wp_themeSkin .mceButton span.mce_col_after,
100
+ .wp_themeSkin .mceButton span.mce_delete_col,
101
+ .wp_themeSkin .mceButton span.mce_split_cells,
102
+ .wp_themeSkin .mceButton span.mce_merge_cells {
103
+ background-image: url('mce-table-buttons-2x.png');
104
+ background-size: 235px 34px;
105
+ }
106
+ }
assets/mce-table-buttons.js ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * WordPress plugin.
3
+ */
4
+
5
+ (function() {
6
+ var DOM = tinymce.DOM;
7
+
8
+ tinymce.create('tinymce.plugins.mcetablebuttons', {
9
+ init : function(ed, url) {
10
+ var mce_table_toolbar;
11
+
12
+ // Hides the specified toolbar and resizes the iframe
13
+ ed.onPostRender.add(function() {
14
+ mce_table_toolbar = ed.controlManager.get('toolbar3');
15
+ if ( ed.getParam('wordpress_adv_hidden', 1) && mce_table_toolbar )
16
+ DOM.hide(mce_table_toolbar.id);
17
+ });
18
+
19
+ ed.onExecCommand.add(function(ed, cmd, ui, val) {
20
+ if ( cmd == 'WP_Adv' ) {
21
+ if ( ed.settings.wordpress_adv_hidden == 1 )
22
+ DOM.hide( mce_table_toolbar.id );
23
+ else
24
+ DOM.show( mce_table_toolbar.id );
25
+ }
26
+ });
27
+ }
28
+ });
29
+
30
+ // Register plugin
31
+ tinymce.PluginManager.add('mcetablebuttons', tinymce.plugins.mcetablebuttons);
32
+ })();
assets/mce-table-buttons.png ADDED
Binary file
mce_table_buttons.php CHANGED
@@ -1,47 +1,30 @@
1
  <?php
2
  /**
3
  Plugin Name: MCE Table Buttons
4
- Plugin URI: http://www.get10up.com/plugins-modules/wordpress-mce-table-buttons/
5
  Description: Add <strong>buttons for table editing</strong> to the WordPress WYSIWYG editor with this <strong>light weight</strong> plug-in.
6
- Version: 1.5
7
- Author: Jake Goldman (10up LLC)
8
- Author URI: http://get10up.com
9
-
10
- Plugin: Copyright 2011 Jake Goldman (email : jake@get10up.com)
11
-
12
- This program is free software; you can redistribute it and/or modify
13
- it under the terms of the GNU General Public License as published by
14
- the Free Software Foundation; either version 2 of the License, or
15
- (at your option) any later version.
16
-
17
- This program is distributed in the hope that it will be useful,
18
- but WITHOUT ANY WARRANTY; without even the implied warranty of
19
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
- GNU General Public License for more details.
21
-
22
- You should have received a copy of the GNU General Public License
23
- along with this program; if not, write to the Free Software
24
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25
-
26
- NOTE: Previous versions may have had their copyright incorrectly attributed
27
- to employers of Mr. Goldman. The copyright belongs solely to Mr. Goldman,
28
- personally.
29
  */
30
 
31
  class MCE_Table_Buttons {
32
  public function __construct() {
33
  add_action( 'admin_init', array( $this, 'admin_init' ) );
34
  add_action( 'content_save_pre', array( $this, 'content_save_pre'), 100 );
35
- add_action( 'admin_footer', array( $this, 'admin_footer' ), 100 );
36
  }
37
 
38
  public function admin_init() {
39
  add_filter( 'mce_external_plugins', array( $this, 'mce_external_plugins' ) );
40
  add_filter( 'mce_buttons_3', array( $this, 'mce_buttons_3' ) );
 
41
  }
42
 
43
  public function mce_external_plugins( $plugin_array ) {
44
- $plugin_array['table'] = plugin_dir_url( __FILE__ ) . 'table/editor_plugin.js';
 
 
45
  return $plugin_array;
46
  }
47
 
@@ -49,29 +32,20 @@ class MCE_Table_Buttons {
49
  array_push( $buttons, 'tablecontrols' );
50
  return $buttons;
51
  }
52
-
53
- public function admin_footer() {
54
- if ( ! wp_script_is( 'editor' ) )
55
- return;
56
- ?>
57
- <script type="text/javascript">
58
- jQuery(window).load(function(){
59
- jQuery('.mceToolbarRow2').each(function(){
60
- if(!jQuery(this).is(':visible')) jQuery(this).siblings('.mceToolbarRow3').hide();
61
- });
62
- jQuery('.mce_wp_adv').click(function(){
63
- var toolbar3 = jQuery(this).closest('table').siblings('.mceToolbarRow3');
64
- if ( jQuery(this).hasClass('mceButtonActive') ) toolbar3.show();
65
- else toolbar3.hide();
66
- });
67
- });
68
- </script>
69
- <?php
70
  }
71
 
72
  public function content_save_pre( $content ) {
73
  if ( substr( $content, -8 ) == '</table>' )
74
- $content = $content . "\n<br />";
75
 
76
  return $content;
77
  }
1
  <?php
2
  /**
3
  Plugin Name: MCE Table Buttons
4
+ Plugin URI: http://10up.com/plugins-modules/wordpress-mce-table-buttons/
5
  Description: Add <strong>buttons for table editing</strong> to the WordPress WYSIWYG editor with this <strong>light weight</strong> plug-in.
6
+ Version: 2.0
7
+ Author: Jake Goldman, 10up, Oomph
8
+ Author URI: http://10up.com
9
+ License: GPLv2 or later
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  */
11
 
12
  class MCE_Table_Buttons {
13
  public function __construct() {
14
  add_action( 'admin_init', array( $this, 'admin_init' ) );
15
  add_action( 'content_save_pre', array( $this, 'content_save_pre'), 100 );
 
16
  }
17
 
18
  public function admin_init() {
19
  add_filter( 'mce_external_plugins', array( $this, 'mce_external_plugins' ) );
20
  add_filter( 'mce_buttons_3', array( $this, 'mce_buttons_3' ) );
21
+ add_filter( 'style_loader_tag', array( $this, 'style_loader_tag' ), 50, 2 );
22
  }
23
 
24
  public function mce_external_plugins( $plugin_array ) {
25
+ $plugin_dir_url = plugin_dir_url( __FILE__ );
26
+ $plugin_array['table'] = $plugin_dir_url . 'table/editor_plugin.js';
27
+ $plugin_array['mcetablebuttons'] = $plugin_dir_url . 'assets/mce-table-buttons.js';
28
  return $plugin_array;
29
  }
30
 
32
  array_push( $buttons, 'tablecontrols' );
33
  return $buttons;
34
  }
35
+
36
+ public function style_loader_tag( $tag, $handle ) {
37
+ if ( $handle == 'editor-buttons' ) {
38
+ remove_filter( 'style_loader_tag', array( $this, 'style_loader_tag' ), 50, 2 );
39
+ wp_register_style( 'mce-table-buttons', plugin_dir_url( __FILE__ ) . 'assets/mce-table-buttons.css' );
40
+ wp_print_styles( 'mce-table-buttons' );
41
+ }
42
+
43
+ return $tag;
 
 
 
 
 
 
 
 
 
44
  }
45
 
46
  public function content_save_pre( $content ) {
47
  if ( substr( $content, -8 ) == '</table>' )
48
+ $content .= "\n<br />";
49
 
50
  return $content;
51
  }
readme.txt CHANGED
@@ -1,10 +1,10 @@
1
  === MCE Table Buttons ===
2
  Contributors: jakemgold, 10up, thinkoomph
3
- Donate link: http://www.get10up.com/plugins-modules/wordpress-mce-table-buttons/
4
  Tags: tables, table, editor, WYSIWYG, buttons, tinymce
5
- Requires at least: 3.3
6
- Tested up to: 3.3
7
- Stable tag: 1.5
8
 
9
  Adds table editing buttons to a new, third row in the WordPress WYSIWYG editor.
10
 
@@ -12,21 +12,28 @@ Adds table editing buttons to a new, third row in the WordPress WYSIWYG editor.
12
 
13
  Adds table editing buttons to a new, third row in the WordPress WYSIWYG editor.
14
 
15
- A very light weight plug-in based on a slightly modified version of the table editor plug-in included with the full version of TinyMCE. Only includes English localization; please let us know if you would like additional localizations added. Note that this should not be used with other plug-ins that significantly alter the editor's default behavior. It is intended to be a simple, light weight solution for editors who only want to add table management to WordPress' included editor.
16
 
17
- The third, editor toolbar is hidden or displayed along with the "kitchen sink."
18
 
19
  == Installation ==
20
 
21
  1. Install easily with the WordPress plugin control panel or manually download the plugin and upload the folder
22
  `mce-table-buttons` to the `/wp-content/plugins/` directory
23
- 1. Activate the plugin through the 'Plugins' menu in WordPress
 
24
 
25
  == Screenshots ==
26
 
27
  1. The editor with the new table editing controls.
28
 
29
  == Changelog ==
 
 
 
 
 
 
30
 
31
  = 1.5 =
32
  * Table toolbar is hidden or displayed along with the kitchen sink (yay!)
1
  === MCE Table Buttons ===
2
  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.5
7
+ Stable tag: 2.0
8
 
9
  Adds table editing buttons to a new, third row in the WordPress WYSIWYG editor.
10
 
12
 
13
  Adds table editing buttons to a new, third row in the WordPress WYSIWYG editor.
14
 
15
+ A light weight plug-in that restores the table editing buttons from the full version of TinyMCE, optimized for WordPress. Note that this should not be used with other plug-ins that significantly alter the editor's default behavior.
16
 
17
+ The third, editor toolbar is hidden or displayed with the "kitchen sink" (just like the second toolbar row).
18
 
19
  == Installation ==
20
 
21
  1. Install easily with the WordPress plugin control panel or manually download the plugin and upload the folder
22
  `mce-table-buttons` to the `/wp-content/plugins/` directory
23
+ 1. Activate the plugin through the 'Plugins' menu in WordPress
24
+ 1. Show the toolbar in the editor by opening the "kitchen sink" (the last button in the first row)
25
 
26
  == Screenshots ==
27
 
28
  1. The editor with the new table editing controls.
29
 
30
  == Changelog ==
31
+
32
+ = 2.0 =
33
+ * New button icons that better conform with WordPress's editor design
34
+ * Retina (HiDPI) ready button icons!
35
+ * Upgraded to latest version of TinyMCE tables plugin (fixes a lot of edge case bugs)
36
+ * Rewrote code for hiding / display toolbar with kitchen sink (now a TinyMCE plug-in instead of a workaround) - the table buttons no longer briefly appear before page loading is finished
37
 
38
  = 1.5 =
39
  * Table toolbar is hidden or displayed along with the kitchen sink (yay!)
screenshot-1.png CHANGED
Binary file
table/editor_plugin.js CHANGED
@@ -1 +1 @@
1
- (function(d){var e=d.each;function c(g,h){var j=h.ownerDocument,f=j.createRange(),k;f.setStartBefore(h);f.setEnd(g.endContainer,g.endOffset);k=j.createElement("body");k.appendChild(f.cloneContents());return k.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length==0}function a(g,f){return parseInt(g.getAttribute(f)||1)}function b(H,G,K){var g,L,D,o;t();o=G.getParent(K.getStart(),"th,td");if(o){L=F(o);D=I();o=z(L.x,L.y)}function A(N,M){N=N.cloneNode(M);N.removeAttribute("id");return N}function t(){var M=0;g=[];e(["thead","tbody","tfoot"],function(N){var O=G.select("> "+N+" tr",H);e(O,function(P,Q){Q+=M;e(G.select("> td, > th",P),function(W,R){var S,T,U,V;if(g[Q]){while(g[Q][R]){R++}}U=a(W,"rowspan");V=a(W,"colspan");for(T=Q;T<Q+U;T++){if(!g[T]){g[T]=[]}for(S=R;S<R+V;S++){g[T][S]={part:N,real:T==Q&&S==R,elm:W,rowspan:U,colspan:V}}}})});M+=O.length})}function z(M,O){var N;N=g[O];if(N){return N[M]}}function s(O,M,N){if(O){N=parseInt(N);if(N===1){O.removeAttribute(M,1)}else{O.setAttribute(M,N,1)}}}function j(M){return M&&(G.hasClass(M.elm,"mceSelected")||M==o)}function k(){var M=[];e(H.rows,function(N){e(N.cells,function(O){if(G.hasClass(O,"mceSelected")||O==o.elm){M.push(N);return false}})});return M}function r(){var M=G.createRng();M.setStartAfter(H);M.setEndAfter(H);K.setRng(M);G.remove(H)}function f(M){var N;d.walk(M,function(P){var O;if(P.nodeType==3){e(G.getParents(P.parentNode,null,M).reverse(),function(Q){Q=A(Q,false);if(!N){N=O=Q}else{if(O){O.appendChild(Q)}}O=Q});if(O){O.innerHTML=d.isIE?"&nbsp;":'<br data-mce-bogus="1" />'}return false}},"childNodes");M=A(M,false);s(M,"rowSpan",1);s(M,"colSpan",1);if(N){M.appendChild(N)}else{if(!d.isIE){M.innerHTML='<br data-mce-bogus="1" />'}}return M}function q(){var M=G.createRng();e(G.select("tr",H),function(N){if(N.cells.length==0){G.remove(N)}});if(G.select("tr",H).length==0){M.setStartAfter(H);M.setEndAfter(H);K.setRng(M);G.remove(H);return}e(G.select("thead,tbody,tfoot",H),function(N){if(N.rows.length==0){G.remove(N)}});t();row=g[Math.min(g.length-1,L.y)];if(row){K.select(row[Math.min(row.length-1,L.x)].elm,true);K.collapse(true)}}function u(S,Q,U,R){var P,N,M,O,T;P=g[Q][S].elm.parentNode;for(M=1;M<=U;M++){P=G.getNext(P,"tr");if(P){for(N=S;N>=0;N--){T=g[Q+M][N].elm;if(T.parentNode==P){for(O=1;O<=R;O++){G.insertAfter(f(T),T)}break}}if(N==-1){for(O=1;O<=R;O++){P.insertBefore(f(P.cells[0]),P.cells[0])}}}}}function C(){e(g,function(M,N){e(M,function(P,O){var S,R,T,Q;if(j(P)){P=P.elm;S=a(P,"colspan");R=a(P,"rowspan");if(S>1||R>1){s(P,"rowSpan",1);s(P,"colSpan",1);for(Q=0;Q<S-1;Q++){G.insertAfter(f(P),P)}u(O,N,R-1,S)}}})})}function p(V,S,Y){var P,O,X,W,U,R,T,M,V,N,Q;if(V){pos=F(V);P=pos.x;O=pos.y;X=P+(S-1);W=O+(Y-1)}else{P=L.x;O=L.y;X=D.x;W=D.y}T=z(P,O);M=z(X,W);if(T&&M&&T.part==M.part){C();t();T=z(P,O).elm;s(T,"colSpan",(X-P)+1);s(T,"rowSpan",(W-O)+1);for(R=O;R<=W;R++){for(U=P;U<=X;U++){if(!g[R]||!g[R][U]){continue}V=g[R][U].elm;if(V!=T){N=d.grep(V.childNodes);e(N,function(Z){T.appendChild(Z)});if(N.length){N=d.grep(T.childNodes);Q=0;e(N,function(Z){if(Z.nodeName=="BR"&&G.getAttrib(Z,"data-mce-bogus")&&Q++<N.length-1){T.removeChild(Z)}})}G.remove(V)}}}q()}}function l(Q){var M,S,P,R,T,U,N,V,O;e(g,function(W,X){e(W,function(Z,Y){if(j(Z)){Z=Z.elm;T=Z.parentNode;U=A(T,false);M=X;if(Q){return false}}});if(Q){return !M}});for(R=0;R<g[0].length;R++){if(!g[M][R]){continue}S=g[M][R].elm;if(S!=P){if(!Q){O=a(S,"rowspan");if(O>1){s(S,"rowSpan",O+1);continue}}else{if(M>0&&g[M-1][R]){V=g[M-1][R].elm;O=a(V,"rowSpan");if(O>1){s(V,"rowSpan",O+1);continue}}}N=f(S);s(N,"colSpan",S.colSpan);U.appendChild(N);P=S}}if(U.hasChildNodes()){if(!Q){G.insertAfter(U,T)}else{T.parentNode.insertBefore(U,T)}}}function h(N){var O,M;e(g,function(P,Q){e(P,function(S,R){if(j(S)){O=R;if(N){return false}}});if(N){return !O}});e(g,function(S,T){var P,Q,R;if(!S[O]){return}P=S[O].elm;if(P!=M){R=a(P,"colspan");Q=a(P,"rowspan");if(R==1){if(!N){G.insertAfter(f(P),P);u(O,T,Q-1,R)}else{P.parentNode.insertBefore(f(P),P);u(O,T,Q-1,R)}}else{s(P,"colSpan",P.colSpan+1)}M=P}})}function n(){var M=[];e(g,function(N,O){e(N,function(Q,P){if(j(Q)&&d.inArray(M,P)===-1){e(g,function(T){var R=T[P].elm,S;S=a(R,"colSpan");if(S>1){s(R,"colSpan",S-1)}else{G.remove(R)}});M.push(P)}})});q()}function m(){var N;function M(Q){var P,R,O;P=G.getNext(Q,"tr");e(Q.cells,function(S){var T=a(S,"rowSpan");if(T>1){s(S,"rowSpan",T-1);R=F(S);u(R.x,R.y,1,1)}});R=F(Q.cells[0]);e(g[R.y],function(S){var T;S=S.elm;if(S!=O){T=a(S,"rowSpan");if(T<=1){G.remove(S)}else{s(S,"rowSpan",T-1)}O=S}})}N=k();e(N.reverse(),function(O){M(O)});q()}function E(){var M=k();G.remove(M);q();return M}function J(){var M=k();e(M,function(O,N){M[N]=A(O,true)});return M}function B(O,N){var P=k(),M=P[N?0:P.length-1],Q=M.cells.length;e(g,function(S){var R;Q=0;e(S,function(U,T){if(U.real){Q+=U.colspan}if(U.elm.parentNode==M){R=1}});if(R){return false}});if(!N){O.reverse()}e(O,function(T){var S=T.cells.length,R;for(i=0;i<S;i++){R=T.cells[i];s(R,"colSpan",1);s(R,"rowSpan",1)}for(i=S;i<Q;i++){T.appendChild(f(T.cells[S-1]))}for(i=Q;i<S;i++){G.remove(T.cells[i])}if(N){M.parentNode.insertBefore(T,M)}else{G.insertAfter(T,M)}})}function F(M){var N;e(g,function(O,P){e(O,function(R,Q){if(R.elm==M){N={x:Q,y:P};return false}});return !N});return N}function w(M){L=F(M)}function I(){var O,N,M;N=M=0;e(g,function(P,Q){e(P,function(S,R){var U,T;if(j(S)){S=g[Q][R];if(R>N){N=R}if(Q>M){M=Q}if(S.real){U=S.colspan-1;T=S.rowspan-1;if(U){if(R+U>N){N=R+U}}if(T){if(Q+T>M){M=Q+T}}}}})});return{x:N,y:M}}function v(S){var P,O,U,T,N,M,Q,R;D=F(S);if(L&&D){P=Math.min(L.x,D.x);O=Math.min(L.y,D.y);U=Math.max(L.x,D.x);T=Math.max(L.y,D.y);N=U;M=T;for(y=O;y<=M;y++){S=g[y][P];if(!S.real){if(P-(S.colspan-1)<P){P-=S.colspan-1}}}for(x=P;x<=N;x++){S=g[O][x];if(!S.real){if(O-(S.rowspan-1)<O){O-=S.rowspan-1}}}for(y=O;y<=T;y++){for(x=P;x<=U;x++){S=g[y][x];if(S.real){Q=S.colspan-1;R=S.rowspan-1;if(Q){if(x+Q>N){N=x+Q}}if(R){if(y+R>M){M=y+R}}}}}G.removeClass(G.select("td.mceSelected,th.mceSelected"),"mceSelected");for(y=O;y<=M;y++){for(x=P;x<=N;x++){if(g[y][x]){G.addClass(g[y][x].elm,"mceSelected")}}}}}d.extend(this,{deleteTable:r,split:C,merge:p,insertRow:l,insertCol:h,deleteCols:n,deleteRows:m,cutRows:E,copyRows:J,pasteRows:B,getPos:F,setStartCell:w,setEndCell:v})}d.create("tinymce.plugins.TablePlugin",{init:function(g,h){var f,m,j=true;function l(p){var o=g.selection,n=g.dom.getParent(p||o.getNode(),"table");if(n){return new b(n,g.dom,o)}}function k(){g.getBody().style.webkitUserSelect="";if(j){g.dom.removeClass(g.dom.select("td.mceSelected,th.mceSelected"),"mceSelected");j=false}}e([["table","table.desc","mceInsertTable",true],["delete_table","table.del","mceTableDelete"],["delete_col","table.delete_col_desc","mceTableDeleteCol"],["delete_row","table.delete_row_desc","mceTableDeleteRow"],["col_after","table.col_after_desc","mceTableInsertColAfter"],["col_before","table.col_before_desc","mceTableInsertColBefore"],["row_after","table.row_after_desc","mceTableInsertRowAfter"],["row_before","table.row_before_desc","mceTableInsertRowBefore"],["row_props","table.row_desc","mceTableRowProps",true],["cell_props","table.cell_desc","mceTableCellProps",true],["split_cells","table.split_cells_desc","mceTableSplitCells",true],["merge_cells","table.merge_cells_desc","mceTableMergeCells",true]],function(n){g.addButton(n[0],{title:n[1],cmd:n[2],ui:n[3]})});if(!d.isIE){g.onClick.add(function(n,o){o=o.target;if(o.nodeName==="TABLE"){n.selection.select(o);n.nodeChanged()}})}g.onPreProcess.add(function(o,p){var n,q,r,t=o.dom,s;n=t.select("table",p.node);q=n.length;while(q--){r=n[q];t.setAttrib(r,"data-mce-style","");if((s=t.getAttrib(r,"width"))){t.setStyle(r,"width",s);t.setAttrib(r,"width","")}if((s=t.getAttrib(r,"height"))){t.setStyle(r,"height",s);t.setAttrib(r,"height","")}}});g.onNodeChange.add(function(q,o,s){var r;s=q.selection.getStart();r=q.dom.getParent(s,"td,th,caption");o.setActive("table",s.nodeName==="TABLE"||!!r);if(r&&r.nodeName==="CAPTION"){r=0}o.setDisabled("delete_table",!r);o.setDisabled("delete_col",!r);o.setDisabled("delete_table",!r);o.setDisabled("delete_row",!r);o.setDisabled("col_after",!r);o.setDisabled("col_before",!r);o.setDisabled("row_after",!r);o.setDisabled("row_before",!r);o.setDisabled("row_props",!r);o.setDisabled("cell_props",!r);o.setDisabled("split_cells",!r);o.setDisabled("merge_cells",!r)});g.onInit.add(function(r){var p,t,q=r.dom,u;f=r.windowManager;r.onMouseDown.add(function(w,z){if(z.button!=2){k();t=q.getParent(z.target,"td,th");p=q.getParent(t,"table")}});q.bind(r.getDoc(),"mouseover",function(C){var A,z,B=C.target;if(t&&(u||B!=t)&&(B.nodeName=="TD"||B.nodeName=="TH")){z=q.getParent(B,"table");if(z==p){if(!u){u=l(z);u.setStartCell(t);r.getBody().style.webkitUserSelect="none"}u.setEndCell(B);j=true}A=r.selection.getSel();try{if(A.removeAllRanges){A.removeAllRanges()}else{A.empty()}}catch(w){}C.preventDefault()}});r.onMouseUp.add(function(F,G){var z,B=F.selection,H,I=B.getSel(),w,C,A,E;if(t){if(u){F.getBody().style.webkitUserSelect=""}function D(J,L){var K=new d.dom.TreeWalker(J,J);do{if(J.nodeType==3&&d.trim(J.nodeValue).length!=0){if(L){z.setStart(J,0)}else{z.setEnd(J,J.nodeValue.length)}return}if(J.nodeName=="BR"){if(L){z.setStartBefore(J)}else{z.setEndBefore(J)}return}}while(J=(L?K.next():K.prev()))}H=q.select("td.mceSelected,th.mceSelected");if(H.length>0){z=q.createRng();C=H[0];E=H[H.length-1];z.setStartBefore(C);z.setEndAfter(C);D(C,1);w=new d.dom.TreeWalker(C,q.getParent(H[0],"table"));do{if(C.nodeName=="TD"||C.nodeName=="TH"){if(!q.hasClass(C,"mceSelected")){break}A=C}}while(C=w.next());D(A);B.setRng(z)}F.nodeChanged();t=u=p=null}});r.onKeyUp.add(function(w,z){k()});r.onKeyDown.add(function(w,z){n(w)});r.onMouseDown.add(function(w,z){if(z.button!=2){n(w)}});function o(D,z,A,F){var B=3,G=D.dom.getParent(z.startContainer,"TABLE"),C,w,E;if(G){C=G.parentNode}w=z.startContainer.nodeType==B&&z.startOffset==0&&z.endOffset==0&&F&&(A.nodeName=="TR"||A==C);E=(A.nodeName=="TD"||A.nodeName=="TH")&&!F;return w||E}function n(A){if(!d.isWebKit){return}var z=A.selection.getRng();var C=A.selection.getNode();var B=A.dom.getParent(z.startContainer,"TD");if(!o(A,z,C,B)){return}if(!B){B=C}var w=B.lastChild;while(w.lastChild){w=w.lastChild}z.setEnd(w,w.nodeValue.length);A.selection.setRng(z)}r.plugins.table.fixTableCellSelection=n;if(r&&r.plugins.contextmenu){r.plugins.contextmenu.onContextMenu.add(function(A,w,C){var D,B=r.selection,z=B.getNode()||r.getBody();if(r.dom.getParent(C,"td")||r.dom.getParent(C,"th")||r.dom.select("td.mceSelected,th.mceSelected").length){w.removeAll();if(z.nodeName=="A"&&!r.dom.getAttrib(z,"name")){w.add({title:"advanced.link_desc",icon:"link",cmd:r.plugins.advlink?"mceAdvLink":"mceLink",ui:true});w.add({title:"advanced.unlink_desc",icon:"unlink",cmd:"UnLink"});w.addSeparator()}if(z.nodeName=="IMG"&&z.className.indexOf("mceItem")==-1){w.add({title:"advanced.image_desc",icon:"image",cmd:r.plugins.advimage?"mceAdvImage":"mceImage",ui:true});w.addSeparator()}w.add({title:"table.desc",icon:"table",cmd:"mceInsertTable",value:{action:"insert"}});w.add({title:"table.props_desc",icon:"table_props",cmd:"mceInsertTable"});w.add({title:"table.del",icon:"delete_table",cmd:"mceTableDelete"});w.addSeparator();D=w.addMenu({title:"table.cell"});D.add({title:"table.cell_desc",icon:"cell_props",cmd:"mceTableCellProps"});D.add({title:"table.split_cells_desc",icon:"split_cells",cmd:"mceTableSplitCells"});D.add({title:"table.merge_cells_desc",icon:"merge_cells",cmd:"mceTableMergeCells"});D=w.addMenu({title:"table.row"});D.add({title:"table.row_desc",icon:"row_props",cmd:"mceTableRowProps"});D.add({title:"table.row_before_desc",icon:"row_before",cmd:"mceTableInsertRowBefore"});D.add({title:"table.row_after_desc",icon:"row_after",cmd:"mceTableInsertRowAfter"});D.add({title:"table.delete_row_desc",icon:"delete_row",cmd:"mceTableDeleteRow"});D.addSeparator();D.add({title:"table.cut_row_desc",icon:"cut",cmd:"mceTableCutRow"});D.add({title:"table.copy_row_desc",icon:"copy",cmd:"mceTableCopyRow"});D.add({title:"table.paste_row_before_desc",icon:"paste",cmd:"mceTablePasteRowBefore"}).setDisabled(!m);D.add({title:"table.paste_row_after_desc",icon:"paste",cmd:"mceTablePasteRowAfter"}).setDisabled(!m);D=w.addMenu({title:"table.col"});D.add({title:"table.col_before_desc",icon:"col_before",cmd:"mceTableInsertColBefore"});D.add({title:"table.col_after_desc",icon:"col_after",cmd:"mceTableInsertColAfter"});D.add({title:"table.delete_col_desc",icon:"delete_col",cmd:"mceTableDeleteCol"})}else{w.add({title:"table.desc",icon:"table",cmd:"mceInsertTable"})}})}if(d.isWebKit){function v(B,M){function F(Q){B.selection.setCursorLocation(Q,0)}function H(R,Q){return R.keyCode==z?Q.previousSibling:Q.nextSibling}function G(R,S){var Q=H(R,S);return Q!==null&&Q.tagName==="TR"?Q:null}function C(Q,R){return Q.dom.getParent(R,"table")}function O(Q){var R=C(B,Q);return H(M,R)}function A(Q){return Q.keyCode==z||Q.keyCode==I}function D(Q){var S=Q.selection.getNode();var R=Q.dom.getParent(S,"tr");return R!==null}function N(R){var Q=0;var S=R;while(S.previousSibling){S=S.previousSibling;Q=Q+a(S,"colspan")}return Q}function E(S,Q){var T=0;var R=0;e(S.children,function(U,V){T=T+a(U,"colspan");R=V;if(T>Q){return false}});return R}function w(S,T,V){var U=N(S.dom.getParent(T,"td,th"));var R=E(V,U);var Q=V.childNodes[R];F(Q)}function L(R,T){var Q=O(R);if(Q!==null){F(Q);return d.dom.Event.cancel(T)}else{var S=T.keyCode==z?R.firstChild:R.lastChild;F(S);return true}}var z=38;var I=40;if(A(M)&&D(B)){var J=B.selection.getNode();var P=B.dom.getParent(J,"tr");var K=G(M,P);if(K==null){return L(P,M)}else{w(B,J,K);d.dom.Event.cancel(M);return true}}}r.onKeyDown.add(v)}if(!d.isIE){function s(){var w;for(w=r.getBody().lastChild;w&&w.nodeType==3&&!w.nodeValue.length;w=w.previousSibling){}if(w&&w.nodeName=="TABLE"){r.dom.add(r.getBody(),"p",null,'<br mce_bogus="1" />')}}if(d.isGecko){r.onKeyDown.add(function(z,B){var w,A,C=z.dom;if(B.keyCode==37||B.keyCode==38){w=z.selection.getRng();A=C.getParent(w.startContainer,"table");if(A&&z.getBody().firstChild==A){if(c(w,A)){w=C.createRng();w.setStartBefore(A);w.setEndBefore(A);z.selection.setRng(w);B.preventDefault()}}}})}r.onKeyUp.add(s);r.onSetContent.add(s);r.onVisualAid.add(s);r.onPreProcess.add(function(w,A){var z=A.node.lastChild;if(z&&z.childNodes.length==1&&z.firstChild.nodeName=="BR"){w.dom.remove(z)}});s();r.startContent=r.getContent({format:"raw"})}});e({mceTableSplitCells:function(n){n.split()},mceTableMergeCells:function(o){var p,q,n;n=g.dom.getParent(g.selection.getNode(),"th,td");if(n){p=n.rowSpan;q=n.colSpan}if(!g.dom.select("td.mceSelected,th.mceSelected").length){f.open({url:h+"/merge_cells.htm",width:240+parseInt(g.getLang("table.merge_cells_delta_width",0)),height:110+parseInt(g.getLang("table.merge_cells_delta_height",0)),inline:1},{rows:p,cols:q,onaction:function(r){o.merge(n,r.cols,r.rows)},plugin_url:h})}else{o.merge()}},mceTableInsertRowBefore:function(n){n.insertRow(true)},mceTableInsertRowAfter:function(n){n.insertRow()},mceTableInsertColBefore:function(n){n.insertCol(true)},mceTableInsertColAfter:function(n){n.insertCol()},mceTableDeleteCol:function(n){n.deleteCols()},mceTableDeleteRow:function(n){n.deleteRows()},mceTableCutRow:function(n){m=n.cutRows()},mceTableCopyRow:function(n){m=n.copyRows()},mceTablePasteRowBefore:function(n){n.pasteRows(m,true)},mceTablePasteRowAfter:function(n){n.pasteRows(m)},mceTableDelete:function(n){n.deleteTable()}},function(o,n){g.addCommand(n,function(){var p=l();if(p){o(p);g.execCommand("mceRepaint");k()}})});e({mceInsertTable:function(n){f.open({url:h+"/table.htm",width:400+parseInt(g.getLang("table.table_delta_width",0)),height:320+parseInt(g.getLang("table.table_delta_height",0)),inline:1},{plugin_url:h,action:n?n.action:0})},mceTableRowProps:function(){f.open({url:h+"/row.htm",width:400+parseInt(g.getLang("table.rowprops_delta_width",0)),height:295+parseInt(g.getLang("table.rowprops_delta_height",0)),inline:1},{plugin_url:h})},mceTableCellProps:function(){f.open({url:h+"/cell.htm",width:400+parseInt(g.getLang("table.cellprops_delta_width",0)),height:295+parseInt(g.getLang("table.cellprops_delta_height",0)),inline:1},{plugin_url:h})}},function(o,n){g.addCommand(n,function(p,q){o(q)})})}});d.PluginManager.add("table",d.plugins.TablePlugin)})(tinymce);
1
+ (function(d){var e=d.each;function c(g,h){var j=h.ownerDocument,f=j.createRange(),k;f.setStartBefore(h);f.setEnd(g.endContainer,g.endOffset);k=j.createElement("body");k.appendChild(f.cloneContents());return k.innerHTML.replace(/<(br|img|object|embed|input|textarea)[^>]*>/gi,"-").replace(/<[^>]+>/g,"").length==0}function a(g,f){return parseInt(g.getAttribute(f)||1)}function b(H,G,K){var g,L,D,o;t();o=G.getParent(K.getStart(),"th,td");if(o){L=F(o);D=I();o=z(L.x,L.y)}function A(N,M){N=N.cloneNode(M);N.removeAttribute("id");return N}function t(){var M=0;g=[];e(["thead","tbody","tfoot"],function(N){var O=G.select("> "+N+" tr",H);e(O,function(P,Q){Q+=M;e(G.select("> td, > th",P),function(W,R){var S,T,U,V;if(g[Q]){while(g[Q][R]){R++}}U=a(W,"rowspan");V=a(W,"colspan");for(T=Q;T<Q+U;T++){if(!g[T]){g[T]=[]}for(S=R;S<R+V;S++){g[T][S]={part:N,real:T==Q&&S==R,elm:W,rowspan:U,colspan:V}}}})});M+=O.length})}function z(M,O){var N;N=g[O];if(N){return N[M]}}function s(O,M,N){if(O){N=parseInt(N);if(N===1){O.removeAttribute(M,1)}else{O.setAttribute(M,N,1)}}}function j(M){return M&&(G.hasClass(M.elm,"mceSelected")||M==o)}function k(){var M=[];e(H.rows,function(N){e(N.cells,function(O){if(G.hasClass(O,"mceSelected")||O==o.elm){M.push(N);return false}})});return M}function r(){var M=G.createRng();M.setStartAfter(H);M.setEndAfter(H);K.setRng(M);G.remove(H)}function f(M){var N;d.walk(M,function(P){var O;if(P.nodeType==3){e(G.getParents(P.parentNode,null,M).reverse(),function(Q){Q=A(Q,false);if(!N){N=O=Q}else{if(O){O.appendChild(Q)}}O=Q});if(O){O.innerHTML=d.isIE?"&nbsp;":'<br data-mce-bogus="1" />'}return false}},"childNodes");M=A(M,false);s(M,"rowSpan",1);s(M,"colSpan",1);if(N){M.appendChild(N)}else{if(!d.isIE){M.innerHTML='<br data-mce-bogus="1" />'}}return M}function q(){var M=G.createRng();e(G.select("tr",H),function(N){if(N.cells.length==0){G.remove(N)}});if(G.select("tr",H).length==0){M.setStartAfter(H);M.setEndAfter(H);K.setRng(M);G.remove(H);return}e(G.select("thead,tbody,tfoot",H),function(N){if(N.rows.length==0){G.remove(N)}});t();row=g[Math.min(g.length-1,L.y)];if(row){K.select(row[Math.min(row.length-1,L.x)].elm,true);K.collapse(true)}}function u(S,Q,U,R){var P,N,M,O,T;P=g[Q][S].elm.parentNode;for(M=1;M<=U;M++){P=G.getNext(P,"tr");if(P){for(N=S;N>=0;N--){T=g[Q+M][N].elm;if(T.parentNode==P){for(O=1;O<=R;O++){G.insertAfter(f(T),T)}break}}if(N==-1){for(O=1;O<=R;O++){P.insertBefore(f(P.cells[0]),P.cells[0])}}}}}function C(){e(g,function(M,N){e(M,function(P,O){var S,R,T,Q;if(j(P)){P=P.elm;S=a(P,"colspan");R=a(P,"rowspan");if(S>1||R>1){s(P,"rowSpan",1);s(P,"colSpan",1);for(Q=0;Q<S-1;Q++){G.insertAfter(f(P),P)}u(O,N,R-1,S)}}})})}function p(V,S,Y){var P,O,X,W,U,R,T,M,V,N,Q;if(V){pos=F(V);P=pos.x;O=pos.y;X=P+(S-1);W=O+(Y-1)}else{L=D=null;e(g,function(Z,aa){e(Z,function(ac,ab){if(j(ac)){if(!L){L={x:ab,y:aa}}D={x:ab,y:aa}}})});P=L.x;O=L.y;X=D.x;W=D.y}T=z(P,O);M=z(X,W);if(T&&M&&T.part==M.part){C();t();T=z(P,O).elm;s(T,"colSpan",(X-P)+1);s(T,"rowSpan",(W-O)+1);for(R=O;R<=W;R++){for(U=P;U<=X;U++){if(!g[R]||!g[R][U]){continue}V=g[R][U].elm;if(V!=T){N=d.grep(V.childNodes);e(N,function(Z){T.appendChild(Z)});if(N.length){N=d.grep(T.childNodes);Q=0;e(N,function(Z){if(Z.nodeName=="BR"&&G.getAttrib(Z,"data-mce-bogus")&&Q++<N.length-1){T.removeChild(Z)}})}G.remove(V)}}}q()}}function l(Q){var M,S,P,R,T,U,N,V,O;e(g,function(W,X){e(W,function(Z,Y){if(j(Z)){Z=Z.elm;T=Z.parentNode;U=A(T,false);M=X;if(Q){return false}}});if(Q){return !M}});for(R=0;R<g[0].length;R++){if(!g[M][R]){continue}S=g[M][R].elm;if(S!=P){if(!Q){O=a(S,"rowspan");if(O>1){s(S,"rowSpan",O+1);continue}}else{if(M>0&&g[M-1][R]){V=g[M-1][R].elm;O=a(V,"rowSpan");if(O>1){s(V,"rowSpan",O+1);continue}}}N=f(S);s(N,"colSpan",S.colSpan);U.appendChild(N);P=S}}if(U.hasChildNodes()){if(!Q){G.insertAfter(U,T)}else{T.parentNode.insertBefore(U,T)}}}function h(N){var O,M;e(g,function(P,Q){e(P,function(S,R){if(j(S)){O=R;if(N){return false}}});if(N){return !O}});e(g,function(S,T){var P,Q,R;if(!S[O]){return}P=S[O].elm;if(P!=M){R=a(P,"colspan");Q=a(P,"rowspan");if(R==1){if(!N){G.insertAfter(f(P),P);u(O,T,Q-1,R)}else{P.parentNode.insertBefore(f(P),P);u(O,T,Q-1,R)}}else{s(P,"colSpan",P.colSpan+1)}M=P}})}function n(){var M=[];e(g,function(N,O){e(N,function(Q,P){if(j(Q)&&d.inArray(M,P)===-1){e(g,function(T){var R=T[P].elm,S;S=a(R,"colSpan");if(S>1){s(R,"colSpan",S-1)}else{G.remove(R)}});M.push(P)}})});q()}function m(){var N;function M(Q){var P,R,O;P=G.getNext(Q,"tr");e(Q.cells,function(S){var T=a(S,"rowSpan");if(T>1){s(S,"rowSpan",T-1);R=F(S);u(R.x,R.y,1,1)}});R=F(Q.cells[0]);e(g[R.y],function(S){var T;S=S.elm;if(S!=O){T=a(S,"rowSpan");if(T<=1){G.remove(S)}else{s(S,"rowSpan",T-1)}O=S}})}N=k();e(N.reverse(),function(O){M(O)});q()}function E(){var M=k();G.remove(M);q();return M}function J(){var M=k();e(M,function(O,N){M[N]=A(O,true)});return M}function B(O,N){var P=k(),M=P[N?0:P.length-1],Q=M.cells.length;e(g,function(S){var R;Q=0;e(S,function(U,T){if(U.real){Q+=U.colspan}if(U.elm.parentNode==M){R=1}});if(R){return false}});if(!N){O.reverse()}e(O,function(T){var S=T.cells.length,R;for(i=0;i<S;i++){R=T.cells[i];s(R,"colSpan",1);s(R,"rowSpan",1)}for(i=S;i<Q;i++){T.appendChild(f(T.cells[S-1]))}for(i=Q;i<S;i++){G.remove(T.cells[i])}if(N){M.parentNode.insertBefore(T,M)}else{G.insertAfter(T,M)}});G.removeClass(G.select("td.mceSelected,th.mceSelected"),"mceSelected")}function F(M){var N;e(g,function(O,P){e(O,function(R,Q){if(R.elm==M){N={x:Q,y:P};return false}});return !N});return N}function w(M){L=F(M)}function I(){var O,N,M;N=M=0;e(g,function(P,Q){e(P,function(S,R){var U,T;if(j(S)){S=g[Q][R];if(R>N){N=R}if(Q>M){M=Q}if(S.real){U=S.colspan-1;T=S.rowspan-1;if(U){if(R+U>N){N=R+U}}if(T){if(Q+T>M){M=Q+T}}}}})});return{x:N,y:M}}function v(S){var P,O,U,T,N,M,Q,R;D=F(S);if(L&&D){P=Math.min(L.x,D.x);O=Math.min(L.y,D.y);U=Math.max(L.x,D.x);T=Math.max(L.y,D.y);N=U;M=T;for(y=O;y<=M;y++){S=g[y][P];if(!S.real){if(P-(S.colspan-1)<P){P-=S.colspan-1}}}for(x=P;x<=N;x++){S=g[O][x];if(!S.real){if(O-(S.rowspan-1)<O){O-=S.rowspan-1}}}for(y=O;y<=T;y++){for(x=P;x<=U;x++){S=g[y][x];if(S.real){Q=S.colspan-1;R=S.rowspan-1;if(Q){if(x+Q>N){N=x+Q}}if(R){if(y+R>M){M=y+R}}}}}G.removeClass(G.select("td.mceSelected,th.mceSelected"),"mceSelected");for(y=O;y<=M;y++){for(x=P;x<=N;x++){if(g[y][x]){G.addClass(g[y][x].elm,"mceSelected")}}}}}d.extend(this,{deleteTable:r,split:C,merge:p,insertRow:l,insertCol:h,deleteCols:n,deleteRows:m,cutRows:E,copyRows:J,pasteRows:B,getPos:F,setStartCell:w,setEndCell:v})}d.create("tinymce.plugins.TablePlugin",{init:function(g,h){var f,m,j=true;function l(p){var o=g.selection,n=g.dom.getParent(p||o.getNode(),"table");if(n){return new b(n,g.dom,o)}}function k(){g.getBody().style.webkitUserSelect="";if(j){g.dom.removeClass(g.dom.select("td.mceSelected,th.mceSelected"),"mceSelected");j=false}}e([["table","table.desc","mceInsertTable",true],["delete_table","table.del","mceTableDelete"],["delete_col","table.delete_col_desc","mceTableDeleteCol"],["delete_row","table.delete_row_desc","mceTableDeleteRow"],["col_after","table.col_after_desc","mceTableInsertColAfter"],["col_before","table.col_before_desc","mceTableInsertColBefore"],["row_after","table.row_after_desc","mceTableInsertRowAfter"],["row_before","table.row_before_desc","mceTableInsertRowBefore"],["row_props","table.row_desc","mceTableRowProps",true],["cell_props","table.cell_desc","mceTableCellProps",true],["split_cells","table.split_cells_desc","mceTableSplitCells",true],["merge_cells","table.merge_cells_desc","mceTableMergeCells",true]],function(n){g.addButton(n[0],{title:n[1],cmd:n[2],ui:n[3]})});if(!d.isIE){g.onClick.add(function(n,o){o=o.target;if(o.nodeName==="TABLE"){n.selection.select(o);n.nodeChanged()}})}g.onPreProcess.add(function(o,p){var n,q,r,t=o.dom,s;n=t.select("table",p.node);q=n.length;while(q--){r=n[q];t.setAttrib(r,"data-mce-style","");if((s=t.getAttrib(r,"width"))){t.setStyle(r,"width",s);t.setAttrib(r,"width","")}if((s=t.getAttrib(r,"height"))){t.setStyle(r,"height",s);t.setAttrib(r,"height","")}}});g.onNodeChange.add(function(q,o,s){var r;s=q.selection.getStart();r=q.dom.getParent(s,"td,th,caption");o.setActive("table",s.nodeName==="TABLE"||!!r);if(r&&r.nodeName==="CAPTION"){r=0}o.setDisabled("delete_table",!r);o.setDisabled("delete_col",!r);o.setDisabled("delete_table",!r);o.setDisabled("delete_row",!r);o.setDisabled("col_after",!r);o.setDisabled("col_before",!r);o.setDisabled("row_after",!r);o.setDisabled("row_before",!r);o.setDisabled("row_props",!r);o.setDisabled("cell_props",!r);o.setDisabled("split_cells",!r);o.setDisabled("merge_cells",!r)});g.onInit.add(function(r){var p,t,q=r.dom,u;f=r.windowManager;r.onMouseDown.add(function(w,z){if(z.button!=2){k();t=q.getParent(z.target,"td,th");p=q.getParent(t,"table")}});q.bind(r.getDoc(),"mouseover",function(C){var A,z,B=C.target;if(t&&(u||B!=t)&&(B.nodeName=="TD"||B.nodeName=="TH")){z=q.getParent(B,"table");if(z==p){if(!u){u=l(z);u.setStartCell(t);r.getBody().style.webkitUserSelect="none"}u.setEndCell(B);j=true}A=r.selection.getSel();try{if(A.removeAllRanges){A.removeAllRanges()}else{A.empty()}}catch(w){}C.preventDefault()}});r.onMouseUp.add(function(F,G){var z,B=F.selection,H,I=B.getSel(),w,C,A,E;if(t){if(u){F.getBody().style.webkitUserSelect=""}function D(J,L){var K=new d.dom.TreeWalker(J,J);do{if(J.nodeType==3&&d.trim(J.nodeValue).length!=0){if(L){z.setStart(J,0)}else{z.setEnd(J,J.nodeValue.length)}return}if(J.nodeName=="BR"){if(L){z.setStartBefore(J)}else{z.setEndBefore(J)}return}}while(J=(L?K.next():K.prev()))}H=q.select("td.mceSelected,th.mceSelected");if(H.length>0){z=q.createRng();C=H[0];E=H[H.length-1];z.setStartBefore(C);z.setEndAfter(C);D(C,1);w=new d.dom.TreeWalker(C,q.getParent(H[0],"table"));do{if(C.nodeName=="TD"||C.nodeName=="TH"){if(!q.hasClass(C,"mceSelected")){break}A=C}}while(C=w.next());D(A);B.setRng(z)}F.nodeChanged();t=u=p=null}});r.onKeyUp.add(function(w,z){k()});r.onKeyDown.add(function(w,z){n(w)});r.onMouseDown.add(function(w,z){if(z.button!=2){n(w)}});function o(D,z,A,F){var B=3,G=D.dom.getParent(z.startContainer,"TABLE"),C,w,E;if(G){C=G.parentNode}w=z.startContainer.nodeType==B&&z.startOffset==0&&z.endOffset==0&&F&&(A.nodeName=="TR"||A==C);E=(A.nodeName=="TD"||A.nodeName=="TH")&&!F;return w||E}function n(A){if(!d.isWebKit){return}var z=A.selection.getRng();var C=A.selection.getNode();var B=A.dom.getParent(z.startContainer,"TD,TH");if(!o(A,z,C,B)){return}if(!B){B=C}var w=B.lastChild;while(w.lastChild){w=w.lastChild}z.setEnd(w,w.nodeValue.length);A.selection.setRng(z)}r.plugins.table.fixTableCellSelection=n;if(r&&r.plugins.contextmenu){r.plugins.contextmenu.onContextMenu.add(function(A,w,C){var D,B=r.selection,z=B.getNode()||r.getBody();if(r.dom.getParent(C,"td")||r.dom.getParent(C,"th")||r.dom.select("td.mceSelected,th.mceSelected").length){w.removeAll();if(z.nodeName=="A"&&!r.dom.getAttrib(z,"name")){w.add({title:"advanced.link_desc",icon:"link",cmd:r.plugins.advlink?"mceAdvLink":"mceLink",ui:true});w.add({title:"advanced.unlink_desc",icon:"unlink",cmd:"UnLink"});w.addSeparator()}if(z.nodeName=="IMG"&&z.className.indexOf("mceItem")==-1){w.add({title:"advanced.image_desc",icon:"image",cmd:r.plugins.advimage?"mceAdvImage":"mceImage",ui:true});w.addSeparator()}w.add({title:"table.desc",icon:"table",cmd:"mceInsertTable",value:{action:"insert"}});w.add({title:"table.props_desc",icon:"table_props",cmd:"mceInsertTable"});w.add({title:"table.del",icon:"delete_table",cmd:"mceTableDelete"});w.addSeparator();D=w.addMenu({title:"table.cell"});D.add({title:"table.cell_desc",icon:"cell_props",cmd:"mceTableCellProps"});D.add({title:"table.split_cells_desc",icon:"split_cells",cmd:"mceTableSplitCells"});D.add({title:"table.merge_cells_desc",icon:"merge_cells",cmd:"mceTableMergeCells"});D=w.addMenu({title:"table.row"});D.add({title:"table.row_desc",icon:"row_props",cmd:"mceTableRowProps"});D.add({title:"table.row_before_desc",icon:"row_before",cmd:"mceTableInsertRowBefore"});D.add({title:"table.row_after_desc",icon:"row_after",cmd:"mceTableInsertRowAfter"});D.add({title:"table.delete_row_desc",icon:"delete_row",cmd:"mceTableDeleteRow"});D.addSeparator();D.add({title:"table.cut_row_desc",icon:"cut",cmd:"mceTableCutRow"});D.add({title:"table.copy_row_desc",icon:"copy",cmd:"mceTableCopyRow"});D.add({title:"table.paste_row_before_desc",icon:"paste",cmd:"mceTablePasteRowBefore"}).setDisabled(!m);D.add({title:"table.paste_row_after_desc",icon:"paste",cmd:"mceTablePasteRowAfter"}).setDisabled(!m);D=w.addMenu({title:"table.col"});D.add({title:"table.col_before_desc",icon:"col_before",cmd:"mceTableInsertColBefore"});D.add({title:"table.col_after_desc",icon:"col_after",cmd:"mceTableInsertColAfter"});D.add({title:"table.delete_col_desc",icon:"delete_col",cmd:"mceTableDeleteCol"})}else{w.add({title:"table.desc",icon:"table",cmd:"mceInsertTable"})}})}if(d.isWebKit){function v(C,N){var L=d.VK;var Q=N.keyCode;function O(Y,U,S){var T=Y?"previousSibling":"nextSibling";var Z=C.dom.getParent(U,"tr");var X=Z[T];if(X){z(C,U,X,Y);d.dom.Event.cancel(S);return true}else{var aa=C.dom.getParent(Z,"table");var W=Z.parentNode;var R=W.nodeName.toLowerCase();if(R==="tbody"||R===(Y?"tfoot":"thead")){var V=w(Y,aa,W,"tbody");if(V!==null){return K(Y,V,U,S)}}return M(Y,Z,T,aa,S)}}function w(V,T,U,X){var S=C.dom.select(">"+X,T);var R=S.indexOf(U);if(V&&R===0||!V&&R===S.length-1){return B(V,T)}else{if(R===-1){var W=U.tagName.toLowerCase()==="thead"?0:S.length-1;return S[W]}else{return S[R+(V?-1:1)]}}}function B(U,T){var S=U?"thead":"tfoot";var R=C.dom.select(">"+S,T);return R.length!==0?R[0]:null}function K(V,T,S,U){var R=J(T,V);R&&z(C,S,R,V);d.dom.Event.cancel(U);return true}function M(Y,U,R,X,W){var S=X[R];if(S){F(S);return true}else{var V=C.dom.getParent(X,"td,th");if(V){return O(Y,V,W)}else{var T=J(U,!Y);F(T);return d.dom.Event.cancel(W)}}}function J(S,R){var T=S&&S[R?"lastChild":"firstChild"];return T&&T.nodeName==="BR"?C.dom.getParent(T,"td,th"):T}function F(R){C.selection.setCursorLocation(R,0)}function A(){return Q==L.UP||Q==L.DOWN}function D(R){var T=R.selection.getNode();var S=R.dom.getParent(T,"tr");return S!==null}function P(S){var R=0;var T=S;while(T.previousSibling){T=T.previousSibling;R=R+a(T,"colspan")}return R}function E(T,R){var U=0;var S=0;e(T.children,function(V,W){U=U+a(V,"colspan");S=W;if(U>R){return false}});return S}function z(T,W,Y,V){var X=P(T.dom.getParent(W,"td,th"));var S=E(Y,X);var R=Y.childNodes[S];var U=J(R,V);F(U||R)}function H(R){var T=C.selection.getNode();var U=C.dom.getParent(T,"td,th");var S=C.dom.getParent(R,"td,th");return U&&U!==S&&I(U,S)}function I(S,R){return C.dom.getParent(S,"TABLE")===C.dom.getParent(R,"TABLE")}if(A()&&D(C)){var G=C.selection.getNode();setTimeout(function(){if(H(G)){O(!N.shiftKey&&Q===L.UP,G,N)}},0)}}r.onKeyDown.add(v)}function s(){var w;for(w=r.getBody().lastChild;w&&w.nodeType==3&&!w.nodeValue.length;w=w.previousSibling){}if(w&&w.nodeName=="TABLE"){if(r.settings.forced_root_block){r.dom.add(r.getBody(),r.settings.forced_root_block,null,d.isIE?"&nbsp;":'<br data-mce-bogus="1" />')}else{r.dom.add(r.getBody(),"br",{"data-mce-bogus":"1"})}}}if(d.isGecko){r.onKeyDown.add(function(z,B){var w,A,C=z.dom;if(B.keyCode==37||B.keyCode==38){w=z.selection.getRng();A=C.getParent(w.startContainer,"table");if(A&&z.getBody().firstChild==A){if(c(w,A)){w=C.createRng();w.setStartBefore(A);w.setEndBefore(A);z.selection.setRng(w);B.preventDefault()}}}})}r.onKeyUp.add(s);r.onSetContent.add(s);r.onVisualAid.add(s);r.onPreProcess.add(function(w,A){var z=A.node.lastChild;if(z&&(z.nodeName=="BR"||(z.childNodes.length==1&&(z.firstChild.nodeName=="BR"||z.firstChild.nodeValue=="\u00a0")))&&z.previousSibling&&z.previousSibling.nodeName=="TABLE"){w.dom.remove(z)}});s();r.startContent=r.getContent({format:"raw"})});e({mceTableSplitCells:function(n){n.split()},mceTableMergeCells:function(o){var p,q,n;n=g.dom.getParent(g.selection.getNode(),"th,td");if(n){p=n.rowSpan;q=n.colSpan}if(!g.dom.select("td.mceSelected,th.mceSelected").length){f.open({url:h+"/merge_cells.htm",width:240+parseInt(g.getLang("table.merge_cells_delta_width",0)),height:110+parseInt(g.getLang("table.merge_cells_delta_height",0)),inline:1},{rows:p,cols:q,onaction:function(r){o.merge(n,r.cols,r.rows)},plugin_url:h})}else{o.merge()}},mceTableInsertRowBefore:function(n){n.insertRow(true)},mceTableInsertRowAfter:function(n){n.insertRow()},mceTableInsertColBefore:function(n){n.insertCol(true)},mceTableInsertColAfter:function(n){n.insertCol()},mceTableDeleteCol:function(n){n.deleteCols()},mceTableDeleteRow:function(n){n.deleteRows()},mceTableCutRow:function(n){m=n.cutRows()},mceTableCopyRow:function(n){m=n.copyRows()},mceTablePasteRowBefore:function(n){n.pasteRows(m,true)},mceTablePasteRowAfter:function(n){n.pasteRows(m)},mceTableDelete:function(n){n.deleteTable()}},function(o,n){g.addCommand(n,function(){var p=l();if(p){o(p);g.execCommand("mceRepaint");k()}})});e({mceInsertTable:function(n){f.open({url:h+"/table.htm",width:400+parseInt(g.getLang("table.table_delta_width",0)),height:320+parseInt(g.getLang("table.table_delta_height",0)),inline:1},{plugin_url:h,action:n?n.action:0})},mceTableRowProps:function(){f.open({url:h+"/row.htm",width:400+parseInt(g.getLang("table.rowprops_delta_width",0)),height:295+parseInt(g.getLang("table.rowprops_delta_height",0)),inline:1},{plugin_url:h})},mceTableCellProps:function(){f.open({url:h+"/cell.htm",width:400+parseInt(g.getLang("table.cellprops_delta_width",0)),height:295+parseInt(g.getLang("table.cellprops_delta_height",0)),inline:1},{plugin_url:h})}},function(o,n){g.addCommand(n,function(p,q){o(q)})})}});d.PluginManager.add("table",d.plugins.TablePlugin)})(tinymce);
table/editor_plugin_src.js CHANGED
@@ -287,6 +287,21 @@
287
  endX = startX + (cols - 1);
288
  endY = startY + (rows - 1);
289
  } else {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
290
  // Use selection
291
  startX = startPos.x;
292
  startY = startPos.y;
@@ -599,6 +614,9 @@
599
  else
600
  dom.insertAfter(row, targetRow);
601
  });
 
 
 
602
  };
603
 
604
  function getPos(target) {
@@ -988,7 +1006,7 @@
988
  rng.endOffset == 0 &&
989
  currentCell &&
990
  (n.nodeName=="TR" || n==tableParent);
991
- tableCellSelection = (n.nodeName=="TD"||n.nodeName=="TH")&& !currentCell;
992
  return allOfCellSelected || tableCellSelection;
993
  // return false;
994
  }
@@ -1000,7 +1018,7 @@
1000
 
1001
  var rng = ed.selection.getRng();
1002
  var n = ed.selection.getNode();
1003
- var currentCell = ed.dom.getParent(rng.startContainer, 'TD');
1004
 
1005
  if (!tableCellSelected(ed, rng, n, currentCell))
1006
  return;
@@ -1012,7 +1030,7 @@
1012
  var end = currentCell.lastChild;
1013
  while (end.lastChild)
1014
  end = end.lastChild;
1015
-
1016
  // Select the entire table cell. Nothing outside of the table cell should be selected.
1017
  rng.setEnd(end, end.nodeValue.length);
1018
  ed.selection.setRng(rng);
@@ -1074,31 +1092,87 @@
1074
  // Fix to allow navigating up and down in a table in WebKit browsers.
1075
  if (tinymce.isWebKit) {
1076
  function moveSelection(ed, e) {
 
 
1077
 
1078
- function moveCursorToStartOfElement(n) {
1079
- ed.selection.setCursorLocation(n, 0);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1080
  }
1081
 
1082
- function getSibling(event, element) {
1083
- return event.keyCode == UP_ARROW ? element.previousSibling : element.nextSibling;
 
 
 
1084
  }
1085
 
1086
- function getNextRow(e, row) {
1087
- var sibling = getSibling(e, row);
1088
- return sibling !== null && sibling.tagName === 'TR' ? sibling : null;
 
 
 
 
 
 
 
 
 
 
 
 
1089
  }
1090
 
1091
- function getTable(ed, currentRow) {
1092
- return ed.dom.getParent(currentRow, 'table');
 
 
1093
  }
1094
 
1095
- function getTableSibling(currentRow) {
1096
- var table = getTable(ed, currentRow);
1097
- return getSibling(e, table);
1098
  }
1099
 
1100
- function isVerticalMovement(event) {
1101
- return event.keyCode == UP_ARROW || event.keyCode == DOWN_ARROW;
1102
  }
1103
 
1104
  function isInTable(ed) {
@@ -1129,103 +1203,117 @@
1129
  return r;
1130
  }
1131
 
1132
- function moveCursorToRow(ed, node, row) {
1133
  var srcColumnIndex = columnIndex(ed.dom.getParent(node, 'td,th'));
1134
- var tgtColumnIndex = findColumn(row, srcColumnIndex)
1135
  var tgtNode = row.childNodes[tgtColumnIndex];
1136
- moveCursorToStartOfElement(tgtNode);
 
1137
  }
1138
 
1139
- function escapeTable(currentRow, e) {
1140
- var tableSiblingElement = getTableSibling(currentRow);
1141
- if (tableSiblingElement !== null) {
1142
- moveCursorToStartOfElement(tableSiblingElement);
1143
- return tinymce.dom.Event.cancel(e);
1144
- } else {
1145
- var element = e.keyCode == UP_ARROW ? currentRow.firstChild : currentRow.lastChild;
1146
- // rely on default behaviour to escape table after we are in the last cell of the last row
1147
- moveCursorToStartOfElement(element);
1148
- return true;
1149
- }
1150
  }
1151
 
1152
- var UP_ARROW = 38;
1153
- var DOWN_ARROW = 40;
1154
-
1155
- if (isVerticalMovement(e) && isInTable(ed)) {
1156
- var node = ed.selection.getNode();
1157
- var currentRow = ed.dom.getParent(node, 'tr');
1158
- var nextRow = getNextRow(e, currentRow);
1159
 
1160
- // If we're at the first or last row in the table, we should move the caret outside of the table
1161
- if (nextRow == null) {
1162
- return escapeTable(currentRow, e);
1163
- } else {
1164
- moveCursorToRow(ed, node, nextRow);
1165
- tinymce.dom.Event.cancel(e);
1166
- return true;
1167
- }
1168
  }
1169
  }
1170
 
1171
  ed.onKeyDown.add(moveSelection);
1172
  }
1173
-
1174
  // Fixes an issue on Gecko where it's impossible to place the caret behind a table
1175
  // This fix will force a paragraph element after the table but only when the forced_root_block setting is enabled
1176
- if (!tinymce.isIE) {
1177
- function fixTableCaretPos() {
1178
- var last;
1179
 
1180
- // Skip empty text nodes form the end
1181
- for (last = ed.getBody().lastChild; last && last.nodeType == 3 && !last.nodeValue.length; last = last.previousSibling) ;
1182
 
1183
- if (last && last.nodeName == 'TABLE')
1184
- ed.dom.add(ed.getBody(), 'p', null, '<br mce_bogus="1" />');
1185
- };
 
 
 
 
1186
 
1187
- // Fixes an bug where it's impossible to place the caret before a table in Gecko
1188
- // this fix solves it by detecting when the caret is at the beginning of such a table
1189
- // and then manually moves the caret infront of the table
1190
- if (tinymce.isGecko) {
1191
- ed.onKeyDown.add(function(ed, e) {
1192
- var rng, table, dom = ed.dom;
1193
 
1194
- // On gecko it's not possible to place the caret before a table
1195
- if (e.keyCode == 37 || e.keyCode == 38) {
1196
- rng = ed.selection.getRng();
1197
- table = dom.getParent(rng.startContainer, 'table');
1198
 
1199
- if (table && ed.getBody().firstChild == table) {
1200
- if (isAtStart(rng, table)) {
1201
- rng = dom.createRng();
1202
 
1203
- rng.setStartBefore(table);
1204
- rng.setEndBefore(table);
1205
 
1206
- ed.selection.setRng(rng);
1207
 
1208
- e.preventDefault();
1209
- }
1210
  }
1211
  }
1212
- });
1213
- }
 
1214
 
1215
- ed.onKeyUp.add(fixTableCaretPos);
1216
- ed.onSetContent.add(fixTableCaretPos);
1217
- ed.onVisualAid.add(fixTableCaretPos);
1218
 
1219
- ed.onPreProcess.add(function(ed, o) {
1220
- var last = o.node.lastChild;
1221
 
1222
- if (last && last.childNodes.length == 1 && last.firstChild.nodeName == 'BR')
1223
- ed.dom.remove(last);
1224
- });
 
1225
 
1226
- fixTableCaretPos();
1227
- ed.startContent = ed.getContent({format : 'raw'});
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1228
  }
 
 
 
 
1229
  });
1230
 
1231
  // Register action commands
287
  endX = startX + (cols - 1);
288
  endY = startY + (rows - 1);
289
  } else {
290
+ startPos = endPos = null;
291
+
292
+ // Calculate start/end pos by checking for selected cells in grid works better with context menu
293
+ each(grid, function(row, y) {
294
+ each(row, function(cell, x) {
295
+ if (isCellSelected(cell)) {
296
+ if (!startPos) {
297
+ startPos = {x: x, y: y};
298
+ }
299
+
300
+ endPos = {x: x, y: y};
301
+ }
302
+ });
303
+ });
304
+
305
  // Use selection
306
  startX = startPos.x;
307
  startY = startPos.y;
614
  else
615
  dom.insertAfter(row, targetRow);
616
  });
617
+
618
+ // Remove current selection
619
+ dom.removeClass(dom.select('td.mceSelected,th.mceSelected'), 'mceSelected');
620
  };
621
 
622
  function getPos(target) {
1006
  rng.endOffset == 0 &&
1007
  currentCell &&
1008
  (n.nodeName=="TR" || n==tableParent);
1009
+ tableCellSelection = (n.nodeName=="TD"||n.nodeName=="TH")&& !currentCell;
1010
  return allOfCellSelected || tableCellSelection;
1011
  // return false;
1012
  }
1018
 
1019
  var rng = ed.selection.getRng();
1020
  var n = ed.selection.getNode();
1021
+ var currentCell = ed.dom.getParent(rng.startContainer, 'TD,TH');
1022
 
1023
  if (!tableCellSelected(ed, rng, n, currentCell))
1024
  return;
1030
  var end = currentCell.lastChild;
1031
  while (end.lastChild)
1032
  end = end.lastChild;
1033
+
1034
  // Select the entire table cell. Nothing outside of the table cell should be selected.
1035
  rng.setEnd(end, end.nodeValue.length);
1036
  ed.selection.setRng(rng);
1092
  // Fix to allow navigating up and down in a table in WebKit browsers.
1093
  if (tinymce.isWebKit) {
1094
  function moveSelection(ed, e) {
1095
+ var VK = tinymce.VK;
1096
+ var key = e.keyCode;
1097
 
1098
+ function handle(upBool, sourceNode, event) {
1099
+ var siblingDirection = upBool ? 'previousSibling' : 'nextSibling';
1100
+ var currentRow = ed.dom.getParent(sourceNode, 'tr');
1101
+ var siblingRow = currentRow[siblingDirection];
1102
+
1103
+ if (siblingRow) {
1104
+ moveCursorToRow(ed, sourceNode, siblingRow, upBool);
1105
+ tinymce.dom.Event.cancel(event);
1106
+ return true;
1107
+ } else {
1108
+ var tableNode = ed.dom.getParent(currentRow, 'table');
1109
+ var middleNode = currentRow.parentNode;
1110
+ var parentNodeName = middleNode.nodeName.toLowerCase();
1111
+ if (parentNodeName === 'tbody' || parentNodeName === (upBool ? 'tfoot' : 'thead')) {
1112
+ var targetParent = getTargetParent(upBool, tableNode, middleNode, 'tbody');
1113
+ if (targetParent !== null) {
1114
+ return moveToRowInTarget(upBool, targetParent, sourceNode, event);
1115
+ }
1116
+ }
1117
+ return escapeTable(upBool, currentRow, siblingDirection, tableNode, event);
1118
+ }
1119
+ }
1120
+
1121
+ function getTargetParent(upBool, topNode, secondNode, nodeName) {
1122
+ var tbodies = ed.dom.select('>' + nodeName, topNode);
1123
+ var position = tbodies.indexOf(secondNode);
1124
+ if (upBool && position === 0 || !upBool && position === tbodies.length - 1) {
1125
+ return getFirstHeadOrFoot(upBool, topNode);
1126
+ } else if (position === -1) {
1127
+ var topOrBottom = secondNode.tagName.toLowerCase() === 'thead' ? 0 : tbodies.length - 1;
1128
+ return tbodies[topOrBottom];
1129
+ } else {
1130
+ return tbodies[position + (upBool ? -1 : 1)];
1131
+ }
1132
+ }
1133
+
1134
+ function getFirstHeadOrFoot(upBool, parent) {
1135
+ var tagName = upBool ? 'thead' : 'tfoot';
1136
+ var headOrFoot = ed.dom.select('>' + tagName, parent);
1137
+ return headOrFoot.length !== 0 ? headOrFoot[0] : null;
1138
  }
1139
 
1140
+ function moveToRowInTarget(upBool, targetParent, sourceNode, event) {
1141
+ var targetRow = getChildForDirection(targetParent, upBool);
1142
+ targetRow && moveCursorToRow(ed, sourceNode, targetRow, upBool);
1143
+ tinymce.dom.Event.cancel(event);
1144
+ return true;
1145
  }
1146
 
1147
+ function escapeTable(upBool, currentRow, siblingDirection, table, event) {
1148
+ var tableSibling = table[siblingDirection];
1149
+ if (tableSibling) {
1150
+ moveCursorToStartOfElement(tableSibling);
1151
+ return true;
1152
+ } else {
1153
+ var parentCell = ed.dom.getParent(table, 'td,th');
1154
+ if (parentCell) {
1155
+ return handle(upBool, parentCell, event);
1156
+ } else {
1157
+ var backUpSibling = getChildForDirection(currentRow, !upBool);
1158
+ moveCursorToStartOfElement(backUpSibling);
1159
+ return tinymce.dom.Event.cancel(event);
1160
+ }
1161
+ }
1162
  }
1163
 
1164
+ function getChildForDirection(parent, up) {
1165
+ var child = parent && parent[up ? 'lastChild' : 'firstChild'];
1166
+ // BR is not a valid table child to return in this case we return the table cell
1167
+ return child && child.nodeName === 'BR' ? ed.dom.getParent(child, 'td,th') : child;
1168
  }
1169
 
1170
+ function moveCursorToStartOfElement(n) {
1171
+ ed.selection.setCursorLocation(n, 0);
 
1172
  }
1173
 
1174
+ function isVerticalMovement() {
1175
+ return key == VK.UP || key == VK.DOWN;
1176
  }
1177
 
1178
  function isInTable(ed) {
1203
  return r;
1204
  }
1205
 
1206
+ function moveCursorToRow(ed, node, row, upBool) {
1207
  var srcColumnIndex = columnIndex(ed.dom.getParent(node, 'td,th'));
1208
+ var tgtColumnIndex = findColumn(row, srcColumnIndex);
1209
  var tgtNode = row.childNodes[tgtColumnIndex];
1210
+ var rowCellTarget = getChildForDirection(tgtNode, upBool);
1211
+ moveCursorToStartOfElement(rowCellTarget || tgtNode);
1212
  }
1213
 
1214
+ function shouldFixCaret(preBrowserNode) {
1215
+ var newNode = ed.selection.getNode();
1216
+ var newParent = ed.dom.getParent(newNode, 'td,th');
1217
+ var oldParent = ed.dom.getParent(preBrowserNode, 'td,th');
1218
+ return newParent && newParent !== oldParent && checkSameParentTable(newParent, oldParent)
 
 
 
 
 
 
1219
  }
1220
 
1221
+ function checkSameParentTable(nodeOne, NodeTwo) {
1222
+ return ed.dom.getParent(nodeOne, 'TABLE') === ed.dom.getParent(NodeTwo, 'TABLE');
1223
+ }
 
 
 
 
1224
 
1225
+ if (isVerticalMovement() && isInTable(ed)) {
1226
+ var preBrowserNode = ed.selection.getNode();
1227
+ setTimeout(function() {
1228
+ if (shouldFixCaret(preBrowserNode)) {
1229
+ handle(!e.shiftKey && key === VK.UP, preBrowserNode, e);
1230
+ }
1231
+ }, 0);
 
1232
  }
1233
  }
1234
 
1235
  ed.onKeyDown.add(moveSelection);
1236
  }
1237
+
1238
  // Fixes an issue on Gecko where it's impossible to place the caret behind a table
1239
  // This fix will force a paragraph element after the table but only when the forced_root_block setting is enabled
1240
+ function fixTableCaretPos() {
1241
+ var last;
 
1242
 
1243
+ // Skip empty text nodes form the end
1244
+ for (last = ed.getBody().lastChild; last && last.nodeType == 3 && !last.nodeValue.length; last = last.previousSibling) ;
1245
 
1246
+ if (last && last.nodeName == 'TABLE') {
1247
+ if (ed.settings.forced_root_block)
1248
+ ed.dom.add(ed.getBody(), ed.settings.forced_root_block, null, tinymce.isIE ? '&nbsp;' : '<br data-mce-bogus="1" />');
1249
+ else
1250
+ ed.dom.add(ed.getBody(), 'br', {'data-mce-bogus': '1'});
1251
+ }
1252
+ };
1253
 
1254
+ // Fixes an bug where it's impossible to place the caret before a table in Gecko
1255
+ // this fix solves it by detecting when the caret is at the beginning of such a table
1256
+ // and then manually moves the caret infront of the table
1257
+ if (tinymce.isGecko) {
1258
+ ed.onKeyDown.add(function(ed, e) {
1259
+ var rng, table, dom = ed.dom;
1260
 
1261
+ // On gecko it's not possible to place the caret before a table
1262
+ if (e.keyCode == 37 || e.keyCode == 38) {
1263
+ rng = ed.selection.getRng();
1264
+ table = dom.getParent(rng.startContainer, 'table');
1265
 
1266
+ if (table && ed.getBody().firstChild == table) {
1267
+ if (isAtStart(rng, table)) {
1268
+ rng = dom.createRng();
1269
 
1270
+ rng.setStartBefore(table);
1271
+ rng.setEndBefore(table);
1272
 
1273
+ ed.selection.setRng(rng);
1274
 
1275
+ e.preventDefault();
 
1276
  }
1277
  }
1278
+ }
1279
+ });
1280
+ }
1281
 
1282
+ ed.onKeyUp.add(fixTableCaretPos);
1283
+ ed.onSetContent.add(fixTableCaretPos);
1284
+ ed.onVisualAid.add(fixTableCaretPos);
1285
 
1286
+ ed.onPreProcess.add(function(ed, o) {
1287
+ var last = o.node.lastChild;
1288
 
1289
+ if (last && (last.nodeName == "BR" || (last.childNodes.length == 1 && (last.firstChild.nodeName == 'BR' || last.firstChild.nodeValue == '\u00a0'))) && last.previousSibling && last.previousSibling.nodeName == "TABLE") {
1290
+ ed.dom.remove(last);
1291
+ }
1292
+ });
1293
 
1294
+
1295
+ /**
1296
+ * Fixes bug in Gecko where shift-enter in table cell does not place caret on new line
1297
+ *
1298
+ * Removed: Since the new enter logic seems to fix this one.
1299
+ */
1300
+ /*
1301
+ if (tinymce.isGecko) {
1302
+ ed.onKeyDown.add(function(ed, e) {
1303
+ if (e.keyCode === tinymce.VK.ENTER && e.shiftKey) {
1304
+ var node = ed.selection.getRng().startContainer;
1305
+ var tableCell = dom.getParent(node, 'td,th');
1306
+ if (tableCell) {
1307
+ var zeroSizedNbsp = ed.getDoc().createTextNode("\uFEFF");
1308
+ dom.insertAfter(zeroSizedNbsp, node);
1309
+ }
1310
+ }
1311
+ });
1312
  }
1313
+ */
1314
+
1315
+ fixTableCaretPos();
1316
+ ed.startContent = ed.getContent({format : 'raw'});
1317
  });
1318
 
1319
  // Register action commands
table/js/cell.js CHANGED
@@ -137,7 +137,7 @@ function updateAction() {
137
  do {
138
  if (cell == tdElm)
139
  break;
140
- col += cell.getAttribute("colspan");
141
  } while ((cell = nextCell(cell)) != null);
142
 
143
  for (var i=0; i<rows.length; i++) {
@@ -152,7 +152,7 @@ function updateAction() {
152
  cell = updateCell(cell, true);
153
  break;
154
  }
155
- curr += cell.getAttribute("colspan");
156
  } while ((cell = nextCell(cell)) != null);
157
  }
158
 
137
  do {
138
  if (cell == tdElm)
139
  break;
140
+ col += cell.getAttribute("colspan")?cell.getAttribute("colspan"):1;
141
  } while ((cell = nextCell(cell)) != null);
142
 
143
  for (var i=0; i<rows.length; i++) {
152
  cell = updateCell(cell, true);
153
  break;
154
  }
155
+ curr += cell.getAttribute("colspan")?cell.getAttribute("colspan"):1;
156
  } while ((cell = nextCell(cell)) != null);
157
  }
158
 
table/js/table.js CHANGED
@@ -60,7 +60,19 @@ function insertTable() {
60
  if (action == "update") {
61
  dom.setAttrib(elm, 'cellPadding', cellpadding, true);
62
  dom.setAttrib(elm, 'cellSpacing', cellspacing, true);
63
- dom.setAttrib(elm, 'border', border);
 
 
 
 
 
 
 
 
 
 
 
 
64
  dom.setAttrib(elm, 'align', align);
65
  dom.setAttrib(elm, 'frame', frame);
66
  dom.setAttrib(elm, 'rules', rules);
@@ -119,7 +131,7 @@ function insertTable() {
119
  if (bordercolor != "") {
120
  elm.style.borderColor = bordercolor;
121
  elm.style.borderStyle = elm.style.borderStyle == "" ? "solid" : elm.style.borderStyle;
122
- elm.style.borderWidth = border == "" ? "1px" : border;
123
  } else
124
  elm.style.borderColor = '';
125
 
@@ -132,7 +144,7 @@ function insertTable() {
132
  //elm.outerHTML = elm.outerHTML;
133
 
134
  inst.nodeChanged();
135
- inst.execCommand('mceEndUndoLevel');
136
 
137
  // Repaint if dimensions changed
138
  if (formObj.width.value != orgTableWidth || formObj.height.value != orgTableHeight)
@@ -146,7 +158,10 @@ function insertTable() {
146
  html += '<table';
147
 
148
  html += makeAttrib('id', id);
149
- html += makeAttrib('border', border);
 
 
 
150
  html += makeAttrib('cellpadding', cellpadding);
151
  html += makeAttrib('cellspacing', cellspacing);
152
  html += makeAttrib('data-mce-new', '1');
@@ -227,13 +242,20 @@ function insertTable() {
227
  } else
228
  inst.execCommand('mceInsertContent', false, html);
229
 
230
- tinymce.each(dom.select('table[data-mce-new]'), function(node) {
231
- var td = dom.select('td', node);
 
 
 
 
 
 
 
 
232
 
233
  try {
234
- // IE9 might fail to do this selection
235
- inst.selection.select(td[0], true);
236
- inst.selection.collapse();
237
  } catch (ex) {
238
  // Ignore
239
  }
@@ -242,7 +264,7 @@ function insertTable() {
242
  });
243
 
244
  inst.addVisual();
245
- inst.execCommand('mceEndUndoLevel');
246
 
247
  tinyMCEPopup.close();
248
  }
@@ -285,6 +307,15 @@ function init() {
285
  var formObj = document.forms[0];
286
  var elm = dom.getParent(inst.selection.getNode(), "table");
287
 
 
 
 
 
 
 
 
 
 
288
  action = tinyMCEPopup.getWindowArg('action');
289
 
290
  if (!action)
@@ -384,6 +415,20 @@ function changedSize() {
384
  formObj.style.value = dom.serializeStyle(st);
385
  }
386
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
387
  function changedBackgroundImage() {
388
  var formObj = document.forms[0];
389
  var st = dom.parseStyle(formObj.style.value);
@@ -398,8 +443,14 @@ function changedBorder() {
398
  var st = dom.parseStyle(formObj.style.value);
399
 
400
  // Update border width if the element has a color
401
- if (formObj.border.value != "" && formObj.bordercolor.value != "")
402
- st['border-width'] = formObj.border.value + "px";
 
 
 
 
 
 
403
 
404
  formObj.style.value = dom.serializeStyle(st);
405
  }
@@ -415,7 +466,7 @@ function changedColor() {
415
 
416
  // Add border-width if it's missing
417
  if (!st['border-width'])
418
- st['border-width'] = formObj.border.value == "" ? "1px" : formObj.border.value + "px";
419
  }
420
 
421
  formObj.style.value = dom.serializeStyle(st);
60
  if (action == "update") {
61
  dom.setAttrib(elm, 'cellPadding', cellpadding, true);
62
  dom.setAttrib(elm, 'cellSpacing', cellspacing, true);
63
+
64
+ if (!isCssSize(border)) {
65
+ dom.setAttrib(elm, 'border', border);
66
+ } else {
67
+ dom.setAttrib(elm, 'border', '');
68
+ }
69
+
70
+ if (border == '') {
71
+ dom.setStyle(elm, 'border-width', '');
72
+ dom.setStyle(elm, 'border', '');
73
+ dom.setAttrib(elm, 'border', '');
74
+ }
75
+
76
  dom.setAttrib(elm, 'align', align);
77
  dom.setAttrib(elm, 'frame', frame);
78
  dom.setAttrib(elm, 'rules', rules);
131
  if (bordercolor != "") {
132
  elm.style.borderColor = bordercolor;
133
  elm.style.borderStyle = elm.style.borderStyle == "" ? "solid" : elm.style.borderStyle;
134
+ elm.style.borderWidth = cssSize(border);
135
  } else
136
  elm.style.borderColor = '';
137
 
144
  //elm.outerHTML = elm.outerHTML;
145
 
146
  inst.nodeChanged();
147
+ inst.execCommand('mceEndUndoLevel', false, {}, {skip_undo: true});
148
 
149
  // Repaint if dimensions changed
150
  if (formObj.width.value != orgTableWidth || formObj.height.value != orgTableHeight)
158
  html += '<table';
159
 
160
  html += makeAttrib('id', id);
161
+ if (!isCssSize(border)) {
162
+ html += makeAttrib('border', border);
163
+ }
164
+
165
  html += makeAttrib('cellpadding', cellpadding);
166
  html += makeAttrib('cellspacing', cellspacing);
167
  html += makeAttrib('data-mce-new', '1');
242
  } else
243
  inst.execCommand('mceInsertContent', false, html);
244
 
245
+ tinymce.each(dom.select('table[data-mce-new]'), function(node) {
246
+ var tdorth = dom.select('td,th', node);
247
+
248
+ // Fixes a bug in IE where the caret cannot be placed after the table if the table is at the end of the document
249
+ if (tinymce.isIE && node.nextSibling == null) {
250
+ if (inst.settings.forced_root_block)
251
+ dom.insertAfter(dom.create(inst.settings.forced_root_block), node);
252
+ else
253
+ dom.insertAfter(dom.create('br', {'data-mce-bogus': '1'}), node);
254
+ }
255
 
256
  try {
257
+ // IE9 might fail to do this selection
258
+ inst.selection.setCursorLocation(tdorth[0], 0);
 
259
  } catch (ex) {
260
  // Ignore
261
  }
264
  });
265
 
266
  inst.addVisual();
267
+ inst.execCommand('mceEndUndoLevel', false, {}, {skip_undo: true});
268
 
269
  tinyMCEPopup.close();
270
  }
307
  var formObj = document.forms[0];
308
  var elm = dom.getParent(inst.selection.getNode(), "table");
309
 
310
+ // Hide advanced fields that isn't available in the schema
311
+ tinymce.each("summary id rules dir style frame".split(" "), function(name) {
312
+ var tr = tinyMCEPopup.dom.getParent(name, "tr") || tinyMCEPopup.dom.getParent("t" + name, "tr");
313
+
314
+ if (tr && !tinyMCEPopup.editor.schema.isValid("table", name)) {
315
+ tr.style.display = 'none';
316
+ }
317
+ });
318
+
319
  action = tinyMCEPopup.getWindowArg('action');
320
 
321
  if (!action)
415
  formObj.style.value = dom.serializeStyle(st);
416
  }
417
 
418
+ function isCssSize(value) {
419
+ return /^[0-9.]+(%|in|cm|mm|em|ex|pt|pc|px)$/.test(value);
420
+ }
421
+
422
+ function cssSize(value, def) {
423
+ value = tinymce.trim(value || def);
424
+
425
+ if (!isCssSize(value)) {
426
+ return parseInt(value, 10) + 'px';
427
+ }
428
+
429
+ return value;
430
+ }
431
+
432
  function changedBackgroundImage() {
433
  var formObj = document.forms[0];
434
  var st = dom.parseStyle(formObj.style.value);
443
  var st = dom.parseStyle(formObj.style.value);
444
 
445
  // Update border width if the element has a color
446
+ if (formObj.border.value != "" && (isCssSize(formObj.border.value) || formObj.bordercolor.value != ""))
447
+ st['border-width'] = cssSize(formObj.border.value);
448
+ else {
449
+ if (!formObj.border.value) {
450
+ st['border'] = '';
451
+ st['border-width'] = '';
452
+ }
453
+ }
454
 
455
  formObj.style.value = dom.serializeStyle(st);
456
  }
466
 
467
  // Add border-width if it's missing
468
  if (!st['border-width'])
469
+ st['border-width'] = cssSize(formObj.border.value, 1);
470
  }
471
 
472
  formObj.style.value = dom.serializeStyle(st);
table/table.htm CHANGED
@@ -46,7 +46,7 @@
46
  <option value="right">{#table_dlg.align_right}</option>
47
  </select></td>
48
  <td><label id="borderlabel" for="border">{#table_dlg.border}</label></td>
49
- <td><input id="border" name="border" type="text" value="" size="3" maxlength="3" onchange="changedBorder();" class="number" /></td>
50
  </tr>
51
  <tr id="width_row">
52
  <td><label id="widthlabel" for="width">{#table_dlg.width}</label></td>
46
  <option value="right">{#table_dlg.align_right}</option>
47
  </select></td>
48
  <td><label id="borderlabel" for="border">{#table_dlg.border}</label></td>
49
+ <td><input id="border" name="border" type="text" value="" size="3" maxlength="5" onchange="changedBorder();" class="size" /></td>
50
  </tr>
51
  <tr id="width_row">
52
  <td><label id="widthlabel" for="width">{#table_dlg.width}</label></td>