Tabbed editor from skeltoac. fixes #2829

git-svn-id: http://svn.automattic.com/wordpress/trunk@4206 1a063a9b-81f0-0310-95a4-ce76da25c4cd
This commit is contained in:
ryan 2006-09-22 07:04:41 +00:00
parent 07a02852ef
commit df430b5df3
8 changed files with 232 additions and 80 deletions

View File

@ -1250,47 +1250,6 @@ function save_mod_rewrite_rules() {
insert_with_markers($home_path.'.htaccess', 'WordPress', $rules);
}
function the_quicktags() {
echo '
<div id="quicktags">
';
wp_print_scripts( 'quicktags' );
echo ' <script type="text/javascript">
//<![CDATA[
if ( typeof tinyMCE == "undefined" || tinyMCE.configs.length < 1 ) edToolbar();
//]]>
</script>
</div>
';
echo '
<script type="text/javascript">
function edInsertContent(myField, myValue) {
//IE support
if (document.selection) {
myField.focus();
sel = document.selection.createRange();
sel.text = myValue;
myField.focus();
}
//MOZILLA/NETSCAPE support
else if (myField.selectionStart || myField.selectionStart == "0") {
var startPos = myField.selectionStart;
var endPos = myField.selectionEnd;
myField.value = myField.value.substring(0, startPos)
+ myValue
+ myField.value.substring(endPos, myField.value.length);
myField.focus();
myField.selectionStart = startPos + myValue.length;
myField.selectionEnd = startPos + myValue.length;
} else {
myField.value += myValue;
myField.focus();
}
}
</script>
';
}
function get_broken_themes() {
global $wp_broken_themes;

View File

@ -410,7 +410,6 @@ function updateOtherIcon(n) {
var win = window.opener ? window.opener : window.dialogArguments;
if (!win) win = top;
tinyMCE = win.tinyMCE;
richedit = ( typeof tinyMCE == 'object' && tinyMCE.configs.length > 0 );
function sendToEditor(n) {
o = document.getElementById('div'+n);
h = o.innerHTML.replace(new RegExp('^\\s*(.*?)\\s*$', ''), '$1'); // Trim
@ -420,7 +419,7 @@ function sendToEditor(n) {
h = h.replace(new RegExp('<(/?)A', 'g'), '<$1a'); // Lowercase tagnames
h = h.replace(new RegExp('<IMG', 'g'), '<img'); // Lowercase again
h = h.replace(new RegExp('(<img .+?")>', 'g'), '$1 />'); // XHTML
if ( richedit )
if ( typeof tinyMCE != 'undefined' && tinyMCE.getInstanceById('content') )
win.tinyMCE.execCommand('mceInsertContent', false, h);
else
win.edInsertContent(win.edCanvas, h);

View File

@ -1,4 +1,4 @@
* html #poststuff {
z* html #poststuff {
height: 100%; /* kill peekaboo bug in IE */
}
@ -490,10 +490,6 @@ table .vers {
width: 100%;
}
#quicktags {
margin-left: -1px;
}
#currenttheme img {
float: left;
border: 1px solid #666;
@ -512,6 +508,27 @@ table .vers {
color: #fff;
}
#postdivrich #quicktags {
background: #f0f0ee;
padding: 0px;
border: 1px solid #ccc;
border-bottom: none;
}
#postdiv #quicktags {
padding-right: 6px;
}
#postdivrich #quicktags {
display: none;
}
#quicktags #ed_toolbar {
padding: 0px 2px;
}
#ed_toolbar input {
background: #fff url( images/fade-butt.png ) repeat-x 0px -2px;
margin: 3px 2px 2px;
}
#quicktags #ed_strong {
font-weight: bold;
}
@ -531,6 +548,7 @@ table .vers {
#quicktags #ed_code {
font-family: "Courier New", Courier, mono;
margin-bottom: 3px;
}
#title {
@ -1118,3 +1136,20 @@ input#catadd { background: #a4a4a4;
#ajax-response.alignleft {
margin-left: 2em;
}
#postdivrich #edButtons {
padding-left: 3px;
}
#postdivrich #content, #postdivrich #content:active {
border: 1px solid #ccc;
}
#edButtons input, #edButtons input:active {
margin: 0px 2px -1px;
}
#edButtons input.edButtonFore, #edButtons input.edButtonFore:active {
background: #f0f0ee;
border-bottom: 1px solid #f0f0ee;
}
#edButtons input.edButtonBack, #edButtons input.edButtonBack:active {
background: #fff url( images/fade-butt.png ) repeat-x 0px 15px;
border-bottom: 1px solid #ccc;
}

