├── README.md ├── class.shortcode.php ├── js ├── boutique-banner-editor-view.js └── mce-button-boutique-banner-inline.js ├── style.content.css ├── templates └── tmpl-editor-boutique-banner.html └── views └── dtbake_shortcode_banner_view.php /README.md: -------------------------------------------------------------------------------- 1 | note: updated to work with WordPress 4.2 2 | 3 | WordPress custom TinyMCE view and shortcode editor 4 | ======================================= 5 | 6 | This file converts a plain WordPress shortcode.... 7 | 8 | ![plain shortocde](http://i.imgur.com/cFs5lJv.png) 9 | 10 | ... into a nice custom MCE view that matches the frontend ... 11 | 12 | ![nice wp mce view](http://i.imgur.com/XxVUdba.png) 13 | 14 | ... and lets you click on it ... 15 | 16 | ![edit delete buttons](http://i.imgur.com/eP3Ed46.png) 17 | 18 | ... and easily edit the shortcode through a popup ... 19 | 20 | ![edit wordpress shortcode in popup](http://i.imgur.com/Q0pnFN2.png) 21 | 22 | .. also adds a button for inserting a new shortcode: 23 | 24 | ![tinymce shortcode insert button](http://i.imgur.com/Qv0bO1h.png) 25 | -------------------------------------------------------------------------------- /class.shortcode.php: -------------------------------------------------------------------------------- 1 | false, 48 | 'title' => 'Special:', 49 | 'link' => '', 50 | 'linkhref' => '', 51 | ), 52 | $atts 53 | ); 54 | $sc_atts['banner_id'] = strtolower(preg_replace('#\W+#','', $sc_atts['title'])); // lets put everything in the view-data object 55 | $sc_atts = (object) $sc_atts; 56 | 57 | // Use Output Buffering feature to have PHP use it's own enging for templating 58 | ob_start(); 59 | include dirname(__FILE__).'/views/dtbaker_shortcode_banner_view.php'; 60 | return ob_get_clean(); 61 | } 62 | 63 | public function mce_plugin($plugin_array){ 64 | $plugin_array['dtbaker_mce_banner'] = plugins_url( 'js/mce-button-boutique-banner-inline.js', __FILE__ ); 65 | return $plugin_array; 66 | } 67 | public function mce_button($buttons){ 68 | array_push($buttons, 'dtbaker_mce_banner_button'); 69 | return $buttons; 70 | } 71 | /** 72 | * Outputs the view inside the wordpress editor. 73 | */ 74 | public function print_media_templates() { 75 | if ( ! isset( get_current_screen()->id ) || get_current_screen()->base != 'post' ) 76 | return; 77 | include_once dirname(__FILE__).'/templates/tmpl-editor-boutique-banner.html'; 78 | } 79 | public function admin_head() { 80 | $current_screen = get_current_screen(); 81 | if ( ! isset( $current_screen->id ) || $current_screen->base !== 'post' ) { 82 | return; 83 | } 84 | 85 | wp_enqueue_script( 'boutique-banner-editor-view', plugins_url( 'js/boutique-banner-editor-view.js', __FILE__ ), array( 'shortcode', 'wp-util', 'jquery' ), false, true ); 86 | } 87 | } 88 | 89 | dtbaker_Shortcode_Banner::get_instance()->init(); 90 | 91 | 92 | -------------------------------------------------------------------------------- /js/boutique-banner-editor-view.js: -------------------------------------------------------------------------------- 1 | /* global tinyMCE */ 2 | (function($){ 3 | var media = wp.media, shortcode_string = 'boutique_banner'; 4 | wp.mce = wp.mce || {}; 5 | wp.mce.boutique_banner = { 6 | shortcode_data: {}, 7 | template: media.template( 'editor-boutique-banner' ), 8 | getContent: function() { 9 | var options = this.shortcode.attrs.named; 10 | options.innercontent = this.shortcode.content; 11 | return this.template(options); 12 | }, 13 | View: { // before WP 4.2: 14 | template: media.template( 'editor-boutique-banner' ), 15 | postID: $('#post_ID').val(), 16 | initialize: function( options ) { 17 | this.shortcode = options.shortcode; 18 | wp.mce.boutique_banner.shortcode_data = this.shortcode; 19 | }, 20 | getHtml: function() { 21 | var options = this.shortcode.attrs.named; 22 | options.innercontent = this.shortcode.content; 23 | return this.template(options); 24 | } 25 | }, 26 | edit: function( data ) { 27 | var shortcode_data = wp.shortcode.next(shortcode_string, data); 28 | var values = shortcode_data.shortcode.attrs.named; 29 | values.innercontent = shortcode_data.shortcode.content; 30 | wp.mce.boutique_banner.popupwindow(tinyMCE.activeEditor, values); 31 | }, 32 | // this is called from our tinymce plugin, also can call from our "edit" function above 33 | // wp.mce.boutique_banner.popupwindow(tinyMCE.activeEditor, "bird"); 34 | popupwindow: function(editor, values, onsubmit_callback){ 35 | values = values || []; 36 | if(typeof onsubmit_callback !== 'function'){ 37 | onsubmit_callback = function( e ) { 38 | // Insert content when the window form is submitted (this also replaces during edit, handy!) 39 | var args = { 40 | tag : shortcode_string, 41 | type : e.data.innercontent.length ? 'closed' : 'single', 42 | content : e.data.innercontent, 43 | attrs : { 44 | title : e.data.title, 45 | link : e.data.link, 46 | linkhref : e.data.linkhref 47 | } 48 | }; 49 | editor.insertContent( wp.shortcode.string( args ) ); 50 | }; 51 | } 52 | editor.windowManager.open( { 53 | title: 'Banner', 54 | body: [ 55 | { 56 | type: 'textbox', 57 | name: 'title', 58 | label: 'Title', 59 | value: values.title 60 | }, 61 | { 62 | type: 'textbox', 63 | name: 'link', 64 | label: 'Button Text', 65 | value: values.link 66 | }, 67 | { 68 | type: 'textbox', 69 | subtype: 'url', 70 | name: 'linkhref', 71 | label: 'Button URL', 72 | value: values.linkhref 73 | }, 74 | { 75 | type: 'textbox', 76 | name: 'innercontent', 77 | label: 'Content', 78 | value: values.innercontent 79 | } 80 | ], 81 | onsubmit: onsubmit_callback 82 | } ); 83 | } 84 | }; 85 | wp.mce.views.register( shortcode_string, wp.mce.boutique_banner ); 86 | }(jQuery)); 87 | -------------------------------------------------------------------------------- /js/mce-button-boutique-banner-inline.js: -------------------------------------------------------------------------------- 1 | /* global tinymce */ 2 | ( function() { 3 | tinymce.PluginManager.add( 'dtbaker_mce_banner', function( editor ) { 4 | editor.addButton( 'dtbaker_mce_banner_button', { 5 | text: 'Banner', 6 | icon: false, 7 | onclick: function() { 8 | wp.mce.boutique_banner.popupwindow(editor); 9 | } 10 | }); 11 | }); 12 | })(); 13 | -------------------------------------------------------------------------------- /style.content.css: -------------------------------------------------------------------------------- 1 | 2 | .full_banner{ 3 | clear:both; 4 | margin: 10px 0 2em 0; 5 | padding: 7px 8px 0 8px; 6 | background-image: url(images/dot-box-left.png), url(images/dot-box-right.png), url(images/dot-box-tile.png); 7 | background-repeat: no-repeat, no-repeat, repeat-x; 8 | background-position: left top, right top, left top; 9 | background-origin: border-box,border-box,padding-box; 10 | background-clip: border-box,border-box,padding-box; 11 | border-left: 12px solid transparent; 12 | border-right: 12px solid transparent; 13 | background-size: 12px 33px, 12px 33px, 3px 33px; 14 | height: 33px; 15 | } 16 | .full_banner .link{ 17 | float:right; 18 | } 19 | .full_banner .title{ 20 | font-size: 1.4em; 21 | margin: 0px 8px 0 0px; 22 | font-weight: normal; 23 | display: inline-block; 24 | float: left; 25 | padding: 0; 26 | background: url(images/bird-yellow.png) no-repeat top left; 27 | background-size: 25px 23px; 28 | padding-left: 37px; 29 | } 30 | .full_banner .content{ 31 | font-size: 1.4em; 32 | margin: 1px 0 0 0px; 33 | display: inline-block; 34 | float: left; 35 | padding: 0; 36 | color: #5799a7; 37 | } 38 | -------------------------------------------------------------------------------- /templates/tmpl-editor-boutique-banner.html: -------------------------------------------------------------------------------- 1 | 13 | -------------------------------------------------------------------------------- /views/dtbake_shortcode_banner_view.php: -------------------------------------------------------------------------------- 1 | 8 | --------------------------------------------------------------------------------