Перейти к основному содержанию.

Nucleus toolbar in comments [plugin v. 0.1]



This version is outdated. Please follow the link to version 0.3.


A hack may work but I won't like it ever. Taiga hunters always leave food and fire stock for those who will come to the outpost later. If one does some coding he\she shall leave maintainable code for those who will be in charge later on.

So, here follows a conventional Nucleus plugin to replace the hack.

(1) File NP_CommentButtons.php goes to Nucleus plugin directory. Typically, it is /nucleus/plugins/

  1. <?php
  2.  
  3. class NP_CommentButtons extends NucleusPlugin
  4. {
  5. // name of plugin
  6. function getName()
  7. {
  8. return 'CommentButtons';
  9. }
  10. // author of plugin
  11. function getAuthor()
  12. {
  13. return 'maxirmx';
  14. }
  15. // an URL to the plugin website
  16. // can also be of the form mailto:foo@bar.com
  17. function getURL()
  18. {
  19. return 'mailto:maxirmx@mail.ru';
  20. }
  21. // version of the plugin
  22. function getVersion()
  23. {
  24. return '0.1';
  25. }
  26. // a description to be shown on the installed plugins listing
  27. function getDescription()
  28. {
  29. return 'This plugin provides Bold, Italic, Link and Image buttons at Nucleus comments form';
  30. }
  31. function supportsFeature ($what)
  32. {
  33. switch ($what)
  34. {
  35. case 'SqlTablePrefix':
  36. return 1;
  37. default:
  38. return 0;
  39. }
  40. }
  41. function getEventList()
  42. {
  43. return array('FormExtra', 'PreComment', 'PreAddComment', 'PreUpdateComment');
  44. }
  45. function addJsButton($fn, $img)
  46. {
  47. global $CONF;
  48. echo " <img class=\"jsbutton\"\n";
  49. echo " onmouseover=\"BtnHighlight(this);\"\n";
  50. echo " onmouseout=\"BtnNormal(this);\"\n";
  51. echo " onclick=\"" . $fn . "()\"\n";
  52. echo " src=\"" . $CONF['AdminURL'] . "images/" .
  53. $img . ".gif\" alt=\"\" width=\"16\" height=\"16\"/>\n";
  54. }
  55.  
  56. function addJsButtonSpacer()
  57. {
  58. echo " <span class=\"jsbuttonspacer\">\n";
  59. echo " </span>\n";
  60. }
  61.  
  62. function addJsAttachEvent($evnt)
  63. {
  64. echo " if (refCT." . $evnt . ") refCT." . $evnt .
  65. "onkeyup = function () { refCT." . $evnt . "(); storeCaret(refCT); };\n";
  66. echo " else refCT." . $evnt . " = function () { storeCaret(refCT); };\n";
  67. }
  68.  
  69. function event_FormExtra(&$data)
  70. {
  71. global $CONF, $member;
  72. if ($data['type'] == 'commentform-loggedin')
  73. {
  74.  
  75. echo "\n <!-- Start NP_CommentButtons -->\n";
  76. echo " <script type=\"text/javascript\"\n";
  77. echo " src=\"" . $this->getAdminURL() . "tinyedit.js\">\n";
  78. echo " </script>\n";
  79. echo " <div id = \"nucleus_cf_buttonbar\" class=\"jsbuttonbar\" name=\"buttonbar\">\n";
  80. echo " <br />\n";
  81. // *** The next three lines are needed if bold and italic buttons are supported
  82. // $this->addJsButton('boldThis','button-bold');
  83. // $this->addJsButton('italicThis','button-italic');
  84. // $this->addJsButtonSpacer();
  85. $this->addJsButton('ahrefThis','button-link');
  86. $this->addJsButton('addMedia','button-media');
  87.  
  88. echo " <br />\n";
  89. echo " <br />\n";
  90. echo " </div>\n";
  91.  
  92. echo " <script type=\"text/javascript\">\n";
  93. echo " refCT = document.getElementById('nucleus_cf_body');\n";
  94. echo " refBtB = document.getElementById('nucleus_cf_buttonbar');\n";
  95. echo " refParent = refCT.parentNode;\n";
  96. echo " refBtB = refParent.removeChild(refBtB);\n";
  97. echo " refParent.insertBefore(refBtB,refCT);\n";
  98.  
  99. $this->addJsAttachEvent('onkeyup');
  100. $this->addJsAttachEvent('onclick');
  101. $this->addJsAttachEvent('onselect');
  102.  
  103. echo " setMediaUrl(\"" . $CONF['MediaURL'] . "\");\n";
  104. echo " setMediaPopupURL(\"" . $CONF['AdminURL'] . "\");\n";
  105. echo " setRefText(refCT);\n";
  106. if ($member->isLoggedIn())
  107. echo " setAuthorId(" . $member->getId() .");\n";
  108.  
  109. echo " </script>\n";
  110. echo " <!-- End NP_CommentButtons -->\n\n";
  111.  
  112. }
  113. }
  114.  
  115. function doAllDirtyJob(&$data)
  116. {
  117. $data['comment']['body'] = preg_replace ('/\>.+\>\&quot\;\&gt\;/','/>',$data['comment']['body']);
  118.  
  119. $search = array (
  120. '&lt;a href=&quot;', '&lt;/a&gt;',
  121. '&lt;%', '%&gt;',
  122. // *** The next two lines are needed if bold and italic buttons are supported
  123. // '&lt;b&gt;', '&lt;/b&gt;',
  124. // '&lt;i&gt;', '&lt;/i&gt;'
  125. );
  126. $replace = array ('','</a>',
  127. '<%','%>',
  128. // *** The next two lines are needed if bold and italic buttons are supported
  129. // '<b>','</b>',
  130. // '<i>','</i>'
  131. );
  132. $data['comment']['body'] = str_replace($search, $replace, $data['comment']['body']);
  133. }
  134.  
  135. function event_PreUpdateComment(&$data)
  136. {
  137. $this->doAllDirtyJob(&$data);
  138. }
  139.  
  140. function event_PreAddComment(&$data)
  141. {
  142. $this->doAllDirtyJob(&$data);
  143. }
  144.  
  145. function createPopupLink($memberid, $arg)
  146. {
  147. global $CONF;
  148. $args = explode('|', $arg);
  149.  
  150. // select private collection when no collection given
  151. if (!strstr($args[0],'/'))
  152. {
  153. $args[0] = $memberid . '/' . $args[0];
  154. }
  155.  
  156. $width = $args[1];
  157. $height = $args[2];
  158. $rawpopuplink = $CONF['Self'] . "?imagepopup=" . htmlspecialchars($args[0]) .
  159. "&amp;width=$width&amp;height=$height&amp;imagetext=" . urlencode(htmlspecialchars($args[3]));
  160. $popupcode = "window.open(this.href,'imagepopup'," .
  161. "'status=no,toolbar=no,scrollbars=no,resizable=yes,width=$width,height=$height');return false;";
  162. $popuptext = htmlspecialchars($args[3]);
  163. $popuplink = '<a href="' . $rawpopuplink. '" onclick="'. $popupcode.'" >' . $popuptext . '</a>';
  164. return $popuplink;
  165. }
  166. function createImageLink($memberid, $arg)
  167. {
  168. global $CONF;
  169. $args = explode('|', $arg);
  170.  
  171. // select private collection when no collection given
  172. if (!strstr($args[0],'/'))
  173. {
  174. $args[0] = $memberid . '/' . $args[0];
  175. }
  176.  
  177. $width = $args[1];
  178. $height = $args[2];
  179. $link = htmlspecialchars($CONF['MediaURL']. $args[0]);
  180. $text = htmlspecialchars($args[3]);
  181. $imagelink = '<img src="' . $link . '" width="' .
  182. $width . '" height="' . $height . '" alt="' . $text . '" title="' . $text . '" />';
  183. return $imagelink;
  184.  
  185. }
  186. function createMediaCode($memberid, $arg)
  187. {
  188.  
  189. global $CONF;
  190. $args = explode('|', $arg);
  191.  
  192. // select private collection when no collection given
  193. if (!strstr($args[0],'/'))
  194. {
  195. $args[0] = $memberid . '/' . $args[0];
  196. }
  197.  
  198. $link = htmlspecialchars($CONF['MediaURL'] . $args[0]);
  199. $text = htmlspecialchars($args[1]);
  200. $medialink = '<a href="' . $link . '">' . $text . '</a>';
  201.  
  202. return $medialink;
  203. }
  204.  
  205. function event_PreComment(&$data)
  206. {
  207. $memberid = $data["comment"]["memberid"];
  208. $replaceFrom = array(
  209. '/(\<\%image\()([^\)]*)(\)\%\>)/e',
  210. '/(\<\%popup\()([^\)]*)(\)\%\>)/e',
  211. '/(\<\%media\()([^\)]*)(\)\%\>)/e'
  212. );
  213. $replaceTo = array(
  214. 'NP_CommentButtons::createImageLink($memberid,"\\2")',
  215. 'NP_CommentButtons::createPopupLink($memberid,"\\2")',
  216. 'NP_CommentButtons::createMediaLink($memberid,"\\2")'
  217. );
  218. $data['comment']['body'] = preg_replace($replaceFrom, $replaceTo, $data['comment']['body']);
  219.  
  220. }
  221. }
  222.  
  223. ?>


