How to execute javascript code from p5js.

First let me say that I am new to HTLM and Javascript..therfore also new to p5js. I found p5js very interesting so I started to create a page using p5js to parse messages from a Mainframe System. I need to peform some selection of text within a TextArea in the HTML, like show here http://jsfiddle.net/YNr7K/364/, using the setSelectionRange method of the TextArea. I don't find any way do it on p5js, so Is there a way to create another script function on the page like:

function selectCup() { var input = document.getElementById("TextAreaId"); input.setSelectionRange(3,5); // Highlights desired text, paramas will be variable. they are hardcode just for test. input.focus(); };

and call this function from within p5js? Thanks in adavance.

Answers

  • For p5.js sketches, the preferred way to deal w/ browser's DOM is via library "p5.dom.js":
    http://p5js.org/reference/#/libraries/p5.dom

    For example, instead of getElementById(), we use select(), which results on a p5.Element object:

    1. http://p5js.org/reference/#/p5/select
    2. http://p5js.org/reference/#/p5.Element

    If for some reason, we need to access the underlying HTMLElement, we access it via property elt:
    http://p5js.org/reference/#/p5.Element/elt

  • edited February 2017

    GoToLoop, thanks for your response. i have something wierd going on here.

    I have created this function in Sketch.js

    function selectCup() {
        console.log('hello');
        var input = document.getElementById("test");
        input.setSelectionRange(0,3); // Highlights "Cup"
        input.focus();
    };
    

    my HTML has:

    <input type="button" value="Select cup" onmousedown="selectCup(); return false">
    
    <textarea type="textarea" id="test"> Cup of tea </textarea>
    

    When i click on the button "Select Cup" on the HTML, the selectCup function is called on the sketch,js and the content is highlighted as expected. But when i try to call this function from within sketch,js nothing happens eventhough the "hello" gets printed on the console, so I know that the function was executed.

    I've tried using select to access textarea "test" but when i do that, by that, I mean replacacing

    var input = document.getElementById("test");
    

    with

    var input = select("#test");
    

    I get this error. TypeError: input.setSelectionRange is not a function.

    using

    input.elt.setSelectionRange(0,3); // Highlights "Cup"
    

    shows no error, but nothing happens, only Hello get printed on the log

  • edited February 2017

    Before anything else, learn how to post code in this forum: L-)
    https://forum.Processing.org/two/discussion/15473/readme-how-to-format-code-and-text

    I get this error. TypeError: input.setSelectionRange is not a function.

    Indeed, class p5.Element doesn't have any method called setSelectionRange().

    As I had mentioned, if you need to access native HTMLElement members, do it via elt:
    input.elt.setSelectionRange(0, 3);

    But when I try to call this function from within "sketch.js" nothing happens...

    What is supposed to happen? Disclaimer: I'm still a DOM noob myself. ~:>
    I guess you're gonna need to post more of your sketch. :|

  • edited February 2017

    well.

    What i mean is...using

    var input = document.getElementById("result");
    input.setSelectionRange(0,3); // Highlights "Cup"
    input.focus();
    

    when the function selectCup that IS defined within the sketch.js is called using the onmousedown event defined in the button Select cup withing the HTML, the function is executed, "hello" is printed on the console and the text "Cup" gets highlited as expected in the textarea.

    but when I call the same function using the mousePressed event from p5.js using a button Parse Content I created calling createButton('Parse Content'); the function selectCup does not work, Nothing is highlithed eventhough "hello" is printed on the console.

    Then...as you suggested I replaced

    var input = document.getElementById("result");
    input.setSelectionRange(0,3); // Highlights "Cup"
    input.focus();
    

    with:

    var input = select("#result");
    input.elt.setSelectionRange(0,3); // Highlights "Cup"
    input.elt.focus();
    

    with that change...Select cup is still working and Parse Content still does NOT work, "hello" gets printed on the console pressing on any button.

    This is my sketch.js.

    var button_parse;
    
    function parse_pressed(){
        // do some validations....and selecte what needs to be highlited
        // call function to highlight
        selectCup();
    };
    
    function setup() {
        noCanvas();
       
        button_parse = createButton('Parse Content');
        button_parse.mousePressed(parse_pressed);
    };
    
    
    function selectCup() {
        console.log('hello');
        var input = document.getElementById("result");
        input.setSelectionRange(0,3); // Highlights "Cup"
        input.focus();
        //or
        //var input = select("#result");
        //input.elt.setSelectionRange(0,3); // Highlights "Cup"
        //input.elt.focus();
    };
    
    

    This is my HTML.

    <html>
    <head>
        <meta charset="UTF-8">
        <script language="javascript" type="text/javascript" src="libraries/p5.js"> </script>
        <!-- uncomment lines below to include extra p5 libraries -->
        <!--<script language="javascript" src="libraries/p5.dom.js"></script>-->
        <!--<script language="javascript" src="libraries/p5.sound.js"></script>-->
        <script type='text/javascript' src='libraries/p5.dom.js'></script>
        <script language="javascript" type="text/javascript" src="sketch.js"></script>
    
        <!-- this line removes any default padding and style. you might only need one of these values set. -->
    </head>
    
    <body>
        <h1>'Message Parser</h1>
        <p>DDL definition to use:</p>
        <input type="button" value="Select cup" onmousedown="selectCup(); return  false">
        <textarea type="textarea" id="result">Cup of tea</textarea>
    </body>
    </html>
    
  • Is this an error?

  • edited February 2017 Answer ✓

    Indeed you're right! Invoking selectCup() from p5.Element::mousePressed()'s callback parse_pressed() somehow fails to keep HTMLInputElement::setSelectionRange()'s highlighted text. @-)

    But fret not, I've found a workaround for it! \m/
    Just switch p5.Element::mousePressed() to another sibling event method. *-:)
    For example: p5.Element::mouseReleased() or p5.Element::mouseClicked(). :D

    You can also run my solution online at the link below: :bz
    http://CodePen.io/GoSubRoutine/pen/qRzapj/top?editors=101

    P.S.: New Version 1.1! :D

    "index.html":

    <meta charset=UTF-8>
    <title>setSelectionRange()</title>
    
    <script async src=http://CDN.JSDelivr.net/g/p5.js(p5.min.js+addons/p5.dom.js)></script>
    <script defer src=sketch.js></script>
    
    <textarea id=result>Cup of Tea</textarea>
    <input type=button value="Select Cup" onmousedown="return selectCup();">
    

    "sketch.js":

    /**
     * setSelectionRange() (v1.1)
     * Gatunox & GoToLoop (2017-Feb-19)
     *
     * https://forum.Processing.org/two/discussion/20880/
     * how-to-execute-javascript-code-from-p5js#Item_6
     *
     * http://CodePen.io/GoSubRoutine/pen/qRzapj/top?editors=101
     */
    
    "use strict";
    
    let inputArea;
    
    function setup() {
      noCanvas(), noLoop();
    
      //createButton('Parse Content').mousePressed(parsePressed);
      createButton('Parse Content').elt.onmousedown = parsePressed;
    
      inputArea = select('#result');
    }
    
    function parsePressed() {
      //mouseEvent.preventDefault();
      return selectCup();
    }
    
    function selectCup() {
      const {elt} = inputArea;
      elt.setSelectionRange(0, 3), elt.focus();
    
      document.bgColor = '#' + hex(~~random(0x1000), 3);
      return false;
    }
    
  • Thanks it works, do you think it needs to be reported?

  • Answer ✓

    Seems like a good idea: https://GitHub.com/processing/p5.js/issues ;))

  • Yes, i know, this is my post :p

  • edited February 2017

    I see the p5.js' repo gave a solution for your bug issue now. <:-P
    However, there are some wrong factual statements on @feedzh's answer though. 8-|

    It seems that this is not so much a p5 problem but JS event bubbling.

    If that was so, <input type=button value="Select Cup" onmousedown="return selectCup();"> woulda failed as well. :-@

    Also it's not related to bubbling propagation but event's default action cancelling. :-B

    You already prevented event from bubbling. When you remove return false; it stops working.

    Again, it's not about bubbling-up propagation. [-X
    Neither return false; nor Event::preventDefault() prevent events from propagating:
    https://developer.Mozilla.org/en-US/docs/Web/API/Event/preventDefault

    If that's desired, we need to invoke Event::stopPropagation(): :P
    https://developer.Mozilla.org/en-US/docs/Web/API/Event/stopPropagation

    Anyways, if you take another look at my solution (now on v1.1), you'd see I'm applying another approach now: createButton('Parse Content').elt.onmousedown = parsePressed;

    After some further experiments, I've realized return false; only works for on*() event types.
    Like GlobalEventHandlers::onmousedown() for example:
    https://developer.Mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onmousedown

    Those registered via EventTarget::addEventListener() can only be cancelled exclusively via Event::preventDefault(): b-(
    https://developer.Mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

    As we can realize now, all of p5.Element's event registering methods rely on EventTarget::addEventListener().
    That's the reason why HTML's input button worked w/ return false;, while the p5.js version's failed!

    And apparently, neither p5.Element::mouseClicked() nor p5.Element::mouseReleased() demand Event::preventDefault() as much as p5.Element::mousePressed() does for your case though. :-?

    Of course, the most reliable solution is to always use Event::preventDefault(), which works for all cases, rather than relying on return false;, which works only for GlobalEventHandlers::on*() event registering style. >-)

Sign In or Register to comment.