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/

<?php

class NP_CommentButtons extends NucleusPlugin
{
        // name of plugin
        function getName()
        {
        return 'CommentButtons';
        }
        // author of plugin
        function getAuthor()
        {
        return 'maxirmx';
        }
        // an URL to the plugin website
        // can also be of the form mailto:foo@bar.com
        function getURL()
        {
        return 'mailto:maxirmx@mail.ru';
        }
        // version of the plugin
        function getVersion()
        {
        return '0.1';
        }
        // a description to be shown on the installed plugins listing
        function getDescription()
        {
        return 'This plugin provides Bold, Italic, Link and Image buttons at Nucleus comments form';
        }
        function supportsFeature ($what)
        {
        switch ($what)
        {
            case 'SqlTablePrefix':
                return 1;
            default:
                return 0;
        }
        }
       
        function getEventList()
        {
                return array('FormExtra', 'PreComment', 'PreAddComment', 'PreUpdateComment');
        }
       
        function addJsButton($fn, $img)
        {
                global $CONF;
echo "         <img  class="jsbutton"\n";
echo "               onmouseover="BtnHighlight(this);"\n";
echo "               onmouseout="BtnNormal(this);"\n";
echo "               onclick="" . $fn . "()"\n";
echo "               src="" . $CONF['AdminURL'] . "images/" .
     $img . "
.gif" alt="" width="16" height="16"/>\n";
        }

        function addJsButtonSpacer()
        {
echo "       <span class="jsbuttonspacer">\n";
echo "       </span>\n";
        }

        function addJsAttachEvent($evnt)
        {
echo "       if (refCT." . $evnt . ") refCT." . $evnt .
     "onkeyup = function () { refCT." . $evnt . "(); storeCaret(refCT); };\n";
echo "       else               refCT." . $evnt . " = function () { storeCaret(refCT); };\n";
        }

        function event_FormExtra(&$data)
        {
                global $CONF, $member;
                if ($data['type'] == 'commentform-loggedin')
                {

echo "\n     <!-- Start NP_CommentButtons -->\n";
echo "      <script type="text/javascript"\n";
echo "       src="" . $this->getAdminURL() . "tinyedit.js">\n";
echo "      </script>\n";
           
echo "      <div id = "nucleus_cf_buttonbar" class="jsbuttonbar" name="buttonbar">\n";
echo "       <br />\n";
                   
// *** The next three lines are needed if bold and italic buttons are supported
//                   $this->addJsButton('boldThis','button-bold');
//                   $this->addJsButton('italicThis','button-italic');
//                   $this->addJsButtonSpacer();                  
                   $this->addJsButton('ahrefThis','button-link');
                   $this->addJsButton('addMedia','button-media');

echo "       <br />\n";
echo "       <br />\n";
echo "      </div>\n";

echo "      <script type="text/javascript">\n";
echo "       refCT = document.getElementById('nucleus_cf_body');\n";
echo "       refBtB = document.getElementById('nucleus_cf_buttonbar');\n";
echo "       refParent = refCT.parentNode;\n";
echo "       refBtB = refParent.removeChild(refBtB);\n";
echo "       refParent.insertBefore(refBtB,refCT);\n";

                   $this->addJsAttachEvent('onkeyup');
                   $this->addJsAttachEvent('onclick');
                   $this->addJsAttachEvent('onselect');

echo "       setMediaUrl("" . $CONF['MediaURL'] . "");\n";
echo "       setMediaPopupURL("" . $CONF['AdminURL'] . "");\n";
echo "       setRefText(refCT);\n";
       
               if ($member->isLoggedIn())
echo "       setAuthorId(" . $member->getId() .");\n";

echo "      </script>\n";
echo "     <!-- End NP_CommentButtons -->\n\n";

                }
        }        

        function doAllDirtyJob(&$data)
        {
                $data['comment']['body'] = preg_replace ('/\>.+\>\&quot\;\&gt\;/','/>',$data['comment']['body']);

               
                $search = array (
                                  '&lt;a href=&quot;', '&lt;/a&gt;',
                                  '&lt;%', '%&gt;',
// *** The next two lines are needed if bold and italic buttons are supported
//                                  '&lt;b&gt;', '&lt;/b&gt;',
//                                  '&lt;i&gt;', '&lt;/i&gt;'  
                                );
                $replace = array ('','</a>',
                                  '<%','%>',
// *** The next two lines are needed if bold and italic buttons are supported
//                                  '<b>','</b>',
//                                  '<i>','</i>'
                                 );
                $data['comment']['body'] = str_replace($search, $replace, $data['comment']['body']);
        }

        function event_PreUpdateComment(&$data)
        {
                $this->doAllDirtyJob(&$data);
        }

