Unexpected behaviour with select method in instance mode

Hi there,

I started a project that uses p5.js in instance mode and I’m encountering a weird behaviour when I try to use the select() method.

In some cases, when I try to select an element in the DOM using that function, the element is not found, and a new empty div is created instead, right before the closing body tag.

Here’s a simple example that reproduces my issue. It works well when I’m using the native document.getElementById() method but not with the p5.js select method.

let container;

let sketch = function(p) {

  p.setup = function() {

    container = p.createDiv();
    container.class('option--container');

    addInputElements();

    p.pixelDensity(1);
    p.noLoop();
  };

  function addInputElements() {

    // Input 1
    let selectorContainer = p.createDiv('Selector');
    selectorContainer.class('option--container');
    let selector = p.createSelect();
    selector.id('selector');
    selector.style('float', 'right');
    selector.option('option_1');
    selector.option('option_2');
    selector.option('option_3');
    selector.selected('option_1');
    selector.changed(handlechange);
    selector.parent(container);
    selectorContainer.parent(container);

    // Input 2
    let thresholdContainer = p.createDiv('Threshold');
    thresholdContainer.id(`threshold`);
    thresholdContainer.class('option--container');
    let value = p.createElement('input');
    value.id(`threshold_slider_value`);
    value.attribute('type', 'number');
    value.attribute('min', '0');
    value.attribute('max', '255');
    value.attribute('value', '128');
    value.style('width', '70px');
    value.style('float', 'right');
    value.changed(updateRangeInput);
    value.parent(thresholdContainer);
    let slider = p.createSlider(0, 255, 128, 1);
    slider.id(`threshold_slider`);
    slider.style('width', '100%');
    slider.input(updateNumberInput);
    slider.parent(thresholdContainer);
    thresholdContainer.style('display', 'none');
    thresholdContainer.parent(container);

    let optionsContainer = p.select('#options--container');
    container.parent(optionsContainer);
  }

  function updateNumberInput(event) {
    let value = event.target.value;
    let feedbackElt = p.select(`#${event.target.id}_value`);
    feedbackElt.elt.value = value;
  }

  function updateRangeInput(event) {
    let value = event.target.value;
    let element = `#${event.target.id}`
    let feedbackElt = p.select(element.replace('_value', ''));
    feedbackElt.elt.value = value;
  }

  function handlechange() {
    let ditherType = this.elt.value;
    let thresholdElt = p.select(`#threshold`);
    // element not found - new div is created instead in the DOM
    console.log(thresholdElt);

    let thresholdElt_ = document.getElementById(`threshold`);
    // element found using the base method
    console.log(thresholdElt_);

    // show element...
  }

};

let myp5 = new p5(sketch);

Thanks for your help.

hi! Welcome to the forum!

I get error at this line

    let optionsContainer = p.select('#options--container');

but did you already create this element in the html file? I only see option--container not options--container and they are classes. If I add

    <div id="options--container"></div>

to the html, it works fine for me.

Hi Micuat,

Yes apologies, my HTML file looks like that:

<body>
    <div id="canvas"></div>

    <div id="options--container">
    </div>

    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
    <script type="text/javascript" src="/js/sketch.js"></script>
</body>

As you mentioned I have also a css class called .option--container.

So when you’re running the code, you can select the element fine?

Here’s how it looks for me. Selecting the element using p5js method returns a weird object named radioOption, with width and height set to 0 (first line). Using the native getElementById() method works as expected (second line).

Many thanks

ok I see, it happens when you select the dropdown box, right? I don’t know why, and it would be great if you can open an issue on p5.js github repository. For now as a solution I would suggest to store dom elements as a variable. This makes the code a bit tidier and more efficient than searching with p5.select or document.getElementById every time.

https://editor.p5js.org/micuat/sketches/beAEiJEcK

Hi,

Yes it happens when I select the dropdown box but I also tried to do the same after clicking a button and the issue remains. I’m puzzled.

I will create an issue on github, thanks for your time on this :slightly_smiling_face:

I think I got what is happening. It’s because of the scope. If you change the callback to arrow function instead

  const handlechange = () => {

and comment out ditherType = this.elt.value, then it works. I’m trying to make a demo to replicate the issue…

edit: sorry perhaps this is wrong. I think I got it wrong :frowning: I’m sure something is wrong with _wrapElement internal function

I found that when the slider is inside #threshold div, somehow select doesn’t work. If the slider is not inside, select works. Here is a small version that demonstrate the issue

https://editor.p5js.org/micuat/sketches/YiD4oRMTk

thanks for opening the issue! for the bug we continue discussion on github instead