{"id":969,"date":"2013-01-04T13:16:56","date_gmt":"2013-01-04T13:16:56","guid":{"rendered":"http:\/\/blog.soton.ac.uk\/webteam\/?p=969"},"modified":"2013-01-04T13:16:56","modified_gmt":"2013-01-04T13:16:56","slug":"adding-a-custom-line-break-plugin-to-the-tinymce-wysiwyg-editor-inside-drupal-7","status":"publish","type":"post","link":"https:\/\/blog.soton.ac.uk\/webteam\/2013\/01\/04\/adding-a-custom-line-break-plugin-to-the-tinymce-wysiwyg-editor-inside-drupal-7\/","title":{"rendered":"Adding a custom Line Break Plugin to the TinyMCE WYSIWYG editor inside Drupal 7"},"content":{"rendered":"<p>This is a long title for a blog post, but it is a complicate and tricky task and I couldn&#8217;t find a complete solution, so this is a summary of how I did it. It also provides a good basis for adding other features to TinyMCE inside Drupal. First of all, the versions of the software I was working with were TinyMCE 3.5.4.1 and Drupal 7.14 (yes, we need to upgrade that!) I spent a lot of time hacking inside the Drupal WYSIWYG plugin and inside tinyMCE itself before I discovered the clean plugin-base solution. My starting point was this simple <a href=\"http:\/\/www.tinymce.com\/forum\/viewtopic.php?id=13823\">TinyMCE newline Plugin from SYNASYS MEDIA<\/a>. This didn&#8217;t work for me out of the box. I came as only compressed javascript, so I had to figure out how to decompress it first. Once I&#8217;d done that, after lots of debugging I worked out that the reason I couldn&#8217;t get it to show up inside Drupal is that you have to make a new (minimal)\u00a0 Drupal plugin to register it properly with the WYSIWYG plugin (see below). After that I worked out that they had used &#8216;&lt;br \/&gt;&#8217; which didn&#8217;t work in all circumstances so I changed it to &#8220;&lt;br \/&gt;\\n&#8221; which nearly did what I wanted but the cursor got screwed up if you did newline at the end of the text, so I tried adding ed.execCommand(&#8216;mceRepaint&#8217;,true); but that didn&#8217;t help. I kept looking at the <a href=\"http:\/\/www.tinymce.com\/wiki.php\/Command_identifiers\">list of mce commands<\/a>and spotted &#8220;mceInsertRawHTML&#8221; but that was worse. In the end I decided to ignore the glitch as it&#8217;s purely cosmetic.<\/p>\n<p>My final version is below. I&#8217;ve kept the name &#8220;smlinebreak&#8221; but I&#8217;ve bolded it so if you wanted your own name for a plugin you can see where you&#8217;d have to tweak it.<\/p>\n<pre>(function(){\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 tinymce.PluginManager.requireLangPack('<strong>smlinebreak<\/strong>');\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 tinymce.create(\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'tinymce.plugins.<strong>SMLineBreak<\/strong>Plugin',\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 {\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 init:function(ed,url){\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ed.addCommand('<strong>SMLineBreak<\/strong>',function(){\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ed.execCommand('mceInsertContent',true,\"&lt;br \/&gt;\\n\")\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 });\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ed.addButton('<strong>smlinebreak<\/strong>',{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 title:'<strong>smlinebreak<\/strong>.desc',\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 cmd:'<strong>SMLineBreak<\/strong>',\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 image:url+'\/img\/icon.gif'\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 })\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 },\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 getInfo:function(){\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 return{\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 longname:'Adapted version of SYNASYS MEDIA LineBreak',\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 author:'Christopher Gutteridge',\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 authorurl:'http:\/\/users.ecs.soton.ac.uk\/cjg\/',\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 infourl:'http:\/\/www.ecs.soton.ac.uk\/',version:\"1.0.0\"}\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 }\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 });\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 tinymce.PluginManager.add('<strong>smlinebreak<\/strong>',tinymce.plugins.<strong>SMLineBreak<\/strong>Plugin)}\r\n)();<\/pre>\n<p>which replaces the editor_plugin.js in the SMLineBreak I downloaded from <a href=\"http:\/\/synasys.de\/index.php?id=5\">http:\/\/synasys.de\/index.php?id=5<\/a>. The other files are trivial, just the image for the icon in img\/icon.gif and a language file in langs\/en.js which looks like<\/p>\n<pre>tinyMCE.addI18n('en.<strong>smlinebreak<\/strong>',{desc : 'line break'});<\/pre>\n<p>This plugin I placed in &#8230;\/sites\/all\/libraries\/tinymce\/jscripts\/tiny_mce\/plugins\/<strong>smlinebreak<\/strong> Then I had to register it, not directly with TinyMCE, but rather with the Drupal WYSIWYG plugin, using a custom Drupal module&#8230;<\/p>\n<h2>Drupal WYSIWYG Plugin<\/h2>\n<p>I gave my plugin the catchy title of &#8220;wysiwyg_linebreak&#8221;. This needs to be inserted into the filenames and function names so I&#8217;ll put it inbold for clarity, so you can see the bit that&#8217;s the module name. This module gets placed in sites\/all\/modules\/<strong>wysiwyg_linebreak<\/strong>\/ and has just two files. <strong>wysiwyg_linebreak<\/strong>.info is just the bit to tell Drupal some basics about the module. As it&#8217;s an in-house hack I&#8217;ve not put much effort into it.<\/p>\n<pre>name = TinyMCE Linebreaks\r\ndescription = Add Linebreaks to TinyMCE\r\ncore = 7.x\r\npackage = UOS<\/pre>\n<p>The last line means it gets lumped-in with all my other custom (University of Southampton) modules so they appear together in the Drupal Modules page. The module file itself is <strong>wysiwyg_linebreak<\/strong>.module and this is a PHP file which just tweaks a setting to add the option to the Drupal WYSIWYG module.<\/p>\n<pre>&lt;?php<\/pre>\n<pre>\/* Implementation of hook_wysiwyg_plugin(). *\/\r\nfunction <strong>wysiwyg_linebreak<\/strong>_wysiwyg_plugin($editor) {\r\n\u00a0 switch ($editor) {\r\n\u00a0\u00a0\u00a0 case 'tinymce':\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 return array(\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 '<strong>smlinebreak<\/strong>' =&gt; array(\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'load' =&gt; TRUE,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'internal' =&gt; TRUE,\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 'buttons' =&gt; array(\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 '<strong>smlinebreak<\/strong>' =&gt; t('SM Line Break'),\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ),\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 ),\r\n\u00a0\u00a0\u00a0\u00a0\u00a0 );\r\n\u00a0 }\r\n}<\/pre>\n<pre>?&gt;<\/pre>\n<p>&#8230; and that seemed to be enough. To enable it you first need to go into the Drupal Modules page and enable the module, then go to <em>Administration \u00bb Configuration \u00bb Content authoring \u00bb WYSIWYG Profiles<\/em> and enable the new button in the buttons\/plugin section. Then if you&#8217;re very lucky it might work.<\/p>\n<h2>Summary<\/h2>\n<p>It&#8217;s possible, even easy, to add new features to the editor inside Drupal. I&#8217;ve written this out long form as I couldn&#8217;t find a worked example myself of how to add such a feature, and it took me enough time I hope this may give a few short cuts to people needing this or similar features.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This is a long title for a blog post, but it is a complicate and tricky task and I couldn&#8217;t find a complete solution, so this is a summary of how I did it. It also provides a good basis for adding other features to TinyMCE inside Drupal. First of all, the versions of the [&hellip;]<\/p>\n","protected":false},"author":5,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[4231,6481],"tags":[],"class_list":["post-969","post","type-post","status-publish","format-standard","hentry","category-drupal","category-javascript"],"_links":{"self":[{"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/posts\/969","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/comments?post=969"}],"version-history":[{"count":2,"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/posts\/969\/revisions"}],"predecessor-version":[{"id":971,"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/posts\/969\/revisions\/971"}],"wp:attachment":[{"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/media?parent=969"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/categories?post=969"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/tags?post=969"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}