        function event_PreAddComment(&$data)
        {
                $this->doAllDirtyJob(&$data);
        }

        function createPopupLink($memberid, $arg)
        {
        global $CONF;
   
            $args = explode('|', $arg);

        // select private collection when no collection given
        if (!strstr($args[0],'/'))
                {
            $args[0] = $memberid . '/' . $args[0];
        }

        $width = $args[1];
        $height = $args[2];
       
                $rawpopuplink = $CONF['Self'] . "?imagepopup=" . htmlspecialchars($args[0]) .
                 "&amp;width=$width&amp;height=$height&amp;imagetext=" . urlencode(htmlspecialchars($args[3]));
                $popupcode = "window.open(this.href,'imagepopup'," .
                 "'status=no,toolbar=no,scrollbars=no,resizable=yes,width=$width,height=$height');return false;";
                $popuptext = htmlspecialchars($args[3]);
                $popuplink = '<a href="' . $rawpopuplink. '" onclick="'. $popupcode.'" >' . $popuptext . '</a>';
       
        return $popuplink;
         }
   
        function createImageLink($memberid, $arg)
        {
        global $CONF;
           
            $args = explode('|', $arg);

        // select private collection when no collection given
        if (!strstr($args[0],'/'))
                {
            $args[0] = $memberid . '/' . $args[0];
        }

        $width = $args[1];
        $height = $args[2];
       
        $link       = htmlspecialchars($CONF['MediaURL']. $args[0]);
        $text       = htmlspecialchars($args[3]);
                $imagelink = '<img src="' . $link . '" width="' .
                $width . '" height="' . $height . '" alt="' . $text . '" title="' . $text . '" />';
   
                return $imagelink;

        }
   
        function createMediaCode($memberid, $arg)
        {

        global $CONF;
       
            $args = explode('|', $arg);

        // select private collection when no collection given
        if (!strstr($args[0],'/'))
                {
            $args[0] = $memberid . '/' . $args[0];
        }

        $link  = htmlspecialchars($CONF['MediaURL'] . $args[0]);
        $text = htmlspecialchars($args[1]);
        $medialink = '<a href="' . $link . '">' . $text . '</a>';

                return $medialink;
        }

        function event_PreComment(&$data)
        {
       
                $memberid = $data["comment"]["memberid"];
                $replaceFrom = array(
            '/(\<\%image\()([^\)]*)(\)\%\>)/e',
            '/(\<\%popup\()([^\)]*)(\)\%\>)/e',
            '/(\<\%media\()([^\)]*)(\)\%\>)/e'
        );
        $replaceTo = array(
                        'NP_CommentButtons::createImageLink($memberid,"\\2")',
                        'NP_CommentButtons::createPopupLink($memberid,"\\2")',
                        'NP_CommentButtons::createMediaLink($memberid,"\\2")'
        );
        $data['comment']['body'] = preg_replace($replaceFrom, $replaceTo, $data['comment']['body']);

        }      
}

?>

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

var nucleusMediaPopupURL = '';
var nucleusMediaURL = 'media/';
var nucleusAuthorId = 0;
var scrollTop = -1;
var refT;

function setRefText(ref) { refT = refCT; }
function setMediaUrl(url) { nucleusMediaURL = url; }
function setAuthorId(id) { nucleusAuthorId = id; }
function setMediaPopupURL(url) { nucleusMediaPopupURL = url; }

function boldThis() { insertAroundCaret('<b>','</b>'); }
function italicThis() { insertAroundCaret('<i>','</i>'); }

function ahrefThis()
{
        strHref = prompt("Create a link to:","http://");
        if (strHref == null) return;

        if (isCaretEmpty(refT))  strSelection = prompt("Text to display ?","");
        else                     strSelection = prompt("Text to display ?", getCaretText(refT));
        insertAtCaret("<a href="" + strHref.replace(/&/g,'&amp;') + "">" + strSelection + "</a>");
}

function addMedia()
{
        var mediapopup = window.open(nucleusMediaPopupURL + 'media.php','name',
        'status=yes,toolbar=no,scrollbars=yes,resizable=yes,width=500,height=450,top=0,left=0');

        return;
}

function includeImage(collection, filename, type, width, height)
{
        if (isCaretEmpty(refT))  text = prompt("Text to display ?","");
        else                     text = getCaretText(refT);
   
// add collection name when not private collection (or editing a message that's not your)
        var fullName;
        if (isNaN(collection) || (nucleusAuthorId != collection))
        fullName = collection + '/' + filename;
        else    fullName = filename;
   
        var replaceBy;
        switch(type)
        {
        case 'popup':
            replaceBy = '<%popup(' +  fullName + '|'+width+'|'+height+'|' + text +')%>';
            break;
        case 'inline':
        default:
            replaceBy = '<%image(' +  fullName + '|'+width+'|'+height+'|' + text +')%>';
        }
        insertAtCaret(replaceBy);
}

