Support for checkbox, input, button and drop-down list

338 views
Skip to first unread message

pablo...@gmail.com

unread,
Jun 15, 2014, 6:51:14 PM6/15/14
to jsxg...@googlegroups.com
Hi,

Will you consider supporting common UI elements?
Checkbox
Input Box
Button
Drop-down list

We can use arbitrary HTML and JavaScript with jsxgraph but there is an advantage in having common used UI elements as jsxgraph elements.
We will be able to use buttons with JessieCode and tools like http://bin.sketchometry.com.
A UI element implemented as a jsxgraph element will be accessed and tracked with the usual API without specific code.
For example, I'm creating a log of a student actions in a board. I can't support buttons because that will require custom code for each board.
It will also improve compatibility with other software.

Geogebra calls them Action Objects.
http://wiki.geogebra.org/en/Action_Objects
http://lokar.fmf.uni-lj.si/www/GeoGebra4/GG_Graphics/Insert_button_and_input_box.htm

Thanks

michael

unread,
Jun 24, 2014, 12:19:26 AM6/24/14
to jsxg...@googlegroups.com, pablo...@gmail.com
Hi,

this is actually a very good way to enable the use of HTML elements with JessieCode in a safe way. If you want, you can implement them and send us a pull request.

It's not hard to create your own new elements. See the information and examples in our repository's 'extensions' subfolder:



Michael

pablo...@gmail.com

unread,
Aug 31, 2014, 10:41:25 AM8/31/14
to jsxg...@googlegroups.com, pablo...@gmail.com
I'm trying to start with a checkbox element which should be the simplest input element.
How can I bind the checkbox state (true/false) to other elements?
For example for showing/hiding another element.

I've looked at the extensions and the text element in core.

Where is element.visProp.display = 'html' defined?
What is the difference between using html element and drawing elements in internally in the renderer?
Can just use html elements for checkbox, input button and select elements?

Is it possible to render html element with an extension or is new rendering has to be in core?
Is there an abstract element for implementing new html elements?

The text element code is complex while extensions are relatively simple. Is it because it can be used for several use cases such as labels and stand alone text?
Should I expect the same level of complexity
https://github.com/jsxgraph/jsxgraph/blob/master/src/base/text.js
https://github.com/jsxgraph/jsxgraph/blob/master/extensions/square.js

Some relevant functions in the renderer.
drawText
Check for element.visProp.display === 'html
https://github.com/jsxgraph/jsxgraph/blob/master/src/renderer/abstract.js#L599

updateText
https://github.com/jsxgraph/jsxgraph/blob/master/src/renderer/abstract.js#L635

drawInternalText
https://github.com/jsxgraph/jsxgraph/blob/master/src/renderer/abstract.js#L575

updateInternalText
https://github.com/jsxgraph/jsxgraph/blob/master/src/renderer/abstract.js#L587

Thanks
Pablo

Alfred Wassermann

unread,
Sep 8, 2014, 5:47:10 AM9/8/14
to jsxg...@googlegroups.com, pablo...@gmail.com
Hi Pablo,
the default attribute
   element.visProp.display = 'html'
