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