Fix back-compat for quicktags, introduce QTags.addButton(), see #16695

git-svn-id: https://develop.svn.wordpress.org/trunk@18511 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Andrew Ozz 2011-08-05 04:09:22 +00:00
parent 19b936f2a8
commit 6ce85719a7
6 changed files with 206 additions and 118 deletions

View File

@ -549,7 +549,7 @@ $(document).ready(function(){
$(document).delegate('span.delete a.delete', 'click', function(){return false;}); $(document).delegate('span.delete a.delete', 'click', function(){return false;});
if ( typeof QTags != 'undefined' ) if ( typeof QTags != 'undefined' )
quicktags({quicktags_id: 'replycontent', quicktags_buttons: 'strong,em,link,block,del,ins,img,ul,ol,li,code,spell,close'}); quicktags({id: 'replycontent', buttons: 'strong,em,link,block,del,ins,img,ul,ol,li,code,spell,close'});
if ( typeof $.table_hotkeys != 'undefined' ) { if ( typeof $.table_hotkeys != 'undefined' ) {
make_hotkeys_redirect = function(which) { make_hotkeys_redirect = function(which) {

File diff suppressed because one or more lines are too long

View File

@ -22,8 +22,8 @@ class WP_Editor {
var $can_richedit; var $can_richedit;
var $default_editor; var $default_editor;
var $first_init; var $first_init;
var $tinymce = false; var $this_tinymce = false;
var $quicktags = false; var $this_quicktags = false;
function __construct() { function __construct() {
$this->can_richedit = user_can_richedit(); $this->can_richedit = user_can_richedit();
@ -33,9 +33,9 @@ class WP_Editor {
/** /**
* Outputs the HTML and enqueues the JavaScript for a single instance of the editor. * Outputs the HTML and enqueues the JavaScript for a single instance of the editor.
* *
* $param $content The initial content of the editor. * @param $content The initial content of the editor.
* $param $editor_id ID for the textarea and TinyMCE and Quicktags instances (can contain only ASCII letters and numbers). * @param $editor_id ID for the textarea and TinyMCE and Quicktags instances (can contain only ASCII letters and numbers).
* $param $settings See below for description. * @param $settings See below for description.
*/ */
function editor( $content, $editor_id, $settings = array() ) { function editor( $content, $editor_id, $settings = array() ) {
@ -52,8 +52,8 @@ class WP_Editor {
'quicktags' => true // load Quicktags, can be used to pass settings directly to Quicktags using an array() 'quicktags' => true // load Quicktags, can be used to pass settings directly to Quicktags using an array()
) ); ) );
$this->tinymce = !empty($set['tinymce']) && $this->can_richedit; $this->this_tinymce = !empty($set['tinymce']) && $this->can_richedit;
$this->quicktags = !empty($set['quicktags']); $this->this_quicktags = !empty($set['quicktags']);
$editor_class = ' class="' . trim( $set['editor_class'] . ' wp-editor-area' ) . '"'; $editor_class = ' class="' . trim( $set['editor_class'] . ' wp-editor-area' ) . '"';
$tabindex = $set['tabindex'] ? ' tabindex="' . (int) $set['tabindex'] . '"' : ''; $tabindex = $set['tabindex'] ? ' tabindex="' . (int) $set['tabindex'] . '"' : '';
$rows = ' rows="' . (int) $set['textarea_rows'] . '"'; $rows = ' rows="' . (int) $set['textarea_rows'] . '"';
@ -63,7 +63,7 @@ class WP_Editor {
if ( !current_user_can( 'upload_files' ) ) if ( !current_user_can( 'upload_files' ) )
$set['media_buttons'] = false; $set['media_buttons'] = false;
if ( $this->can_richedit && $this->quicktags && $this->tinymce ) { if ( $this->can_richedit && $this->this_quicktags && $this->this_tinymce ) {
$switch_class = 'html-active'; $switch_class = 'html-active';
if ( 'html' == $this->default_editor ) { if ( 'html' == $this->default_editor ) {
@ -117,14 +117,14 @@ class WP_Editor {
global $editor_styles; global $editor_styles;
$first_run = false; $first_run = false;
if ( $this->quicktags ) { if ( $this->this_quicktags ) {
$qtbuttons = apply_filters( 'quicktags_buttons', array(), $editor_id ); $qtbuttons = apply_filters( 'quicktags_buttons', array(), $editor_id );
$qtbuttons_disabled = apply_filters( 'quicktags_disabled_buttons', array(), $editor_id ); $qtbuttons_disabled = apply_filters( 'quicktags_disabled_buttons', array(), $editor_id );
$qtInit = array( $qtInit = array(
'quicktags_id' => $editor_id, 'id' => $editor_id,
'quicktags_buttons' => implode($qtbuttons, ','), 'buttons' => implode($qtbuttons, ','),
'quicktags_disabled_buttons' => implode($qtbuttons_disabled, ',') 'disabled_buttons' => implode($qtbuttons_disabled, ',')
); );
if ( is_array($settings['quicktags']) ) if ( is_array($settings['quicktags']) )
@ -133,7 +133,7 @@ class WP_Editor {
$this->qt_settings[$editor_id] = $qtInit; $this->qt_settings[$editor_id] = $qtInit;
} }
if ( $this->tinymce ) { if ( $this->this_tinymce ) {
if ( empty($this->first_init) ) { if ( empty($this->first_init) ) {
$this->baseurl = includes_url('js/tinymce'); $this->baseurl = includes_url('js/tinymce');
@ -375,7 +375,7 @@ class WP_Editor {
$this->mce_settings[$editor_id] = $mceInit; $this->mce_settings[$editor_id] = $mceInit;
$first_run = false; $first_run = false;
} // end if $this->tinymce } // end if $this->this_tinymce
} }
function _parse_init($init) { function _parse_init($init) {
@ -419,20 +419,15 @@ class WP_Editor {
wp_enqueue_script('quicktags'); wp_enqueue_script('quicktags');
wp_enqueue_script('word-count'); wp_enqueue_script('word-count');
wp_enqueue_script('wplink'); wp_enqueue_script('wplink');
wp_enqueue_script('editor');
wp_enqueue_style('editor-buttons'); wp_enqueue_style('editor-buttons');
wp_enqueue_script('wpdialogs-popup'); wp_enqueue_script('wpdialogs-popup');
wp_enqueue_style('wp-jquery-ui-dialog'); wp_enqueue_style('wp-jquery-ui-dialog');
if ( $this->tinymce )
wp_enqueue_script('editor');
else
wp_enqueue_script('utils');
if ( in_array('wpfullscreen', $this->plugins, true) ) if ( in_array('wpfullscreen', $this->plugins, true) )
wp_enqueue_script('wp-fullscreen'); wp_enqueue_script('wp-fullscreen');
if ( !is_admin() )
add_thickbox(); add_thickbox();
} }
@ -447,6 +442,7 @@ class WP_Editor {
* If the plugin has a popup dialog, a query string can be added to the button action that opens it (in the plugin's code). * If the plugin has a popup dialog, a query string can be added to the button action that opens it (in the plugin's code).
*/ */
$version = 'ver=' . $tinymce_version; $version = 'ver=' . $tinymce_version;
$tmce_on = !empty($this->mce_settings);
if ( ! isset($concatenate_scripts) ) if ( ! isset($concatenate_scripts) )
script_concat_settings(); script_concat_settings();
@ -454,11 +450,11 @@ class WP_Editor {
$compressed = $compress_scripts && $concatenate_scripts && isset($_SERVER['HTTP_ACCEPT_ENCODING']) $compressed = $compress_scripts && $concatenate_scripts && isset($_SERVER['HTTP_ACCEPT_ENCODING'])
&& false !== stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip'); && false !== stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
if ( $this->tinymce && 'en' != $this->mce_locale ) if ( $tmce_on && 'en' != $this->mce_locale )
include_once(ABSPATH . WPINC . '/js/tinymce/langs/wp-langs.php'); include_once(ABSPATH . WPINC . '/js/tinymce/langs/wp-langs.php');
$mceInit = $qtInit = ''; $mceInit = $qtInit = '';
if ( !empty($this->mce_settings) ) { if ( $tmce_on ) {
foreach ( $this->mce_settings as $editor_id => $init ) { foreach ( $this->mce_settings as $editor_id => $init ) {
$options = $this->_parse_init( $init ); $options = $this->_parse_init( $init );
$mceInit .= "'$editor_id':{$options},\n"; $mceInit .= "'$editor_id':{$options},\n";
@ -503,7 +499,7 @@ class WP_Editor {
</script> </script>
<?php <?php
if ( $this->tinymce ) { if ( $tmce_on ) {
if ( $compressed ) if ( $compressed )
echo "<script type='text/javascript' src='$this->baseurl/wp-tinymce.php?c=1&amp;$version'></script>\n"; echo "<script type='text/javascript' src='$this->baseurl/wp-tinymce.php?c=1&amp;$version'></script>\n";
else else
@ -570,7 +566,7 @@ class WP_Editor {
ed.execCommand('mceInsertContent', false, h); ed.execCommand('mceInsertContent', false, h);
} else if ( typeof quicktags != 'undefined' ) { } else if ( typeof quicktags != 'undefined' ) {
quicktags.insertContent(wpActiveEditor, h); QTags.insertContent(wpActiveEditor, h);
} else { } else {
jQuery('#'+wpActiveEditor).val( jQuery('#'+wpActiveEditor).val() + h ); jQuery('#'+wpActiveEditor).val( jQuery('#'+wpActiveEditor).val() + h );
} }
@ -582,7 +578,7 @@ class WP_Editor {
if ( $this->ext_plugins ) if ( $this->ext_plugins )
echo "$this->ext_plugins\n"; echo "$this->ext_plugins\n";
if ( ! $compressed && $this->tinymce ) { if ( ! $compressed && $tmce_on ) {
?> ?>
(function(){var t=tinyMCEPreInit,sl=tinymce.ScriptLoader,ln=t.ref.language,th=t.ref.theme,pl=t.ref.plugins;sl.markDone(t.base+'/langs/'+ln+'.js');sl.markDone(t.base+'/themes/'+th+'/langs/'+ln+'.js');sl.markDone(t.base+'/themes/'+th+'/langs/'+ln+'_dlg.js');sl.markDone(t.base+'/themes/advanced/skins/wp_theme/ui.css');tinymce.each(pl.split(','),function(n){if(n&&n.charAt(0)!='-'){sl.markDone(t.base+'/plugins/'+n+'/langs/'+ln+'.js');sl.markDone(t.base+'/plugins/'+n+'/langs/'+ln+'_dlg.js');}});})(); (function(){var t=tinyMCEPreInit,sl=tinymce.ScriptLoader,ln=t.ref.language,th=t.ref.theme,pl=t.ref.plugins;sl.markDone(t.base+'/langs/'+ln+'.js');sl.markDone(t.base+'/themes/'+th+'/langs/'+ln+'.js');sl.markDone(t.base+'/themes/'+th+'/langs/'+ln+'_dlg.js');sl.markDone(t.base+'/themes/advanced/skins/wp_theme/ui.css');tinymce.each(pl.split(','),function(n){if(n&&n.charAt(0)!='-'){sl.markDone(t.base+'/plugins/'+n+'/langs/'+ln+'.js');sl.markDone(t.base+'/plugins/'+n+'/langs/'+ln+'_dlg.js');}});})();
<?php <?php

View File

@ -6,9 +6,11 @@
* *
* Run quicktags(settings) to initialize it, where settings is an object containing up to 3 properties: * Run quicktags(settings) to initialize it, where settings is an object containing up to 3 properties:
* settings = { * settings = {
* quicktags_id: 'myid', // required * id : 'my_id', // the HTML ID of the textarea, required
* buttons: '', // optional * buttons: '', // Comma separated list of the names of the default buttons to show. Optional.
* disabled_buttons: '' // optional * // This overwrites buttons order and any buttons added by plugins.
* // Current list of default button names: 'strong,em,link,block,del,ins,img,ul,ol,li,code,more,spell,close'
* disabled_buttons : '' // Comma separated list of the names of the buttons to disable.
* } * }
* *
* The settings can also be a string quicktags_id. * The settings can also be a string quicktags_id.
@ -24,12 +26,35 @@
// by Alex King // by Alex King
// http://www.alexking.org/ // http://www.alexking.org/
var QTags, edButtons, edButton; var QTags, edButtons = [], edCanvas;
/**
* Initialize new instance of the Quicktags editor
*/
function quicktags(settings) { function quicktags(settings) {
return new QTags(settings); return new QTags(settings);
} }
/**
* Inderts content at the caret in the active editor (textarea)
*
* Added for back compatibility
* @see QTags.insertContent()
*/
function edInsertContent(bah, txt) {
return QTags.insertContent(txt);
}
/**
* Adds a button to all instances of the editor
*
* Added for back compatibility
* @see QTags.addButton()
*/
function edButton(id, display, tagStart, tagEnd, access, open) {
return QTags.addButton( id, display, tagStart, tagEnd, open, access );
}
(function(){ (function(){
// private stuff is prefixed with an underscore // private stuff is prefixed with an underscore
var _domReady = function(func) { var _domReady = function(func) {
@ -109,18 +134,18 @@ function quicktags(settings) {
qt = QTags = function(settings) { qt = QTags = function(settings) {
if ( typeof(settings) == 'string' ) if ( typeof(settings) == 'string' )
settings = {quicktags_id: settings}; settings = {id: settings};
else if ( typeof(settings) != 'object' ) else if ( typeof(settings) != 'object' )
return false; return false;
var t = this, var t = this,
id = settings.quicktags_id, id = settings.id,
buttons = {}, buttons = {},
theButtons = {}, theButtons = {},
canvas = document.getElementById(id), canvas = document.getElementById(id),
name = 'qt_' + id, name = 'qt_' + id,
html = '', html = '',
i, tb, qb, btn, onclick; i, tb, qb, btn, onclick, toolbar_id;
if ( !id || !canvas ) if ( !id || !canvas )
return false; return false;
@ -130,6 +155,9 @@ function quicktags(settings) {
// default buttons // default buttons
for ( i in edButtons ) { for ( i in edButtons ) {
if ( !edButtons[i] )
continue;
buttons[edButtons[i].id] = edButtons[i]; buttons[edButtons[i].id] = edButtons[i];
} }
@ -141,8 +169,8 @@ function quicktags(settings) {
buttons[i] = new t._customButtons[i](); buttons[i] = new t._customButtons[i]();
} }
if ( settings.quicktags_buttons ) { if ( settings.buttons ) {
qb = settings.quicktags_buttons.split(','); qb = settings.buttons.split(',');
for ( i in qb ) { for ( i in qb ) {
btn = qb[i]; btn = qb[i];
@ -153,8 +181,8 @@ function quicktags(settings) {
theButtons = buttons; theButtons = buttons;
} }
if ( settings.quicktags_disabled_buttons ) { if ( settings.disabled_buttons ) {
qb = settings.quicktags_disabled_buttons.split(','); qb = settings.disabled_buttons.split(',');
for ( i in qb ) { for ( i in qb ) {
btn = qb[i]; btn = qb[i];
@ -166,8 +194,15 @@ function quicktags(settings) {
for ( i in theButtons ) for ( i in theButtons )
html += theButtons[i].html(name + '_'); html += theButtons[i].html(name + '_');
if ( id == 'content' && !qt.instances[0] ) { // back compat hack :-(
edCanvas = canvas;
toolbar_id = 'ed_toolbar';
} else {
toolbar_id = name + '_toolbar';
}
tb = document.createElement('div'); tb = document.createElement('div');
tb.id = name + '_toolbar'; tb.id = toolbar_id;
tb.className = 'quicktags-toolbar'; tb.className = 'quicktags-toolbar';
canvas.parentNode.insertBefore(tb, canvas); canvas.parentNode.insertBefore(tb, canvas);
@ -197,6 +232,9 @@ function quicktags(settings) {
tb.attachEvent('onclick', onclick); tb.attachEvent('onclick', onclick);
} }
if ( !qt.instances[0] )
qt.instances[0] = t;
qt.instances[id] = t; qt.instances[id] = t;
}; };
@ -210,8 +248,64 @@ function quicktags(settings) {
return qt.instances[id]; return qt.instances[id];
}; };
qt.insertContent = function(editor_id, content) { /**
var sel, startPos, endPos, scrollTop, text, ed = document.getElementById(editor_id); * Main API function for adding a button to Quicktags
*
* Adds qt.Button or qt.TagButton depending on the args. The first three args are always required.
* For TagButton arg2 is also required. To be able to add button(s) to Quicktags, your script
* should be enqueued as dependant on "quicktags" and outputted in the footer. If you are echoing JS
* directly from PHP, use add_action( 'admin_print_footer_scripts', 'output_my_js', 100 ) or add_action( 'wp_footer', 'output_my_js', 100 )
*
* Minimun required to add a button that calls an external function:
* QTags.addButton( 'my_id', 'my button', my_callback );
* function my_callback() { alert('yeah!'); }
*
* Minimun required to add a button that inserts a tag:
* QTags.addButton( 'my_id', 'my button', '<span>', '</span>' );
*
* @param id string required button HTML ID
* @param display string required button's value="..."
* @param arg1 string || function required either a starting tag to be inserted like "<span>" or a callback that is executed when the button is pressed
* @param arg2 string ending tag like "</span>"
* @param arg3 int set to -1 if the inserted tag is self-closing
* @param access string access key for the button
* @param title string button's title="..."
* @param priority int number representing the desired position of the button in the toolbar. 1 - 9 = first, 11 - 19 = second, 21 - 29 = third, etc.
* @return bool TRUE on success FALSE on failure
*/
qt.addButton = function( id, display, arg1, arg2, arg3, access, title, priority ) {
var btn;
if ( !id || !display )
return false;
if ( typeof(arg1) == 'function' ) {
btn = new qt.Button(id, display, access, title);
btn.callback = arg1;
} else if ( typeof(arg1) == 'string' && arg1 && arg2 ) {
btn = new qt.TagButton(id, display, arg1, arg2, access, arg3, title);
} else {
return false;
}
if ( priority ) {
while ( typeof(edButtons[priority]) != 'undefined' ) {
priority++
}
edButtons[priority] = btn;
} else {
edButtons[edButtons.length] = btn;
}
return true;
};
qt.insertContent = function(content) {
var sel, startPos, endPos, scrollTop, text, ed = document.getElementById(wpActiveEditor);
if ( !ed )
return false;
if ( document.selection ) { //IE if ( document.selection ) { //IE
ed.focus(); ed.focus();
@ -234,6 +328,7 @@ function quicktags(settings) {
ed.value += content; ed.value += content;
ed.focus(); ed.focus();
} }
return true;
}; };
// a plain, dumb button // a plain, dumb button
@ -468,22 +563,19 @@ function quicktags(settings) {
}; };
// ensure backward compatibility // ensure backward compatibility
edButtons = [ edButtons[10] = new qt.TagButton('strong','b','<strong>','</strong>','b');
new qt.TagButton('strong','b','<strong>','</strong>','b'), edButtons[20] = new qt.TagButton('em','i','<em>','</em>','i'),
new qt.TagButton('em','i','<em>','</em>','i'), edButtons[30] = new qt.LinkButton(), // special case
new qt.LinkButton(), // special case edButtons[40] = new qt.TagButton('block','b-quote','\n\n<blockquote>','</blockquote>\n\n','q'),
new qt.TagButton('block','b-quote','\n\n<blockquote>','</blockquote>\n\n','q'), edButtons[50] = new qt.TagButton('del','del','<del datetime="' + _datetime + '">','</del>','d'),
new qt.TagButton('del','del','<del datetime="' + _datetime + '">','</del>','d'), edButtons[60] = new qt.TagButton('ins','ins','<ins datetime="' + _datetime + '">','</ins>','s'),
new qt.TagButton('ins','ins','<ins datetime="' + _datetime + '">','</ins>','s'), edButtons[70] = new qt.ImgButton(), // special case
new qt.ImgButton(), // special case edButtons[80] = new qt.TagButton('ul','ul','<ul>\n','</ul>\n\n','u'),
new qt.TagButton('ul','ul','<ul>\n','</ul>\n\n','u'), edButtons[90] = new qt.TagButton('ol','ol','<ol>\n','</ol>\n\n','o'),
new qt.TagButton('ol','ol','<ol>\n','</ol>\n\n','o'), edButtons[100] = new qt.TagButton('li','li','\t<li>','</li>\n','l'),
new qt.TagButton('li','li','\t<li>','</li>\n','l'), edButtons[110] = new qt.TagButton('code','code','<code>','</code>','c'),
new qt.TagButton('code','code','<code>','</code>','c'), edButtons[120] = new qt.TagButton('more','more','<!--more-->','','t',-1),
new qt.TagButton('more','more','<!--more-->','','t',-1), edButtons[130] = new qt.SpellButton(),
new qt.SpellButton(), edButtons[140] = new qt.CloseButton()
new qt.CloseButton()
];
edButton = qt.TagButton;
})(); })();

File diff suppressed because one or more lines are too long

View File

@ -68,7 +68,7 @@ function wp_default_scripts( &$scripts ) {
$scripts->add( 'sack', "/wp-includes/js/tw-sack$suffix.js", false, '1.6.1', 1 ); $scripts->add( 'sack', "/wp-includes/js/tw-sack$suffix.js", false, '1.6.1', 1 );
$scripts->add( 'quicktags', "/wp-includes/js/quicktags$suffix.js", false, '20110802', 1 ); $scripts->add( 'quicktags', "/wp-includes/js/quicktags$suffix.js", false, '20110804', 1 );
$scripts->add_script_data( 'quicktags', 'quicktagsL10n', array( $scripts->add_script_data( 'quicktags', 'quicktagsL10n', array(
'wordLookup' => __('Enter a word to look up:'), 'wordLookup' => __('Enter a word to look up:'),
'dictionaryLookup' => esc_attr(__('Dictionary lookup')), 'dictionaryLookup' => esc_attr(__('Dictionary lookup')),
@ -269,7 +269,7 @@ function wp_default_scripts( &$scripts ) {
$scripts->add( 'admin-custom-fields', "/wp-admin/js/custom-fields$suffix.js", array('wp-lists'), '20110429', 1 ); $scripts->add( 'admin-custom-fields', "/wp-admin/js/custom-fields$suffix.js", array('wp-lists'), '20110429', 1 );
$scripts->add( 'admin-comments', "/wp-admin/js/edit-comments$suffix.js", array('wp-lists', 'jquery-ui-resizable', 'quicktags', 'jquery-query'), '20110802', 1 ); $scripts->add( 'admin-comments', "/wp-admin/js/edit-comments$suffix.js", array('wp-lists', 'jquery-ui-resizable', 'quicktags', 'jquery-query'), '20110804', 1 );
$scripts->add_script_data( 'admin-comments', 'adminCommentsL10n', array( $scripts->add_script_data( 'admin-comments', 'adminCommentsL10n', array(
'hotkeys_highlight_first' => isset($_GET['hotkeys_highlight_first']), 'hotkeys_highlight_first' => isset($_GET['hotkeys_highlight_first']),
'hotkeys_highlight_last' => isset($_GET['hotkeys_highlight_last']), 'hotkeys_highlight_last' => isset($_GET['hotkeys_highlight_last']),