function includeOtherMedia(collection, filename)
{
        if (isCaretEmpty(refT))  text = prompt("Text to display ?","");
        else                     text = getCaretText(refT);
   
// add collection name when not private collection (or editing a message that's not your)
        var fullName;
        if (isNaN(collection) || (nucleusAuthorId != collection))
        fullName = collection + '/' + filename;
        else    fullName = filename;
   
        var replaceBy = '<%media(' +  fullName + '|' + text +')%>';
        insertAtCaret(replaceBy);
}


// code to store the caret (cursor) position of a text field/text area
// taken from javascript.faqts and modified
// http://www.faqts.com/knowledge_base/view.phtml/aid/1052/fid/130

var lastSelected;

// stores the caret
function storeCaret (textEl)
{

    // store caret
    if (textEl.createTextRange)
        textEl.caretPos = document.selection.createRange().duplicate();

    // also store lastselectedelement
    lastSelected = textEl;
    scrollTop = textEl.scrollTop;
}


// inserts text at caret (overwriting selection)
function insertAtCaret (text)
{
        var textEl = lastSelected;
        if (textEl && textEl.createTextRange && textEl.caretPos)
        {
        var caretPos = textEl.caretPos;
        caretPos.text = caretPos.text.charAt(caretPos.text.length - 1) == ' ' ? text + ' ' : text;
        }
        else if (!document.all)
        {
        mozReplace(refT, text);            
        if (scrollTop>-1) refT.scrollTop = scrollTop;
        }
        else
        {
        refT.value += text;    
        if(scrollTop>-1) refT.scrollTop = scrollTop;
        }
}

// inserts a tag around the selected text
function insertAroundCaret (textpre, textpost)
{
        var textEl = lastSelected;
   
        if (textEl && textEl.createTextRange && textEl.caretPos)
        {
        var caretPos = textEl.caretPos;
        caretPos.text = textpre + caretPos.text + textpost;
        }
        else if (!document.all)
        {
        mozWrap(refT, textpre, textpost);      
        if(scrollTop>-1) refT.scrollTop = scrollTop;
        }
        else
        {
        refT.value += textpre + textpost;
        if(scrollTop>-1) refT.scrollTop = scrollTop;
        }
}

/* some methods to get things working in Mozilla as well */
function mozWrap(txtarea, lft, rgt)
{
    var selLength = txtarea.textLength;
    var selStart = txtarea.selectionStart;
    var selEnd = txtarea.selectionEnd;
    if (selEnd==1 || selEnd==2) selEnd=selLength;
    var s1 = (txtarea.value).substring(0,selStart);
    var s2 = (txtarea.value).substring(selStart, selEnd)
    var s3 = (txtarea.value).substring(selEnd, selLength);
    txtarea.value = s1 + lft + s2 + rgt + s3;
}
function mozReplace(txtarea, newText)
{
    var selLength = txtarea.textLength;
    var selStart = txtarea.selectionStart;
    var selEnd = txtarea.selectionEnd;
    if (selEnd==1 || selEnd==2) selEnd=selLength;
    var s1 = (txtarea.value).substring(0,selStart);
    var s2 = (txtarea.value).substring(selStart, selEnd)
    var s3 = (txtarea.value).substring(selEnd, selLength);
    txtarea.value = s1 + newText + s3;
}
function mozSelectedText(txtarea)
{
    var selLength = txtarea.textLength;
    var selStart = txtarea.selectionStart;
    var selEnd = txtarea.selectionEnd;
    if (selEnd==1 || selEnd==2) selEnd=selLength;
    return (txtarea.value).substring(selStart, selEnd);
}

function getCaretText(txtarea)
{
    if (!document.all && document.getElementById)
        return mozSelectedText(txtarea);
    else
        return lastSelected.caretPos.text;
}

function isCaretEmpty(txtarea)
{
    if (lastSelected && lastSelected.createTextRange && lastSelected.caretPos)
        return (lastSelected.caretPos.text == '');
    else if (!document.all && document.getElementById)
        return (mozSelectedText(txtarea) == '');
    else
        return true;
}

function BtnHighlight(el)
{
        with(el.style)
        {
        borderLeft="1px solid gray";
        borderRight="1px solid #e9e9e9";
        borderTop="1px solid gray";
        borderBottom="1px solid #e9e9e9";
        }
}

function BtnNormal(el)
{
        with(el.style)
        {
        padding="3px";
        border="1px solid #dddddd";
        }
}

Оставьте комментарий