1 /* 2 Copyright 2008-2023 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 <https://www.gnu.org/licenses/> 29 and <https://opensource.org/licenses/MIT/>. 30 */ 31 32 /*global JXG: true, define: true, window: true*/ 33 /*jslint nomen: true, plusplus: true*/ 34 35 /** 36 * @fileoverview In this file the Text element is defined. 37 */ 38 39 import JXG from "../jxg"; 40 import Env from "../utils/env"; 41 import Type from "../utils/type"; 42 43 var priv = { 44 CheckboxChangeEventHandler: function () { 45 this._value = this.rendNodeCheckbox.checked; 46 this.board.update(); 47 } 48 }; 49 50 /** 51 * @class This element is used to provide a constructor for special texts containing a 52 * form checkbox element. 53 * <p> 54 * For this element, the attribute "display" has to have the value 'html' (which is the default). 55 * <p> 56 * The underlying HTML checkbox element can be accessed through the sub-object 'rendNodeCheck', e.g. to 57 * add event listeners. 58 * 59 * @pseudo 60 * @description 61 * @name Checkbox 62 * @augments Text 63 * @constructor 64 * @type JXG.Text 65 * 66 * @param {number,function_number,function_String,function} x,y,label Parent elements for checkbox elements. 67 * <p> 68 * x and y are the coordinates of the lower left corner of the text box. 69 * The position of the text is fixed, 70 * x and y are numbers. The position is variable if x or y are functions. 71 * <p> 72 * The label of the input element may be given as string or function. 73 * <p> 74 * The value of the checkbox can be controlled with the attribute <tt>checked</tt> 75 * <p>The HTML node can be accessed with <tt>element.rendNodeCheckbox</tt> 76 * 77 * @example 78 * // Create a checkbox element at position [0,3]. 79 * var checkbox = board.create('checkbox', [0, 3, 'Change Y'], {}); 80 * var p = board.create('point', [ 81 * function(){ return 0.5;}, // X-coordinate 82 * function() { 83 * y = 0.5; 84 * if (checkbox.Value()) { 85 * y += 0.5; 86 * } 87 * return y; 88 * }]); 89 * </pre><div class="jxgbox" id="JXG0e835e0b-ed0c-4b85-b682-78158c0e6f5c" style="width: 300px; height: 300px;"></div> 90 * <script type="text/javascript"> 91 * (function() { 92 * var t1_board = JXG.JSXGraph.initBoard('JXG0e835e0b-ed0c-4b85-b682-78158c0e6f5c', {boundingbox: [-3, 6, 5, -3], axis: true, showcopyright: false, shownavigation: false}); 93 * var checkbox = t1_board.create('checkbox', [0, 3, 'Change Y'], {}); 94 * var p = t1_board.create('point', [ 95 * function(){ return 0.5;}, // X-coordinate 96 * function() { 97 * y = 0.5; 98 * if (checkbox.Value()) { 99 * y += 0.5; 100 * } 101 * return y; 102 * }]); 103 * })(); 104 * </script><pre> 105 * 106 * The checkbox can be supplied with custom-made events by using the property rendNodeCheckbox. 107 * @example 108 * var checkbox = board.create('checkbox', [0, 4, 'Click me']), 109 * p = board.create('point', [1, 1]); 110 * 111 * JXG.addEvent(checkbox.rendNodeCheckbox, 'change', function() { 112 * if (this.Value()) { 113 * p.moveTo([4, 1]); 114 * } else { 115 * p.moveTo([1, 1]); 116 * } 117 * }, checkbox); 118 * </pre><div class="jxgbox" id="JXGb2f2345a-057d-44ce-bd7a-6aaff70bc810" style="width: 300px; height: 300px;"></div> 119 * <script type="text/javascript"> 120 * (function() { 121 * var board = JXG.JSXGraph.initBoard('JXGb2f2345a-057d-44ce-bd7a-6aaff70bc810', {boundingbox: [-3, 6, 5, -3], axis: true, showcopyright: false, shownavigation: false}); 122 * var checkbox = board.create('checkbox', [0, 4, 'Click me']), 123 * p = board.create('point', [1, 1]); 124 * 125 * JXG.addEvent(checkbox.rendNodeCheckbox, 'change', function() { 126 * if (this.Value()) { 127 * p.moveTo([4, 1]); 128 * } else { 129 * p.moveTo([1, 1]); 130 * } 131 * }, checkbox); 132 * })(); 133 * </script><pre> 134 * 135 * @example 136 * var i1 = board.create('input', [-3, 4, 'sin(x)', 'f(x)='], {cssStyle: 'width:4em', maxlength: 2}); 137 * var c1 = board.create('checkbox', [-3, 2, 'label 1'], {}); 138 * var b1 = board.create('button', [-3, -1, 'Change texts', function () { 139 * i1.setText('g(x)'); 140 * i1.set('cos(x)'); 141 * c1.setText('label 2'); 142 * b1.setText('Texts are changed'); 143 * }], 144 * {cssStyle: 'width:400px'}); 145 * 146 * </pre><div id="JXG11cac8gg-2354-47e7-9da4-eb298e53de05" class="jxgbox" style="width: 300px; height: 300px;"></div> 147 * <script type="text/javascript"> 148 * (function() { 149 * var board = JXG.JSXGraph.initBoard('JXG11cac8gg-2354-47e7-9da4-eb298e53de05', 150 * {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false}); 151 * var i1 = board.create('input', [-3, 4, 'sin(x)', 'f(x)='], {cssStyle: 'width:4em', maxlength: 2}); 152 * var c1 = board.create('checkbox', [-3, 2, 'label 1'], {}); 153 * var b1 = board.create('button', [-3, -1, 'Change texts', function () { 154 * i1.setText('g(x)'); 155 * i1.set('cos(x)'); 156 * c1.setText('label 2'); 157 * b1.setText('Texts are changed'); 158 * }], 159 * {cssStyle: 'width:400px'}); 160 * 161 * })(); 162 * 163 * </script><pre> 164 */ 165 JXG.createCheckbox = function (board, parents, attributes) { 166 var t, 167 par, 168 attr = Type.copyAttributes(attributes, board.options, "checkbox"); 169 170 //if (parents.length !== 3) { 171 //throw new Error("JSXGraph: Can't create checkbox with parent types '" + 172 // (typeof parents[0]) + "' and '" + (typeof parents[1]) + "'." + 173 // "\nPossible parents are: [[x,y], label]"); 174 //} 175 176 par = [ 177 parents[0], 178 parents[1], 179 '<span style="display:inline">' + 180 '<input type="checkbox" /><label for=""></label>' + 181 "</span>" 182 ]; 183 184 // 1. Create checkbox element with empty label 185 t = board.create("text", par, attr); 186 t.type = Type.OBJECT_TYPE_CHECKBOX; 187 188 t.rendNodeCheckbox = t.rendNode.childNodes[0].childNodes[0]; 189 t.rendNodeLabel = t.rendNode.childNodes[0].childNodes[1]; 190 191 t.rendNodeTag = t.rendNodeCheckbox; // Needed for unified treatment in setAttribute 192 t.rendNodeTag.disabled = !!attr.disabled; 193 194 // t.rendNodeLabel.innerHTML = parents[2]; 195 t.rendNodeCheckbox.id = t.rendNode.id + "_checkbox"; 196 t.rendNodeLabel.id = t.rendNode.id + "_label"; 197 t.rendNodeLabel.setAttribute("for", t.rendNodeCheckbox.id); 198 199 // 2. Set parents[2] (string|function) as label of the checkbox element. 200 // abstract.js selects the correct DOM element for the update 201 t.setText(parents[2]); 202 203 // This sets the font-size of the checkbox itself 204 t.visPropOld.fontsize = "0px"; 205 board.renderer.updateTextStyle(t, false); 206 207 t.rendNodeCheckbox.checked = attr.checked; 208 209 t._value = attr.checked; 210 211 /** 212 * Returns the value of the checkbox element 213 * @name Value 214 * @memberOf Checkbox.prototype 215 * @function 216 * @returns {String} value of the checkbox. 217 */ 218 t.Value = function () { 219 return this._value; 220 }; 221 222 t.update = function () { 223 if (this.needsUpdate) { 224 JXG.Text.prototype.update.call(this); 225 this._value = this.rendNodeCheckbox.checked; 226 } 227 return this; 228 }; 229 230 Env.addEvent(t.rendNodeCheckbox, "change", priv.CheckboxChangeEventHandler, t); 231 232 return t; 233 }; 234 235 JXG.registerElement("checkbox", JXG.createCheckbox); 236 237 // export default { 238 // createCheckbox: JXG.createCheckbox 239 // }; 240