4

EDIT: Simpler explenation of the problem first. More detailed explanation below.

I use some jquery widgets code to create a UI slider. The code is here:

https://webgl2fundamentals.org/webgl/resources/jquery-gman-circle.js

This can be used, calling the component directly in the JS script like this:

$("#rotation").gmanUnitCircle({
    width: 200,
    height: 200,
    value: 0,
    slide: function(e, u) {
      rotation[0] = u.x;
      rotation[1] = u.y;
      drawScene();
    },
  });

What I want to do is set a value to the slider with code. This seems to be possible calling the drawCircle(ctx) function of the code, with the angle you want but I dont know how to call it because is part of a big JQuery function that calls itself and sets all slider callbacks in the element construction. (you can check that in code of the link above).

The question is how can I do this in a simple way, or how can I call or access the drawCircle(ctx) function from the outside (from my specific circle instance)?

(Coming from c# I would do this exposing the method I want to access from the outside with an interface)

Code used to create the slider and se how it works, with the possibility of code edition in the web itself can be found here:

https://webgl2fundamentals.org/webgl/lessons/webgl-2d-rotation.html

Edit: This semms to be possible but still not able to achieve it.

https://learn.jquery.com/jquery-ui/widget-factory/widget-method-invocation/

Accessing widget instance from outside widget

So I tried $('#rotation').gmanUnitCircle('drawCircle') after setting the rotation that I want and similar combinations code attempts but it doesnt worrk.

More detailed explanation: (You dont need to read this if the problem is already understood. I just explain more extensively the problem, how a similar one was solved and more attempts to solve it I tried)

This question comes as a continuation of this question:

Set value to slider directly

I have the very same problem updating the circle slider.

My problem is that I set the values of the circle with the mouse click and drag, but I cannot set the values directly. I want to set the rotation of the circle to a determined value.

The full code I am working with is here:

https://webgl2fundamentals.org/webgl/lessons/webgl-2d-rotation.html

I tried to create a function that updates the value, calling the updateValue function in:

https://webgl2fundamentals.org/webgl/resources/jquery-gman-circle.js

function updateSlider(slider, value) {slider.updateValue(value)}

But it is not a function present in the UI element funtionality as in the slider case.

I tried then to call the drawCircle(ctx) function that can be found as used in the code:

function drawCircle(ctx)

But it is inside the _create: function() { and I dont know how to call it for my circle.

I also considered extendin the funcionality of the cicle created to set a value with the setSlider value function, but I dont know how to vinculate my click button event with this function to update the value.

rotCircle = $('#rotation').gmanUnitCircle({
      width: 200,
      height: 200,
      value: 0,
      slide: (e, u) => {
        this.rotation[0] = u.x;
        this.rotation[1] = u.y;
        this.drawScene(shader);
      },
      setSliderValue: (e, u) => { // <- I would want to call this function to set the values I desire in u
        this.rotation[0] = u.x;
        this.rotation[1] = u.y;
        this.drawScene(shader);
      },
    });

I tried to trigger the event of the function I created trying to dispatch o trigger an event that calls the function, with no success:

https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/dispatchEvent

Moreover, try to call a function through a forced event call does not seem to a good approach. Also I tried to call it through a button click event, as actually the value to the slider should be set with a button.

To sum up, I just want to set the value of the circle rotation slider directly. I am not familar with the Javascript event approach so that is why I guess I find this harder that expected.

Thanks in advance

rustyBucketBay
  • 4,320
  • 3
  • 17
  • 47
  • 1
    The definition of this widget is kinda odd. You can't access the `drawCircle` at the moment from the outside. What you could do if you can edit the widgets code is to add an object property to the widget. Like 'this.drawCircle = drawCircle'. – David P. Jun 02 '20 at 05:58
  • So, as far as I understand you mean that instead of using the circle code with the link in the html I should import the circle code into my project and access the function through the property I implement in the code. I contemplated that option, but asked the question in case there could be a more simple and direct approach. I will do that if a simpler option does not come up though. Thanks for your comment. – rustyBucketBay Jun 02 '20 at 07:03
  • Yes. The way this widget is has beeen written, all functions are more or less "private". – David P. Jun 02 '20 at 12:09
  • The problem of your proposal is that as you can see in the html where the code of the jquery widget is, comes along with another 3 links of code, so this does not seem be an easy isolated widget that I can import in my project as I did with the standard slider. There should be a way that I can get a function of the slider called, or call some function I add to set the sliders value – rustyBucketBay Jun 06 '20 at 16:41

1 Answers1

4

I had a closer look at your code and reduced it to the absolute minimum. It turns out you can supply the starting value of the angle simply by putting it into the empty options argument of the initiatior method: $("#example").gmanUnitCircle({value: -Math.PI/3});. In my example I chose the value of -60° in radians.

$(function(){
  var widget=$("#example").gmanUnitCircle({value: -Math.PI/3});
  function setval(w,val){w.empty().data("gmanUnitCircle",null).gmanUnitCircle({value:val});}

  $('input').on('input',function(ev){ setval(widget,ev.target.value*Math.PI/180); })
});
#ui { width: 200px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.8.16/jquery-ui.min.js"></script>
<script src="https://webgl2fundamentals.org/webgl/resources/jquery.mousecapture.js"></script>
<script src="https://webgl2fundamentals.org/webgl/resources/jquery-gman-circle.js"></script>
<body>
<div class="description">
Drag Circle
<p><input type="text" placeholder="enter an angle (deg)"></p>
</div>
<div id="example"></div>

I now added a work-around: Whenever you enter a number in the input field the widget will simply be re-created! It is probably not what you were looking for but it does the job very well.

Carsten Massmann
  • 26,510
  • 2
  • 22
  • 43
  • thanks for your answer. You can provide the starting value, but that cannot be changed afterwards. My question is how to set the value after the element is created. If I run $("#example").gmanUnitCircle({value: otherValue}); the value does not change anymore. I would like to set that value whenever I wanted with a function – rustyBucketBay Jun 06 '20 at 17:49
  • I am still playing with it ... ;-) – Carsten Massmann Jun 06 '20 at 17:53
  • 1
    Got to stop for the moment. It has something to do with scope, as the `drawCircle()` function is defined within the widget constructor function `_create()`. `drawCircle()` is not a public method of the widget object. I managed to change the `options` value of the widget but cannot (as yet) trigger a redraw of the circle. – Carsten Massmann Jun 06 '20 at 18:29
  • Yeah, that is exactly my problem. Other thing I was trying was keep a reference to the "u" argument of the slide function, that passes in an object with the angle, the x and the y on the slide event, to change those outside that scope with my value, but as far as I am researching, arguments are passed by value in Javascript so that does not seem to be possible. – rustyBucketBay Jun 06 '20 at 18:37
  • 1
    Please have another look at my answer, I added a work-around. – Carsten Massmann Jun 06 '20 at 19:47
  • Thats perfect!! This makes the widget usable anywhere. That was exactly one of my attempts, but I am not familiar with Javascript, less even with Jquery and this kind of widgets. As the code is not modificable to expose the variables/methods I would like to access, and also there are not many instances of the cricle when its re-created so, it is recreated over the previous one (I believe due to fact that it is created with the same name), for me this is a solution more than a workaround. Thank you so much!!! – rustyBucketBay Jun 06 '20 at 20:28