(2) File tinyesit.js goes to plugin admin directory. Typically, it would be /nucleus/plugins/commentbuttons/

  1. var nucleusMediaPopupURL = '';
  2. var nucleusMediaURL = 'media/';
  3. var nucleusAuthorId = 0;
  4. var scrollTop = -1;
  5. var refT;
  6.  
  7. function setRefText(ref) { refT = refCT; }
  8. function setMediaUrl(url) { nucleusMediaURL = url; }
  9. function setAuthorId(id) { nucleusAuthorId = id; }
  10. function setMediaPopupURL(url) { nucleusMediaPopupURL = url; }
  11.  
  12. function boldThis() { insertAroundCaret('<b>','</b>'); }
  13. function italicThis() { insertAroundCaret('<i>','</i>'); }
  14.  
  15. function ahrefThis()
  16. {
  17. strHref = prompt("Create a link to:","http://");
  18. if (strHref == null) return;
  19.  
  20. if (isCaretEmpty(refT)) strSelection = prompt("Text to display ?","");
  21. else strSelection = prompt("Text to display ?", getCaretText(refT));
  22. insertAtCaret("<a href=\"" + strHref.replace(/&/g,'&amp;') + "\">" + strSelection + "</a>");
  23. }
  24.  
  25. function addMedia()
  26. {
  27. var mediapopup = window.open(nucleusMediaPopupURL + 'media.php','name',
  28. 'status=yes,toolbar=no,scrollbars=yes,resizable=yes,width=500,height=450,top=0,left=0');
  29.  
  30. return;
  31. }
  32.  
  33. function includeImage(collection, filename, type, width, height)
  34. {
  35. if (isCaretEmpty(refT)) text = prompt("Text to display ?","");
  36. else text = getCaretText(refT);
  37. // add collection name when not private collection (or editing a message that's not your)
  38. var fullName;
  39. if (isNaN(collection) || (nucleusAuthorId != collection))
  40. fullName = collection + '/' + filename;
  41. else fullName = filename;
  42. var replaceBy;
  43. switch(type)
  44. {
  45. case 'popup':
  46. replaceBy = '<%popup(' + fullName + '|'+width+'|'+height+'|' + text +')%>';
  47. break;
  48. case 'inline':
  49. default:
  50. replaceBy = '<%image(' + fullName + '|'+width+'|'+height+'|' + text +')%>';
  51. }
  52. insertAtCaret(replaceBy);
  53. }
  54.  
  55. function includeOtherMedia(collection, filename)
  56. {
  57. if (isCaretEmpty(refT)) text = prompt("Text to display ?","");
  58. else text = getCaretText(refT);
  59. // add collection name when not private collection (or editing a message that's not your)
  60. var fullName;
  61. if (isNaN(collection) || (nucleusAuthorId != collection))
  62. fullName = collection + '/' + filename;
  63. else fullName = filename;
  64. var replaceBy = '<%media(' + fullName + '|' + text +')%>';
  65. insertAtCaret(replaceBy);
  66. }
  67.  
  68.  
  69. // code to store the caret (cursor) position of a text field/text area
  70. // taken from javascript.faqts and modified
  71. // http://www.faqts.com/knowledge_base/view.phtml/aid/1052/fid/130
  72.  
  73. var lastSelected;
  74.  
  75. // stores the caret
  76. function storeCaret (textEl)
  77. {
  78.  
  79. // store caret
  80. if (textEl.createTextRange)
  81. textEl.caretPos = document.selection.createRange().duplicate();
  82.  
  83. // also store lastselectedelement
  84. lastSelected = textEl;
  85. scrollTop = textEl.scrollTop;
  86. }
  87.  
  88.  
  89. // inserts text at caret (overwriting selection)
  90. function insertAtCaret (text)
  91. {
  92. var textEl = lastSelected;
  93. if (textEl && textEl.createTextRange && textEl.caretPos)
  94. {
  95. var caretPos = textEl.caretPos;
  96. caretPos.text = caretPos.text.charAt(caretPos.text.length - 1) == ' ' ? text + ' ' : text;
  97. }
  98. else if (!document.all)
  99. {
  100. mozReplace(refT, text);
  101. if (scrollTop>-1) refT.scrollTop = scrollTop;
  102. }
  103. else
  104. {
  105. refT.value += text;
  106. if(scrollTop>-1) refT.scrollTop = scrollTop;
  107. }
  108. }
  109.  
  110. // inserts a tag around the selected text
  111. function insertAroundCaret (textpre, textpost)
  112. {
  113. var textEl = lastSelected;
  114. if (textEl && textEl.createTextRange && textEl.caretPos)
  115. {
  116. var caretPos = textEl.caretPos;
  117. caretPos.text = textpre + caretPos.text + textpost;
  118. }
  119. else if (!document.all)
  120. {
  121. mozWrap(refT, textpre, textpost);
  122. if(scrollTop>-1) refT.scrollTop = scrollTop;
  123. }
  124. else
  125. {
  126. refT.value += textpre + textpost;
  127. if(scrollTop>-1) refT.scrollTop = scrollTop;
  128. }
  129. }
  130.  
  131. /* some methods to get things working in Mozilla as well */
  132. function mozWrap(txtarea, lft, rgt)
  133. {
  134. var selLength = txtarea.textLength;
  135. var selStart = txtarea.selectionStart;
  136. var selEnd = txtarea.selectionEnd;
  137. if (selEnd==1 || selEnd==2) selEnd=selLength;
  138. var s1 = (txtarea.value).substring(0,selStart);
  139. var s2 = (txtarea.value).substring(selStart, selEnd)
  140. var s3 = (txtarea.value).substring(selEnd, selLength);
  141. txtarea.value = s1 + lft + s2 + rgt + s3;
  142. }
  143. function mozReplace(txtarea, newText)
  144. {
  145. var selLength = txtarea.textLength;
  146. var selStart = txtarea.selectionStart;
  147. var selEnd = txtarea.selectionEnd;
  148. if (selEnd==1 || selEnd==2) selEnd=selLength;
  149. var s1 = (txtarea.value).substring(0,selStart);
  150. var s2 = (txtarea.value).substring(selStart, selEnd)
  151. var s3 = (txtarea.value).substring(selEnd, selLength);
  152. txtarea.value = s1 + newText + s3;
  153. }
  154. function mozSelectedText(txtarea)
  155. {
  156. var selLength = txtarea.textLength;
  157. var selStart = txtarea.selectionStart;
  158. var selEnd = txtarea.selectionEnd;
  159. if (selEnd==1 || selEnd==2) selEnd=selLength;
  160. return (txtarea.value).substring(selStart, selEnd);
  161. }
  162.  
  163. function getCaretText(txtarea)
  164. {
  165. if (!document.all && document.getElementById)
  166. return mozSelectedText(txtarea);
  167. else
  168. return lastSelected.caretPos.text;
  169. }
  170.  
  171. function isCaretEmpty(txtarea)
  172. {
  173. if (lastSelected && lastSelected.createTextRange && lastSelected.caretPos)
  174. return (lastSelected.caretPos.text == '');
  175. else if (!document.all && document.getElementById)
  176. return (mozSelectedText(txtarea) == '');
  177. else
  178. return true;
  179. }
  180.  
  181. function BtnHighlight(el)
  182. {
  183. with(el.style)
  184. {
  185. borderLeft="1px solid gray";
  186. borderRight="1px solid #e9e9e9";
  187. borderTop="1px solid gray";
  188. borderBottom="1px solid #e9e9e9";
  189. }
  190. }
  191.  
  192. function BtnNormal(el)
  193. {
  194. with(el.style)
  195. {
  196. padding="3px";
  197. border="1px solid #dddddd";
  198. }
  199. }

^ TOP

02/09/2007

Комментарии

 
( ):