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 ButtonClickEventHandler: function () { 45 if (this._handler) { 46 this._handler(); 47 } 48 this.board.update(); 49 } 50 }; 51 52 /** 53 * @class This element is used to provide a constructor for special texts containing a 54 * form button element. 55 * <p> 56 * For this element, the attribute "display" has to have the value 'html' (which is the default). 57 * <p> 58 * The underlying HTML button element can be accessed through the sub-object 'rendNodeButton', e.g. to 59 * add event listeners. 60 * 61 * @pseudo 62 * @name Button 63 * @augments Text 64 * @constructor 65 * @type JXG.Text 66 * 67 * @param {number,function_number,function_String,function_function} x,y,label,handler Parent elements for button elements. 68 * <p> 69 * x and y are the coordinates of the lower left corner of the text box. 70 * The position of the text is fixed, 71 * x and y are numbers. The position is variable if x or y are functions. 72 * <p> 73 * The label of the input element may be given as string. 74 * <p> 75 * The (optional) handler function which is called when the button is pressed. 76 * 77 * @example 78 * var p = board.create('point', [0.5, 0.5], {id: 'p1'}); 79 * 80 * // Create a button element at position [1,2]. 81 * var button1 = board.create('button', [1, 2, 'Change Y with JavaScript', function() { 82 * p.moveTo([p.X(), p.Y() + 0.5], 100); 83 * }], {}); 84 * 85 * // Create a button element at position [1,4]. 86 * var button2 = board.create('button', [1, 4, 'Change Y with JessieCode', 87 * "$('p1').Y = $('p1').Y() - 0.5;" 88 * ], {}); 89 * 90 * </pre><div class="jxgbox" id="JXGf19b1bce-dd00-4e35-be97-ff1817d11514" style="width: 500px; height: 300px;"></div> 91 * <script type="text/javascript"> 92 * var t1_board = JXG.JSXGraph.initBoard('JXGf19b1bce-dd00-4e35-be97-ff1817d11514', {boundingbox: [-3, 6, 5, -3], axis: true, showcopyright: false, shownavigation: false}); 93 * var p = t1_board.create('point', [0, -1], {id: 'p1'}); 94 * 95 * // Create a button element at position [1,2]. 96 * var button1 = t1_board.create('button', [1, 2, 'Change Y with JavaScript', function() { 97 * p.moveTo([p.X(), p.Y() + 0.5], 100); 98 * }], {}); 99 * 100 * // Create a button element at position [1,4]. 101 * var button2 = t1_board.create('button', [1, 4, 'Change Y with JessieCode', 102 * "$('p1').Y = $('p1').Y() - 0.5;" 103 * ], {}); 104 * 105 * </script><pre> 106 * 107 * @example 108 * // A toggle button 109 * var butt = board.create('button', [-2, -2, 'Off', function() { 110 * var txt; 111 * butt.value = !butt.value; 112 * if (butt.value) { 113 * txt = 'On'; 114 * } else { 115 * txt = 'Off'; 116 * } 117 * butt.rendNodeButton.innerHTML = txt; 118 * }]); 119 * 120 * // Set initial value for the button 121 * if (!JXG.exists(butt.value)) { 122 * butt.value = false; 123 * } 124 * 125 * var p = board.create('point', [2, -2], { 126 * visible: () => butt.value 127 * }); 128 * 129 * 130 * 131 * </pre><div id="JXGa1eaab8f-c73b-4660-96ce-4ca17bcac4d6" class="jxgbox" style="width: 300px; height: 300px;"></div> 132 * <script type="text/javascript"> 133 * (function() { 134 * var board = JXG.JSXGraph.initBoard('JXGa1eaab8f-c73b-4660-96ce-4ca17bcac4d6', 135 * {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false}); 136 * var butt = board.create('button', [-2, -2, 'Off', function() { 137 * var txt; 138 * butt.value = !butt.value; 139 * if (butt.value) { 140 * txt = 'On'; 141 * } else { 142 * txt = 'Off'; 143 * } 144 * butt.rendNodeButton.innerHTML = txt; 145 * }]); 146 * 147 * // Set initial value for the button 148 * if (!JXG.exists(butt.value)) { 149 * butt.value = false; 150 * } 151 * 152 * var p = board.create('point', [2, -2], { 153 * visible: () => butt.value 154 * }); 155 * 156 * })(); 157 * 158 * </script><pre> 159 * 160 * @example 161 * var i1 = board.create('input', [-3, 4, 'sin(x)', 'f(x)='], {cssStyle: 'width:4em', maxlength: 2}); 162 * var c1 = board.create('checkbox', [-3, 2, 'label 1'], {}); 163 * var b1 = board.create('button', [-3, -1, 'Change texts', function () { 164 * i1.setText('g(x)'); 165 * i1.set('cos(x)'); 166 * c1.setText('label 2'); 167 * b1.setText('Texts are changed'); 168 * }], 169 * {cssStyle: 'width:400px'}); 170 * 171 * </pre><div id="JXG11cac8ff-2354-47e7-9da4-eb928e53de05" class="jxgbox" style="width: 300px; height: 300px;"></div> 172 * <script type="text/javascript"> 173 * (function() { 174 * var board = JXG.JSXGraph.initBoard('JXG11cac8ff-2354-47e7-9da4-eb928e53de05', 175 * {boundingbox: [-8, 8, 8,-8], axis: true, showcopyright: false, shownavigation: false}); 176 * var i1 = board.create('input', [-3, 4, 'sin(x)', 'f(x)='], {cssStyle: 'width:4em', maxlength: 2}); 177 * var c1 = board.create('checkbox', [-3, 2, 'label 1'], {}); 178 * var b1 = board.create('button', [-3, -1, 'Change texts', function () { 179 * i1.setText('g(x)'); 180 * i1.set('cos(x)'); 181 * c1.setText('label 2'); 182 * b1.setText('Texts are changed'); 183 * }], 184 * {cssStyle: 'width:400px'}); 185 * 186 * })(); 187 * 188 * </script><pre> 189 * 190 */ 191 JXG.createButton = function (board, parents, attributes) { 192 var t, 193 par, 194 attr = Type.copyAttributes(attributes, board.options, "button"); 195 196 //if (parents.length < 3) { 197 //throw new Error("JSXGraph: Can't create button with parent types '" + 198 // (typeof parents[0]) + "' and '" + (typeof parents[1]) + "'." + 199 // "\nPossible parents are: [x, y, label, handler]"); 200 //} 201 202 // 1. Create empty button 203 par = [parents[0], parents[1], '<button type="button" style="width:100%;"></button>']; 204 t = board.create("text", par, attr); 205 t.type = Type.OBJECT_TYPE_BUTTON; 206 207 t.rendNodeButton = t.rendNode.childNodes[0]; 208 t.rendNodeButton.id = t.rendNode.id + "_button"; 209 // t.rendNodeButton.innerHTML = parents[2]; 210 211 t.rendNodeTag = t.rendNodeButton; // Needed for unified treatment in setAttribute 212 t.rendNodeTag.disabled = !!attr.disabled; 213 214 // 2. Set parents[2] (string|function) as content of the button. 215 // abstract.js selects the correct DOM element for the update 216 t.setText(parents[2]); 217 218 // This sets the font-size of the button text 219 t.visPropOld.fontsize = "0px"; 220 board.renderer.updateTextStyle(t, false); 221 222 if (parents[3]) { 223 if (Type.isString(parents[3])) { 224 t._jc = new JXG.JessieCode(); 225 t._jc.use(board); 226 t._handler = function () { 227 t._jc.parse(parents[3]); 228 }; 229 } else { 230 t._handler = parents[3]; 231 } 232 } 233 234 Env.addEvent(t.rendNodeButton, "click", priv.ButtonClickEventHandler, t); 235 Env.addEvent( 236 t.rendNodeButton, 237 "mousedown", 238 function (evt) { 239 if (Type.exists(evt.stopPropagation)) { 240 evt.stopPropagation(); 241 } 242 }, 243 t 244 ); 245 Env.addEvent( 246 t.rendNodeButton, 247 "touchstart", 248 function (evt) { 249 if (Type.exists(evt.stopPropagation)) { 250 evt.stopPropagation(); 251 } 252 }, 253 t 254 ); 255 Env.addEvent( 256 t.rendNodeButton, 257 "pointerdown", 258 function (evt) { 259 if (Type.exists(evt.stopPropagation)) { 260 evt.stopPropagation(); 261 } 262 }, 263 t 264 ); 265 266 return t; 267 }; 268 269 JXG.registerElement("button", JXG.createButton); 270 271 // export default { 272 // createButton: JXG.createButton 273 // }; 274