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