vb.org Archive

vb.org Archive (https://vborg.vbsupport.ru/index.php)
-   vB4 Programming Discussions (https://vborg.vbsupport.ru/forumdisplay.php?f=252)
-   -   Appending data to a post via javascript (https://vborg.vbsupport.ru/showthread.php?t=311997)

MarkFL 06-08-2014 06:21 PM

Appending data to a post via javascript
 
Hello all,

I help administrate a math forum running vBulletin 4.2.1. I have recently added an element to the editpost, newreply and newthread templates that introduces a live preview of LaTeX to aid in debugging code more efficiently than using the "Preview Post" function repeatedly.

Within this element, I have an input button that, using the onclick event, will copy the value of an internal textarea element to the post body using the javascript code:

Code:

document.getElementsByClassName('cke_source')[0].value += document.getElementById('MathInput').value
This works fine unless the user has opted for the WYSIWYG editor, in which case the DOM is constructed differently.

My question: is there a way to append data to the post message that will work regardless of the editor chosen by the user? I have tried manipulating {vb:raw post.message} to no avail.

I appreciate any insights into how to get this to work. :)

Best Regards,

Mark.

MarkFL 06-27-2014 04:06 AM

I figured out how to accomplish inserting data into a post message regardless of editor mode (that works with Firefox 29 and Chrome 35), and thought it would be good etiquette to share my findings here.

I have a textarea element with id="MathInput" whose contents I wish to insert into the post message at the current cursor location within the post message when a "Copy to Post" button is clicked. I want the cursor to be located at the end of the inserted data after the operation. This is the function that does this:

Code:

function copyMathToPost()
{
    var content = document.getElementById('MathInput').value, el = document.getElementsByClassName('cke_source')[0];
    if (el)
    {
        var pos = getCaretPosition(el);
        el.value = el.value.substr(0, pos) + content + el.value.substr(pos);
        setCaretPosition(el,pos + content.length);
        el.focus();
    }
    else
    {
        var iFrame = document.getElementsByTagName('iframe')[0];
        insertHtmlAtCursor(iFrame,content);
        moveCaret(iFrame, -1);
        moveCaret(iFrame, 1);
    }
}

Here are the supporting functions:

Code:

function getCaretPosition(el)
{
    if (el.selectionStart)
    {
        return el.selectionStart;
    }
    else if (document.selection)
    {
        el.focus();
        var r = document.selection.createRange();
        if (r == null)
        {
            return 0;
        }
        var re = el.createTextRange(), rc = re.duplicate();
        re.moveToBookmark(r.getBookmark());
        rc.setEndPoint('EndToStart', re);
        return rc.text.length;
    } 
    return 0;
}

function setCaretPosition(ctrl,pos)
{
    if(ctrl.setSelectionRange)
    {
        ctrl.focus();
        ctrl.setSelectionRange(pos,pos);
    }
    else if(ctrl.createTextRange)
    {
        var range = ctrl.createTextRange();
        range.collapse(true);
        range.moveEnd('character',pos);
        range.moveStart('character', pos);
        range.select();
    }
}

function insertHtmlAtCursor(iFrame,html)
{
    var sel, range, node;
    html = html.replace(/\r\n?|\n/g, '<br>');
    if (iFrame.contentWindow.getSelection && iFrame.contentWindow.getSelection().getRangeAt)
    {
        sel = iFrame.contentWindow.getSelection();
        try{range = sel.getRangeAt(0);}
        catch (e){alert("This function is not supported by your browser. Please switch editor to Source Mode.");}
        node = range.createContextualFragment(html);
        range.insertNode(node);
        range = range.cloneRange();
        range.collapse();
        sel.removeAllRanges();
        sel.addRange(range);
    }
    else if (iFrame.contentWindow.selection && iFrame.contentWindow.selection.createRange)
    {
        iFrame.contentWindow.selection.createRange().pasteHTML(html);
    }
    else
    {
        alert("This function is not supported by your browser. Please switch editor to Source Mode.");
    }
    iFrame.focus();
}

function moveCaret(win, charCount)
{
    var sel, range;
    if (win.contentWindow.getSelection)
    {
        sel = win.contentWindow.getSelection();
        if (sel.rangeCount > 0)
        {
            var textNode = sel.focusNode;
            var newOffset = sel.focusOffset + charCount;
            sel.collapse(textNode, newOffset);
        }
    }
    else if (sel = win.contentDocument.selection)
    {
        if (sel.type != "Control")
        {
            range = sel.createRange();
            range.move("character", charCount);
            range.select();
        }
    }
}


tbworld 06-27-2014 07:59 AM

Nice work, as soon as I have time I am going to check this out in detail. Thank you so much for sharing. :)

I have been working on a pretty easy model by using the existing vb javascript files "vbulletin_quick_reply.js", "vbulletin_quick_edit.js", ... anyway, you already know the problem with that method -- so many different editor modes to modify. After staring at the code for awhile, I too was thinking that I should just position the data via the DOM and be done with it. Since essentially that is all that is being done in the vb JavaScript files.

Sorry, I missed your first (previous) post somehow. I must have been traveling for work or I would have answered, but it looks like you were a bit ahead of my work. I just finished "quick_reply" and "quick_editor" two days ago and still needed to verify caret positioning among the browsers.

Good work! -- I am impressed. :)

