1 /* 2 Copyright 2008-2025 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.js"; 40 import Env from "../utils/env.js"; 41 import Type from "../utils/type.js"; 42 43 var priv = { 44 /** 45 * @class 46 * @ignore 47 */ 48 CheckboxChangeEventHandler: function () { 49 this._value = this.rendNodeCheckbox.checked; 50 this.board.update(); 51 } 52 }; 53 54 /** 55 * @class A text element that contains an HTML checkbox tag. 56 * For this element, the attribute "display" has to have the value 'html' (which is the default). 57 * 58 * <p><b>Setting a CSS class:</b> The attribute <tt>cssClass</tt> affects the HTML div element that contains the checkbox element. To change the CSS properties of the HTML checkbox element a selector of the form 59 * <tt>.mycheck > checkbox { ... }</tt> has to be used. See the analog example for buttons: 60 * {@link Button}. 61 * 62 * <p><b>Access the checkbox element with JavaScript:</b> 63 * The underlying HTML checkbox element can be accessed through the sub-object 'rendNodeCheck', e.g. to 64 * add event listeners. 65 * 66 * @pseudo 67 * @name Checkbox 68 * @augments Text 69 * @constructor 70 * @type JXG.Text 71 * 72 * @param {number,function_number,function_String,function} 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 or function. 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 * @example 141 * var i1 = board.create('input', [1, 5, 'sin(x)', 'f(x)='], {cssStyle: 'width:4em', maxlength: 2}); 142 * var c1 = board.create('checkbox', [1, 3, 'label 1'], {}); 143 * var b1 = board.create('button', [1, 1, 'Change texts', function () { 144 * i1.setText('g(x)='); 145 * i1.set('cos(x)'); 146 * c1.setText('label 2'); 147 * b1.setText('Texts are changed'); 148 * }], 149 * {cssStyle: 'width:200px'}); 150 * 151 * </pre><div id="JXG31c6d070-354b-4f09-aab9-9aaa796f730c" class="jxgbox" style="width: 300px; height: 300px;"></div> 152 * <script type="text/javascript"> 153 * (function() { 154 * var board = JXG.JSXGraph.initBoard('JXG31c6d070-354b-4f09-aab9-9aaa796f730c', 155 * {boundingbox: [-1, 7, 7, -1], axis: true, showcopyright: false, shownavigation: false}); 156 * var i1 = board.create('input', [1, 5, 'sin(x)', 'f(x)='], {cssStyle: 'width:4em', maxlength: 2}); 157 * var c1 = board.create('checkbox', [1, 3, 'label 1'], {}); 158 * var b1 = board.create('button', [1, 1, 'Change texts', function () { 159 * i1.setText('g(x)='); 160 * i1.set('cos(x)'); 161 * c1.setText('label 2'); 162 * b1.setText('Texts are changed'); 163 * }], 164 * {cssStyle: 'width:200px'}); 165 * 166 * })(); 167 * 168 * </script><pre> 169 * 170 */ 171 JXG.createCheckbox = function (board, parents, attributes) { 172 var t, 173 par, 174 attr = Type.copyAttributes(attributes, board.options, "checkbox"); 175 176 //if (parents.length !== 3) { 177 //throw new Error("JSXGraph: Can't create checkbox with parent types '" + 178 // (typeof parents[0]) + "' and '" + (typeof parents[1]) + "'." + 179 // "\nPossible parents are: [[x,y], label]"); 180 //} 181 182 par = [ 183 parents[0], 184 parents[1], 185 '<span style="display:inline">' + 186 '<input type="checkbox" /><label for=""></label>' + 187 "</span>" 188 ]; 189 190 // 1. Create checkbox element with empty label 191 t = board.create("text", par, attr); 192 t.type = Type.OBJECT_TYPE_CHECKBOX; 193 194 t.rendNodeCheckbox = t.rendNode.childNodes[0].childNodes[0]; 195 t.rendNodeLabel = t.rendNode.childNodes[0].childNodes[1]; 196 197 t.rendNodeTag = t.rendNodeCheckbox; // Needed for unified treatment in setAttribute 198 t.rendNodeTag.disabled = !!attr.disabled; 199 200 // t.rendNodeLabel.innerHTML = parents[2]; 201 t.rendNodeCheckbox.id = t.rendNode.id + "_checkbox"; 202 t.rendNodeLabel.id = t.rendNode.id + "_label"; 203 t.rendNodeLabel.setAttribute("for", t.rendNodeCheckbox.id); 204 205 // 2. Set parents[2] (string|function) as label of the checkbox element. 206 // abstract.js selects the correct DOM element for the update 207 t.setText(parents[2]); 208 209 // This sets the font-size of the checkbox itself 210 t.visPropOld.fontsize = "0px"; 211 board.renderer.updateTextStyle(t, false); 212 213 t.rendNodeCheckbox.checked = attr.checked; 214 215 t._value = attr.checked; 216 217 /** 218 * Returns the value of the checkbox element 219 * @name Value 220 * @memberOf Checkbox.prototype 221 * @function 222 * @returns {String} value of the checkbox. 223 */ 224 t.Value = function () { 225 return this._value; 226 }; 227 228 /** 229 * @class 230 * @ignore 231 */ 232 t.update = function () { 233 if (this.needsUpdate) { 234 JXG.Text.prototype.update.call(this); 235 this._value = this.rendNodeCheckbox.checked; 236 } 237 return this; 238 }; 239 240 Env.addEvent(t.rendNodeCheckbox, "change", priv.CheckboxChangeEventHandler, t); 241 242 return t; 243 }; 244 245 JXG.registerElement("checkbox", JXG.createCheckbox); 246 247 // export default { 248 // createCheckbox: JXG.createCheckbox 249 // }; 250