is set in options.js.
If you start to implement e.g. a checkbox element you may have a look at my htmlSlider implementation in text.js:
https://github.com/jsxgraph/jsxgraph/blob/master/src/base/text.js, starting from line 835.

    JXG.createHTMLSlider = function (board, parents, attributes) {
       var t, par,
           attr = Type.copyAttributes(attributes, board.options, 'htmlslider');


        if (parents.length !== 2 || parents[0].length !== 2 || parents[1].length !== 3) {
           throw new Error("JSXGraph: Can't create htmlslider with parent types '" +
               (typeof parents[0]) + "' and '" + (typeof parents[1]) + "'." +
               "\nPossible parents are: [[x,y], [min, start, max]]");
       }


        // backwards compatibility
       attr.anchor = attr.parent || attr.anchor;
       attr.fixed = attr.fixed || true;


        par = [parents[0][0], parents[0][1],
           '<form style="display:inline">' +
           '<input type="range" /><span></span><input type="text" />' +
           '</form>'];

       t = JXG.createText(board, par, attr);
       t.type = Type.OBJECT_TYPE_HTMLSLIDER;

       t.rendNodeForm = t.rendNode.childNodes[0];
       t.rendNodeForm.id = t.rendNode.id + '_form';


       t.rendNodeRange = t.rendNodeForm.childNodes[0];
       t.rendNodeRange.id = t.rendNode.id + '_range';
       t.rendNodeRange.min = parents[1][0];
       t.rendNodeRange.max = parents[1][2];
       t.rendNodeRange.step = attr.step;
       t.rendNodeRange.value = parents[1][1];


       t.rendNodeLabel = t.rendNodeForm.childNodes[1];
       t.rendNodeLabel.id = t.rendNode.id + '_label';


        if (attr.withlabel) {
           t.rendNodeLabel.innerHTML = t.name + '=';
       }


       t.rendNodeOut = t.rendNodeForm.childNodes[2];
       t.rendNodeOut.id = t.rendNode.id + '_out';
       t.rendNodeOut.value = parents[1][1];


       t.rendNodeRange.style.width = attr.widthrange + 'px';
       t.rendNodeRange.style.verticalAlign = 'middle';
       t.rendNodeOut.style.width = attr.widthout + 'px';


       t._val = parents[1][1];


      if (JXG.supportsVML()) {
           /*
           * OnChange event is used for IE browsers
           * The range element is supported since IE10
           */
           Env.addEvent(t.rendNodeForm, 'change', priv.HTMLSliderInputEventHandler, t);
       } else {
           /*
           * OnInput event is used for non-IE browsers
           */
           Env.addEvent(t.rendNodeForm, 'input', priv.HTMLSliderInputEventHandler, t);
       }


       t.Value = function () {
           return this._val;
       };


        return t;
   };

   
JXG.registerElement('htmlslider', JXG.createHTMLSlider);
     



Important is that you follow the convention in naming the method:
JXG.createCheckbox(board, parents, attribute) { ... ]
and then call
JXG.registerElement('checkbox', JXG.createCheckbox);
If you do this, you can call
   attr = Type.copyAttributes(attributes, board.options, 'checkbox');

and therefore get for free the default options which should be (and can be) defined in options.js.

display=='html' means the text is contained in a sperated div-element which is displayed above the JSXGraph canvas.
The only drawback is that if the construction is exported into a png image the text-divs are missing.
For display=='internal' the internal text elements of SVG, canvas and VML are used. Since all these methods are different it is a little bit of a mess to support them all.

You should only allow display==='html'. I'm not aware that SVG text elements and canvas text elements support interactive form elements.
Next, you should provide a method Value() returning true/false in the case of checkboxes.

If you provide the Value method for an element it can be used in every parent or attribute which supports dynamic input:

var check = board.create('checkbox', [3, 5, "Add 5"])  // coordinates and label text are parent elements

var f = board.create('point', [function(){ return 1;}, // X-coordinate
                               
function() {
                                 y
= 2;
                                 
if (check.Value()) {
                                     y
+= 5;
                                 
}
                                 
return y;
                               
}]);

One important point is, you should add an update method for the checkbox element which saves the value in a JavaScript variable.
t.update = function() {
   
this._value = this.rendNode.value;  // rendNode is a pointer to the DOM element, created in JXG.Text
};
Then, in the call of Value() you just refer to this variable:
t.Value = function() {
   
return this._value;


Otherwise there would way too many DOM accesses which would slow down everything.

Further, I would recommend to keep the new elements in a separate file.

Hoe that helps a little bit...
Best wishes and many thanks,
Alfred

 


Reply all
Reply to author
Forward
0 new messages