MarkFL 06-27-2014 02:15 PM

Because of an issue reported to me by one of my fellow administrators, who uses a different OS (I use Windows 7 and he uses Xubuntu and we both use Firefox), I have moved the focus method to the end of the moveCaret function, and this alleviates the need to make two calls to the moveCaret function (which I used previously so that Chrome did not lose the cursor).

So, the updated functions are:

Code:

function copyMathToPost()
{
    var content = document.getElementById('MathInput').value, el = document.getElementsByClassName('cke_source')[0];
    if (el)
    {
        var pos = getCaretPosition(el);
        el.value = el.value.substr(0, pos) + content + el.value.substr(pos);
        setCaretPosition(el,pos + content.length);
        el.focus();
    }
    else
    {
        var iFrame = document.getElementsByTagName('iframe')[0];
        insertHtmlAtCursor(iFrame,content);
        moveCaret(iFrame, 0);
    }
}

function insertHtmlAtCursor(iFrame,html)
{
    var sel, range, node;
    html = html.replace(/\r\n?|\n/g, '<br>');
    if (iFrame.contentWindow.getSelection && iFrame.contentWindow.getSelection().getRangeAt)
    {
        sel = iFrame.contentWindow.getSelection();
        try{range = sel.getRangeAt(0);}
        catch (e){alert("This function is not supported by your browser. Please switch editor to Source Mode.");}
        node = range.createContextualFragment(html);
        range.insertNode(node);
        range = range.cloneRange();
        range.collapse();
        sel.removeAllRanges();
        sel.addRange(range);
    }
    else if (iFrame.contentWindow.selection && iFrame.contentWindow.selection.createRange)
    {
        iFrame.contentWindow.selection.createRange().pasteHTML(html);
    }
    else
    {
        alert("This function is not supported by your browser. Please switch editor to Source Mode.");
    }
}

function moveCaret(win, charCount)
{
    var sel, range;
    if (win.contentWindow.getSelection)
    {
        sel = win.contentWindow.getSelection();
        if (sel.rangeCount > 0)
        {
            var textNode = sel.focusNode;
            var newOffset = sel.focusOffset + charCount;
            sel.collapse(textNode, newOffset);
        }
    }
    else if (sel = win.contentDocument.selection)
    {
        if (sel.type != "Control")
        {
            range = sel.createRange();
            range.move("character", charCount);
            range.select();
        }
    }
    win.focus();
}



All times are GMT. The time now is 06:27 AM.

Powered by vBulletin® Version 3.8.12 by vBS
Copyright ©2000 - 2025, vBulletin Solutions Inc.

X vBulletin 3.8.12 by vBS Debug Information
  • Page Generation 0.01540 seconds
  • Memory Usage 1,745KB
  • Queries Executed 10 (?)
More Information
Template Usage:
  • (1)ad_footer_end
  • (1)ad_footer_start
  • (1)ad_header_end
  • (1)ad_header_logo
  • (1)ad_navbar_below
  • (4)bbcode_code_printable
  • (1)footer
  • (1)gobutton
  • (1)header
  • (1)headinclude
  • (6)option
  • (1)post_thanks_navbar_search
  • (1)printthread
  • (4)printthreadbit
  • (1)spacer_close
  • (1)spacer_open 

Phrase Groups Available:
  • global
  • postbit
  • showthread
Included Files:
  • ./printthread.php
  • ./global.php
  • ./includes/init.php
  • ./includes/class_core.php
  • ./includes/config.php
  • ./includes/functions.php
  • ./includes/class_hook.php
  • ./includes/modsystem_functions.php
  • ./includes/class_bbcode_alt.php
  • ./includes/class_bbcode.php
  • ./includes/functions_bigthree.php 

Hooks Called:
  • init_startup
  • init_startup_session_setup_start
  • init_startup_session_setup_complete
  • cache_permissions
  • fetch_threadinfo_query
  • fetch_threadinfo
  • fetch_foruminfo
  • style_fetch
  • cache_templates
  • global_start
  • parse_templates
  • global_setup_complete
  • printthread_start
  • bbcode_fetch_tags
  • bbcode_create
  • bbcode_parse_start
  • bbcode_parse_complete_precache
  • bbcode_parse_complete
  • printthread_post
  • printthread_complete