      1 /*
      2     Copyright 2008-2022
      3         Matthias Ehmann,
      4         Michael Gerhaeuser,
      5         Carsten Miller,
      6         Bianca Valentin,
      7         Alfred Wassermann,
      8         Peter Wilfahrt
      9
     10     This file is part of JSXGraph.
     11
     12     JSXGraph is free software dual licensed under the GNU LGPL or MIT License.
     13
     14     You can redistribute it and/or modify it under the terms of the
     15
     16       * GNU Lesser General Public License as published by
     17         the Free Software Foundation, either version 3 of the License, or
     18         (at your option) any later version
     19       OR
     20       * MIT License: https://github.com/jsxgraph/jsxgraph/blob/master/LICENSE.MIT
     21
     22     JSXGraph is distributed in the hope that it will be useful,
     23     but WITHOUT ANY WARRANTY; without even the implied warranty of
     24     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     25     GNU Lesser General Public License for more details.
     26
     27     You should have received a copy of the GNU Lesser General Public License and
     28     the MIT License along with JSXGraph. If not, see <http://www.gnu.org/licenses/>
     29     and <http://opensource.org/licenses/MIT/>.
     30  */
     31
     32
     33 /*global JXG: true, define: true, window: true*/
     34 /*jslint nomen: true, plusplus: true*/
     35
     36 /* depends:
     37  jxg
     38  utils/env
     39  utils/type
     40  */
     41
     42 /**
     43  * @fileoverview In this file the Text element is defined.
     44  */
     45
     46 define([
     47     'jxg', 'utils/env', 'utils/type'
     48 ], function (JXG, Env, Type) {
     49
     50     "use strict";
     51
     52     var priv = {
     53             CheckboxChangeEventHandler: function () {
     54                 this._value = this.rendNodeCheckbox.checked;
     55                 this.board.update();
     56             }
     57         };
     58
     59     /**
     60      * @class This element is used to provide a constructor for special texts containing a
     61      * form checkbox element.
     62      * <p>
     63      * For this element, the attribute "display" has to have the value 'html' (which is the default).
     64      *
     65      * @pseudo
     66      * @description
     67      * @name Checkbox
     68      * @augments Text
     69      * @constructor
     70      * @type JXG.Text
     71      *
     72      * @param {number,function_number,function_String_String} x,y,label Parent elements for checkbox elements.
     73      *                     <p>
     74      *                     x and y are the coordinates of the lower left corner of the text box.
     75      *                      The position of the text is fixed,
     76      *                     x and y are numbers. The position is variable if x or y are functions.
     77      *                     <p>
     78      *                     The label of the input element may be given as string.
     79      *                     <p>
     80      *                     The value of the checkbox can be controlled with the attribute <tt>checked</tt>
     81      *                     <p>The HTML node can be accessed with <tt>element.rendNodeCheckbox</tt>
     82      *
     83      * @example
     84      *   // Create a checkbox element at position [0,3].
     85      *   var checkbox = board.create('checkbox', [0, 3, 'Change Y'], {});
     86      *   var p = board.create('point', [
     87      *       function(){ return 0.5;}, // X-coordinate
     88      *       function() {
     89      *           y = 0.5;
     90      *           if (checkbox.Value()) {
     91      *               y += 0.5;
     92      *           }
     93      *           return y;
     94      *       }]);
     95      * </pre><div class="jxgbox" id="JXG0e835e0b-ed0c-4b85-b682-78158c0e6f5c" style="width: 300px; height: 300px;"></div>
     96      * <script type="text/javascript">
     97      * (function() {
     98      *   var t1_board = JXG.JSXGraph.initBoard('JXG0e835e0b-ed0c-4b85-b682-78158c0e6f5c', {boundingbox: [-3, 6, 5, -3], axis: true, showcopyright: false, shownavigation: false});
     99      *   var checkbox = t1_board.create('checkbox', [0, 3, 'Change Y'], {});
    100      *   var p = t1_board.create('point', [
    101      *       function(){ return 0.5;}, // X-coordinate
    102      *       function() {
    103      *           y = 0.5;
    104      *           if (checkbox.Value()) {
    105      *               y += 0.5;
    106      *           }
    107      *           return y;
    108      *       }]);
    109      * })();
    110      * </script><pre>
    111      *
    112      * The checkbox can be supplied with custom-made events by using the property rendNodeCheckbox.
    113      * @example
    114      * var checkbox = board.create('checkbox', [0, 4, 'Click me']),
    115      *     p = board.create('point', [1, 1]);
    116      *
    117      * JXG.addEvent(checkbox.rendNodeCheckbox, 'change', function() {
    118      *     if (this.Value()) {
    119      *         p.moveTo([4, 1]);
    120      *     } else {
    121      *         p.moveTo([1, 1]);
    122      *     }
    123      * }, checkbox);
    124      * </pre><div class="jxgbox" id="JXGb2f2345a-057d-44ce-bd7a-6aaff70bc810" style="width: 300px; height: 300px;"></div>
    125      * <script type="text/javascript">
    126      * (function() {
    127      * var board = JXG.JSXGraph.initBoard('JXGb2f2345a-057d-44ce-bd7a-6aaff70bc810', {boundingbox: [-3, 6, 5, -3], axis: true, showcopyright: false, shownavigation: false});
    128      * var checkbox = board.create('checkbox', [0, 4, 'Click me']),
    129      *     p = board.create('point', [1, 1]);
    130      *
    131      * JXG.addEvent(checkbox.rendNodeCheckbox, 'change', function() {
    132      *     if (this.Value()) {
    133      *         p.moveTo([4, 1]);
    134      *     } else {
    135      *         p.moveTo([1, 1]);
    136      *     }
    137      * }, checkbox);
    138      * })();
    139      * </script><pre>
    140      *
    141      * @example
    142      *         var i1 = board.create('input', [-3, 4, 'sin(x)', 'f(x)='], {cssStyle: 'width:4em', maxlength: 2});
    143      *         var c1 = board.create('checkbox', [-3, 2, 'label 1'], {});
    144      *         var b1 = board.create('button', [-3, -1, 'Change texts', function () {
    145      *                 i1.setText('g(x)');
    146      *                 i1.set('cos(x)');
    147      *                 c1.setText('label 2');
    148      *                 b1.setText('Texts are changed');
    149      *             }],
    150      *             {cssStyle: 'width:400px'});
    151      *
    152      * </pre><div id="JXG11cac8gg-2354-47e7-9da4-eb298e53de05" class="jxgbox" style="width: 300px; height: 300px;"></div>
    153      * <script type="text/javascript">
    154      *     (function() {
    155      *         var board = JXG.JSXGraph.initBoard('JXG11cac8gg-2354-47e7-9da4-eb298e53de05',
    156      *             {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false});
    157      *             var i1 = board.create('input', [-3, 4, 'sin(x)', 'f(x)='], {cssStyle: 'width:4em', maxlength: 2});
    158      *             var c1 = board.create('checkbox', [-3, 2, 'label 1'], {});
    159      *             var b1 = board.create('button', [-3, -1, 'Change texts', function () {
    160      *                     i1.setText('g(x)');
    161      *                     i1.set('cos(x)');
    162      *                     c1.setText('label 2');
    163      *                     b1.setText('Texts are changed');
    164      *                 }],
    165      *                 {cssStyle: 'width:400px'});
    166      *
    167      *     })();
    168      *
    169      * </script><pre>
    170      */
    171     JXG.createCheckbox = function (board, parents, attributes) {
    172         var t, par,
    173             attr = Type.copyAttributes(attributes, board.options, 'checkbox');
    174
    175         //if (parents.length !== 3) {
    176             //throw new Error("JSXGraph: Can't create checkbox with parent types '" +
    177             //    (typeof parents[0]) + "' and '" + (typeof parents[1]) + "'." +
    178             //    "\nPossible parents are: [[x,y], label]");
    179         //}
    180
    181         par = [parents[0], parents[1],
    182             '<span style="display:inline">' +
    183             '<input type="checkbox" /><label for=""></label>' +
    184             '</span>'
    185             ];
    186
    187         //t = JXG.createText(board, par, attr);
    188         t = board.create('text', par, attr);
    189         t.type = Type.OBJECT_TYPE_CHECKBOX;
    190
    191         t.rendNodeCheckbox = t.rendNode.childNodes[0].childNodes[0];
    192         t.rendNodeLabel = t.rendNode.childNodes[0].childNodes[1];
    193
    194         t.rendNodeTag = t.rendNodeCheckbox; // Needed for unified treatment in setAttribute
    195         t.rendNodeTag.disabled = !!attr.disabled;
    196
    197         t.rendNodeLabel.innerHTML = parents[2];
    198         t.rendNodeCheckbox.id = t.rendNode.id + '_checkbox';
    199         t.rendNodeLabel.id = t.rendNode.id + '_label';
    200         t.rendNodeLabel.setAttribute('for', t.rendNodeCheckbox.id);
    201
    202         // This sets the font-size of the checkbox itself
    203         t.visPropOld.fontsize = "0px";
    204         board.renderer.updateTextStyle(t, false);
    205
    206         t.rendNodeCheckbox.checked = attr.checked;
    207
    208         t._value = attr.checked;
    209
    210         /**
    211          * Returns the value of the checkbox element
    212          * @name Value
    213          * @memberOf Checkbox.prototype
    214          * @function
    215          * @returns {String} value of the checkbox.
    216          */
    217         t.Value = function () {
    218             return this._value;
    219         };
    220
    221         t.update = function () {
    222             if (this.needsUpdate) {
    223                 JXG.Text.prototype.update.call(this);
    224                 this._value = this.rendNodeCheckbox.checked;
    225             }
    226             return this;
    227         };
    228
    229         Env.addEvent(t.rendNodeCheckbox, 'change', priv.CheckboxChangeEventHandler, t);
    230
    231         return t;
    232     };
    233
    234     JXG.registerElement('checkbox', JXG.createCheckbox);
    235
    236     return {
    237         createCheckbox: JXG.createCheckbox
    238     };
    239 });
    240