View File

@ -735,13 +735,6 @@ function noindex() {
echo "<meta name='robots' content='noindex,nofollow' />\n";
}
/**
* Places a textarea according to the current user's preferences, filled with $content.
* Also places a script block that enables tabbing between Title and Content.
*
* @param string Editor contents
* @param string (optional) Previous form field's ID (for tabbing support)
*/
function the_editor($content, $id = 'content', $prev_id = 'title') {
$rows = get_option('default_post_edit_rows');
if (($rows < 3) || ($rows > 100))
@ -749,11 +742,61 @@ function the_editor($content, $id = 'content', $prev_id = 'title') {
$rows = "rows='$rows'";
the_quicktags();
if ( user_can_richedit() )
if ( user_can_richedit() ) :
add_filter('the_editor_content', 'wp_richedit_pre');
// The following line moves the border so that the active button "attaches" to the toolbar. Only IE needs it.
?>
<!--[if IE]><style type="text/css">
#postdivrich table, #postdivrich #quicktags {border-top: none;}
#quicktags {border-bottom: none; padding-bottom: 2px; margin-bottom: -1px;}
#edButtons {border-bottom: 1px solid #ccc;}
</style><![endif]-->
<div id='edButtons' style='display:none;'>
<div class='zerosize'><input accesskey='e' type='button' onclick='switchEditors("<?php echo $id; ?>")' /></div>
<input id='edButtonPreview' class='edButtonFore' type='button' value='<?php _e('Compose'); ?>' />
<input id='edButtonHTML' class='edButtonBack' type='button' value='<?php _e('HTML'); ?>' onclick='switchEditors("<?php echo $id; ?>")' />
</div>
<script type="text/javascript">
if ( typeof tinyMCE != "undefined" && tinyMCE.configs.length > 0 )
document.getElementById('edButtons').style.display = 'block';
</script>
<?php endif; ?>
<div id="quicktags">
<?php wp_print_scripts( 'quicktags' ); ?>
<script type="text/javascript">edToolbar()</script>
</div>
<script type="text/javascript">
if ( typeof tinyMCE != "undefined" && tinyMCE.configs.length > 0 )
document.getElementById("quicktags").style.display="none";
function edInsertContent(myField, myValue) {
//IE support
if (document.selection) {
myField.focus();
sel = document.selection.createRange();
sel.text = myValue;
myField.focus();
}
//MOZILLA/NETSCAPE support
else if (myField.selectionStart || myField.selectionStart == "0") {
var startPos = myField.selectionStart;
var endPos = myField.selectionEnd;
myField.value = myField.value.substring(0, startPos)
+ myValue
+ myField.value.substring(endPos, myField.value.length);
myField.focus();
myField.selectionStart = startPos + myValue.length;
myField.selectionEnd = startPos + myValue.length;
} else {
myField.value += myValue;
myField.focus();
}
}
</script>
<?php
$the_editor = apply_filters('the_editor', "<div><textarea class='mceEditor' $rows cols='40' name='$id' tabindex='2' id='$id'>%s</textarea></div>\n");
$the_editor_content = apply_filters('the_editor_content', $content);
@ -763,17 +806,17 @@ function the_editor($content, $id = 'content', $prev_id = 'title') {
<script type="text/javascript">
//<!--
edCanvas = document.getElementById('<?php echo $id; ?>');
<?php if ( user_can_richedit() ) : ?>
<?php if ( $prev_id && user_can_richedit() ) : ?>
// This code is meant to allow tabbing from Title to Post (TinyMCE).
if ( tinyMCE.isMSIE )
document.getElementById('<?php echo $prev_id; ?>').onkeydown = function (e)
{
e = e ? e : window.event;
if (e.keyCode == 9 && !e.shiftKey && !e.controlKey && !e.altKey) {
var i = tinyMCE.selectedInstance;
var i = tinyMCE.getInstanceById('<?php echo $id; ?>');
if(typeof i == 'undefined')
return true;
tinyMCE.execCommand("mceStartTyping");
tinyMCE.execCommand("mceStartTyping");
this.blur();
i.contentWindow.focus();
e.returnValue = false;
@ -785,10 +828,10 @@ function the_editor($content, $id = 'content', $prev_id = 'title') {
{
e = e ? e : window.event;
if (e.keyCode == 9 && !e.shiftKey && !e.controlKey && !e.altKey) {
var i = tinyMCE.selectedInstance;
var i = tinyMCE.getInstanceById('<?php echo $id; ?>');
if(typeof i == 'undefined')
return true;
tinyMCE.execCommand("mceStartTyping");
tinyMCE.execCommand("mceStartTyping");
this.blur();
i.contentWindow.focus();
e.returnValue = false;

View File

@ -72,11 +72,12 @@ function autosave_saved() {
function autosave() {
var form = $('post');
var rich = tinyMCE.getInstanceById('content') ? true : false;
autosaveAjax = new sack();
/* Gotta do this up here so we can check the length when tinyMCE is in use */
if ( typeof tinyMCE == "undefined" || tinyMCE.configs.length < 1 ) {
if ( typeof tinyMCE == "undefined" || tinyMCE.configs.length < 1 || rich == false ) {
autosaveAjax.setVar("content", form.content.value);
} else {
if(tinyMCE.selectedInstance.spellcheckerOn) return;
@ -110,7 +111,7 @@ function autosave() {
if(form.excerpt)
autosaveAjax.setVar("excerpt", form.excerpt.value);
if ( typeof tinyMCE == "undefined" || tinyMCE.configs.length < 1 ) {
if ( typeof tinyMCE == "undefined" || tinyMCE.configs.length < 1 || rich == false ) {
autosaveAjax.setVar("content", form.content.value);
} else {
tinyMCE.wpTriggerSave();

View File

@ -38,9 +38,9 @@ var TinyMCE_wordpressPlugin = {
+ '<input type="button" accesskey="g" onclick="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'wpPage\');" />'
+ '<input type="button" accesskey="u" onclick="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'Undo\',false);" />'
+ '<input type="button" accesskey="y" onclick="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'Redo\',false);" />'
+ '<input type="button" accesskey="e" onclick="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'mceCodeEditor\',false);" />'
+ '<input type="button" accesskey="h" onclick="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'wpHelp\',false);" />'
+ '<input type="button" accesskey="b" onclick="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'wpAdv\',false);" />'
+ '<input type="button" accesskey="b" onclick="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'Bold\',false);" />'
+ '<input type="button" accesskey="v" onclick="tinyMCE.execInstanceCommand(\'{$editor_id}\',\'wpAdv\',false);" />'
+ '</div>';
return buttons+hiddenControls;
case "wp_adv":
@ -241,18 +241,18 @@ var TinyMCE_wordpressPlugin = {
// Remove anonymous, empty paragraphs.
content = content.replace(new RegExp('<p>(\\s|&nbsp;)*</p>', 'mg'), '');
// Handle table badness.
content = content.replace(new RegExp('<(table( [^>]*)?)>.*?<((tr|thead)( [^>]*)?)>', 'mg'), '<$1><$3>');
content = content.replace(new RegExp('<(tr|thead|tfoot)>.*?<((td|th)( [^>]*)?)>', 'mg'), '<$1><$2>');
content = content.replace(new RegExp('</(td|th)>.*?<(td( [^>]*)?|th( [^>]*)?|/tr|/thead|/tfoot)>', 'mg'), '</$1><$2>');
content = content.replace(new RegExp('</tr>.*?<(tr|/table)>', 'mg'), '</tr><$1>');
content = content.replace(new RegExp('<(/?(table|tbody|tr|th|td)[^>]*)>(\\s*|(<br ?/?>)*)*', 'g'), '<$1>');
// Pretty it up for the source editor.
var blocklist = 'blockquote|ul|ol|li|table|thead|tr|th|td|div|h\\d|pre|p';
content = content.replace(new RegExp('\\s*</('+blocklist+')>\\s*', 'mg'), '</$1>\n');
content = content.replace(new RegExp('\\s*<(('+blocklist+')[^>]*)>\\s*', 'mg'), '\n<$1>');
content = content.replace(new RegExp('\\s*<(('+blocklist+')[^>]*)>', 'mg'), '\n<$1>');
content = content.replace(new RegExp('<((li|/?tr|/?thead|/?tfoot)( [^>]*)?)>', 'g'), '\t<$1>');
content = content.replace(new RegExp('<((td|th)( [^>]*)?)>', 'g'), '\t\t<$1>');
content = content.replace(new RegExp('\\s*<br ?/?>\\s*', 'mg'), '<br />\n');
@ -294,9 +294,9 @@ var TinyMCE_wordpressPlugin = {
// content = content.replace(new RegExp('&amp;', 'g'), '&');
// Get it ready for wpautop.
content = content.replace(new RegExp('[\\s]*<p>[\\s]*', 'mgi'), '');
content = content.replace(new RegExp('[\\s]*</p>[\\s]*', 'mgi'), '\n\n');
content = content.replace(new RegExp('\\n\\s*\\n\\s*\\n*', 'mgi'), '\n\n');
content = content.replace(new RegExp('\\s*<p>', 'mgi'), '');
content = content.replace(new RegExp('\\s*</p>\\s*', 'mgi'), '\n\n');
content = content.replace(new RegExp('\\n\\s*\\n', 'mgi'), '\n\n');
content = content.replace(new RegExp('\\s*<br ?/?>\\s*', 'gi'), '\n');
// Fix some block element newline issues
@ -309,8 +309,7 @@ var TinyMCE_wordpressPlugin = {
content = content.replace(new RegExp('</p#>', 'g'), '</p>\n');
content = content.replace(new RegExp('\\s*(<p[^>]+>.*</p>)', 'mg'), '\n$1');
// Trim any whitespace
content = content.replace(new RegExp('^\\s*', ''), '');
// Trim trailing whitespace
content = content.replace(new RegExp('\\s*$', ''), '');
// Hope.
@ -468,3 +467,119 @@ tinyMCE.wpTriggerSave = function () {
inst.wpTriggerSave(false, false);
}
}
function switchEditors(id) {
var inst = tinyMCE.getInstanceById(id);
var qt = document.getElementById('quicktags');
var H = document.getElementById('edButtonHTML');
var P = document.getElementById('edButtonPreview');
var pdr = document.getElementById('postdivrich');
var ta = document.getElementById(id);
if ( inst ) {
edToggle(H, P);
if ( tinyMCE.isMSIE && !tinyMCE.isOpera ) {
// IE rejects the later overflow assignment so we skip this step.
// Alternate code might be nice. Until then, IE reflows.
} else {
// Lock the fieldset's height to prevent reflow/flicker
pdr.style.height = pdr.clientHeight + 'px';
pdr.style.overflow = 'hidden';
}
// Save the coords of the bottom right corner of the rich editor
var table = document.getElementById(inst.editorId + '_parent').getElementsByTagName('table')[0];
var y1 = table.offsetTop + table.offsetHeight;
// Unload the rich editor
inst.triggerSave(false, false);
htm = inst.formElement.value;
tinyMCE.removeMCEControl(id);
document.getElementById(id).value = htm;
--tinyMCE.idCounter;
// Reveal Quicktags and textarea
qt.style.display = 'block';
ta.style.display = 'inline';
// Set the textarea height to match the rich editor
y2 = ta.offsetTop + ta.offsetHeight;
ta.style.height = (ta.clientHeight + y1 - y2) + 'px';
// Tweak the widths
ta.parentNode.style.paddingRight = '2px';
if ( tinyMCE.isMSIE && !tinyMCE.isOpera ) {
} else {
// Unlock the fieldset's height
pdr.style.height = 'auto';
pdr.style.overflow = 'display';
}
} else {
edToggle(P, H);
edCloseAllTags(); // :-(
if ( tinyMCE.isMSIE && !tinyMCE.isOpera ) {
} else {
// Lock the fieldset's height
pdr.style.height = pdr.clientHeight + 'px';
pdr.style.overflow = 'hidden';
}
// Hide Quicktags and textarea
qt.style.display = 'none';
ta.style.display = 'none';
// Tweak the widths
ta.parentNode.style.paddingRight = '0px';
// Load the rich editor with formatted html
if ( tinyMCE.isMSIE ) {
ta.value = wpautop(ta.value);
tinyMCE.addMCEControl(ta, id);
} else {
htm = wpautop(ta.value);
tinyMCE.addMCEControl(ta, id);
tinyMCE.getInstanceById(id).execCommand('mceSetContent', null, htm);
}
if ( tinyMCE.isMSIE && !tinyMCE.isOpera ) {
} else {
// Unlock the fieldset's height
pdr.style.height = 'auto';
pdr.style.overflow = 'display';
}
}
}
function edToggle(A, B) {
A.className = 'edButtonFore';
B.className = 'edButtonBack';
B.onclick = A.onclick;
A.onclick = null;
}
function wpautop(pee) {
pee = pee + "\n\n";
pee = pee.replace(new RegExp('<br />\\s*<br />', 'gi'), "\n\n");
pee = pee.replace(new RegExp('(<(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)', 'gi'), "\n$1");
pee = pee.replace(new RegExp('(</(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])>)', 'gi'), "$1\n\n");
pee = pee.replace(new RegExp("\\r\\n|\\r", 'g'), "\n");
pee = pee.replace(new RegExp("\\n\\s*\\n+", 'g'), "\n\n");
pee = pee.replace(new RegExp('\n*([^\Z]+?)\\n{2}', 'mg'), "<p>$1</p>\n");
pee = pee.replace(new RegExp('<p>\\s*?</p>', 'gi'), '');
pee = pee.replace(new RegExp('<p>\\s*(</?(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|hr|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)\\s*</p>', 'gi'), "$1");
pee = pee.replace(new RegExp("<p>(<li.+?)</p>", 'gi'), "$1");
pee = pee.replace(new RegExp('<p><blockquote([^>]*)>', 'gi'), "<blockquote$1><p>");
pee = pee.replace(new RegExp('</blockquote></p>', 'gi'), '</p></blockquote>');
pee = pee.replace(new RegExp('<p>\\s*(</?(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|hr|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)', 'gi'), "$1");
pee = pee.replace(new RegExp('(</?(?:table|thead|tfoot|caption|colgroup|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)\\s*</p>', 'gi'), "$1");
pee = pee.replace(new RegExp('\\s*\\n', 'gi'), "<br />\n");
pee = pee.replace(new RegExp('(</?(?:table|thead|tfoot|caption|tbody|tr|td|th|div|dl|dd|dt|ul|ol|li|pre|select|form|blockquote|address|math|p|h[1-6])[^>]*>)\\s*<br />', 'gi'), "$1");
pee = pee.replace(new RegExp('<br />(\\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)>)', 'gi'), '$1');
pee = pee.replace(new RegExp('^((?:&nbsp;)*)\\s', 'mg'), '$1&nbsp;');
//pee = pee.replace(new RegExp('(<pre.*?>)(.*?)</pre>!ise', " stripslashes('$1') . stripslashes(clean_pre('$2')) . '</pre>' "); // Hmm...
return pee;
}

View File

@ -21,14 +21,14 @@
}
// Set up init variables
$valid_elements = 'p/-div[*],-b[*],-font[*],-ul[*],-ol[*],-li[*],*[*]';
$valid_elements = 'p/-div[*],-strong/-b[*],-em/-i[*],-font[*],-ul[*],-ol[*],-li[*],*[*]';
$valid_elements = apply_filters('mce_valid_elements', $valid_elements);
$plugins = array('inlinepopups', 'autosave', 'spellchecker', 'paste', 'wordpress');
$plugins = apply_filters('mce_plugins', $plugins);
$plugins = implode($plugins, ',');
$mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', 'separator', 'bullist', 'numlist', 'outdent', 'indent', 'separator', 'justifyleft', 'justifycenter', 'justifyright', 'separator', 'link', 'unlink', 'image', 'wp_more', 'separator', 'spellchecker', 'separator', 'code', 'wp_help', 'wp_adv_start', 'wp_adv', 'separator', 'formatselect', 'underline', 'justifyfull', 'forecolor', 'separator', 'pastetext', 'pasteword', 'separator', 'removeformat', 'cleanup', 'separator', 'charmap', 'separator', 'undo', 'redo', 'wp_adv_end'));
$mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', 'separator', 'bullist', 'numlist', 'outdent', 'indent', 'separator', 'justifyleft', 'justifycenter', 'justifyright', 'separator', 'link', 'unlink', 'image', 'wp_more', 'separator', 'spellchecker', 'separator', 'wp_help', 'wp_adv_start', 'wp_adv', 'separator', 'formatselect', 'underline', 'justifyfull', 'forecolor', 'separator', 'pastetext', 'pasteword', 'separator', 'removeformat', 'cleanup', 'separator', 'charmap', 'separator', 'undo', 'redo', 'wp_adv_end'));
$mce_buttons = implode($mce_buttons, ',');
$mce_buttons_2 = apply_filters('mce_buttons_2', array());

View File

@ -15,10 +15,10 @@ class WP_Scripts {
$this->add( 'sack', '/wp-includes/js/tw-sack.js', false, '1.6.1' );
$this->add( 'quicktags', '/wp-includes/js/quicktags.js', false, '3517' );
$this->add( 'colorpicker', '/wp-includes/js/colorpicker.js', false, '3517' );
$this->add( 'tiny_mce', '/wp-includes/js/tinymce/tiny_mce_gzip.php', false, '08152006' );
$this->add( 'wp_tiny_mce', '/wp-includes/js/tinymce/tiny_mce_config.php', array('tiny_mce'), '04162006' );
$this->add( 'tiny_mce', '/wp-includes/js/tinymce/tiny_mce_gzip.php', false, '09212006' );
$this->add( 'wp_tiny_mce', '/wp-includes/js/tinymce/tiny_mce_config.php', array('tiny_mce'), '09212006' );
$this->add( 'prototype', '/wp-includes/js/prototype.js', false, '1.5.0');
$this->add( 'autosave', '/wp-includes/js/autosave.js.php', array('prototype', 'sack'), '4183');
$this->add( 'autosave', '/wp-includes/js/autosave.js.php', array('prototype', 'sack'), '4206');
$this->add( 'wp-ajax', '/wp-includes/js/wp-ajax-js.php', array('prototype'), '4187');
$this->add( 'listman', '/wp-includes/js/list-manipulation-js.php', array('wp-ajax', 'fat'), '4187');
if ( is_admin() ) {