diff --git a/corsscripts/stackjsxgraph.js b/corsscripts/stackjsxgraph.js index b4e45d878d4817c3d50d2da255f3d0e34996d340..35310dbb17a5c0d54786a16bf5339a159f43174a 100644 --- a/corsscripts/stackjsxgraph.js +++ b/corsscripts/stackjsxgraph.js @@ -394,6 +394,41 @@ export const stack_jxg = { }; this.custom_bind(inputRef, serializer, deserializer, list_of_objects); + }, + + /** + * Convert a string containing a MAXIMA /STACK expression into a JSXGraph / JessieCode string + * or an array of JSXGraph / JessieCode strings. + * + * @example + * console.log( stack_jxg.stack2jsxgraph("%e**x") ); + * // Output: + * // "EULER**x" + * + * @example + * console.log( stack_jxg.stack2jsxgraph("[%pi*(x**2 - 1), %phi*(x - 1), %gamma*(x+1)]") ); + * // Output: + * // [ "PI*(x**2 - 1)", "1.618033988749895*(x - 1)", "0.5772156649015329*(x+1)" ] + * + * @param {String} str + * @returns String + */ + stack2jsxgraph: function(str) { + var t; + + t = str. + replace(/%pi/g, 'PI'). + replace(/%e/g, 'EULER'). + replace(/%phi/g, '1.618033988749895'). + replace(/%gamma/g, '0.5772156649015329'). + trim(); + + // String containing array -> array containing strings + if (t[0] === '[' && t[t.length - 1] === ']') { + t = t.slice(1, -1).split(/\s*,\s*/); + } + + return t; } }; diff --git a/corsscripts/stackjsxgraph.min.js b/corsscripts/stackjsxgraph.min.js index b99c843392f7bfd35f974bebf58e846b016bd92a..b43273fae533af2fa0338a24671bede432d58960 100644 --- a/corsscripts/stackjsxgraph.min.js +++ b/corsscripts/stackjsxgraph.min.js @@ -1 +1 @@ -"use strict";var serializers={};var deserializers={};var initials={};var objectgroups=[];var objectinput={};var registeredobjects={};var active=false;function _commonsetup(inputname){if(!(inputname in serializers)){serializers[inputname]={};deserializers[inputname]=[];var input=document.getElementById(inputname);input.addEventListener("input",()=>generalinputupdatehandler(inputname));input.addEventListener("change",()=>generalinputupdatehandler(inputname))}}function registerobject(object,eventtype){if(eventtype===undefined){eventtype=["update"]}else if(typeof eventtype==="string"||eventtype instanceof String){eventtype=[eventtype]}eventtype.forEach(et=>{if(!(et in registeredobjects)){registeredobjects[et]={}}if(!(object.id in registeredobjects[et])){object.board.on(et,()=>generalobjectupdatehandlerid(object.id));registeredobjects[et][object.id]=object}})}function pointserializer(point){return JSON.stringify([point.X(),point.Y()])}function pointdeserializer(point,data){try{var tmp=JSON.parse(data);if(typeof tmp[0]=="number"&&typeof tmp[1]=="number"){point.setPosition(JXG.COORDS_BY_USER,tmp);point.board.update();point.update()}}catch(err){}}function pointdeserializerparsed(point,data){try{if(typeof data[0]=="number"&&typeof data[1]=="number"){point.setPosition(JXG.COORDS_BY_USER,data);point.board.update();point.update()}}catch(err){}}function sliderserializer(slider){return JSON.stringify(slider.Value())}function sliderdeserializer(slider,data){try{slider.setValue(JSON.parse(data));slider.board.update();slider.update()}catch(err){}}function generalobjectupdatehandler(object){generalobjectupdatehandlerid(object.id)}function generalobjectupdatehandlerid(id){if(!active){active=true;try{var handledinputs=[];if(id in objectinput){for(var i=0;i<objectinput[id].length;i++){var inputname=objectinput[id][i];if(handledinputs.indexOf(inputname)===-1){handledinputs.push(inputname);var input=document.getElementById(inputname);var val=serializers[inputname][id]();if(val!==initials[inputname]){initials[inputname]=null;input.value=val}else{active=false;return}}}}for(var gi=0;gi<objectgroups.length;gi++){var group=objectgroups[gi];if(group.indexOf(id)!==-1){for(var gt=0;gt<group.length;gt++){var obj=group[gt];if(obj!==id){if(obj in objectinput){for(var i=0;i<objectinput[obj].length;i++){var inputname=objectinput[obj][i];if(handledinputs.indexOf(inputname)===-1){initials[inputname]=null;handledinputs.push(inputname);var input=document.getElementById(inputname);input.value=serializers[inputname][obj]()}}}}}}}for(var i=0;i<handledinputs.length;i++){var input=document.getElementById(handledinputs[i]);var e=new Event("change");input.dispatchEvent(e)}}catch(err){}active=false}}function generalinputupdatehandler(inputname){if(inputname in deserializers){var input=document.getElementById(inputname);var keys=Object.keys(serializers[inputname]);var ok=false;for(var i=0;i<keys.length;i++){var old=serializers[inputname][keys[i]]();if(old!==input.value){ok=true;i=keys.length+1}}if(ok){for(var i=0;i<deserializers[inputname].length;i++){deserializers[inputname][i](input.value)}}}}export const stack_jxg={define_group:function(list){var l=[];for(var i=0;i<list.length;i++){if(l.indexOf(list[i].id)===-1){l.push(list[i].id)}}objectgroups.push(l)},starts_moved:function(obj){if(obj.id in objectinput){for(var i=0;i<objectinput[obj.id].length;i++){initials[objectinput[obj.id][i]]=null}generalobjectupdatehandler(obj)}},clear_initial:function(obj){if(obj.id in objectinput){for(var i=0;i<objectinput[obj.id].length;i++){initials[objectinput[obj.id][i]]=null}}},custom_bind:function(input,serializer,deserializer,objects,eventtypes){_commonsetup(input);initials[input]=serializer();var theInput=document.getElementById(input);if(theInput.value&&theInput.value!=""){deserializer(theInput.value)}deserializers[input].push(deserializer);for(var i=0;i<objects.length;i++){this.register_object(input,objects[i],serializer,eventtypes)}},register_object:function(input,object,serializer,eventtypes){if(object.id in objectinput){if(!(input in objectinput[object.id])){objectinput[object.id].push(input)}}else{objectinput[object.id]=[input]}if(!(input in serializers)){_commonsetup(input)}serializers[input][object.id]=serializer;registerobject(object,eventtypes)},bind_point:function(inputRef,point){var serializer=()=>pointserializer(point);var deserializer=value=>pointdeserializer(point,value);this.custom_bind(inputRef,serializer,deserializer,[point])},bind_point_dual:function(inputRef,p1,p2){var serializer=()=>{return JSON.stringify([[p1.X(),p1.Y()],[p2.X(),p2.Y()]])};var deserializer=value=>{var tmp=JSON.parse(value);pointdeserializerparsed(p1,tmp[0]);pointdeserializerparsed(p2,tmp[1])};this.custom_bind(inputRef,serializer,deserializer,[p1,p2])},bind_point_relative:function(inputRef,p1,p2){var serializer=()=>{return JSON.stringify([[p1.X(),p1.Y()],[p2.X()-p1.X(),p2.Y()-p1.Y()]])};var deserializer=value=>{var tmp=JSON.parse(value);pointdeserializerparsed(p1,tmp[0]);tmp[1][0]=tmp[1][0]+tmp[0][0];tmp[1][1]=tmp[1][1]+tmp[0][1];pointdeserializerparsed(p2,tmp[1])};this.custom_bind(inputRef,serializer,deserializer,[p1,p2])},bind_point_direction:function(inputRef,p1,p2){var serializer=()=>{return JSON.stringify([[p1.X(),p1.Y()],[Math.atan2(p2.Y()-p1.Y(),p2.X()-p1.X()),Math.sqrt((p2.X()-p1.X())*(p2.X()-p1.X())+(p2.Y()-p1.Y())*(p2.Y()-p1.Y()))]])};var deserializer=value=>{var tmp=JSON.parse(value);pointdeserializerparsed(p1,tmp[0]);var angle=tmp[1][0];var len=tmp[1][1];tmp[1][0]=tmp[0][0]+len*Math.cos(angle);tmp[1][1]=tmp[0][1]+len*Math.sin(angle);pointdeserializerparsed(p2,tmp[1])};this.custom_bind(inputRef,serializer,deserializer,[p1,p2])},bind_slider:function(inputRef,slider){var serializer=()=>sliderserializer(slider);var deserializer=value=>sliderdeserializer(slider,value);this.custom_bind(inputRef,serializer,deserializer,[slider])},bind_list_of:function(inputRef,list_of_objects){var serializer=()=>{var r="[";for(var i=0;i<list_of_objects.length;i++){var obj=list_of_objects[i];if(obj.getType()==="slider"){r=r+JSON.stringify(obj.Value())+","}else{r=r+pointserializer(obj)+","}}r=r.substring(0,r.length-1);return r+"]"};var deserializer=value=>{var tmp=JSON.parse(value);for(var i=0;i<list_of_objects.length&&i<tmp.length;i++){var obj=list_of_objects[i];if(obj.getType()==="slider"){obj.setValue(tmp[i])}else{pointdeserializerparsed(obj,tmp[i])}}};this.custom_bind(inputRef,serializer,deserializer,list_of_objects)}};export default stack_jxg; +"use strict";var serializers={};var deserializers={};var initials={};var objectgroups=[];var objectinput={};var registeredobjects={};var active=false;function _commonsetup(inputname){if(!(inputname in serializers)){serializers[inputname]={};deserializers[inputname]=[];var input=document.getElementById(inputname);input.addEventListener("input",()=>generalinputupdatehandler(inputname));input.addEventListener("change",()=>generalinputupdatehandler(inputname))}}function registerobject(object,eventtype){if(eventtype===undefined){eventtype=["update"]}else if(typeof eventtype==="string"||eventtype instanceof String){eventtype=[eventtype]}eventtype.forEach(et=>{if(!(et in registeredobjects)){registeredobjects[et]={}}if(!(object.id in registeredobjects[et])){object.board.on(et,()=>generalobjectupdatehandlerid(object.id));registeredobjects[et][object.id]=object}})}function pointserializer(point){return JSON.stringify([point.X(),point.Y()])}function pointdeserializer(point,data){try{var tmp=JSON.parse(data);if(typeof tmp[0]=="number"&&typeof tmp[1]=="number"){point.setPosition(JXG.COORDS_BY_USER,tmp);point.board.update();point.update()}}catch(err){}}function pointdeserializerparsed(point,data){try{if(typeof data[0]=="number"&&typeof data[1]=="number"){point.setPosition(JXG.COORDS_BY_USER,data);point.board.update();point.update()}}catch(err){}}function sliderserializer(slider){return JSON.stringify(slider.Value())}function sliderdeserializer(slider,data){try{slider.setValue(JSON.parse(data));slider.board.update();slider.update()}catch(err){}}function generalobjectupdatehandler(object){generalobjectupdatehandlerid(object.id)}function generalobjectupdatehandlerid(id){if(!active){active=true;try{var handledinputs=[];if(id in objectinput){for(var i=0;i<objectinput[id].length;i++){var inputname=objectinput[id][i];if(handledinputs.indexOf(inputname)===-1){handledinputs.push(inputname);var input=document.getElementById(inputname);var val=serializers[inputname][id]();if(val!==initials[inputname]){initials[inputname]=null;input.value=val}else{active=false;return}}}}for(var gi=0;gi<objectgroups.length;gi++){var group=objectgroups[gi];if(group.indexOf(id)!==-1){for(var gt=0;gt<group.length;gt++){var obj=group[gt];if(obj!==id){if(obj in objectinput){for(var i=0;i<objectinput[obj].length;i++){var inputname=objectinput[obj][i];if(handledinputs.indexOf(inputname)===-1){initials[inputname]=null;handledinputs.push(inputname);var input=document.getElementById(inputname);input.value=serializers[inputname][obj]()}}}}}}}for(var i=0;i<handledinputs.length;i++){var input=document.getElementById(handledinputs[i]);var e=new Event("change");input.dispatchEvent(e)}}catch(err){}active=false}}function generalinputupdatehandler(inputname){if(inputname in deserializers){var input=document.getElementById(inputname);var keys=Object.keys(serializers[inputname]);var ok=false;for(var i=0;i<keys.length;i++){var old=serializers[inputname][keys[i]]();if(old!==input.value){ok=true;i=keys.length+1}}if(ok){for(var i=0;i<deserializers[inputname].length;i++){deserializers[inputname][i](input.value)}}}}export const stack_jxg={define_group:function(list){var l=[];for(var i=0;i<list.length;i++){if(l.indexOf(list[i].id)===-1){l.push(list[i].id)}}objectgroups.push(l)},starts_moved:function(obj){if(obj.id in objectinput){for(var i=0;i<objectinput[obj.id].length;i++){initials[objectinput[obj.id][i]]=null}generalobjectupdatehandler(obj)}},clear_initial:function(obj){if(obj.id in objectinput){for(var i=0;i<objectinput[obj.id].length;i++){initials[objectinput[obj.id][i]]=null}}},custom_bind:function(input,serializer,deserializer,objects,eventtypes){_commonsetup(input);initials[input]=serializer();var theInput=document.getElementById(input);if(theInput.value&&theInput.value!=""){deserializer(theInput.value)}deserializers[input].push(deserializer);for(var i=0;i<objects.length;i++){this.register_object(input,objects[i],serializer,eventtypes)}},register_object:function(input,object,serializer,eventtypes){if(object.id in objectinput){if(!(input in objectinput[object.id])){objectinput[object.id].push(input)}}else{objectinput[object.id]=[input]}if(!(input in serializers)){_commonsetup(input)}serializers[input][object.id]=serializer;registerobject(object,eventtypes)},bind_point:function(inputRef,point){var serializer=()=>pointserializer(point);var deserializer=value=>pointdeserializer(point,value);this.custom_bind(inputRef,serializer,deserializer,[point])},bind_point_dual:function(inputRef,p1,p2){var serializer=()=>{return JSON.stringify([[p1.X(),p1.Y()],[p2.X(),p2.Y()]])};var deserializer=value=>{var tmp=JSON.parse(value);pointdeserializerparsed(p1,tmp[0]);pointdeserializerparsed(p2,tmp[1])};this.custom_bind(inputRef,serializer,deserializer,[p1,p2])},bind_point_relative:function(inputRef,p1,p2){var serializer=()=>{return JSON.stringify([[p1.X(),p1.Y()],[p2.X()-p1.X(),p2.Y()-p1.Y()]])};var deserializer=value=>{var tmp=JSON.parse(value);pointdeserializerparsed(p1,tmp[0]);tmp[1][0]=tmp[1][0]+tmp[0][0];tmp[1][1]=tmp[1][1]+tmp[0][1];pointdeserializerparsed(p2,tmp[1])};this.custom_bind(inputRef,serializer,deserializer,[p1,p2])},bind_point_direction:function(inputRef,p1,p2){var serializer=()=>{return JSON.stringify([[p1.X(),p1.Y()],[Math.atan2(p2.Y()-p1.Y(),p2.X()-p1.X()),Math.sqrt((p2.X()-p1.X())*(p2.X()-p1.X())+(p2.Y()-p1.Y())*(p2.Y()-p1.Y()))]])};var deserializer=value=>{var tmp=JSON.parse(value);pointdeserializerparsed(p1,tmp[0]);var angle=tmp[1][0];var len=tmp[1][1];tmp[1][0]=tmp[0][0]+len*Math.cos(angle);tmp[1][1]=tmp[0][1]+len*Math.sin(angle);pointdeserializerparsed(p2,tmp[1])};this.custom_bind(inputRef,serializer,deserializer,[p1,p2])},bind_slider:function(inputRef,slider){var serializer=()=>sliderserializer(slider);var deserializer=value=>sliderdeserializer(slider,value);this.custom_bind(inputRef,serializer,deserializer,[slider])},bind_list_of:function(inputRef,list_of_objects){var serializer=()=>{var r="[";for(var i=0;i<list_of_objects.length;i++){var obj=list_of_objects[i];if(obj.getType()==="slider"){r=r+JSON.stringify(obj.Value())+","}else{r=r+pointserializer(obj)+","}}r=r.substring(0,r.length-1);return r+"]"};var deserializer=value=>{var tmp=JSON.parse(value);for(var i=0;i<list_of_objects.length&&i<tmp.length;i++){var obj=list_of_objects[i];if(obj.getType()==="slider"){obj.setValue(tmp[i])}else{pointdeserializerparsed(obj,tmp[i])}}};this.custom_bind(inputRef,serializer,deserializer,list_of_objects)},stack2jsxgraph:function(str){var t;t=str.replace(/%pi/g,"PI").replace(/%e/g,"EULER").replace(/%phi/g,"1.618033988749895").replace(/%gamma/g,"0.5772156649015329").trim();if(t[0]==="["&&t[t.length-1]==="]"){t=t.slice(1,-1).split(/\s*,\s*/)}return t}};export default stack_jxg; diff --git a/doc/en/Developer/Updating_JSXGraph.md b/doc/en/Developer/Updating_JSXGraph.md index 796c8ad9f7eedad3e6d736b7509c88a89e9673fb..0dfde3ca902c094602b8cf0714e694d73506601c 100644 --- a/doc/en/Developer/Updating_JSXGraph.md +++ b/doc/en/Developer/Updating_JSXGraph.md @@ -8,7 +8,9 @@ Download JSXGraph from here: [https://github.com/jsxgraph/jsxgraph](https://gith The files one needs to copy over are `jsxgraph.min.css` and `jsxgraphcore.min.js`, there is no need to copy the non minified versions. -The old STACK side `jsxgraph.js` that provided the `stack_jxg` features is now called `stackjsxgraph.js` and is being served from that same CORS-header tuning directory with that specific script. +The old STACK side `jsxgraph.js` that provided the `stack_jxg` features is now called `stackjsxgraph.js` and is being served from that same CORS-header tuning directory with that specific script. (Minification can be done using uglify-js: +`npm install -g uglify-js` +`uglifyjs stackjsxgraph.js > stackjsxgraph.min.js`.) We do not apply Moodles or any other systems JavaScript processing on these, no need to run `grunt` or any such tool.