3 * Facilitates adding of the WordPress editor as used on the Write and Edit screens.
8 * Private, not included by default. See wp_editor() in wp-includes/general-template.php.
11 final class _WP_Editors {
12 public static $mce_locale;
14 private static $mce_settings = array();
15 private static $qt_settings = array();
16 private static $plugins = array();
17 private static $qt_buttons = array();
18 private static $ext_plugins;
19 private static $baseurl;
20 private static $first_init;
21 private static $this_tinymce = false;
22 private static $this_quicktags = false;
23 private static $has_tinymce = false;
24 private static $has_quicktags = false;
25 private static $has_medialib = false;
26 private static $editor_buttons_css = true;
28 private function __construct() {}
30 public static function parse_settings($editor_id, $settings) {
31 $set = wp_parse_args( $settings, array(
32 'wpautop' => true, // use wpautop?
33 'media_buttons' => true, // show insert/upload button(s)
34 'textarea_name' => $editor_id, // set the textarea name to something different, square brackets [] can be used here
35 'textarea_rows' => get_option('default_post_edit_rows', 10), // rows="..."
37 'editor_css' => '', // intended for extra styles for both visual and HTML editors buttons, needs to include the <style> tags, can use "scoped".
38 'editor_class' => '', // add extra class(es) to the editor textarea
39 'teeny' => false, // output the minimal editor config used in Press This
40 'dfw' => false, // replace the default fullscreen with DFW (needs specific DOM elements and css)
41 'tinymce' => true, // load TinyMCE, can be used to pass settings directly to TinyMCE using an array()
42 'quicktags' => true // load Quicktags, can be used to pass settings directly to Quicktags using an array()
45 self::$this_tinymce = ( $set['tinymce'] && user_can_richedit() );
46 self::$this_quicktags = (bool) $set['quicktags'];
48 if ( self::$this_tinymce )
49 self::$has_tinymce = true;
51 if ( self::$this_quicktags )
52 self::$has_quicktags = true;
58 * Outputs the HTML for a single instance of the editor.
60 * @param string $content The initial content of the editor.
61 * @param string $editor_id ID for the textarea and TinyMCE and Quicktags instances (can contain only ASCII letters and numbers).
62 * @param array $settings See the _parse_settings() method for description.
64 public static function editor( $content, $editor_id, $settings = array() ) {
66 $set = self::parse_settings($editor_id, $settings);
67 $editor_class = ' class="' . trim( $set['editor_class'] . ' wp-editor-area' ) . '"';
68 $tabindex = $set['tabindex'] ? ' tabindex="' . (int) $set['tabindex'] . '"' : '';
69 $rows = ' rows="' . (int) $set['textarea_rows'] . '"';
70 $switch_class = 'html-active';
71 $toolbar = $buttons = '';
73 if ( !current_user_can( 'upload_files' ) )
74 $set['media_buttons'] = false;
76 if ( self::$this_quicktags && self::$this_tinymce ) {
77 $switch_class = 'html-active';
79 if ( 'html' == wp_default_editor() ) {
80 add_filter('the_editor_content', 'wp_htmledit_pre');
82 add_filter('the_editor_content', 'wp_richedit_pre');
83 $switch_class = 'tmce-active';
86 $buttons .= '<a id="' . $editor_id . '-html" class="hide-if-no-js wp-switch-editor switch-html" onclick="switchEditors.switchto(this);">' . __('HTML') . "</a>\n";
87 $buttons .= '<a id="' . $editor_id . '-tmce" class="hide-if-no-js wp-switch-editor switch-tmce" onclick="switchEditors.switchto(this);">' . __('Visual') . "</a>\n";
90 echo '<div id="wp-' . $editor_id . '-wrap" class="wp-editor-wrap ' . $switch_class . '">';
92 if ( self::$editor_buttons_css ) {
93 wp_print_styles('editor-buttons');
94 self::$editor_buttons_css = false;
97 if ( !empty($set['editor_css']) )
98 echo $set['editor_css'] . "\n";
100 if ( !empty($buttons) || $set['media_buttons'] ) {
101 echo '<div id="wp-' . $editor_id . '-editor-tools" class="wp-editor-tools">';
104 if ( $set['media_buttons'] ) {
105 self::$has_medialib = true;
107 if ( !function_exists('media_buttons') )
108 include(ABSPATH . 'wp-admin/includes/media.php');
110 echo '<div id="wp-' . $editor_id . '-media-buttons" class="hide-if-no-js wp-media-buttons">';
111 do_action('media_buttons', $editor_id);
117 $the_editor = apply_filters('the_editor', '<div id="wp-' . $editor_id . '-editor-container" class="wp-editor-container"><textarea' . $editor_class . $rows . $tabindex . ' cols="40" name="' . $set['textarea_name'] . '" id="' . $editor_id . '">%s</textarea></div>');
118 $content = apply_filters('the_editor_content', $content);
120 printf($the_editor, $content);
123 self::editor_settings($editor_id, $set);
126 public static function editor_settings($editor_id, $set) {
127 global $editor_styles;
130 if ( empty(self::$first_init) ) {
132 add_action( 'admin_print_footer_scripts', array( __CLASS__, 'editor_js'), 50 );
133 add_action( 'admin_footer', array( __CLASS__, 'enqueue_scripts'), 1 );
135 add_action( 'wp_print_footer_scripts', array( __CLASS__, 'editor_js'), 50 );
136 add_action( 'wp_footer', array( __CLASS__, 'enqueue_scripts'), 1 );
140 if ( self::$this_quicktags ) {
147 if ( is_array($set['quicktags']) )
148 $qtInit = array_merge($qtInit, $set['quicktags']);
150 if ( empty($qtInit['buttons']) )
151 $qtInit['buttons'] = 'strong,em,link,block,del,ins,img,ul,ol,li,code,more,spell,close';
154 $qtInit['buttons'] .= ',fullscreen';
156 $qtInit = apply_filters('quicktags_settings', $qtInit, $editor_id);
157 self::$qt_settings[$editor_id] = $qtInit;
159 self::$qt_buttons = array_merge( self::$qt_buttons, explode(',', $qtInit['buttons']) );
162 if ( self::$this_tinymce ) {
164 if ( empty(self::$first_init) ) {
165 self::$baseurl = includes_url('js/tinymce');
166 self::$mce_locale = $mce_locale = ( '' == get_locale() ) ? 'en' : strtolower( substr(get_locale(), 0, 2) ); // only ISO 639-1
167 $no_captions = (bool) apply_filters( 'disable_captions', '' );
168 $plugins = array( 'inlinepopups', 'spellchecker', 'tabfocus', 'paste', 'media', 'fullscreen', 'wordpress', 'wpeditimage', 'wpgallery', 'wplink', 'wpdialogs' );
171 if ( $set['teeny'] ) {
172 self::$plugins = $plugins = apply_filters( 'teeny_mce_plugins', array('inlinepopups', 'fullscreen', 'wordpress', 'wplink', 'wpdialogs'), $editor_id );
176 The following filter takes an associative array of external plugins for TinyMCE in the form 'plugin_name' => 'url'.
177 It adds the plugin's name to TinyMCE's plugins init and the call to PluginManager to load the plugin.
178 The url should be absolute and should include the js file name to be loaded. Example:
179 array( 'myplugin' => 'http://my-site.com/wp-content/plugins/myfolder/mce_plugin.js' )
180 If the plugin uses a button, it should be added with one of the "$mce_buttons" filters.
182 $mce_external_plugins = apply_filters('mce_external_plugins', array());
185 if ( ! empty($mce_external_plugins) ) {
188 The following filter loads external language files for TinyMCE plugins.
189 It takes an associative array 'plugin_name' => 'path', where path is the
190 include path to the file. The language file should follow the same format as
191 /tinymce/langs/wp-langs.php and should define a variable $strings that
192 holds all translated strings.
193 When this filter is not used, the function will try to load {mce_locale}.js.
194 If that is not found, en.js will be tried next.
196 $mce_external_languages = apply_filters('mce_external_languages', array());
198 $loaded_langs = array();
201 if ( ! empty($mce_external_languages) ) {
202 foreach ( $mce_external_languages as $name => $path ) {
203 if ( @is_file($path) && @is_readable($path) ) {
205 $ext_plugins .= $strings . "\n";
206 $loaded_langs[] = $name;
211 foreach ( $mce_external_plugins as $name => $url ) {
213 if ( is_ssl() ) $url = str_replace('http://', 'https://', $url);
215 $plugins[] = '-' . $name;
217 $plugurl = dirname($url);
218 $strings = $str1 = $str2 = '';
219 if ( ! in_array($name, $loaded_langs) ) {
220 $path = str_replace( content_url(), '', $plugurl );
221 $path = WP_CONTENT_DIR . $path . '/langs/';
223 if ( function_exists('realpath') )
224 $path = trailingslashit( realpath($path) );
226 if ( @is_file($path . $mce_locale . '.js') )
227 $strings .= @file_get_contents($path . $mce_locale . '.js') . "\n";
229 if ( @is_file($path . $mce_locale . '_dlg.js') )
230 $strings .= @file_get_contents($path . $mce_locale . '_dlg.js') . "\n";
232 if ( 'en' != $mce_locale && empty($strings) ) {
233 if ( @is_file($path . 'en.js') ) {
234 $str1 = @file_get_contents($path . 'en.js');
235 $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str1, 1 ) . "\n";
238 if ( @is_file($path . 'en_dlg.js') ) {
239 $str2 = @file_get_contents($path . 'en_dlg.js');
240 $strings .= preg_replace( '/([\'"])en\./', '$1' . $mce_locale . '.', $str2, 1 ) . "\n";
244 if ( ! empty($strings) )
245 $ext_plugins .= "\n" . $strings . "\n";
248 $ext_plugins .= 'tinyMCEPreInit.load_ext("' . $plugurl . '", "' . $mce_locale . '");' . "\n";
249 $ext_plugins .= 'tinymce.PluginManager.load("' . $name . '", "' . $url . '");' . "\n";
251 self::$ext_plugins .= $ext_plugins;
255 $plugins = array_unique( apply_filters('tiny_mce_plugins', $plugins) );
259 $plugins[] = 'wpfullscreen';
261 self::$plugins = $plugins;
264 The following filter allows localization scripts to change the languages displayed in the spellchecker's drop-down menu.
265 By default it uses Google's spellchecker API, but can be configured to use PSpell/ASpell if installed on the server.
266 The + sign marks the default language. More information:
267 http://wiki.moxiecode.com/index.php/TinyMCE:Plugins/spellchecker
269 $mce_spellchecker_languages = apply_filters('mce_spellchecker_languages', '+English=en,Danish=da,Dutch=nl,Finnish=fi,French=fr,German=de,Italian=it,Polish=pl,Portuguese=pt,Spanish=es,Swedish=sv');
271 self::$first_init = array(
274 'theme' => 'advanced',
275 'skin' => 'wp_theme',
276 'language' => self::$mce_locale,
277 'spellchecker_languages' => $mce_spellchecker_languages,
278 'theme_advanced_toolbar_location' => 'top',
279 'theme_advanced_toolbar_align' => 'left',
280 'theme_advanced_statusbar_location' => 'bottom',
281 'theme_advanced_resizing' => true,
282 'theme_advanced_resize_horizontal' => false,
283 'dialog_type' => 'modal',
286 {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'left'}},
287 {selector : 'img,table', classes : 'alignleft'}
290 {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'center'}},
291 {selector : 'img,table', classes : 'aligncenter'}
294 {selector : 'p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li', styles : {textAlign : 'right'}},
295 {selector : 'img,table', classes : 'alignright'}
297 strikethrough : {inline : 'del'}
299 'relative_urls' => false,
300 'remove_script_host' => false,
301 'convert_urls' => false,
302 'remove_linebreaks' => true,
303 'gecko_spellcheck' => true,
304 'keep_styles' => false,
305 'entities' => '38,amp,60,lt,62,gt',
306 'accessibility_focus' => true,
307 'tabfocus_elements' => 'major-publishing-actions',
308 'media_strict' => false,
309 'paste_remove_styles' => true,
310 'paste_remove_spans' => true,
311 'paste_strip_class_attributes' => 'all',
312 'paste_text_use_dialog' => true,
313 'extended_valid_elements' => 'article[*],aside[*],audio[*],canvas[*],command[*],datalist[*],details[*],embed[*],figcaption[*],figure[*],footer[*],header[*],hgroup[*],keygen[*],mark[*],meter[*],nav[*],output[*],progress[*],section[*],source[*],summary,time[*],video[*],wbr',
314 'wpeditimage_disable_captions' => $no_captions,
315 'wp_fullscreen_content_css' => self::$baseurl . '/plugins/wpfullscreen/css/wp-fullscreen.css',
316 'plugins' => implode( ',', $plugins )
319 // load editor_style.css if the current theme supports it
320 if ( ! empty( $editor_styles ) && is_array( $editor_styles ) ) {
322 $editor_styles = array_unique($editor_styles);
323 $style_uri = get_stylesheet_directory_uri();
324 if ( ! is_child_theme() ) {
325 foreach ( $editor_styles as $file )
326 $mce_css[] = "$style_uri/$file";
328 $style_dir = get_stylesheet_directory();
329 $template_uri = get_template_directory_uri();
330 $template_dir = get_template_directory();
332 foreach ( $editor_styles as $file ) {
333 if ( file_exists( "$template_dir/$file" ) )
334 $mce_css[] = "$template_uri/$file";
337 foreach ( $editor_styles as $file ) {
338 if ( file_exists( "$style_dir/$file" ) )
339 $mce_css[] = "$style_uri/$file";
342 $mce_css = implode( ',', $mce_css );
347 $mce_css = trim( apply_filters( 'mce_css', $mce_css ), ' ,' );
349 if ( ! empty($mce_css) )
350 self::$first_init['content_css'] = $mce_css;
353 if ( $set['teeny'] ) {
354 $mce_buttons = apply_filters( 'teeny_mce_buttons', array('bold', 'italic', 'underline', 'blockquote', 'separator', 'strikethrough', 'bullist', 'numlist', 'justifyleft', 'justifycenter', 'justifyright', 'undo', 'redo', 'link', 'unlink', 'fullscreen'), $editor_id );
355 $mce_buttons_2 = $mce_buttons_3 = $mce_buttons_4 = array();
357 $mce_buttons = apply_filters('mce_buttons', array('bold', 'italic', 'strikethrough', '|', 'bullist', 'numlist', 'blockquote', '|', 'justifyleft', 'justifycenter', 'justifyright', '|', 'link', 'unlink', 'wp_more', '|', 'spellchecker', 'fullscreen', 'wp_adv' ), $editor_id);
358 $mce_buttons_2 = apply_filters('mce_buttons_2', array( 'formatselect', 'underline', 'justifyfull', 'forecolor', '|', 'pastetext', 'pasteword', 'removeformat', '|', 'charmap', '|', 'outdent', 'indent', '|', 'undo', 'redo', 'wp_help' ), $editor_id);
359 $mce_buttons_3 = apply_filters('mce_buttons_3', array(), $editor_id);
360 $mce_buttons_4 = apply_filters('mce_buttons_4', array(), $editor_id);
364 // replace the first 'fullscreen' with 'wp_fullscreen'
365 if ( ($key = array_search('fullscreen', $mce_buttons)) !== false )
366 $mce_buttons[$key] = 'wp_fullscreen';
367 elseif ( ($key = array_search('fullscreen', $mce_buttons_2)) !== false )
368 $mce_buttons_2[$key] = 'wp_fullscreen';
369 elseif ( ($key = array_search('fullscreen', $mce_buttons_3)) !== false )
370 $mce_buttons_3[$key] = 'wp_fullscreen';
371 elseif ( ($key = array_search('fullscreen', $mce_buttons_4)) !== false )
372 $mce_buttons_4[$key] = 'wp_fullscreen';
376 'elements' => $editor_id,
377 'wpautop' => (bool) $set['wpautop'],
378 'remove_linebreaks' => (bool) $set['wpautop'],
379 'apply_source_formatting' => (bool) !$set['wpautop'],
380 'theme_advanced_buttons1' => implode($mce_buttons, ','),
381 'theme_advanced_buttons2' => implode($mce_buttons_2, ','),
382 'theme_advanced_buttons3' => implode($mce_buttons_3, ','),
383 'theme_advanced_buttons4' => implode($mce_buttons_4, ',')
387 $mceInit = array_merge(self::$first_init, $mceInit);
389 if ( is_array($set['tinymce']) )
390 $mceInit = array_merge($mceInit, $set['tinymce']);
392 // For people who really REALLY know what they're doing with TinyMCE
393 // You can modify initArray to add, remove, change elements of the config before tinyMCE.init
394 // Setting "valid_elements", "invalid_elements" and "extended_valid_elements" can be done through this filter.
395 // Best is to use the default cleanup by not specifying valid_elements, as TinyMCE contains full set of XHTML 1.0.
396 if ( $set['teeny'] ) {
397 $mceInit = apply_filters('teeny_mce_before_init', $mceInit, $editor_id);
399 $mceInit = apply_filters('tiny_mce_before_init', $mceInit, $editor_id);
402 if ( empty($mceInit['theme_advanced_buttons3']) && !empty($mceInit['theme_advanced_buttons4']) ) {
403 $mceInit['theme_advanced_buttons3'] = $mceInit['theme_advanced_buttons4'];
404 $mceInit['theme_advanced_buttons4'] = '';
407 self::$mce_settings[$editor_id] = $mceInit;
408 } // end if self::$this_tinymce
411 private static function _parse_init($init) {
414 foreach ( $init as $k => $v ) {
416 $val = $v ? 'true' : 'false';
417 $options .= $k . ':' . $val . ',';
419 } elseif ( !empty($v) && is_string($v) && ( ('{' == $v{0} && '}' == $v{strlen($v) - 1}) || ('[' == $v{0} && ']' == $v{strlen($v) - 1}) || preg_match('/^\(?function ?\(/', $v) ) ) {
420 $options .= $k . ':' . $v . ',';
423 $options .= $k . ':"' . $v . '",';
426 return '{' . trim( $options, ' ,' ) . '}';
429 public static function enqueue_scripts() {
430 wp_enqueue_script('word-count');
432 if ( self::$has_tinymce )
433 wp_enqueue_script('editor');
435 if ( self::$has_quicktags )
436 wp_enqueue_script('quicktags');
438 if ( in_array('wplink', self::$plugins, true) || in_array('link', self::$qt_buttons, true) ) {
439 wp_enqueue_script('wplink');
440 wp_enqueue_script('wpdialogs-popup');
441 wp_enqueue_style('wp-jquery-ui-dialog');
444 if ( in_array('wpfullscreen', self::$plugins, true) || in_array('fullscreen', self::$qt_buttons, true) )
445 wp_enqueue_script('wp-fullscreen');
447 if ( self::$has_medialib ) {
449 wp_enqueue_script('media-upload');
453 public static function editor_js() {
454 global $tinymce_version, $concatenate_scripts, $compress_scripts;
457 * Filter "tiny_mce_version" is deprecated
459 * The tiny_mce_version filter is not needed since external plugins are loaded directly by TinyMCE.
460 * These plugins can be refreshed by appending query string to the URL passed to "mce_external_plugins" filter.
461 * 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).
463 $version = 'ver=' . $tinymce_version;
464 $tmce_on = !empty(self::$mce_settings);
466 if ( ! isset($concatenate_scripts) )
467 script_concat_settings();
469 $compressed = $compress_scripts && $concatenate_scripts && isset($_SERVER['HTTP_ACCEPT_ENCODING'])
470 && false !== stripos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
472 if ( $tmce_on && 'en' != self::$mce_locale )
473 include_once(ABSPATH . WPINC . '/js/tinymce/langs/wp-langs.php');
475 $mceInit = $qtInit = '';
477 foreach ( self::$mce_settings as $editor_id => $init ) {
478 $options = self::_parse_init( $init );
479 $mceInit .= "'$editor_id':{$options},";
481 $mceInit = '{' . trim($mceInit, ',') . '}';
486 if ( !empty(self::$qt_settings) ) {
487 foreach ( self::$qt_settings as $editor_id => $init ) {
488 $options = self::_parse_init( $init );
489 $qtInit .= "'$editor_id':{$options},";
491 $qtInit = '{' . trim($qtInit, ',') . '}';
497 'plugins' => implode( ',', self::$plugins ),
498 'theme' => 'advanced',
499 'language' => self::$mce_locale
502 do_action('before_wp_tiny_mce', self::$mce_settings);
505 <script type="text/javascript">
507 base : "<?php echo self::$baseurl; ?>",
509 query : "<?php echo $version; ?>",
510 mceInit : <?php echo $mceInit; ?>,
511 qtInit : <?php echo $qtInit; ?>,
512 ref : <?php echo self::_parse_init( $ref ); ?>,
513 load_ext : function(url,lang){var sl=tinymce.ScriptLoader;sl.markDone(url+'/langs/'+lang+'.js');sl.markDone(url+'/langs/'+lang+'_dlg.js');}
518 $baseurl = self::$baseurl;
522 echo "<script type='text/javascript' src='{$baseurl}/wp-tinymce.php?c=1&$version'></script>\n";
524 echo "<script type='text/javascript' src='{$baseurl}/tiny_mce.js?$version'></script>\n";
526 if ( 'en' != self::$mce_locale && isset($lang) )
527 echo "<script type='text/javascript'>\n$lang\n</script>\n";
529 echo "<script type='text/javascript' src='{$baseurl}/langs/wp-langs-en.js?$version'></script>\n";
533 <script type="text/javascript">
535 var init, ed, qt, first_init, mce = <?php echo wp_default_editor() == 'tinymce' ? 'true' : 'false'; ?>;
537 if ( typeof(tinymce) == 'object' ) {
538 // mark wp_theme/ui.css as loaded
539 tinymce.DOM.files[tinymce.baseURI.getURI() + '/themes/advanced/skins/wp_theme/ui.css'] = true;
541 for ( ed in tinyMCEPreInit.mceInit ) {
543 init = tinyMCEPreInit.mceInit[ed] = tinymce.extend( {}, first_init, tinyMCEPreInit.mceInit[ed] );
545 init = first_init = tinyMCEPreInit.mceInit[ed];
549 try { tinymce.init(init); } catch(e){}
553 if ( typeof(QTags) == 'function' ) {
554 for ( qt in tinyMCEPreInit.qtInit ) {
555 try { quicktags( tinyMCEPreInit.qtInit[qt] ); } catch(e){}
562 jQuery('.wp-editor-wrap').mousedown(function(e){
563 wpActiveEditor = this.id.slice(3, -5);
568 if ( self::$ext_plugins )
569 echo self::$ext_plugins . "\n";
571 if ( ! $compressed && $tmce_on ) {
573 (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');}});})();
578 echo 'var ajaxurl = "' . admin_url('admin-ajax.php') . '";';
583 if ( in_array('wplink', self::$plugins, true) || in_array('link', self::$qt_buttons, true) )
584 self::wp_link_dialog();
586 if ( in_array('wpfullscreen', self::$plugins, true) || in_array('fullscreen', self::$qt_buttons, true) )
587 self::wp_fullscreen_html();
589 do_action('after_wp_tiny_mce', self::$mce_settings);
592 public static function wp_fullscreen_html() {
593 global $content_width, $post;
595 $width = isset($content_width) && 800 > $content_width ? $content_width : 800;
596 $width = $width + 22; // compensate for the padding and border
597 $dfw_width = get_user_setting( 'dfw_width', $width );
598 $save = isset($post->post_status) && $post->post_status == 'publish' ? __('Update') : __('Save');
600 <div id="wp-fullscreen-body">
601 <div id="fullscreen-topbar">
602 <div id="wp-fullscreen-toolbar">
603 <div id="wp-fullscreen-close"><a href="#" onclick="fullscreen.off();return false;"><?php _e('Exit fullscreen'); ?></a></div>
604 <div id="wp-fullscreen-central-toolbar" style="width:<?php echo $width; ?>px;">
606 <div id="wp-fullscreen-mode-bar"><div id="wp-fullscreen-modes">
607 <a href="#" onclick="fullscreen.switchmode('tinymce');return false;"><?php _e('Visual'); ?></a>
608 <a href="#" onclick="fullscreen.switchmode('html');return false;"><?php _e('HTML'); ?></a>
611 <div id="wp-fullscreen-button-bar"><div id="wp-fullscreen-buttons" class="wp_themeSkin">
615 // format: title, onclick, show in both editors
616 'bold' => array( 'title' => __('Bold (Ctrl + B)'), 'onclick' => 'fullscreen.b();', 'both' => false ),
617 'italic' => array( 'title' => __('Italic (Ctrl + I)'), 'onclick' => 'fullscreen.i();', 'both' => false ),
619 'bullist' => array( 'title' => __('Unordered list (Alt + Shift + U)'), 'onclick' => 'fullscreen.ul();', 'both' => false ),
620 'numlist' => array( 'title' => __('Ordered list (Alt + Shift + O)'), 'onclick' => 'fullscreen.ol();', 'both' => false ),
622 'blockquote' => array( 'title' => __('Blockquote (Alt + Shift + Q)'), 'onclick' => 'fullscreen.blockquote();', 'both' => false ),
623 'image' => array( 'title' => __('Insert/edit image (Alt + Shift + M)'), 'onclick' => "fullscreen.medialib();", 'both' => true ),
625 'link' => array( 'title' => __('Insert/edit link (Alt + Shift + A)'), 'onclick' => 'fullscreen.link();', 'both' => true ),
626 'unlink' => array( 'title' => __('Unlink (Alt + Shift + S)'), 'onclick' => 'fullscreen.unlink();', 'both' => false ),
628 'help' => array( 'title' => __('Help (Alt + Shift + H)'), 'onclick' => 'fullscreen.help();', 'both' => false )
631 $buttons = apply_filters( 'wp_fullscreen_buttons', $buttons );
633 foreach ( $buttons as $button => $args ) {
634 if ( 'separator' == $args ) { ?>
635 <div><span aria-orientation="vertical" role="separator" class="mceSeparator"></span></div>
639 <div<?php if ( $args['both'] ) { ?> class="wp-fullscreen-both"<?php } ?>>
640 <a title="<?php echo $args['title']; ?>" onclick="<?php echo $args['onclick']; ?>return false;" class="mceButton mceButtonEnabled mce_<?php echo $button; ?>" href="#" id="wp_fs_<?php echo $button; ?>" role="button" aria-pressed="false">
641 <span class="mceIcon mce_<?php echo $button; ?>"></span>
649 <div id="wp-fullscreen-save">
650 <span><?php if ( $post->post_status == 'publish' ) _e('Updated.'); else _e('Saved.'); ?></span>
651 <img src="images/wpspin_light.gif" alt="" />
652 <input type="button" class="button-primary" value="<?php echo $save; ?>" onclick="fullscreen.save();" />
659 <div id="wp-fullscreen-wrap" style="width:<?php echo $dfw_width; ?>px;">
660 <?php if ( post_type_supports($post->post_type, 'title') ) { ?>
661 <label id="wp-fullscreen-title-prompt-text" for="wp-fullscreen-title"><?php echo apply_filters( 'enter_title_here', __( 'Enter title here' ), $post ); ?></label>
662 <input type="text" id="wp-fullscreen-title" value="" autocomplete="off" />
665 <div id="wp-fullscreen-container">
666 <textarea id="wp_mce_fullscreen"></textarea>
669 <div id="wp-fullscreen-status">
670 <div id="wp-fullscreen-count"><?php printf( __( 'Word count: %s' ), '<span class="word-count">0</span>' ); ?></div>
671 <div id="wp-fullscreen-tagline"><?php _e('Just write.'); ?></div>
676 <div class="fullscreen-overlay" id="fullscreen-overlay"></div>
677 <div class="fullscreen-overlay fullscreen-fader fade-600" id="fullscreen-fader"></div>
682 * Performs post queries for internal linking.
686 * @param array $args Optional. Accepts 'pagenum' and 's' (search) arguments.
687 * @return array Results.
689 public static function wp_link_query( $args = array() ) {
690 $pts = get_post_types( array( 'public' => true ), 'objects' );
691 $pt_names = array_keys( $pts );
694 'post_type' => $pt_names,
695 'suppress_filters' => true,
696 'update_post_term_cache' => false,
697 'update_post_meta_cache' => false,
698 'post_status' => 'publish',
700 'orderby' => 'post_date',
701 'posts_per_page' => 20,
704 $args['pagenum'] = isset( $args['pagenum'] ) ? absint( $args['pagenum'] ) : 1;
706 if ( isset( $args['s'] ) )
707 $query['s'] = $args['s'];
709 $query['offset'] = $args['pagenum'] > 1 ? $query['posts_per_page'] * ( $args['pagenum'] - 1 ) : 0;
712 $get_posts = new WP_Query;
713 $posts = $get_posts->query( $query );
714 // Check if any posts were found.
715 if ( ! $get_posts->post_count )
720 foreach ( $posts as $post ) {
721 if ( 'post' == $post->post_type )
722 $info = mysql2date( __( 'Y/m/d' ), $post->post_date );
724 $info = $pts[ $post->post_type ]->labels->singular_name;
728 'title' => trim( esc_html( strip_tags( get_the_title( $post ) ) ) ),
729 'permalink' => get_permalink( $post->ID ),
738 * Dialog for internal linking.
742 public static function wp_link_dialog() {
744 <div style="display:none;">
745 <form id="wp-link" tabindex="-1">
746 <?php wp_nonce_field( 'internal-linking', '_ajax_linking_nonce', false ); ?>
747 <div id="link-selector">
748 <div id="link-options">
749 <p class="howto"><?php _e( 'Enter the destination URL' ); ?></p>
751 <label><span><?php _e( 'URL' ); ?></span><input id="url-field" type="text" tabindex="10" name="href" /></label>
754 <label><span><?php _e( 'Title' ); ?></span><input id="link-title-field" type="text" tabindex="20" name="linktitle" /></label>
756 <div class="link-target">
757 <label><input type="checkbox" id="link-target-checkbox" tabindex="30" /> <?php _e( 'Open link in a new window/tab' ); ?></label>
760 <?php $show_internal = '1' == get_user_setting( 'wplink', '0' ); ?>
761 <p class="howto toggle-arrow <?php if ( $show_internal ) echo 'toggle-arrow-active'; ?>" id="internal-toggle"><?php _e( 'Or link to existing content' ); ?></p>
762 <div id="search-panel"<?php if ( ! $show_internal ) echo ' style="display:none"'; ?>>
763 <div class="link-search-wrapper">
765 <span><?php _e( 'Search' ); ?></span>
766 <input type="text" id="search-field" class="link-search-field" tabindex="60" autocomplete="off" />
767 <img class="waiting" src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" alt="" />
770 <div id="search-results" class="query-results">
772 <div class="river-waiting">
773 <img class="waiting" src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" alt="" />
776 <div id="most-recent-results" class="query-results">
777 <div class="query-notice"><em><?php _e( 'No search term specified. Showing recent items.' ); ?></em></div>
779 <div class="river-waiting">
780 <img class="waiting" src="<?php echo esc_url( admin_url( 'images/wpspin_light.gif' ) ); ?>" alt="" />
785 <div class="submitbox">
786 <div id="wp-link-cancel">
787 <a class="submitdelete deletion" href="#"><?php _e( 'Cancel' ); ?></a>
789 <div id="wp-link-update">
790 <input type="submit" tabindex="100" value="<?php esc_attr_e( 'Add Link' ); ?>" class="button-primary" id="wp-link-submit" name="wp-link-submit">