1 /*
  2     Copyright 2008-2016
  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             InputInputEventHandler: function (evt) {
 54                 this._value = this.rendNodeInput.value;
 55                 this.board.update();
 56             }
 57         };
 58 
 59     /**
 60      * @class This element is used to provide a constructor for special texts containing a form input element.
 61      *
 62      * @pseudo
 63      * @description
 64      * @name Input
 65      * @augments Text
 66      * @constructor
 67      * @type JXG.Text
 68      *
 69      * @param {number,function_number,function_String_String} x,y,value,label Parent elements for input elements.
 70      *                     <p>
 71      *                     x and y are the coordinates of the lower left corner of the text box. 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 default value of the input element may be given as string.
 75      *                     <p>
 76      *                     The label of the input element may be given  as string.
 77      *
 78      * @example
 79      *  // Create an input element at position [1,4].
 80      *  var input = board.create('input', [0, 1, 'sin(x)*x', 'f(x)='], {});
 81      *  var f = board.jc.snippet(input.Value(), true, 'x', false);
 82      *  var graph = board.create('functiongraph',[f,
 83      *          function() {text:dsddfghj
 84      *            var c = new JXG.Coords(JXG.COORDS_BY_SCREEN,[0,0],board);
 85      *            return c.usrCoords[1];
 86      *          },
 87      *          function() {
 88      *            var c = new JXG.Coords(JXG.COORDS_BY_SCREEN,[board.canvasWidth,0],board);
 89      *            return c.usrCoords[1];
 90      *          }
 91      *        ]);
 92      *
 93      *  board.create('text', [1, 3, '<button onclick="updateGraph()">Update graph</button>']);
 94      *
 95      *  var updateGraph = function() {
 96      *      graph.Y = board.jc.snippet(input.Value(), true, 'x', false);
 97      *      graph.updateCurve();
 98      *      board.update();
 99      *  }
100      * </pre><div class="jxgbox"id="c70f55f1-21ba-4719-a37d-a93ae2943faa" style="width: 500px; height: 300px;"></div>
101      * <script type="text/javascript">
102      *   var t1_board = JXG.JSXGraph.initBoard('c70f55f1-21ba-4719-a37d-a93ae2943faa', {boundingbox: [-3, 6, 5, -3], axis: true, showcopyright: false, shownavigation: false});
103      *   var input = t1_board.create('input', [1, 4, 'sin(x)*x', 'f(x)='], {});
104      *   var f = t1_board.jc.snippet(input.Value(), true, 'x', false);
105      *   var graph = t1_board.create('functiongraph',[f,
106      *          function() {
107      *            var c = new JXG.Coords(JXG.COORDS_BY_SCREEN,[0,0],t1_board);
108      *            return c.usrCoords[1];
109      *          },
110      *          function() {
111      *            var c = new JXG.Coords(JXG.COORDS_BY_SCREEN,[t1_board.canvasWidth,0],t1_board);
112      *            return c.usrCoords[1];
113      *          }
114      *        ]);
115      *
116      *  t1_board.create('text', [1, 3, '<button onclick="updateGraph()">Update graph</button>']);
117      *
118      *  var updateGraph = function() {
119      *      graph.Y = t1_board.jc.snippet(input.Value(), true, 'x', false);
120      *      graph.updateCurve();
121      *      t1_board.update();
122      *  }
123      * </script><pre>
124      */
125     JXG.createInput = function (board, parents, attributes) {
126         var t, par,
127             attr = Type.copyAttributes(attributes, board.options, 'input');
128 
129         //if (parents.length !== 4) {
130             //throw new Error("JSXGraph: Can't create input with parent types '" +
131             //    (typeof parents[0]) + "' and '" + (typeof parents[1]) + "'." +
132             //    "\nPossible parents are: [x, y, value, label]");
133         //}
134 
135         par = [parents[0], parents[1],
136             '<form style="display:inline">' +
137             '<span></span><input type="text" />' +
138             '</form>'
139             ];
140 
141         t = JXG.createText(board, par, attr);
142         t.type = Type.OBJECT_TYPE_INPUT;
143 
144         t.rendNodeForm = t.rendNode.childNodes[0];
145         t.rendNodeForm.id = t.rendNode.id + '_form';
146 
147         t.rendNodeLabel = t.rendNodeForm.childNodes[0];
148         t.rendNodeLabel.id = t.rendNode.id + '_label';
149         t.rendNodeLabel.innerHTML = parents[3];
150 
151         t.rendNodeInput = t.rendNodeForm.childNodes[1];
152         t.rendNodeInput.id = t.rendNode.id + '_input';
153         t.rendNodeInput.value = parents[2];
154 
155         t.rendNodeTag = t.rendNodeInput; // Needed for unified treatment in setAttribute
156         t.rendNodeTag.disabled = !!attr.disabled;
157 
158         // This sets the font-size of the input HTML element
159         t.visPropOld.fontsize = "0px";
160         board.renderer.updateTextStyle(t, false);
161 
162         t._value = parents[2];
163 
164         t.Value = function () {
165             return this._value;
166         };
167 
168         t.update = function () {
169             if (this.needsUpdate) {
170                 this._value = this.rendNodeInput.value;
171             }
172             return this;
173         };
174 
175         Env.addEvent(t.rendNodeInput, 'input', priv.InputInputEventHandler, t);
176 
177         //Env.addEvent(t.rendNodeInput, 'mousedown', function(evt) { evt.stopPropagation(); }, t);
178 
179         return t;
180     };
181 
182     JXG.registerElement('input', JXG.createInput);
183 
184     return {
185         createInput: JXG.createInput
186     };
187 });
188