diff --git a/sitemap.html b/sitemap.html index 9d812d8..9425480 100644 --- a/sitemap.html +++ b/sitemap.html @@ -38,8 +38,6 @@ Vex 5
Drift -
- constructs '; - windowContent += '' - for (var i = 0; i < arr.length; i++) { - data[i] = arr[i].toDataURL(); - windowContent += ''; - } - windowContent += ''; - windowContent += ''; - var printWin = window.open(); - printWin.document.open(); - printWin.document.write(windowContent); - printWin.document.addEventListener('load', function() { - printWin.focus(); - printWin.print(); - //printWin.document.close(); - //printWin.close(); - //printWin.onfocus = function () {printWin.close();} - setTimeout(function() { - printWin.document.close(); - printWin.close(); - },500); - }, true); -} - -function getHighestZIndex() { - var elems = container.childNodes; - var highest = 0; - for (var i = 0; i < elems.length; i++) { - if (elems[i].nodeType !== 1) continue; - var zIndex = Number(elems[i].style.zIndex); - if ((zIndex > highest) && (zIndex != 'auto')) highest = zIndex; - } - return highest; -} -function getNodes() { - var elems = container.childNodes; - var obj = []; - for (var i = 0; i < elems.length; i++) { - if (elems[i].nodeType !== 1) continue; - var zIndex = Number(elems[i].style.zIndex); - var rect = []; - if (!un(elems[i].data)) { - rect[0] = elems[i].data[100]; - rect[1] = elems[i].data[101]; - rect[2] = elems[i].data[102]; - rect[3] = elems[i].data[103]; - } - var opacity = elems[i].style.opacity; - var pointerEvents = elems[i].style.pointerEvents == 'auto' ? true : false; - obj.push({zIndex:zIndex,node:elems[i],rect:rect,opacity:opacity,pointerEvents:pointerEvents}); - } - obj.sort(function(a,b) { - return a.zIndex - b.zIndex; - }); - return obj; -} - -function funcLog() { - augment(function(name, fn) { - console.log("fn " + name); - }); -} -function augment(withFn) { - var name, fn; - for (name in window) { - fn = window[name]; - var exceptions = ['mouseCoordsChange', 'xWindowToCanvas', 'yWindowToCanvas', 'xCanvasToWindow','yCanvasToWindow', 'setTimeout', 'clearTimeout', 'dragMove', 'pointerEventsListen', 'hitTestMouseOver', 'mathsInputCursorBlink', 'drawMathsInputText', 'drawMathsText', 'mapArray', 'removeTags', 'buildArray', 'clearCorrectingInterval', 'logMe', 'boolean', 'replaceAll', 'showObj', 'dist', 'distancePointToLineSegment', 'closestPointOnLineSegment', 'escapeRegExp', 'resizeCanvas', 'arraysEqual','def','un','resizeCanvas3','updateMouse','addListener','createCanvas','newctx','clone','addEventListener','addListenerStart','addListenerEnd','resize','showObj','hideObj','removeEventListener','addListenerMove','clearCanvas','active','inactive','stopDefaultBackspaceBehaviour']; - if (typeof fn === 'function' && exceptions.indexOf(name) == -1) { - window[name] = (function(name, fn) { - var args = arguments; - return function() { - withFn.apply(this, args); - return fn.apply(this, arguments); - } - })(name, fn); - } - } -} -//funcLog(); - -var mainCanvasLeft = 0; -var mainCanvasTop = 0; -var mainCanvasWidth = 1200; -var mainCanvasHeight = 700; -var mainCanvasMargins = [0,0,0,0]; //l,t,r,b - used in teach: edit mode -var canvasDisplayLeft = 0; -var canvasDisplayTop = 0; -if (typeof mainCanvasBorderWidth == 'undefined') var mainCanvasBorderWidth = 10; -if (typeof mainCanvasFillStyle == 'undefined') var mainCanvasFillStyle = mainCanvasFillStyle || '#FFC'; -var mainCanvasMode = 'full'; - -var pi = String.fromCharCode(0x03C0); -var times = String.fromCharCode(0x00D7); -var divide = String.fromCharCode(0x00F7); -var degrees = String.fromCharCode(0x00B0); -var infinity = String.fromCharCode(0x221E); -var lessThanEq = String.fromCharCode(0x2264); -var moreThanEq = String.fromCharCode(0x2265); -var notEqual = String.fromCharCode(0x2260); -var theta = String.fromCharCode(0x03B8); -var plusMinus = String.fromCharCode(0x00B1); -var minusPlus = String.fromCharCode(0x2213); -var tab = String.fromCharCode(0x21F4); -var br = String.fromCharCode(0x23CE); - -var key1 = []; -var key1Data = []; - -var mouse = {x:0, y:0}; -function updateMouse(e) { - if (un(e)) return; - if (e.touches) { - if (un(e.touches[0])) return; - var x = e.touches[0].pageX; - var y = e.touches[0].pageY; - } else { - var x = e.clientX || e.pageX; - var y = e.clientY || e.pageY; - } - - if (!un(draw) && !un(draw.div)) { - var bounds = draw.drawCanvas[0].getBoundingClientRect(); - mouse.x = (x - bounds.left) * (1200 / bounds.width); - mouse.y = (y - bounds.top) * (1700 / bounds.height); - draw.mouse = [mouse.x,mouse.y]; - } else { - mouse.x = xWindowToCanvas(x); - mouse.y = yWindowToCanvas(y); - if (!un(draw) && !un(draw.drawRelPos)) { - draw.mouse = canvasPosToDrawPos([mouse.x,mouse.y]); - } - } -} -function canvasPosToDrawPos(pos) { - if (un(draw)) return pos; - return [ - (pos[0]-draw.drawRelPos[0])/draw.scale, - (pos[1]-draw.drawRelPos[1])/draw.scale - ]; -} -function drawPosToCanvasPos(pos) { - if (un(draw)) return pos; - return [ - pos[0]*draw.scale+draw.drawRelPos[0], - pos[1]*draw.scale+draw.drawRelPos[1] - ]; -} - -var dragObject = []; -var dragObjectData = []; -var currentDragId; -var dragOffset = {x:0, y:0}; -var dragArea = {xMin:0, xMax:0, yMin:0, yMax:0}; - -var currMathsInput; -var currMathsInputId; -var mathsInputCursorBlinkInterval; -var mathsInputCursorState; -var mathsInputCursor = {x:0, top:0, bottom:0} -var charMap = [[42,215,215], [48,48,41], [49,49,33], [50,50,34], [51,51,163], [52,52,36], [53,53,37], [54,54,94], [55,55,38], [56,56,215], [57,57,40], [96,48,48], [97,49,49], [98,50,50], [99,51,51], [100,52,52], [101,53,53], [102,54,54], [103,55,55], [104,56,56], [105,57,57], [106,215,215], [107,43,43], [109,189,189], [110,190,190], [111,191,191], [186,59,58], [187,61,43], [188,44,60], [189,45,95], [190,46,62], [191,247,63], [192,39,64], [219,91,123], [220,92,124], [221,93,125], [222,35,126]]; -var endInputExceptions = []; -var currSlider; -var slider = []; -var draw; -var keyboard = []; -var keyboardData = []; -var keyboardVis = []; -var showKeys = []; -var hideKeys = []; -var zIndexFront = 1000; - -var canvases = [[]]; -var mathsInput = [[]]; - -var container = document.getElementById('canvascontainer'); -var canvas = document.getElementById('canvas'); -var ctx = canvas.getContext('2d'); - -var canvasDisplayRect; -var canvasDisplayWidth; -var canvasDisplayHeight; -var canvasMetrics = canvas.getBoundingClientRect(); - -var openhand = 'url("cursors/openhand.cur"), auto'; -var closedhand = 'url("cursors/closedhand.cur"), auto'; - -var logPointerEvents = false; -window.addEventListener("touchstart", function (e) { - updateMouse(e); - if (un(e.target.allowDefault) || e.target.allowDefault == false) e.preventDefault(); - if (logPointerEvents) - console.log('touchstart', e.target); -}, true); -window.addEventListener("touchmove", function (e) { - updateMouse(e); - if (un(e.target.allowDefault) || e.target.allowDefault == false) e.preventDefault(); - if (logPointerEvents) - console.log('touchmove', e.target); -}, true); -window.addEventListener("touchend", function (e) { - if (un(e.target.allowDefault) || e.target.allowDefault == false) e.preventDefault(); - if (logPointerEvents) - console.log('touchend', e.target); -}, true); -window.addEventListener("pointerstart", function (e) { - if (un(e.target.allowDefault) || e.target.allowDefault == false) e.preventDefault(); - if (logPointerEvents) console.log('pointerstart'); -}, true); -window.addEventListener("pointermove", function (e) { - if (un(e.target.allowDefault) || e.target.allowDefault == false) e.preventDefault(); - //if (logPointerEvents) console.log('pointermove'); -}, true); -window.addEventListener("pointerend", function (e) { - if (un(e.target.allowDefault) || e.target.allowDefault == false) e.preventDefault(); - if (logPointerEvents) console.log('pointerend'); -}, true); -window.addEventListener("mousedown", function (e) { - updateMouse(e); - if (e.target.allowDefault === true) return; - e.preventDefault(); - if (logPointerEvents) console.log('mousedown'); -}, true); -window.addEventListener("mousemove", function (e) { - updateMouse(e); - if (un(e.target.allowDefault) || e.target.allowDefault == false) e.preventDefault(); - if (logPointerEvents) - console.log('mousemove'); -}, true); -window.addEventListener("mouseup", function (e) { - if (e.target.allowDefault === true) return; - e.preventDefault(); - if (logPointerEvents) console.log('mouseup'); -}, true); - -window.addEventListener('resize', resize, false); -window.addEventListener('orientationchange', resize, false); -window.addEventListener('keydown', stopDefaultBackspaceBehaviour, false); -//window.addEventListener('mousemove', updateMouse, false); -//window.addEventListener('touchstart', updateMouse, false); -//window.addEventListener('touchmove', updateMouse, false); -var foc = true; -var blinking = false; -window.addEventListener('focus', function () { - foc = true; - if (blinking == true) { - setTimeout(function () { - mathsInputCursorBlinkInterval = setCorrectingInterval(function () { - mathsInputCursorBlink() - }, 600); - }, 100); - } -}); -window.addEventListener('blur', function () { - foc = false; - if (blinking == true) { - clearCorrectingInterval(mathsInputCursorBlinkInterval); - inputCursorState = false; - drawMathsInputText(currMathsInput); - } - if (typeof currMathsInput !== 'undefined') - endMathsInput(); -}); -var makePDFLoaded = false; -function loadMakePDF(callback) { - if (makePDFLoaded == false) { - makePDFLoaded = true; - window.callback = callback; - loadScript('pdfmake.min.js',loadMakePDF2); - } else { - callback(); - } -} -function loadMakePDF2() { - var callback = window.callback; - delete window.callback; - loadScript('vfs_fonts.js',callback); -} - -/*window.addEventListener('touchstart',touchPreventDefault,false); -window.addEventListener('touchmove',touchPreventDefault,false); -window.addEventListener('touchend',touchPreventDefault,false); -var touchPreventDefault = function(e) { - e.preventDefault; -} - -var isMobile = { - Android: function () { - return navigator.userAgent.match(/Android/i); - }, - BlackBerry: function () { - return navigator.userAgent.match(/BlackBerry/i); - }, - iOS: function () { - return navigator.userAgent.match(/iPhone|iPad|iPod/i); - }, - Opera: function () { - return navigator.userAgent.match(/Opera Mini/i); - }, - Windows: function () { - return navigator.userAgent.match(/IEMobile/i) || navigator.userAgent.match(/WPDesktop/i); - }, - any: function () { - return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows()); - } -} -if (isMobile.any()) { - document.getElementsByTagName("head")[0].innerHTML += '' - document.ontouchmove = function (event) { - event.preventDefault() - } -} -*/ - -if (isTask == true) { - var page = []; - if (boolean(window.sortPages,true) == true) { - pages.sort(function(a,b) { - return Number(a.order) - Number(b.order); - }); - } - //pages.reverse(); - prevPages.sort(function(a,b) { - var d1 = new Date(a.timestamp).getTime(); - var d2 = new Date(b.timestamp).getTime(); - return d2-d1; - }); - for (var i = 0; i < prevPages.length; i++) { - if (Number(prevPages[i].percentage < 100)) continue; - var pageId = Number(prevPages[i].pageid); - for (var j = 0; j < pages.length; j++) { - if (Number(pages[j].pageid) == pageId) { - if (un(pages[j].prev)) { - pages[j].prev = prevPages[i].timestamp; - } - break; - } - } - } -} - -if (typeof FontFace !== 'undefined') { - document.fonts.ready.then(function(res) { - //console.log(document.fonts.size, 'FontFaces loaded.'); - //console.log('result',res); - loadScripts1(); - }, function(err) { - //console.log('error',err); - loadScripts1(); - }); -} else { - loadScripts1(); -} - -function loadScripts1() { - for (var i = 0; i < scriptsToLoad.length; i++) { - loadScript(scriptsToLoad[i], scriptLoaded); - } -} -function loadScript(url, callback, errorCallback, index) { - if (un(errorCallback)) errorCallback = function() {}; - var head = document.getElementsByTagName('head')[0]; - var script = document.createElement('script'); - script.type = 'text/javascript'; - script.charset = "UTF-8"; - var url2 = typeof cacheVersion === 'string' ? url + '?' + cacheVersion : url; - script.src = url2; - script.index = index; - script.onload = function() { - if (!un(callback)) callback(this.index); - }; - script.onerror = function() { - if (!un(errorCallback)) errorCallback(this.index); - }; - head.appendChild(script); -} -function scriptLoaded() { - loadedScriptCount++; - if (loadedScriptCount >= scriptsToLoad.length) { - clearCanvas(); - if (boolean(isTask,true) == true) { - window.holder = createHolder(); - showPage(0); - } else { - if (!un(scriptsToLoad2)) { - for (var i = 0; i < scriptsToLoad2.length; i++) { - loadScript(scriptsToLoad2[i]); - } - } - } - resize(); - if (isTask == true) { - TimeMe.initialize({ - currentPageName: "page", - idleTimeoutInSeconds: idleTimeoutInSeconds - }); - TimeMe.callWhenUserLeaves(function(){ - inactive(); - }); - TimeMe.callWhenUserReturns(function(){ - active(); - }); - if (typeof taskLogData == 'undefined') return; - if (Number(taskLogData.status) < 3) { - TimeMe.callAfterTimeElapsedInSeconds(reportIntervalInSeconds,reportHandler); - } - } - } -} -var inactiveBox; - -function openPHP(url,postVars) { - var form = document.createElement("form"); - form.target = "_blank"; - form.method = "POST"; - form.action = url; - form.style.display = "none"; - - for (var key in postVars) { - var input = document.createElement("input"); - input.type = "hidden"; - input.name = key; - input.value = encodeURIComponent(postVars[key]); - form.appendChild(input); - } - - document.body.appendChild(form); - form.submit(); - document.body.removeChild(form); -} - -if (isTask == true) { - var pointsMode = false; - - var pageLoadErrorCount = 0; - var faded = false; - function createInactiveBox() { - inactiveBox = document.createElement('canvas'); - inactiveBox.width = 400; - inactiveBox.height = 120; - inactiveBox.setAttribute('position', 'absolute'); - inactiveBox.setAttribute('cursor', 'auto'); - inactiveBox.setAttribute('draggable', 'false'); - inactiveBox.setAttribute('class', 'buttonClass'); - - var ctx = inactiveBox.getContext('2d'); - ctx.lineCap = "round"; - ctx.lineJoin = "round"; - ctx.clearRect(0, 0, 400, 120); - ctx.fillStyle = "#FFF"; - ctx.strokeStyle = "#000"; - ctx.lineWidth = 6; - ctx.beginPath(); - ctx.moveTo(3, 3); - ctx.lineTo(397, 3); - ctx.lineTo(397, 117); - ctx.lineTo(3, 117); - ctx.lineTo(3, 3); - ctx.closePath(); - ctx.fill(); - ctx.stroke(); - ctx.font = "80px Hobo"; - ctx.textAlign = "center"; - ctx.textBaseline = "middle"; - ctx.fillStyle = "#000"; - ctx.fillText('Inactive', 200, 66); - inactiveBox.style.pointerEvents = 'default'; - inactiveBox.style.cursor = 'default'; - inactiveBox.style.zIndex = 900000000; - resize(); - return inactiveBox; - } - - //* - var idleTimeoutInSeconds = 2*60; - var reportIntervalInSeconds = 4*60; - function reportHandler() { - if (Number(taskLogData.status) == 3 || userType !== 0) return; - logTime(); - if (un(TimeMe)) return; - clearReportTimeouts(); - var time = Math.round(TimeMe.getTimeOnPageInSeconds('page')); - TimeMe.callAfterTimeElapsedInSeconds(time+reportIntervalInSeconds,reportHandler); - } - function clearReportTimeouts() { - for (var i = TimeMe.timeElapsedCallbacks.length - 1; i >= 0; i--) { - TimeMe.timeElapsedCallbacks[i].pending = false; - } - } - - function active(e) { - /*unfadePage(); - /if (!un(inactiveBox)) { - if (inactiveBox.parentNode == container) { - container.removeChild(inactiveBox); - } - }*/ - removeListenerStart(window,active); - //console.log('active'); - } - function inactive() { - /*fadePage(); - if (un(inactiveBox)) inactiveBox = createInactiveBox(); - container.appendChild(inactiveBox);*/ - addListenerStart(window,active); - //console.log('inactive'); - } - - function logTime() { - if (userType !== 0) return; - if (Number(taskLogData.percentage) == 100 || Number(taskLogData.status) == 3) { - clearReportTimeouts(); - return; - } - var timeSpent = Math.round(TimeMe.getTimeOnPageInSeconds('page')/60); - var browserInfo = getBrowserInfo(); - var params = "tasksLogId="+taskLogData.taskNumber+"&timeSpent="+timeSpent+"&browserInfo="+browserInfo; - //console.log('logTime params: ', params); - var sendReportX = new XMLHttpRequest(); - sendReportX.open("post", "_logTime.php", true); - sendReportX.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); - sendReportX.errorCallback = function() {}; - sendReportX.onreadystatechange = function() { - if (this.readyState == 4) { - if (this.status !== 200) { - if (typeof this.errorCallback == 'function') this.errorCallback(); - return; - } - //console.log('logTime sent'); - //reportHandler(); - } - } - sendReportX.send(params); - } - - //*/ - - /* - var inactiveAfter = 300; - var inactiveStartTime; - var inactiveTime = 0; - var isActive = true; - var startTime = new Date(); - var activityMonitor = setTimeout(function(){inactive()}, inactiveAfter*1000); - - window.addEventListener('mouseup', active, false); - window.addEventListener('touchend', active, false); - window.addEventListener('mousedown', active, false); - window.addEventListener('touchstart', active, false); - window.addEventListener('keydown', active, false); - window.addEventListener('blur', inactive, false); - - function active(event) { - if (!un(event) && event.target.nodeName !== 'TEXTAREA') event.preventDefault(); - if (isTask == true) { - clearTimeout(activityMonitor); - activityMonitor = setTimeout(function(){inactive()}, inactiveAfter*1000); - if (isActive == false && pageIndex !== pages.length) { - isActive = true; - var currentTime = new Date(); - inactiveTime += (currentTime - inactiveStartTime); - if (inactiveBox.parentNode == container) container.removeChild(inactiveBox); - unfadePage(); - } - } - } - function inactive() { - clearTimeout(activityMonitor); - isActive = false; - inactiveStartTime = new Date(); - if (boolean(window.logPages,false) == false) { - fadePage(); - if (un(inactiveBox)) inactiveBox = createInactiveBox(); - container.appendChild(inactiveBox); - } - } - - function getTimeSpent() { - var currentTime = new Date(); - var ms = currentTime - startTime - inactiveTime; - return Math.floor(ms/1000); - } - function getTime() { - var currentTime = new Date(); - var timeSpent = currentTime - startTime - inactiveTime; - timeSpent /= 60000; - return Math.round(timeSpent+Number(taskLogData.prevTime)); - } - - function logTime() { - if (userType !== 0) return; - if (Number(taskLogData.percentage) == 100 || Number(taskLogData.status) == 3) { - clearTimeout(minuteCounter); - return; - } - if (isActive == true) { - var timeSpent = getTime(); - var browserInfo = getBrowserInfo(); - var params = "tasksLogId="+taskLogData.taskNumber+"&time="+timeSpent+"&inactiveTime="+inactiveTime+"&browserInfo="+browserInfo; - //console.log('logTime params: ', params); - var sendReportX = new XMLHttpRequest(); - sendReportX.open("post", "_logTime.php", true); - sendReportX.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); - sendReportX.onload = function() { - //var response = (this.responseText).split(';'); - //console.log('logTime response: ', this.responseText); - taskLogData.totalTime = this.responseText; - connectionErrorMessage = 0; - } - sendReportX.onreadystatechange = function() { - if (sendReportX.readyState == 4 && sendReportX.status !== 200 && connectionErrorMessage == 0) { - alert('Error connecting to the MathsPad database. Your results may not be logged. Check your internet connection.'); - connectionErrorMessage = 1; - } - } - sendReportX.send(params); - } - clearTimeout(minuteCounter); - minuteCounter = setTimeout(function(){logTime()}, 4*60000); - } - if (userType == 0) { - taskLogData.prevTime = taskLogData.totalTime; - taskLogData.prevStatus = taskLogData.status; - taskLogData.prevPercentage = taskLogData.percentage; - var connectionErrorMessage; - var minuteCounter = setTimeout(function(){logTime()}, 4*60000); - } - //*/ - - function fadePage() { - if (faded == true) return; - var nodes = container.childNodes; - for (var n = 0; n < nodes.length; n++) { - if (nodes[n].nodeType !== 1 || nodes[n] == inactiveBox) continue; - nodes[n].savedOpacity = nodes[n].style.opacity; - nodes[n].style.opacity = 0.5; - } - faded = true; - } - function unfadePage() { - var nodes = container.childNodes; - for (var n = 0; n < nodes.length; n++) { - if (nodes[n].nodeType !== 1) continue; - var opacity = !un(nodes[n].savedOpacity) ? nodes[n].savedOpacity : 1; - nodes[n].style.opacity = opacity; - delete nodes[n].savedOpacity; - } - faded = false; - } - - function createHolder() { - var prev = playButton(20,20,50,prevPage,{dir:'left',fillColor:'#3FF',lineWidth:4,radius:8,zIndex:1000}); - var next = playButton(1200-20-50,20,50,nextPage,{dir:'right',fillColor:'#3FF',lineWidth:4,radius:8,zIndex:1000}); - var reload = newctx({rect:[1200-130,20,50,50],pe:true,zIndex:1000}); - addListener(reload.canvas,reloadPage); - drawRefreshButton(reload,4,4,42,'#C9F','left'); - var canvas = newctx({rect:[0,0,1200,700],z:1}).canvas; - showObj(canvas); - var check = newctx({rect:[1200-340,20,200,50],pe:true,z:10000000}).canvas; - text({ctx:check.ctx,textArray:['<><>Check Answer'],left:2,top:2,width:196,height:46,align:'center',vertAlign:'middle',box:{type:'loose',borderColor:'#000',borderWidth:4,radius:8,color:'#6F9'}}); - addListenerEnd(check,checkPage); - var home2 = newctx({rect:[712,555,386,80],pe:true,zIndex:1000}).canvas; - text({ctx:home2.ctx,rect:[2,2,382,76],text:['<><>Return to My Profile '],align:'right',vertAlign:'middle',box:{type:'loose',borderColor:'#000',borderWidth:4,color:'#FFF',radius:8},allowSpaces:true}); - var home = newctx({rect:[80,20,50,50],pe:true,zIndex:1000}).canvas; - roundedRect2(home.ctx,2,2,46,46,8,4,'#000','#FFF'); - var homeImage = new Image; - homeImage.onload = function() { - holder.home.ctx.drawImage(homeImage, 4.5, 4, 42, 42); - - var image = holder.home.ctx.getImageData(0, 0, 500, 200); - var imageData = image.data, - length = imageData.length; - for (var i=0; i < length; i+=4) { - if (imageData[i] == 255 && imageData[i+1] == 255 && imageData[i+2] == 255) imageData[i+3] = 50; - } - image.data = imageData; - - roundedRect2(home.ctx,2,2,46,46,8,4,'#000','#FFF'); - holder.home.ctx.putImageData(image, 0, 0); - roundedRect2(holder.home.ctx,2,2,46,46,8,4,'#000'); - - holder.home2.ctx.drawImage(homeImage, 12, 8, 42*1.5, 42*1.5); - } - homeImage.src = "/Images/logoSmall.PNG"; - var loading = newctx({pe:true,z:1000000}).canvas; - loading.style.cursor = 'default'; - textBox(loading.ctx,[425,295,350,110],['<><>Loading...'],'#3FF'); - var disablePeCanvas = newctx({pe:true,zIndex:1000000000000}).canvas; - disablePeCanvas.style.cursor = 'default'; - var summary = newctx().canvas; - var summary2 = newctx({z:3}).canvas; - return {prev:prev,next:next,reload:reload.canvas,canvas:canvas,check:check,home:home,loading:loading,feedback:[],feedbackButton:[],completed:[],disablePeCanvas:disablePeCanvas,summary:summary,summary2:summary2,home2:home2}; - } - function prevPage() { - if (pageIndex == 0) return; - hidePage(); - pageIndex--; - showPage(); - } - function nextPage() { - if (pageIndex == pages.length - 1) return; - hidePage(); - pageIndex++; - showPage(); - } - function goToPage(num) { - if (un(num)) num = pages.length - 1; - if (num < 0 || num > pages.length-1) return; - hidePage(); - pageIndex = roundToNearest(num,1); - showPage(); - } - function hidePage() { - endMathsInput(); - unfadePage(); - keyboardHardOpen = false; - hideKeyboard2(); - if (pageIndex < pages.length) { - for (var c = 0; c < canvases[pageIndex].length; c++) { - if (canvases[pageIndex][c].parentNode == container) { - container.removeChild(canvases[pageIndex][c]); - } - } - for (var m = 0; m < mathsInput[pageIndex].length; m++) { - hideMathsInput(mathsInput[pageIndex][m]); - } - for (var s = 0; s < pages[pageIndex].stars.length; s++) { - hideObj(pages[pageIndex].stars[s]); - //pages[pageIndex].stars[s].stopSpin(); - } - } - if (!un(draw) && !un(draw.drawCanvas)) { - pages[pageIndex].paths = draw.path; - pages[pageIndex].beforeDraw = draw.beforeDraw; - pages[pageIndex].afterDraw = draw.afterDraw; - pages[pageIndex].drawMode = draw.drawMode; - - delete draw.beforeDraw; - delete draw.afterDraw; - draw.path = []; - drawCanvasPaths(); - calcCursorPositions(); - } - holder.canvas.ctx.clearRect(0,80,1200,620); - hideObj(holder.feedbackButton[pageIndex]); - hideObj(holder.completed[pageIndex]); - hideObj(holder.summary); - hideObj(holder.summary2); - hideObj(holder.home2); - } - function showPage() { - /*if (pageIndex == pages.length) { - showSummaryPage(); - return; - }*/ - active(); - if (un(page[pageIndex])) { - pageLoadErrorCount++; - loadPage(function() { - if (boolean(p.taskPageAutoLoad,false) == true) { - taskPageAutoLoad(p); - }; - pages[pageIndex].paths = draw.path; - pages[pageIndex].beforeDraw = draw.beforeDraw; - pages[pageIndex].afterDraw = draw.afterDraw; - showPage(); - },function() { - page[pageIndex] = undefined; - if (pageLoadErrorCount < 3) prevPage(); - Notifier.error('Error connecting to the server. The page cannot be loaded.'); - }); - } else { - for (var c = 0; c < canvases[pageIndex].length; c++) { - if (canvases[pageIndex][c].vis == true) { - container.appendChild(canvases[pageIndex][c]); - } - } - for (var m = 0; m < mathsInput[pageIndex].length; m++) { - showMathsInput(mathsInput[pageIndex][m]); - } - - holder.canvas.ctx.clearRect(0,0,1200,700); - if (boolean(window.logPages,false) == false) { - textBox(holder.canvas.ctx,[140,20,100,50],['<><>'+String(pageIndex+1)+' / '+String(pages.length)],'#CCF'); - drawPoints(); - for (var s = 0; s < pages[pageIndex].stars.length; s++) { - if (pages[pageIndex].stars[s].show == true) { - showObj(pages[pageIndex].stars[s]); - } - } - if (pages[pageIndex].completed == false && un(pages[pageIndex].prev)) { - if (boolean(page[pageIndex].showHolderCheckButton,true) == true) { - showObj(holder.check); - } else { - hideObj(holder.check); - } - holder.reload.style.opacity = 1; - holder.reload.style.pointerEvents = 'auto'; - if (pointsMode == true) holder.canvas.ctx.rect2({rect:[650+2,20+2,200-4,50-4],lineWidth:4,color:'#000',radius:8}); - if (!un(holder.feedback[pageIndex]) && holder.feedback[pageIndex].fb == true) { - showObj(holder.feedbackButton[pageIndex]); - } else { - hideObj(holder.feedbackButton[pageIndex]); - } - } else if (pages[pageIndex].completed == true) { - hideObj(holder.check); - showObj(holder.completed[pageIndex]); - text({ctx:holder.canvas.ctx,left:650,width:410,top:20,height:50,align:'center',vertAlign:'middle',textArray:['<><><>Page Completed!']}); - holder.reload.style.opacity = 0.5; - holder.reload.style.pointerEvents = 'none'; - hideObj(holder.feedbackButton[pageIndex]); - } else if (!un(pages[pageIndex].prev)) { - if (boolean(page[pageIndex].showHolderCheckButton,true) == true) { - showObj(holder.check); - } else { - hideObj(holder.check); - } - showObj(holder.completed[pageIndex]); - holder.reload.style.opacity = 1; - holder.reload.style.pointerEvents = 'auto'; - if (pointsMode == true) holder.canvas.ctx.rect2({rect:[650+2,20+2,200-4,50-4],lineWidth:4,color:'#000',radius:8}); - if (!un(holder.feedback[pageIndex]) && holder.feedback[pageIndex].fb == true) { - showObj(holder.feedbackButton[pageIndex]); - } else { - hideObj(holder.feedbackButton[pageIndex]); - } - } - showObj(holder.reload); - showObj(holder.home); - } else { - var filename = String(pageData[pageIndex].pageid); - while (filename.length < 4) filename = "0"+filename; - textBox(holder.canvas.ctx,[80,20,100,50],['<><>'+String(filename)],'#CCF'); - if (typeof preview !== 'undefined' && !un(preview.button)) showObj(preview.button); - } - showObj(holder.prev); - showObj(holder.next); - hideObj(holder.loading); - if (boolean(page[pageIndex].allowReload,true) == false) { - hideObj(holder.reload); - } else { - showObj(holder.reload); - } - - if (!un(draw) && !un(draw.drawCanvas)) { - draw.path = pages[pageIndex].paths || []; - draw.beforeDraw = pages[pageIndex].beforeDraw; - draw.afterDraw = pages[pageIndex].afterDraw; - if (!un(pages[pageIndex].drawMode)) { - if (draw.drawMode !== pages[pageIndex].drawMode) { - changeDrawMode(pages[pageIndex].drawMode); - } - } - drawCanvasPaths(); - calcCursorPositions(); - for (var i = 0; i < draw.drawCanvas.length; i++) showObj(draw.drawCanvas); - showObj(draw.cursorCanvas); - } - - if (pageIndex == 0) { - holder.prev.style.opacity = 0.5; - holder.prev.style.pointerEvents = 'none'; - } else { - holder.prev.style.opacity = 1; - holder.prev.style.pointerEvents = 'auto'; - } - if (pageIndex == pages.length - 1) { - holder.next.style.opacity = 0.5; - holder.next.style.pointerEvents = 'none'; - } else { - holder.next.style.opacity = 1; - holder.next.style.pointerEvents = 'auto'; - } - - if (typeof keyboardButton1[pageIndex] !== 'undefined') { - showObj(keyboardButton1[pageIndex]); - } - resize(); - p = page[pageIndex]; - if (boolean(window.logPages,false) == true) { - if (typeof pageDataLog == 'function') pageDataLog(); - if (typeof savePagePNG == 'function') savePagePNG(); - } - pageLoadErrorCount = 0; - } - } - /*function showSummaryPage() { - holder.canvas.ctx.clearRect(0,0,1200,700); - hideObj(holder.check); - hideObj(holder.reload); - hideObj(holder.home); - holder.next.style.opacity = 0.5; - holder.next.style.pointerEvents = 'none'; - - var ctx = holder.summary.ctx; - var ctx2 = holder.summary2.ctx; - ctx.clear(); - ctx2.clear(); - text({ctx:ctx,rect:[120,5,1000,80],text:['<><>Task Summary'],vertAlign:'middle'}); - - var l = 712; - var t = 130; - text({ctx:ctx,left:l,width:386,top:t,height:46,vertAlign:'middle',textArray:['<>'+userName],box:{type:'loose',radius:8,color:'#CFF',borderColor:'#000',borderWidth:4,padding:10}}); - if (pointsMode == true) { - text({ctx:ctx,left:l,width:386,top:t,height:46,align:'right',vertAlign:'middle',textArray:['<><><>'+userPoints+' '],allowSpaces:true}); - ctx.beginPath(); - ctx.lineWidth = 4; - ctx.strokeStyle = '#000'; - drawStar({ctx:ctx,c:[l+361,t+23],r:12}); - ctx.closePath(); - ctx.stroke(); - ctx.beginPath(); - ctx.fillStyle = '#00F'; - drawStar({ctx:ctx,c:[l+361,t+23],r:12}); - ctx.fill(); - } - - var cells = []; - var comp = 0; - var totalPoints = 0; - for (var r = 0; r < pages.length; r++) { - if (pages[r].completed == true) { - comp++; - totalPoints += pages[r].points; - cells[r] = [ - {text:['Page '+(r+1)],color:'#CFC'}, - {minWidth:180,text:['<>Completed!'],color:'#CFC'} - ]; - if (pointsMode == true) cells[r].push({minWidth:200,color:'#CFC'}); - } else if (!un(pages[r].prev)) { - comp++; - cells[r] = [ - {text:['Page '+(r+1)],color:'#CFC'}, - {minWidth:180,text:['<>Completed!'],color:'#CFC'} - ]; - if (pointsMode == true) cells[r].push({minWidth:200,color:'#CFC'}); - } else { - cells[r] = [ - {text:['Page '+(r+1)]}, - {minWidth:180,text:['Keep Trying!']} - ]; - if (pointsMode == true) cells[r].push({minWidth:200}); - } - } - - var table = drawTable2({ - ctx:ctx, - left:102, - top:t, - minCellWidth:100, - minCellHeight:40, - horizAlign:'center', - text:{font:'Hobo',size:28,color:'#000'}, - outerBorder:{show:true,width:4,color:'#000'}, - innerBorder:{show:true,width:2,color:'#000'}, - cells:cells - }); - - if (pointsMode == true) { - for (var r = 0; r < pages.length; r++) { - var c = table.cell[r][2]; - var rect = [c.left,c.top,c.width,c.height]; - var l = rect[0]+rect[2]/2-(pages[r].points-1)*17.5; - var t = (table.yPos[r]+table.yPos[r+1])/2; - ctx2.lineWidth = 4; - if (pages[r].completed == true) { - ctx2.strokeStyle = '#000'; - ctx2.fillStyle = '#FC3'; - } else if (!un(pages[r].prev)) { - ctx2.strokeStyle = '#666'; - ctx2.fillStyle = '#CFC'; - } else { - ctx2.strokeStyle = '#666'; - ctx2.fillStyle = '#FFC'; - } - for (var s = 0; s < pages[r].points; s++) { - ctx2.beginPath(); - drawStar({ctx:ctx2,c:[l,t],r:12}); - ctx2.closePath(); - ctx2.stroke(); - ctx2.beginPath(); - drawStar({ctx:ctx2,c:[l,t],r:12}); - ctx2.fill(); - l += 35; - } - } - } - - if (pointsMode == true) { - textBox(ctx2,[712,190,386,350],['<>Task Progress: '+String(taskLogData.percentage)+'%'+br+br+'Points earned: '+totalPoints+br+br+'Time Spent: '+String(taskLogData.totalTime)+' mins'+br+br+'<><>Your progress has'+br+'been logged.'],'#CFF'); - } else { - textBox(ctx2,[712,190,386,350],['<>Task Progress: '+String(taskLogData.percentage)+'%'+br+br+'Time Spent: '+String(taskLogData.totalTime)+' mins'+br+br+'<><>Your progress has'+br+'been logged.'],'#CFF'); - } - - showObj(holder.summary); - showObj(holder.summary2); - showObj(holder.home2); - inactive(); - resize(); - }*/ - function loadPage(callback,errorCallback) { - showObj(holder.loading); - holder.prev.style.pointerEvents = 'none'; - holder.prev.style.opacity = 0.5; - holder.next.style.pointerEvents = 'none'; - holder.next.style.opacity = 0.5; - if (un(errorCallback)) errorCallback = function() {}; - var filename = pages[pageIndex].pageid; - while (filename.length < 4) { - filename = "0" + filename; - } - pages[pageIndex].filename = filename; - if (!un(pages[pageIndex].prev)) { - pages[pageIndex].maxPoints = 1; - pages[pageIndex].points = 1; - holder.completed[pageIndex] = textCanvas([600-450/2,285,450,170],[''],'#EEE').canvas; - resizeCanvas3(holder.completed[pageIndex]); - var date = new Date(pages[pageIndex].prev.slice(0,pages[pageIndex].prev.indexOf(" "))); - pages[pageIndex].prevDate = ['Sun','Mon','Tues','Weds','Thurs','Fri','Sat'][date.getDay()]+" "+date.getDate()+" "+['Jan','Feb','Mar','Apr','May','June','July','Aug','Sep','Oct','Nov','Dec'][date.getMonth()]+" "+date.getFullYear(); - if (pointsMode == true) { - text({ctx:holder.completed[pageIndex].ctx,left:0,top:16,width:450,height:100,textArray:['<><>Page Completed!<>'+br+'<><>Completed on '+pages[pageIndex].prevDate+br+'Click to practise again for an extra point'],align:'center'}); - } else { - text({ctx:holder.completed[pageIndex].ctx,left:0,top:28,width:450,height:100,textArray:['<><>Page Completed!<>'+br+'<><>Completed on '+pages[pageIndex].prevDate],align:'center'}); - text({ctx:holder.completed[pageIndex].ctx,left:450-100,top:0,width:100,height:30,textArray:['<><>'+times+'<>Dismiss'],align:'center',vertAlign:'middle'}); - } - holder.completed[pageIndex].style.pointerEvents = 'auto'; - holder.completed[pageIndex].style.zIndex = 10000000; - addListener(holder.completed[pageIndex],function() { - hideObj(holder.completed[pageIndex]); - }); - } else { - pages[pageIndex].maxPoints = Number(pages[pageIndex].points); - pages[pageIndex].points = Number(pages[pageIndex].points); - } - pages[pageIndex].completed = false; - pages[pageIndex].stars = []; - var l = 650+100-(pages[pageIndex].maxPoints-1)*17.5; - if (pointsMode == true) { - for (var s = 0; s < pages[pageIndex].maxPoints; s++) { - var star = newctx({rect:[l+s*35-17.5,45-17.5,35,35],z:100000000}).canvas; - star.color = ['#FC3','#000']; - star.draw = function() { - this.ctx.clear(); - this.ctx.beginPath(); - this.ctx.lineWidth = 4; - this.ctx.strokeStyle = this.color[1]; - drawStar({ctx:this.ctx,c:[17.5,17.5],r:12}); - this.ctx.closePath(); - this.ctx.stroke(); - this.ctx.beginPath(); - this.ctx.fillStyle = this.color[0]; - drawStar({ctx:this.ctx,c:[17.5,17.5],r:12}); - this.ctx.fill(); - } - star.draw(); - star.click = function() { - do { - var color = ['#FC3','#F00','#33F','#3FF','#0C0','#CCC'][ran(0,5)]; - } while(this.color[0] == color); - this.color[0] = color; - this.draw(); - } - star.show = true; - pages[pageIndex].stars[s] = star; - } - } - var feedbackButton = textCanvas([1130,90,50,50],['<><>!'],'#FC9').canvas; - feedbackButton.style.zIndex = 1000; - addListenerStart(feedbackButton,toggleFeedback); - holder.feedbackButton[pageIndex] = feedbackButton; - window.p = page[pageIndex] = {}; - mathsInput[pageIndex] = []; - canvases[pageIndex] = []; - loadScript('pages/'+filename+'.js',function() { - page[pageIndex] = p; - callback(); - },errorCallback); - } - function reloadPage() { - for (var c = 0; c < canvases[pageIndex].length; c++) { - canvases[pageIndex][c].data[100] = canvases[pageIndex][c].data[0]; - canvases[pageIndex][c].data[101] = canvases[pageIndex][c].data[1]; - resizeCanvas3(canvases[pageIndex][c]); - canvases[pageIndex][c].style.zIndex = canvases[pageIndex][c].z; - } - for (var m = 0; m < mathsInput[pageIndex].length; m++) { - setMathsInputText(mathsInput[pageIndex][m],[""]); - } - if (!un(page[pageIndex].dragSnapPos)) { - for (var d = 0; d < page[pageIndex].dragSnapPos.length; d++) { - page[pageIndex].dragSnapPos[d][4] = null; - } - } - p = page[pageIndex]; - if (!un(page[pageIndex].reload)) { - page[pageIndex].reload(); - } else if (!un(page[pageIndex].taskPageAutoLoad)) { - taskPageAutoReload(page[pageIndex]); - } - if (!un(page[pageIndex].clear)) { - page[pageIndex].clear(); - } - removeFeedback(); - } - function shuffleTableCells(obj) { - var cells = []; - for (var r = 0; r < obj.cells.length; r++) { - for (var c = 0; c < obj.cells[r].length; c++) { - cells.push(obj.cells[r][c]); - } - } - cells = shuffleArray(cells); - for (var r = 0; r < obj.cells.length; r++) { - for (var c = 0; c < obj.cells[r].length; c++) { - obj.cells[r][c] = cells.shift(); - } - } - return obj; - } - function taskPageAutoLoad(p) { - //console.log(p); - p.ctx1 = newctx(); - p.ctx2 = newctx({z:1000}); - - var paths = p.paths; - var shuffleInputs = []; - var shufflePos = []; - - var dragCheckMode = 'none'; - var dragCanvasCount = 0; - var dragAreaCount = 0; - var dragSnapAreaCount = 0; - for (var p2 = 0; p2 < paths.length; p2++) { - var path = paths[p2]; - if (un(path.isInput)) continue; - if (path.isInput.type == 'drag') { - dragCanvasCount++; - } else if (path.isInput.type == 'dragArea') { - if (path.isInput.snap == true) { - dragSnapAreaCount++; - } else { - dragAreaCount++; - } - } - } - if (dragCanvasCount > 0) { - if (dragSnapAreaCount > 0) { - dragCheckMode = 'dragArea'; - } else { - dragCheckMode = 'dragCanvas'; - } - } - - for (var p2 = 0; p2 < paths.length; p2++) { - var path = paths[p2]; - if (un(path.isInput)) continue; - for (var o = 0; o < path.obj.length; o++) { - var obj = path.obj[o]; - if (obj.type == 'text2' && path.isInput.type == 'text') { - obj.draw = false; - if (typeof p.inputs == 'undefined') p.inputs = []; - var input = createMathsInput2({left:obj.rect[0],top:obj.rect[1],width:obj.rect[2],height:obj.rect[3],fontSize:32,algText:boolean(path.isInput.algText,false)}); - input.pathObj = obj; - input.type = 'text'; - if (!un(path.isInput.tickStyle)) input.tickStyle = path.isInput.tickStyle; - p.inputs.push(input); - } else if (obj.type == 'table2' && path.isInput.type == 'select') { - if (typeof p.inputs == 'undefined') p.inputs = []; - obj.isInput = path.isInput; - var multiSelect = boolean(path.isInput.multiSelect,false); - var checkSelectCount = boolean(path.isInput.checkSelectCount,true); - var shuffle = boolean(path.isInput.shuffle,false); - - var input = {type:'select',buttons:[],multiSelect:multiSelect,checkSelectCount:checkSelectCount,shuffle:shuffle}; - p.inputs.push(input); - - if (shuffle == true) shuffleTableCells(obj); - - var yPos = obj.top; - for (var r = 0; r < obj.cells.length; r++) { - var xPos = obj.left; - for (var c = 0; c < obj.cells[r].length; c++) { - var button = newctx({rect:[xPos,yPos,obj.widths[c],obj.heights[r]],pE:true,z:100}).canvas; - button.input = input; - button.cell = obj.cells[r][c]; - button.row = r; - button.col = c; - button.obj = obj; - addListener(button,taskPageSelectButtonClick); - input.buttons.push(button); - - obj.cells[r][c].toggle = false; - xPos += obj.widths[c]; - } - yPos += obj.heights[r]; - } - } else if (path.isInput.type == 'drag') { - updateBorder(path); - var rect = path.tightBorder; - rect[0] -= 3; - rect[1] -= 3; - rect[2] += 6; - rect[3] += 6; - - var dragCanvas = newctx({rect:rect,drag:true,pe:true}).canvas; - dragCanvas.ctx.translate(-rect[0],-rect[1]); - for (var o = 0; o < path.obj.length; o++) { - drawObjToCtx(dragCanvas.ctx,path,path.obj[o],1,1,0,0); - } - - if (dragCheckMode == 'dragCanvas') { - if (typeof p.inputs == 'undefined') p.inputs = []; - p.inputs.push({type:'drag',canvas:dragCanvas,shuffle:path.isInput.shuffle,value:path.isInput.value}); - } - - if (typeof p.dragCanvases == 'undefined') p.dragCanvases = []; - p.dragCanvases.push({canvas:dragCanvas,shuffle:path.isInput.shuffle,value:path.isInput.value}); - - if (path.isInput.shuffle == true) { - shuffleInputs.push(dragCanvas); - shufflePos.push([rect[0],rect[1],shufflePos.length]); - } - - paths.splice(p2,1); - p2--; - } else if (path.isInput.type == 'dragArea') { - updateBorder(path); - var rect = path.tightBorder; - rect[0] -= 3; - rect[1] -= 3; - rect[2] += 6; - rect[3] += 6; - - if (typeof p.dragAreas == 'undefined') p.dragAreas = []; - p.dragAreas.push({rect:rect,value:path.isInput.value,snap:path.isInput.snap}); - - if (dragCheckMode == 'dragArea') { - if (typeof p.inputs == 'undefined') p.inputs = []; - p.inputs.push({type:'dragArea',rect:rect,value:path.isInput.value}); - } - - if (path.isInput.snap == true) { - if (typeof p.dragSnapPos == 'undefined') p.dragSnapPos = []; - p.dragSnapPos.push(clone(rect.slice(0,4))); - } - } - } - } - if (shuffleInputs.length > 0) { - shufflePos = shuffleArray(shufflePos); - for (var i = 0; i < shuffleInputs.length; i++) { - shuffleInputs[i].data[0] = shufflePos[i][0]; - shuffleInputs[i].data[1] = shufflePos[i][1]; - shuffleInputs[i].data[100] = shufflePos[i][0]; - shuffleInputs[i].data[101] = shufflePos[i][1]; - shuffleInputs[i].style.zIndex = shufflePos[i][2]+10; - shuffleInputs[i].z = shufflePos[i][2]+10; - resizeCanvas(shuffleInputs[i]); - } - } - taskPageAutoDrawPaths(p); - - if (!un(p.keyboard)) addKeyboard(p.keyboard); - } - function taskPageAutoDrawPaths(p) { - p.ctx1.clear(); - for (var p2 = 0; p2 < p.paths.length; p2++) { - for (var o = 0; o < p.paths[p2].obj.length; o++) { - var obj = p.paths[p2].obj[o]; - if (boolean(obj.draw,true) == true) { - drawObjToCtx(p.ctx1,p.paths[p2],obj); - } - } - } - } - function taskPageSelectButtonClick(e) { - var cells = e.target.obj.cells; - var cell = e.target.cell; - - if (cell.toggle == true) { - delete cell.toggle; - } else if (e.target.input.multiSelect == true) { - cell.toggle = true; - } else { - for (var r = 0; r < cells.length; r++) { - for (var c = 0; c < cells[r].length; c++) { - if (r == e.target.row && c == e.target.col) { - cells[r][c].toggle = true; - } else { - delete cells[r][c].toggle; - } - } - } - } - - taskPageAutoDrawPaths(page[pageIndex]); - } - function taskPageAutoCheck(p) { - var checkVars = {check:true,a:[],qs:p.inputs.length}; - - for (var q = 0; q < p.inputs.length; q++) { - var input = p.inputs[q]; - if (input.type == 'text') { - var answer = false; - if (input.stringJS !== "") { - var obj = input.pathObj; - var ans = removeTags(clone(input.richText)); - for (var a = 0; a < obj.ans.length; a++) { - if (arraysEqual(ans,removeTags(clone(obj.ans[a])))) { - answer = true; - break; - } - } - } - checkVars.a[q] = {type:'text',check:answer}; - } else if (input.type == 'select') { - var answer = []; - var toggleCount = 0; - var ansCount = 0; - for (var b = 0; b < input.buttons.length; b++) { - var cell = input.buttons[b].cell; - var ans = boolean(cell.ans,false); - if (ans == true) ansCount++; - var toggle = boolean(cell.toggle,false); - if (toggle == true) toggleCount++; - answer[b] = {toggle:toggle,answer:ans}; - } - if (input.checkSelectCount == true) { - if (toggleCount < ansCount || toggleCount == 0) { - checkVars.check = false; - checkVars.fb = "You need to select more answers."; - } else if (toggleCount > ansCount) { - checkVars.check = false; - checkVars.fb = "You have selected too many answers."; - } - } - checkVars.a[q] = {type:'select',check:answer}; - } else if (input.type == 'drag') { - var check = false; - var hit = false; - for (var a = 0; a < p.dragAreas.length; a++) { - var rect = p.dragAreas[a].rect; - if (hitTestRect2(input.canvas,rect[0],rect[1],rect[2],rect[3])) { - hit = true; - if (input.value == p.dragAreas[a].value) check = true; - break; - } - } - if (hit == false) { - checkVars.check = false; - checkVars.fb = "You need to drag all the boxes into position."; - } - checkVars.a[q] = {type:'dragArea',check:check}; - } else if (input.type == 'dragArea') { - var check = false; - var hit = false; - for (var d = 0; d < p.dragCanvases.length; d++) { - var rect = input.rect; - if (hitTestRect2(p.dragCanvases[d].canvas,rect[0],rect[1],rect[2],rect[3])) { - hit = true; - if (input.value == p.dragCanvases[d].value) check = true; - break; - } - } - if (hit == false) { - checkVars.check = false; - checkVars.fb = "You need to drag boxes into the positions."; - } - checkVars.a[q] = {type:'dragArea',check:check}; - } - } - - return checkVars; - } - function taskPageAutoMark(p,r) { - p.ctx2.clear(); - - for (var q = 0; q < p.inputs.length; q++) { - if (p.inputs[q].type !== 'text') continue; - var data = p.inputs[q].data; - if (p.inputs[q].tickStyle == 'small') { - var mult = 0.6; - var l2 = data[100]+data[102]-40*mult-3; - var t2 = data[101]+data[103]-50*mult-3; - if (r.m[q] == 1) { - drawTick(p.ctx2,40*mult,50*mult,'#060',l2,t2,7*mult); - } else { - drawCross(p.ctx2,40*mult,50*mult,'#F00',l2,t2,7*mult); - } - p.inputs[q].markPos = [l2,t2,40*mult,50*mult]; - p.inputs[q].markctx = p.ctx2; - } else { - var l2 = data[100]+data[102]+15; - var t2 = data[101]+0.5*data[103]-25; - if (r.m[q] == 1) { - drawTick(p.ctx2,40,50,'#060',l2,t2,7); - } else { - drawCross(p.ctx2,40,50,'#F00',l2,t2,7); - } - p.inputs[q].markPos = [l2,t2,40,50]; - p.inputs[q].markctx = p.ctx2; - } - } - } - function taskPageAutoReload(p) { - p.ctx2.clear(); - } - - function checkPage() { - if (!un(holder.checkPageIndex) && holder.checkPageIndex > -1) return; - holder.checkPageIndex = pageIndex; - deselectMathsInput(); - if (typeof page[holder.checkPageIndex].check == 'function') { - var c = page[holder.checkPageIndex].check(); - var checkFileName = String(pages[holder.checkPageIndex].filename); - } else if (!un(page[holder.checkPageIndex].taskPageAutoLoad)) { - var c = taskPageAutoCheck(page[holder.checkPageIndex]); - var checkFileName = 'autoCheck'; - } else { - delete holder.checkPageIndex; - return; - } - - if (c.check == false) { - if (!un(c.fb)) { - drawFeedback(c.fb); - } - delete holder.checkPageIndex; - } else { - hideObj(holder.disablePeCanvas); - hideObj(holder.check); - - var xmlHttp = new XMLHttpRequest(); - xmlHttp.open("post", "pages/"+checkFileName+".php", true); - xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); - xmlHttp.errorCallback = function() { - Notifier.error('Error connecting to the server. Please try again shortly...'); - hideObj(holder.disablePeCanvas); - delete holder.checkPageIndex; - setTimeout(function() { - if (boolean(page[pageIndex].showHolderCheckButton,true) == true) { - showObj(holder.check); - } else { - hideObj(holder.check); - } - },2000); - }; - xmlHttp.onerror = xmlHttp.errorCallback; - xmlHttp.onreadystatechange = function() { - if (this.readyState !== 4) return; - if (this.status >= 400) { - if (typeof this.errorCallback == 'function') this.errorCallback(); - delete holder.checkPageIndex; - return; - } - - if (!un(document.origin) && document.origin.indexOf('localhost') > -1) console.log(this.responseText); - var response = JSON.parse(this.responseText); - if (!un(document.origin) && document.origin.indexOf('localhost') > -1) console.log('check php response:',response); - pages[holder.checkPageIndex].pageLogKey = response.pageLogKey; - if (un(pages[holder.checkPageIndex].checkCount)) pages[holder.checkPageIndex].checkCount = 0; - pages[holder.checkPageIndex].checkCount++; - p = page[holder.checkPageIndex]; - if (!un(p.mark)) { - p.mark(response); - } else if (!un(p.taskPageAutoLoad)) { - taskPageAutoMark(p,response); - } - if (typeof taskLogData !== 'undefined' && taskLogData !== null) { - taskLogData.percentage = response.percentage; - taskLogData.totalTime = response.timeSpent; - taskLogData.status = response.status; - } - if (response.correct == 1) { - pages[holder.checkPageIndex].completed = true; - hideObj(holder.feedbackButton[holder.checkPageIndex]); - hideObj(holder.feedback[holder.checkPageIndex]); - holder.canvas.ctx.clearRect(650,20,200,50); - removeFeedback(); - if (Number(response.percentage) == 100) { - showTaskCompleteMessage(); - } else { - reportHandler(); - } - if (boolean(page[holder.checkPageIndex].allowInteractionAfterCompletion,false) == false) { - for (var c = 0; c < canvases[holder.checkPageIndex].length; c++) { - canvases[holder.checkPageIndex][c].style.pointerEvents = 'none'; - } - for (var m = 0; m < mathsInput[holder.checkPageIndex].length; m++) { - mathsInput[holder.checkPageIndex][m].cursorCanvas.style.pointerEvents = 'none'; - } - if (!un(draw) && !un(draw.cursorCanvas)) { - pages[holder.checkPageIndex].drawMode = 'none'; - changeDrawMode('none'); - } - } - if (pointsMode == true) { - window.count = 0; - window.int = setCorrectingInterval(function() { - var star = pages[holder.checkPageIndex].stars[window.count]; - star.data[100] = Math.max(star.data[100]-9,613-17.5); - resizeCanvas3(star); - if (star.data[100] <= 613-17.5) { - userPoints++; - drawPoints(); - window.count++; - if (window.count == pages[holder.checkPageIndex].points) { - clearCorrectingInterval(window.int); - setTimeout(function() { - for (s = 0; s < pages[holder.checkPageIndex].maxPoints; s++) { - var star = pages[holder.checkPageIndex].stars[s]; - if (s < pages[holder.checkPageIndex].points) { - star.show = true; - star.data[100] = 600-(pages[holder.checkPageIndex].points-1)*17.5+s*35-17.5; - star.data[101] = 360; - resizeCanvas3(star); - star.style.pointerEvents = 'auto'; - addListener(star,star.click); - } else { - star.show = false; - hideObj(star); - } - } - if (!un(holder.completed[holder.checkPageIndex])) { - hideObj(holder.completed[holder.checkPageIndex]); - } - holder.completed[holder.checkPageIndex] = textCanvas([600-450/2,285,450,130],[''],['#F6F','#6FF','#FF6','#6F6','#66F','#F66'].ran()).canvas; - showObj(holder.completed[holder.checkPageIndex]); - text({ctx:holder.completed[holder.checkPageIndex].ctx,left:0,top:12,width:450,height:100,textArray:['<><>Page Completed!'],align:'center'}); - holder.completed[holder.checkPageIndex].style.pointerEvents = 'auto'; - holder.completed[holder.checkPageIndex].style.zIndex = 10000000; - addListener(holder.completed[holder.checkPageIndex],function() { - hideObj(holder.completed[holder.checkPageIndex]); - for (var s = 0; s < pages[holder.checkPageIndex].stars.length; s++) { - hideObj(pages[holder.checkPageIndex].stars[s]); - } - }); - hideObj(holder.disablePeCanvas); - showPage(); - },800); - } - } - },1000/26); - } else { - if (!un(holder.completed[holder.checkPageIndex])) { - hideObj(holder.completed[holder.checkPageIndex]); - } - holder.completed[holder.checkPageIndex] = textCanvas([600-450/2,285,450,130],[''],['#F6F','#6FF','#FF6','#6F6','#66F','#F66'].ran()).canvas; - var ctx = holder.completed[holder.checkPageIndex].ctx; - text({ctx:ctx,left:0,top:12,width:450,height:100,textArray:['<><>Page Completed!'],align:'center'}); - - ctx.beginPath(); - ctx.lineWidth = 4; - ctx.strokeStyle = '#000'; - drawStar({ctx:ctx,c:[450/2-35,90],r:12}); - ctx.closePath(); - ctx.stroke(); - ctx.beginPath(); - ctx.fillStyle = '#FC3'; - drawStar({ctx:ctx,c:[450/2-35,90],r:12}); - ctx.fill(); - - ctx.beginPath(); - ctx.lineWidth = 4; - ctx.strokeStyle = '#000'; - drawStar({ctx:ctx,c:[450/2,90],r:12}); - ctx.closePath(); - ctx.stroke(); - ctx.beginPath(); - ctx.fillStyle = '#FC3'; - drawStar({ctx:ctx,c:[450/2,90],r:12}); - ctx.fill(); - - ctx.beginPath(); - ctx.lineWidth = 4; - ctx.strokeStyle = '#000'; - drawStar({ctx:ctx,c:[450/2+35,90],r:12}); - ctx.closePath(); - ctx.stroke(); - ctx.beginPath(); - ctx.fillStyle = '#FC3'; - drawStar({ctx:ctx,c:[450/2+35,90],r:12}); - ctx.fill(); - - holder.completed[holder.checkPageIndex].style.pointerEvents = 'auto'; - holder.completed[holder.checkPageIndex].style.zIndex = 100000; - - hideObj(holder.disablePeCanvas); - if (holder.checkPageIndex === pageIndex) { - addListener(holder.completed[holder.checkPageIndex],function() { - hideObj(holder.completed[holder.checkPageIndex]); - }); - showPage(); - if (Number(response.percentage) < 100) { - showObj(holder.completed[holder.checkPageIndex]); - } else { - hideObj(holder.completed[holder.checkPageIndex]); - } - } - } - } else { - hideObj(holder.disablePeCanvas); - if (holder.checkPageIndex === pageIndex) { - setTimeout(function() { - if (boolean(page[pageIndex].showHolderCheckButton,true) == true) { - showObj(holder.check); - } else { - hideObj(holder.check); - } - },4000); - if (pointsMode == true && pages[holder.checkPageIndex].points > 1) { - pages[holder.checkPageIndex].points--; - var star = pages[holder.checkPageIndex].stars[pages[holder.checkPageIndex].points]; - star.color = ['#CFF','#999']; - star.draw(); - } - if (!un(response.fb)) { - drawFeedback(response.fb); - } - } - } - delete holder.checkPageIndex; - } - c.points = pages[holder.checkPageIndex].points; - if (!un(pages[holder.checkPageIndex].pageLogKey)) c.pageLogKey = pages[holder.checkPageIndex].pageLogKey; - c.userKey = userKey; - c.userType = userType; - c.pageId = pages[holder.checkPageIndex].pageid; - c.checkCount = pages[holder.checkPageIndex].checkCount || 0; - c.pageIds = []; - c.browserInfo = getBrowserInfo(); - c.timeSpent = Math.round(TimeMe.getTimeOnPageInSeconds('page')/60); - for (var p = 0; p < pages.length; p++) { - c.pageIds.push(pages[p].pageid); - } - if (typeof taskLogData !== 'undefined' && taskLogData !== null) { - c.tasksLogId = taskLogData.taskNumber; - } - if (!un(document.origin) && document.origin.indexOf('localhost') > -1) console.log(c); - console.log(c, "c="+encodeURIComponent(JSON.stringify(c))); - xmlHttp.send("c="+encodeURIComponent(JSON.stringify(c))); - } - } - function drawPoints() { - holder.canvas.ctx.clearRect(250,20,390,50); - text({ctx:holder.canvas.ctx,left:252,width:386,top:22,height:46,vertAlign:'middle',textArray:['<>'+userName],box:{type:'loose',radius:8,color:'#CFF',borderColor:'#000',borderWidth:4,padding:10}}); - if (pointsMode == true) { - text({ctx:holder.canvas.ctx,left:252,width:386,top:22,height:46,align:'right',vertAlign:'middle',textArray:['<><><>'+userPoints+' '],allowSpaces:true}); - holder.canvas.ctx.beginPath(); - holder.canvas.ctx.lineWidth = 4; - holder.canvas.ctx.strokeStyle = '#000'; - drawStar({ctx:holder.canvas.ctx,c:[613,45],r:12}); - holder.canvas.ctx.closePath(); - holder.canvas.ctx.stroke(); - holder.canvas.ctx.beginPath(); - holder.canvas.ctx.fillStyle = '#00F'; - drawStar({ctx:holder.canvas.ctx,c:[613,45],r:12}); - holder.canvas.ctx.fill(); - } - } - function drawFeedback(txt) { - if (typeof txt == 'string') txt = [txt]; - txt.unshift('<>'); - if (un(holder.feedback[pageIndex])) { - holder.feedback[pageIndex] = newctx({pe:true,z:100000}).canvas; - addListenerEnd(holder.feedback[pageIndex],toggleFeedback); - } - holder.feedback[pageIndex].fb = true; - var fb = holder.feedback[pageIndex]; - showObj(holder.feedbackButton[pageIndex]); - var size = text({ctx:fb.ctx,textArray:txt,align:'center',measureOnly:true,left:800,top:90+5,width:400,height:610,box:{type:'tight',color:'#FC9',borderColor:'#000',borderWidth:4,radius:8,padding:15}}); - fb.data[100] = 1120 - size.tightRect[2]; - fb.data[101] = 90; - fb.data[102] = size.tightRect[2]; - fb.data[103] = size.tightRect[3]; - fb.width = size.tightRect[2]; - fb.height = size.tightRect[3]; - resizeCanvas3(fb); - textBox(fb.ctx,[0,0,size.tightRect[2],size.tightRect[3]],txt,'#FC9'); - showObj(holder.feedback[pageIndex]); - }; - function toggleFeedback() { - if (un(holder.feedback[pageIndex])) return; - if (holder.feedback[pageIndex].parentNode == container) { - hideObj(holder.feedback[pageIndex]); - } else { - showObj(holder.feedback[pageIndex]); - } - }; - function removeFeedback() { - if (!un(holder.feedback[pageIndex])) { - holder.feedback[pageIndex].fb = false; - hideObj(holder.feedbackButton[pageIndex]); - hideObj(holder.feedback[pageIndex]); - } - } - - var taskCompleteMessage; - function loadTaskCompleteMessage() { - //create purple background - taskCompleteMessage = newctx({rect:[20,94,1150,576],vis:false,z:1000000,pE:true,page:false}).canvas; - taskCompleteMessage.style.backgroundColor = "#C6F"; - taskCompleteMessage.style.borderRadius = "5px"; - taskCompleteMessage.style.border = "4px solid black" - taskCompleteMessage.style.cursor = "auto"; - //addListener(taskCompleteMessage,dismissTaskCompleteMessage); - - taskCompleteMessage.starYellow = new Image; - taskCompleteMessage.starYellowPointy = new Image; - taskCompleteMessage.starWhite6points = new Image; - - taskCompleteMessage.starYellow.src = "../Images/starYellow.png"; - taskCompleteMessage.starYellowPointy.src = "../Images/starYellowPointy.png"; - taskCompleteMessage.starWhite6points.src = "../Images/starWhite6points.png"; - - taskCompleteMessage.stars = []; - - //create dismiss button - var dismiss = newctx({rect:[1050, 120, 110, 26],vis:false,z:10000001,pE:true,page:false}).canvas; - dismiss.ctx.font = "30px Arial"; - dismiss.ctx.fillStyle = "#FFF"; - dismiss.ctx.textAlign = "center"; - dismiss.ctx.textBaseline = "middle"; - dismiss.ctx.fillText("Dismiss", 55, 13); - //addListener(dismiss, dismissTaskCompleteMessage) - taskCompleteMessage.stars.push(dismiss); - - for (var i = 0; i < 9; i++) { - var l = [100,750,700,300,950,900,820,1000,500][i]-6; - var t = [150,120,400,120,300,120,250,500,100][i]; - var w = [126,126,252,189,189,126,126,126,252][i]; - var star = newctx({rect:[l,t,w,w],vis:false,z:100000002+i,page:false}).canvas; - star.style.cursor = "auto"; - taskCompleteMessage.stars.push(star); - } - resize(); - } - function showTaskCompleteMessage() { - if (un(taskCompleteMessage)) loadTaskCompleteMessage(); - hideObj(holder.completed[pageIndex]); - showObj(taskCompleteMessage); - for (i = 0; i < taskCompleteMessage.stars.length; i++) { - showObj(taskCompleteMessage.stars[i]); - taskCompleteMessage.stars[i].style.zIndex = 1000000; - } - - taskCompleteMessage.ctx.fillStyle = "#FFF"; - taskCompleteMessage.ctx.textAlign = "center"; - taskCompleteMessage.ctx.textBaseline = "middle"; - - if (userType == 'Pupil') { - taskCompleteMessage.ctx.font = "110px Hobo"; - taskCompleteMessage.ctx.fillText("Task Complete!", 350, 275); - taskCompleteMessage.ctx.font = "55px Hobo"; - taskCompleteMessage.ctx.fillText("Well done, " + userName, 350, 420); - taskCompleteMessage.ctx.font = "55px Hobo"; - taskCompleteMessage.ctx.fillText("Your result has been logged", 350, 490); - } else { - taskCompleteMessage.ctx.font = "110px Hobo"; - taskCompleteMessage.ctx.fillText("Task Complete!", 350, 375); - } - - taskCompleteMessage.interval = setInterval(function(){taskCompleteMessage.rotate()},25); - - taskCompleteMessage.rotate = function() { - for (i = 1; i < taskCompleteMessage.stars.length; i++) { - taskCompleteMessage.stars[i].ctx.clear(); - taskCompleteMessage.stars[i].ctx.translate(taskCompleteMessage.stars[i].data[2] / 2, taskCompleteMessage.stars[i].data[3] / 2); - taskCompleteMessage.stars[i].ctx.rotate(Math.PI / 180); - taskCompleteMessage.stars[i].ctx.translate(taskCompleteMessage.stars[i].data[2] / -2, taskCompleteMessage.stars[i].data[3] / -2); - } - taskCompleteMessage.stars[1].ctx.drawImage(taskCompleteMessage.starYellow,20,20,86,86); - taskCompleteMessage.stars[2].ctx.drawImage(taskCompleteMessage.starYellow,20,20,86,86); - taskCompleteMessage.stars[3].ctx.drawImage(taskCompleteMessage.starYellow,60,60,172,172); - taskCompleteMessage.stars[4].ctx.drawImage(taskCompleteMessage.starWhite6points,24,33,141,123); - taskCompleteMessage.stars[5].ctx.drawImage(taskCompleteMessage.starWhite6points,24,33,141,123); - taskCompleteMessage.stars[6].ctx.drawImage(taskCompleteMessage.starYellowPointy,20,21,86,84); - taskCompleteMessage.stars[7].ctx.drawImage(taskCompleteMessage.starYellowPointy,20,21,86,84); - taskCompleteMessage.stars[8].ctx.drawImage(taskCompleteMessage.starYellowPointy,20,21,86,84); - taskCompleteMessage.stars[9].ctx.drawImage(taskCompleteMessage.starYellowPointy,40,42,152,148); - } - addListener(window,dismissTaskCompleteMessage); - } - function dismissTaskCompleteMessage() { - hideObj(taskCompleteMessage); - for (i = 0; i < taskCompleteMessage.stars.length; i++) { - hideObj(taskCompleteMessage.stars[i]); - } - if (!un(taskCompleteMessage.interval)) { - clearInterval(taskCompleteMessage.interval); - } - removeListener(window,dismissTaskCompleteMessage); - } - - function createHorizPos(num,width,left,right) { - if (typeof left == 'undefined') left = width; - if (typeof right == 'undefined') right = width; - var space = (1200 - num * width - left - right) / (num-1); - var arr = []; - for (var i = 0; i < num; i++) { - arr[i] = left+i*(width+space); - } - return arr; - } - function createVertPos(num,height,top,bottom) { - if (typeof top == 'undefined') top = height; - if (typeof bottom == 'undefined') bottom = height; - var space = (620 - num * height - top - bottom) / (num-1); - var arr = []; - for (var i = 0; i < num; i++) { - arr[i] = 80+top+i*(height+space); - } - return arr; - } - - function swipedetect(el, callback){ - var touchsurface = el, - swipedir, - startX, - startY, - distX, - distY, - dist, - threshold = 150, //required min distance traveled to be considered swipe - restraint = 100, // maximum distance allowed at the same time in perpendicular direction - allowedTime = 400, // maximum time allowed to travel that distance - elapsedTime, - startTime, - handleswipe = callback || function(swipedir){} - - touchsurface.addEventListener('touchstart', function(e){ - var touchobj = e.changedTouches[0] - swipedir = 'none' - dist = 0 - startX = touchobj.pageX - startY = touchobj.pageY - startTime = new Date().getTime() // record time when finger first makes contact with surface - e.preventDefault() - }, false) - - touchsurface.addEventListener('touchmove', function(e){ - e.preventDefault() // prevent scrolling when inside DIV - }, false) - - touchsurface.addEventListener('touchend', function(e){ - var touchobj = e.changedTouches[0] - distX = touchobj.pageX - startX // get horizontal dist traveled by finger while in contact with surface - distY = touchobj.pageY - startY // get vertical dist traveled by finger while in contact with surface - elapsedTime = new Date().getTime() - startTime // get time elapsed - if (elapsedTime <= allowedTime){ // first condition for awipe met - if (Math.abs(distX) >= threshold && Math.abs(distY) <= restraint){ // 2nd condition for horizontal swipe met - swipedir = (distX < 0)? 'left' : 'right' // if dist traveled is negative, it indicates left swipe - } - else if (Math.abs(distY) >= threshold && Math.abs(distX) <= restraint){ // 2nd condition for vertical swipe met - swipedir = (distY < 0)? 'up' : 'down' // if dist traveled is negative, it indicates up swipe - } - } - if (e.target.drag !== true) handleswipe(swipedir) - e.preventDefault() - }, false) - } - swipedetect (canvas, function(swipedir){ - // swipedir contains either "none", "left", "right", "top", or "down" - - if (swipedir == 'left') { - nextPage(); - } else if (swipedir == 'right') { - prevPage(); - } - }) -} -function getBrowserInfo() { - /** - * JavaScript Client Detection - * (C) viazenetti GmbH (Christian Ludwig) - */ - - var unknown = '-'; - - // screen - var screenSize = ''; - if (screen.width) { - width = (screen.width) ? screen.width : ''; - height = (screen.height) ? screen.height : ''; - screenSize += '' + width + " x " + height; - } - - // browser - var nVer = navigator.appVersion; - var nAgt = navigator.userAgent; - var browser = navigator.appName; - var version = '' + parseFloat(navigator.appVersion); - var majorVersion = parseInt(navigator.appVersion, 10); - var nameOffset, verOffset, ix; - - // Opera - if ((verOffset = nAgt.indexOf('Opera')) != -1) { - browser = 'Opera'; - version = nAgt.substring(verOffset + 6); - if ((verOffset = nAgt.indexOf('Version')) != -1) { - version = nAgt.substring(verOffset + 8); - } - } - // Opera Next - if ((verOffset = nAgt.indexOf('OPR')) != -1) { - browser = 'Opera'; - version = nAgt.substring(verOffset + 4); - } - // Edge - else if ((verOffset = nAgt.indexOf('Edge')) != -1) { - browser = 'Microsoft Edge'; - version = nAgt.substring(verOffset + 5); - } - // MSIE - else if ((verOffset = nAgt.indexOf('MSIE')) != -1) { - browser = 'Microsoft Internet Explorer'; - version = nAgt.substring(verOffset + 5); - } - // Chrome - else if ((verOffset = nAgt.indexOf('Chrome')) != -1) { - browser = 'Chrome'; - version = nAgt.substring(verOffset + 7); - } - // Safari - else if ((verOffset = nAgt.indexOf('Safari')) != -1) { - browser = 'Safari'; - version = nAgt.substring(verOffset + 7); - if ((verOffset = nAgt.indexOf('Version')) != -1) { - version = nAgt.substring(verOffset + 8); - } - } - // Firefox - else if ((verOffset = nAgt.indexOf('Firefox')) != -1) { - browser = 'Firefox'; - version = nAgt.substring(verOffset + 8); - } - // MSIE 11+ - else if (nAgt.indexOf('Trident/') != -1) { - browser = 'Microsoft Internet Explorer'; - version = nAgt.substring(nAgt.indexOf('rv:') + 3); - } - // Other browsers - else if ((nameOffset = nAgt.lastIndexOf(' ') + 1) < (verOffset = nAgt.lastIndexOf('/'))) { - browser = nAgt.substring(nameOffset, verOffset); - version = nAgt.substring(verOffset + 1); - if (browser.toLowerCase() == browser.toUpperCase()) { - browser = navigator.appName; - } - } - // trim the version string - if ((ix = version.indexOf(';')) != -1) version = version.substring(0, ix); - if ((ix = version.indexOf(' ')) != -1) version = version.substring(0, ix); - if ((ix = version.indexOf(')')) != -1) version = version.substring(0, ix); - - majorVersion = parseInt('' + version, 10); - if (isNaN(majorVersion)) { - version = '' + parseFloat(navigator.appVersion); - majorVersion = parseInt(navigator.appVersion, 10); - } - - // mobile version - var mobile = /Mobile|mini|Fennec|Android|iP(ad|od|hone)/.test(nVer); - - // cookie - var cookieEnabled = (navigator.cookieEnabled) ? true : false; - - if (typeof navigator.cookieEnabled == 'undefined' && !cookieEnabled) { - document.cookie = 'testcookie'; - cookieEnabled = (document.cookie.indexOf('testcookie') != -1) ? true : false; - } - - // system - var os = unknown; - var clientStrings = [ - {s:'Windows 10', r:/(Windows 10.0|Windows NT 10.0)/}, - {s:'Windows 8.1', r:/(Windows 8.1|Windows NT 6.3)/}, - {s:'Windows 8', r:/(Windows 8|Windows NT 6.2)/}, - {s:'Windows 7', r:/(Windows 7|Windows NT 6.1)/}, - {s:'Windows Vista', r:/Windows NT 6.0/}, - {s:'Windows Server 2003', r:/Windows NT 5.2/}, - {s:'Windows XP', r:/(Windows NT 5.1|Windows XP)/}, - {s:'Windows 2000', r:/(Windows NT 5.0|Windows 2000)/}, - {s:'Windows ME', r:/(Win 9x 4.90|Windows ME)/}, - {s:'Windows 98', r:/(Windows 98|Win98)/}, - {s:'Windows 95', r:/(Windows 95|Win95|Windows_95)/}, - {s:'Windows NT 4.0', r:/(Windows NT 4.0|WinNT4.0|WinNT|Windows NT)/}, - {s:'Windows CE', r:/Windows CE/}, - {s:'Windows 3.11', r:/Win16/}, - {s:'Android', r:/Android/}, - {s:'Open BSD', r:/OpenBSD/}, - {s:'Sun OS', r:/SunOS/}, - {s:'Linux', r:/(Linux|X11)/}, - {s:'iOS', r:/(iPhone|iPad|iPod)/}, - {s:'Mac OS X', r:/Mac OS X/}, - {s:'Mac OS', r:/(MacPPC|MacIntel|Mac_PowerPC|Macintosh)/}, - {s:'QNX', r:/QNX/}, - {s:'UNIX', r:/UNIX/}, - {s:'BeOS', r:/BeOS/}, - {s:'OS/2', r:/OS\/2/}, - {s:'Search Bot', r:/(nuhk|Googlebot|Yammybot|Openbot|Slurp|MSNBot|Ask Jeeves\/Teoma|ia_archiver)/} - ]; - for (var id in clientStrings) { - var cs = clientStrings[id]; - if (cs.r.test(nAgt)) { - os = cs.s; - break; - } - } - - var osVersion = unknown; - - if (/Windows/.test(os)) { - var a = /Windows (.*)/.exec(os) - if (a instanceof Array) { - osVersion = a[1]; - } - os = 'Windows'; - } - - switch (os) { - case 'Mac OS X': - var a = /Mac OS X (10[\.\_\d]+)/.exec(nAgt); - if (a instanceof Array) { - osVersion = a[1]; - } - break; - - case 'Android': - var a = /Android ([\.\_\d]+)/.exec(nAgt); - if (a instanceof Array) { - osVersion = a[1]; - } - break; - - case 'iOS': - var a = /OS (\d+)_(\d+)_?(\d+)?/.exec(nVer); - if (a instanceof Array) { - osVersion = a[1] + '.' + a[2] + '.' + (a[3] | 0); - } - break; - } - - window.browserinfo = { - screen: screenSize, - browser: browser, - browserVersion: version, - browserMajorVersion: majorVersion, - mobile: mobile, - os: os, - osVersion: osVersion, - cookies: cookieEnabled, - }; - return os+" "+osVersion+" "+browser+" "+version+" "+screenSize+" mobile:"+mobile+" cookies:"+cookieEnabled; -} - -function stopDefaultBackspaceBehaviour(e) { - if (e.keyCode == 8 && e.target.nodeName !== 'TEXTAREA' && e.target.nodeName !== 'INPUT' && e.target.nodeName !== 'TD') { - e.preventDefault ? e.preventDefault() : e.returnValue = false; - } -} -function xWindowToCanvas(xCoord) { - return mainCanvasWidth * ((xCoord - canvasMetrics.left) / (canvasDisplayWidth)); -} -function xCanvasToWindow(xCoord) { - return canvasMetrics.left + (xCoord / mainCanvasWidth) * canvasDisplayWidth; -} -function yWindowToCanvas(yCoord) { - return mainCanvasHeight * ((yCoord - canvasMetrics.top) / canvasDisplayHeight); -} -function yCanvasToWindow(yCoord) { - return canvasMetrics.top + (yCoord / mainCanvasHeight) * canvasDisplayHeight; -} - -function addListener(toButton, yourFunction) { - toButton.addEventListener("touchend", yourFunction, false) - toButton.addEventListener("mouseup", yourFunction, false) -} -function removeListener(toButton, yourFunction) { - toButton.removeEventListener("touchend", yourFunction, false) - toButton.removeEventListener("mouseup", yourFunction, false) -} -function addListenerStart(toButton, yourFunction) { - toButton.addEventListener("touchstart", yourFunction, false) - toButton.addEventListener("mousedown", yourFunction, false); -} -function removeListenerStart(toButton, yourFunction) { - toButton.removeEventListener("touchstart", yourFunction, false) - toButton.removeEventListener("mousedown", yourFunction, false); -} -function addListenerMove(toButton, yourFunction) { - toButton.addEventListener("touchmove", yourFunction, false) - toButton.addEventListener("mousemove", yourFunction, false) -} -function removeListenerMove(toButton, yourFunction) { - toButton.removeEventListener("touchmove", yourFunction, false) - toButton.removeEventListener("mousemove", yourFunction, false) -} -function addListenerEnd(toButton, yourFunction) { - toButton.addEventListener("touchend", yourFunction, false) - toButton.addEventListener("mouseup", yourFunction, false); -} -function removeListenerEnd(toButton, yourFunction) { - toButton.removeEventListener("touchend", yourFunction, false) - toButton.removeEventListener("mouseup", yourFunction, false); -} - -function resize() { - var totalWidth = mainCanvasWidth + mainCanvasMargins[0] + mainCanvasMargins[2]; - var totalHeight = mainCanvasHeight + mainCanvasMargins[1] + mainCanvasMargins[3]; - var aspectRatio = totalWidth / totalHeight; - if (window.innerWidth / window.innerHeight > aspectRatio) { - var totalDisplayWidth = window.innerHeight * aspectRatio; - var totalDisplayHeight = window.innerHeight; - } else { - var totalDisplayWidth = window.innerWidth; - var totalDisplayHeight = window.innerWidth / aspectRatio; - } - canvasDisplayWidth = totalDisplayWidth * (mainCanvasWidth / totalWidth); - canvasDisplayHeight = totalDisplayHeight * (mainCanvasHeight / totalHeight); - canvasDisplayLeft = (window.innerWidth - totalDisplayWidth) / 2 + mainCanvasMargins[0] * (totalDisplayWidth/totalWidth); - canvasDisplayTop = (window.innerHeight - totalDisplayHeight) / 2 + mainCanvasMargins[1] * (totalDisplayHeight/totalHeight); - - //canvas.style.left = canvasDisplayLeft + 'px'; - //canvas.style.top = canvasDisplayTop + 'px'; - //canvas.style.top = '0px'; - canvas.style.width = canvasDisplayWidth + 'px'; - canvas.style.height = canvasDisplayHeight + 'px'; - canvasDisplayRect = canvas.getBoundingClientRect(); - - if (typeof inactiveBox !== 'undefined') resizeCanvas(inactiveBox, 400, 290, 400, 120); - if (boolean(isTask,true) == true) { - resizeCanvas3(holder.prev); - resizeCanvas3(holder.next); - resizeCanvas3(holder.reload); - resizeCanvas3(holder.canvas); - resizeCanvas3(holder.check); - resizeCanvas3(holder.home); - resizeCanvas3(holder.home2); - resizeCanvas3(holder.loading); - resizeCanvas3(holder.summary); - resizeCanvas3(holder.summary2); - resizeCanvas3(holder.disablePeCanvas); - for (var i = 0; i < holder.feedback.length; i++) { - if (!un(holder.feedback[i])) resizeCanvas3(holder.feedback[i]); - } - for (var i = 0; i < holder.feedbackButton.length; i++) { - if (!un(holder.feedbackButton[i])) resizeCanvas3(holder.feedbackButton[i]); - } - for (var i = 0; i < holder.completed.length; i++) { - if (!un(holder.completed[i])) resizeCanvas3(holder.completed[i]); - } - if (pageIndex < pages.length) { - if (!un(pages[pageIndex].stars)) { - for (var s = 0; s < pages[pageIndex].stars.length; s++) { - resizeCanvas3(pages[pageIndex].stars[s]); - } - } - } - } - if (!un(canvases[pageIndex])) { - for (var c = 0; c < canvases[pageIndex].length; c++) { - resizeCanvas3(canvases[pageIndex][c]); - } - } - if (!un(taskCompleteMessage)) { - resizeCanvas3(taskCompleteMessage); - for (var c = 0; c < taskCompleteMessage.stars.length; c++) { - resizeCanvas3(taskCompleteMessage.stars[c]); - } - } - if (!un(mathsInput[pageIndex])) { - for (var m = 0; m < mathsInput[pageIndex].length; m++) { - resizeCanvas3(mathsInput[pageIndex][m].canvas); - resizeCanvas3(mathsInput[pageIndex][m].cursorCanvas); - } - } - if (!un(slider[pageIndex])) { - for (var s = 0; s < slider[pageIndex].length; s++) { - resizeCanvas3(slider[pageIndex][s].backCanvas); - resizeCanvas3(slider[pageIndex][s].sliderCanvas); - resizeCanvas3(slider[pageIndex][s].labelCanvas); - } - } - for (var j = 0; j < keyboard.length; j++) { - if (typeof keyboard[j] !== 'undefined') { - resizeCanvas3(keyboardButton1); - resizeCanvas3(keyboardButton2); - resizeCanvas(keyboard[j], keyboardData[j][100], keyboardData[j][101], keyboardData[j][2], keyboardData[j][3]); - for (var i = 0; i -1) { - var pos = closestPos; - if (typeof pos[4] !== 'undefined' && pos[4] !== null) { - pos[4].data[100] = pos[4].data[0]; - pos[4].data[101] = pos[4].data[1]; - resizeCanvas3(pos[4]); - } - dragObj.data[100] = pos[0]; - dragObj.data[101] = pos[1]; - resizeCanvas3(dragObj); - pos[4] = dragObj; - } - } - if (typeof dragObj.ondragstop == 'function') dragObj.ondragstop(); - if (typeof dragObj.dragStop == 'function') dragObj.dragStop(); - dragObj = null; -} - -function showObj(obj, hideAfter) { - if (un(obj)) return; - if (!isElement(obj)) { - if (obj instanceof Array) { - for (var i = 0; i < obj.length; i++) { - showObj(obj[i]); - } - } else if (typeof obj == 'object') { - for (var i in obj) { - showObj(obj[i]); - } - } - return; - } - if (!un(draw) && !un(draw.div) && draw.drawCanvas.indexOf(obj) > -1) { - draw.div.children[0].appendChild(obj); - } else { - container.appendChild(obj); - resizeCanvas3(obj); - } - obj.vis = true; - if (typeof hideAfter == 'number') { - setTimeout(function () { - hideObj(obj) - }, hideAfter); - } -} -function hideObj(obj) { - if (un(obj)) return; - if (!isElement(obj)) { - if (obj instanceof Array) { - for (var i = 0; i < obj.length; i++) { - hideObj(obj[i]); - } - } else if (typeof obj == 'object') { - for (var i in obj) { - hideObj(obj[i]); - } - } - return; - } - obj.vis = false; - if (obj.parentNode == container) { - container.removeChild(obj) - } else if (!un(draw) && !un(draw.div) && draw.drawCanvas.indexOf(obj) > -1 && !un(obj.parentNode)) { - obj.parentNode.removeChild(obj); - } -} diff --git a/tools/i2/_keyboard.js b/tools/i2/_keyboard.js deleted file mode 100644 index 5de2e55..0000000 --- a/tools/i2/_keyboard.js +++ /dev/null @@ -1,709 +0,0 @@ - -function mathsInputFrac(e) {mathsInputElement("['frac', [''], ['']]");} -function mathsInputPow(e) {mathsInputElement("['power', false, ['']]");} -function mathsInputSubs(e) {mathsInputElement("['subs', [''], ['']]");} -function mathsInputRoot(e) {mathsInputElement("['root', [''], ['']]");} -function mathsInputSqrt(e) {mathsInputElement("['sqrt', ['']]");} -function mathsInputSin(e) {mathsInputElement("['sin', ['']]");} -function mathsInputCos(e) {mathsInputElement("['cos', ['']]");} -function mathsInputTan(e) {mathsInputElement("['tan', ['']]");} -function mathsInputInvSin(e) {mathsInputElement("['sin-1', ['']]");} -function mathsInputInvCos(e) {mathsInputElement("['cos-1', ['']]");} -function mathsInputInvTan(e) {mathsInputElement("['tan-1', ['']]");} -function mathsInputLn(e) {mathsInputElement("['ln', ['']]");} -function mathsInputLog(e) {mathsInputElement("['log', ['']]");} -function mathsInputLogBase(e) {mathsInputElement("['logBase', [''], ['']]");} -function mathsInputAbs(e) {mathsInputElement("['abs', ['']]");} -function mathsInputExp(e) {mathsInputElement("['exp', ['']]");} -function mathsInputSigma1(e) {mathsInputElement("['sigma1', ['']]");} -function mathsInputSigma2(e) {mathsInputElement("['sigma2', [''], [''], ['']]");} -function mathsInputInt1(e) {mathsInputElement("['int1', ['']]");} -function mathsInputInt2(e) {mathsInputElement("['int2', [''], [''], ['']]");} -function mathsInputVectorArrow(e) {mathsInputElement("['vectorArrow', ['']]");} -function mathsInputBar(e) {mathsInputElement("['bar', ['']]");} -function mathsInputHat(e) {mathsInputElement("['hat', ['']]");} -function mathsInputRecurring(e) {mathsInputElement("['recurring', ['']]");} -function mathsInputColVector2d(e) {mathsInputElement("['colVector2d', [''], ['']]");} -function mathsInputColVector3d(e) {mathsInputElement("['colVector3d', [''], [''], ['']]");} -function mathsInputMixedNum(e) {mathsInputElement("['mixedNum', [''], [''], ['']]");} -function mathsInputLim(e) {mathsInputElement("['lim', [''], ['']]");} - -var keyboardButton1 = []; -var keyboardButton2 = []; -var keyboardChars = [ - {display:'0x00D7',name:'times'}, - {display:'0x00F7',name:'divide'}, - {display:'0x00B0',name:'degrees'}, - {display:'0x221E',name:'infinity'}, - {display:'0x2261',name:'equivalence'}, - {display:'0x2248',name:'approximately'}, - {display:'0x2264',name:'lessEqual'}, - {display:'0x2265',name:'moreEqual'}, - {display:'0x03C0',name:'pi'}, - {display:'0x2260',name:'notEqual'}, - {display:'0x03B8',name:'theta'}, - {display:'0x00B1',name:'plusMinus'}, - {display:'0x2213',name:'minusPlus'}, - {display:'0x2B1A',name:'dottedSquare'}, - {display:'0x2115',name:'naturals'}, - {display:'0x2124',name:'integers'}, - {display:'0x211A',name:'rationals'}, - {display:'0x211D',name:'reals'}, - {display:'0x2208',name:'elementOf'}, - {display:'0x2209',name:'notElementOf'}, - {display:'0x221D',name:'proportionalTo'}, - {display:'0x2220',name:'angle'}, - {display:'0x2229',name:'intersection'}, - {display:'0x222A',name:'union'}, - {display:'0x2234',name:'therefore'}, - {display:'0x2190',name:'leftArrow'}, - {display:'0x2191',name:'upArrow'}, - {display:'0x2192',name:'rightArrow'}, - {display:'0x2193',name:'downArrow'} -]; -var keyboardElements = [ - {display:['<>x',['power',false,['']]],name:'power',func:mathsInputPow}, - {display:['<>x',['power',false,['']]],name:'pow',func:mathsInputPow}, - {display:['x',['subs',false,['']]],name:'subs',func:mathsInputSubs}, - {display:[['frac',[''],['']]],name:'frac',func:mathsInputFrac}, - {display:[['sqrt',['']]],name:'sqrt',func:mathsInputSqrt}, - {display:[['root',[''],['']]],name:'root',func:mathsInputRoot}, - {display:[['sin',['']]],name:'sin',func:mathsInputSin}, - {display:[['sin-1',['']]],name:'sin-1',func:mathsInputInvSin}, - {display:[['cos',['']]],name:'cos',func:mathsInputCos}, - {display:[['cos-1',['']]],name:'cos-1',func:mathsInputInvCos}, - {display:[['tan',['']]],name:'tan',func:mathsInputTan}, - {display:[['tan-1',['']]],name:'tan-1',func:mathsInputInvTan}, - {display:[['ln',['']]],name:'ln',func:mathsInputLn}, - {display:[['log',['']]],name:'log',func:mathsInputLog}, - {display:[['logBase',[''],['']]],name:'logBase',func:mathsInputLogBase}, - {display:[['abs',['']]],name:'abs',func:mathsInputAbs}, - {display:[['exp',['']]],name:'exp',func:mathsInputExp}, - {display:[['sigma1',['']]],name:'sigma1',func:mathsInputSigma1}, - {display:[['sigma2',[''],[''],['']]],name:'sigma2',func:mathsInputSigma2}, - {display:[['int1',['']]],name:'int1',func:mathsInputInt1}, - {display:[['int2',[''],[''],['']]],name:'int2',func:mathsInputInt2}, - {display:[['vectorArrow',['']]],name:'vectorArrow',func:mathsInputVectorArrow}, - {display:[['bar',['']]],name:'bar',func:mathsInputBar}, - {display:[['hat',['']]],name:'hat',func:mathsInputHat}, - {display:[['recurring',['']]],name:'recurring',func:mathsInputRecurring}, - {display:[['colVector2d',[''],['']]],name:'colVector2d',func:mathsInputColVector2d}, - {display:[['colVector3d',[''],[''],['']]],name:'colVector3d',func:mathsInputColVector3d}, - {display:[['mixedNum',[''],[''],['']]],name:'mixedNum',func:mathsInputMixedNum}, - {display:[['lim',[''],['']]],name:'lim',func:mathsInputLim} -]; - -function addKeyboard(object) { - if (object.type == 'num') { - object.keyArray = [ - ['1','2','3'], - ['4','5','6'], - ['7','8','9'], - ['-','0','delete'] - ]; - } - object.keySize = 50; - object.fontSize = 36; - createKeyboard(object); -} - -function createKeyboard(object) { - var keySize = object.keySize || 60; - var fontSize = object.fontSize || 40; - var keyPadding = object.keyPadding || 5; - var align = object.align || 'left'; - var keyArray = object.keyArray; - var backColor = object.backColor || '#F0F'; - var algText = object.algText || false; - var rows = object.keyArray.length; - var keyButtonLeft = object.keyButtonLeft || 1130; - var keyButtonTop = object.keyButtonTop || 630; - var keyButtonSize = object.keyButtonSize || 50; - var dragArea = object.dragArea || [15,100,15,15]; // this is xMin, yMin, xMax, yMax - //var textInputMode = boolean(object.textInputMode,false); - - var cols; - for (var i = 0; i < keyArray.length; i++) { - if (!cols) {cols = keyArray[i].length}; - cols = Math.max(cols, keyArray[i].length); - } - - // width and height of keyboard - var width = cols * (keySize + keyPadding) + keyPadding * 5; - var height = rows * (keySize + keyPadding) + 40 + keyPadding * 4; - - var left = object.left || 1180 - width; - var top = object.top || 620 - height; - - // create keyboard canvas - var canvasInstance = document.createElement('canvas'); - canvasInstance.width = width; - canvasInstance.height = height; - canvasInstance.setAttribute('position', 'absolute'); - canvasInstance.setAttribute('cursor', 'auto'); - canvasInstance.setAttribute('draggable', 'false'); - canvasInstance.setAttribute('class', 'buttonClass'); - canvasInstance.style.zIndex = 800000; - canvasInstance.style.cursor = openhand; - //canvasInstance.textInputMode = textInputMode; - - canvasInstance.dragArea = dragArea; - var contextInstance = canvasInstance.getContext('2d'); - roundedRect(contextInstance, 2, 2, width - 4, height - 4, 15, 4, '#000', backColor) - contextInstance.strokeStyle = '#333'; - contextInstance.lineWidth = 4; - contextInstance.beginPath(); - contextInstance.moveTo(15, 25); - contextInstance.lineTo(width - 55, 25); - contextInstance.closePath(); - contextInstance.stroke(); - contextInstance.font = '20px Arial'; - contextInstance.textBaseline = 'middle'; - contextInstance.textAlign = 'center'; - contextInstance.fillStyle = backColor; - contextInstance.fillRect((0.5 * width - 20) - 0.5 * contextInstance.measureText('Keyboard').width - 10, 20, contextInstance.measureText('Keyboard').width + 20, 10); - contextInstance.fillStyle = '#333'; - contextInstance.fillText('Keyboard', 0.5 * width - 20, 25); - - canvasInstance.data = [left, top, width, height]; - for (var i = 0; i < 4; i++) { - canvasInstance.data[100+i] = canvasInstance.data[i]; - } - canvasInstance.data[116] = false; - keyboard[pageIndex] = canvasInstance; - keyboardData[pageIndex] = canvasInstance.data; - - // make draggable - addListenerStart(keyboard[pageIndex],dragKeyboardStart) - keyboardVis[pageIndex] = false; - - // create keys - var rowNum; - var colNum; - var keyCount = 0; - key1[pageIndex] = []; - key1Data[pageIndex] = []; - - for (var rowNum = 0; rowNum < keyArray.length; rowNum++) { - var keyLeft; - if (align == 'left') { - keyLeft = left + keyPadding * 3; - } else if (align == 'right') { - keyLeft = left + width - keyArray[rowNum].length * (keySize + keyPadding) - keyPadding * 2; - } else { - keyLeft = left + 0.5 * (width - keyArray[rowNum].length * (keySize + keyPadding)); - } - var keyTop = top + keyPadding + 40 + keyPadding + rowNum * (keySize + keyPadding); - - for (var colNum = 0; colNum < keyArray[rowNum].length; colNum++) { - var canvasInstance = document.createElement('canvas'); - canvasInstance.width = keySize; - canvasInstance.height = keySize; - canvasInstance.setAttribute('position', 'absolute'); - canvasInstance.setAttribute('cursor', 'auto'); - canvasInstance.setAttribute('draggable', 'false'); - canvasInstance.setAttribute('class', 'buttonClass'); - canvasInstance.style.zIndex = 800000; - canvasInstance.style.opacity = 0.7; - canvasInstance.style.pointerEvents = 'none'; - - var contextInstance = canvasInstance.getContext('2d'); - - canvasInstance.name = keyArray[rowNum][colNum]; - canvasInstance.value = clone(keyArray[rowNum][colNum]); - canvasInstance.func = function(){}; - canvasInstance.relFontSize = 1; - canvasInstance.keySize = keySize; - canvasInstance.element = false; - canvasInstance.static = false; - - for (var c = 0; c < keyboardChars.length; c++) { - if (canvasInstance.value == keyboardChars[c].name) { - canvasInstance.value = String.fromCharCode(keyboardChars[c].display); - break; - } - } - for (var e = 0; e < keyboardElements.length; e++) { - if (canvasInstance.value == keyboardElements[e].name) { - canvasInstance.relFontSize = 0.7; - if (['frac','mixedNum'].indexOf(canvasInstance.value) > -1) { - canvasInstance.relFontSize = 0.6; - } - if (['sqrt','root'].indexOf(canvasInstance.value) > -1) { - canvasInstance.relFontSize = 0.6; - } - canvasInstance.value = keyboardElements[e].display; - canvasInstance.func = keyboardElements[e].func; - canvasInstance.element = true; - break; - } - } - - if (canvasInstance.element == true || ['leftArrow','rightArrow','del','delete'].indexOf(canvasInstance.name) > -1) { - canvasInstance.color = '#FF0'; // color for operators - canvasInstance.colorPressed = '#990'; - canvasInstance.keyType = 'operator'; - } else if (['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'].indexOf(canvasInstance.name) > -1) { - canvasInstance.color = '#AFF'; // color for letters - canvasInstance.colorPressed = '#6CC'; - canvasInstance.keyType = 'letter'; - } else if(['0','1','2','3','4','5','6','7','8','9',0,1,2,3,4,5,6,7,8,9].indexOf(canvasInstance.name) > -1) { - canvasInstance.color = '#AFA'; // color for numbers - canvasInstance.colorPressed = '#9C9'; - canvasInstance.keyType = 'number'; - } else { - canvasInstance.color = '#FB8'; // color for misc - canvasInstance.colorPressed = '#C95'; - canvasInstance.keyType = 'misc'; - } - - canvasInstance.ctx = contextInstance; - canvasInstance.ctx.canvas = canvasInstance; - canvasInstance.keySize = keySize; - canvasInstance.algText = algText; - canvasInstance.fontSize = fontSize; - - drawKey(canvasInstance.ctx,canvasInstance.name,canvasInstance.algText,false,canvasInstance.keySize,canvasInstance.fontSize); - addListenerStart(canvasInstance,keyStart); - - var relKeyLeft = keyLeft - left; - var relKeyTop = keyTop - top; - - key1[pageIndex][keyCount] = canvasInstance; - key1Data[pageIndex][keyCount] = [keyLeft, keyTop, keySize, keySize, relKeyLeft, relKeyTop, keyArray[rowNum][colNum]]; - key1Data[pageIndex][keyCount][100] = keyLeft; - key1Data[pageIndex][keyCount][101] = keyTop; - - keyLeft += keySize + keyPadding; - keyCount++; - } - } - - if (typeof object.staticKeys !== 'undefined') { - var keys2 = object.staticKeys; - var keyLeft = object.staticKeyPos[0]; - var keyTop = object.staticKeyPos[1]; - var staticKeySize = object.staticKeySize || keySize; - var staticKeyPadding = object.staticKeyPadding || keyPadding; - for (var k = 0; k < keys2.length; k++) { - var canvasInstance = document.createElement('canvas'); - canvasInstance.width = staticKeySize; - canvasInstance.height = staticKeySize; - canvasInstance.setAttribute('position', 'absolute'); - canvasInstance.setAttribute('cursor', 'auto'); - canvasInstance.setAttribute('draggable', 'false'); - canvasInstance.setAttribute('class', 'buttonClass'); - canvasInstance.style.zIndex = 800000; - canvasInstance.style.opacity = 0.7; - canvasInstance.style.pointerEvents = 'none'; - - var contextInstance = canvasInstance.getContext('2d'); - - canvasInstance.name = keys2[k]; - canvasInstance.value = keys2[k]; - canvasInstance.func = function(){}; - canvasInstance.keySize = staticKeySize; - canvasInstance.relFontSize = 1; - canvasInstance.element = false; - canvasInstance.static = true; - container.appendChild(canvasInstance); - - for (var c = 0; c < keyboardChars.length; c++) { - if (canvasInstance.value == keyboardChars[c].name) { - canvasInstance.value = String.fromCharCode(keyboardChars[c].display); - break; - } - } - for (var e = 0; e < keyboardElements.length; e++) { - if (canvasInstance.value == keyboardElements[e].name) { - canvasInstance.relFontSize = 0.9; - if (['frac','mixedNum'].indexOf(canvasInstance.value) > -1) { - canvasInstance.relFontSize = 0.8; - } - canvasInstance.value = keyboardElements[e].display; - canvasInstance.func = keyboardElements[e].func; - canvasInstance.element = true; - break; - } - } - - canvasInstance.ctx = contextInstance; - canvasInstance.ctx.canvas = canvasInstance; - canvasInstance.staticKeySize = staticKeySize; - canvasInstance.algText = algText; - canvasInstance.fontSize = fontSize; - - if (canvasInstance.element == true || ['leftArrow','rightArrow','del','delete'].indexOf(canvasInstance.name) > -1) { - canvasInstance.color = '#FF0'; // color for operators - canvasInstance.colorPressed = '#990'; - canvasInstance.keyType = 'operator'; - } else if (['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'].indexOf(canvasInstance.name) > -1) { - canvasInstance.color = '#AFF'; // color for letters - canvasInstance.colorPressed = '#6CC'; - canvasInstance.keyType = 'letter'; - } else if(['0','1','2','3','4','5','6','7','8','9',0,1,2,3,4,5,6,7,8,9].indexOf(canvasInstance.name) > -1) { - canvasInstance.color = '#CFC'; // color for numbers - canvasInstance.colorPressed = '#9C9'; - canvasInstance.keyType = 'number'; - } else { - canvasInstance.color = '#CCC'; // color for misc - canvasInstance.colorPressed = '#AAA'; - canvasInstance.keyType = 'misc'; - } - - drawKey(canvasInstance.ctx,canvasInstance.name,canvasInstance.algText,false,canvasInstance.staticKeySize,canvasInstance.fontSize); - addListenerStart(canvasInstance,keyStart); - - var relKeyLeft = keyLeft - left; - var relKeyTop = keyTop - top; - - key1[pageIndex][keyCount] = canvasInstance; - key1Data[pageIndex][keyCount] = [keyLeft, keyTop, staticKeySize, staticKeySize, relKeyLeft, relKeyTop, keys2[k]]; - key1Data[pageIndex][keyCount][100] = keyLeft; - key1Data[pageIndex][keyCount][101] = keyTop; - - keyLeft += staticKeySize + staticKeyPadding; - keyCount++; - } - } - - // create close button - var canvasInstance = document.createElement('canvas'); - canvasInstance.width = 40; - canvasInstance.height = 40; - canvasInstance.setAttribute('position', 'absolute'); - canvasInstance.setAttribute('cursor', 'auto'); - canvasInstance.setAttribute('draggable', 'false'); - canvasInstance.setAttribute('class', 'buttonClass'); - canvasInstance.style.zIndex = 800000; - addListener(canvasInstance, hideKeyboard) - - var contextInstance = canvasInstance.getContext('2d'); - roundedRect(contextInstance, 3, 3, 34, 34, 8, 6, '#000', '#000'); - contextInstance.strokeStyle = '#FFF'; - contextInstance.fillStyle = '#FFF'; - contextInstance.lineWidth = 5; - contextInstance.beginPath(); - - contextInstance.moveTo(10, 30); - contextInstance.lineTo(30, 30); - - contextInstance.closePath(); - contextInstance.stroke(); - key1[pageIndex][keyCount] = canvasInstance; - key1Data[pageIndex][keyCount] = [left + width - 40, top+1, 40, 40, width - 40, 0, 'closeKeyboard']; - key1Data[pageIndex][keyCount][100] = left + width - 40; - key1Data[pageIndex][keyCount][101] = top+1; - - // create showKeyboard button - var s = keyButtonSize; - var canvasInstance = document.createElement('canvas'); - canvasInstance.width = s; - canvasInstance.height = s; - canvasInstance.setAttribute('position', 'absolute'); - canvasInstance.setAttribute('cursor', 'auto'); - canvasInstance.setAttribute('draggable', 'false'); - canvasInstance.setAttribute('class', 'buttonClass'); - canvasInstance.style.zIndex = 8000000000000; - addListener(canvasInstance, showKeyboard) - var contextInstance = canvasInstance.getContext('2d'); - roundedRect(contextInstance, s*1.5/50, s*1.5/50, s*47/50, s*47/50, s*5/50, s*3/50, '#000', backColor); - roundedRect(contextInstance, s*9/50, s*9/50, s*8/50, s*8/50, s*3/50, s*2/50, '#000', '#AFF'); - roundedRect(contextInstance, s*21/50, s*9/50, s*8/50, s*8/50, s*3/50, s*2/50, '#000', '#AFF'); - roundedRect(contextInstance, s*33/50, s*9/50, s*8/50, s*8/50, s*3/50, s*2/50, '#000', '#AFF'); - roundedRect(contextInstance, s*9/50, s*21/50, s*8/50, s*8/50, s*3/50, s*2/50, '#000', '#AFF'); - roundedRect(contextInstance, s*21/50, s*21/50, s*8/50, s*8/50, s*3/50, s*2/50, '#000', '#AFF'); - roundedRect(contextInstance, s*33/50, s*21/50, s*8/50, s*8/50, s*3/50, s*2/50, '#000', '#AFF'); - roundedRect(contextInstance, s*9/50, s*33/50, s*8/50, s*8/50, s*3/50, s*2/50, '#000', '#AFF'); - roundedRect(contextInstance, s*21/50, s*33/50, s*8/50, s*8/50, s*3/50, s*2/50, '#000', '#AFF'); - roundedRect(contextInstance, s*33/50, s*33/50, s*8/50, s*8/50, s*3/50, s*2/50, '#000', '#AFF'); - canvases[pageIndex].push(canvasInstance); - showKeys[pageIndex] = canvasInstance; - var dataInstance = [keyButtonLeft, keyButtonTop, s, s, true, false, true]; - dataInstance[100] = keyButtonLeft; - dataInstance[101] = keyButtonTop; - dataInstance[102] = s; - dataInstance[103] = s; - canvasInstance.data = dataInstance; - canvasInstance.ctx = contextInstance; - - keyboardButton1[pageIndex] = canvasInstance; - - // create hideKeyboard button - var canvasInstance = document.createElement('canvas'); - canvasInstance.width = s; - canvasInstance.height = s; - canvasInstance.setAttribute('position', 'absolute'); - canvasInstance.setAttribute('cursor', 'auto'); - canvasInstance.setAttribute('draggable', 'false'); - canvasInstance.setAttribute('class', 'buttonClass'); - canvasInstance.style.zIndex = 8000000000000; - addListener(canvasInstance, hideKeyboard) - var contextInstance = canvasInstance.getContext('2d'); - roundedRect(contextInstance, s*1.5/50, s*1.5/50, s*47/50, s*47/50, s*5/50, s*3/50, '#000', backColor); - canvases[pageIndex].push(canvasInstance); - hideKeys[pageIndex] = canvasInstance; - var dataInstance = [keyButtonLeft, keyButtonTop, s, s, false, false, true]; - dataInstance[100] = keyButtonLeft; - dataInstance[101] = keyButtonTop; - dataInstance[102] = s; - dataInstance[103] = s; - canvasInstance.data = dataInstance; - canvasInstance.ctx = contextInstance; - - keyboardButton2[pageIndex] = canvasInstance; -} - -function keyStart(e) { - e.preventDefault(); - var name = e.target.name; - var ctx = e.target.ctx; - var algText = e.target.algText; - var keySize = e.target.keySize; - var fontSize = e.target.fontSize; - var element = e.target.element; - - addListenerEnd(e.target,keyStop); - drawKey(ctx,name,algText,true,keySize,fontSize); - - if (!un(draw) && !un(draw.keyboard) && draw.keyboard.active == true) { - textEdit.softKeyInput(e.target.name); - } else { - if (name == 'leftArrow') { - mathsInputLeftArrow(e); - } else if (name == 'rightArrow') { - mathsInputRightArrow(e) - } else { - if (boolean(element,false) == true) { - e.target.func.apply(); - } else { - softKeyMathsInput(e); - } - } - } -} - -function keyStop(e) { - var name = e.target.name; - var ctx = e.target.ctx; - var algText = e.target.algText; - var keySize = e.target.keySize; - var fontSize = e.target.fontSize; - drawKey(ctx,name,algText,false,keySize,fontSize); - removeListenerEnd(e.target,keyStop); -} - -var keyboardCurrFont = 'Arial'; -function updateKeyboardCurrFont() { - var prev = keyboardCurrFont; - - if (typeof currMathsInput == 'undefined') return; - if (currMathsInput.selected == true && currMathsInput.selectPos.length > 0) { - var cursorMapPos = currMathsInput.cursorMap[Math.max(currMathsInput.selectPos[0],currMathsInput.selectPos[1])]; - } else { - var cursorMapPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - } - - for (var pos = 0; pos < currMathsInput.allMap.length; pos++) { - if (arraysEqual(cursorMapPos,currMathsInput.allMap[pos]) == true) break; - var posText = currMathsInput.richText; - for (var pos2 = 0; pos2 < currMathsInput.allMap[pos].length - 1; pos2++) { - posText = posText[currMathsInput.allMap[pos][pos2]]; - } - posText = posText.slice(currMathsInput.allMap[pos][currMathsInput.allMap[pos].length - 1]); - var tagType = 'none'; - if (posText.indexOf('<>') == 0) { - keyboardCurrFont = posText.slice(7,pos3); - break; - } - } - } - } - if (keyboardCurrFont !== prev && typeof key1 !== 'undefined' && typeof key1[pageIndex] !== 'undefined') { - for (var k = 0; k < key1[pageIndex].length - 1; k++) { - if (key1[pageIndex][k].keyType == 'letter') { - drawKey(key1[pageIndex][k].ctx,key1[pageIndex][k].name,key1[pageIndex][k].algText,false,key1[pageIndex][k].keySize,key1[pageIndex][k].fontSize); - } - } - } -} - -function drawKey(ctx,name,algText,pressed,keySize,fontSize,font) { - var isAlgText = boolean(algText,false); - var isPressed = boolean(pressed,false); - if (!keySize) keySize = 60; - if (!fontSize) fontSize = 40; - if (!font) { - font = keyboardCurrFont; - } - if (isAlgText == true) font = 'algebra'; - fontSize = fontSize * ctx.canvas.relFontSize; - - ctx.clearRect(0,0,keySize,keySize); - if (isPressed == false) { - var color = ctx.canvas.color; - } else { - var color = ctx.canvas.colorPressed; - } - /*var color = '#AFF'; - if (boolean(ctx.canvas.element,false) == true || ['leftArrow','rightArrow','del','delete'].indexOf(name) > -1) { - font = 'algebra'; - if (isPressed == true) { - color = '#990'; - } else { - color = '#FF0'; - } - } else { - if (isPressed == true) { - color = '#6CC'; - } - }*/ - - switch (name) { - case 'leftArrow' : - case 'left' : - text({ctx:ctx,textArray:[],left:1.5,top:1.5,height:keySize-3,width:keySize-3,align:'center',vertAlign:'middle',box:{type:'loose',radius:6,color:color,borderWidth:3}}); - ctx.lineWidth = 2; - ctx.beginPath(); - ctx.moveTo(45*keySize/60, 30*keySize/60); - ctx.lineTo(15*keySize/60, 30*keySize/60); - ctx.lineTo(25*keySize/60, 20*keySize/60); - ctx.moveTo(15*keySize/60, 30*keySize/60); - ctx.lineTo(25*keySize/60, 40*keySize/60); - ctx.stroke(); - break; - case 'rightArrow' : - case 'right' : - text({ctx:ctx,textArray:[],left:1.5,top:1.5,height:keySize-3,width:keySize-3,align:'center',vertAlign:'middle',box:{type:'loose',radius:6,color:color,borderWidth:3}}); - ctx.lineWidth = 2; - ctx.beginPath(); - ctx.moveTo(15*keySize/60, 30*keySize/60); - ctx.lineTo(45*keySize/60, 30*keySize/60); - ctx.lineTo(35*keySize/60, 20*keySize/60); - ctx.moveTo(45*keySize/60, 30*keySize/60); - ctx.lineTo(35*keySize/60, 40*keySize/60); - ctx.stroke(); - break; - case 'delete' : - case 'del' : - text({ctx:ctx,textArray:[],left:1.5,top:1.5,height:keySize-3,width:keySize-3,align:'center',vertAlign:'middle',box:{type:'loose',radius:6,color:color,borderWidth:3}}); - ctx.textAlign = "center"; - ctx.textBaseline = "middle"; - ctx.fillStyle = "#000"; - ctx.font = (fontSize/2)+"px Arial"; - ctx.fillText("DEL", keySize * 0.5, keySize * 0.65); - break; - default : - var txt = []; - if (typeof ctx.canvas.value == 'number') { - txt = [String(ctx.canvas.value)]; - } else if (typeof ctx.canvas.value == 'string') { - txt = [ctx.canvas.value]; - } if (typeof ctx.canvas.value == 'object') { - txt = ctx.canvas.value; - } - text({ctx:ctx,text:txt,font:font,fontSize:fontSize,rect:[1.5,1.5,keySize-3,keySize-3],align:[0,0],box:{type:'loose',radius:6,color:color,borderWidth:3}}); - - break; - } -} - -var keyboardHardClosed = false; // has the user clicked the minimise button? -var keyboardHardOpen = false; // has the user clicked the minimise button? - -function showKeyboard(event) { - event.preventDefault(); - keyboardHardClosed = false; - keyboardHardOpen = true; - showKeyboard2(); -} - -function showKeyboard2(lightUp) { - if (un(keyboard[pageIndex])) return; - if (boolean(lightUp,false) == true) { - for (var i = 0; i < key1[pageIndex].length; i++) { - key1[pageIndex][i].style.opacity = 1; - key1[pageIndex][i].style.pointerEvents = 'auto'; - } - } - if (keyboardHardClosed) return; - if (keyboard[pageIndex].parentNode !== container) { - container.appendChild(keyboard[pageIndex]); - for (i = 0; i < key1[pageIndex].length; i++) { - if (boolean(key1[pageIndex][i].static,false) == false) { - container.appendChild(key1[pageIndex][i]); - } - } - if (showKeys[pageIndex].parentNode == container) {container.removeChild(showKeys[pageIndex])}; - container.appendChild(hideKeys[pageIndex]) - keyboardVis[pageIndex] = true; - } -} - - -function hideKeyboard(event) { - event.preventDefault(); - keyboardHardClosed = true; - keyboardHardOpen = false; - hideKeyboard2(); -} - -function hideKeyboard2(lightDown) { - if (un(keyboard[pageIndex])) return; - if (boolean(lightDown,false) == true) { - for (var i = 0; i < key1[pageIndex].length - 1; i++) { - key1[pageIndex][i].style.opacity = 0.7; - key1[pageIndex][i].style.pointerEvents = 'none'; - } - } - if (keyboard[pageIndex].parentNode == container && keyboardHardOpen == false) { - container.removeChild(keyboard[pageIndex]); - for (var i = 0; i < key1[pageIndex].length; i++) { - if (boolean(key1[pageIndex][i].static,false) == false) { - container.removeChild(key1[pageIndex][i]); - } - } - if (hideKeys[pageIndex].parentNode == container) {container.removeChild(hideKeys[pageIndex])}; - container.appendChild(showKeys[pageIndex]); - keyboardVis[pageIndex] = false; - } -} - -var drag; -function dragKeyboardStart(e) { - updateMouse(e); - e.target.style.cursor = closedhand; - e.target.dragOffset = [mouse.x-e.target.data[100],mouse.y-e.target.data[101]]; - drag = e.target; - addListenerMove(window, dragKeyboardMove ) - addListenerEnd(window, dragKeyboardStop ) -} -function dragKeyboardMove(e) { - e.target.style.cursor = closedhand; - updateMouse(e); - var l = mouse.x - drag.dragOffset[0]; - l = Math.max(l,drag.dragArea[0]); - l = Math.min(l,mainCanvasWidth-drag.dragArea[2]-drag.data[102]); - var t = mouse.y - drag.dragOffset[1]; - t = Math.max(t,drag.dragArea[1]); - t = Math.min(t,mainCanvasHeight-drag.dragArea[3]-drag.data[103]); - drag.data[100] = l; - drag.data[101] = t; - resizeCanvas2(drag,l,t); - - for (i = 0; i < key1[pageIndex].length; i++) { - if (boolean(key1[pageIndex][i].static,false) == false) { - key1Data[pageIndex][i][100] = l + key1Data[pageIndex][i][4]; - key1Data[pageIndex][i][101] = t + key1Data[pageIndex][i][5]; - resizeCanvas2(key1[pageIndex][i],key1Data[pageIndex][i][100],key1Data[pageIndex][i][101]); - } - } -} -function dragKeyboardStop(e) { - removeListenerMove(window, dragKeyboardMove) - removeListenerEnd(window, dragKeyboardStop) - e.target.style.cursor = openhand; - //drag.style.cursor = 'url("../images/cursors/openhand.cur"), auto'; -} \ No newline at end of file diff --git a/tools/i2/_mathsInput.js b/tools/i2/_mathsInput.js deleted file mode 100644 index 0fa3ff2..0000000 --- a/tools/i2/_mathsInput.js +++ /dev/null @@ -1,3723 +0,0 @@ -/*if (typeof console == "undefined") { - this.console = { log: function (msg) { alert(msg); } }; -}*/ - -/* -text selection - double click should select word -cursor up/down - remember horizPos of original line and find closest in other lines - -*/ - -/* example of basic use: -var j000inputs = inputs({ - inputs:[ - {left:900,top:300,width:100,height:50,algText:true}, - {left:900,top:500,width:100,height:50,algText:true} - ], - leftText:[ - ['Perimeter = '], - ['Area = '] - ], - rightText:[ - ['cm'], - ['cm',['pow',false,['2']]] - ], - checkFuncs:[ - function(mathsInput) { - if (mathsInput.stringJS == 'correctAns') { - return true; - } else { - return false - } - }, - function(mathsInput) { - if (mathsInput.stringJS == 'correctAns') { - return true; - } else { - return false - } - } - ], -}); -*/ -function inputs(object) { - var inputs = object.inputs; - var checkFuncs = object.checkFuncs; - var buttonPos = object.buttonPos || [990,620]; - var taskComplete = boolean(object.taskCompleted,true); - var buttonVis = boolean(object.buttonVisible,true); - - var inputArray = []; - - for (var i = 0; i < inputs.length; i++) { - var zIndex = inputs[i].zIndex || 2; - // mathsInput - var input = createMathsInput2(inputs[i]); - var vis = boolean(inputs[i].visible,true); - - // leftText && rightText - var button3 = document.createElement('canvas'); - button3.width = 1200; - button3.height = 700; - button3.setAttribute('position', 'absolute'); - button3.setAttribute('cursor', 'auto'); - button3.setAttribute('draggable', 'false'); - button3.setAttribute('class', 'buttonClass'); - var data3 = [0,0,1200,700,vis,false,false,zIndex]; - if (vis == true) container.appendChild(button3); - data3[130] = true; - for (var j = 0; j < 8; j++) {data3[100+j] = data3[j];} - button3.style.zIndex = zIndex; - button3.style.pointerEvents = 'none'; - canvases[pageIndex].push(button3); - button3.data = data3; - button3.ctx = button3.getContext('2d'); - - if (typeof object.leftText == 'object') { - if (typeof object.leftText[i] == 'object') { - var maxLines = inputs[i].maxLines || 1; - var fontSize = inputs[i].fontSize || 0.5 * (inputs[i].height / maxLines); - var textColor = inputs[i].textColor || '#000'; - drawMathsText(button3.ctx,object.leftText[i],fontSize,inputs[i].left-4,inputs[i].top+0.5*inputs[i].height,false,[],'right','middle',textColor); - input.leftText = object.leftText[i]; - } - } - if (typeof object.rightText == 'object') { - if (typeof object.rightText[i] == 'object') { - var maxLines = inputs[i].maxLines || 1; - var fontSize = inputs[i].fontSize || 0.5 * (inputs[i].height / maxLines); - var textColor = inputs[i].textColor || '#000'; - drawMathsText(button3.ctx,object.rightText[i],fontSize,inputs[i].left+inputs[i].width+15,inputs[i].top+0.5*inputs[i].height,false,[],'left','middle',textColor); - var textMeasure = drawMathsText(button3.ctx,object.rightText[i],fontSize,inputs[i].left+inputs[i].width+15,inputs[i].top+0.5*inputs[i].height,false,[],'left','middle',textColor,'measure'); - if (typeof inputs[i].offset === 'undefined') inputs[i].offset = [textMeasure[0]+5,0]; - input.rightText = object.rightText[i]; - } - } - if (typeof inputs[i].offset === 'undefined') inputs[i].offset = [0,0]; - - input.leftRightTextCanvas = button3; - input.canvas.leftRightTextCanvas = button3; - - // what if... maths input is entered through tab key, rather than clicking on?? - addListener(input.canvas, function() { - hideObj(this.tick,this.tick.data); - hideObj(this.cross,this.cross.data); - }); - - // tick canvas - var button = document.createElement('canvas'); - button.width = 40; - button.height = 50; - button.setAttribute('position', 'absolute'); - button.setAttribute('cursor', 'auto'); - button.setAttribute('draggable', 'false'); - button.setAttribute('class', 'buttonClass'); - var data = [inputs[i].left+inputs[i].width+13+inputs[i].offset[0],inputs[i].top+0.5*inputs[i].height-25+inputs[i].offset[1],40,50,false,false,false,zIndex]; - data[130] = true; - for (var j = 0; j < 8; j++) {data[100+j] = data[j];} - button.style.zIndex = zIndex; - button.style.pointerEvents = 'none'; - canvases[pageIndex].push(button3); - button.data = data; - button.ctx = button.getContext('2d'); - drawTick(button.ctx,40,50); - - // cross canvas - var button2 = document.createElement('canvas'); - button2.width = 32; - button2.height = 40; - button2.setAttribute('position', 'absolute'); - button2.setAttribute('cursor', 'auto'); - button2.setAttribute('draggable', 'false'); - button2.setAttribute('class', 'buttonClass'); - var data2 = [inputs[i].left+inputs[i].width+20+inputs[i].offset[0],inputs[i].top+0.5*inputs[i].height-20+inputs[i].offset[1],32,40,false,false,false,zIndex]; - data2[130] = true; - for (var j = 0; j < 8; j++) {data2[100+j] = data2[j];} - button2.style.zIndex = zIndex; - button.style.pointerEvents = 'none'; - canvases[pageIndex].push(button3); - button2.data = data2; - button2.ctx = button2.getContext('2d'); - drawCross(button2.ctx,32,40); - - input.tick = button; - input.cross = button2; - input.canvas.tick = button; - input.canvas.cross = button2; - - inputArray.push(input); - } - if (boolean(object.checkAnsButton,true)) { - // check answer button - var button = document.createElement('canvas'); - button.width = 180; - button.height = 50; - button.setAttribute('position', 'absolute'); - button.setAttribute('cursor', 'auto'); - button.setAttribute('draggable', 'false'); - button.setAttribute('class', 'buttonClass'); - var data = [buttonPos[0],buttonPos[1],180,50,buttonVis,false,true,2]; - if (buttonVis == true) container.appendChild(button); - data[130] = true; - for (var i = 0; i < 8; i++) {data[100+i] = data[i];} - button.style.zIndex = 2; - canvases[pageIndex].push(button3); - button.data = data; - button.ctx = button.getContext('2d'); - if (inputs.length > 1) { - drawTextBox(button,button.ctx,button.data,'#6F9','#000',4,'28px Hobo','#000','center','Check Answers'); - } else { - drawTextBox(button,button.ctx,button.data,'#6F9','#000',4,'28px Hobo','#000','center','Check Answer'); - } - - addListener(button,function() { - var inputs = this.inputs; - var checkFuncs = this.checkFuncs; - var complete = true; - for (var i = 0; i < inputs.length; i++) { - if (checkFuncs[i](inputs[i]) == true) { - hideObj(inputs[i].cross,inputs[i].cross.data); - showObj(inputs[i].tick,inputs[i].tick.data); - } else { - hideObj(inputs[i].tick,inputs[i].tick.data); - showObj(inputs[i].cross,inputs[i].cross.data,3000); - complete = false; - } - } - if (complete == true) { - taskCompleted(); - } - }); - - button.inputs = inputArray; - button.checkFuncs = checkFuncs; - button.taskComplete = true; - button.textCanvas = button3; - return button; - } -} - -function hideAllInputs() { - for (var i = 0; i < mathsInput[pageIndex].length; i++) { - hideMathsInput(mathsInput[pageIndex][i]); - } -} -function showAllInputs() { - for (var i = 0; i < mathsInput[pageIndex].length; i++) { - showMathsInput(mathsInput[pageIndex][i]); - } -} -function hideMathsInput(mathsInput) { - hideObj(mathsInput.canvas); - if (typeof mathsInput.cursorCanvas !== 'undefined') { - hideObj(mathsInput.cursorCanvas); - } - if (typeof mathsInput.tick !== 'undefined') { - hideObj(mathsInput.tick); - } - if (typeof mathsInput.cross !== 'undefined') { - hideObj(mathsInput.cross); - } - if (typeof mathsInput.leftRightTextCanvas !== 'undefined') { - hideObj(mathsInput.leftRightTextCanvas); - } -} -function showMathsInput(mathsInput) { - showObj(mathsInput.canvas); - if (typeof mathsInput.cursorCanvas !== 'undefined') { - showObj(mathsInput.cursorCanvas); - } - if (typeof mathsInput.leftRightTextCanvas !== 'undefined') { - showObj(mathsInput.leftRightTextCanvas); - } -} -function moveMathsInput(input,left,top) { - if (typeof input.data == 'undefined') return; - var dx = left - input.data[100]; - var dy = top - input.data[101]; - - input.data[100] += dx; - input.data[101] += dy; - resizeCanvas2(input.canvas,input.data[100],input.data[101]); - - if (typeof input.cross !== 'undefined') { - input.cross.data[100] += dx; - input.cross.data[101] += dy; - resizeCanvas2(input.cross,input.cross.data[100],input.cross.data[101]); - } - - if (typeof input.tick !== 'undefined') { - input.tick.data[100] += dx; - input.tick.data[101] += dy; - resizeCanvas2(input.tick,input.tick.data[100],input.tick.data[101]); - } - - input.cursorData[100] += dx; - input.cursorData[101] += dy; - resizeCanvas2(input.cursorCanvas,input.cursorData[100],input.cursorData[101]); - - if (typeof input.leftRightTextCanvas !== 'undefined') { - input.leftRightTextCanvas.data[100] += dx; - input.leftRightTextCanvas.data[101] += dy; - resizeCanvas2(input.leftRightTextCanvas,input.leftRightTextCanvas.data[100],input.leftRightTextCanvas.data[101]); - } -} -function enlargeMathsInput(input,sf) { // be careful! - if (typeof sf !== 'number') return; - //var l = input.data[100]; - //var t = input.data[101]; - - //input.data[102] = input.data[102] * sf; - //input.data[103] = input.data[103] * sf; - - resizeCanvas(input.canvas,input.data[100],input.data[101],input.data[102]*sf,input.data[103]*sf); - - /*input.cursorData[100] += (l -input.cursorData[100])*sf; - input.cursorData[101] += (t -input.cursorData[101])*sf; - input.cursorData[102] = input.cursorData[102] * sf; - input.cursorData[103] = input.cursorData[103] * sf; - resizeCanvas(input.cursorCanvas,input.cursorData[100],input.cursorData[101],input.cursorData[102],input.cursorData[103]); - - if (typeof input.cross !== 'undefined') { - input.cross.data[100] += (l -input.cross.data[100])*sf; - input.cross.data[101] += (t -input.cross.data[101])*sf; - input.cross.data[102] = input.cross.data[102] * sf; - input.cross.data[103] = input.cross.data[103] * sf; - resizeCanvas(input.cross,input.cross.data[100],input.cross.data[101],input.cross.data[102],input.cross.data[103]); - } - - if (typeof input.tick !== 'undefined') { - input.tick.data[100] += (l -input.tick.data[100])*sf; - input.tick.data[101] += (t -input.tick.data[101])*sf; - input.tick.data[102] = input.tick.data[102] * sf; - input.tick.data[103] = input.tick.data[103] * sf; - resizeCanvas(input.tick,input.tick.data[100],input.tick.data[101],input.tick.data[102],input.tick.data[103]); - } - - if (typeof input.leftRightTextCanvas !== 'undefined') { - input.leftRightTextCanvas.data[100] += (l -input.leftRightTextCanvas.data[100])*sf; - input.leftRightTextCanvas.data[101] += (t -input.leftRightTextCanvas.data[101])*sf; - input.leftRightTextCanvas.data[102] = input.leftRightTextCanvas.data[102] * sf; - input.leftRightTextCanvas.data[103] = input.leftRightTextCanvas.data[103] * sf; - resizeCanvas(input.leftRightTextCanvas,input.leftRightTextCanvas.data[100],input.leftRightTextCanvas.data[101],input.leftRightTextCanvas.data[102],input.leftRightTextCanvas.data[103]); - }*/ -} -function setMathsInputZIndex(input,zIndex) { - if (typeof input.leftRightTextCanvas == 'object') input.leftRightTextCanvas.style.zIndex = zIndex; - if (typeof input.tick == 'object') input.tick.style.zIndex = zIndex; - if (typeof input.cross == 'object') input.cross.style.zIndex = zIndex; - if (typeof input.canvas == 'object') input.canvas.style.zIndex = zIndex; - if (typeof input.cursorCanvas == 'object') input.cursorCanvas.style.zIndex = zIndex; -} -function setMathsInputFont(input,font) { - removeTagsOfType(input.richText,'font'); - input.richText.unshift('<>'); - input.richText = combineSpacesTextArray(input.richText); - removeTagsOfType(input.startRichText,'font'); - input.startRichText.unshift('<>'); - input.startRichText = combineSpacesTextArray(input.startRichText); - input.startTags = removeTagsOfType(input.startTags,'font'); - input.startTags = '<>'+input.startTags; - currMathsInput = input; - mathsInputMapCursorPos(); - mathsInputCursorCoords(); - deselectMathsInput(); -} -function setMathsInputColor(input,color) { - removeTagsOfType(input.richText,'color'); - input.richText.unshift('<>'); - input.richText = combineSpacesTextArray(input.richText); - removeTagsOfType(input.startRichText,'color'); - input.startRichText.unshift('<>'); - input.startRichText = combineSpacesTextArray(input.startRichText); - input.startTags = removeTagsOfType(input.startTags,'color'); - input.startTags = '<>'+input.startTags; - var saveCurrMathsInput = currMathsInput; - currMathsInput = input; - drawMathsInputText(input); - deselectMathsInput(); -} -function setMathsInputText(mathsInputObj, opt_newText, opt_newCursorPos) { // eg. setMathsInputText(j37mathsInput[3]); - var newText; - if (un(opt_newText)) { - newText = [""]; - } else if (typeof opt_newText == 'string') { - newText = [opt_newText]; - } else if (typeof opt_newText == 'number') { - newText = String(opt_newText); - newText = [newText]; - } else { - newText = clone(opt_newText); - } - mathsInputObj.text = newText; - if (!un(mathsInputObj.startTags)) newText.unshift(mathsInputObj.startTags); - mathsInputObj.richText = newText; - currMathsInput = mathsInputObj; - mathsInputMapCursorPos(); - if (typeof opt_newCursorPos !== 'undefined') { - mathsInputObj.cursorPos = opt_newCursorPos; - } else { - mathsInputObj.cursorPos = mathsInputObj.cursorMap.length - 1; - } - mathsInputCursorCoords(); - deselectMathsInput(); -} -function setMathsInputTextToInitialTags(m) { - var newText = ""; - if (!un(m.richText) && typeof m.richText[0] == 'string' && m.richText[0].indexOf('<<') == 0) { - for (c = 2; c < m.richText[0].length; c++) { - if (m.richText[0].slice(c).indexOf('>>') == 0 && m.richText[0].slice(c).indexOf('>><<') !== 0) { - newText = m.richText[0].slice(0,c+2); - break; - } - } - } - setMathsInputText(m,[newText],0); -} - -function drawTick(ctx,width,height,color,left,top,lineWidth) { - if (!left) left = 0; - if (!top) top = 0; - if (!width) width = 75; - if (!height) height = 75; - if (!color) color = '#F0F'; - if(!lineWidth) lineWidth = 8; - ctx.save(); - ctx.lineWidth = lineWidth; - ctx.strokeStyle = color; - ctx.lineJoin = 'round'; - ctx.lineCap = 'round'; - ctx.beginPath(); - ctx.moveTo(left+4,top+0.5*height); - ctx.lineTo(left+width/3,top+height-4); - ctx.lineTo(left+width-4,top+4); - ctx.stroke(); - ctx.restore(); -} -function drawCross(ctx,width,height,color,left,top,lineWidth) { - if (!left) left = 0; - if (!top) top = 0; - if (!width) width = 75; - if (!height) height = 75; - if (!color) color = '#F00'; - if(!lineWidth) lineWidth = 8; - ctx.save(); - ctx.lineWidth = lineWidth; - ctx.strokeStyle = color; - ctx.lineJoin = 'round'; - ctx.lineCap = 'round'; - ctx.beginPath(); - ctx.moveTo(left+4,top+4); - ctx.lineTo(left+width-4,top+height-4); - ctx.moveTo(left+width-4,top+4); - ctx.lineTo(left+4,top+height-4); - ctx.stroke(); - ctx.restore(); -} - -function createMathsInput2(object) { - // non-optional: - var left = object.left; - var top = object.top; - var width = object.width; - var height = object.height; - - // optional & defaults: - var varSize = object.varSize; // varSize:{minWidth:50,maxWidth:400,minHeight:50,maxHeight:300,padding:5} - var visible; - if (typeof object.visible == 'boolean') {visible = object.visible} else {visible = true}; - var zIndex = object.zIndex || 2; - var algText; - if (typeof object.algText == 'boolean') {algText = object.algText} else {algText = false}; - var textArray = object.textArray || [""]; - var leftPoint = object.leftPoint || 10; - var textColor = object.textColor || '#000'; - var textAlign = object.textAlign || 'center'; - var vertAlign = object.vertAlign || 'middle'; - var transparent; - if (typeof object.transparent == 'boolean') {transparent = object.transparent} else {transparent = false}; - var maxChars = object.maxChars || 1000000000; - var backColor = object.backColor || '#FFF'; - var selectColor = object.selectColor || '#FCF'; - var border; - if (typeof object.border == 'boolean') {border = object.border} else {border = true}; - var borderWidth = object.borderWidth || 3; - var borderDash = object.borderDash || []; - var borderColor = object.borderColor || '#000'; - var maxLines = object.maxLines || 1; - var fontSize = object.fontSize || 0.5 * (height/maxLines); - var selectable = boolean(object.selectable,false); - var pointerCanvas = object.pointerCanvas || false; - - var inputObject = createMathsInput(0, left, top, width, height, visible, zIndex, algText, textArray, leftPoint, fontSize, textColor, textAlign, transparent, maxChars, backColor, selectColor, border, borderColor, maxLines, vertAlign, varSize, borderWidth, borderDash, selectable, pointerCanvas); - return inputObject; -} - -// creates mathsInput canvas -function createMathsInput(id, left, top, width, height, visible, zIndex, algText, textArray, leftPoint, fontSize, textColor, textAlign, transparent, maxChars, backColor, selectColor, border, borderColor, maxLines, vertAlign, varSize, borderWidth, borderDash,selectable, pointerCanvas) { - if (!maxLines) {maxLines = 1}; - if (!zIndex) {zIndex = 2}; - if (!algText) {algText = false}; - if (!fontSize) (fontSize = (height/maxLines) * 0.75); - if (!textColor) (textColor = '#000'); - if (!textAlign) {textAlign = 'center'}; - if (textAlign == 'center') {leftPoint = 0.5 * width}; - if (!vertAlign) {vertAlign = 'middle'}; - if (!textArray) {textArray = [""]}; - var font = 'Arial'; - if (algText == true) font = 'algebra'; - var startText = textArray.slice(0); - var startTags = "<><><><><><><>"; - textArray.unshift(startTags); - var startRichText = textArray.slice(0); - if (!leftPoint) {leftPoint = 10}; - if (typeof transparent !== 'boolean') {transparent = false}; - if (!maxChars) {maxChars = 100000000} - if (!backColor) backColor = "#fff"; - var currBackColor = backColor; - if (!selectColor) selectColor = '#FCF'; - if (typeof border !== 'boolean') border = true; - if (!borderWidth) borderWidth = 5; - if (!borderDash) borderDash = []; - if (!borderColor) borderColor = '#000'; - if (!startText) startText = ['']; - if (typeof selectable !== 'boolean') selectable = false; - if (!pointerCanvas) pointerCanvas = false; - - function makeInputCanvas(l,t,w,h,v,d,p,z) { - var canvas = document.createElement('canvas'); - canvas.setAttribute('class', 'inputClass'); - canvas.setAttribute('width', w); - canvas.setAttribute('height', h); - canvas.setAttribute('left', l); - canvas.setAttribute('top', t); - canvas.setAttribute('position', 'absolute'); - canvas.style.border = 'none'; - canvas.style.zIndex = z; - if (p == false) { - canvas.style.pointerEvents = 'none'; - } else { - canvas.style.pointerEvents = 'auto'; - } - canvas.data = [l,t,w,h,v,d,p,z]; - canvas.ctx = canvas.getContext('2d'); - for (var i = 0; i < 8; i++) {canvas.data[i+100] = canvas.data[i]}; - resizeCanvas3(canvas); - return canvas; - } - - var textCanvas = makeInputCanvas(left, top, width, height, visible, false, false, zIndex); - var cursorCanvas = makeInputCanvas(left, top, width, height, visible, false, true, zIndex); - cursorCanvas.addEventListener('mousedown', startMathsInput, false); - cursorCanvas.addEventListener('touchstart', startMathsInput, false); - - var input = { - id:id, - canvas:textCanvas, - ctx:textCanvas.ctx, - data:textCanvas.data, - cursorCanvas:cursorCanvas, - cursorctx:cursorCanvas.ctx, - cursorData:cursorCanvas.data, - active:true, - stringJS:"", - text:startText, - richText:startRichText, - textLoc:[], - cursorPos:0, - cursorMap:[], - algText:algText, - leftPoint:leftPoint, - fontSize:fontSize, - textColor:textColor, - textAlign:textAlign, - transparent:transparent, - maxChars:maxChars, - backColor:backColor, - selectColor:selectColor, - border:border, // boolean - borderWidth:borderWidth, - borderDash:borderDash, - borderColor:borderColor, - currBackColor:currBackColor, - startText:startText, - startRichText:startRichText, - startTags:startTags, - maxLines:maxLines, - preText:'', - postText:'', - vertAlign:vertAlign, - varSize:varSize, - selectable:selectable, - selectPos:[], - selected:false, - setBackColor:function(color) { - this.backColor = color; - drawMathsInputText(this); - }, - pointerCanvas:pointerCanvas - }; - //input.creationTime = (new Date()).getTime(); - mathsInput[pageIndex].push(input); - currMathsInput = input; - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - mathsInputCursorCoords(); - deselectMathsInput(); - if (isTask == false && visible == true) showMathsInput(input); - return input; -} - -function mathsInputFrac(e) {mathsInputElement("['frac', [''], ['']]");} -function mathsInputPow(e) {mathsInputElement("['power', false, ['']]");} -function mathsInputSubs(e) {mathsInputElement("['subs', [''], ['']]");} -function mathsInputRoot(e) {mathsInputElement("['root', [''], ['']]");} -function mathsInputSqrt(e) {mathsInputElement("['sqrt', ['']]");} -function mathsInputSin(e) {mathsInputElement("['sin', ['']]");} -function mathsInputCos(e) {mathsInputElement("['cos', ['']]");} -function mathsInputTan(e) {mathsInputElement("['tan', ['']]");} -function mathsInputInvSin(e) {mathsInputElement("['sin-1', ['']]");} -function mathsInputInvCos(e) {mathsInputElement("['cos-1', ['']]");} -function mathsInputInvTan(e) {mathsInputElement("['tan-1', ['']]");} -function mathsInputLn(e) {mathsInputElement("['ln', ['']]");} -function mathsInputLog(e) {mathsInputElement("['log', ['']]");} -function mathsInputLogBase(e) {mathsInputElement("['logBase', [''], ['']]");} -function mathsInputAbs(e) {mathsInputElement("['abs', ['']]");} -function mathsInputExp(e) {mathsInputElement("['exp', ['']]");} -function mathsInputSigma1(e) {mathsInputElement("['sigma1', ['']]");} -function mathsInputSigma2(e) {mathsInputElement("['sigma2', [''], [''], ['']]");} -function mathsInputInt1(e) {mathsInputElement("['int1', ['']]");} -function mathsInputInt2(e) {mathsInputElement("['int2', [''], [''], ['']]");} -function mathsInputVectorArrow(e) {mathsInputElement("['vectorArrow', ['']]");} -function mathsInputBar(e) {mathsInputElement("['bar', ['']]");} -function mathsInputHat(e) {mathsInputElement("['hat', ['']]");} -function mathsInputRecurring(e) {mathsInputElement("['recurring', ['']]");} -function mathsInputColVector2d(e) {mathsInputElement("['colVector2d', [''], ['']]");} -function mathsInputColVector3d(e) {mathsInputElement("['colVector3d', [''], [''], ['']]");} -function mathsInputMixedNum(e) {mathsInputElement("['mixedNum', [''], [''], ['']]");} -function mathsInputLim(e) {mathsInputElement("['lim', [''], ['']]");} - -function mathsInputCut() { - if (currMathsInput.selected == false) return; - mathsInputCopy(); - currMathsInput.cursorPos = Math.min(currMathsInput.selectPos[0],currMathsInput.selectPos[1]); - currMathsInput.selPos = []; - currMathsInput.selected = false; - deleteSelected(); - removeSelectTags(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - mathsInputCursorCoords(); -} -function mathsInputCopy() { - if (currMathsInput.selected == false) return; - var sel = false; - clipboard = arrayHandler(clone(currMathsInput.richText)); - - //console.log(clipboard); - - function arrayHandler(array) { - for (var l = 0; l < array.length; l++) { - if (typeof array[l] == 'string') { - if (l > 0 || array.length == 1 || ['frac','power','pow','subs','subscript','sin','cos','tan','ln','log','logBase','sin-1','cos-1','tan-1','abs','exp','root','sqrt','sigma1','sigma2','int1','int2','recurring','bar','hat','vectorArrow','colVector2d','colVector3d','mixedNum','lim'].indexOf(array[l]) == -1) { - array[l] = stringHandler(array[l]); - } - } else { - array[l] = arrayHandler(array[l]); - if (sel == false) { - array.splice(l,1); - l--; - } - } - } - return array; - } - function stringHandler(string) { - var delPos = []; - if (sel == true) delPos[0] = 0; - var savedTags = ''; - for (var j = 0; j < string.length; j++) { - var slice = string.slice(j); - if (slice.indexOf('<>') == 0) { - delPos[0] = j+17; - sel = true; - } - if (slice.indexOf('<>') == 0) { - delPos[1] = j; - sel = false; - } - /*if (sel == true && (slice.indexOf('<>')+2); - }*/ - } - if (delPos.length > 0) { - if (delPos.length == 1) { - return string.slice(delPos[0])+savedTags; - } else { - return string.slice(delPos[0],delPos[1]); - } - } else { - return string; - } - } -} -function mathsInputPaste() { - if (typeof clipboard !== 'object' || clipboard == [] || arraysEqual(clipboard,[''])) return; - var elementString = JSON.stringify(clipboard); - - if (currMathsInput.selected == true) { - currMathsInput.cursorPos = Math.min(currMathsInput.selectPos[0],currMathsInput.selectPos[1]); - currMathsInput.selPos = []; - currMathsInput.selected = false; - deleteSelected(); - removeSelectTags(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - mathsInputCursorCoords(); - } - - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - var parent = currMathsInput.richText; - for (var aa = 0; aa < cursorPos.length - 1; aa++) {parent = parent[cursorPos[aa]]}; - var pos = cursorPos[cursorPos.length - 1]; - pos = adjustForBreakPoints(pos); - var parentPos = cursorPos[cursorPos.length - 2]; - var evalString = 'currMathsInput.richText' - for (var aa = 0; aa < cursorPos.length - 2; aa++) { - evalString += '[' + cursorPos[aa] + ']'; - } - var before = parent.slice(0,pos); - var after = parent.slice(pos); - - //console.log('before:',before); - //console.log('after:',after); - - var newParent = clone(clipboard); - newParent.unshift(before); - newParent.push(after); - - //console.log('newParent:',newParent); - - eval(evalString+" = newParent;"); - - //console.log('currMathsInput.richText:',currMathsInput.richText); - - var cursorPosCount = 0; - arrayHandler(clipboard); - - function arrayHandler(array) { - for (var l = 0; l < array.length; l++) { - if (typeof array[l] == 'string') { - if (array.length == 1 || ['frac','power','pow','subs','subscript','sin','cos','tan','ln','log','logBase','sin-1','cos-1','tan-1','abs','exp','root','sqrt','sigma1','sigma2','int1','int2','recurring','bar','hat','vectorArrow','colVector2d','colVector3d','mixedNum','lim'].indexOf(array[l]) == -1) { - cursorPosCount += array[l].length; - } - } else { - arrayHandler(array[l]); - } - } - } - - mathsInputMapCursorPos(); - currMathsInput.cursorPos += cursorPosCount; - mathsInputCursorCoords(); - currMathsInput.preText = ''; - currMathsInput.postText = ''; -} - -function mathsInputElement(elementString) { - if (currMathsInput.selected == true) { - currMathsInput.cursorPos = Math.min(currMathsInput.selectPos[0],currMathsInput.selectPos[1]); - currMathsInput.selPos = []; - currMathsInput.selected = false; - deleteSelected(); - removeSelectTags(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - mathsInputCursorCoords(); - } - - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - var gparent = currMathsInput.richText; - for (var aa = 0; aa < cursorPos.length - 2; aa++) { - gparent = gparent[cursorPos[aa]] - }; - var parent = gparent[cursorPos[cursorPos.length-2]]; - var parentPos = cursorPos[cursorPos.length-2]; - var pos = cursorPos[cursorPos.length-1]; - pos = adjustForBreakPoints(pos); - var before = parent.slice(0,pos); - var after = parent.slice(pos); - if (!un(currMathsInput.preText) && currMathsInput.preText !== null && currMathsInput.preText !== '') { - before += currMathsInput.preText; - } - if (!un(currMathsInput.postText) && currMathsInput.postText !== null && currMathsInput.postText !== '') { - after = currMathsInput.postText + after; - } - gparent.splice(parentPos,1,before,eval(elementString),after); - - mathsInputMapCursorPos(); - currMathsInput.cursorPos++; - mathsInputCursorCoords(); - currMathsInput.preText = ''; - currMathsInput.postText = ''; -} - -function mathsInputNewLine() { - // get cursorPos - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - - if (typeof currMathsInput.richText[cursorPos[0]] == 'string') { - var slicePos = cursorPos[1]; - slicePos = adjustForBreakPoints(slicePos); - // check if there is an align tag - if (currMathsInput.richText[cursorPos[0]].slice(slicePos).indexOf('<>')+2; - } - slicePos = mathsInputAvoidTagSplit(currMathsInput.richText[cursorPos[0]],slicePos); - - currMathsInput.richText[cursorPos[0]] = currMathsInput.richText[cursorPos[0]].slice(0,slicePos) + '<
>' + currMathsInput.richText[cursorPos[0]].slice(slicePos); - mathsInputMapCursorPos(); - currMathsInput.cursorPos += 1; - mathsInputCursorCoords(); - } else { - // jump forward from element to next string (if it exists) and insert <
> - var cursorPosShiftCount = 0; - for (var i = currMathsInput.cursorPos; i < currMathsInput.cursorMap.length; i++) { - cursorPosShiftCount++; - // if the next element has been reached - if (cursorPos[0] < currMathsInput.cursorMap[i][0]) { - if (typeof currMathsInput.richText[currMathsInput.cursorMap[i][0]] == 'string') { - cursorPos = currMathsInput.cursorMap[i]; - currMathsInput.richText[currMathsInput.cursorMap[i][0]] = '<
>'+currMathsInput.richText[currMathsInput.cursorMap[i][0]]; - break; - } else { - // this shouldn't happen?? All elements will be separated by a text string - } - } else if (i == currMathsInput.cursorMap.length - 1) { - currMathsInput.richText.push('<
>'); - cursorPosShiftCount += 6; - - } - } - - mathsInputMapCursorPos(); - currMathsInput.cursorPos += cursorPosShiftCount; - mathsInputCursorCoords(); - } -} -function mathsInputTab(howMany) { - if (un(howMany)) howMany = 1; - var ins = ""; - for (var i = 0; i < howMany; i++) { - ins += String.fromCharCode(0x21F4); - } - // get cursorPos - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - - if (typeof currMathsInput.richText[cursorPos[0]] == 'string') { - var slicePos = cursorPos[1]; - slicePos = adjustForBreakPoints(slicePos); - // check if there is an align tag - if (currMathsInput.richText[cursorPos[0]].slice(slicePos).indexOf('<>')+2; - } - currMathsInput.richText[cursorPos[0]] = currMathsInput.richText[cursorPos[0]].slice(0,slicePos) + ins + currMathsInput.richText[cursorPos[0]].slice(slicePos); - mathsInputMapCursorPos(); - currMathsInput.cursorPos += howMany; - mathsInputCursorCoords(); - } else { - // jump forward from element to next string (if it exists) and insert <
> - var cursorPosShiftCount = 0; - for (var i = currMathsInput.cursorPos; i < currMathsInput.cursorMap.length; i++) { - cursorPosShiftCount++; - // if the next element has been reached - if (cursorPos[0] < currMathsInput.cursorMap[i][0]) { - if (typeof currMathsInput.richText[currMathsInput.cursorMap[i][0]] == 'string') { - cursorPos = currMathsInput.cursorMap[i]; - currMathsInput.richText[currMathsInput.cursorMap[i][0]] = ins+currMathsInput.richText[currMathsInput.cursorMap[i][0]]; - break; - } else { - // this shouldn't happen?? All elements will be separated by a text string - } - } else if (i == currMathsInput.cursorMap.length - 1) { - currMathsInput.richTexts.push(String.fromCharCode(0x21F4)); - cursorPosShiftCount += howMany; - - } - } - - mathsInputMapCursorPos(); - currMathsInput.cursorPos += cursorPosShiftCount; - mathsInputCursorCoords(); - } -} -function mathsInputLeftArrow(e) { - if (currMathsInput.cursorPos > 0) { - currMathsInput.cursorPos--; - mathsInputCursorCoords(); - } else { - mathsInputTabPrev(); - } -} -function mathsInputRightArrow(e) { - if (currMathsInput.cursorPos < currMathsInput.cursorMap.length - 1) { - currMathsInput.cursorPos++; - mathsInputCursorCoords(); - } else { - mathsInputTabNext(); - } -} -function mathsInputTabPrev() { - var dx,dy,x,y,currBest1,currBest2; - for (var i = 0; i < mathsInput[pageIndex].length; i++) { - if (i == currMathsInputId || mathsInput[pageIndex][i].canvas.parentNode !== container || mathsInput[pageIndex][i].active == false) continue; - if (mathsInput[pageIndex][i].data[100] < mathsInput[pageIndex][currMathsInputId].data[100] && mathsInput[pageIndex][i].data[101] == mathsInput[pageIndex][currMathsInputId].data[101]) { // if directly to the left - if (typeof dy == 'undefined') { - dy = 0; - dx = mathsInput[pageIndex][currMathsInputId].data[100] - mathsInput[pageIndex][i].data[100]; - currBest1 = i; - } else if (dy > 0 || (dy == 0 && mathsInput[pageIndex][currMathsInputId].data[100] - mathsInput[pageIndex][i].data[100] < dx)) { - dy = 0; - dx = mathsInput[pageIndex][currMathsInputId].data[100] - mathsInput[pageIndex][i].data[100]; - currBest1 = i; - } - } else if (mathsInput[pageIndex][i].data[101] < mathsInput[pageIndex][currMathsInputId].data[101]) { // if above - if (typeof dy == 'undefined') { - dy = mathsInput[pageIndex][currMathsInputId].data[101] - mathsInput[pageIndex][i].data[101]; - dx = mathsInput[pageIndex][currMathsInputId].data[100] - mathsInput[pageIndex][i].data[100]; - currBest1 = i; - } else if (dy > mathsInput[pageIndex][currMathsInputId].data[101] - mathsInput[pageIndex][i].data[101] || (dy == mathsInput[pageIndex][currMathsInputId].data[101] - mathsInput[pageIndex][i].data[101] && mathsInput[pageIndex][currMathsInputId].data[100] - mathsInput[pageIndex][i].data[100] < dx)) { - dy = mathsInput[pageIndex][currMathsInputId].data[101] - mathsInput[pageIndex][i].data[101]; - dx = mathsInput[pageIndex][currMathsInputId].data[100] - mathsInput[pageIndex][i].data[100]; - currBest1 = i; - } - - } else if ((mathsInput[pageIndex][i].data[100] > mathsInput[pageIndex][currMathsInputId].data[100] && mathsInput[pageIndex][i].data[101] == mathsInput[pageIndex][currMathsInputId].data[101]) || mathsInput[pageIndex][i].data[101] > mathsInput[pageIndex][currMathsInputId].data[101]) { // if directly to the right or below - if (typeof y == 'undefined') { - y = mathsInput[pageIndex][i].data[101]; - x = mathsInput[pageIndex][i].data[100]; - currBest2 = i; - } else if (mathsInput[pageIndex][i].data[101] > y || (mathsInput[pageIndex][i].data[101] == y && mathsInput[pageIndex][i].data[100] > x)) { - y = mathsInput[pageIndex][i].data[101]; - x = mathsInput[pageIndex][i].data[100]; - currBest2 = i; - } - } - } - if (typeof currBest1 !== 'undefined') { - currMathsInput.preText = ''; - currMathsInput.postText = ''; - deselectMathsInput(mathsInput[pageIndex][currBest1],true); - startMathsInput(mathsInput[pageIndex][currBest1]); - currMathsInput.cursorPos = currMathsInput.cursorMap.length - 1; - mathsInputCursorCoords(); - } else if (typeof currBest2 !== 'undefined') { - currMathsInput.preText = ''; - currMathsInput.postText = ''; - deselectMathsInput(mathsInput[pageIndex][currBest2],true); - startMathsInput(mathsInput[pageIndex][currBest2]); - currMathsInput.cursorPos = 0; - mathsInputCursorCoords(); - } -} -function mathsInputTabNext() { - var index = mathsInput[pageIndex].indexOf(currMathsInput); - if (index > -1) { - var newIndex = (index+1) % mathsInput[pageIndex].length; - currMathsInput.preText = ''; - currMathsInput.postText = ''; - deselectMathsInput(mathsInput[pageIndex][newIndex],true); - startMathsInput(mathsInput[pageIndex][newIndex]); - currMathsInput.cursorPos = currMathsInput.cursorMap.length - 1; - mathsInputCursorCoords(); - } - return; - - /*var dx,dy,x,y,currBest1,currBest2; - for (var i = 0; i < mathsInput[pageIndex].length; i++) { - if (i == currMathsInputId || mathsInput[pageIndex][i].canvas.parentNode !== container || mathsInput[pageIndex][i].active == false) continue; - if (mathsInput[pageIndex][i].data[100] > mathsInput[pageIndex][currMathsInputId].data[100] && mathsInput[pageIndex][i].data[101] == mathsInput[pageIndex][currMathsInputId].data[101]) { // if directly to the right - if (typeof dy == 'undefined') { - dy = 0; - dx = mathsInput[pageIndex][i].data[100] - mathsInput[pageIndex][currMathsInputId].data[100]; - currBest1 = i; - } else if (dy > 0 || (dy == 0 && mathsInput[pageIndex][i].data[100] - mathsInput[pageIndex][currMathsInputId].data[100] < dx)) { - dy = 0; - dx = mathsInput[pageIndex][i].data[100] - mathsInput[pageIndex][currMathsInputId].data[100]; - currBest1 = i; - } - } else if (mathsInput[pageIndex][i].data[101] > mathsInput[pageIndex][currMathsInputId].data[101]) { // if below - if (typeof dy == 'undefined') { - dy = mathsInput[pageIndex][i].data[101] - mathsInput[pageIndex][currMathsInputId].data[101]; - dx = mathsInput[pageIndex][i].data[100] - mathsInput[pageIndex][currMathsInputId].data[100]; - currBest1 = i; - } else if (dy > mathsInput[pageIndex][i].data[101] - mathsInput[pageIndex][currMathsInputId].data[101] || (dy == mathsInput[pageIndex][i].data[101] - mathsInput[pageIndex][currMathsInputId].data[101] && mathsInput[pageIndex][i].data[100] - mathsInput[pageIndex][currMathsInputId].data[100] < dx)) { - dy = mathsInput[pageIndex][i].data[101] - mathsInput[pageIndex][currMathsInputId].data[101]; - dx = mathsInput[pageIndex][i].data[100] - mathsInput[pageIndex][currMathsInputId].data[100]; - currBest1 = i; - } - - } else if ((mathsInput[pageIndex][i].data[100] < mathsInput[pageIndex][currMathsInputId].data[100] && mathsInput[pageIndex][i].data[101] == mathsInput[pageIndex][currMathsInputId].data[101]) || mathsInput[pageIndex][i].data[101] < mathsInput[pageIndex][currMathsInputId].data[101]) { // if directly to the left or above - if (typeof y == 'undefined') { - y = mathsInput[pageIndex][i].data[101]; - x = mathsInput[pageIndex][i].data[100]; - currBest2 = i; - } else if (mathsInput[pageIndex][i].data[101] < y || (mathsInput[pageIndex][i].data[101] == y && mathsInput[pageIndex][i].data[100] < x)) { - y = mathsInput[pageIndex][i].data[101]; - x = mathsInput[pageIndex][i].data[100]; - currBest2 = i; - } - } - } - if (typeof currBest1 !== 'undefined') { - currMathsInput.preText = ''; - currMathsInput.postText = ''; - deselectMathsInput(mathsInput[pageIndex][currBest1],true); - startMathsInput(mathsInput[pageIndex][currBest1]); - currMathsInput.cursorPos = currMathsInput.cursorMap.length - 1; - mathsInputCursorCoords(); - } else if (typeof currBest2 !== 'undefined') { - currMathsInput.preText = ''; - currMathsInput.postText = ''; - deselectMathsInput(mathsInput[pageIndex][currBest2],true); - startMathsInput(mathsInput[pageIndex][currBest2]); - currMathsInput.cursorPos = 0; - mathsInputCursorCoords(); - }*/ -} - -function mathsInputAvoidTagSplit(txt,slicePos) { - // check that a tag is not being split - if so adjust slicePos - var leftText = txt.slice(0,slicePos); - var rightText = txt.slice(slicePos); - //console.clear(); - //console.log(txt,slicePos); - //console.log(leftText); - //console.log(rightText); - var tagLeft = false; - var tagLeftCount = 0; - for (var i = 0; i < leftText.length; i++) { - tagLeftCount++; - //console.log('left '+i+':',leftText.slice(leftText.length - i)); - if (leftText.slice(leftText.length - i).indexOf('>>') == 0) break; - if (leftText.slice(leftText.length - i).indexOf('<<') == 0) { - tagLeft = true; - break; - } - } - var tagRight = false; - var tagRightCount = 0; - for (var j = 0; j < rightText.length; j++) { - tagRightCount++; - //console.log('right '+j+':',rightText.slice(j)); - if (rightText.slice(j).indexOf('<<') == 0) break; - if (rightText.slice(j).indexOf('>>') == 0) { - tagRight = true; - break; - } - } - //console.log(tagLeft,tagRight,tagLeftCount,tagRightCount); - if (tagLeft == true && tagRight == true) { - if (tagLeftCount <= tagRightCount) { - slicePos -= tagLeftCount; - } else { - slicePos += tagRightCount; - } - } - // test if '<',slicePos,'<' or '>',slicePos,'>' - if (leftText.slice(-1) == '<' && rightText.slice(0,1) == '<' && rightText.slice(0,2) !== '<<') slicePos--; - if (leftText.slice(-1) == '>' && leftText.slice(-2) !== '>>' && rightText.slice(0,1) == '>') slicePos++; - - return slicePos; -} - -function startMathsInput(e,startCursorPos) { - deselectMathsInput(e,true); - window.addEventListener('keydown', hardKeyMathsInput, false); - canvas.addEventListener('mousedown', endMathsInput, false); // clicking anywhere on the canvas will end the input - canvas.addEventListener('touchstart', endMathsInput, false); // touching anywhere on the canvas will end the input - /*// clicking a holder button will end the input - if (typeof holderButton !== 'undefined') { - for (i = 0; i < 3; i++) { - holderButton[i].addEventListener('mousedown', endMathsInput, false); - holderButton[i].addEventListener('touchstart', endMathsInput, false); - } - } - for (i = 0; i < taskObject[pageIndex].length; i++) { // clicking any other object will also end the input - if (endInputExceptions.indexOf(taskObject[pageIndex][i]) == -1) { - taskObject[pageIndex][i].addEventListener('mousedown', endMathsInput, false); - taskObject[pageIndex][i].addEventListener('touchstart', endMathsInput, false); - } - }*/ - if (e.target) { - var inputCanvas = e.target; - } else { - var inputCanvas = e; - }; - for (i = 0; i < mathsInput[pageIndex].length; i++) { - if (mathsInput[pageIndex][i].cursorCanvas == inputCanvas || mathsInput[pageIndex][i].canvas == inputCanvas || mathsInput[pageIndex][i] == inputCanvas) { - currMathsInput = mathsInput[pageIndex][i]; - currMathsInputId = i; - } - } - if (currMathsInput.transparent == false && currMathsInput.selectColor !== 'none') { - currMathsInput.canvas.style.backgroundColor = "#FCF"; - } else if (currMathsInput.transparent == false || currMathsInput.selectColor == 'none') { - currMathsInput.canvas.style.backgroundColor = "#transparent"; - } - inputState = true; // allows the onscreen keys to function - var closestPos = getClosestTextPos(); - //console.log(currMathsInput,closestPos,currMathsInput.selectable,startCursorPos); - if (currMathsInput.selectable == true && typeof startCursorPos == 'undefined') { - currMathsInput.selectPos = [closestPos,closestPos]; - setSelectPositions(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - if (typeof currMathsInput.pointerCanvas !== 'object') { - addListenerMove(currMathsInput.cursorCanvas,selectTextMove); - addListenerEnd(currMathsInput.cursorCanvas,selectTextStop); - } - } else { - mathsInputMapCursorPos(); - currMathsInput.cursorPos = startCursorPos || Number(closestPos) || 0; - //console.log(currMathsInput,currMathsInput.cursorPos,currMathsInput.cursorMap[currMathsInput.cursorPos],currMathsInput.textLoc); - mathsInputCursorCoords(); - updateKeyboardCurrFont(); - showKeyboard2(true); - } - if (!un(currMathsInput.markPos)) { - currMathsInput.markctx.clearRect(currMathsInput.markPos[0]-5,currMathsInput.markPos[1]-5,currMathsInput.markPos[2]+10,currMathsInput.markPos[3]+10); - } - //shiftOn = false; - //ctrlOn = false; - //altOn = false; - if (!un(window.textMenu) && typeof textMenu.show == 'function' && textMenu.showOnStartInput == true) { - textMenu.update(); - textMenu.show(); - } -} -function selectTextMove(e) { - updateMouse(e); - var closestPos = getClosestTextPos(); - //console.log(closestPos); - if (currMathsInput.selectPos[1] !== closestPos) { - currMathsInput.selectPos[1] = closestPos; - //console.log(currMathsInput.selectPos); - currMathsInput.selected = true; - setSelectPositions(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - } - console.log(currMathsInput.selectPos); - //console.log('selectTextMove',currMathsInput.selected); -} -function selectTextStop(e) { - //console.log(currMathsInput.selectPos); - removeListenerMove(currMathsInput.cursorCanvas,selectTextMove); - removeListenerEnd(currMathsInput.cursorCanvas,selectTextStop); - if (currMathsInput.selectPos[0] == currMathsInput.selectPos[1]) { - currMathsInput.cursorPos = currMathsInput.selectPos[0]; - currMathsInput.selectPos = []; - currMathsInput.selected = false; - setSelectPositions(); - mathsInputMapCursorPos(); - mathsInputCursorCoords(); - } - updateKeyboardCurrFont(); - showKeyboard2(true); -} -function getClosestTextPos(mathsInput) { - if (!mathsInput) mathsInput = currMathsInput; - // search through text character locations for a mouse hit test - var mousePos = [mouse.x-mathsInput.data[100],mouse.y-mathsInput.data[101]]; - //console.log(mathsInput); - if (typeof mathsInput.cursorMap == 'undefined') { - mathsInputMapCursorPos(); - } - var map = mathsInput.cursorMap; - var closestPos = 0; - var closestDist; - var vertDist; - var closestVertDist; - //console.log('getClosestTextPos()'); - //console.clear(); - for (var pos = 0; pos < map.length; pos++) { - var loc = mathsInput.textLoc; - for (var aa = 0; aa < map[pos].length; aa++) { - loc = loc[map[pos][aa]]; - }; - - /* - var ctx = mathsInput.ctx; - ctx.strokeStyle = '#F0F'; - ctx.beginPath(); - ctx.moveTo(loc.left,loc.top); - ctx.lineTo(loc.left,loc.top+loc.height); - ctx.stroke(); - */ - - if (!loc) continue; - - if (pos == 0) { - closestDist = distancePointToLineSegment(mousePos,[loc.left,loc.top],[loc.left,loc.top+loc.height]); - closestPos = pos; - vertDist = Math.min(Math.abs(mousePos[1]-loc.top),Math.abs(mousePos[1]-(loc.top+loc.height))); - if (mousePos[1] >= loc.top && mousePos[1] <= loc.top + loc.height) vertDist = 0; - closestVertDist = vertDist; - } else { - var newDist = distancePointToLineSegment(mousePos,[loc.left,loc.top],[loc.left,loc.top+loc.height]); - var newVertDist = Math.min(Math.abs(mousePos[1]-loc.top),Math.abs(mousePos[1]-(loc.top+loc.height))); - if (mousePos[1] >= loc.top && mousePos[1] <= loc.top + loc.height) newVertDist = 0; - if (newVertDist < closestVertDist || (newVertDist == closestVertDist && newDist < closestDist)) { - closestVertDist = newVertDist; - closestDist = newDist; - closestPos = pos; - } - } - - //console.log(pos,loc.left,newDist,closestDist,closestPos) - } - - /* - ctx.beginPath(); - ctx.moveTo(mousePos[0]-3,mousePos[1]-3); - ctx.lineTo(mousePos[0]+3,mousePos[1]+3); - ctx.moveTo(mousePos[0]-3,mousePos[1]+3); - ctx.lineTo(mousePos[0]+3,mousePos[1]-3); - ctx.stroke(); - */ - //console.log(closestPos); - if (isNaN(closestPos) || typeof closestPos == 'undefined' || closestPos == null) { - closestPos = 0; - } - return closestPos; -} -function endMathsInput(e) { - if (!un(e) && !un(keyboardButton1) && !un(keyboardButton1[pageIndex]) && e.target == keyboardButton1[pageIndex]) return; - if (!un(e) && !un(keyboardButton2) && !un(keyboardButton2[pageIndex]) && e.target == keyboardButton2[pageIndex]) return; - if (un(currMathsInput)) return; - if (currMathsInput.selected == true) { - removeSelectTags(); - mathsInputMapCursorPos(); - currMathsInput.cursorPos = Math.min(currMathsInput.selectPos[0],currMathsInput.selectPos[1]); - currMathsInput.selectPos = []; - mathsInputCursorCoords(); - currMathsInput.selected = false; - removeSelectTags(); - } - deselectMathsInput(e); - - if (typeof currMathsInput.onInputEnd == 'function') { - currMathsInput.onInputEnd(e); - } -} -function deselectMathsInput(e,diffInput) { - if (un(currMathsInput)) return; - currMathsInput.preText = ''; - currMathsInput.postText = ''; - if (currMathsInput.selected == true) { - removeSelectTags(); - mathsInputMapCursorPos(); - currMathsInput.cursorPos = Math.min(currMathsInput.selectPos[0],currMathsInput.selectPos[1]); - currMathsInput.selectPos = []; - mathsInputCursorCoords(); - currMathsInput.selected = false; - removeSelectTags(); - } - // test if the deselection is caused by a new input - var diffInputTest = -1; - if (typeof e == 'object' && e && typeof e.target == 'object' && e.target !== currMathsInput.canvas && !un(mathsInput[pageIndex])) { - for (var i = 0; i < mathsInput[pageIndex].length; i++) { - if (mathsInput[pageIndex][i].cursorCanvas == e.target) { - if (currMathsInput.canvas == e.target) { - return; // indicates the currently active mathsInput has been reclicked - do nothing - } else { - diffInputTest = i; - } - break; - } - } - } - - if ((typeof diffInput !== 'undefined' && diffInput == true) || diffInputTest > -1) { - - } else { - hideKeyboard2(true); - inputState = false; - // remove event listeners for mathsInput - window.removeEventListener('keydown', hardKeyMathsInput, false); - canvas.removeEventListener('mousedown', endMathsInput, false); - canvas.removeEventListener('touchstart', endMathsInput, false); - } - - //currMathsInput.currBackColor = currMathsInput.backColor; - /* - currMathsInput.ctx.clearRect(0, 0, currMathsInput.data[2], currMathsInput.data[3]); - if (currMathsInput.transparent == false && currMathsInput.backColor !== 'none') { - currMathsInput.ctx.fillStyle = currMathsInput.backColor || '#FFF'; - } - */ - - currMathsInput.canvas.style.backgroundColor = currMathsInput.backColor || 'transparent'; - if (currMathsInput.backColor == 'none') { - currMathsInput.canvas.style.backgroundColor = 'transparent' - } - - clearCorrectingInterval(mathsInputCursorBlinkInterval); - inputCursorState = false - blinking = false; - - currMathsInput.cursorctx.clearRect(0,0,1200,700); - - if ((typeof diffInput !== 'undefined' && diffInput == true) || diffInputTest > -1) { - if (typeof currMathsInput.onInputEnd == 'function') { - currMathsInput.onInputEnd(); - } - } else { - if (!un(window.textMenu)) { - if (typeof textMenu.show == 'function' && textMenu.showOnStartInput == true) { - textMenu.hide(); - } - } - } - if (typeof holderButton !== 'undefined') { - for (var i = 0; i < 3; i++) { - holderButton[i].removeEventListener('mousedown', endMathsInput, false); - holderButton[i].removeEventListener('mousedown', endMathsInput, false); - } - } - /*var startAt = 0; - if (taskKey[pageIndex]) {startAt = taskKey[pageIndex].length} - function listenerForI(i) { - taskObject[pageIndex][i].removeEventListener('mousedown', endMathsInput, false); - taskObject[pageIndex][i].removeEventListener('touchstart', endMathsInput, false); - } - if (taskObject[pageIndex]) { - for (var i = startAt; i < taskObject[pageIndex].length; i++) { // clicking any other object will also end the input - listenerForI(i); //'scopes' the variable i - } - }*/ - -} - -function setSelectPositions() { - // check for a need to adjust each selectPos - - var selPos1 = clone(currMathsInput.cursorMap[currMathsInput.selectPos[0]]); - if (typeof selPos1 !== 'undefined') { - var txt = clone(currMathsInput.richText); - for (var i = 0; i < selPos1.length - 1; i++) {txt = txt[selPos1[i]]}; - var txtSlice = txt.slice(0,selPos1[selPos1.length-1]); - if (txtSlice.indexOf('<>') > -1) { - selPos1[selPos1.length-1] -= 17; - } - if (txtSlice.indexOf('<>') > -1) { - selPos1[selPos1.length-1] -= 18; - } - } - - var selPos2 = clone(currMathsInput.cursorMap[currMathsInput.selectPos[1]]); - if (typeof selPos2 !== 'undefined') { - var txt = clone(currMathsInput.richText); - for (var i = 0; i < selPos2.length - 1; i++) {txt = txt[selPos2[i]]}; - var txtSlice = txt.slice(0,selPos2[selPos2.length-1]); - if (txtSlice.indexOf('<>') > -1) { - selPos2[selPos2.length-1] -= 17; - } - if (txtSlice.indexOf('<>') > -1) { - selPos2[selPos2.length-1] -= 18; - } - } - - removeSelectTags(); - - if (arraysEqual(currMathsInput.selectPos,[]) == false) { - if (currMathsInput.selectPos[0] == currMathsInput.selectPos[1]) { - insertTag('<><>',selPos1); - } else if (currMathsInput.selectPos[0] > currMathsInput.selectPos[1]) { - insertTag('<>',selPos1); - insertTag('<>',selPos2); - } else if (currMathsInput.selectPos[0] < currMathsInput.selectPos[1]) { - insertTag('<>',selPos2); - insertTag('<>',selPos1); - } - } - - function insertTag(insertion,cursorPos) { - // get the relevant string from currMathsInput.richText - var text = currMathsInput.richText; - for (var aa = 0; aa < cursorPos.length - 1; aa++) { - text = text[cursorPos[aa]]; - } - // pos is position of cursor - var pos = cursorPos[cursorPos.length - 1]; - - // adjust pos to account for breakPoints - if (typeof currMathsInput.breakPoints == 'object') { - for (var k = 0; k < currMathsInput.breakPoints.length - 1; k++) { - var breakPoint = currMathsInput.allMap[currMathsInput.breakPoints[k]]; - if (breakPoint[0] == cursorPos[0] && breakPoint[1] < cursorPos[1]) { - pos--; - } - } - } - // check that a tag is not being split - if so adjust pos - var leftText = text.slice(0,pos); - var rightText = text.slice(pos); - var tagLeft = false; - var tagLeftCount = 0; - for (var i = 0; i < leftText.length; i++) { - tagLeftCount++; - if (leftText.slice(leftText.length - i).indexOf('>>') == 0) break; - if (leftText.slice(leftText.length - i).indexOf('<<') == 0) { - tagLeft = true; - break; - } - } - var tagRight = false; - var tagRightCount = 0; - for (var j = 0; j < rightText.length; j++) { - tagRightCount++; - if (rightText.slice(j).indexOf('<<') == 0) break; - if (rightText.slice(j).indexOf('>>') == 0) { - tagRight = true; - break; - } - } - if (tagLeft == true && tagRight == true) { - if (tagLeftCount <= tagRightCount) { - pos -= tagLeftCount; - } else { - pos += tagRightCount; - } - } - var leftText = text.slice(0,pos); - var rightText = text.slice(pos); - if (leftText.slice(-1) == '<' && rightText.slice(0,1) == '<' && rightText.slice(0,2) !== '<<') pos--; - if (leftText.slice(-1) == '>' && leftText.slice(-2) !== '>>' && rightText.slice(0,1) == '>') pos++; - var textBefore = text.slice(0,pos); - var textAfter = text.slice(pos); - - text = textBefore + insertion + textAfter; - // replace the string - var evalString = 'currMathsInput.richText' - for (aa = 0; aa < cursorPos.length - 1; aa++) { - evalString += '[' + cursorPos[aa] + ']'; - } - eval(evalString + ' = text;'); - } -} -function removeSelectTags() { - var map1; - var map2; - var pos = []; - function arrayHandler(array) { - pos.push(0); - for (var l = array.length - 1; l >= 0; l--) { - pos[pos.length-1] = l; - if (typeof array[l] == 'string') { - array[l] = stringHandler(array[l]); - } else { - array[l] = arrayHandler(array[l]); - } - } - pos.pop(); - return array; - } - function stringHandler(string) { - //console.log(string,JSON.stringify(pos)); - for (var j = string.length - 1; j >= 0; j--) { - var slice = string.slice(j); - if (slice.indexOf('<>') == 0) { - string = string.slice(0,j)+string.slice(j+slice.indexOf('>>')+2); - if (typeof map1 !== 'undefined' && arraysEqual(pos,map1) == true && map2 > j) { - map2 = Math.max(0,map2-18); - } - } - if (slice.indexOf('<>') == 0) { - string = string.slice(0,j)+string.slice(j+slice.indexOf('>>')+2); - if (typeof map1 !== 'undefined' && arraysEqual(pos,map1) == true && map2 > j) { - map2 = Math.max(0,map2-17); - } - } - } - return string; - } - - //console.log(JSON.stringify(currMathsInput.cursorMap[currMathsInput.cursorPos])); - if (typeof currMathsInput.cursorPos == 'number') { - map1 = currMathsInput.cursorMap[currMathsInput.cursorPos]; - if (typeof map1 !== 'undefined') { - map2 = map1[map1.length-1]; - map1 = map1.slice(0,-1); - //console.log(JSON.stringify(map1),map2); - } - } - - currMathsInput.richText = arrayHandler(currMathsInput.richText); - - //console.log('---',map2); - if (typeof map2 !== 'undefined') { - currMathsInput.cursorMap[currMathsInput.cursorPos][currMathsInput.cursorMap[currMathsInput.cursorPos].length-1] = map2; - } - // adjust cursorPos if necessary - -} -function removeSelectTagsFromArray(textArray) { - var map1; - var map2; - var pos = []; - function arrayHandler(array) { - pos.push(0); - for (var l = array.length - 1; l >= 0; l--) { - pos[pos.length-1] = l; - if (typeof array[l] == 'string') { - array[l] = stringHandler(array[l]); - } else { - array[l] = arrayHandler(array[l]); - } - } - pos.pop(); - return array; - } - function stringHandler(string) { - //console.log(string,JSON.stringify(pos)); - for (var j = string.length - 1; j >= 0; j--) { - var slice = string.slice(j); - if (slice.indexOf('<>') == 0) { - string = string.slice(0,j)+string.slice(j+slice.indexOf('>>')+2); - if (typeof map1 !== 'undefined' && arraysEqual(pos,map1) == true && map2 > j) { - map2 = Math.max(0,map2-18); - } - } - if (slice.indexOf('<>') == 0) { - string = string.slice(0,j)+string.slice(j+slice.indexOf('>>')+2); - if (typeof map1 !== 'undefined' && arraysEqual(pos,map1) == true && map2 > j) { - map2 = Math.max(0,map2-17); - } - } - } - return string; - } - - return arrayHandler(textArray); -} -function deleteSelected() { - var sel = false; - currMathsInput.richText = arrayHandler(currMathsInput.richText); - - function arrayHandler(array) { - for (var l = 0; l < array.length; l++) { - if (typeof array[l] == 'string') { - if (l > 0 || array.length == 1 || ['frac','power','pow','subs','subscript','sin','cos','tan','ln','log','logBase','sin-1','cos-1','tan-1','abs','exp','root','sqrt','sigma1','sigma2','int1','int2','recurring','bar','hat','vectorArrow','colVector2d','colVector3d','mixedNum','lim'].indexOf(array[l]) == -1) { - array[l] = stringHandler(array[l]); - } - } else { - var preSel = false; - if (sel == true) {preSel = true}; - array[l] = arrayHandler(array[l]); - if (sel == true && preSel == true) { - array.splice(l,1); - l--; - } - } - } - return array; - } - function stringHandler(string) { - var delPos = []; - if (sel == true) delPos[0] = 0; - var savedTags = ''; - for (var j = 0; j < string.length; j++) { - var slice = string.slice(j); - if (slice.indexOf('<>') == 0) { - delPos[0] = j; - sel = true; - } - if (slice.indexOf('<>') == 0) { - delPos[1] = j + 18; - sel = false; - } - if (sel == true && (slice.indexOf('<>')+2); - } - } - if (delPos.length > 0) { - if (delPos.length == 1) { - return string.slice(0,delPos[0])+savedTags; - } else { - return string.slice(0,delPos[0])+savedTags+string.slice(delPos[1]); - } - } else { - return string; - } - } -} - -function mathsInputMapCursorPos() { // (re-)builds cursor map - currMathsInput.richText = reduceTags(currMathsInput.richText); - currMathsInput.richText = combineSpacesCursor(currMathsInput.richText); - - // create new cursor map - currMathsInput.textLoc = []; - drawMathsInputText(currMathsInput); - currMathsInput.cursorMap = mapArray(currMathsInput.textLoc,false); - - // create new allMap - this includes all markup tag characters - currMathsInput.allMap = mapArray(currMathsInput.textLoc,true); - - // move cursor positions in cursorMap from end to beginning of markup tags (except for beginning) - var cursorMap = currMathsInput.cursorMap; - - //console.log(currMathsInput.cursorPos,JSON.stringify(cursorMap)); - - for (var i = 1; i < cursorMap.length; i++) { - - // get text element - var richText = currMathsInput.richText; - for (var j = 0; j < cursorMap[i].length - 1; j++) richText = richText[cursorMap[i][j]]; - - // char is position of cursor - var char = cursorMap[i][cursorMap[i].length-1]; - - // adjust char to account for breakPoints - if (typeof currMathsInput.breakPoints == 'object') { - for (var k = 0; k < currMathsInput.breakPoints.length - 1; k++) { - var breakPoint = currMathsInput.allMap[currMathsInput.breakPoints[k]]; - if (breakPoint[0] == cursorMap[i][0] && breakPoint[1] < cursorMap[i][1]) { - char--; - } - } - } - - // if proceeded by a tag - if (richText.slice(char-2).indexOf('>>') == 0 && richText.slice(char-6).indexOf('<
>') !== 0) { - - // get text to the left of char - var leftText = richText.slice(0,char); - - // get tagCharCount to the left of char - var tagCharCount = 0; - for (var j = 0; j < leftText.length; j++) { - if (richText.slice(char-j,char).indexOf('<<') == 0 && (leftText.slice(char-j-2,char).indexOf('>>') !== 0 || leftText.slice(char-j-6,char).indexOf('<
>') == 0)) { - tagCharCount = j; - break; - } - } - - // check that it's not the very beginning - if (cursorMap[i][0] == 0 && cursorMap[i][1] == tagCharCount) continue; - - // alter the cursorMap by tagCharCount - currMathsInput.cursorMap[i][currMathsInput.cursorMap[i].length-1] -= tagCharCount; - } - - - } - - // update currMathsInput.text to be the same as currMathsInput.richText without any markuptags - currMathsInput.text = clone(currMathsInput.richText); - for (var p = 0; p < currMathsInput.text.length; p++) { - currMathsInput.text[p] = removeTags(currMathsInput.text[p]); - } -} -function combineSpacesCursor(array) { - //console.log(array.length); - if (array.length > 1) { - for (var gg = array.length - 1; gg >= 0; gg--) { - //console.log(gg, array[gg], typeof array[gg]); - if (typeof array[gg] == 'object') { - arrayString += '[' + gg + ']'; - combineSpacesCursor(array[gg]); - } else { - if (gg < array.length - 1 && typeof array[gg] == 'string' && typeof array[gg+1] == 'string') { - eval('currMathsInput.richText' + arrayString + '[' + gg + '] += currMathsInput.richText' + arrayString + '[' + (gg+1) + ']'); - eval('currMathsInput.richText' + arrayString + '.splice(gg+1, 1);'); - } - } - } - } - arrayString = arrayString.slice(0, arrayString.lastIndexOf('[') - arrayString.length); - return array; -} -function combineSpacesTextArray(array) { - if (array.length > 1) { - for (var i = array.length - 1; i >= 0; i--) { - if (typeof array[i] == 'object') { - if (i < array.length - 1 && typeof array[i] == 'string' && typeof array[i+1] == 'string') { - array[i] = array[i] + array[i+1]; - array.splice(i+1,1); - } - } else { - combineSpacesTextArray(array[i]); - } - } - } - return array; -} - -function mathsInputCursorCoords() { // updates cursor coordinates - drawMathsInputText(currMathsInput); - var char; - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - - if (typeof cursorPos == 'undefined') return; - - char = currMathsInput.textLoc; - for (var aa = 0 ; aa < cursorPos.length; aa++) { - char = char[cursorPos[aa]]; - } - - mathsInputCursor.x = char.left; - mathsInputCursor.top = char.top; - mathsInputCursor.bottom = char.top + char.height; - - //logText(true); - - //console.log('mathsInputCursor:',mathsInputCursor); - - inputCursorState = false; - clearCorrectingInterval(mathsInputCursorBlinkInterval); - drawMathsInputText(currMathsInput); - mathsInputCursorBlink(); - mathsInputCursorBlinkInterval = setCorrectingInterval(function(){mathsInputCursorBlink()}, 600); - blinking = true; - currMathsInput.stringJS = createJsString(); - if (typeof textMenu !== 'undefined' && typeof textMenu !== 'undefined' && typeof textMenu.update == 'function') textMenu.update(); -} -var showCursorPos = false; -function adjustForBreakPointsAllMap(pos) { - //console.log('pos:',pos); - if (typeof currMathsInput.breakPoints == 'object') { - //console.log('pos:',pos); - var map = currMathsInput.allMap[pos]; - for (var i = 0; i < currMathsInput.breakPoints.length - 1; i++) { - var iBreak = currMathsInput.allMap[currMathsInput.breakPoints[i]]; - if (iBreak[0] == map[0] && iBreak[1] < map[1]) { - pos--; - } - } - //console.log('pos:',pos); - } - return pos; -} -function adjustForBreakPoints(pos,map,breakPoints) { - if (typeof pos == 'undefined') pos = currMathsInput.cursorPos; - if (typeof map == 'undefined') map = currMathsInput.cursorMap[currMathsInput.cursorPos]; - if (typeof breakPoints == 'undefined') breakPoints = currMathsInput.breakPoints; - - if (typeof breakPoints == 'object') { - for (var i = 0; i < breakPoints.length - 1; i++) { - var iBreak = currMathsInput.allMap[breakPoints[i]]; - //if (i > 0 && iBreak[1] - currMathsInput.allMap[breakPoints[i-1]][1] <= 7) continue; - //console.log(iBreak,iBreak[0] == map[0] && iBreak[1] < map[1]); - if (iBreak[0] == map[0] && iBreak[1] < map[1]) { - pos--; - } - } - } - - return pos; -} -function mathsInputCursorBlink() { - if (inputCursorState == true) {inputCursorState = false} else {inputCursorState = true}; - - currMathsInput.cursorctx.clearRect(0,0,1200,700); - currMathsInput.cursorCanvas.style.zIndex = currMathsInput.canvas.style.zIndex + 1; - - if (showCursorPos == true) { - for (var i = 0; i < currMathsInput.cursorMap.length; i++) { - var cPos = currMathsInput.textLoc; - - for (var j = 0; j < currMathsInput.cursorMap[i].length; j++) { - cPos = cPos[currMathsInput.cursorMap[i][j]]; - } - - // adjust cPos to account for difference between canvas and cursor canvas positions - cPos.left += (currMathsInput.data[100] - currMathsInput.cursorData[100]); - cPos.top += (currMathsInput.data[101] - currMathsInput.cursorData[101]); - - //console.log(cPos); - - currMathsInput.cursorctx.save(); - currMathsInput.cursorctx.strokeStyle = '#F00'; - currMathsInput.cursorctx.lineWidth = 2; - currMathsInput.cursorctx.beginPath(); - currMathsInput.cursorctx.moveTo(cPos.left, cPos.top); - currMathsInput.cursorctx.lineTo(cPos.left, cPos.top + cPos.height); - currMathsInput.cursorctx.closePath(); - currMathsInput.cursorctx.stroke(); - currMathsInput.cursorctx.restore(); - } - } else if (inputCursorState == true && currMathsInput.selected == false) { - var hAdjust = currMathsInput.data[100] - currMathsInput.cursorData[100]; - var vAdjust = currMathsInput.data[101] - currMathsInput.cursorData[101]; - //console.log('blink',inputCursorState,currMathsInput.selected,mathsInputCursor,currMathsInput.cursorPos,hAdjust,vAdjust); - currMathsInput.cursorctx.save(); - currMathsInput.cursorctx.strokeStyle = currMathsInput.textColor; - currMathsInput.cursorctx.lineWidth = 2; - currMathsInput.cursorctx.beginPath(); - currMathsInput.cursorctx.moveTo(hAdjust + mathsInputCursor.x, vAdjust + mathsInputCursor.top); - currMathsInput.cursorctx.lineTo(hAdjust + mathsInputCursor.x, vAdjust + mathsInputCursor.bottom); - currMathsInput.cursorctx.closePath(); - currMathsInput.cursorctx.stroke(); - currMathsInput.cursorctx.restore(); - } else { - //console.log('blink',inputCursorState,currMathsInput.selected,mathsInputCursor,currMathsInput.cursorPos); - } -} - -//var shiftOn = false; -//window.addEventListener('keyup', shiftKeyUp, false); -/*function shiftKeyUp(e) { - e.preventDefault(); - if (e.keyCode == 16) { - shiftOn = false; - } -}*/ -function hardKeyMathsInput(e) { // if a key is pressed via the hardware keyboard - e.preventDefault(); - if (inputState == true) { - var charCode = e.keyCode; // determine which key has been pressed - var keysToIgnore = [16,17,18,27,33,34,35,36,46,112,113,114,115,116,117,118,119,120,121,122,123,144,223]; - if (e.getModifierState('Control')) { - if (charCode == 88) { //CTRL-x - mathsInputCut(); - } else if (charCode == 67) { //CTRL-c - mathsInputCopy(); - } else if (charCode == 86) { //CTRL-v - mathsInputPaste(); - } - return; - } - if (e.getModifierState('Alt')) return; - switch (charCode) { - case 37 : // left arrow - currMathsInput.preText = ''; - currMathsInput.postText = ''; - if (e.getModifierState('Shift') == true && currMathsInput.cursorPos > 0) { - if (currMathsInput.selected == true) { - currMathsInput.selectPos[1] = [currMathsInput.cursorPos-1]; - setSelectPositions(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - currMathsInput.cursorPos--; - } else { - currMathsInput.selected = true; - currMathsInput.selectPos = [currMathsInput.cursorPos,currMathsInput.cursorPos-1]; - setSelectPositions(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - currMathsInput.cursorPos--; - } - } else if (currMathsInput.selected == true) { - removeSelectTags(); - mathsInputMapCursorPos(); - currMathsInput.cursorPos = Math.min(currMathsInput.selectPos[0],currMathsInput.selectPos[1]); - currMathsInput.selectPos = []; - mathsInputCursorCoords(); - currMathsInput.selected = false; - removeSelectTags(); - } else if (currMathsInput.cursorPos > 0) { - currMathsInput.cursorPos--; - mathsInputCursorCoords(); - } else { - mathsInputTabPrev(); - } - break; - case 38 : // up arrow - currMathsInput.preText = ''; - currMathsInput.postText = ''; - if (e.getModifierState('Shift') == true) { - if (currMathsInput.selected == false) { - currMathsInput.selectPos[0] = currMathsInput.cursorPos; - } - } else if (currMathsInput.selected == true) { - removeSelectTags(); - mathsInputMapCursorPos(); - currMathsInput.cursorPos = Math.min(currMathsInput.selectPos[0],currMathsInput.selectPos[1]); - currMathsInput.selectPos = []; - mathsInputCursorCoords(); - currMathsInput.selected = false; - removeSelectTags(); - } - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - // get the parent of the current string - var parent = currMathsInput.richText; - for (var i = 0; i < cursorPos.length - 3; i++) {parent = parent[cursorPos[i]]}; - if (parent[0] == 'frac' && cursorPos[cursorPos.length - 3] == 2) { - currMathsInput.cursorPos -= cursorPos[cursorPos.length - 1]; - currMathsInput.cursorPos--; - mathsInputCursorCoords(); - } else { - // check if there is a row above - var lowerBreakPoints = []; - for (var i = 0; i < currMathsInput.breakPoints.length - 1; i++) { - if (currMathsInput.allMap[currMathsInput.breakPoints[i]][0] < currMathsInput.cursorMap[currMathsInput.cursorPos][0] || (currMathsInput.allMap[currMathsInput.breakPoints[i]][0] == currMathsInput.cursorMap[currMathsInput.cursorPos][0] && currMathsInput.allMap[currMathsInput.breakPoints[i]][1] < currMathsInput.cursorMap[currMathsInput.cursorPos][1])) { - lowerBreakPoints.unshift(currMathsInput.allMap[currMathsInput.breakPoints[i]]); - } - } - if (lowerBreakPoints.length == 0) { - // cursor is on top line - if (shiftOn == true) { - if (currMathsInput.selected == true) { - currMathsInput.selectPos[1] = 0; - } else { - currMathsInput.selectPos = [currMathsInput.cursorPos,0]; - currMathsInput.selected = true; - } - setSelectPositions(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - currMathsInput.cursorPos = 0; - } - } else { - // get top point of current cursor position - var textLoc = currMathsInput.textLoc; - for (var i = 0; i < currMathsInput.cursorMap[currMathsInput.cursorPos].length; i++) { - textLoc = textLoc[currMathsInput.cursorMap[currMathsInput.cursorPos][i]]; - } - var pos = [textLoc.left,textLoc.top]; - // search through textLocs - var closestPos; - var closestDist; - for (var i = 0; i < currMathsInput.cursorMap.length; i++) { - // position must be less than lowerBreakPoints[0] - if (currMathsInput.cursorMap[i][0] < lowerBreakPoints[0][0] || (currMathsInput.cursorMap[i][0] == lowerBreakPoints[0][0] && currMathsInput.cursorMap[i][1] < lowerBreakPoints[0][1])) { - // if it is above the current line - - // position must not be less than lowerBreakPoints[1] - if (lowerBreakPoints.length > 1) { - if (currMathsInput.cursorMap[i][0] < lowerBreakPoints[1][0] || (currMathsInput.cursorMap[i][0] == lowerBreakPoints[1][0] && currMathsInput.cursorMap[i][1] < lowerBreakPoints[1][1])) continue; - } - - var loc = currMathsInput.textLoc; - for (var j = 0; j < currMathsInput.cursorMap[i].length; j++) { - loc = loc[currMathsInput.cursorMap[i][j]]; - } - if (typeof closestPos == 'undefined') { - closestPos = i; - closestDist = distancePointToLineSegment(pos,[loc.left,loc.top],[loc.left,loc.top+loc.height]); - } else { - var newDist = distancePointToLineSegment(pos,[loc.left,loc.top],[loc.left,loc.top+loc.height]); - if (newDist < closestDist) { - closestPos = i; - closestDist = newDist; - } - } - } - } - if (shiftOn == true) { - if (currMathsInput.selected == true) { - currMathsInput.selectPos[1] = closestPos; - } else { - currMathsInput.selectPos = [currMathsInput.cursorPos,closestPos]; - currMathsInput.selected = true; - } - setSelectPositions(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - currMathsInput.cursorPos = closestPos; - } else { - currMathsInput.cursorPos = closestPos; - mathsInputCursorCoords(); - } - } - } - break; - case 39 : // right arrow - currMathsInput.preText = ''; - currMathsInput.postText = ''; - if (e.getModifierState('Shift') == true && currMathsInput.cursorPos > 0) { - if (currMathsInput.selected == true) { - currMathsInput.selectPos[1] = [currMathsInput.cursorPos+1]; - setSelectPositions(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - currMathsInput.cursorPos++; - } else { - currMathsInput.selected = true; - currMathsInput.selectPos = [currMathsInput.cursorPos,currMathsInput.cursorPos+1]; - setSelectPositions(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - currMathsInput.cursorPos++; - } - } else if (currMathsInput.selected == true) { - removeSelectTags(); - mathsInputMapCursorPos(); - currMathsInput.cursorPos = Math.max(currMathsInput.selectPos[0],currMathsInput.selectPos[1]); - currMathsInput.selectPos = []; - mathsInputCursorCoords(); - currMathsInput.selected = false; - removeSelectTags(); - } else if (currMathsInput.cursorPos < currMathsInput.cursorMap.length - 1) { - currMathsInput.cursorPos++; - mathsInputCursorCoords(); - } else { - mathsInputTabNext(); - } - break; - case 40 : // down arrow - currMathsInput.preText = ''; - currMathsInput.postText = ''; - if (e.getModifierState('Shift') == true) { - if (currMathsInput.selected == false) { - currMathsInput.selectPos[0] = currMathsInput.cursorPos; - } - } else if (currMathsInput.selected == true) { - removeSelectTags(); - mathsInputMapCursorPos(); - currMathsInput.cursorPos = Math.max(currMathsInput.selectPos[0],currMathsInput.selectPos[1]); - currMathsInput.selectPos = []; - mathsInputCursorCoords(); - currMathsInput.selected = false; - removeSelectTags(); - } - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - // get the parent of the current string - var parent = currMathsInput.richText; - for (var aa = 0; aa < cursorPos.length - 3; aa++) {parent = parent[cursorPos[aa]]}; - if (parent[0] == 'frac' && cursorPos[cursorPos.length - 3] == 1) { - // move to the beginning of the denominator text - do { - currMathsInput.cursorPos++; - var cursorPos2 = currMathsInput.cursorMap[currMathsInput.cursorPos]; - // get the parent of the cursorPos - var parent2 = currMathsInput.richText; - for (var aa = 0; aa < cursorPos2.length - 3; aa++) {parent2 = parent2[cursorPos2[aa]]}; - } while ((parent2 !== parent) || (parent2 == parent && cursorPos2[cursorPos.length - 3] !== 2)); - // move to the end of the denominator text - do { - currMathsInput.cursorPos++; - var cursorPos2 = currMathsInput.cursorMap[currMathsInput.cursorPos]; - } while (cursorPos2.length >= cursorPos.length); - currMathsInput.cursorPos--; - mathsInputCursorCoords(); - } else { - var higherBreakPoints = []; - for (var i = 0; i < currMathsInput.breakPoints.length - 1; i++) { - if (currMathsInput.allMap[currMathsInput.breakPoints[i]][0] > currMathsInput.cursorMap[currMathsInput.cursorPos][0] || (currMathsInput.allMap[currMathsInput.breakPoints[i]][0] == currMathsInput.cursorMap[currMathsInput.cursorPos][0] && currMathsInput.allMap[currMathsInput.breakPoints[i]][1] > currMathsInput.cursorMap[currMathsInput.cursorPos][1])) { - higherBreakPoints.push(currMathsInput.allMap[currMathsInput.breakPoints[i]]); - } - } - if (higherBreakPoints.length == 0) { - // cursor is on bottom line - if (shiftOn == true) { - if (currMathsInput.selected == true) { - currMathsInput.selectPos[1] = currMathsInput.cursorMap.length - 1; - } else { - currMathsInput.selectPos = [currMathsInput.cursorPos,currMathsInput.cursorMap.length - 1]; - currMathsInput.selected = true; - } - setSelectPositions(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - currMathsInput.cursorPos = currMathsInput.cursorMap.length - 1; - } - } else { - // get bottom point of current cursor position - var textLoc = currMathsInput.textLoc; - for (var i = 0; i < currMathsInput.cursorMap[currMathsInput.cursorPos].length; i++) { - textLoc = textLoc[currMathsInput.cursorMap[currMathsInput.cursorPos][i]]; - } - var pos = [textLoc.left,textLoc.top+textLoc.height]; - // search through textLocs - var closestPos; - var closestDist; - for (var i = 0; i < currMathsInput.cursorMap.length; i++) { - // position must be more than higherBreakPoints[0] - if (currMathsInput.cursorMap[i][0] > higherBreakPoints[0][0] || (currMathsInput.cursorMap[i][0] == higherBreakPoints[0][0] && currMathsInput.cursorMap[i][1] > higherBreakPoints[0][1])) { - // if it is above the current line - - // position must not be less than higherBreakPoints[1] - if (higherBreakPoints.length > 1) { - if (currMathsInput.cursorMap[i][0] > higherBreakPoints[1][0] || (currMathsInput.cursorMap[i][0] == higherBreakPoints[1][0] && currMathsInput.cursorMap[i][1] > higherBreakPoints[1][1])) continue; - } - var loc = currMathsInput.textLoc; - for (var j = 0; j < currMathsInput.cursorMap[i].length; j++) { - loc = loc[currMathsInput.cursorMap[i][j]]; - } - if (typeof closestPos == 'undefined') { - closestPos = i; - closestDist = distancePointToLineSegment(pos,[loc.left,loc.top],[loc.left,loc.top+loc.height]); - } else { - var newDist = distancePointToLineSegment(pos,[loc.left,loc.top],[loc.left,loc.top+loc.height]); - if (newDist < closestDist) { - closestPos = i; - closestDist = newDist; - } - } - } - } - if (shiftOn == true) { - if (currMathsInput.selected == true) { - currMathsInput.selectPos[1] = closestPos; - } else { - currMathsInput.selectPos = [currMathsInput.cursorPos,closestPos]; - currMathsInput.selected = true; - } - setSelectPositions(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - currMathsInput.cursorPos = closestPos; - } else { - currMathsInput.cursorPos = closestPos; - mathsInputCursorCoords(); - } - } - - } - break; - case 8 : // backspace key pressed - currMathsInput.preText = ''; - currMathsInput.postText = ''; - if (currMathsInput.selected == true) { - currMathsInput.cursorPos = Math.min(currMathsInput.selectPos[0],currMathsInput.selectPos[1]); - currMathsInput.selPos = []; - currMathsInput.selected = false; - deleteSelected(); - removeSelectTags(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - mathsInputCursorCoords(); - } else if (currMathsInput.cursorPos > 0) { - removeSelectTags(); - // get the relevant string from currMathsInput.richText - // ie. currMathsInput.richText[cursorPos[0]][cursorPos[1]]...[cursorPos[n]] - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - var pos = cursorPos[cursorPos.length - 1]; - pos = adjustForBreakPoints(pos); - - var text = currMathsInput.richText; - for (var i = 0; i < cursorPos.length - 1; i++) {text = text[cursorPos[i]]}; - - var parent; - if (cursorPos.length > 1) { - parent = currMathsInput.richText; - for (var i = 0; i < cursorPos.length - 2; i++) {parent = parent[cursorPos[i]]}; - } - var grandParent; - if (cursorPos.length > 2) { - grandParent = currMathsInput.richText; - for (var i = 0; i < cursorPos.length - 3; i++) {grandParent = grandParent[cursorPos[i]]}; - } - - if (text !== '') { - if (pos !== 0) { - //console.clear(); - //console.log(1,text,pos,text.slice(pos-1)); - if (text.slice(pos-6).indexOf('<
>') == 0) { - text = text.slice(0, pos-6) + text.slice(pos); - } else { - text = text.slice(0, pos-1) + text.slice(pos); - } - //console.log(2,text); - // replace the string - var evalString = 'currMathsInput.richText' - for (var aa = 0; aa < cursorPos.length - 1; aa++) { - // ugly string creation apprach in order to use eval() - evalString += '[' + cursorPos[aa] + ']'; - } - eval(evalString + ' = text;'); - } - } else { - if (parent.length == 1) { // ie. empty string is only sub-element - var elemsOneParam = ['sqrt', 'pow', 'power', 'subs', 'subscript', 'sin', 'cos', 'tan', 'sin-1', 'cos-1', 'tan-1', 'log', 'ln', 'abs', 'exp', 'sigma1', 'int1', 'vectorArrow', 'bar', 'hat', 'recurring']; - var elemsTwoParams = ['root', 'frac', 'logBase', 'colVector2d', 'lim']; - var elemsThreeParams = ['sigma2', 'int2', 'colVector3d', 'mixedNum']; - if (elemsOneParam.indexOf(grandParent[0]) > -1 || (elemsTwoParams.indexOf(grandParent[0]) > -1 && cursorPos[cursorPos.length - 3] == 1) || (elemsThreeParams.indexOf(grandParent[0]) > -1 && cursorPos[cursorPos.length - 3] == 1)) { // conditions to delete - // replace grandParent with ""; - var evalString = 'currMathsInput.richText' - for (var i = 0; i < cursorPos.length - 3; i++) { - // ugly string creation apprach in order to use eval() - evalString += '[' + cursorPos[i] + ']'; - } - eval(evalString + ' = "";'); - } - } - } - //console.log(JSON.stringify(currMathsInput.richText)); - mathsInputMapCursorPos(); - currMathsInput.cursorPos--; - mathsInputCursorCoords(); - } - break; - case 46 : // delete key - currMathsInput.preText = ''; - currMathsInput.postText = ''; - if (currMathsInput.selected == true) { - currMathsInput.cursorPos = Math.min(currMathsInput.selectPos[0],currMathsInput.selectPos[1]); - currMathsInput.selPos = []; - currMathsInput.selected = false; - deleteSelected(); - removeSelectTags(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - mathsInputCursorCoords(); - } else if (currMathsInput.cursorPos < currMathsInput.cursorMap.length - 1) { - // get the relevant string from currMathsInput.richText - // ie. currMathsInput.richText[cursorPos[0]][cursorPos[1]]...[cursorPos[n]] - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - var pos = cursorPos[cursorPos.length - 1]; - pos = adjustForBreakPoints(pos); - - var text = currMathsInput.richText; - for (var i = 0; i < cursorPos.length - 1; i++) {text = text[cursorPos[i]]}; - - if (cursorPos[cursorPos.length - 1] !== text.length) { - if (text.slice(pos).indexOf('<
>') == 0) { - text = text.slice(0,pos) + text.slice(pos+6); - } else if (text.slice(pos).indexOf('<<') == 0) { - //skip forward to end of tags - var text2 = text.slice(pos); - var endFound = false; - var charCount = 0; - do { - var c = text2.indexOf('>>') + 2; - charCount += c; - var text2 = text2.slice(c); - if (text2.indexOf('<<') !== 0) { - endFound = true; - } - } while (endFound == false); - pos += charCount; - text = text.slice(0,pos) + text.slice(pos+1); - } else { - text = text.slice(0,pos) + text.slice(pos+1); - } - // replace the string - var evalString = 'currMathsInput.richText' - for (var i = 0; i < cursorPos.length - 1; i++) { - // ugly string creation apprach in order to use eval() - evalString += '[' + cursorPos[i] + ']'; - } - eval(evalString + ' = text;'); - mathsInputMapCursorPos(); - mathsInputCursorCoords(); - } - } - break; - case 9 : // tab key pressed - if (typeof draw !== 'undefined' && draw.drawMode == 'textEdit') { - if (e.getModifierState('Control')) { - mathsInputTab(10); - } else if (e.getModifierState('Shift')) { - mathsInputTab(5); - } else { - mathsInputTab(); - } - } else { - mathsInputTabNext(); - } - break; - case 13 : // enter key pressed - if (currMathsInput.maxLines > 1 || (typeof draw !== 'undefined' && draw.drawMode == 'textEdit')) { - if (currMathsInput.selected == true) { - currMathsInput.cursorPos = Math.min(currMathsInput.selectPos[0],currMathsInput.selectPos[1]); - currMathsInput.selPos = []; - currMathsInput.selected = false; - deleteSelected(); - removeSelectTags(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - mathsInputCursorCoords(); - } - mathsInputNewLine(); - } else { - endMathsInput(e); - } - break; - case 27 : // escape key pressed - endMathsInput(e); - break; - /*case 16 : //shift key pressed - shiftOn = true; - window.addEventListener('keyup', shiftKeyUp, false); - break;*/ - default : - - // need to protect against << or >> being entered - - if (currMathsInput.text[0].length >= currMathsInput.maxChars) {break}; - if (e.getModifierState('Shift') == true && charCode == 54/* && currMathsInput.cursorMap[currMathsInput.cursorPos].length == 2*/) { // if hat symbol is used and current text element is a text string - mathsInputPow(); - break; - } - if (keysToIgnore.indexOf(charCode) == -1) { - - if (currMathsInput.selected == true) { - currMathsInput.cursorPos = Math.min(currMathsInput.selectPos[0],currMathsInput.selectPos[1]); - currMathsInput.selPos = []; - currMathsInput.selected = false; - deleteSelected(); - removeSelectTags(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - mathsInputCursorCoords(); - } - - var caps = false; - if (e.getModifierState('Shift') || e.getModifierState('CapsLock')) caps = true - - for (var ii = 0; ii < charMap.length; ii++) { - if (charCode == charMap[ii][0]) { - if (caps) { - charCode = charMap[ii][2]; - } else { - charCode = charMap[ii][1]; - } - } - } - // if it is a letter key and shift is not pressed, use lower case instead of upper case - if (!caps && charCode >= 65 && charCode <= 90) charCode += 32; - var keyValue = String.fromCharCode(charCode); - - // get the relevant string from currMathsInput.richText - // ie. currMathsInput.richText[cursorPos[0]][cursorPos[1]]...[cursorPos[n]] - //console.log(currMathsInput.cursorMap,currMathsInput.cursorPos,currMathsInput.cursorMap[currMathsInput.cursorPos]); - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - - /* - console.log('currMathsInput.cursorMap:',JSON.stringify(currMathsInput.cursorMap,null,4),currMathsInput.cursorMap.length-1); - console.log('currMathsInput.cursorPos:',JSON.stringify(currMathsInput.cursorPos,null,4)); - console.log('currMathsInput.cursorMap[currMathsInput.cursorPos]:',JSON.stringify(currMathsInput.cursorMap[currMathsInput.cursorPos],null,4)); - console.log('currMathsInput.richText[0]:',JSON.stringify(currMathsInput.richText[0],null,4),currMathsInput.richText[0].length-1); - console.log('cursorPos:',JSON.stringify(cursorPos,null,4)); - */ - - var text = currMathsInput.richText; - for (var i = 0; i < cursorPos.length - 1; i++) { - text = text[cursorPos[i]]; - } - - var slicePos = cursorPos[cursorPos.length - 1]; - slicePos = adjustForBreakPoints(slicePos); - - /*var prev = 0; - var breakPoints = currMathsInput.breakPoints; - for (var b = 0; b < breakPoints.length; b++) { - prev = breakPoints[b]; - }*/ - - //console.log(text,slicePos); - - slicePos = mathsInputAvoidTagSplit(text,slicePos); - /* this section replaced by the function above - // check that a tag is not being split - if so adjust slicePos - var leftText = text.slice(0,slicePos); - var rightText = text.slice(slicePos); - var tagLeft = false; - var tagLeftCount = 0; - for (var i = 0; i < leftText.length; i++) { - tagLeftCount++; - //console.log('left '+i+':',leftText.slice(leftText.length - i)); - if (leftText.slice(leftText.length - i).indexOf('>>') == 0) break; - if (leftText.slice(leftText.length - i).indexOf('<<') == 0) { - tagLeft = true; - break; - } - } - var tagRight = false; - var tagRightCount = 0; - for (var j = 0; j < rightText.length; j++) { - tagRightCount++; - //console.log('right '+j+':',rightText.slice(j)); - if (rightText.slice(j).indexOf('<<') == 0) break; - if (rightText.slice(j).indexOf('>>') == 0) { - tagRight = true; - break; - } - } - //console.log(tagLeft,tagRight,tagLeftCount,tagRightCount); - if (tagLeft == true && tagRight == true) { - if (tagLeftCount <= tagRightCount) { - slicePos -= tagLeftCount; - } else { - slicePos += tagRightCount; - } - } - // test if '<',slicePos,'<' or '>',slicePos,'>' - if (leftText.slice(-1) == '<' && rightText.slice(0,1) == '<' && rightText.slice(0,2) !== '<<') slicePos--; - if (leftText.slice(-1) == '>' && leftText.slice(-2) !== '>>' && rightText.slice(0,1) == '>') slicePos++;*/ - - if (un(currMathsInput.preText) || currMathsInput.preText == null) { - var pre = ""; - } else { - var pre = currMathsInput.preText; - } - if (un(currMathsInput.postText) || currMathsInput.postText == null) { - var post = ""; - } else { - var post = currMathsInput.postText; - } - - text = text.slice(0, slicePos) + pre + keyValue + post + text.slice(slicePos); - - // replace the string - var evalString = 'currMathsInput.richText' - for (var i = 0; i < cursorPos.length - 1; i++) { - // ugly string creation apprach in order to use eval() - evalString += '[' + cursorPos[i] + ']'; - } - eval(evalString + ' = text;'); - - //logText(); - mathsInputMapCursorPos(); - - // set the last number of cursorMap[cursorPos+1] to be one more than cursorMap[cursorPos] - //currMathsInput.cursorMap[currMathsInput.cursorPos + 1][currMathsInput.cursorMap[currMathsInput.cursorPos + 1].length - 1] = currMathsInput.cursorMap[currMathsInput.cursorPos][currMathsInput.cursorMap[currMathsInput.cursorPos].length - 1] + 1; - - currMathsInput.cursorPos += 1; - mathsInputCursorCoords(); - currMathsInput.preText = ''; - currMathsInput.postText = ''; - //logText(); - } - } - } -} -function softKeyMathsInput(e) { - //console.log(inputState); - if (inputState == true) { - /* - if (mathsInputDoubleInput == true) { - return; - } else { - mathsInputDoubleInput = true; - setTimeout(function() { - mathsInputDoubleInput = false; - }, 250); - } - */ - var keyNum; - var keyValue; - if (keyboard[pageIndex]) { - keyNum = key1[pageIndex].indexOf(e.target); - keyValue = key1Data[pageIndex][keyNum][6]; - } - //console.log(keyValue); - if (keyValue == 'delete') { // if it's the delete button - currMathsInput.preText = ''; - currMathsInput.postText = ''; - if (currMathsInput.selected == true) { - currMathsInput.cursorPos = Math.min(currMathsInput.selectPos[0],currMathsInput.selectPos[1]); - currMathsInput.selPos = []; - currMathsInput.selected = false; - deleteSelected(); - removeSelectTags(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - mathsInputCursorCoords(); - } else if (currMathsInput.cursorPos > 0) { - // get the relevant string from currMathsInput.richText - // ie. currMathsInput.richText[cursorPos[0]][cursorPos[1]]...[cursorPos[n]] - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - //console.log(cursorPos); - var pos = cursorPos[cursorPos.length - 1]; - //console.log(pos); - pos = adjustForBreakPoints(pos); - //console.log(pos); - - var text = currMathsInput.richText; - for (var i = 0; i < cursorPos.length - 1; i++) {text = text[cursorPos[i]]}; - - var parent; - if (cursorPos.length > 1) { - parent = currMathsInput.richText; - for (var i = 0; i < cursorPos.length - 2; i++) {parent = parent[cursorPos[i]]}; - } - var grandParent; - if (cursorPos.length > 2) { - grandParent = currMathsInput.richText; - for (var i = 0; i < cursorPos.length - 3; i++) {grandParent = grandParent[cursorPos[i]]}; - } - - if (text !== '') { - if (pos !== 0) { - //console.log(1,text,text.length,pos,text.slice(0, pos-1) + text.slice(pos)); - if (text.slice(pos-6).indexOf('<
>') == 0) { - text = text.slice(0, pos-6) + text.slice(pos); - } else { - text = text.slice(0, pos-1) + text.slice(pos); - } - //console.log(2,text); - // replace the string - var evalString = 'currMathsInput.richText' - for (var aa = 0; aa < cursorPos.length - 1; aa++) { - // ugly string creation apprach in order to use eval() - evalString += '[' + cursorPos[aa] + ']'; - } - eval(evalString + ' = text;'); - } - } else { - if (parent.length == 1) { // ie. empty string is only sub-element - var elemsOneParam = ['sqrt', 'pow', 'power', 'subs', 'subscript', 'sin', 'cos', 'tan', 'sin-1', 'cos-1', 'tan-1', 'log', 'ln', 'abs', 'exp', 'sigma1', 'int1', 'vectorArrow', 'bar', 'hat', 'recurring']; - var elemsTwoParams = ['root', 'frac', 'logBase', 'colVector2d', 'lim']; - var elemsThreeParams = ['sigma2', 'int2', 'colVector3d', 'mixedNum']; - if (elemsOneParam.indexOf(grandParent[0]) > -1 || (elemsTwoParams.indexOf(grandParent[0]) > -1 && cursorPos[cursorPos.length - 3] == 1) || (elemsThreeParams.indexOf(grandParent[0]) > -1 && cursorPos[cursorPos.length - 3] == 1)) { // conditions to delete elements - // replace grandParent with ""; - var evalString = 'currMathsInput.richText' - for (var i = 0; i < cursorPos.length - 3; i++) { - // ugly string creation apprach in order to use eval() - evalString += '[' + cursorPos[i] + ']'; - } - eval(evalString + ' = "";'); - } - } - } - mathsInputMapCursorPos(); - currMathsInput.cursorPos--; - mathsInputCursorCoords(); - } - } else { - // type text char - if (currMathsInput.text[0].length >= currMathsInput.maxChars) {return}; - - if (currMathsInput.selected == true) { - currMathsInput.cursorPos = Math.min(currMathsInput.selectPos[0],currMathsInput.selectPos[1]); - currMathsInput.selPos = []; - currMathsInput.selected = false; - deleteSelected(); - removeSelectTags(); - drawMathsInputText(currMathsInput); - mathsInputMapCursorPos(); - mathsInputCursorCoords(); - } - - // get the relevant string from currMathsInput.richText - // ie. currMathsInput.richText[cursorPos[0]][cursorPos[1]]...[cursorPos[n]] - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - - var text = currMathsInput.richText; - for (var aa = 0; aa < cursorPos.length - 1; aa++) { - text = text[cursorPos[aa]]; - } - - /* - // test if sin, cos, tan, ln or log have been written: - if (keyValue == 'n' && text.length > 1 && text.slice(cursorPos[cursorPos.length - 1] - 2, cursorPos[cursorPos.length - 1]) == 'si') { - // get cursorPos - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - // get parent - var parent = currMathsInput.richText; - for (var aa = 0; aa < cursorPos.length - 1; aa++) {parent = parent[cursorPos[aa]]}; - // get position of cursor in parent string - var pos = cursorPos[cursorPos.length - 1]; - var parentPos = cursorPos[cursorPos.length - 2]; - - var evalString = 'currMathsInput.richText' - for (var aa = 0; aa < cursorPos.length - 2; aa++) { - // ugly string creation apprach in order to use eval() - evalString += '[' + cursorPos[aa] + ']'; - } - eval(evalString + ".splice(parentPos, 1, parent.slice(0, pos - 2), ['sin', ['']], parent.slice(pos));"); - mathsInputMapCursorPos(); - currMathsInput.cursorPos--; - mathsInputCursorCoords(); - return; - } - if (keyValue == 's' && text.length > 1 && text.slice(cursorPos[cursorPos.length - 1] - 2, cursorPos[cursorPos.length - 1]) == 'co') { - // get cursorPos - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - // get parent - var parent = currMathsInput.richText; - for (var aa = 0; aa < cursorPos.length - 1; aa++) {parent = parent[cursorPos[aa]]}; - // get position of cursor in parent string - var pos = cursorPos[cursorPos.length - 1]; - var parentPos = cursorPos[cursorPos.length - 2]; - - var evalString = 'currMathsInput.richText' - for (var aa = 0; aa < cursorPos.length - 2; aa++) { - // ugly string creation apprach in order to use eval() - evalString += '[' + cursorPos[aa] + ']'; - } - eval(evalString + ".splice(parentPos, 1, parent.slice(0, pos - 2), ['cos', ['']], parent.slice(pos));"); - mathsInputMapCursorPos(); - currMathsInput.cursorPos--; - mathsInputCursorCoords(); - return; - } - if (keyValue == 'n' && text.length > 1 && text.slice(cursorPos[cursorPos.length - 1] - 2, cursorPos[cursorPos.length - 1]) == 'ta') { - console.log('tan'); - // get cursorPos - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - // get parent - var parent = currMathsInput.richText; - for (var aa = 0; aa < cursorPos.length - 1; aa++) {parent = parent[cursorPos[aa]]}; - // get position of cursor in parent string - var pos = cursorPos[cursorPos.length - 1]; - var parentPos = cursorPos[cursorPos.length - 2]; - - var evalString = 'currMathsInput.richText' - for (var aa = 0; aa < cursorPos.length - 2; aa++) { - // ugly string creation apprach in order to use eval() - evalString += '[' + cursorPos[aa] + ']'; - } - eval(evalString + ".splice(parentPos, 1, parent.slice(0, pos - 2), ['tan', ['']], parent.slice(pos));"); - mathsInputMapCursorPos(); - currMathsInput.cursorPos--; - mathsInputCursorCoords(); - return; - } - if (keyValue == 'n' && text.length > 0 && text.slice(cursorPos[cursorPos.length - 1] - 1, cursorPos[cursorPos.length - 1]) == 'l') { - console.log('ln'); - // get cursorPos - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - // get parent - var parent = currMathsInput.richText; - for (var aa = 0; aa < cursorPos.length - 1; aa++) {parent = parent[cursorPos[aa]]}; - // get position of cursor in parent string - var pos = cursorPos[cursorPos.length - 1]; - var parentPos = cursorPos[cursorPos.length - 2]; - - var evalString = 'currMathsInput.richText' - for (var aa = 0; aa < cursorPos.length - 2; aa++) { - // ugly string creation apprach in order to use eval() - evalString += '[' + cursorPos[aa] + ']'; - } - eval(evalString + ".splice(parentPos, 1, parent.slice(0, pos - 1), ['ln', ['']], parent.slice(pos));"); - mathsInputMapCursorPos(); - mathsInputCursorCoords(); - return; - } - if (keyValue == 'g' && text.length > 1 && text.slice(cursorPos[cursorPos.length - 1] - 2, cursorPos[cursorPos.length - 1]) == 'lo') { - console.log('log'); - // get cursorPos - var cursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos]; - // get parent - var parent = currMathsInput.richText; - for (var aa = 0; aa < cursorPos.length - 1; aa++) {parent = parent[cursorPos[aa]]}; - // get position of cursor in parent string - var pos = cursorPos[cursorPos.length - 1]; - var parentPos = cursorPos[cursorPos.length - 2]; - - var evalString = 'currMathsInput.richText' - for (var aa = 0; aa < cursorPos.length - 2; aa++) { - // ugly string creation apprach in order to use eval() - evalString += '[' + cursorPos[aa] + ']'; - } - eval(evalString + ".splice(parentPos, 1, parent.slice(0, pos - 2), ['log', ['']], parent.slice(pos));"); - mathsInputMapCursorPos(); - currMathsInput.cursorPos--; - mathsInputCursorCoords(); - return; - } - */ - - var slicePos = cursorPos[cursorPos.length - 1]; - slicePos = adjustForBreakPoints(slicePos); - //console.log(slicePos); - - slicePos = mathsInputAvoidTagSplit(text,slicePos); - /* the section below is replaced by the function above - // check that a tag is not being split - if so adjust slicePos - var leftText = text.slice(0,slicePos); - var rightText = text.slice(slicePos); - var tagLeft = false; - var tagLeftCount = 0; - for (var i = 0; i < leftText.length; i++) { - tagLeftCount++; - //console.log('left '+i+':',leftText.slice(leftText.length - i)); - if (leftText.slice(leftText.length - i).indexOf('>>') == 0) break; - if (leftText.slice(leftText.length - i).indexOf('<<') == 0) { - tagLeft = true; - break; - } - } - var tagRight = false; - var tagRightCount = 0; - for (var j = 0; j < rightText.length; j++) { - tagRightCount++; - //console.log('right '+j+':',rightText.slice(j)); - if (rightText.slice(j).indexOf('<<') == 0) break; - if (rightText.slice(j).indexOf('>>') == 0) { - tagRight = true; - break; - } - } - //console.log(tagLeft,tagRight,tagLeftCount,tagRightCount); - if (tagLeft == true && tagRight == true) { - if (tagLeftCount <= tagRightCount) { - slicePos -= tagLeftCount; - } else { - slicePos += tagRightCount; - } - } - // test if '<',slicePos,'<' or '>',slicePos,'>' - if (leftText.slice(-1) == '<' && rightText.slice(0,1) == '<' && rightText.slice(0,2) !== '<<') slicePos--; - if (leftText.slice(-1) == '>' && leftText.slice(-2) !== '>>' && rightText.slice(0,1) == '>') slicePos++;*/ - - - if (un(currMathsInput.preText) || currMathsInput.preText == null) { - var pre = ""; - } else { - var pre = currMathsInput.preText; - } - if (un(currMathsInput.postText) || currMathsInput.postText == null) { - var post = ""; - } else { - var post = currMathsInput.postText; - } - - text = text.slice(0, slicePos) + pre + keyValue + post + text.slice(slicePos); - - // replace the string - var evalString = 'currMathsInput.richText' - for (var i = 0; i < cursorPos.length - 1; i++) { - // ugly string creation approach in order to use eval() - evalString += '[' + cursorPos[i] + ']'; - } - eval(evalString + ' = text;'); - - // if followed by a power, test if a baseSpacer is now required - if (cursorPos[cursorPos.length - 1] + 1 == text.length && typeof currMathsInput.cursorMap[currMathsInput.cursorPos + 1] !== 'undefined') { - // get the next element after the parent - var nextCursorPos = currMathsInput.cursorMap[currMathsInput.cursorPos + 1]; - var nextElem = currMathsInput.richText; - for (var aa = 0; aa < nextCursorPos.length - 3; aa++) {nextElem = nextElem[nextCursorPos[aa]]}; - if (nextElem[0] == 'power' || nextElem[0] == 'subs') { - var baseSpacer = true; - if (/[a-zA-Z0-9)]/g.test(keyValue) == true) baseSpacer = false - var evalString = 'currMathsInput.richText' - for (var aa = 0; aa < nextCursorPos.length - 3; aa++) { - // ugly string creation apprach in order to use eval() - evalString += '[' + nextCursorPos[aa] + ']'; - } - eval(evalString + "[1] = " + baseSpacer + ";"); - } - } - - mathsInputMapCursorPos(); - currMathsInput.cursorPos += 1; - mathsInputCursorCoords(); - currMathsInput.preText = ''; - currMathsInput.postText = ''; - } - } -} - -//var date = new Date(); -//var prevMathsInputTime = date.getTime(); -var mathsInputDoubleInput = false; - -/*function setMathsInputBackColor(input,color) { - input.backColor = color; - drawMathsInputText(input); -}*/ -function measureMathsInputText(input) { - var leftPoint = 10; - if (input.textAlign == 'center') {leftPoint = 0.5 * input.data[2]}; - if (typeof input.richText[input.richText.length - 1] !== 'string') {input.richText.push('')}; - return drawMathsText(input.ctx, input.richText, input.fontSize, leftPoint, 0.5 * input.data[3], input.algText, input.textLoc, input.textAlign, 'middle', input.textColor, 'measure'); -} -function drawMathsInputText(input,ctxLocal,sf,useRelPos) { - if (typeof sf == 'undefined') sf = 1; - if (typeof ctxLocal == 'undefined') { - input.ctx.clearRect(0,0,input.data[102],input.data[103]); - var ctx = input.ctx; - var ownCanvas = true; - } else { - var ctx = ctxLocal; // will draw to a different canvas - var ownCanvas = false; - } - if (typeof input.richText[input.richText.length-1] !== 'string') {input.richText.push('')}; - var leftPoint = 10*sf; - var topPoint = 0; - - if (typeof input.varSize == 'object') { - if (input.textAlign == 'left') { - leftPoint = input.varSize.padding*sf; - if (typeof input.varSize.padding !== 'number') leftPoint = 10*sf; - } else if (input.textAlign == 'center') { - leftPoint = 0; - } else if (input.textAlign == 'right') { - leftPoint = 0 - input.varSize.padding*sf; - if (typeof input.varSize.padding !== 'number') leftPoint = -10*sf; - } - var minTightWidth = input.varSize.minWidth*sf || 50*sf; - var minTightHeight = input.varSize.minHeight*sf || 50*sf; - var padding = input.varSize.padding*sf; - var maxWidth = input.varSize.maxWidth*sf || input.data[102]*sf; - var maxHeight = input.varSize.maxHeight*sf || input.data[103]*sf; - } else { - if (input.textAlign == 'left') { - leftPoint = 10*sf; - } else if (input.textAlign == 'center') { - leftPoint = 0; - } else if (input.textAlign == 'right') { - - } - var minTightWidth = 50*sf; - var minTightHeight = 50*sf; - var padding = 0.01*sf; - var maxWidth = input.data[102]*sf; - var maxHeight = input.data[103]*sf; - } - - if (input.border == true) { - if (typeof input.varSize == 'object') { - var border = { - type:'tight', - color:input.backColor, - borderColor:input.borderColor, - borderWidth:input.borderWidth*sf, - dash:input.borderDash, - radius:input.borderRadius*sf || input.radius*sf || 0 - } - } else { - var radius = input.borderRadius*sf || input.radius*sf || 0; - var borderLeft = input.borderWidth*sf/2; - var borderTop = input.borderWidth*sf/2; - if (ownCanvas == false) { - borderLeft += input.data[100]*sf; - borderTop += input.data[101]*sf; - } - roundedRect(ctx,borderLeft,borderTop,input.data[102]*sf-input.borderWidth*sf,input.data[103]*sf-input.borderWidth*sf,radius,input.borderWidth*sf,input.borderColor,input.backColor,input.borderDash); - var border = {type:'none'}; - } - } else { - var border = {type:'none'}; - } - - if (ownCanvas == false) { - if (!isNaN(input.data[100])) { - leftPoint += input.data[100]*sf; - topPoint += input.data[101]*sf; - } else { - leftPoint += input.data[0]*sf; - topPoint += input.data[1]*sf; - } - if (boolean(useRelPos,true) == true && typeof draw !== 'undefined' && typeof draw !== 'undefined' && typeof draw.drawRelPos !== 'undefined') { - leftPoint -= draw.drawRelPos[0]*sf; - topPoint -= draw.drawRelPos[1]*sf; - } - } - - var lineSpacingFactor = input.lineSpacingFactor || 1.2; - var lineSpacingStyle = input.lineSpacingStyle || 'variable'; - - var drawText = text({ - context:ctx, - textArray:input.richText, - left:leftPoint, - top:topPoint, - width:maxWidth, - height:maxHeight, - allowSpaces:true, - textAlign:input.textAlign, - vertAlign:input.vertAlign, - minTightWidth:minTightWidth, - minTightHeight:minTightHeight, - padding:padding, - box:border, - sf:sf, - lineSpacingFactor:lineSpacingFactor, - spacingStyle:lineSpacingStyle - }); - - if (ownCanvas == true) { - input.textLoc = drawText.textLoc; - input.breakPoints = drawText.breakPoints; - input.tightRect = drawText.tightRect; - input.totalTextWidth = drawText.totalTextWidth; - input.maxWordWidth = drawText.maxWordWidth; - } - - /*if (typeof input.drawPath == 'object') { - if (input.tightRect[3] > input.drawPath.obj[0].height) { - input.drawPath.obj[0].height = input.tightRect[3]; - input.varSize.maxHeight = input.tightRect[3]; - updateBorder(input.drawPath); - drawCanvasPaths(); - } - }*/ - - if (typeof input.varSize == 'object' && ownCanvas == true) { - // resize cursor canvas - if (typeof input.tightRect == 'object') { - input.cursorData[100] = input.data[100] + input.tightRect[0]; - input.cursorData[101] = input.data[101] + input.tightRect[1]; - input.cursorData[102] = input.tightRect[2]; - input.cursorData[103] = input.tightRect[3]; - } else { - input.cursorData[100] = input.data[100]; - input.cursorData[101] = input.data[101]; - input.cursorData[102] = input.data[102]; - input.cursorData[103] = input.data[103]; - } - input.cursorCanvas.width = input.cursorData[102]; - input.cursorCanvas.height = input.cursorData[103]; - resizeCanvas(input.cursorCanvas,input.cursorData[100],input.cursorData[101],input.cursorData[102],input.cursorData[103]); - } - - if (!un(draw) && draw.drawMode == 'textEdit') { - var obj = sel(); - if (obj.type == 'text' && obj.mathsInput.canvas == input.canvas) { - if (input.cursorData[103] > obj.height || input.cursorData[102] > obj.width) { - for (var i = 0; i < draw.path.length; i++) { - if (draw.path[i].selected == true) { - if (input.cursorData[103] > obj.height) obj.height = input.cursorData[103]; - if (input.cursorData[102] > obj.width) obj.width = input.cursorData[102]; - updateBorder(draw.path[i]); - } - } - } - } - calcCursorPositions(); - drawSelectCanvas(); - } - //console.clear(); - //if (currMathsInput.id == 1) console.log(currMathsInput.id,JSON.stringify(currMathsInput.richText)); -} -function mathsInputAddChar(mInput,char) { - if (un(mInput)) mInput = currMathsInput; - // get last position - var cursorPos = mInput.cursorMap[mInput.cursorMap.length-1]; - var loc = mInput.textLoc; - for (var aa = 0 ; aa < cursorPos.length; aa++) { - loc = loc[cursorPos[aa]]; - } - //console.log(cursorPos); - - var font,fontSize,color,bold,italic; - arrayHandler(mInput.richText); - var newLoc = drawMathsText(mInput.ctx,char,fontSize,loc.left,loc.top+0.5*loc.height,false,[],'left','middle',color,'draw','none',bold,italic,font,false,1).textLoc; - - var evalString = ''; - for (var aa = 0 ; aa < cursorPos.length-1; aa++) { - evalString += '['+cursorPos[aa]+']'; - } - eval('mInput.richText'+evalString+'=mInput.richText'+evalString+'+char'); - eval('mInput.textLoc'+evalString+'.push(newLoc[0][1])'); - cursorPos[cursorPos.length-1]++; - mInput.cursorMap.push(cursorPos); - - //console.log(mInput); - - function markupTag(tag) { - if (tag.indexOf('< -1) bold = true; - if (tag.indexOf('false') > -1) bold = false; - } else if (tag.indexOf('< -1) italic = true; - if (tag.indexOf('false') > -1) italic = false; - } - } - function arrayHandler(arr) { - //console.log(JSON.stringify(arr)); - for (var i = 0; i < arr.length; i++) { - if (typeof arr[i] == 'object') { - arrayHandler(arr[i]); - } else if (typeof arr[i] == 'string') { - var splitText = splitMarkup(arr[i]); - for (var splitElem = 0; splitElem < splitText.length; splitElem++) { - if (splitText[splitElem].indexOf('<<') == 0 && splitText[splitElem].indexOf('<
>') !== 0) { - markupTag(splitText[splitElem],true); - } - } - } - } - } -} -function createJsString (angleMode) { - if (typeof angleMode == 'undefined') { - angleMode = currMathsInput.angleMode || 'deg'; - } - - var depth = 0; - var jsArray = ['']; - var js = ''; - var algArray = ['']; - var alg = ''; - var exceptions = ['Math.pow','Math.sqrt','Math.PI','Math.sin','Math.cos','Math.tan','Math.asin','Math.acos','Math.atan','Math.e','Math.log','Math.abs','sin','cos','tan']; - var position = [0]; - - for (var p = 0; p < currMathsInput.richText.length; p++) { - //console.log('Before ' + p + ' base element(s):', jsArray); - subJS(currMathsInput.richText[p],true); - position[depth]++; - //console.log('After ' + p + ' base elements:', jsArray); - } - - js = jsArray[0]; - alg = algArray[0]; - //console.log(js); - - function removeAllTagsFromString(str) { - for (var char = str.length-1; char > -1; char--) { - if (str.slice(char).indexOf('>>') == 0 && str.slice(char-1).indexOf('>>>') !== 0) { - for (var char2 = char-2; char2 > -1; char2--) { - if (str.slice(char2).indexOf('<<') == 0) { - str = str.slice(0,char2) + str.slice(char+2); - char = char2; - break; - } - } - } - } - return str; - } - - function subJS(elem, addMultIfNecc) { - if (typeof addMultIfNecc !== 'boolean') addMultIfNecc = true; - //console.log('subJS', elem); - if (typeof elem == 'string') { - //console.log('string'); - var subText = replaceAll(elem, ' ', ''); // remove white space - subText = removeAllTagsFromString(subText); - - subText = subText.replace(/\u00D7/g, '*'); // replace multiplications signs with * - subText = subText.replace(/\u00F7/g, '/'); // replace division signs with / - subText = subText.replace(/\u2264/g, '<='); // replace signs with <= - subText = subText.replace(/\u2265/g, '>='); // replace signs with >= - for (var c = 0; c < subText.length - 2; c++) { - if (subText.slice(c).indexOf('sin') == 0 || subText.slice(c).indexOf('cos') == 0 || subText.slice(c).indexOf('tan') == 0) { - if (subText.slice(c).indexOf('(') == 3) { - if (angleMode == 'rad') { - subText = subText.slice(0,c)+'Math.'+subText.slice(c); - c += 5; - } else { - subText = subText.slice(0,c)+'Math.'+subText.slice(c,c+4)+'(Math.PI/180)*'+subText.slice(c+4); - c += 19; - } - } - } - } - subText = timesBeforeLetters(subText); - // if following frac or power, add * if necessary - if (addMultIfNecc == true && jsArray[depth] !== '' && elem !== '' && /[ \+\-\=\u00D7\u00F7\u2264\u2265\<\>\])]/.test(elem.charAt(0)) == false) subText = '*' + subText; - jsArray[depth] += subText; - algArray[depth] += subText; - return; - } else if (elem[0] == 'frac') { - //console.log('frac'); - var subText = ''; - var subText2 = ''; - // if not proceeded by an operator, put a times sign in - if (jsArray[depth] !== '' && /[\+\-\u00D7\u00F7\*\/\=\[(]/.test(jsArray[depth].slice(-1)) == false) subText += "*"; - depth++; - position.push(0); - jsArray[depth] = ''; - subJS(elem[1], false); - jsArray[depth] = replaceAll(jsArray[depth], ' ', ''); // remove white space - subText += '((' + jsArray[depth] + ')/'; - subText2 += 'frac(' + jsArray[depth] + ','; - jsArray[depth] = ''; - subJS(elem[2], false); - jsArray[depth] = replaceAll(jsArray[depth], ' ', ''); // remove white space - subText += '(' + jsArray[depth] + '))'; - subText2 += jsArray[depth] + ')'; - jsArray[depth] = ''; - depth--; - position.pop(); - jsArray[depth] += subText; - algArray[depth] += subText2; - return; - } else if (elem[0] == 'sqrt') { - //console.log('sqrt'); - var subText = ''; - var subText2 = ''; - // if not proceeded by an operator, put a times sign in - if (jsArray[depth] !== '' && /[\+\-\u00D7\u00F7\*\/\=\[(]/.test(jsArray[depth].slice(-1)) == false) subText += "*"; - depth++; - position.push(0); - jsArray[depth] = ''; - subJS(elem[1], false); - jsArray[depth] = replaceAll(jsArray[depth], ' ', ''); // remove white space - subText += 'Math.sqrt('+ jsArray[depth] +')'; - subText2 += 'sqrt('+jsArray[depth]+')'; - jsArray[depth] = ''; - depth--; - position.pop(); - jsArray[depth] += subText; - algArray[depth] += subText2; - return; - } else if (elem[0] == 'root') { - //console.log(elem[0]); - var subText = ''; - var subText2 = ''; - // if not proceeded by an operator, put a times sign in - if (jsArray[depth] !== '' && /[\+\-\u00D7\u00F7\*\/\=\[(]/.test(jsArray[depth].slice(-1)) == false) subText += "*"; - depth++; - position.push(0); - jsArray[depth] = ''; - subJS(elem[2], false); - jsArray[depth] = replaceAll(jsArray[depth], ' ', ''); // remove white space - subText += '(Math.pow('+jsArray[depth]+','; - subText2 += 'root('+jsArray[depth]+','; - jsArray[depth] = ''; - subJS(elem[1], false); - jsArray[depth] = replaceAll(jsArray[depth], ' ', ''); // remove white space - subText += '(1/('+jsArray[depth]+'))))'; - subText2 += jsArray[depth]+')'; - jsArray[depth] = ''; - depth--; - position.pop(); - jsArray[depth] += subText; - algArray[depth] += subText2; - return; - } else if (elem[0] == 'sin' || elem[0] == 'cos' || elem[0] == 'tan') { - //console.log(elem[0]); - var subText = ''; - // if not proceeded by an operator, put a times sign in - if (jsArray[depth] !== '' && /[\+\-\u00D7\u00F7\*\/\=\[(]/.test(jsArray[depth].slice(-1)) == false) subText += "*"; - depth++; - position.push(0); - jsArray[depth] = ''; - subJS(elem[1], false); - jsArray[depth] = replaceAll(jsArray[depth], ' ', ''); // remove white space - var convertText1 = ''; - var convertText2 = ''; - if (angleMode == 'deg' || angleMode == 'degrees') { - convertText1 = '('; - convertText2 = ')*Math.PI/180'; - } - subText += 'Math.'+ elem[0] +'('+convertText1+jsArray[depth]+convertText2+')'; - jsArray[depth] = ''; - depth--; - position.pop(); - jsArray[depth] += subText; - algArray[depth] += subText; - return; - } else if (elem[0] == 'sin-1' || elem[0] == 'cos-1' || elem[0] == 'tan-1') { - //console.log(elem[0]); - var subText = ''; - // if not proceeded by an operator, put a times sign in - if (jsArray[depth] !== '' && /[\+\-\u00D7\u00F7\*\/\=\[(]/.test(jsArray[depth].slice(-1)) == false) subText += "*"; - depth++; - position.push(0); - jsArray[depth] = ''; - subJS(elem[1], false); - jsArray[depth] = replaceAll(jsArray[depth], ' ', ''); // remove white space - var convertText1 = ''; - var convertText2 = ''; - if (angleMode == 'deg' || angleMode == 'degrees') { - convertText1 = '(('; - convertText2 = ')*180/Math.PI)'; - } - subText += convertText1+'Math.a'+elem[0].slice(0,3)+'('+jsArray[depth]+')'+convertText2;; - jsArray[depth] = ''; - depth--; - position.pop(); - jsArray[depth] += subText; - algArray[depth] += subText; - return; - } else if (elem[0] == 'ln') { - //console.log(elem[0]); - var subText = ''; - // if not proceeded by an operator, put a times sign in - if (jsArray[depth] !== '' && /[\+\-\u00D7\u00F7\*\/\=\[(]/.test(jsArray[depth].slice(-1)) == false) subText += "*"; - depth++; - position.push(0); - jsArray[depth] = ''; - subJS(elem[1], false); - jsArray[depth] = replaceAll(jsArray[depth], ' ', ''); // remove white space - subText += 'Math.log('+jsArray[depth]+')'; - jsArray[depth] = ''; - position.pop(); - depth--; - jsArray[depth] += subText; - algArray[depth] += subText; - return; - } else if (elem[0] == 'log') { - //console.log(elem[0]); - var subText = ''; - // if not proceeded by an operator, put a times sign in - if (jsArray[depth] !== '' && /[\+\-\u00D7\u00F7\*\/\=\[(]/.test(jsArray[depth].slice(-1)) == false) subText += "*"; - depth++; - position.push(0); - jsArray[depth] = ''; - subJS(elem[1], false); - jsArray[depth] = replaceAll(jsArray[depth], ' ', ''); // remove white space - subText += '((Math.log('+jsArray[depth]+'))/(Math.log(10)))'; - jsArray[depth] = ''; - depth--; - position.pop(); - jsArray[depth] += subText; - algArray[depth] += subText; - return; - } else if (elem[0] == 'logBase') { - //console.log(elem[0]); - var subText = ''; - // if not proceeded by an operator, put a times sign in - if (jsArray[depth] !== '' && /[\+\-\u00D7\u00F7\*\/\=\[(]/.test(jsArray[depth].slice(-1)) == false) subText += "*"; - depth++; - position.push(0); - jsArray[depth] = ''; - subJS(elem[2], false); - jsArray[depth] = replaceAll(jsArray[depth], ' ', ''); // remove white space - subText += '((Math.log('+jsArray[depth]+'))/'; - jsArray[depth] = ''; - subJS(elem[1], false); - jsArray[depth] = replaceAll(jsArray[depth], ' ', ''); // remove white space - subText += '(Math.log('+jsArray[depth]+')))'; - jsArray[depth] = ''; - depth--; - position.pop(); - jsArray[depth] += subText; - algArray[depth] += subText; - return; - } else if (elem[0] == 'abs') { - //console.log(elem[0]); - var subText = ''; - // if not proceeded by an operator, put a times sign in - if (jsArray[depth] !== '' && /[\+\-\u00D7\u00F7\*\/\=\[(]/.test(jsArray[depth].slice(-1)) == false) subText += "*"; - depth++; - position.push(0); - jsArray[depth] = ''; - subJS(elem[1], false); - jsArray[depth] = replaceAll(jsArray[depth], ' ', ''); // remove white space - subText += 'Math.abs('+jsArray[depth]+')'; - jsArray[depth] = ''; - depth--; - position.pop(); - jsArray[depth] += subText; - algArray[depth] += subText; - return; - } else if (elem[0] == 'power' || elem[0] == 'pow') { - //console.log('power'); - - var baseSplitPoint = 0; - var trigPower = false; - //if the power is after a close bracket - if (jsArray[depth] !== '') { - if (jsArray[depth].charAt(jsArray[depth].length - 1) == ')') { - var bracketCount = 1 - for (jsChar = jsArray[depth].length - 2; jsChar >= 0; jsChar--) { - if (jsArray[depth].charAt(jsChar) == ')') {bracketCount++} - if (jsArray[depth].charAt(jsChar) == '(') {bracketCount--} - if (bracketCount == 0 && !baseSplitPoint) { - baseSplitPoint = jsChar; - break; - } - } - //if the power is after sin, cos or tan - - } else if (jsArray[depth].slice(jsArray[depth].length-3) == 'sin' || jsArray[depth].slice(jsArray[depth].length-3) == 'coa' || jsArray[depth].slice(jsArray[depth].length-3) == 'tan') { - trigPower = true; - //if the power is after a letter - } else if (/[A-Za-z]/g.test(jsArray[depth].charAt(jsArray[depth].length - 1)) == true) { - baseSplitPoint = jsArray[depth].length - 1; - //if the power is after a numerical digit - } else if (/[0-9]/g.test(jsArray[depth].charAt(jsArray[depth].length - 1)) == true) { - var decPoint = false; - for (jsChar = jsArray[depth].length - 2; jsChar >= 0; jsChar--) { - if (decPoint == false && jsArray[depth].charAt(jsChar) == '.') { - decPoint = true; - } else if (decPoint == true && jsArray[depth].charAt(jsChar) == '.') { - baseSplitPoint = jsChar + 1; - break; - } else if (/[0-9]/g.test(jsArray[depth].charAt(jsChar)) == false) { - baseSplitPoint = jsChar + 1; - break; - } - } - } else { - return ''; // error - } - } - - /*if (trigPower == true) { - var power = elem[2]; - if (typeof power == 'string') { - power = removeAllTagsFromString(power); - console.log(power); - if (power == '-1') { - jsArray[depth] = jsArray[depth].slice(0,-3) + 'Math.a' + jsArray[depth].slice(-3); - } else if (power == '2') { - - } - } - - }*/ - - var base = jsArray[depth].slice(baseSplitPoint); - jsArray[depth] = jsArray[depth].slice(0, baseSplitPoint); - depth++; - position.push(0); - jsArray[depth] = ''; - subJS(elem[2], false) - jsArray[depth] = replaceAll(jsArray[depth], ' ', ''); - if (trigPower == true) { - console.log(jsArray,jsArray[depth-1],jsArray[depth]); - if (jsArray[depth] == '-1') { - jsArray[depth-1] = jsArray[depth-1].slice(0,-3) + 'Math.a' + jsArray[depth-1].slice(-3); - } - } else { - var subText = 'Math.pow(' + base + ',' + jsArray[depth] + ')'; - var subText2 = base + '^' + jsArray[depth]; - } - jsArray[depth] = ''; - depth--; - position.pop(); - jsArray[depth] += subText; - algArray[depth] += subText2; - return; - } else if (typeof elem == 'object') { - //console.log('array'); - depth++; - position.push(0); - jsArray[depth] = ''; - for (var sub = 0; sub < elem.length; sub++) { - //console.log('depth:', depth); - //console.log('Before ' + sub + ' sub element(s):', jsArray); - subJS(elem[sub], addMultIfNecc); - //console.log('After ' + sub + ' sub element(s):', jsArray); - } - jsArray[depth-1] += jsArray[depth]; - algArray[depth-1] += algArray[depth]; - jsArray[depth] = ''; - depth--; - position.pop(); - //console.log('endOfArray', jsArray); - return; - } - } - - function timesBeforeLetters(testText) { - // find instances of letters - if proceeded by a number, add * - for (q = 0; q < testText.length; q++) { - if (q > 0) { - if (/[a-zA-Z]/g.test(testText.charAt(q)) == true && /[a-zA-Z0-9)]/.test(testText.charAt(q - 1)) == true) { - testText = testText.slice(0, q) + '*' + testText.slice(q); - } - // if an open bracket is proceeded by a letter, number or ), add * - if (/[\[(]/g.test(testText.charAt(q)) == true && testText.length > q && /[A-Za-z0-9)]/g.test(testText.charAt(q - 1)) == true) { - testText = testText.slice(0, q) + '*' + testText.slice(q); - } - } - for (var i = 0; i < exceptions.length; i++) { - if (testText.slice(q).indexOf(exceptions[i]) == 0) { - q += exceptions[i].length; - } - } - } - return testText; - } - var jsValue; - try { - jsValue = eval(js); - } catch (err) {} - return js; -} -function splitText(text) { - // find split points in text string - var splitPointCount = 0; - var textSplitPoints = []; - var delimiter = '%&^'; - for (i = 0; i <= text.length; i++) { - var fracStartPos = text.substring(i, text.length).indexOf('frac('); - var rootStartPos = text.substring(i, text.length).indexOf('root('); - var powerStartPos = text.substring(i, text.length).indexOf('power('); - if (fracStartPos !== -1) {fracStartPos += i}; - if (rootStartPos !== -1) {rootStartPos += i}; - if (powerStartPos !== -1) {powerStartPos += i}; - if (fracStartPos > -1 || rootStartPos > -1 || powerStartPos > -1) { - textSplitPoints[splitPointCount] = []; - if (fracStartPos == -1) {fracStartPos = 10000}; - if (rootStartPos == -1) {rootStartPos = 10000}; - if (powerStartPos == -1) {powerStartPos = 10000}; - textSplitPoints[splitPointCount][0] = Math.min(fracStartPos, rootStartPos, powerStartPos); - var openBracketCount = 0; - var closeBracketCount = 0; - for (j = textSplitPoints[splitPointCount][0]; j <= text.length; j++) { - if (!textSplitPoints[splitPointCount][1]) { - if (text.charAt(j) == '(') {openBracketCount++}; - if (text.charAt(j) == ')') {closeBracketCount++}; - if (openBracketCount > 0 && (openBracketCount == closeBracketCount)) { - textSplitPoints[splitPointCount][1] = j; - i = j; - } - } - } - splitPointCount++; - } - } - - if (textSplitPoints.length == 0) {return text} - - for (i = 0; i < textSplitPoints.length; i++) { - text = text.substring(0, textSplitPoints[i][0] + i * 2 * delimiter.length) + delimiter + text.substring(textSplitPoints[i][0] + i * 2 * delimiter.length, textSplitPoints[i][1] + 1 + i * 2 * delimiter.length) + delimiter + text.substring(textSplitPoints[i][1] + 1 + i * 2 * delimiter.length, text.length); - } - var splitArray = text.split(delimiter); - var returnArray = []; - for (i = 0; i < splitArray.length; i++) { - var type = 0; - if (splitArray[i].indexOf('frac(') == 0) {type = 'frac'}; - if (splitArray[i].indexOf('root(') == 0) {type = 'root'}; - if (splitArray[i].indexOf('power(') == 0) {type = 'power'}; - if (type == 0) { - if (splitArray[i] !== '') {returnArray.push(splitArray[i])} - } else { - var subArray = []; - subArray[0] = type; - - var params = splitArray[i].substring(type.length + 1, splitArray[i].length - 1); - var openBracketCount = 0; - var closeBracketCount = 0; - var splitPoint = -1; - - // find split point of params - for (j = 0; j <= params.length; j++) { - if (params.charAt(j) == '(') {openBracketCount++}; - if (params.charAt(j) == ')') {closeBracketCount++}; - if (params.charAt(j) == ',' && (openBracketCount == closeBracketCount) && splitPoint == -1) { - splitPoint = j; - } - } - subArray[1] = params.substring(0, splitPoint); - subArray[2] = params.substring(splitPoint + 1, params.length).trim(); - returnArray.push(subArray) - } - } - return returnArray; -} - -/*! correcting-interval 2.0.0 | Copyright 2014 Andrew Duthie | MIT License */ -/* jshint evil: true */ -/* usage example: -var startTime = Date.now(); -setCorrectingInterval(function() { - console.log((Date.now() - startTime) + 'ms elapsed'); -}, 1000); -*/ -;(function(global, factory) { - // Use UMD pattern to expose exported functions - if (typeof exports === 'object') { - // Expose to Node.js - module.exports = factory(); - } else if (typeof define === 'function' && define.amd) { - // Expose to RequireJS - define([], factory); - } - - // Expose to global object (likely browser window) - var exports = factory(); - for (var prop in exports) { - global[prop] = exports[prop]; - } -}(this, function() { - // Track running intervals - var numIntervals = 0, - intervals = {}; - - // Polyfill Date.now - var now = Date.now || function() { - return new Date().valueOf(); - }; - - var setCorrectingInterval = function(func, delay) { - var id = numIntervals++, - planned = now() + delay; - - // Normalize func as function - switch (typeof func) { - case 'function': - break; - case 'string': - var sFunc = func; - func = function() { - eval(sFunc); - }; - break; - default: - func = function() { }; - } - - function tick() { - func(); - - // Only re-register if clearCorrectingInterval was not called during function - if (intervals[id]) { - planned += delay; - intervals[id] = setTimeout(tick, planned - now()); - } - } - - intervals[id] = setTimeout(tick, delay); - return id; - }; - - var clearCorrectingInterval = function(id) { - clearTimeout(intervals[id]); - delete intervals[id]; - }; - - return { - setCorrectingInterval: setCorrectingInterval, - clearCorrectingInterval: clearCorrectingInterval - }; -})); -function logText(clearConsole) { - var input = currMathsInput; - if (clearConsole == true) console.clear(); - console.log('richText:',input.richText); - console.log('cursorMap:'); - for (var i = 0; i < input.cursorMap.length; i++) { - var char = input.richText; - for (var j = 0; j < input.cursorMap[i].length - 1; j++) {char = char[input.cursorMap[i][j]];}; - // check for breakPoints - var slicePos = input.cursorMap[i][input.cursorMap[i].length-1]; - if (typeof currMathsInput.breakPoints == 'object') { - var map = currMathsInput.cursorMap[i]; - for (var k = 0; k < currMathsInput.breakPoints.length - 1; k++) { - var iBreak = currMathsInput.allMap[currMathsInput.breakPoints[k]]; - if (iBreak[0] == map[0] && iBreak[1] < map[1]) { - slicePos--; - } - } - } - var char1 = char.slice(slicePos-5,slicePos); - var char2 = char.slice(slicePos,slicePos+5); - if (i == input.cursorPos) { - console.log('>'+i+':',input.cursorMap[i],char1,char2,'<<< cursorPos'); - } else { - console.log('>'+i+':',input.cursorMap[i],char1,char2); - } - } -} -function drawTextLocs() { - for (var loc = 0; loc < currMathsInput.cursorMap.length; loc++) { - var cursorPos = currMathsInput.cursorMap[loc]; - var evalString = 'currMathsInput.textLoc' - for (aa = 0; aa < cursorPos.length; aa++) { - evalString += '[' + cursorPos[aa] + ']'; - } - var pos = eval(evalString); - console.log(loc, pos.left); - currMathsInput.ctx.strokeStyle = '#00F'; - currMathsInput.ctx.lineWidth = 2; - currMathsInput.ctx.beginPath(); - currMathsInput.ctx.moveTo(pos.left,pos.top); - currMathsInput.ctx.lineTo(pos.left,pos.top+pos.height); - currMathsInput.ctx.closePath(); - currMathsInput.ctx.stroke(); - } -} -function isMouseOverText(mathsInput) { - if (typeof mathsInput == 'undefined') mathsInput = currMathsInput; - var locs = []; - for (var i = 0; i < mathsInput.cursorMap.length; i++) { - var textLoc = mathsInput.textLoc; - for (var j = 0; j < mathsInput.cursorMap[i].length; j++) {textLoc = textLoc[mathsInput.cursorMap[i][j]];}; - locs.push(textLoc); - } - var left = mathsInput.data[100]; - var top = mathsInput.data[101]; - for (var i = 0; i < locs.length; i++) { - if (mouse.x >= left + locs[i].left && mouse.x <= left + locs[i].left + locs[i].width && mouse.y >= top + locs[i].top && mouse.y <= top + locs[i].top + locs[i].height) { - return true; - } - } - return false; -} - - -function splitMarkup(element) { - // seperates markup tags from other text - var splitAt = [0]; - for (var c = 0; c < element.length; c++) { - if (element.slice(c).indexOf('<<') == 0 && element.slice(c).indexOf('<<<') !== 0) { - for (var d = c; d < element.length; d++) { - if (element.slice(d).indexOf('>>') == 0) { - splitAt.push(c,d+2); - break; - } - } - } else if (element.slice(c).indexOf(br) == 0) { - splitAt.push(c,c+1); - } - } - splitAt.push(element.length); - var returnArray = []; - for (var c = 0; c < splitAt.length-1; c++) { - returnArray.push(element.slice(splitAt[c],splitAt[c+1])) - } - return returnArray; -} -function reduceTags(textArray) { - var bold = {value:null,char:true}; - var italic = {value:null,char:true}; - var fontSize = {value:null,char:true}; - var font = {value:null,char:true}; - var color = {value:null,char:true}; - var backColor = {value:null,char:true}; - var align = {set:false}; - var selected = {value:null}; - - function arrayHandler(arr) { - for (var l = arr.length - 1; l >= 0; l--) { - if (typeof arr[l] == 'string') { - arr[l] = stringHandler(arr[l]); - } else if (typeof arr[l] == 'object') { - arr[l] = arrayHandler(arr[l]); - } - } - return arr; - } - - function stringHandler(string) { - // first split string into tag and non-tag elements - var splitString = splitMarkup(string); - - // work backwards through the string looking for tags - for (var j = splitString.length - 1; j >= 0; j--) { - if (splitString[j].indexOf('<<') == 0) { - for (var k = splitString[j].length; k >= 0; k--) { - var slice = splitString[j].slice(k); - if (slice.indexOf('<>')+2); - } else { - var value = splitString[j].slice(k+7,k+splitString[j].slice(k).indexOf('>>')).toLowerCase(); - if (value == bold.value) { - // repeated tag - !! - } else { - // new tag - bold.value = value; - bold.char = false; - } - } - } else if (slice.indexOf('<>')+2); - } else { - var value = splitString[j].slice(k+9,k+splitString[j].slice(k).indexOf('>>')).toLowerCase(); - if (value == italic.value) { - // repeated tag - } else { - // new tag - italic.value = value; - italic.char = false; - } - } - } else if (slice.indexOf('<>')+2); - } else { - var value = splitString[j].slice(k+11,k+splitString[j].slice(k).indexOf('>>')).toLowerCase(); - if (value == fontSize.value) { - // repeated tag - } else { - // new tag - fontSize.value = value; - fontSize.char = false; - } - } - } else if (slice.indexOf('<>')+2); - } else { - var value = splitString[j].slice(k+7,k+splitString[j].slice(k).indexOf('>>')).toLowerCase(); - if (value == font.value) { - // repeated tag - } else { - // new tag - font.value = value; - font.char = false; - } - } - } else if (slice.indexOf('<>')+2); - } else { - var value = splitString[j].slice(k+8,k+splitString[j].slice(k).indexOf('>>')).toLowerCase(); - if (value == color.value) { - // repeated tag - } else { - // new tag - color.value = value; - color.char = false; - } - } - } else if (slice.indexOf('<>')+2); - } else { - var value = splitString[j].slice(k+12,k+splitString[j].slice(k).indexOf('>>')).toLowerCase(); - if (value == backColor.value) { - // repeated tag - } else { - // new tag - backColor.value = value; - backColor.char = false; - } - } - } else if (slice.indexOf('<
>') == 0 || slice.indexOf(br) == 0) { - align.set = false; - } else if (slice.indexOf('<>')+2); - } - } else if (slice.indexOf('<>')).toLowerCase(); - //console.log('selected tag',j,k,value,JSON.stringify(splitString[j])); - if (value == selected.value) { - // repeated tag - } else { - // new tag - selected.value = value; - } - } - - } - } else { - if (splitString[j].length > 0) { - bold.char = true; - italic.char = true; - fontSize.char = true; - font.char = true; - color.char = true; - backColor.char = true; - } - } - } - string = ''; - for (var j = 0; j < splitString.length; j++) string += splitString[j]; - return string; - } - - if (typeof textArray == 'object') textArray = arrayHandler(textArray); - //var arrayString = ''; - //console.log('reduceTags()1',JSON.stringify(textArray)); - textArray = combineSpaces2(textArray); - - // find any adjacent text blocks and combine them - function combineSpaces2(textArray) { - if (textArray.length > 1) { - for (var gg = textArray.length - 1; gg >= 0; gg--) { - if (typeof textArray[gg] == 'object') { - //arrayString += '[' + gg + ']'; - combineSpaces2(textArray[gg]); - } else { - if (gg < textArray.length - 1 && typeof textArray[gg] == 'string' && typeof textArray[gg+1] == 'string') { - eval('textArray[' + gg + '] += textArray[' + (gg+1) + ']'); - eval('textArray.splice(gg+1, 1);'); - } - } - } - } - //arrayString = arrayString.slice(0, arrayString.lastIndexOf('[') - arrayString.length); - return textArray; - } - - //console.log('reduceTags()2',JSON.stringify(textArray)); - - return textArray; -} \ No newline at end of file diff --git a/tools/i2/_miscFuncs.js b/tools/i2/_miscFuncs.js deleted file mode 100644 index 5b49571..0000000 --- a/tools/i2/_miscFuncs.js +++ /dev/null @@ -1,12393 +0,0 @@ -//Javascript document - -var alg = { - toObj: function(txt) { - txt = simplifyText(clone(txt)); - txt = removeTags(txt); - var exp = []; - - //console.log('---'); - //console.log('txt',txt); - var terms = splitTerms(txt); - - //console.log('terms',clone(terms)); - - for (var t = 0; t < terms.length; t++) processTerm(terms[t]); - - //console.log('toObj:',JSON.stringify(exp)); - - return exp; - - function splitTerms(txt) { - var terms = [[]]; - var bracketCount = 0; - for (var i = 0; i < txt.length; i++) { - var txt1 = txt[i]; - if (typeof txt1 === 'string') { - for (var c = 0; c < txt1.length; c++) { - if (txt1.charAt(c) === '(') { - bracketCount++; - } else if (txt1.charAt(c) === ')') { - bracketCount--; - } else if (bracketCount === 0 && (txt1.charAt(c) === '+' || txt1.charAt(c) === '-')) { - if (c > 0) { - terms.last().push(txt1.slice(0,c)); - txt1 = txt1.slice(c); - c = 0; - } - if (terms.last().length > 0) { - terms.push([]); - } - } - } - terms.last().push(txt1); - } else { - terms.last().push(txt1); - } - } - return terms; - } - function getAlgFrac(term) { - //console.log('term:',clone(term)); - - var sign = 1; - if (term[0] === '-') { - sign = -1; - term.shift(); - } else if (term[0] === '+') { - term.shift(); - } - var num = alg.toObj(term[0][1]); - var denom = alg.toObj(term[0][2]); - - var coeff = [1,1]; - if (num.length === 1) { - coeff[0] *= num[0].coeff[0]; - coeff[1] *= num[0].coeff[1]; - num[0].coeff = [1,1]; - } else { - num = [{sign:1,coeff:[1,1],subterms:[[num,1]]}]; - } - if (denom.length === 1) { - coeff[0] *= denom[0].coeff[1]; - coeff[1] *= denom[0].coeff[0]; - denom[0].coeff = [1,1]; - for (var s = 0; s < denom[0].subterms.length; s++) { - denom[0].subterms[s][1] *= -1; - } - } else { - denom = [{sign:1,coeff:[1,1],subterms:[[denom,-1]]}]; - } - - var numSubterms = num[0].subterms; - var denomSubterms = denom[0].subterms; - var subterms = numSubterms.concat(denomSubterms); - //subterms = alg.simplifySubterms(subterms); - subterms = alg.orderSubterms(subterms); - - var obj = { - sign:sign, - coeff:coeff, - subterms:subterms - }; - - term.shift(); - return obj; - } - function processTerm(term) { - if (term.length === 0) return; - //console.log('term',clone(term)); - - var obj = {}; - exp.push(obj); - while (term[0] === '') term.shift(); - - var coeff = 1; - if ((term[0] === '-' || term[0] === '+') && typeof term[1] === 'object' && term[1][0] === 'frac') { - if (term[1][1].length === 1 && !isNaN(Number(term[1][1][0])) && term[1][2].length === 1 && !isNaN(Number(term[1][2][0]))) { - obj.sign = term[0] === '-' ? -1: 1; - obj.coeff = [Number(term[1][1][0]),Number(term[1][2][0])]; - term.shift(); - term.shift(); - } else { - exp[exp.length-1] = getAlgFrac(term); - } - } else if (typeof term[0] === 'string') { - var sign = 1; - if (term[0][0] === '-') { - sign = -1; - term[0] = term[0].slice(1); - } else if (term[0][0] === '+') { - term[0] = term[0].slice(1); - } - var charCount = 0; - for (var c = 1; c < term[0].length+1; c++) { - if (isNaN(Number(term[0].slice(0,c)))) { - term[0] = term[0].slice(charCount); - break; - } else { - coeff = Number(term[0].slice(0,c)); - charCount++; - if (c === term[0].length) { - term[0] = term[0].slice(charCount); - break; - } - } - } - obj.sign = sign; - obj.coeff = [coeff,1]; - } else if (typeof term[0] === 'object' && term[0][0] === 'frac') { - if (term[0][1].length === 1 && !isNaN(Number(term[0][1][0])) && term[0][2].length === 1 && !isNaN(Number(term[0][2][0]))) { - obj.sign = 1; - obj.coeff = [Number(term[0][1][0]),Number(term[0][2][0])]; - term.shift(); - } else { - exp[exp.length-1] = getAlgFrac(term); - } - } - while (term[0] === '') term.shift(); - - if (term.length === 0) { - obj.subterms = []; - return; - } - var subterms = []; - var count = 0; - while (!un(term[0]) && typeof term[0] === 'string' && count < 100) { - count++; - var subterms2 = []; - if (typeof term[0] === 'string') { - if (term[0][0] === '(') { - term[0] = term[0].slice(1); - if (term[0] === '') term.shift(); - var term2 = []; - var bracketCount = 1; - var count = 0; - while (bracketCount > 0 && count < 100) { - count++; - if (typeof term[0] === 'string') { - var str = term[0]; - for (var c = 0; c < str.length; c++) { - var char = str[c]; - if (char === '(') { - bracketCount++; - } else if (char === ')') { - bracketCount--; - if (bracketCount === 0) { - if (c > 0) term2.push(str.slice(0,c)); - term[0] = str.slice(c+1); - break; - } - } - } - if (bracketCount !== 0) { - term2.push(term[0]); - term.shift(); - } - } else if (typeof term[0] === 'object') { - term2.push(term[0]); - term.shift(); - } - } - subterms2 = [alg.toObj(term2),1]; - if (term[0] === '') term.shift(); - if (typeof term[0] === 'object' && term[0][0] === 'pow') { - if (!isNaN(Number(term[0][2]))) subterms2[1] = Number(term[0][2]); - term.shift(); - } - } else { - subterms2 = [term[0][0],1]; - term[0] = term[0].slice(1); - if (term[0] === '') term.shift(); - if (typeof term[0] === 'object' && term[0][0] === 'pow') { - if (!isNaN(Number(term[0][2]))) subterms2[1] = Number(term[0][2]); - term.shift(); - } - } - } - if (term[0] === '') term.shift(); - subterms.push(subterms2); - } - obj.subterms = subterms; - } - - }, - toText: function(exp,type) { - if (un(type)) type = 'default'; // default is fracTerms - var txt = ['']; - if (exp instanceof Array === false && typeof exp === 'object') exp = [exp]; - if (exp.length === 0) return ["0"]; - for (var e = 0; e < exp.length; e++) { - var term = exp[e]; - //console.log('term',term); - var isFirstTerm = e === 0 ? true : false; - var isOnlyTerm = exp.length === 1 ? true : false; - if (type === 'inline') { - txt = txt.concat(termToTextInline(term,isFirstTerm,isOnlyTerm)); - } else { - txt = txt.concat(termToTextFracTerms(term,isFirstTerm,isOnlyTerm)) - } - } - txt = simplifyText(txt); - return txt; - - function termToTextInline(term,isFirstTerm,isOnlyTerm) { - var txt = []; - var sign = term.sign === -1 ? '-' : '+'; - var coeff = term.coeff; - if (coeff[1] === 1) coeff = coeff[0]; - var subterms = term.subterms; - if (coeff === 1 && subterms.length > 0) coeff = ''; - if (isFirstTerm === false || sign === '-') txt.push(sign); - if (coeff instanceof Array) { - txt.push(['frac',[String(Math.abs(coeff[0]))],[String(Math.abs(coeff[1]))]]); - } else { - txt.push(String(coeff)); - } - var subtermsText = []; - for (var s = 0; s < subterms.length; s++) { - var sub = subterms[s]; - if (typeof sub[0] === 'string') { - subtermsText.push(sub[0]); - } else if (typeof sub[0] === 'object') { - var brackets = sub.length > 1 ? true : false; - if (brackets = true) subtermsText.push('('); - subtermsText = subtermsText.concat(alg.toText(sub[0])); - if (brackets = true) subtermsText.push(')'); - } - if (!un(sub[1]) && sub[1] !== 1) subtermsText.push(['pow',false,String(sub[1])]); - } - txt = txt.concat(subtermsText); - - return txt; - } - function termToTextFracTerms(term,isFirstTerm,isOnlyTerm) { - var num = []; - var denom = []; - - var subterms = term.subterms; - for (var s = 0; s < subterms.length; s++) { - var sub = subterms[s]; - var type = alg.getSubtermType(sub); - if (type === 'single') { - if (sub[1] > 0) { - num.push(sub[0]); - if (sub[1] > 1) num.push(['pow',false,String(sub[1])]); - } else { - denom.push(sub[0]); - if (sub[1] < -1) denom.push(['pow',false,String(Math.abs(sub[1]))]); - } - } else if (type === 'compound') { - if (sub[1] > 0) { - var brackets = subtermRequiresBrackets(sub); - if (brackets === true) num.push('('); - num = num.concat(alg.toText(sub[0])); - if (brackets === true) num.push(')'); - if (sub[1] > 1) num.push(['pow',false,String(sub[1])]); - } else { - var brackets = subtermRequiresBrackets(sub); - if (brackets === true) denom.push('('); - denom = denom.concat(alg.toText(sub[0])); - if (brackets === true) denom.push(')'); - if (sub[1] < -1) denom.push(['pow',false,String(Math.abs(sub[1]))]); - } - } - } - - function subtermRequiresBrackets(subterm) { - if (subterm[1] > 1 || subterm[1] < -1) return true; - if (subterm[0].length > 1) return true; - var exp = subterm[0][0].subterms; - if (exp.length > 1 || un(exp[0])) return true; - if (Math.abs(exp[0][1]) > 1) return false; - if (arraysEqual(exp[0][0].coeff,[1,1]) === true) return false; - return false; - } - - var coeff = term.coeff; - if (coeff[0] !== 1 || num.length === 0) num.unshift(String(coeff[0])); - if (coeff[1] !== 1 || denom.length === 0) denom.unshift(String(coeff[1])); - - var sign = term.sign === -1 ? '-' : '+'; - if (isFirstTerm === true && sign === '+') sign = ''; - - num = simplifyText(num); - denom = simplifyText(denom); - - var isFraction = (arraysEqual(denom,['1']) || denom.length === 0) ? false : true; - - if (isFraction) { - if (typeof num[0] === 'string' && num[0][0] === '(' && typeof num[num.length-1] === 'string' && num[num.length-1].slice(-1) === ')') { - var bracketCount = 1; - var bracketClosed = false; - for (var i = 0; i < num.length; i++) { - if (typeof num[i] !== 'string') continue; - for (var j = 0; j < num[i].length; j++) { - if (i == 0 && j == 0) continue; - if (i == num.length-1 && j == num[i].length-1) continue; - if (num[i][j] === '(') bracketCount++; - if (num[i][j] === ')') bracketCount--; - if (bracketCount === 0) { - bracketClosed = true; - j = num[i].length; - i = num.length; - } - } - } - if (bracketClosed === false) { - num[0] = num[0].slice(1); - num[num.length-1] = num[num.length-1].slice(0,-1); - num = simplifyText(num); - } - } - - if (typeof denom[0] === 'string' && denom[0][0] === '(' && typeof denom[denom.length-1] === 'string' && denom[denom.length-1].slice(-1) === ')') { - var bracketCount = 1; - var bracketClosed = false; - for (var i = 0; i < denom.length; i++) { - if (typeof denom[i] !== 'string') continue; - for (var j = 0; j < denom[i].length; j++) { - if (i == 0 && j == 0) continue; - if (i == denom.length-1 && j == denom[i].length-1) continue; - if (denom[i][j] === '(') bracketCount++; - if (denom[i][j] === ')') bracketCount--; - if (bracketCount === 0) { - bracketClosed = true; - j = denom[i].length; - i = denom.length; - } - } - } - if (bracketClosed === false) { - denom[0] = denom[0].slice(1); - denom[denom.length-1] = denom[denom.length-1].slice(0,-1); - denom = simplifyText(denom); - } - } - var txt = [sign,['frac',num,denom,1]]; - } else { - var txt = [sign].concat(num); - } - - return txt; - } - }, - - add: function(exp1,exp2) { - var exp3 = clone(exp1); - exp3 = exp3.concat(clone(exp2)); - //exp3 = alg.collect(exp3); - return exp3; - }, - subtract: function(exp1,exp2) { - var exp2 = clone(exp2); - var exp2 = alg.multiply(exp2,[{sign:-1,coeff:[1,1],subterms:[]}]); - var exp3 = alg.add(exp1,exp2); - return exp3; - }, - multiply: function(exp1,exp2,simplify) { - exp1 = clone(exp1); - exp2 = clone(exp2); - if (exp1.length > 1) exp1 = [{sign:1,coeff:[1,1],subterms:[[exp1,1]]}]; - if (exp2.length > 1) exp2 = [{sign:1,coeff:[1,1],subterms:[[exp2,1]]}]; - var term1 = clone(exp1[0]); - var subterms1 = term1.subterms; - var coeff1 = term1.coeff; - var term2 = clone(exp2[0]); - var subterms2 = term2.subterms; - var coeff2 = term2.coeff; - var sign3 = term1.sign*term2.sign; - var coeff3 = [coeff1[0]*coeff2[0],coeff1[1]*coeff2[1]]; - var subterms3 = subterms1.concat(subterms2); - if (boolean(simplify,true) === true) { - coeff3 = simplifyFrac2(coeff3); - subterms3 = alg.orderSubterms(subterms3); - subterms3 = alg.simplifySubterms(subterms3); - } - return [{sign:sign3,coeff:coeff3,subterms:subterms3}]; - }, - divide: function(exp1,exp2,simplify) { - var exp2 = alg.getExpressionReciprocal(exp2); - var exp3 = alg.multiply(exp1,exp2,simplify); - return exp3; - }, - - collect: function(exp) { - exp = clone(exp); - for (var e2 = exp.length-1; e2 >= 0; e2--) { - var term2 = exp[e2]; - var subterms2 = term2.subterms; - for (var e1 = e2-1; e1 >= 0; e1--) { - var term1 = exp[e1]; - var subterms1 = term1.subterms; - if (alg.likeTerms(term1,term2)) { - term1.coeff[0] *= term1.sign; - term2.coeff[0] *= term2.sign; - var coeff = addFracs2(term1.coeff,term2.coeff); - term1.sign = coeff[0]/coeff[1] < 0 ? -1 : 1; - term1.coeff = simplifyFrac2([Math.abs(coeff[0]),Math.abs(coeff[1])]); - exp.splice(e2,1); - break; - } - } - } - for (var e = 0; e < exp.length; e++) { - if (exp[e].coeff[0] === 0) { - exp.splice(e,1); - e--; - } - } - return exp; - }, - collectable: function(exp) { - var exp2 = clone(exp); - var exp3 = alg.collect(exp2); - return !isEqual(exp2,exp3); - }, - expand: function(exp) { - //console.log('exp',JSON.stringify(exp)); - var exp3 = clone(exp); - var exp2 = clone(exp); - - var count = 0; - do { - count++; - var exp2 = clone(exp3); - var exp3 = expandExp(exp3); - } while (!isEqual(exp2,exp3) && count < 10); - //console.log('exp3',JSON.stringify(exp3)); - return exp3; - - function expandExp(exp) { - var exp2 = clone(exp); - var exp3 = []; - for (var e = 0; e < exp2.length; e++) { - var term = exp2[e]; - - //console.log('term',JSON.stringify(term)); - - var num = alg.getTermNumerator(term); - var denom = alg.getTermDenominator(term); - - //console.log('num:',clone(num)); - //console.log('denom:',clone(denom)); - - var num2 = expandTerm(num); - var denom2 = expandTerm(denom); - - //console.log('num2:',clone(num2)); - //console.log('denom2:',clone(denom2)); - - var term2 = alg.divide(num2,denom2); - //console.log('term2',JSON.stringify(term2)); - - exp3 = exp3.concat(term2); - } - var exp4 = []; - for (var e = 0; e < exp3.length; e++) { - var term = exp3[e]; - if (term.sign === 1 && arraysEqual(term.coeff,[1,1]) && !un(term.subterms) && term.subterms.length === 1 && !un(term.subterms[0]) && alg.getSubtermType(term.subterms[0]) === 'compound' && term.subterms[0][1] === 1) { - exp4 = exp4.concat(term.subterms[0][0]); - } else { - exp4.push(term); - } - } - //console.log('exp4',JSON.stringify(exp4)); - return exp4; - } - function expandTerm(term) { - var term = clone(term); - - // apply powers to compound subterms - for (var s = 0; s < term.subterms.length; s++) { - var subterm = term.subterms[s]; - if (alg.getSubtermType(subterm) !== 'compound') continue; - if (subterm[1] > 1) { - var index = subterm[1]; - var subterm2 = clone(subterm[0]); - for (var i = 1; i < index; i++) { - subterm2 = alg.multiplyExpressions(subterm2,subterm[0]); - } - term.subterms[s] = [subterm2,1]; - } else if (subterm[1] < 1) { - var index = -1*subterm[1]; - var subterm2 = clone(subterm[0]); - for (var i = 1; i < index; i++) { - subterm2 = alg.multiplyExpressions(subterm2,subterm[0]); - } - term.subterms[s] = [subterm2,-1]; - } - } - - // mutiply subterms together - var count = 0; - while (term.subterms.length > 1 && count < 100) { - count++; - var subterm1 = term.subterms[0]; - var type1 = alg.getSubtermType(subterm1); - if (type1 === 'single') { - for (var i = 1; i < term.subterms.length; i++) { - var subterm2 = term.subterms[i]; - var type2 = alg.getSubtermType(subterm2); - if (type2 === 'compound') { - for (var s = 0; s < subterm2[0].length; s++) { - var subterm3 = subterm2[0][s].subterms; - subterm3.push(clone(subterm1)); - subterm2[0][s].subterms = alg.simplifySubterms(subterm3); - } - term.subterms.shift(); - break; - } - } - } else if (type1 === 'compound') { - var subterm2 = term.subterms[1]; - var type2 = alg.getSubtermType(subterm2); - if (type2 === 'single') { - for (var s = 0; s < subterm1[0].length; s++) { - var subterm3 = subterm1[0][s].subterms; - subterm3.push(clone(subterm2)); - subterm1[0][s].subterms = alg.simplifySubterms(subterm3); - } - term.subterms.splice(1,1); - } else if (type2 === 'compound') { - term.subterms[1] = [alg.multiplyExpressions(subterm1[0],subterm2[0]),1]; - term.subterms.shift(); - } - } - } - - var exp = []; - //console.log(JSON.stringify(term)); - if (!un(term.subterms[0])) { - if (alg.getSubtermType(term.subterms[0]) === 'compound') { - var terms2 = term.subterms[0][0]; - for (var s = 0; s < terms2.length; s++) { - var term2 = terms2[s]; - exp.push({ - sign:term.sign*term2.sign, - coeff:simplifyFrac2([term.coeff[0]*term2.coeff[0],term.coeff[1]*term2.coeff[1]]), - subterms:term2.subterms - }); - } - } else { - exp.push({ - sign:term.sign, - coeff:simplifyFrac2([term.coeff[0],term.coeff[1]]), - subterms:term.subterms - }); - } - } - if (exp.length === 0) exp.push({sign:term.sign,coeff:clone(term.coeff),subterms:[]}); - return exp; - } - }, - expandable: function(exp) { - var exp2 = clone(exp); - var exp3 = alg.expand(exp2); - return !isEqual(exp2,exp3); - }, - factorise: function(exp) { - var exp2 = clone(exp); - if (alg.collectable(exp2) === true) return exp; - //console.log('exp',JSON.stringify(exp)); - var exp3 = []; - - // look in each term for factorisable subterms - for (var t = 0; t < exp2.length; t++) { - var term = exp2[t]; - - var num = alg.getTermNumerator(term); - //console.log('num:',JSON.stringify(num)); - num = factoriseTerm(num); - - var denom = alg.getTermDenominator(term); - //console.log('denom:',JSON.stringify(denom)); - denom = factoriseTerm(denom); - - var term2 = alg.divide([num],[denom],false); - //console.log('term2:',JSON.stringify(term2)); - - exp3 = exp3.concat(term2); - } - - exp3 = factoriseExp(exp3); - return exp3; - - function factoriseTerm(term) { - var term = clone(term); - var factors = []; - //console.log('factorise term',clone(term)); - for (var s = 0; s < term.subterms.length; s++) { - var subterm = term.subterms[s]; - //console.log('-----',s); - //console.log('term',clone(term)); - //console.log('subterm',JSON.stringify(subterm)); - if (un(subterm)) continue; - if (alg.getSubtermType(subterm) === 'simple') continue; - var index = subterm[1]; - var exp = subterm[0]; - //console.log('exp',clone(exp)); - //console.log('index',index); - - var factor = alg.getHCF(exp); - //console.log('factor',JSON.stringify(factor)); - if (isEqual(factor,[{sign:1,coeff:[1,1],subterms:[]}])) continue; - var dividend = []; - for (var t = 0; t < exp.length; t++) { - var termdiv = alg.divide([exp[t]],factor); - termdiv = alg.simplify(termdiv); - dividend.push(termdiv[0]); - } - if (isEqual(dividend,[{sign:1,coeff:[1,1],subterms:[]}])) continue; - //console.log('dividend',JSON.stringify(dividend)); - - if (index !== 1) { - factor[0].coeff[0] = Math.pow(factor[0].coeff[0],index); - factor[0].coeff[1] = Math.pow(factor[0].coeff[1],index); - for (var s2 = 0; s2 < factor[0].subterms.length; s2++) { - factor[0].subterms[s2][1] = index; - } - } - - term.sign *= factor[0].sign; - term.coeff = [term.coeff[0]*factor[0].coeff[0],term.coeff[1]*factor[0].coeff[1]]; - factors = factors.concat(factor[0].subterms); - term.subterms[s] = [dividend,index]; - - //console.log('subterm',JSON.stringify(term.subterms[s])); - //console.log('term',JSON.stringify(term)); - } - term.subterms = factors.concat(term.subterms); - //console.log('term = '+JSON.stringify(term,null,2)); - return term; - } - function factoriseExp(exp) { - //console.log('exp',clone(exp)); - var factor = alg.getHCF(exp); - - //console.log('-----'); - //console.log('exp',JSON.stringify(exp)); - //console.log('factor',JSON.stringify(factor)); - - if (isEqual(factor,[{sign:1,coeff:[1,1],subterms:[]}])) { - var exp2 = exp; - } else { - var dividend = []; - for (var t = 0; t < exp.length; t++) { - var termdiv = alg.divide([exp[t]],factor); - termdiv = alg.simplify(termdiv); - dividend.push(termdiv[0]); - } - //console.log('dividend',JSON.stringify(dividend)); - - if (isEqual(dividend,[{sign:1,coeff:[1,1],subterms:[]}])) { - var exp2 = exp; - } else { - var exp2 = factor; - exp2[0].subterms.push([dividend,1]); - //console.log('exp2',JSON.stringify(exp2)); - } - } - - for (var t = 0; t < exp2.length; t++) { - var term = exp2[t]; - for (var s = 0; s < term.subterms.length; s++) { - var subterm = term.subterms[s]; - if (alg.getSubtermType(subterm) !== 'compound') continue; - term.subterms[s][0] = alg.quadFactorise(term.subterms[s][0]); - } - } - exp2 = alg.quadFactorise(exp2); - - //console.log('exp2',JSON.stringify(exp2)); - - return exp2; - } - }, - factorisable: function(exp) { - var exp2 = clone(exp); - var exp3 = alg.factorise(exp2); - return !isEqual(exp2,exp3); - }, - quadFactorise: function(exp) { - if (exp.length > 3) return exp; - var exp2 = clone(exp); - exp2 = alg.collect(exp2); - - var terms = []; - for (var t = 0; t < exp2.length; t++) { - var term = exp2[t]; - var subterms = term.subterms; - if (subterms.length === 0) { - terms[2] = term; - } else if (subterms[0][1] === 2) { - terms[0] = term; - } else if (subterms[0][1] === 1) { - terms[1] = term; - } - } - if (un(terms[0])) return exp; - if (un(terms[2])) return exp; - var vari = terms[0].subterms[0][0]; - if (un(terms[1])) terms[1] = {sign:1,coeff:[0,1],subterms:[[vari,1]]}; - if (un(terms[2])) terms[2] = {sign:1,coeff:[0,1],subterms:[]}; - - var a = terms[0].sign*terms[0].coeff[0]; - var b = terms[1].sign*terms[1].coeff[0]; - var c = terms[2].sign*terms[2].coeff[0]; - - var det = b*b-4*a*c; - if (det < 0) return exp; - var detroot = Math.sqrt(det); - if (detroot !== Math.round(detroot)) return exp; - - var roots = [ - simplifyFrac2([-b+detroot,2*a]), - simplifyFrac2([-b-detroot,2*a]) - ]; - - var sign1 = roots[0][0]/roots[0][1] < 0 ? 1 : -1; - var sign2 = roots[1][0]/roots[1][1] < 0 ? 1 : -1; - roots[0][0] = Math.abs(roots[0][0]); - roots[0][1] = Math.abs(roots[0][1]); - roots[1][0] = Math.abs(roots[1][0]); - roots[1][1] = Math.abs(roots[1][1]); - - var exp3 = [{sign:1,coeff:[1,1],subterms:[]}]; - - if (sign1 === sign2 && arraysEqual(roots[0],roots[1])) { - var exp3 = [{sign:1,coeff:[1,1],subterms:[[[{sign:1,coeff:[roots[0][1],1],subterms:[[vari,1]]},{sign:sign1,coeff:[roots[0][0],1],subterms:[]}],2]]}]; - } else { - var exp3 = [ - {sign:1,coeff:[1,1],subterms:[ - [[{sign:1,coeff:[roots[0][1],1],subterms:[[vari,1]]},{sign:sign1,coeff:[roots[0][0],1],subterms:[]}],1], - [[{sign:1,coeff:[roots[1][1],1],subterms:[[vari,1]]},{sign:sign2,coeff:[roots[1][0],1],subterms:[]}],1] - ]} - ]; - } - - - return exp3; - }, - simplify: function(exp) { // simplifies fractions - var exp2 = clone(exp); - for (var e = 0; e < exp2.length; e++) { - var term = exp2[e]; - term.coeff = simplifyFrac2(term.coeff); - term.subterms = alg.simplifySubterms(term.subterms); - for (var s = 0; s < term.subterms.length; s++) { - var subterm = term.subterms[s]; - if (alg.getSubtermType(subterm) === 'compound') { - term.subterms[s] = [alg.simplify(subterm[0]),subterm[1]]; - } - } - } - var exp3 = []; - for (var e = 0; e < exp2.length; e++) { - var term = exp2[e]; - if (term.sign === 1 && arraysEqual(term.coeff,[1,1]) && !un(term.subterms) && term.subterms.length === 1 && !un(term.subterms[0]) && alg.getSubtermType(term.subterms[0]) === 'compound' && term.subterms[0][1] === 1) { - exp3 = exp3.concat(term.subterms[0][0]); - } else { - exp3.push(term); - } - } - return exp3; - - - /*var exp2 = clone(exp); - alg.collect(exp2); - for (var t = 0; t < exp2.length; t++) { - var term = exp2[t]; - term.coeff = simplifyFrac2(term.coeff); - term.subterms = alg.simplifySubterms(term.subterms); - for (var s = 0; s < term.subterms.length; s++) { - var subterm = term.subterms[s]; - if (alg.getSubtermType(subterm) === 'compound') { - term.subterms[s] = [alg.simplify(subterm[0]),subterm[1]]; - } - } - term.subterms = alg.orderSubterms(term.subterms); - } - return exp2;*/ - }, - simplifiable: function(exp) { - var exp2 = clone(exp); - var exp3 = alg.simplify(exp2); - return !isEqual(exp2,exp3); - }, - - likeTerms: function(term1,term2) { - var subterms1 = clone(term1.subterms); - var subterms2 = clone(term2.subterms); - if (subterms1.length !== subterms2.length) return false; - for (var s1 = 0; s1 < subterms1.length; s1++) { - var sub1 = subterms1[s1]; - for (var s2 = 0; s2 < subterms2.length; s2++) { - var sub2 = subterms2[s2]; - if (alg.likeSubterm(sub1,sub2) === false || sub1[1] !== sub2[1]) return false; - } - return true; - } - return true; - }, - getTermNumerator: function(term) { - if (typeof term === 'string') return {sign:1,coeff:[1,1],subterms:[[term,1]]}; - var num = {sign:term.sign,coeff:[term.coeff[0],1],subterms:[]}; - for (var s = 0; s < term.subterms.length; s++) { - var subterm = term.subterms[s]; - if (subterm[1] >= 0) { - num.subterms.push(subterm); - } - } - return num; - }, - getTermDenominator: function(term) { - if (typeof term === 'string') return {sign:1,coeff:[1,1],subterms:[]}; - var denom = {sign:1,coeff:[term.coeff[1],1],subterms:[]}; - for (var s = 0; s < term.subterms.length; s++) { - var subterm = term.subterms[s]; - if (subterm[1] < 0) { - denom.subterms.push([subterm[0],-1*subterm[1]]); - } - } - return denom; - }, - multiplyExpressions: function(exp1,exp2) { - var exp3 = []; - for (var e1 = 0; e1 < exp1.length; e1++) { - var term1 = clone(exp1[e1]); - var subterms1 = term1.subterms; - var coeff1 = term1.coeff; - for (var e2 = 0; e2 < exp2.length; e2++) { - var term2 = clone(exp2[e2]); - var subterms2 = term2.subterms; - var coeff2 = term2.coeff; - var sign3 = term1.sign*term2.sign; - var coeff3 = simplifyFrac2([coeff1[0]*coeff2[0],coeff1[1]*coeff2[1]]); - var subterms3 = subterms1.concat(subterms2); - subterms3 = alg.simplifySubterms(subterms3); - exp3.push({sign:sign3,coeff:coeff3,subterms:subterms3}); - } - } - return exp3; - }, - getTermReciprocal: function(term) { - var term2 = { - sign:term.sign, - coeff:[term.coeff[1],term.coeff[0]], - subterms:[] - }; - for (var s = 0; s < term.subterms.length; s++) { - var sub = clone(term.subterms[s]); - sub[1] *= -1; - term2.subterms.push(sub); - } - return term2; - }, - getExpressionReciprocal: function(exp) { - var exp = clone(exp); - if (exp.length === 1) { - var term = alg.getTermReciprocal(exp[0]); - return [term]; - } else { - return [{sign:1,coeff:[1,1],subterms:[[exp,-1]]}]; - } - }, - simplifySubterms: function(subterms) { - var subterms = clone(subterms); - for (var v2 = subterms.length-1; v2 >= 0; v2--) { // combine like subterms - for (var v1 = v2-1; v1 >= 0; v1--) { - if (alg.likeSubterm(subterms[v2],subterms[v1])) { - subterms[v1][1] += subterms[v2][1]; - subterms.splice(v2,1); - break; - } - } - } - for (var v2 = subterms.length-1; v2 >= 0; v2--) { // remove subterms with power 0 - if (subterms[v2][1] === 0) subterms.splice(v2,1); - } - return subterms; - }, - orderSubterms: function(subterms) { - //console.log(subterms); - subterms.sort(function(a,b) { - if (isEqual(a[0],b[0])) return b[1]-a[1]; - var typeA = alg.getSubtermType(a); - var typeB = alg.getSubtermType(b); - if (typeA === 'single' && typeB === 'single') { - if (a[0] < b[0]) return -1; - if (a[0] > b[0]) return 1; - } else if (typeA === 'single') { - return -1; - } else if (typeB === 'single') { - return 1; - } - return 0; - }); - for (var s = 0; s < subterms.length; s++) { - var subterm = subterms[s]; - var type = alg.getSubtermType(subterm); - if (type === 'compound') { - //console.log(subterm); - for (var s2 = 0; s2 < subterm[0].length; s2++) { - var sub2 = subterm[0][s2]; - alg.orderSubterms(sub2.subterms); - } - } - } - return subterms; - }, - getSubtermType: function(subterm) { - if (subterm.length === 2 && typeof subterm[0] === 'string' && typeof subterm[1] === 'number') { - return 'single'; - } else { - return 'compound'; - } - }, - likeSubterm: function(subterm1,subterm2) { - if (un(subterm1) && un(subterm2)) return true; - var sub1 = subterm1[0]; - var sub2 = subterm2[0]; - if (un(sub1) && un(sub2)) return true; - if (isEqual(sub1,sub2)) return true; - if (sub1 instanceof Array && sub2 instanceof Array) { - if (sub1.length !== sub2.length) return false; - sub1 = clone(sub1); - sub2 = clone(sub2); - for (var s1 = 0; s1 < sub1.length; s1++) { - var sub11 = sub1[s1]; - var found = false; - for (var s2 = 0; s2 < sub2.length; s2++) { - var sub22 = sub2[s2]; - if (sub11.sign === sub22.sign && arraysEqual(sub11.coeff,sub22.coeff) === true && arraysEqual(sub11.subterms,sub22.subterms) === true) { - found = true; - break; - } - } - if (found === false) return false; - } - return true; - } - return false; - }, - getHCF: function(exp) { - var exp = clone(exp); - if (exp.length === 1) return [{sign:1,coeff:[1,1],subterms:[]}]; - var term = exp[0]; - var sign = term.sign; - var num = term.coeff[0]; - var denom = term.coeff[1]; - var subterms = clone(term.subterms); - for (var t = 1; t < exp.length; t++) { - var term = exp[t]; - if (term.sign === 1) sign = 1; - num = hcf(num,term.coeff[0]); - denom = hcf(denom,term.coeff[1]); - for (var s1 = 0; s1 < subterms.length; s1++) { - var subterm1 = subterms[s1]; - var found = false; - for (var s2 = 0; s2 < term.subterms.length; s2++) { - var subterm2 = term.subterms[s2]; - if (alg.likeSubterm(subterm1,subterm2) === true) { - found = true; - subterm1[1] = Math.min(subterm1[1],subterm2[1]); - break; - } - } - if (found === false) { - subterms.splice(s1,1); - s1--; - } - } - } - return [{sign:sign,coeff:[num,denom],subterms:subterms}]; - }, - - hasNegativeIndices: function(exp) { - for (var e = 0; e < exp.length; e++) { - if (exp[e][1] < 0) return true; - } - return false; - }, - getCommonDenominator: function(exp) { - var exp = clone(exp); - var denomCoeff = 1; - var denomSubterms = []; - for (var e = 0; e < exp.length; e++) { - var term = exp[e]; - denomCoeff = (denomCoeff*term.coeff[1])/hcf(denomCoeff,term.coeff[1]); - var subterms = term.subterms; - for (var s = 0; s < subterms.length; s++) { - if (subterms[s][1] < 0) { - subterms[s][1] *= -1; - denomSubterms.push(subterms[s]); - } - } - } - for (var s1 = denomSubterms.length-1; s1 >= 0; s1--) { - var sub1 = denomSubterms[s1]; - for (var s2 = s1-1; s2 >= 0; s2--) { - var sub2 = denomSubterms[s2]; - if (alg.likeSubterm(sub1,sub2) === true) { - sub2[1] = Math.max(sub1[1],sub2[1]); - denomSubterms.splice(s1,1); - break; - } - } - } - - var exp2 = {sign:1,coeff:denomCoeff,subterms:denomSubterms}; - return exp2; - } -} - -function bound(value, min, max, roundTo) { - if (!un(roundTo)) - value = roundToNearest(value, roundTo); - return Math.max(min, Math.min(max, value)); -} - -function pngVis(sf, dl) { - if (un(sf)) sf = 0.4; - - var ctx = newctx({ - vis: false - }); - - var obj = container.childNodes; - for (var o = 0; o < obj.length; o++) { - if (obj[o].nodeType !== 1) - continue; - if (obj[o].nodeName.toLowerCase() !== 'canvas') - continue; - var dims = obj[o].getBoundingClientRect(); - var left = roundToNearest(xWindowToCanvas(dims.left), 1); - var top = roundToNearest(yWindowToCanvas(dims.top), 1); - flattenCanvases(ctx.canvas, obj[o], left, top); - } - - if (sf !== 1) { - var w = mainCanvasWidth * sf; - var h = mainCanvasHeight * sf; - var ctx2 = newctx({ - rect: [0, 0, w, h], - vis: false - }); - ctx2.drawImage(ctx.canvas, 0, 0, w, h); - var imgURL = canvasToPNG(ctx2.canvas); - } else { - var imgURL = canvasToPNG(ctx.canvas); - } - - //window.open(imgURL,'_blank'); - - return imgURL; - /* - if (boolean(dl, true) == true) { - var dlLink = document.createElement('a'); - dlLink.download = 'dl.png'; - dlLink.href = imgURL; - dlLink.dataset.downloadurl = ["image/png", dlLink.download, dlLink.href].join(':'); - document.body.appendChild(dlLink); - dlLink.click(); - document.body.removeChild(dlLink); - return; - } - return imgURL;*/ -} -function canvasToPNG(canvas, filename, l, t, w, h) { - var width = mainCanvasWidth; - var height = mainCanvasHeight; - if (isElement(canvas)) { - width = canvas.width; - height = canvas.height; - } - var canvas2 = document.createElement('canvas'); - canvas2.width = width; - canvas2.height = height; - var ctx2 = canvas2.getContext('2d'); - if (isElement(canvas)) { - ctx2.drawImage(canvas, 0, 0); - } else if (typeof canvas == 'object') { - for (var i = 0; i < canvas.length; i++) { - ctx2.drawImage(canvas[i], canvas[i].data[100], canvas[i].data[101]); - } - } - var left = l || 0; - var top = t || 0; - var w2 = w || width; - var h2 = h || height; - var canvas3 = document.createElement('canvas'); - canvas3.width = w2; - canvas3.height = h2; - var ctx3 = canvas3.getContext('2d'); - ctx3.drawImage(canvas2, -left, -top); - var imgURL = canvas3.toDataURL("image/png"); - return imgURL; -} - -function calcRects(obj) { - if (un(obj)) - obj = {}; - var left = def([obj.left, 0]); - var top = def([obj.top, 80]); - if (typeof obj.margin == 'object') { - obj.marginLeft = obj.margin[0]; - obj.marginTop = obj.margin[1]; - obj.marginRight = obj.margin[2]; - obj.marginBottom = obj.margin[3]; - } - var marginLeft = def([obj.marginLeft, obj.margin, 20]); - var marginBottom = def([obj.marginBottom, obj.margin, 20]); - var marginTop = def([obj.marginTop, obj.margin, 20]); - var marginRight = def([obj.marginRight, obj.margin, 20]); - var paddingVert = def([obj.paddingVert, obj.padding, 40]); - var paddingHoriz = def([obj.paddingHoriz, obj.padding, 40]); - var rows = def([obj.rows, 2]); - var cols = def([obj.cols, 2]); - var order = def([obj.order, 'v']); - - var width = (1200 - left - marginLeft - marginRight - (cols - 1) * paddingHoriz) / cols; - var height = (700 - top - marginTop - marginBottom - (rows - 1) * paddingVert) / rows; - - var arr = []; - - for (var r = 0; r < rows; r++) { - for (var c = 0; c < cols; c++) { - if (order == 'h') { - var index = r * cols + c; - } else { - var index = c * rows + r; - } - arr[index] = [ - left + marginLeft + c * (width + paddingHoriz), - top + marginTop + r * (height + paddingVert), - width, - height, - left + marginLeft + c * (width + paddingHoriz) + width, - top + marginTop + r * (height + paddingVert) + height, - left + marginLeft + c * (width + paddingHoriz) + 0.5 * width, - top + marginTop + r * (height + paddingVert) + 0.5 * height, - ]; - } - } - if (!un(obj.ctx)) { // if ctx is supplied, draw rects - for (var i = 0; i < arr.length; i++) { - obj.ctx.save(); - obj.ctx.strokeStyle = '#000'; - obj.ctx.lineWidth = 2; - obj.ctx.strokeRect(arr[i][0], arr[i][1], arr[i][2], arr[i][3]); - obj.ctx.lineWidth = 1; - obj.ctx.strokeStyle = '#666'; - obj.ctx.setLineDash([15, 15]); - obj.ctx.beginPath(); - obj.ctx.moveTo(arr[i][0], arr[i][7]); - obj.ctx.lineTo(arr[i][4], arr[i][7]); - obj.ctx.moveTo(arr[i][6], arr[i][1]); - obj.ctx.lineTo(arr[i][6], arr[i][5]); - obj.ctx.stroke(); - obj.ctx.restore(); - } - } - return arr; -} - -var dropMenus = []; -function dropMenu(obj) { - obj.open = false; - obj.selected = -1; - obj.buttonColor = def([obj.buttonColor, obj.selectedColor, '#3FF']); - obj.buttonBorderColor = def([obj.buttonBorderColor, '#000']); - obj.buttonBorder = boolean(obj.buttonBorder, true); - obj.showDownArrow = boolean(obj.showDownArrow, true); - obj.selectedColor = def([obj.selectedColor, '#3FF']); - obj.unselectedColor = def([obj.unselectedColor, '#CFF']); - obj.z = def([obj.z, 100000000]); - obj.listShowMax = def([obj.listShowMax, -1]); - obj.overflow = false; - obj.fullWidth = clone(obj.listRect[2]); - obj.font = def([obj.font, 'Arial']); - obj.fontSize = def([obj.fontSize, 16]); - obj.align = def([obj.align, 'left']); - - obj.canvas1 = createCanvas(obj.buttonRect[0], obj.buttonRect[1], obj.buttonRect[2], obj.buttonRect[3], true, false, true, obj.z); - obj.canvas1.parent = obj; - obj.canvas1.click = function () { - var obj = this.parent; - obj.open = !obj.open; - if (obj.open == true) { - showObj(obj.canvas2); - showObj(obj.canvas3); - if (obj.overflow) - showScroller(obj.scroller); - addListenerMove(window, obj.move); - addListener(obj.canvas2, obj.click); - addListenerStart(window, obj.windowClickClose); - if (obj.overflow == true) - window.addEventListener("mousewheel", obj.mouseWheelHandler, false); - } else { - obj.close(); - } - } - obj.canvas1.draw = function () { - var obj = this.parent; - var ctx = this.ctx; - var w = obj.buttonRect[2]; - var h = obj.buttonRect[3]; - ctx.clearRect(0, 0, w, h); - if (obj.buttonBorder == true) { - text({ - ctx: obj.canvas1.ctx, - text: [obj.title], - left: 1.5, - top: 1.5, - width: w - 3, - height: h - 3, - align: 'center', - vertAlign: 'middle', - box: { - type: 'loose', - color: obj.buttonColor, - borderWidth: 3, - borderColor: obj.buttonBorderColor - } - }); - } else { - text({ - ctx: obj.canvas1.ctx, - text: [obj.title], - left: 1.5, - top: 1.5, - width: w - 3, - height: h - 3, - align: 'center', - vertAlign: 'middle' - }); - } - if (obj.showDownArrow == true) { - ctx.fillStyle = '#000'; - ctx.lineJoin = 'round'; - ctx.lineCap = 'round'; - var l = w - 15; - var t = h / 2; - ctx.beginPath(); - ctx.moveTo(l - 8, t - 4); - ctx.lineTo(l + 8, t - 4); - ctx.lineTo(l, t + 8); - ctx.lineTo(l - 8, t - 4); - ctx.fill(); - } - } - obj.canvas1.draw(); - addListenerEnd(obj.canvas1, obj.canvas1.click); - obj.windowClickClose = function (e) { - for (var i = 0; i < dropMenus.length; i++) { - if (dropMenus[i].open == true) { - var obj = dropMenus[i]; - if (e.target !== obj.canvas1 && e.target !== obj.canvas2 && (un(obj.scroller) || (e.target !== obj.scroller.canvas && e.target !== obj.scroller.sliderCanvas))) { - obj.close(); - } - } - } - } - obj.close = function () { - var obj = this; - hideObj(obj.canvas2); - hideObj(obj.canvas3); - hideScroller(obj.scroller); - removeListenerMove(window, obj.move); - removeListener(obj.canvas2, obj.click); - removeListener(window, obj.windowClickClose); - if (obj.overflow == true) - window.removeEventListener("mousewheel", obj.mouseWheelHandler, false); - obj.selected = -1; - obj.open = false; - obj.draw(); - } - - obj.canvas2 = createCanvas(obj.listRect[0], obj.listRect[1], obj.listRect[2], obj.listRect[3], false, false, true, obj.z); // text - drawn once - obj.canvas2.parent = obj; - obj.canvas3 = createCanvas(obj.listRect[0], obj.listRect[1], obj.listRect[2], obj.listRect[3], false, false, false, obj.z + 1); // colors - obj.canvas3.parent = obj; - obj.scroller = createScroller({ - rect: [obj.listRect[0] + obj.listRect[2] - 20, obj.listRect[1], 20, obj.listRect[3] * obj.listShowMax], - z: obj.z + 2, - min: 0, - max: obj.data.length - obj.listShowMax, - inc: 1, - sliderHeight: (obj.listRect[3] * obj.listShowMax - 2 * 20) * (obj.listShowMax / obj.data.length), - funcMove: function (value) { - var obj = this.parent; - value = roundToNearest(value, 1); - obj.draw(value); - removeListenerMove(window, obj.move); - removeListener(obj.canvas2, obj.click); - removeListener(window, obj.windowClickClose); - }, - funcStop: function (value) { - var obj = this.parent; - value = roundToNearest(value, 1); - obj.draw(value); - addListenerMove(window, obj.move); - addListener(obj.canvas2, obj.click); - addListener(window, obj.windowClickClose); - } - }); - obj.scroller.parent = obj; - obj.mouseWheelHandler = function (e) { - // cross-browser wheel delta - var e = window.event || e; // old IE support - var delta = Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail))); - for (var i = 0; i < dropMenus.length; i++) { - if (dropMenus[i].open == true) { - var obj = dropMenus[i]; - setScrollerValue(obj.scroller, obj.scrollPos - delta, true); - break; - } - } - } - hideScroller(obj.scroller); - obj.updateData = function () { - var obj = this; - var height = this.listRect[3] * this.data.length; - if (this.listShowMax !== -1 && this.listShowMax < this.data.length) { - this.overflow = true; - this.listRect[2] = this.fullWidth - 20; - height = this.listRect[3] * this.listShowMax; - var s = this.scroller; - s.max = this.data.length - this.listShowMax; - s.sliderHeight = (height - 2 * 20) * (this.listShowMax / this.data.length); - s.incDist = (s.rect[3] - 2 * 20 - s.sliderHeight) / ((s.max - s.min) / s.inc); - s.sliderRect[3] = s.sliderHeight; - s.sliderCanvas.data[100] = s.sliderRect[0]; - s.sliderCanvas.data[101] = s.sliderRect[1]; - s.sliderCanvas.data[102] = s.sliderRect[2]; - s.sliderCanvas.data[103] = s.sliderRect[3]; - resizeCanvas(s.sliderCanvas, s.sliderCanvas.data[100], s.sliderCanvas.data[101], s.sliderCanvas.data[102], s.sliderCanvas.data[103]); - setScrollerValue(s, 0, true); - } else { - this.overflow = false; - this.listRect[2] = this.fullWidth; - } - this.scrollPos = 0; - this.canvas2.data[102] = this.listRect[2]; - this.canvas2.width = this.listRect[2]; - this.canvas2.data[103] = height; - this.canvas2.height = height; - resizeCanvas(this.canvas2, this.listRect[0], this.listRect[1], this.listRect[2], height); - this.canvas3.data[102] = this.listRect[2]; - this.canvas3.width = this.listRect[2]; - this.canvas3.data[103] = height; - this.canvas3.height = height; - resizeCanvas(this.canvas3, this.listRect[0], this.listRect[1], this.listRect[2], height); - obj.drawListText(); - obj.draw(); - - } - obj.drawListText = function () { - var obj = this; - var top = 0; - if (obj.overflow) - top -= obj.scrollPos * obj.listRect[3]; - var ctx = obj.canvas3.ctx; - for (var d = 0; d < obj.data.length; d++) { - text({ - ctx: ctx, - text: ['<><>' + obj.data[d]], - left: 0, - top: top, - width: obj.listRect[2], - height: obj.listRect[3], - align: this.align, - vertAlign: 'middle', - box: { - color: 'none', - borderWidth: 0.01 - } - }); - top += obj.listRect[3]; - ctx.strokeStyle = '#000'; - ctx.lineWidth = 1; - ctx.beginPath(); - ctx.moveTo(0, top); - ctx.lineTo(obj.listRect[2], top); - ctx.stroke(); - } - ctx.strokeStyle = '#000'; - ctx.lineWidth = 2; - ctx.beginPath(); - ctx.moveTo(0, 0); - ctx.lineTo(obj.listRect[2], 0); - ctx.moveTo(0, 0); - ctx.lineTo(0, top); - ctx.moveTo(obj.listRect[2], 0); - ctx.lineTo(obj.listRect[2], top); - ctx.stroke(); - } - obj.draw = function (newScrollPos) { - var obj = this; - var ctx = this.canvas2.ctx; - if (this.overflow == true) { - if (!un(newScrollPos) && newScrollPos !== obj.scrollPos) { - obj.scrollPos = newScrollPos; - var ctx2 = this.canvas3.ctx; - ctx2.clearRect(0, 0, this.listRect[2], this.listRect[3] * this.listShowMax); - obj.drawListText(); - } - ctx.fillStyle = this.unselectedColor; - ctx.fillRect(0, 0 - this.scrollPos * this.listRect[3], this.listRect[2], this.listRect[3] * this.data.length); - ctx.fillStyle = this.selectedColor; - ctx.fillRect(0, this.listRect[3] * this.selected - this.scrollPos * this.listRect[3], this.listRect[2], this.listRect[3]); - } else { - ctx.fillStyle = this.unselectedColor; - ctx.fillRect(0, 0, this.listRect[2], this.listRect[3] * this.data.length); - ctx.fillStyle = this.selectedColor; - ctx.fillRect(0, this.listRect[3] * this.selected, this.listRect[2], this.listRect[3]); - } - } - obj.updateData(); - obj.move = function (e) { - updateMouse(e); - var found = false; - for (var i = 0; i < dropMenus.length; i++) { - if (dropMenus[i].open == true) { - obj = dropMenus[i]; - var found = true; - break; - } - } - if (found == false) - return; - if (mouse.x < obj.listRect[0] || mouse.x > obj.listRect[0] + obj.listRect[2] || mouse.y < obj.listRect[1] || mouse.y > obj.listRect[1] + obj.data.length * obj.listRect[3]) { - if (obj.selected !== -1) { - obj.selected = -1; - obj.draw(); - } - } else { - var sel = Math.floor((mouse.y - obj.listRect[1]) / obj.listRect[3]); - if (obj.overflow == true) - sel += obj.scrollPos; - if (obj.selected !== sel) { - obj.selected = sel; - obj.draw(); - } - } - } - obj.click = function () { - var obj = this.parent; - if (!un(obj.func)) - obj.func.apply(); - obj.close(); - } - resize(); - obj.index = dropMenus.length; - dropMenus.push(obj); // place in global array - return obj; -} - -function drawTable(context, lineWidth, lineColor, l, t, hLines, vLines) { - context.save(); - context.beginPath(); - context.lineWidth = lineWidth; - context.strokeStyle = lineColor; - context.lineCap = 'round'; - // draw horizontal lines - for (h = 0; h < hLines.length; h++) { - context.moveTo(l + vLines[0], t + hLines[h]); - context.lineTo(l + vLines[vLines.length - 1], t + hLines[h]); - } - // draw vertical lines - for (v = 0; v < vLines.length; v++) { - context.moveTo(l + vLines[v], t + hLines[0]); - context.lineTo(l + vLines[v], t + hLines[hLines.length - 1]); - } - context.stroke(); - context.restore(); -} -function calcTable2(object) { - var left = object.left; - var top = object.top; - var cells = object.cells; - - var minCellWidth = object.minCellWidth || 80; - var maxCellWidth = object.maxCellWidth || 150; - var minCellHeight = object.minCellHeight || 100; - var minCellPadding = object.minCellPadding || 10; - var horizAlign = object.horizAlign || object.align || 'center'; - if (typeof object.text == 'object') { - var font = object.text.font || 'Arial'; - var fontSize = object.text.size || 32; - var textColor = object.text.color || '#000'; - } else { - var font = 'Arial'; - var fontSize = 32; - var textColor = '#000'; - } - - var numRows = cells.length; - var numCols = 0; - for (var i = 0; i < cells.length; i++) { - numCols = Math.max(cells[i].length, numCols); - } - var cellHeights = []; - for (var i = 0; i < numRows; i++) { - cellHeights[i] = minCellHeight; - } - var cellWidths = []; - for (var j = 0; j < numCols; j++) { - cellWidths[j] = minCellWidth; - } - var totalWidth = 0; - var totalHeight = 0; - - for (var i = 0; i < cells.length; i++) { - var maxHeight = minCellHeight; - for (var j = 0; j < cells[i].length; j++) { - if (typeof cells[i][j] == 'object') { - if (typeof cells[i][j].text !== 'object') - cells[i][j].text = []; - if (typeof cells[i][j].minWidth !== 'number') - cells[i][j].minWidth = 0; - if (typeof cells[i][j].minHeight !== 'number') - cells[i][j].minHeight = 0; - cells[i][j].text.unshift('<><><>'); - cells[i][j].text = reduceTags(cells[i][j].text); - var dims = drawMathsText(ctx, cells[i][j].text, fontSize, 0, 0, false, [], horizAlign, 'middle', text.color, 'measure'); - maxHeight = Math.max(dims[1] + 2 * minCellPadding, cells[i][j].minHeight, maxHeight); - cellWidths[j] = Math.max(dims[0] + 2 * minCellPadding, cells[i][j].minWidth, cellWidths[j]); - } - } - cellHeights[i] = Math.max(maxHeight, cellHeights[i]); - totalHeight += cellHeights[i]; - } - for (var j = 0; j < cellWidths.length; j++) { - totalWidth += cellWidths[j]; - } - - var horizPos = [left]; - for (var i = 0; i < cellWidths.length; i++) { - horizPos.push(horizPos[horizPos.length - 1] + cellWidths[i]) - } - - var vertPos = [top]; - for (var i = 0; i < cellHeights.length; i++) { - vertPos.push(vertPos[vertPos.length - 1] + cellHeights[i]) - } - - var cellDims = []; - - var topPos = top; - for (var i = 0; i < cells.length; i++) { - var leftPos = left; - cellDims[i] = []; - for (var j = 0; j < cells[i].length; j++) { - cellDims[i][j] = { - left: leftPos + 2, - top: topPos + 1, - width: cellWidths[j] - 9, - height: cellHeights[i] - 8, - border: false, - offset: [-40, 0.5 * (cellHeights[i] - 8) - 20], - fontSize: fontSize, - leftPoint: minCellPadding, - textColor: textColor, - textAlign: horizAlign, - fontSize: fontSize - }; - leftPos += cellWidths[j]; - } - topPos += cellHeights[i]; - } - - return { - cell: cellDims, - xPos: horizPos, - yPos: vertPos - }; -} -function drawTable2(object) { - /* EXAMPLE USAGE: - var j0001table1 = drawTable2({ - ctx:j0001buttonctx[0], - left:100, - top:150, - minCellWidth:80, - minCellHeight:50, - horizAlign:'center', - text:{font:'Arial',size:32,color:'#000'}, - outerBorder:{show:true,width:4,color:'#000'}, - innerBorder:{show:true,width:2,color:'#666',dash:[5,5]}, - cells:[ - [ // row 0{text:['<><>x'],color:'#CCF',minWidth:100,minHeight:70},{text:['<><>y'],color:'#CCF',minWidth:100,minHeight:70},{text:['<><><>z'],color:'#CCF',minWidth:100,minHeight:70}, - ], [ // row 1{},{text:['2']},{text:['<>3']}, - ], [ // row 2{text:['4']},{},{text:['<>6']}, - ], - ] - }); - - // CAN EASILY USE IN CONJUNCTION WITH INPUTS()... - inputs({ - inputs:[ - // j0001table1.cell[row][col] - nb. start counting from zero - j0001table1.cell[1][0], - j0001table1.cell[2][1] - ], - checkFuncs:[ - function(input) { - if (input.stringJS == '1') { - return true; - } else { - return false; - } - }, - function(input) { - if (input.stringJS == '5') { - return true; - } else { - return false; - } - }, - ] - }); - */ - - if (typeof object.sf !== 'undefined') { - var sf = object.sf; - } else { - var sf = 1; - } - var ctx = object.ctx || object.context; - var left = object.left * sf; - var top = object.top * sf; - var cells = object.cells; - - var minCellWidth = object.minCellWidth * sf || 80 * sf; - var maxCellWidth = object.maxCellWidth * sf || Math.max(1200 * sf, object.minCellWidth * sf); - var minCellHeight = object.minCellHeight * sf || 100 * sf; - var minCellPadding = object.minCellPadding * sf || 7 * sf; - var paddingH = minCellPadding; - var paddingV = minCellPadding; - if (typeof object.paddingH == 'number') - paddingH = object.paddingH * sf; - if (typeof object.paddingV == 'number') - paddingV = object.paddingV * sf; - var horizAlign = object.horizAlign || object.align || 'center'; - if (typeof object.text == 'object') { - var font = object.text.font || 'Arial'; - var fontSize = object.text.size || 32; - var textColor = object.text.color || '#000'; - } else { - var font = 'Arial'; - var fontSize = 32; - var textColor = '#000'; - } - if (typeof object.alpha == 'number') { - var alpha = object.alpha; - } else { - var alpha = 1; - } - var lineJoin = object.lineJoin || object.lineCap || 'round'; - var lineCap = object.lineCap || object.lineJoin || 'round'; - var outerBorder = {}; - if (typeof object.outerBorder == 'object') { - outerBorder.show = boolean(object.outerBorder.show, true); - outerBorder.width = object.outerBorder.width * sf || 4 * sf; - if (typeof object.outerBorder.color == 'undefined') { - outerBorder.color = colorA('#000', alpha); - } else { - outerBorder.color = colorA(object.outerBorder.color, alpha); - } - outerBorder.dash = object.outerBorder.dash || []; - } else { - outerBorder.show = true; - outerBorder.width = 4 * sf; - outerBorder.color = colorA('#000', alpha); - outerBorder.dash = []; - } - outerBorder.dash = enlargeDash(outerBorder.dash, sf); - var innerBorder = {}; - if (typeof object.innerBorder == 'object') { - innerBorder.show = boolean(object.innerBorder.show, true); - innerBorder.width = object.innerBorder.width * sf || 4 * sf; - if (typeof object.innerBorder.color == 'undefined') { - innerBorder.color = colorA('#000', alpha); - } else { - innerBorder.color = colorA(object.innerBorder.color, alpha); - } - innerBorder.dash = object.innerBorder.dash || []; - } else { - innerBorder.show = true; - innerBorder.width = 4 * sf; - innerBorder.color = colorA('#000', alpha); - innerBorder.dash = [20, 15]; - } - innerBorder.dash = enlargeDash(innerBorder.dash, sf); - var tableAlignHoriz = object.tableAlignHoriz || 'left'; // is the whole table centred on [left,top]? - var tableAlignVert = object.tableAlignVert || 'top'; - - var numRows = cells.length; - var numCols = 0; - for (var i = 0; i < cells.length; i++) { - numCols = Math.max(cells[i].length, numCols); - } - var cellHeights = []; - for (var i = 0; i < numRows; i++) { - cellHeights[i] = minCellHeight; - } - var cellWidths = []; - for (var j = 0; j < numCols; j++) { - cellWidths[j] = minCellWidth; - } - var totalWidth = 0; - var totalHeight = 0; - - if (typeof hiddenCanvas == 'undefined') { - var hiddenCanvas = document.createElement('canvas'); - hiddenCanvas.width = mainCanvasWidth * sf; - hiddenCanvas.height = mainCanvasHeight * sf; - hiddenCanvas.ctx = hiddenCanvas.getContext('2d'); - } - - for (var r = 0; r < cells.length; r++) { - var maxHeight = minCellHeight; - for (var c = 0; c < cells[r].length; c++) { - if (typeof cells[r][c] == 'object') { - if (typeof cells[r][c].text !== 'object') { - cells[r][c].text = []; - } else { - cells[r][c].text = clone(cells[r][c].text); - } - if (typeof cells[r][c].color !== 'string') - cells[r][c].color = 'none'; - if (typeof cells[r][c].minWidth !== 'number') - cells[r][c].minWidth = 0; - if (typeof cells[r][c].minHeight !== 'number') - cells[r][c].minHeight = 0; - var font2 = font; - var fontSize2 = fontSize; - var textColor2 = textColor; - if (!un(cells[r][c].font)) - font2 = cells[r][c].font; - if (!un(cells[r][c].fontSize)) - fontSize2 = cells[r][c].fontSize; - if (!un(cells[r][c].textColor)) - textColor2 = cells[r][c].textColor; - if (un(cells[r][c].styled)) { - cells[r][c].text.unshift('<><><>'); - cells[r][c].styled = true; - } - //var dims = drawMathsText(ctx,cells[r][c].text,fontSize,0,0,false,[],horizAlign,'middle',text.color,'measure'); - //maxHeight = Math.max(dims[1]+2*minCellPadding,cells[r][c].minHeight,maxHeight); - //cellWidths[c] = Math.max(dims[0]+2*minCellPadding,cells[r][c].minWidth,cellWidths[c]); - - var cellText = text({ - ctx: hiddenCanvas.ctx, - left: 0, - top: 0, - width: maxCellWidth, - textArray: cells[r][c].text, - minTightWidth: 5, - minTightHeight: 5, - box: cells[r][c].box, - sf: sf - }); - maxHeight = Math.max(cellText.tightRect[3] + 2 * paddingV, cells[r][c].minHeight * sf, maxHeight); - cellWidths[c] = Math.max(cellText.tightRect[2] + 3 * paddingH, cells[r][c].minWidth * sf, cellWidths[c]); - } - } - cellHeights[r] = Math.max(maxHeight, cellHeights[r]); - totalHeight += cellHeights[r]; - } - for (var j = 0; j < cellWidths.length; j++) { - totalWidth += cellWidths[j]; - } - - if (tableAlignHoriz == 'center') { - left = left - totalWidth / 2; - } else if (tableAlignHoriz == 'right') { - left = left - totalWidth; - } - - if (tableAlignVert == 'middle') { - top = top - totalHeight / 2; - } else if (tableAlignVert == 'bottom') { - top = top - totalHeight; - } - - ctx.save(); - ctx.lineCap = lineCap; - ctx.lineJoin = lineJoin; - - var cellDims = []; - - var horizPos = [left]; - for (var i = 0; i < cellWidths.length; i++) { - horizPos.push(horizPos[horizPos.length - 1] + cellWidths[i]) - } - - var vertPos = [top]; - for (var i = 0; i < cellHeights.length; i++) { - vertPos.push(vertPos[vertPos.length - 1] + cellHeights[i]) - } - - // write text to each cell - var topPos = top; - for (var i = 0; i < cells.length; i++) { - var leftPos = left; - cellDims[i] = []; - for (var j = 0; j < cells[i].length; j++) { - cellDims[i][j] = { - left: leftPos + 2, - top: topPos + 1, - width: cellWidths[j] - 9, - height: cellHeights[i] - 8, - border: false, - offset: [-40, 0.5 * (cellHeights[i] - 8) - 20], - fontSize: fontSize, - leftPoint: paddingH, - textColor: textColor, - textAlign: horizAlign, - fontSize: fontSize - }; - if (cells[i][j].highlight == true) { - if (typeof cells[i][j].color == 'undefined' || cells[i][j].color !== 'none') { - ctx.fillStyle = colorA(invertColor(cells[i][j].color), alpha); - } else { - ctx.fillStyle = colorA(invertColor('#FFC'), alpha); - } - ctx.fillRect(leftPos, topPos, cellWidths[j], cellHeights[i]); - } else if (typeof cells[i][j].color == 'undefined' || cells[i][j].color !== 'none') { - ctx.fillStyle = colorA(cells[i][j].color, alpha); - ctx.fillRect(leftPos, topPos, cellWidths[j], cellHeights[i]); - } - /*if (horizAlign == 'left') { - var dims = drawMathsText(ctx,cells[i][j].text,fontSize,leftPos+minCellPadding,topPos+0.5*cellHeights[i],false,[],horizAlign,'middle',textColor); - } else if (horizAlign == 'center') { - var dims = drawMathsText(ctx,cells[i][j].text,fontSize,leftPos+0.5*cellWidths[j],topPos+0.5*cellHeights[i],false,[],horizAlign,'middle',textColor); - } else if (horizAlign == 'right') { - var dims = drawMathsText(ctx,cells[i][j].text,fontSize,leftPos+cellWidths[j]-minCellPadding,topPos+0.5*cellHeights[i],false,[],horizAlign,'middle',textColor); - }*/ - var align = horizAlign; - if (!un(cells[i][j].align)) - align = cells[i][j].align; - var cellText = text({ - ctx: ctx, - left: leftPos + paddingH, - top: topPos + paddingV, - width: cellWidths[j] - 2 * paddingH, - height: cellHeights[i] - 2 * paddingV, - textArray: cells[i][j].text, - textAlign: align, - vertAlign: 'middle', - padding: 0.001, - box: cells[i][j].box, - sf: sf - //box:{type:'tight'} - }); - //console.log(cellText.tightRect[2],cellText.tightRect[3]); - leftPos += cellWidths[j]; - } - topPos += cellHeights[i]; - } - - // draw inner border - if (innerBorder.show == true) { - ctx.strokeStyle = innerBorder.color; - ctx.lineWidth = innerBorder.width; - if (!ctx.setLineDash) { - ctx.setLineDash = function () {} - } - ctx.setLineDash(innerBorder.dash); - var leftPos = left; - for (var i = 0; i < cellWidths.length - 1; i++) { - leftPos += cellWidths[i]; - ctx.beginPath(); - ctx.moveTo(leftPos, top); - ctx.lineTo(leftPos, top + totalHeight); - ctx.stroke(); - } - var topPos = top; - for (var i = 0; i < cellHeights.length - 1; i++) { - topPos += cellHeights[i]; - ctx.beginPath(); - ctx.moveTo(left, topPos); - ctx.lineTo(left + totalWidth, topPos); - ctx.stroke(); - } - } - - // draw outer border - if (outerBorder.show == true) { - ctx.strokeStyle = outerBorder.color; - ctx.lineWidth = outerBorder.width; - if (!ctx.setLineDash) { - ctx.setLineDash = function () {} - } - ctx.setLineDash(outerBorder.dash); - ctx.beginPath(); - ctx.strokeRect(left, top, totalWidth, totalHeight); - } - - ctx.restore(); - - return { - cell: cellDims, - xPos: horizPos, - yPos: vertPos - }; -} -function drawTable3(object) { - var sf = typeof object.sf !== 'undefined' ? object.sf : 1; - var ctx = object.ctx || object._ctx || object.context; - var left = object.left * sf; - var top = object.top * sf; - var cells = object.cells; - - var widths = clone(object.widths); - var heights = clone(object.heights); - if (sf !== 1) { - for (var w = 0; w < widths.length; w++) widths[w] = widths[w] * sf; - for (var h = 0; h < heights.length; h++) heights[h] = heights[h] * sf; - } - var minCellPadding = object.minCellPadding * sf || 0; - var paddingH = minCellPadding; - var paddingV = minCellPadding; - if (typeof object.paddingH == 'number') paddingH = object.paddingH * sf; - if (typeof object.paddingV == 'number') paddingV = object.paddingV * sf; - //var innerPaddingH = !un(obj.innerPaddingH) ? obj.innerPaddingH*sf : 0; - //var innerPaddingV = !un(obj.innerPaddingV) ? obj.innerPaddingV*sf : 0; - var horizAlign = object.horizAlign || object.align || 'center'; - var alpha = typeof object.alpha == 'number' ? object.alpha : 1; - var lineJoin = object.lineJoin || object.lineCap || 'round'; - var lineCap = object.lineCap || object.lineJoin || 'round'; - var outerBorder = {}; - if (typeof object.outerBorder == 'object') { - outerBorder.show = boolean(object.outerBorder.show, true); - outerBorder.width = object.outerBorder.width * sf || 4 * sf; - if (typeof object.outerBorder.color == 'undefined') { - outerBorder.color = colorA('#000', alpha); - } else { - outerBorder.color = colorA(object.outerBorder.color, alpha); - } - outerBorder.dash = object.outerBorder.dash || []; - outerBorder.radius = object.outerBorder.radius*sf || 0; - } else { - outerBorder.show = true; - outerBorder.width = 4 * sf; - outerBorder.color = colorA('#000', alpha); - outerBorder.dash = []; - outerBorder.radius = 0; - } - outerBorder.dash = enlargeDash(outerBorder.dash, sf); - var innerBorder = {}; - if (typeof object.innerBorder == 'object') { - innerBorder.show = boolean(object.innerBorder.show, true); - innerBorder.width = object.innerBorder.width * sf || 4 * sf; - if (typeof object.innerBorder.color == 'undefined') { - innerBorder.color = colorA('#000', alpha); - } else { - innerBorder.color = colorA(object.innerBorder.color, alpha); - } - innerBorder.dash = object.innerBorder.dash || []; - innerBorder.dash = enlargeDash(innerBorder.dash, sf); - } else { - innerBorder.show = false; - /*innerBorder.show = true; - innerBorder.width = 4 * sf; - innerBorder.color = colorA('#000', alpha); - innerBorder.dash = [20, 15]; - innerBorder.dash = enlargeDash(innerBorder.dash, sf);*/ - } - - var tableAlignHoriz = object.tableAlignHoriz || 'center'; // is the whole table centred on [left,top]? - var tableAlignVert = object.tableAlignVert || 'middle'; - if (!un(object.align)) { - tableAlignHoriz = object.align[0] == -1 ? 'left' : object.align[0] == 0 ? 'center' : 'right'; - tableAlignVert = object.align[1] == -1 ? 'top' : object.align[1] == 0 ? 'middle' : 'bottom'; - } - if (typeof object.text == 'object') { - var font = object.text.font || 'Arial'; - var fontSize = object.text.size || 28; - var textColor = object.text.color || '#000'; - } else { - var font = 'Arial'; - var fontSize = 28; - var textColor = '#000'; - } - var fracScale = object.fracScale; - var algPadding = object.algPadding; - - var totalWidth = arraySum(widths); - var totalHeight = arraySum(heights); - - ctx.save(); - ctx.lineCap = lineCap; - ctx.lineJoin = lineJoin; - - var cellDims = []; - - var horizPos = [left]; - for (var i = 0; i < widths.length; i++) { - horizPos.push(horizPos[horizPos.length - 1] + widths[i]) - } - - var vertPos = [top]; - for (var i = 0; i < heights.length; i++) { - vertPos.push(vertPos[vertPos.length - 1] + heights[i]) - } - - // color, inner border & text for cells - var topPos = top; - var cellTextMeasure = []; - for (var i = 0; i < cells.length; i++) { - var leftPos = left; - cellDims[i] = []; - var skipCells = 0; - cellTextMeasure[i] = []; - for (var j = 0; j < cells[i].length; j++) { - var cell = cells[i][j]; - if (skipCells > 0) { - skipCells--; - continue; - } - if (un(cell.colSpan)) { - var cellWidth = widths[j]; - } else { - var cellWidth = 0; - for (var k = j; k < Math.min(j + cell.colSpan, cells[i].length); k++) { - cellWidth += widths[k]; - } - skipCells = cell.colSpan - 1; - } - var cellPaddingH = def([cell.paddingH, cell.padding, paddingH]); - var cellPaddingV = def([cell.paddingV, cell.padding, paddingV]); - cellDims[i][j] = { - left: leftPos, - top: topPos, - width: cellWidth, - height: heights[i], - border: false, - offset: [-40, 0.5 * (heights[i]) - 20], - leftPoint: cellPaddingH, - }; - - var c1 = (typeof cell.color !== 'undefined' && cell.color !== 'none') ? true : false; - var c2 = (!un(cell.box) && cell.box.show == true) ? true : false; - var hl = cell.highlight; - /*if (!un(object.isInput)) { - if (draw.mode == 'interact') { - var selected = boolean(cell.toggle, false); - } else { - var selected = boolean(cell.ans, false); - } - if (!un(cell.selColors)) { - var isInputColor = selected ? cell.selColors[1] : cell.selColors[0]; - } else if (!un(object.isInput.selColors)) { - var isInputColor = selected ? object.isInput.selColors[1] : object.isInput.selColors[0]; - } else { - var isInputColor = selected ? '#66F' : '#CCF'; - } - */ - - if (c2 == true) { - var box = cell.box; - //var fillColor = isInputColor || box.fillColor || box.color || undefined; - var fillColor = box.fillColor || box.color || undefined; - var lineColor = box.borderColor || box.lineColor || undefined; - if (hl == true) { - if (!un(fillColor) && fillColor !== 'none') - fillColor = colorA(invertColor(fillColor), alpha); - if (!un(lineColor) && lineColor !== 'none') - lineColor = colorA(invertColor(lineColor), alpha); - } - var lineWidth = box.borderWidth || box.lineWidth || box.width || 3; - lineWidth = lineWidth * sf; - var dash = def([box.dash, []]); - var radius = box.borderRadius || box.radius || 0; - radius = radius * sf; - roundedRect(ctx, leftPos + cellPaddingH, topPos + cellPaddingV, cellWidth - 2 * cellPaddingH, heights[i] - 2 * cellPaddingV, radius, lineWidth, lineColor, fillColor, dash); - } else if (c1 == true) { - //var fillColor = isInputColor || cell.color; - var fillColor = cell.color; - if (hl == true) { - fillColor = colorA(invertColor(fillColor), alpha); - } else { - fillColor = colorA(fillColor, alpha); - } - /*ctx.fillStyle = fillColor; - ctx.globalCompositeOperation = 'destination-over'; // draw behind existing content - ctx.fillRect(leftPos,topPos,cellWidth,heights[i]); - ctx.globalCompositeOperation = 'source-over'; // default*/ - roundedRect(ctx, leftPos + cellPaddingH, topPos + cellPaddingV, cellWidth - 2 * cellPaddingH, heights[i] - 2 * cellPaddingV, 0, 0, 'none', fillColor); - } else { - if (hl == true) { - ctx.fillStyle = colorA(invertColor(mainCanvasFillStyle), alpha); - ctx.globalCompositeOperation = 'destination-over'; // draw behind existing content - ctx.fillRect(leftPos, topPos, cellWidth, heights[i]); - ctx.globalCompositeOperation = 'source-over'; // default - } - } - - if (innerBorder.show == true) { - ctx.strokeStyle = innerBorder.color; - ctx.lineWidth = innerBorder.width; - if (un(ctx.setLineDash)) { - ctx.setLineDash = function () {} - } - ctx.setLineDash(innerBorder.dash); - ctx.beginPath(); - if (i > 0) { - ctx.moveTo(leftPos, topPos); - ctx.lineTo(leftPos + cellWidth, topPos); - } - if (i < cells.length - 1) { - ctx.moveTo(leftPos, topPos + heights[i]); - ctx.lineTo(leftPos + cellWidth, topPos + heights[i]); - } - if (j > 0) { - ctx.moveTo(leftPos, topPos); - ctx.lineTo(leftPos, topPos + heights[i]); - } - if (j < cells[i].length - 1 && (un(cell.colSpan) || j + cell.colSpan < cells[i].length - 1)) { - ctx.moveTo(leftPos + cellWidth, topPos); - ctx.lineTo(leftPos + cellWidth, topPos + heights[i]); - } - ctx.stroke(); - } - - if (!un(cell.text)) { - var txt = clone(cell.text); - var align = [0, 0]; - if (tableAlignHoriz == 'left') align[0] = -1; - if (tableAlignHoriz == 'center') align[0] = 0; - if (tableAlignHoriz == 'right') align[0] = 1; - if (tableAlignVert == 'top') align[1] = -1; - if (tableAlignVert == 'middle') align[1] = 0; - if (tableAlignVert == 'bottom') align[1] = 1; - if (cell.align == 'left') align[0] = -1; - if (cell.align == 'center') align[0] = 0; - if (cell.align == 'right') align[0] = 1; - if (cell.vertAlign == 'top') align[1] = -1; - if (cell.vertAlign == 'middle') align[1] = 0; - if (cell.vertAlign == 'bottom') align[1] = 1; - if (typeof cell.align == 'object') align = cell.align; - var font2 = def([cell.font, font]); - var fontSize2 = def([cell.fontSize, fontSize]); - var textColor2 = def([cell.textColor, textColor]); - var italic2 = def([cell.italic, false]); - var bold2 = def([cell.bold, false]); - var paddingH2 = def([cell.paddingH, cell.padding, paddingH]); - var paddingV2 = def([cell.paddingV, cell.padding, paddingV]); - var fracScale = def([cell.fracScale, fracScale]); - var algPadding = def([cell.algPadding, algPadding]); - var marginLeft = def([cell.marginLeft, object.marginLeft, 0]); - var marginRight = def([cell.marginRight, object.marginRight, 0]); - var lineSpacingFactor = def([cell.lineSpacingFactor, object.lineSpacingFactor, 1.2]); - var lineSpacingStyle = def([cell.lineSpacingStyle, cell.spacingStyle, object.lineSpacingStyle, object.spacingStyle, "variable"]); - - var backgroundColor = typeof cell.color !== 'undefined' && cell.color !== 'none' ? cell.color : '#FFF'; - var box = clone(cell.box); - - if (!un(box) && typeof isInputColor !== 'undefined') box.color = isInputColor; - - cellTextMeasure[i][j] = text({ - ctx: ctx, - rect: [leftPos + paddingH2, topPos + paddingV2, cellWidth - 2 * paddingH2, heights[i] - 2 * paddingV2], - text: txt, - box: box, - sf: sf, - align: align, - font: font2, - fontSize: fontSize2, - color: textColor2, - italic: italic2, - bold: bold2, - selected: hl, - backgroundColor: backgroundColor, - fracScale:fracScale, - algPadding:algPadding, - marginLeft:marginLeft, - marginRight:marginRight, - lineSpacingFactor:lineSpacingFactor, - lineSpacingStyle:lineSpacingStyle - }); - } - - leftPos += cellWidth; - } - topPos += heights[i]; - } - - // draw outer border - if (outerBorder.show == true) { - /*ctx.strokeStyle = outerBorder.color; - ctx.lineWidth = outerBorder.width; - if (un(ctx.setLineDash)) { - ctx.setLineDash = function () {} - } - ctx.setLineDash(outerBorder.dash); - ctx.beginPath(); - ctx.strokeRect(left, top, totalWidth, totalHeight);*/ - var color = outerBorder.color || '#000'; - var width = outerBorder.width || 4; - var radius = outerBorder.radius || 0; - var dash = outerBorder.dash || [0,0]; - roundedRect(ctx,left,top,totalWidth,totalHeight,radius,width,color,'none',dash) - } - - ctx.restore(); - - return { - cellTextMeasure: cellTextMeasure, - cell: cellDims, - xPos: horizPos, - yPos: vertPos - }; -} -function createScrollTable(object) { - var left = object.left; - var top = object.top; - var z = object.z || object.zIndex || 2; - - var padding = 2; // padding for canvas - var fullRect = [0, 0, 100, 100]; - var visRect = [left, top, 100, 100]; - var topRowRect = [left, top, 100, 100]; - var scrollRect = [left, top, 25, 10]; - - var ctxVis = newctx({ - rect: visRect, - z: z - }); - var ctxTopRow = newctx({ - rect: topRowRect, - z: z - }); - var ctxInvis = newctx({ - rect: fullRect, - vis: false - }); - - var topRowFreeze = boolean(object.topRowFreeze, true); - - var scrollMax = 10; - var scrollDiff = 5; - - var scroll = createScroller({ - rect: scrollRect, - max: scrollMax, - zIndex: z, - funcMove: function (value) { - this.table.scrollPos = (value / this.table.scrollMax) * this.table.scrollDiff; - this.table.redraw(); - }, - funcStop: function (value) { - this.table.scrollPos = (value / this.table.scrollMax) * this.table.scrollDiff; - this.table.redraw(); - } - }); - - if (!un(object.funcMove)) { - ctxVis.canvas.style.pointerEvents = 'auto'; - ctxVis.data[6] = true; - ctxVis.data[106] = true; - addListenerMove(ctxVis.canvas, function (e) { - updateMouse(e); - var r = -1, - c = -1; - for (var x = 0; x < this.table.xPos.length - 1; x++) { - if (mouse.x >= this.table.xPos[x] + this.table.ctxVis.data[100] && mouse.x <= this.table.xPos[x + 1] + this.table.ctxVis.data[100]) { - c = x; - break; - } - } - if (this.table.topRowFreeze && mouse.y <= this.table.yPos[1] + this.table.ctxVis.data[101]) { - r = 0; - } else { - for (var y = 0; y < this.table.yPos.length - 1; y++) { - if (mouse.y + this.table.scrollPos >= this.table.yPos[y] + this.table.ctxVis.data[101] && mouse.y + this.table.scrollPos <= this.table.yPos[y + 1] + this.table.ctxVis.data[101]) { - r = y; - break; - } - } - } - this.table.funcMove(r, c); - }); - } else { - object.funcMove = function () {}; - } - if (!un(object.funcClick)) { - ctxVis.canvas.style.pointerEvents = 'auto'; - ctxVis.data[6] = true; - ctxVis.data[106] = true; - addListener(ctxVis.canvas, function (e) { - updateMouse(e); - var r = -1, - c = -1, - xProp = 0, - yProp = 0; - for (var x = 0; x < this.table.xPos.length - 1; x++) { - if (mouse.x >= this.table.xPos[x] + this.table.ctxVis.data[100] && mouse.x <= this.table.xPos[x + 1] + this.table.ctxVis.data[100]) { - c = x; - xProp = (mouse.x - (this.table.xPos[x] + this.table.ctxVis.data[100])) / (this.table.xPos[x + 1] - this.table.xPos[x]); - break; - } - } - if (this.table.topRowFreeze && mouse.y <= this.table.yPos[1] + this.table.ctxVis.data[101]) { - r = 0; - } else { - for (var y = 0; y < this.table.yPos.length - 1; y++) { - if (mouse.y + this.table.scrollPos >= this.table.yPos[y] + this.table.ctxVis.data[101] && mouse.y + this.table.scrollPos <= this.table.yPos[y + 1] + this.table.ctxVis.data[101]) { - r = y; - yProp = (mouse.y - (this.table.yPos[y] + this.table.ctxVis.data[101])) / (this.table.yPos[y + 1] - this.table.yPos[y]); - break; - } - } - } - this.table.funcClick(r, c, xProp, yProp); - }); - } else { - object.funcClick = function () {}; - } - - object.ctxVis = ctxVis; - object.ctxInvis = ctxInvis; - object.ctxTopRow = ctxTopRow; - object.padding = padding; - object.scroller = scroll; - object.scrollPos = 0; - object.scrollMax = scrollMax; - object.scrollDiff = scrollDiff; - object.topRowFreeze = topRowFreeze; - object.redraw = function () { - this.ctxVis.clearRect(0, 0, this.ctxVis.canvas.data[102], this.ctxVis.canvas.data[103]); - this.ctxVis.drawImage(this.ctxInvis.canvas, 0, -this.scrollPos); - }; - - object.scroller.table = object; - object.ctxVis.canvas.table = object; - - if (!un(object.additionalDraw)) { - object.additionalDraw(); - } - object.refreshCells = function () { - var sf = def([this.sf, 1]); - - var left = this.left * sf; - var top = this.top * sf; - var cells = this.cells; - var z = this.z || this.zIndex || 2; - - var minCellWidth = this.minCellWidth * sf || 80 * sf; - var maxCellWidth = this.maxCellWidth * sf || Math.max(1200 * sf, this.minCellWidth * sf); - var minCellHeight = this.minCellHeight * sf || 100 * sf; - var minCellPadding = this.minCellPadding * sf || 7 * sf; - var paddingH = minCellPadding; - var paddingV = minCellPadding; - if (typeof this.paddingH == 'number') - paddingH = this.paddingH * sf; - if (typeof this.paddingV == 'number') - paddingV = this.paddingV * sf; - var horizAlign = this.horizAlign || this.align || 'center'; - if (typeof this.text == 'this') { - var font = this.text.font || 'Arial'; - var fontSize = this.text.size || 32; - var textColor = this.text.color || '#000'; - } else { - var font = 'Arial'; - var fontSize = 32; - var textColor = '#000'; - } - if (typeof this.alpha == 'number') { - var alpha = this.alpha; - } else { - var alpha = 1; - } - var lineJoin = this.lineJoin || this.lineCap || 'round'; - var lineCap = this.lineCap || this.lineJoin || 'round'; - var outerBorder = {}; - if (typeof this.outerBorder == 'object') { - outerBorder.show = boolean(this.outerBorder.show, true); - outerBorder.width = this.outerBorder.width * sf || 4 * sf; - if (typeof this.outerBorder.color == 'undefined') { - outerBorder.color = colorA('#000', alpha); - } else { - outerBorder.color = colorA(this.outerBorder.color, alpha); - } - outerBorder.dash = this.outerBorder.dash || []; - } else { - outerBorder.show = true; - outerBorder.width = 4 * sf; - outerBorder.color = colorA('#000', alpha); - outerBorder.dash = []; - } - outerBorder.dash = enlargeDash(outerBorder.dash, sf); - var innerBorder = {}; - if (typeof this.innerBorder == 'object') { - innerBorder.show = boolean(this.innerBorder.show, true); - innerBorder.width = this.innerBorder.width * sf || 4 * sf; - if (typeof this.innerBorder.color == 'undefined') { - innerBorder.color = colorA('#000', alpha); - } else { - innerBorder.color = colorA(this.innerBorder.color, alpha); - } - innerBorder.dash = this.innerBorder.dash || []; - } else { - innerBorder.show = true; - innerBorder.width = 4 * sf; - innerBorder.color = colorA('#000', alpha); - innerBorder.dash = [20, 15]; - } - innerBorder.dash = enlargeDash(innerBorder.dash, sf); - var tableAlignHoriz = this.tableAlignHoriz || 'left'; // is the whole table centred on [left,top]? - var tableAlignVert = this.tableAlignVert || 'top'; - - var numRows = cells.length; - var numCols = 0; - for (var i = 0; i < cells.length; i++) { - numCols = Math.max(cells[i].length, numCols); - } - var cellHeights = []; - for (var i = 0; i < numRows; i++) { - cellHeights[i] = minCellHeight; - } - var cellWidths = []; - for (var j = 0; j < numCols; j++) { - cellWidths[j] = minCellWidth; - } - var totalWidth = 0; - var totalHeight = 0; - - var cellHeights = []; - for (var i = 0; i < numRows; i++) { - cellHeights[i] = minCellHeight; - } - var cellWidths = []; - for (var j = 0; j < numCols; j++) { - cellWidths[j] = minCellWidth; - } - var totalWidth = 0; - var totalHeight = 0; - - if (typeof hiddenCanvas == 'undefined') { - var hiddenCanvas = document.createElement('canvas'); - hiddenCanvas.width = mainCanvasWidth * sf; - hiddenCanvas.height = mainCanvasHeight * sf; - hiddenCanvas.ctx = hiddenCanvas.getContext('2d'); - } - - for (var r = 0; r < cells.length; r++) { - var maxHeight = minCellHeight; - for (var c = 0; c < cells[r].length; c++) { - if (typeof cells[r][c] == 'this') { - if (typeof cells[r][c].text !== 'this') { - cells[r][c].text = []; - } else { - cells[r][c].text = clone(cells[r][c].text); - } - if (typeof cells[r][c].color !== 'string') - cells[r][c].color = 'none'; - if (typeof cells[r][c].minWidth !== 'number') - cells[r][c].minWidth = 0; - if (typeof cells[r][c].minHeight !== 'number') - cells[r][c].minHeight = 0; - var font2 = font; - var fontSize2 = fontSize; - var textColor2 = textColor; - if (!un(cells[r][c].font)) - font2 = cells[r][c].font; - if (!un(cells[r][c].fontSize)) - fontSize2 = cells[r][c].fontSize; - if (!un(cells[r][c].textColor)) - textColor2 = cells[r][c].textColor; - if (un(cells[r][c].styled)) { - cells[r][c].text.unshift('<><><>'); - cells[r][c].styled = true; - } - //var dims = drawMathsText(ctx,cells[r][c].text,fontSize,0,0,false,[],horizAlign,'middle',text.color,'measure'); - //maxHeight = Math.max(dims[1]+2*minCellPadding,cells[r][c].minHeight,maxHeight); - //cellWidths[c] = Math.max(dims[0]+2*minCellPadding,cells[r][c].minWidth,cellWidths[c]); - - var cellText = text({ - ctx: hiddenCanvas.ctx, - left: 0, - top: 0, - width: maxCellWidth, - textArray: cells[r][c].text, - minTightWidth: 5, - minTightHeight: 5, - box: cells[r][c].box, - sf: sf - }); - maxHeight = Math.max(cellText.tightRect[3] + 2 * paddingV, cells[r][c].minHeight * sf, maxHeight); - cellWidths[c] = Math.max(cellText.tightRect[2] + 3 * paddingH, cells[r][c].minWidth * sf, cellWidths[c]); - } - } - cellHeights[r] = Math.max(maxHeight, cellHeights[r]); - totalHeight += cellHeights[r]; - } - for (var j = 0; j < cellWidths.length; j++) { - totalWidth += cellWidths[j]; - } - - if (tableAlignHoriz == 'center') { - left = left - totalWidth / 2; - } else if (tableAlignHoriz == 'right') { - left = left - totalWidth; - } - - if (tableAlignVert == 'middle') { - top = top - totalHeight / 2; - } else if (tableAlignVert == 'bottom') { - top = top - totalHeight; - } - - var maxHeight = this.maxHeight; - var padding = def([this.padding, this.outerBorder.width / 2]); // padding for canvas - if (totalHeight + 2 * padding < maxHeight) { - var hasScroll = true; - } else { - var hasScroll = false; - } - var fullRect = [0, 0, totalWidth + 2 * padding, totalHeight + 2 * padding]; - var visRect = [left, top, totalWidth + 2 * padding, maxHeight]; - var topRowRect = [left, top, totalWidth + 2 * padding, maxHeight]; - var scrollRect = [left + totalWidth + 4 * padding, top, 25, maxHeight]; - - var ctxInvis = this.ctxInvis; - var ctxVis = this.ctxVis; - var ctxTopRow = this.ctxTopRow; - ctxInvis.data[102] = fullRect[2]; - ctxInvis.canvas.width = fullRect[2]; - ctxInvis.data[103] = fullRect[3]; - ctxInvis.canvas.height = fullRect[3]; - ctxVis.data[100] = visRect[0]; - ctxVis.data[101] = visRect[1]; - ctxVis.data[102] = visRect[2]; - ctxVis.canvas.width = visRect[2]; - ctxVis.data[103] = visRect[3]; - ctxVis.canvas.height = visRect[3]; - ctxTopRow.data[100] = topRowRect[0]; - ctxTopRow.data[101] = topRowRect[1]; - ctxTopRow.data[102] = topRowRect[2]; - ctxTopRow.canvas.width = topRowRect[2]; - ctxTopRow.data[103] = topRowRect[3]; - ctxTopRow.canvas.height = topRowRect[3]; - resizeCanvas(ctxInvis.canvas, 0, 0, fullRect[2], fullRect[3]); - resizeCanvas(ctxVis.canvas, visRect[0], visRect[1], visRect[2], visRect[3]); - resizeCanvas(ctxTopRow.canvas, topRowRect[0], topRowRect[1], topRowRect[2], topRowRect[3]); - ctxInvis.clear(); - ctxVis.clear(); - ctxTopRow.clear(); - - var left = padding; - var top = padding; - - ctxInvis.save(); - ctxInvis.lineCap = lineCap; - ctxInvis.lineJoin = lineJoin; - - var cellDims = []; - - var horizPos = [left]; - for (var i = 0; i < cellWidths.length; i++) { - horizPos.push(horizPos[horizPos.length - 1] + cellWidths[i]) - } - - var vertPos = [top]; - for (var i = 0; i < cellHeights.length; i++) { - vertPos.push(vertPos[vertPos.length - 1] + cellHeights[i]) - } - - // write text to each cell - var topPos = top; - for (var i = 0; i < cells.length; i++) { - var leftPos = left; - cellDims[i] = []; - for (var j = 0; j < cells[i].length; j++) { - cellDims[i][j] = { - left: leftPos + 2, - top: topPos + 1, - width: cellWidths[j] - 9, - height: cellHeights[i] - 8, - border: false, - offset: [-40, 0.5 * (cellHeights[i] - 8) - 20], - fontSize: fontSize, - leftPoint: paddingH, - textColor: textColor, - textAlign: horizAlign, - fontSize: fontSize - }; - if (cells[i][j].highlight == true) { - if (typeof cells[i][j].color !== 'undefined' && cells[i][j].color !== 'none') { - ctxInvis.fillStyle = colorA(invertColor(cells[i][j].color), alpha); - } else { - ctxInvis.fillStyle = colorA(invertColor('#FFC'), alpha); - } - ctxInvis.fillRect(leftPos, topPos, cellWidths[j], cellHeights[i]); - } else if (typeof cells[i][j].color !== 'undefined' && cells[i][j].color !== 'none') { - ctxInvis.fillStyle = colorA(cells[i][j].color, alpha); - ctxInvis.fillRect(leftPos, topPos, cellWidths[j], cellHeights[i]); - } - var align = horizAlign; - if (!un(cells[i][j].align)) - align = cells[i][j].align; - var cellText = text({ - ctx: ctxInvis, - left: leftPos + paddingH, - top: topPos + paddingV, - width: cellWidths[j] - 2 * paddingH, - height: cellHeights[i] - 2 * paddingV, - textArray: cells[i][j].text, - textAlign: align, - vertAlign: 'middle', - padding: 0.001, - box: cells[i][j].box, - sf: sf - }); - /*console.log(cellText.tightRect[2],cellText.tightRect[3],{ - ctx:ctxInvis, - left:leftPos+paddingH, - top:topPos+paddingV, - width:cellWidths[j]-2*paddingH, - height:cellHeights[i]-2*paddingV, - textArray:cells[i][j].text, - textAlign:align, - vertAlign:'middle', - padding:0.001, - box:cells[i][j].box, - sf:sf - });*/ - leftPos += cellWidths[j]; - } - topPos += cellHeights[i]; - } - - // draw inner border - if (innerBorder.show == true) { - ctxInvis.strokeStyle = innerBorder.color; - ctxInvis.lineWidth = innerBorder.width; - if (!ctxInvis.setLineDash) { - ctxInvis.setLineDash = function () {} - } - ctxInvis.setLineDash(innerBorder.dash); - var leftPos = left; - for (var i = 0; i < cellWidths.length - 1; i++) { - leftPos += cellWidths[i]; - ctxInvis.beginPath(); - ctxInvis.moveTo(leftPos, top); - ctxInvis.lineTo(leftPos, top + totalHeight); - ctxInvis.stroke(); - } - var topPos = top; - for (var i = 0; i < cellHeights.length - 1; i++) { - topPos += cellHeights[i]; - ctxInvis.beginPath(); - ctxInvis.moveTo(left, topPos); - ctxInvis.lineTo(left + totalWidth, topPos); - ctxInvis.stroke(); - } - } - - // draw outer border - if (outerBorder.show == true) { - ctxInvis.strokeStyle = outerBorder.color; - ctxInvis.lineWidth = outerBorder.width; - if (!ctxInvis.setLineDash) { - ctxInvis.setLineDash = function () {} - } - ctxInvis.setLineDash(outerBorder.dash); - ctxInvis.beginPath(); - ctxInvis.strokeRect(left, top, totalWidth, totalHeight); - } - - ctxInvis.restore(); - - this.cell = cellDims; - this.xPos = horizPos; - this.yPos = vertPos; - - if (!un(this.additionalDraw)) { - this.additionalDraw(); - } - - //this.scroller.max = totalHeight/maxHeight; - //this.scroller.rect = scrollRect; - this.scroller.reposition(totalHeight / maxHeight, scrollRect); - setScrollerValue(this.scroller, 0, true); - this.scrollPos = 0; - this.scrollMax = scrollMax; - this.scrollDiff = totalHeight - maxHeight + 2 * padding; - - this.redraw(); - - if (totalHeight + 2 * padding > this.maxHeight) { - this.hasScroll = true; - //this.scrollPos = 0; - //this.scrollMax = totalHeight/maxHeight; - //this.scrollDiff = totalHeight-maxHeight+2*padding; - //this.scroller.max = totalHeight/maxHeight; - //this.scroller.value = 0; - //this.scroller = updateScrollerDims(this.scroller); - showScroller(this.scroller); - if (this.topRowFreeze) { - showObj(ctxTopRow.canvas); - ctxTopRow.data[3] = ctxTopRow.data[103] = padding + vertPos[1]; - ctxTopRow.canvas.width = ctxTopRow.data[102]; - ctxTopRow.canvas.height = ctxTopRow.data[103]; - resize(); - ctxTopRow.drawImage(ctxInvis.canvas, 0, 0); - } else { - hideObj(ctxTopRow.canvas); - } - } else { - this.hasScroll = false; - hideScroller(this.scroller); - hideObj(ctxTopRow.canvas); - } - } - object.refreshCells(); - - object.move = function (left, top) { - var relLeft = this.scroller.rect[0] - this.ctxVis.canvas.data[100]; - this.left = left; - this.top = top; - this.ctxVis.canvas.data[100] = left; - this.ctxVis.canvas.data[101] = top; - resizeCanvas3(this.ctxVis.canvas); - this.ctxTopRow.canvas.data[100] = left; - this.ctxTopRow.canvas.data[101] = top; - resizeCanvas3(this.ctxTopRow.canvas); - this.scroller.rect[0] = left + relLeft; - this.scroller.rect[1] = top; - this.scroller.reposition(); - } - - return object; -} -function drawScrollTable(object) { - /* EXAMPLE USAGE: - var j0001table1 = drawScrollTable({ - left:100, - top:150, - minCellWidth:80, - minCellHeight:50, - horizAlign:'center', - text:{font:'Arial',size:32,color:'#000'}, - outerBorder:{show:true,width:4,color:'#000'}, - innerBorder:{show:true,width:2,color:'#666'}, - cells:[ - [ // row 0{text:['<><>x'],color:'#CCF',minWidth:100,minHeight:70},{text:['<><>y'],color:'#CCF',minWidth:100,minHeight:70},{text:['<><><>z'],color:'#CCF',minWidth:100,minHeight:70}, - ], [ // row 1{},{text:['2']},{text:['<>3']}, - ], [ // row 2{text:['4']},{},{text:['<>6']}, - ], - ], - maxHeight:300, - moveFunc:function(r,c) {console.log(r,c)), - clickFunc:function(r,c) {console.log(r,c)), - padding:2 // def: outerBorder.width/2 - }); - */ - - if (typeof object.sf !== 'undefined') { - var sf = object.sf; - } else { - var sf = 1; - } - - var left = object.left * sf; - var top = object.top * sf; - var cells = object.cells; - var z = object.z || object.zIndex || 2; - - var minCellWidth = object.minCellWidth * sf || 80 * sf; - var maxCellWidth = object.maxCellWidth * sf || Math.max(1200 * sf, object.minCellWidth * sf); - var minCellHeight = object.minCellHeight * sf || 100 * sf; - var minCellPadding = object.minCellPadding * sf || 7 * sf; - var paddingH = minCellPadding; - var paddingV = minCellPadding; - if (typeof object.paddingH == 'number') - paddingH = object.paddingH * sf; - if (typeof object.paddingV == 'number') - paddingV = object.paddingV * sf; - var horizAlign = object.horizAlign || object.align || 'center'; - if (typeof object.text == 'object') { - var font = object.text.font || 'Arial'; - var fontSize = object.text.size || 32; - var textColor = object.text.color || '#000'; - } else { - var font = 'Arial'; - var fontSize = 32; - var textColor = '#000'; - } - if (typeof object.alpha == 'number') { - var alpha = object.alpha; - } else { - var alpha = 1; - } - var lineJoin = object.lineJoin || object.lineCap || 'round'; - var lineCap = object.lineCap || object.lineJoin || 'round'; - var outerBorder = {}; - if (typeof object.outerBorder == 'object') { - outerBorder.show = boolean(object.outerBorder.show, true); - outerBorder.width = object.outerBorder.width * sf || 4 * sf; - if (typeof object.outerBorder.color == 'undefined') { - outerBorder.color = colorA('#000', alpha); - } else { - outerBorder.color = colorA(object.outerBorder.color, alpha); - } - outerBorder.dash = object.outerBorder.dash || []; - } else { - outerBorder.show = true; - outerBorder.width = 4 * sf; - outerBorder.color = colorA('#000', alpha); - outerBorder.dash = []; - } - outerBorder.dash = enlargeDash(outerBorder.dash, sf); - var innerBorder = {}; - if (typeof object.innerBorder == 'object') { - innerBorder.show = boolean(object.innerBorder.show, true); - innerBorder.width = object.innerBorder.width * sf || 4 * sf; - if (typeof object.innerBorder.color == 'undefined') { - innerBorder.color = colorA('#000', alpha); - } else { - innerBorder.color = colorA(object.innerBorder.color, alpha); - } - innerBorder.dash = object.innerBorder.dash || []; - } else { - innerBorder.show = true; - innerBorder.width = 4 * sf; - innerBorder.color = colorA('#000', alpha); - innerBorder.dash = [20, 15]; - } - innerBorder.dash = enlargeDash(innerBorder.dash, sf); - var tableAlignHoriz = object.tableAlignHoriz || 'left'; // is the whole table centred on [left,top]? - var tableAlignVert = object.tableAlignVert || 'top'; - - var numRows = cells.length; - var numCols = 0; - for (var i = 0; i < cells.length; i++) { - numCols = Math.max(cells[i].length, numCols); - } - var cellHeights = []; - for (var i = 0; i < numRows; i++) { - cellHeights[i] = minCellHeight; - } - var cellWidths = []; - for (var j = 0; j < numCols; j++) { - cellWidths[j] = minCellWidth; - } - var totalWidth = 0; - var totalHeight = 0; - //calcTableDims(object); - - if (typeof hiddenCanvas == 'undefined') { - var hiddenCanvas = document.createElement('canvas'); - hiddenCanvas.width = mainCanvasWidth * sf; - hiddenCanvas.height = mainCanvasHeight * sf; - hiddenCanvas.ctx = hiddenCanvas.getContext('2d'); - } - - for (var r = 0; r < cells.length; r++) { - var maxHeight = minCellHeight; - for (var c = 0; c < cells[r].length; c++) { - if (typeof cells[r][c] == 'object') { - if (typeof cells[r][c].text !== 'object') { - cells[r][c].text = []; - } else { - cells[r][c].text = clone(cells[r][c].text); - } - if (typeof cells[r][c].color !== 'string') - cells[r][c].color = 'none'; - if (typeof cells[r][c].minWidth !== 'number') - cells[r][c].minWidth = 0; - if (typeof cells[r][c].minHeight !== 'number') - cells[r][c].minHeight = 0; - var font2 = font; - var fontSize2 = fontSize; - var textColor2 = textColor; - if (!un(cells[r][c].font)) - font2 = cells[r][c].font; - if (!un(cells[r][c].fontSize)) - fontSize2 = cells[r][c].fontSize; - if (!un(cells[r][c].textColor)) - textColor2 = cells[r][c].textColor; - if (un(cells[r][c].styled)) { - cells[r][c].text.unshift('<><><>'); - cells[r][c].styled = true; - } - //var dims = drawMathsText(ctx,cells[r][c].text,fontSize,0,0,false,[],horizAlign,'middle',text.color,'measure'); - //maxHeight = Math.max(dims[1]+2*minCellPadding,cells[r][c].minHeight,maxHeight); - //cellWidths[c] = Math.max(dims[0]+2*minCellPadding,cells[r][c].minWidth,cellWidths[c]); - - var cellText = text({ - ctx: hiddenCanvas.ctx, - left: 0, - top: 0, - width: maxCellWidth, - textArray: cells[r][c].text, - minTightWidth: 5, - minTightHeight: 5, - box: cells[r][c].box, - sf: sf - }); - maxHeight = Math.max(cellText.tightRect[3] + 2 * paddingV, cells[r][c].minHeight * sf, maxHeight); - cellWidths[c] = Math.max(cellText.tightRect[2] + 3 * paddingH, cells[r][c].minWidth * sf, cellWidths[c]); - } - } - cellHeights[r] = Math.max(maxHeight, cellHeights[r]); - totalHeight += cellHeights[r]; - } - for (var j = 0; j < cellWidths.length; j++) { - totalWidth += cellWidths[j]; - } - - if (tableAlignHoriz == 'center') { - left = left - totalWidth / 2; - } else if (tableAlignHoriz == 'right') { - left = left - totalWidth; - } - - if (tableAlignVert == 'middle') { - top = top - totalHeight / 2; - } else if (tableAlignVert == 'bottom') { - top = top - totalHeight; - } - - // now the table dims are known, create canvases - var maxHeight = object.maxHeight; - if (totalHeight + 2 * padding < maxHeight) { - var hasScroll = true; - } else { - var hasScroll = false; - } - var padding = def([object.padding, object.outerBorder.width / 2]); // padding for canvas - var fullRect = [0, 0, totalWidth + 2 * padding, totalHeight + 2 * padding]; - var visRect = [left, top, totalWidth + 2 * padding, maxHeight]; - var topRowRect = [left, top, totalWidth + 2 * padding, maxHeight]; - var scrollRect = [left + totalWidth + 4 * padding, top, 25, maxHeight]; - - var ctxVis = newctx({ - rect: visRect, - z: z - }); - var ctxTopRow = newctx({ - rect: topRowRect, - z: z - }); - var ctxInvis = newctx({ - rect: fullRect, - vis: false - }); - - var left = padding; - var top = padding; - - ctxInvis.save(); - ctxInvis.lineCap = lineCap; - ctxInvis.lineJoin = lineJoin; - - var cellDims = []; - - var horizPos = [left]; - for (var i = 0; i < cellWidths.length; i++) { - horizPos.push(horizPos[horizPos.length - 1] + cellWidths[i]) - } - - var vertPos = [top]; - for (var i = 0; i < cellHeights.length; i++) { - vertPos.push(vertPos[vertPos.length - 1] + cellHeights[i]) - } - - // write text to each cell - var topPos = top; - for (var i = 0; i < cells.length; i++) { - var leftPos = left; - cellDims[i] = []; - for (var j = 0; j < cells[i].length; j++) { - cellDims[i][j] = { - left: leftPos + 2, - top: topPos + 1, - width: cellWidths[j] - 9, - height: cellHeights[i] - 8, - border: false, - offset: [-40, 0.5 * (cellHeights[i] - 8) - 20], - fontSize: fontSize, - leftPoint: paddingH, - textColor: textColor, - textAlign: horizAlign, - fontSize: fontSize - }; - if (cells[i][j].highlight == true) { - if (typeof cells[i][j].color == 'undefined' || cells[i][j].color !== 'none') { - ctxInvis.fillStyle = colorA(invertColor(cells[i][j].color), alpha); - } else { - ctxInvis.fillStyle = colorA(invertColor('#FFC'), alpha); - } - ctxInvis.fillRect(leftPos, topPos, cellWidths[j], cellHeights[i]); - } else if (typeof cells[i][j].color == 'undefined' || cells[i][j].color !== 'none') { - ctxInvis.fillStyle = colorA(cells[i][j].color, alpha); - ctxInvis.fillRect(leftPos, topPos, cellWidths[j], cellHeights[i]); - } - var align = horizAlign; - if (!un(cells[i][j].align)) - align = cells[i][j].align; - var cellText = text({ - ctx: ctxInvis, - left: leftPos + paddingH, - top: topPos + paddingV, - width: cellWidths[j] - 2 * paddingH, - height: cellHeights[i] - 2 * paddingV, - textArray: cells[i][j].text, - textAlign: align, - vertAlign: 'middle', - padding: 0.001, - box: cells[i][j].box, - sf: sf - }); - //console.log(cellText.tightRect[2],cellText.tightRect[3]); - leftPos += cellWidths[j]; - } - topPos += cellHeights[i]; - } - - // draw inner border - if (innerBorder.show == true) { - ctxInvis.strokeStyle = innerBorder.color; - ctxInvis.lineWidth = innerBorder.width; - if (!ctxInvis.setLineDash) { - ctxInvis.setLineDash = function () {} - } - ctxInvis.setLineDash(innerBorder.dash); - var leftPos = left; - for (var i = 0; i < cellWidths.length - 1; i++) { - leftPos += cellWidths[i]; - ctxInvis.beginPath(); - ctxInvis.moveTo(leftPos, top); - ctxInvis.lineTo(leftPos, top + totalHeight); - ctxInvis.stroke(); - } - var topPos = top; - for (var i = 0; i < cellHeights.length - 1; i++) { - topPos += cellHeights[i]; - ctxInvis.beginPath(); - ctxInvis.moveTo(left, topPos); - ctxInvis.lineTo(left + totalWidth, topPos); - ctxInvis.stroke(); - } - } - - // draw outer border - if (outerBorder.show == true) { - ctxInvis.strokeStyle = outerBorder.color; - ctxInvis.lineWidth = outerBorder.width; - if (!ctxInvis.setLineDash) { - ctxInvis.setLineDash = function () {} - } - ctxInvis.setLineDash(outerBorder.dash); - ctxInvis.beginPath(); - ctxInvis.strokeRect(left, top, totalWidth, totalHeight); - } - - ctxInvis.restore(); - - var topRowFreeze = boolean(object.topRowFreeze, true); - - var scrollMax = totalHeight / maxHeight; - var scrollDiff = totalHeight - maxHeight + 2 * padding; - //console.log(scrollMax,scrollDiff); - - var scroll = createScroller({ - rect: scrollRect, - max: scrollMax, - zIndex: z, - funcMove: function (value) { - this.table.scrollPos = (value / this.table.scrollMax) * this.table.scrollDiff; - this.table.redraw(); - }, - funcStop: function (value) { - this.table.scrollPos = (value / this.table.scrollMax) * this.table.scrollDiff; - this.table.redraw(); - } - }); - - if (!un(object.funcMove)) { - ctxVis.canvas.style.pointerEvents = 'auto'; - ctxVis.data[6] = true; - ctxVis.data[106] = true; - addListenerMove(ctxVis.canvas, function (e) { - updateMouse(e); - var r = -1, - c = -1; - for (var x = 0; x < this.table.xPos.length - 1; x++) { - if (mouse.x >= this.table.xPos[x] + this.table.ctxVis.data[100] && mouse.x <= this.table.xPos[x + 1] + this.table.ctxVis.data[100]) { - c = x; - break; - } - } - if (this.table.topRowFreeze && mouse.y <= this.table.yPos[1] + this.table.ctxVis.data[101]) { - r = 0; - } else { - for (var y = 0; y < this.table.yPos.length - 1; y++) { - if (mouse.y + this.table.scrollPos >= this.table.yPos[y] + this.table.ctxVis.data[101] && mouse.y + this.table.scrollPos <= this.table.yPos[y + 1] + this.table.ctxVis.data[101]) { - r = y; - break; - } - } - } - this.table.funcMove(r, c); - }); - } else { - object.funcMove = function () {}; - } - if (!un(object.funcClick)) { - ctxVis.canvas.style.pointerEvents = 'auto'; - ctxVis.data[6] = true; - ctxVis.data[106] = true; - addListener(ctxVis.canvas, function (e) { - updateMouse(e); - var r = -1, - c = -1, - xProp = 0, - yProp = 0; - for (var x = 0; x < this.table.xPos.length - 1; x++) { - if (mouse.x >= this.table.xPos[x] + this.table.ctxVis.data[100] && mouse.x <= this.table.xPos[x + 1] + this.table.ctxVis.data[100]) { - c = x; - xProp = (mouse.x - (this.table.xPos[x] + this.table.ctxVis.data[100])) / (this.table.xPos[x + 1] - this.table.xPos[x]); - break; - } - } - if (this.table.topRowFreeze && mouse.y <= this.table.yPos[1] + this.table.ctxVis.data[101]) { - r = 0; - } else { - for (var y = 0; y < this.table.yPos.length - 1; y++) { - if (mouse.y + this.table.scrollPos >= this.table.yPos[y] + this.table.ctxVis.data[101] && mouse.y + this.table.scrollPos <= this.table.yPos[y + 1] + this.table.ctxVis.data[101]) { - r = y; - yProp = (mouse.y - (this.table.yPos[y] + this.table.ctxVis.data[101])) / (this.table.yPos[y + 1] - this.table.yPos[y]); - break; - } - } - } - this.table.funcClick(r, c, xProp, yProp); - }); - } else { - object.funcClick = function () {}; - } - - var returnObj = clone(object); - - returnObj.ctxVis = ctxVis; - returnObj.ctxInvis = ctxInvis; - returnObj.ctxTopRow = ctxTopRow; - returnObj.cell = cellDims; - returnObj.xPos = horizPos; - returnObj.yPos = vertPos; - returnObj.padding = padding; - returnObj.hasScroll = hasScroll; - returnObj.scroller = scroll; - returnObj.scrollPos = 0; - returnObj.scrollMax = scrollMax; - returnObj.scrollDiff = scrollDiff; - returnObj.topRowFreeze = topRowFreeze; - returnObj.redraw = function () { - this.ctxVis.clearRect(0, 0, this.ctxVis.canvas.data[102], this.ctxVis.canvas.data[103]); - this.ctxVis.drawImage(this.ctxInvis.canvas, 0, -this.scrollPos); - }; - - returnObj.scroller.table = returnObj; - returnObj.ctxVis.canvas.table = returnObj; - - if (!un(returnObj.additionalDraw)) { - returnObj.additionalDraw(); - } - - returnObj.redraw(); - - if (topRowFreeze) { - ctxTopRow.data[3] = ctxTopRow.data[103] = padding + vertPos[1]; - ctxTopRow.canvas.width = ctxTopRow.data[102]; - ctxTopRow.canvas.height = ctxTopRow.data[103]; - resizeCanvas2(ctxTopRow.canvas, ctxTopRow.data[102], ctxTopRow.data[103]); - resize(); - ctxTopRow.drawImage(ctxInvis.canvas, 0, 0); - } else { - hideObj(ctxTopRow.canvas); - } - - return returnObj; -} -function updateScrollTable(object) { // update previously drawn scrollTable with changed cell data - var sf = def([object.sf, 1]); - - var left = object.left * sf; - var top = object.top * sf; - var cells = object.cells; - var z = object.z || object.zIndex || 2; - - ///console.log(object); - - var minCellWidth = object.minCellWidth * sf || 80 * sf; - var maxCellWidth = object.maxCellWidth * sf || Math.max(1200 * sf, object.minCellWidth * sf); - var minCellHeight = object.minCellHeight * sf || 100 * sf; - var minCellPadding = object.minCellPadding * sf || 7 * sf; - var paddingH = minCellPadding; - var paddingV = minCellPadding; - if (typeof object.paddingH == 'number') - paddingH = object.paddingH * sf; - if (typeof object.paddingV == 'number') - paddingV = object.paddingV * sf; - var horizAlign = object.horizAlign || object.align || 'center'; - if (typeof object.text == 'object') { - var font = object.text.font || 'Arial'; - var fontSize = object.text.size || 32; - var textColor = object.text.color || '#000'; - } else { - var font = 'Arial'; - var fontSize = 32; - var textColor = '#000'; - } - if (typeof object.alpha == 'number') { - var alpha = object.alpha; - } else { - var alpha = 1; - } - var lineJoin = object.lineJoin || object.lineCap || 'round'; - var lineCap = object.lineCap || object.lineJoin || 'round'; - var outerBorder = {}; - if (typeof object.outerBorder == 'object') { - outerBorder.show = boolean(object.outerBorder.show, true); - outerBorder.width = object.outerBorder.width * sf || 4 * sf; - if (typeof object.outerBorder.color == 'undefined') { - outerBorder.color = colorA('#000', alpha); - } else { - outerBorder.color = colorA(object.outerBorder.color, alpha); - } - outerBorder.dash = object.outerBorder.dash || []; - } else { - outerBorder.show = true; - outerBorder.width = 4 * sf; - outerBorder.color = colorA('#000', alpha); - outerBorder.dash = []; - } - outerBorder.dash = enlargeDash(outerBorder.dash, sf); - var innerBorder = {}; - if (typeof object.innerBorder == 'object') { - innerBorder.show = boolean(object.innerBorder.show, true); - innerBorder.width = object.innerBorder.width * sf || 4 * sf; - if (typeof object.innerBorder.color == 'undefined') { - innerBorder.color = colorA('#000', alpha); - } else { - innerBorder.color = colorA(object.innerBorder.color, alpha); - } - innerBorder.dash = object.innerBorder.dash || []; - } else { - innerBorder.show = true; - innerBorder.width = 4 * sf; - innerBorder.color = colorA('#000', alpha); - innerBorder.dash = [20, 15]; - } - innerBorder.dash = enlargeDash(innerBorder.dash, sf); - var tableAlignHoriz = object.tableAlignHoriz || 'left'; // is the whole table centred on [left,top]? - var tableAlignVert = object.tableAlignVert || 'top'; - - var numRows = cells.length; - var numCols = 0; - for (var i = 0; i < cells.length; i++) { - numCols = Math.max(cells[i].length, numCols); - } - var cellHeights = []; - for (var i = 0; i < numRows; i++) { - cellHeights[i] = minCellHeight; - } - var cellWidths = []; - for (var j = 0; j < numCols; j++) { - cellWidths[j] = minCellWidth; - } - var totalWidth = 0; - var totalHeight = 0; - - var cellHeights = []; - for (var i = 0; i < numRows; i++) { - cellHeights[i] = minCellHeight; - } - var cellWidths = []; - for (var j = 0; j < numCols; j++) { - cellWidths[j] = minCellWidth; - } - var totalWidth = 0; - var totalHeight = 0; - - if (typeof hiddenCanvas == 'undefined') { - var hiddenCanvas = document.createElement('canvas'); - hiddenCanvas.width = mainCanvasWidth * sf; - hiddenCanvas.height = mainCanvasHeight * sf; - hiddenCanvas.ctx = hiddenCanvas.getContext('2d'); - } - - for (var r = 0; r < cells.length; r++) { - var maxHeight = minCellHeight; - for (var c = 0; c < cells[r].length; c++) { - if (typeof cells[r][c] == 'object') { - if (typeof cells[r][c].text !== 'object') { - cells[r][c].text = []; - } else { - cells[r][c].text = clone(cells[r][c].text); - } - if (typeof cells[r][c].color !== 'string') - cells[r][c].color = 'none'; - if (typeof cells[r][c].minWidth !== 'number') - cells[r][c].minWidth = 0; - if (typeof cells[r][c].minHeight !== 'number') - cells[r][c].minHeight = 0; - var font2 = font; - var fontSize2 = fontSize; - var textColor2 = textColor; - if (!un(cells[r][c].font)) - font2 = cells[r][c].font; - if (!un(cells[r][c].fontSize)) - fontSize2 = cells[r][c].fontSize; - if (!un(cells[r][c].textColor)) - textColor2 = cells[r][c].textColor; - if (un(cells[r][c].styled)) { - cells[r][c].text.unshift('<><><>'); - cells[r][c].styled = true; - } - //var dims = drawMathsText(ctx,cells[r][c].text,fontSize,0,0,false,[],horizAlign,'middle',text.color,'measure'); - //maxHeight = Math.max(dims[1]+2*minCellPadding,cells[r][c].minHeight,maxHeight); - //cellWidths[c] = Math.max(dims[0]+2*minCellPadding,cells[r][c].minWidth,cellWidths[c]); - - var cellText = text({ - ctx: hiddenCanvas.ctx, - left: 0, - top: 0, - width: maxCellWidth, - textArray: cells[r][c].text, - minTightWidth: 5, - minTightHeight: 5, - box: cells[r][c].box, - sf: sf - }); - maxHeight = Math.max(cellText.tightRect[3] + 2 * paddingV, cells[r][c].minHeight * sf, maxHeight); - cellWidths[c] = Math.max(cellText.tightRect[2] + 3 * paddingH, cells[r][c].minWidth * sf, cellWidths[c]); - } - } - cellHeights[r] = Math.max(maxHeight, cellHeights[r]); - totalHeight += cellHeights[r]; - } - for (var j = 0; j < cellWidths.length; j++) { - totalWidth += cellWidths[j]; - } - - if (tableAlignHoriz == 'center') { - left = left - totalWidth / 2; - } else if (tableAlignHoriz == 'right') { - left = left - totalWidth; - } - - if (tableAlignVert == 'middle') { - top = top - totalHeight / 2; - } else if (tableAlignVert == 'bottom') { - top = top - totalHeight; - } - - //update canvases - var maxHeight = object.maxHeight; - var padding = def([object.padding, object.outerBorder.width / 2]); // padding for canvas - var fullRect = [0, 0, totalWidth + 2 * padding, totalHeight + 2 * padding]; - var visRect = [left, top, totalWidth + 2 * padding, maxHeight]; - var topRowRect = [left, top, totalWidth + 2 * padding, maxHeight]; - var scrollRect = [left + totalWidth + 4 * padding, top, 25, maxHeight]; - - var ctxInvis = object.ctxInvis; - var ctxVis = object.ctxVis; - var ctxTopRow = object.ctxTopRow; - ctxInvis.clear(); - ctxVis.clear(); - ctxTopRow.clear(); - ctxInvis.data[102] = fullRect[2]; - ctxInvis.data[103] = fullRect[3]; - ctxInvis.canvas.width = fullRect[2]; - ctxInvis.canvas.height = fullRect[3]; - ctxVis.data[100] = visRect[0]; - ctxVis.data[101] = visRect[1]; - ctxVis.data[102] = visRect[2]; - ctxVis.data[103] = visRect[3]; - ctxVis.canvas.width = visRect[2]; - ctxVis.canvas.height = visRect[3]; - ctxTopRow.data[100] = topRowRect[0]; - ctxTopRow.data[101] = topRowRect[1]; - ctxTopRow.data[102] = topRowRect[2]; - ctxTopRow.data[103] = topRowRect[3]; - ctxTopRow.canvas.width = visRect[2]; - ctxTopRow.canvas.height = visRect[3]; - resize(); - - var left = padding; - var top = padding; - - ctxInvis.save(); - ctxInvis.lineCap = lineCap; - ctxInvis.lineJoin = lineJoin; - - var cellDims = []; - - var horizPos = [left]; - for (var i = 0; i < cellWidths.length; i++) { - horizPos.push(horizPos[horizPos.length - 1] + cellWidths[i]) - } - - var vertPos = [top]; - for (var i = 0; i < cellHeights.length; i++) { - vertPos.push(vertPos[vertPos.length - 1] + cellHeights[i]) - } - - // write text to each cell - var topPos = top; - for (var i = 0; i < cells.length; i++) { - var leftPos = left; - cellDims[i] = []; - for (var j = 0; j < cells[i].length; j++) { - cellDims[i][j] = { - left: leftPos + 2, - top: topPos + 1, - width: cellWidths[j] - 9, - height: cellHeights[i] - 8, - border: false, - offset: [-40, 0.5 * (cellHeights[i] - 8) - 20], - fontSize: fontSize, - leftPoint: paddingH, - textColor: textColor, - textAlign: horizAlign, - fontSize: fontSize - }; - if (cells[i][j].highlight == true) { - if (typeof cells[i][j].color == 'undefined' || cells[i][j].color !== 'none') { - ctxInvis.fillStyle = colorA(invertColor(cells[i][j].color), alpha); - } else { - ctxInvis.fillStyle = colorA(invertColor('#FFC'), alpha); - } - ctxInvis.fillRect(leftPos, topPos, cellWidths[j], cellHeights[i]); - } else if (typeof cells[i][j].color == 'undefined' || cells[i][j].color !== 'none') { - ctxInvis.fillStyle = colorA(cells[i][j].color, alpha); - ctxInvis.fillRect(leftPos, topPos, cellWidths[j], cellHeights[i]); - } - var align = horizAlign; - if (!un(cells[i][j].align)) - align = cells[i][j].align; - var cellText = text({ - ctx: ctxInvis, - left: leftPos + paddingH, - top: topPos + paddingV, - width: cellWidths[j] - 2 * paddingH, - height: cellHeights[i] - 2 * paddingV, - textArray: cells[i][j].text, - textAlign: align, - vertAlign: 'middle', - padding: 0.001, - box: cells[i][j].box, - sf: sf - }); - /*console.log(cellText.tightRect[2],cellText.tightRect[3],{ - ctx:ctxInvis, - left:leftPos+paddingH, - top:topPos+paddingV, - width:cellWidths[j]-2*paddingH, - height:cellHeights[i]-2*paddingV, - textArray:cells[i][j].text, - textAlign:align, - vertAlign:'middle', - padding:0.001, - box:cells[i][j].box, - sf:sf - });*/ - leftPos += cellWidths[j]; - } - topPos += cellHeights[i]; - } - - // draw inner border - if (innerBorder.show == true) { - ctxInvis.strokeStyle = innerBorder.color; - ctxInvis.lineWidth = innerBorder.width; - if (!ctxInvis.setLineDash) { - ctxInvis.setLineDash = function () {} - } - ctxInvis.setLineDash(innerBorder.dash); - var leftPos = left; - for (var i = 0; i < cellWidths.length - 1; i++) { - leftPos += cellWidths[i]; - ctxInvis.beginPath(); - ctxInvis.moveTo(leftPos, top); - ctxInvis.lineTo(leftPos, top + totalHeight); - ctxInvis.stroke(); - } - var topPos = top; - for (var i = 0; i < cellHeights.length - 1; i++) { - topPos += cellHeights[i]; - ctxInvis.beginPath(); - ctxInvis.moveTo(left, topPos); - ctxInvis.lineTo(left + totalWidth, topPos); - ctxInvis.stroke(); - } - } - - // draw outer border - if (outerBorder.show == true) { - ctxInvis.strokeStyle = outerBorder.color; - ctxInvis.lineWidth = outerBorder.width; - if (!ctxInvis.setLineDash) { - ctxInvis.setLineDash = function () {} - } - ctxInvis.setLineDash(outerBorder.dash); - ctxInvis.beginPath(); - ctxInvis.strokeRect(left, top, totalWidth, totalHeight); - } - - ctxInvis.restore(); - - object.cell = cellDims; - object.xPos = horizPos; - object.yPos = vertPos; - - if (!un(object.additionalDraw)) { - object.additionalDraw(); - } - - object.redraw(); - - if (totalHeight + 2 * padding > object.maxHeight) { - moveScroller(object.scroller, object.left + object.xPos.last(), object.top + object.yPos[0]); - object.hasScroll = true; - object.scrollPos = 0; - object.scrollMax = totalHeight / maxHeight; - object.scrollDiff = totalHeight - maxHeight + 2 * padding; - object.scroller.max = totalHeight / maxHeight; - object.scroller.value = 0; - object.scroller = updateScrollerDims(object.scroller); - showScroller(object.scroller); - if (object.topRowFreeze) { - showObj(ctxTopRow.canvas); - ctxTopRow.data[3] = ctxTopRow.data[103] = padding + vertPos[1]; - ctxTopRow.canvas.width = ctxTopRow.data[102]; - ctxTopRow.canvas.height = ctxTopRow.data[103]; - resizeCanvas3(ctxTopRow.canvas); - ctxTopRow.drawImage(ctxInvis.canvas, 0, 0); - } else { - hideObj(ctxTopRow.canvas); - } - } else { - object.hasScroll = false; - hideScroller(object.scroller); - hideObj(ctxTopRow.canvas); - } - - return object; -} -function moveScrollTable(object, left, top) { - var relLeft = object.scroller.rect[0] - object.ctxVis.canvas.data[100]; - object.left = left; - object.top = top; - object.ctxVis.canvas.data[100] = left; - object.ctxVis.canvas.data[101] = top; - resizeCanvas3(object.ctxVis.canvas); - object.ctxTopRow.canvas.data[100] = left; - object.ctxTopRow.canvas.data[101] = top; - resizeCanvas3(object.ctxTopRow.canvas); - object.scroller.rect[0] = left + relLeft; - object.scroller.rect[1] = top; - object.scroller.reposition(); -} -function showScrollTable(object, includeTopRow) { - showObj(object.ctxVis.canvas); - if (boolean(includeTopRow, true)) - showObj(object.ctxTopRow.canvas); - /*if (object.hasScroll == true)*/ - showScroller(object.scroller); -} -function hideScrollTable(object) { - hideObj(object.ctxVis.canvas); - hideObj(object.ctxTopRow.canvas); - hideScroller(object.scroller); -} - -function createSlider(object) { - if (typeof slider[pageIndex] == 'undefined') - slider[pageIndex] = []; - var id = object.id || slider[pageIndex].length; - if (typeof object.gridDetails == 'undefined') - object.gridDetails = {}; - var left = object.left || object.l || (object.gridDetails.left - 10); - var top = object.top || object.t || (object.gridDetails.top + object.gridDetails.height); - var width = object.width || object.w || (object.gridDetails.width + 20); - var height = object.height || object.h || 60; - var bottom = top + height; - var min, - max; - if (typeof object.min == 'number') { - min = object.min; - } else { - min = object.gridDetails.xMin; - } - if (typeof object.max == 'number') { - max = object.max; - } else { - max = object.gridDetails.xMax; - } - var vari = object.vari || "a"; - var linkedVar = object.linkedVar; - var varChangeListener = object.varChangeListener; - var onchange = object.onchange; - var startNum = min; - if (typeof object.startNum == 'number') - startNum = object.startNum; - var inc = object.inc || 1; - var label = true; - if (typeof object.label == 'boolean') - label = object.label; - var labelFont = object.labelFont || "24px Arial"; - var labelColor = object.labelColor || '#000'; - var visible = boolean(object.visible, true); - var zIndex = object.zIndex || 2; - var handleColor = object.handleColor || '#00F'; - var handleStyle = object.handleStyle || 'rect'; // rect or circle - var discrete = false; - if (typeof object.discrete == 'boolean') - discrete = object.discrete; - var stepNum = 1; - if (typeof object.stepNum == 'number') - stepNum = object.stepNum; - var snap = false; - if (typeof object.snap == 'boolean') - snap = object.snap; - var snapNum = 1; - if (typeof object.snapNum == 'number') - snapNum = object.snapNum; - var vert = boolean(object.vertical, false); - - if (vert == false) { - var sliderWidth = 20; - if (handleStyle == 'circle') - sliderWidth = 40; - var sliderHeight = 40; - } else { - var sliderHeight = 20; - if (handleStyle == 'circle') - sliderHeight = 40; - var sliderWidth = 40; - } - - var backCanvas = document.createElement('canvas'); - backCanvas.width = width; - backCanvas.height = height * 1.5; - backCanvas.setAttribute('position', 'absolute'); - backCanvas.setAttribute('cursor', 'auto'); - backCanvas.setAttribute('draggable', 'false'); - backCanvas.setAttribute('class', 'buttonClass'); - backCanvas.style.pointerEvents = 'none'; - backCanvas.style.zIndex = zIndex; - if (visible == true) - container.appendChild(backCanvas); - canvases[pageIndex].push(backCanvas); - var backCtx = backCanvas.getContext('2d'); - var backCanvasData = [left, top, width, height * 1.5, visible, false, false, zIndex]; - for (var i = 0; i < 8; i++) { - backCanvasData[100 + i] = backCanvasData[i]; - } - backCanvasData[130] = visible; - backCanvas.data = backCanvasData; - - backCtx.lineWidth = 5; - backCtx.strokeStyle = object.backColor || '#666'; - backCtx.lineCap = 'round'; - backCtx.lineJoin = 'round'; - backCtx.beginPath(); - if (vert == false) { - backCtx.moveTo(0.5 * sliderWidth, 0.5 * height); - backCtx.lineTo(width - 0.5 * sliderWidth, 0.5 * height); - } else { - backCtx.moveTo(0.5 * width, 0.5 * sliderHeight); - backCtx.lineTo(0.5 * width, height - 0.5 * sliderHeight); - } - backCtx.closePath(); - backCtx.stroke(); - if (!un(object.scale)) { - var step = def([object.scale.step, 1]); - var xInc = (width - 20) / ((max - min) / step); - var color = def([object.scale.color, backCtx.strokeStyle]); - backCtx.lineWidth = 2; - backCtx.strokeStyle = color; - backCtx.beginPath(); - var l = 10; - for (var i = min; i <= max; i += step) { - backCtx.moveTo(l, 0.5 * height); - backCtx.lineTo(l, 0.85 * height); - text({ - ctx: backCtx, - left: l - 50, - top: 0.85 * height, - width: 100, - height: height, - align: 'center', - color: color, - textArray: ['<>' + i] - }); - l += xInc; - } - backCtx.stroke(); - } - - var sliderCanvas = document.createElement('canvas'); - sliderCanvas.width = sliderWidth; - sliderCanvas.height = sliderHeight; - sliderCanvas.setAttribute('position', 'absolute'); - sliderCanvas.setAttribute('cursor', 'auto'); - sliderCanvas.setAttribute('draggable', 'false'); - sliderCanvas.setAttribute('class', 'buttonClass'); - sliderCanvas.style.zIndex = zIndex; - if (visible == true) - container.appendChild(sliderCanvas); - canvases[pageIndex].push(sliderCanvas); - var sliderCtx = sliderCanvas.getContext('2d'); - if (vert == false) { - var leftPos = left + (startNum - min) * (width - sliderWidth) / (max - min); - var sliderCanvasData = [leftPos, top + 0.5 * height - 0.5 * sliderHeight, sliderWidth, sliderHeight, visible, false, true, zIndex]; - } else { - var topPos = bottom - sliderHeight - (startNum - min) * (height - sliderHeight) / (max - min); - var sliderCanvasData = [left + 0.5 * width - 0.5 * sliderWidth, topPos, sliderWidth, sliderHeight, visible, false, true, zIndex]; - } - for (var i = 0; i < 8; i++) { - sliderCanvasData[100 + i] = sliderCanvasData[i]; - } - sliderCanvasData[130] = visible; - sliderCanvas.data = sliderCanvasData; - addListenerStart(sliderCanvas, sliderDragStart); - - sliderCtx.fillStyle = handleColor; - if (handleStyle == 'rect') { - sliderCtx.fillRect(0, 0, sliderWidth, sliderHeight); - } else if (handleStyle == 'circle') { - sliderCtx.beginPath(); - sliderCtx.arc(0.5 * sliderWidth, 0.5 * sliderHeight, 0.5 * sliderHeight - 2, 0, 2 * Math.PI); - sliderCtx.closePath(); - sliderCtx.fill(); - } - - var labelCanvas = document.createElement('canvas'); - labelCanvas.width = width; - labelCanvas.height = parseInt(labelFont) * 2; - labelCanvas.setAttribute('position', 'absolute'); - labelCanvas.setAttribute('cursor', 'auto'); - labelCanvas.setAttribute('draggable', 'false'); - labelCanvas.setAttribute('class', 'buttonClass'); - labelCanvas.style.pointerEvents = 'none'; - labelCanvas.style.zIndex = zIndex; - if (label == true && visible == true) { - container.appendChild(labelCanvas); - } - canvases[pageIndex].push(labelCanvas); - var labelCtx = labelCanvas.getContext('2d'); - var labelCanvasData = [left, top + height, width, height, visible, false, false, zIndex]; - for (var i = 0; i < 8; i++) { - labelCanvasData[100 + i] = labelCanvasData[i]; - } - labelCanvasData[130] = visible; - labelCanvas.data = labelCanvasData; - - if (label == true) { - labelCtx.fillStyle = labelColor; - labelCtx.font = "24px Arial"; - labelCtx.textAlign = 'center'; - labelCtx.textBaseline = 'middle'; - labelCtx.fillText(vari + " = " + startNum, 0.5 * width, parseInt(labelFont)); - } - - resize(); - - slider[pageIndex][id] = { - id: id, - backCanvas: backCanvas, - backctx: backCtx, - backData: backCanvasData, - sliderCanvas: sliderCanvas, - sliderctx: sliderCtx, - sliderData: sliderCanvasData, - labelCanvas: labelCanvas, - labelctx: labelCtx, - labelData: labelCanvasData, - left: left, - top: top, - width: width, - height: height, - bottom: bottom, - sliderWidth: sliderWidth, - sliderHeight: sliderHeight, - min: min, - max: max, - startNum: startNum, - currNum: startNum, - vari: vari, - linkedVar: linkedVar, - varChangeListener: varChangeListener, - onchange: onchange, - inc: inc, - label: label, - labelFont: labelFont, - labelColor: labelColor, - visible: visible, - zIndex: zIndex, - discrete: discrete, - stepNum: stepNum, - snap: snap, - snapNum: snapNum, - vert: vert - }; - - return slider[pageIndex][id]; -} -function showSlider(slider) { - showObj(slider.backCanvas, slider.backData); - showObj(slider.sliderCanvas, slider.sliderData); - showObj(slider.labelCanvas, slider.labelData); -} -function hideSlider(slider) { - hideObj(slider.backCanvas, slider.backData); - hideObj(slider.sliderCanvas, slider.sliderData); - hideObj(slider.labelCanvas, slider.labelData); -} -function setSliderValue(slider, value) { - var val = Math.min(Math.max(slider.min, value), slider.max); - if (slider.vert == false) { - var left = slider.left + ((val - slider.min) / (slider.max - slider.min)) * (slider.width - slider.sliderWidth); - slider.sliderData[100] = left; - } else { - var top = slider.bottom - slider.sliderHeight - ((val - slider.min) / (slider.max - slider.min)) * (slider.height - slider.sliderHeight); - slider.sliderData[101] = top; - } - slider.currNum = val; - if (slider.label == true) { - slider.labelctx.clearRect(0, 0, slider.width, mainCanvasHeight); - slider.labelctx.fillStyle = slider.labelColor; - slider.labelctx.font = slider.labelFont; - slider.labelctx.textAlign = 'center'; - slider.labelctx.textBaseline = 'middle'; - slider.labelctx.fillText(slider.vari + " = " + roundToNearest(val, 0.01), 0.5 * slider.width, parseInt(slider.labelFont)); - } - resizeCanvas2(slider.sliderCanvas, slider.sliderData[100], slider.sliderData[101]); - if (!un(slider.linkedVar)) - eval(slider.linkedVar + "=" + val); - if (!un(slider.varChangeListener)) - eval(slider.varChangeListener + "()"); - if (!un(slider.onchange)) - slider.onchange(val); -} -function sliderDragStart(e) { - for (var i = 0; i < slider[pageIndex].length; i++) { - if (slider[pageIndex][i].sliderCanvas == e.target) { - currSlider = i; - break; - } - } - removeListenerStart(e.target, sliderDragStart) - addListenerMove(window, sliderDragMove); - addListenerEnd(window, sliderDragStop); -} -function sliderDragMove(e) { - var s = slider[pageIndex][currSlider]; - if (s.vert == false) { - var left = Math.min(Math.max(mouse.x, s.left), s.left + s.width - s.sliderWidth); - slider[pageIndex][currSlider].sliderData[100] = left; - var val = s.min + (left - s.left) * (s.max - s.min) / (s.width - s.sliderWidth); - } else { - var top = Math.min(Math.max(mouse.y, s.top), s.bottom - s.sliderHeight); - slider[pageIndex][currSlider].sliderData[101] = top; - var val = s.min + (s.bottom - s.sliderHeight - top) * (s.max - s.min) / (s.height - s.sliderHeight); - } - if (s.discrete == true) { - val = roundToNearest(val, s.stepNum); - } - s.currNum = val; - if (!un(s.linkedVar)) - eval(s.linkedVar + "=" + val); - if (!un(s.varChangeListener)) - eval(s.varChangeListener + "()"); - if (!un(s.onchange)) - s.onchange(val); - if (s.label == true) { - s.labelctx.clearRect(0, 0, s.width, mainCanvasHeight); - s.labelctx.fillStyle = s.labelColor; - s.labelctx.font = s.labelFont; - s.labelctx.textAlign = 'center'; - s.labelctx.textBaseline = 'middle'; - s.labelctx.fillText(s.vari + " = " + roundToNearest(val, 0.01), 0.5 * s.width, parseInt(s.labelFont)); - } - resize(); -} -function sliderDragStop(e) { - removeListenerMove(window, sliderDragMove); - removeListenerEnd(window, sliderDragStop); - // snap slider to position - var s = slider[pageIndex][currSlider]; - if (s.snap == true) { - if (s.vert == false) { - var left = Math.min(Math.max(mouse.x, s.left), s.left + s.width - s.sliderWidth); - var val = s.min + (left - s.left) * (s.max - s.min) / (s.width - s.sliderWidth); - } else { - var top = Math.min(Math.max(mouse.y, s.top), s.bottom - s.sliderHeight); - var val = s.min + (s.bottom - s.sliderHeight - top) * (s.max - s.min) / (s.height - s.sliderHeight); - } - if (s.discrete == true) { - val = roundToNearest(val, s.stepNum); - } else if (s.snap == true) { - val = roundToNearest(val, s.snapNum); - } else { - val = roundToNearest(val, s.inc); - } - s.currNum = val; - eval(s.linkedVar + "=" + val); - eval(s.varChangeListener + "()"); - if (s.vert == false) { - var leftSnap = s.left + (val - s.min) * (s.width - s.sliderWidth) / (s.max - s.min); - slider[pageIndex][currSlider].sliderData[100] = leftSnap; - } else { - var topSnap = s.bottom - s.sliderHeight - (val - s.min) * (s.height - s.sliderHeight) / (s.max - s.min); - slider[pageIndex][currSlider].sliderData[101] = topSnap; - } - resize(); - } - addListenerStart(slider[pageIndex][currSlider].sliderCanvas, sliderDragStart) -} - -var currScroller; -function createScroller(obj) { - var rect = obj.rect; - var z = obj.zIndex || obj.z || 2; - var vis = boolean(obj.visible, boolean(obj.vis, true)); - var min = obj.min || 0; - var max = obj.max; - //var colors = obj.colors || ['#3FF','#00F','#333','#CCC','#333']; - var colors = obj.colors || { - buttons: '#3FF', - slider: '#00F', - border: '#333', - back: '#CCC', - buttonsBorder: '#333', - arrows: '#333' - }; - var sliderHeight = obj.sliderHeight || (rect[3] - rect[2] * 2) / (max - min); - var inc = obj.inc || 1; - var incDist = (rect[3] - 2 * rect[2] - sliderHeight) / ((max - min) / inc); - var sliderRect = [rect[0], rect[1] + rect[2], rect[2], sliderHeight]; - var radius = def([obj.radius, 0]); - var scroller = { - rect: rect, - zIndex: z, - min: min, - max: max, - value: min, - colors: colors, - sliderRect: sliderRect, - sliderHeight: sliderHeight, - inc: inc, - incDist: incDist, - radius: radius - }; - if (typeof obj.funcMove == 'function') - scroller.funcMove = obj.funcMove; - if (typeof obj.funcStop == 'function') - scroller.funcStop = obj.funcStop; - scroller.canvas = newctx({ - rect: scroller.rect, - pE: true, - z: scroller.zIndex - }).canvas; - scroller.canvas.scroller = scroller; - scroller.ctx = scroller.canvas.ctx; - scroller.slider = {}; - scroller.sliderCanvas = newctx({ - rect: sliderRect, - pE: true, - z: scroller.zIndex + 1 - }).canvas; - scroller.sliderCanvas.scroller = scroller; - scroller.sliderctx = scroller.sliderCanvas.ctx; - scroller.sliderctx.fillStyle = colors[1]; - scroller.sliderctx.fillRect(0, 0, sliderRect[2], sliderRect[3]); - scroller.reposition = function (newMax, newRect, sliderHeight) { - if (!un(newMax)) - this.max = newMax; - if (!un(newRect)) - this.rect = newRect; - this.canvas.data[100] = this.rect[0]; - this.canvas.data[101] = this.rect[1]; - this.canvas.data[102] = this.rect[2]; - this.canvas.data[103] = this.rect[3]; - resizeCanvas(this.canvas, this.rect[0], this.rect[1], this.rect[2], this.rect[3]); - this.canvas.width = this.rect[2]; - this.canvas.height = this.rect[3]; - if (!un(sliderHeight)) { - this.sliderHeight = sliderHeight; - } else { - this.sliderHeight = (this.rect[3] - this.rect[2] * 2) / (this.max - this.min); - } - this.sliderRect = [this.rect[0], this.rect[1] + this.rect[2], this.rect[2], this.sliderHeight]; - this.sliderCanvas.data[100] = this.sliderRect[0]; - this.sliderCanvas.data[101] = this.sliderRect[1]; - this.sliderCanvas.data[102] = this.sliderRect[2]; - this.sliderCanvas.data[103] = this.sliderRect[3]; - resizeCanvas(this.sliderCanvas, this.sliderRect[0], this.sliderRect[1], this.sliderRect[2], this.sliderRect[3]); - this.sliderCanvas.width = this.sliderRect[2]; - this.sliderCanvas.height = this.sliderRect[3]; - this.draw(); - this.value = 0; - this.sliderRect[1] = this.rect[1] + this.rect[2] + (this.rect[3] - 2 * this.rect[2] - this.sliderHeight) * ((this.value - this.min) / (this.max - this.min)); - resizeCanvas(this.sliderCanvas, this.sliderRect[0], this.sliderRect[1]); - } - scroller.draw = function () { - var ctx = this.ctx; - var w = this.rect[2]; - var h = this.rect[3]; - ctx.clearRect(0, 0, w, h); - var lineWidth = this.lineWidth || 4; - var radius = this.radius; - roundedRect(ctx, lineWidth / 2, lineWidth / 2, w - lineWidth, h - lineWidth, radius, lineWidth, this.colors.border, this.colors.back); - roundedRect(ctx, lineWidth / 2, lineWidth / 2, w - lineWidth, w - lineWidth, radius, lineWidth, this.colors.buttonsBorder, this.colors.buttons); - roundedRect(ctx, lineWidth / 2, h - w, w - lineWidth, w - lineWidth, radius, lineWidth, this.colors.buttonsBorder, this.colors.buttons); - ctx.fillStyle = this.colors.arrows; - ctx.lineCap = 'round'; - ctx.lineJoin = 'round'; - ctx.beginPath(); - ctx.moveTo(w * 14 / 50, w * 34 / 50); - ctx.lineTo(w * 25 / 50, w * 16 / 50); - ctx.lineTo(w * 36 / 50, w * 34 / 50); - ctx.lineTo(w * 14 / 50, w * 34 / 50); - ctx.fill(); - ctx.beginPath(); - ctx.moveTo(w * 14 / 50, h - w + w * 16 / 50); - ctx.lineTo(w * 25 / 50, h - w + w * 34 / 50); - ctx.lineTo(w * 36 / 50, h - w + w * 16 / 50); - ctx.lineTo(w * 14 / 50, h - w + w * 16 / 50); - ctx.fill(); - this.sliderctx.fillStyle = this.colors.slider; - this.sliderctx.fillRect(0, 0, this.sliderRect[2], this.sliderHeight); - } - scroller.draw(); - addListener(scroller.canvas, function (e) { - updateMouse(e); - var scroller = this.scroller; - if (mouse.y < scroller.sliderRect[1]) { - scroller.update(-1); - } else if (mouse.y > scroller.sliderRect[1] + scroller.sliderRect[3]) { - scroller.update(1); - } - }); - addListenerStart(scroller.sliderCanvas, scrollerMoveStart); - scroller.update = function (change) { - var newValue = Math.min(this.max, Math.max(this.min, this.value + change)); - if (newValue == this.value) - return; - this.value = newValue; - this.sliderRect[1] = this.rect[1] + this.rect[2] + (this.rect[3] - 2 * this.rect[2] - this.sliderHeight) * ((this.value - this.min) / (this.max - this.min)); - resizeCanvas(this.sliderCanvas, this.sliderRect[0], this.sliderRect[1]); - if (typeof this.funcStop == 'function') { - this.funcStop(this.value); - } else if (typeof this.funcMove == 'function') { - this.funcMove(this.value); - } - } - return scroller; -} -function updateScrollerDims(s) { // update max - s.sliderHeight = (s.rect[3] - s.rect[2] * 2) / (s.max - s.min); - s.incDist = (s.rect[3] - 2 * s.rect[2] - s.sliderHeight) / ((s.max - s.min) / s.inc); - s.sliderRect[3] = s.sliderHeight; - s.sliderCanvas.data[100] = s.sliderRect[0]; - s.sliderCanvas.data[101] = s.sliderRect[1]; - s.sliderCanvas.data[102] = s.sliderRect[2]; - s.sliderCanvas.data[103] = s.sliderRect[3]; - resizeCanvas3(s.sliderCanvas); - setScrollerValue(s, s.value, true); - return s; -} -function scrollerMoveStart(e) { - updateMouse(e); - currScroller = e.target.scroller; - currScroller.dragStartPos = mouse.y; - currScroller.dragStartValue = currScroller.value; - currScroller.dragStartY = currScroller.sliderRect[1]; - currScroller.dragOffset = mouse.y - currScroller.sliderRect[1]; - currScroller.dragMinY = currScroller.rect[1] + currScroller.rect[2]; - currScroller.dragMaxY = currScroller.rect[1] + currScroller.rect[3] - currScroller.rect[2] - currScroller.sliderRect[3]; - addListenerMove(window, scrollerMoveMove); - addListenerEnd(window, scrollerMoveStop); -} -function scrollerMoveMove(e) { - updateMouse(e); - var dy = mouse.y - currScroller.dragStartPos; - var newY = Math.min(Math.max(currScroller.dragStartY + dy, currScroller.dragMinY), currScroller.dragMaxY); - if (newY == currScroller.sliderRect[1]) - return; - currScroller.sliderRect[1] = newY; - resizeCanvas(currScroller.sliderCanvas, currScroller.sliderRect[0], currScroller.sliderRect[1]); - currScroller.value = currScroller.min + (currScroller.max - currScroller.min) * (currScroller.sliderRect[1] - currScroller.dragMinY) / (currScroller.dragMaxY - currScroller.dragMinY); - if (typeof currScroller.funcMove == 'function') - currScroller.funcMove(currScroller.value); -}; -function scrollerMoveStop(e) { - if (typeof currScroller.funcStop == 'function') - currScroller.funcStop(currScroller.value); - currScroller = null; - removeListenerMove(window, scrollerMoveMove); - removeListenerEnd(window, scrollerMoveStop); -}; -function setScrollerValue(scroller, value, applyFunc) { - var newValue = Math.min(Math.max(scroller.min, value), scroller.max); - //if (newValue == scroller.value) return; - scroller.value = newValue; - scroller.sliderRect[1] = scroller.rect[1] + scroller.rect[2] + (scroller.rect[3] - 2 * scroller.rect[2] - scroller.sliderHeight) * ((scroller.value - scroller.min) / (scroller.max - scroller.min)); - resizeCanvas(scroller.sliderCanvas, scroller.sliderRect[0], scroller.sliderRect[1]); - scroller.update(0); - if (!applyFunc && applyFunc == false) - return; - if (typeof scroller.funcStop == 'function') { - scroller.funcStop(scroller.value); - } else if (typeof scroller.funcMove == 'function') { - scroller.funcMove(scroller.value); - } -} -function moveScroller(scroller, left, top) { - var relTop = scroller.sliderCanvas.data[101] - scroller.canvas.data[100]; - scroller.sliderRect[0] = left; - scroller.sliderRect[1] = top + relTop; - scroller.rect[0] = left; - scroller.rect[1] = top; - scroller.canvas.data[100] = left; - scroller.canvas.data[101] = top; - resizeCanvas3(scroller.canvas); - scroller.sliderCanvas.data[100] = left; - scroller.sliderCanvas.data[101] = top + relTop; - resizeCanvas3(scroller.sliderCanvas); -} -function hideScroller(scroller) { - if (un(scroller)) - return; - hideObj(scroller.canvas); - hideObj(scroller.sliderCanvas); -} -function showScroller(scroller) { - if (un(scroller)) - return; - showObj(scroller.canvas); - showObj(scroller.sliderCanvas); -} - -function drawArrow(object) { - var context = object.context || object.ctx; - var startX = object.startX; - var startY = object.startY; - var finX = object.finX || startX; - var finY = object.finY || startY; - - var doubleEnded; - if (typeof object.doubleEnded == 'boolean') { - doubleEnded = object.doubleEnded - } else { - doubleEnded = false - } - var arrowLength = object.arrowLength || 30; - var angleBetweenLinesRads = object.angleBetweenLinesRads || 0.5; - var fillArrow = boolean(object.fillArrow, false); - var showLine = boolean(object.showLine, true); - var dash = object.dash || []; - - context.save(); - context.strokeStyle = object.color || '#000'; - context.fillStyle = object.color || '#000'; - context.lineWidth = object.lineWidth || 4; - - if (showLine == true) { - //draw line - if (typeof context.setLineDash == 'undefined') - context.setLineDash = function () {}; - context.setLineDash(dash); - context.beginPath(); - context.moveTo(startX, startY); - context.lineTo(finX, finY); - context.stroke(); - } - - context.lineWidth = object.arrowLineWidth || object.lineWidth || 4; - context.beginPath(); - if (typeof context.setLineDash == 'undefined') - context.setLineDash = function () {}; - context.setLineDash([]); - context.lineJoin = 'round'; - context.lineCap = 'round'; - - var posX; - var posY; - var otherX; - var otherY; - var endToDraw = "fin"; - - do { - if (endToDraw == "fin") { - posX = finX; - posY = finY; - otherX = startX; - otherY = startY; - } else if (endToDraw == "start") { - posX = startX; - posY = startY; - otherX = finX; - otherY = finY; - } - - var nGradient = (-1 * (posY - otherY)) / (posX - otherX); - - var angleToHorizontal = Math.abs(Math.atan(nGradient)); - var remainingAngle = Math.PI / 2 - angleBetweenLinesRads - angleToHorizontal; - - var narrowX1, - narrowX2, - narrowY1, - narrowY2; - - if (nGradient == Infinity) { - //first half of arrow - narrowX1 = Math.sin(remainingAngle) * arrowLength; - narrowY1 = Math.cos(remainingAngle) * arrowLength; - context.moveTo(posX, posY); - context.lineTo(posX + narrowX1, posY + narrowY1); - - // second half of arrow - narrowX2 = Math.cos(angleBetweenLinesRads - angleToHorizontal) * arrowLength; - narrowY2 = Math.sin(angleBetweenLinesRads - angleToHorizontal) * arrowLength; - context.moveTo(posX, posY); - context.lineTo(posX + narrowX2, posY - narrowY2); - - if (fillArrow == true) - context.lineTo(posX + narrowX1, posY + narrowY1); - } else if (nGradient == -Infinity) { - //first half of arrow - narrowX1 = Math.sin(remainingAngle) * arrowLength; - narrowY1 = Math.cos(remainingAngle) * arrowLength; - context.moveTo(posX, posY); - context.lineTo(posX + narrowX1, posY - narrowY1); - - // second half of arrow - narrowX2 = Math.cos(angleBetweenLinesRads - angleToHorizontal) * arrowLength; - narrowY2 = Math.sin(angleBetweenLinesRads - angleToHorizontal) * arrowLength; - context.moveTo(posX, posY); - context.lineTo(posX + narrowX2, posY + narrowY2); - - if (fillArrow == true) - context.lineTo(posX + narrowX1, posY - narrowY1); - } else - - ///case 1 - arrow is pointing up and to the left - if (nGradient < 0 && posY < otherY) { - - //first half of arrow - narrowX1 = Math.sin(remainingAngle) * arrowLength; - narrowY1 = Math.cos(remainingAngle) * arrowLength; - context.moveTo(posX, posY); - context.lineTo(posX + narrowX1, posY + narrowY1); - - // second half of arrow - narrowX2 = Math.cos(angleBetweenLinesRads - angleToHorizontal) * arrowLength; - narrowY2 = Math.sin(angleBetweenLinesRads - angleToHorizontal) * arrowLength; - context.moveTo(posX, posY); - context.lineTo(posX + narrowX2, posY - narrowY2); - - if (fillArrow == true) - context.lineTo(posX + narrowX1, posY + narrowY1); - } else - - ///case 2 - arrow is pointing up and to the right - if (nGradient > 0 && posY < otherY) { - - //first half of arrow - narrowX1 = Math.sin(remainingAngle) * arrowLength; - narrowY1 = Math.cos(remainingAngle) * arrowLength; - context.moveTo(posX, posY); - context.lineTo(posX - narrowX1, posY + narrowY1); - - // second half of arrow - narrowX2 = Math.cos(angleBetweenLinesRads - angleToHorizontal) * arrowLength; - narrowY2 = Math.sin(angleBetweenLinesRads - angleToHorizontal) * arrowLength; - context.moveTo(posX, posY); - context.lineTo(posX - narrowX2, posY - narrowY2); - - if (fillArrow == true) - context.lineTo(posX - narrowX1, posY + narrowY1); - } else - - //gradient is 0 and pointing right - if (nGradient == 0 && posX > otherX) { - - //first half of arrow - narrowX1 = Math.sin(remainingAngle) * arrowLength - narrowY1 = Math.cos(remainingAngle) * arrowLength - context.moveTo(posX, posY) - context.lineTo(posX - narrowX1, posY + narrowY1) - - // second half of arrow - narrowX2 = Math.cos(angleBetweenLinesRads - angleToHorizontal) * arrowLength - narrowY2 = Math.sin(angleBetweenLinesRads - angleToHorizontal) * arrowLength - context.moveTo(posX, posY) - context.lineTo(posX - narrowX2, posY - narrowY2) - - if (fillArrow == true) - context.lineTo(posX - narrowX1, posY + narrowY1); - } else - - // gradient is 0 and pointing left - if (nGradient == 0 && posX < otherX) { - - //first half of arrow - narrowX1 = Math.sin(remainingAngle) * arrowLength - narrowY1 = Math.cos(remainingAngle) * arrowLength - context.moveTo(posX, posY) - context.lineTo(posX + narrowX1, posY + narrowY1) - - // second half of arrow - narrowX2 = Math.cos(angleBetweenLinesRads - angleToHorizontal) * arrowLength - narrowY2 = Math.sin(angleBetweenLinesRads - angleToHorizontal) * arrowLength - context.moveTo(posX, posY) - context.lineTo(posX + narrowX2, posY - narrowY2) - - if (fillArrow == true) - context.lineTo(posX + narrowX1, posY + narrowY1); - } else - - ///case 3 - arrow is pointing down and to the right - if (nGradient < 0 && posY > otherY) { - - angleBetweenLinesRads = Math.PI - angleBetweenLinesRads - remainingAngle = Math.PI / 2 - angleBetweenLinesRads - angleToHorizontal; - - //first half of arrow - narrowX1 = Math.sin(remainingAngle) * arrowLength - narrowY1 = Math.cos(remainingAngle) * arrowLength - context.moveTo(posX, posY) - context.lineTo(posX + narrowX1, posY + narrowY1) - - // second half of arrow - narrowX2 = Math.cos(angleBetweenLinesRads - angleToHorizontal) * arrowLength - narrowY2 = Math.sin(angleBetweenLinesRads - angleToHorizontal) * arrowLength - context.moveTo(posX, posY) - context.lineTo(posX + narrowX2, posY - narrowY2) - - if (fillArrow == true) - context.lineTo(posX + narrowX1, posY + narrowY1); - } else - - ///case 4 - arrow is pointing down and to the left - if (nGradient > 0 && posY > otherY) { - - angleBetweenLinesRads = Math.PI - angleBetweenLinesRads - remainingAngle = Math.PI / 2 - angleBetweenLinesRads - angleToHorizontal; - - //first half of arrow - narrowX1 = Math.sin(remainingAngle) * arrowLength - narrowY1 = Math.cos(remainingAngle) * arrowLength - context.moveTo(posX, posY) - context.lineTo(posX - narrowX1, posY + narrowY1) - - // second half of arrow - narrowX2 = Math.cos(angleBetweenLinesRads - angleToHorizontal) * arrowLength - narrowY2 = Math.sin(angleBetweenLinesRads - angleToHorizontal) * arrowLength - context.moveTo(posX, posY) - context.lineTo(posX - narrowX2, posY - narrowY2) - - if (fillArrow == true) - context.lineTo(posX - narrowX1, posY + narrowY1); - } - - if (doubleEnded == true && endToDraw == "fin") { - endToDraw = "start"; - } else { - endToDraw = "none"; - } - } while (endToDraw !== "none"); - - context.closePath(); - context.stroke(); - if (fillArrow == true) - context.fill(); - context.restore(); - -} -function drawVector(vectorCtx, lineEndPointX1, lineEndPointY1, lineEndPointX2, lineEndPointY2, arrowLength, angleBetweenLinesInRadians, opt_color, opt_lineWidth) { - - if (typeof opt_color == 'undefined') { - vectorCtx.strokeStyle = "#000"; - } - if (typeof opt_lineWidth == 'undefined') { - vectorCtx.lineWidth = 5; - } - - //draw line - - vectorCtx.beginPath(); - vectorCtx.moveTo(lineEndPointX1, lineEndPointY1); - vectorCtx.lineTo(lineEndPointX2, lineEndPointY2); - - //draw Arrow - var nMidpointX = (lineEndPointX1 + lineEndPointX2) / 2 - var nMidpointY = (lineEndPointY1 + lineEndPointY2) / 2 - - var nGradient = (-1 * (lineEndPointY2 - lineEndPointY1)) / (lineEndPointX2 - lineEndPointX1); - - var angleToHorizontal = Math.abs(Math.atan(nGradient)); - var remainingAngle = Math.PI / 2 - angleBetweenLinesInRadians - angleToHorizontal; - - var narrowX; - var narrowY; - - ///case 1 - arrow is pointing up and to the left - if (nGradient < 0 && lineEndPointY2 < lineEndPointY1) { - - //first half of arrow - - narrowX = Math.sin(remainingAngle) * arrowLength - narrowY = Math.cos(remainingAngle) * arrowLength - - vectorCtx.moveTo(nMidpointX, nMidpointY) - vectorCtx.lineTo(nMidpointX + narrowX, nMidpointY + narrowY) - - // second half of arrow - - narrowX = Math.cos(angleBetweenLinesInRadians - angleToHorizontal) * arrowLength - narrowY = Math.sin(angleBetweenLinesInRadians - angleToHorizontal) * arrowLength - - vectorCtx.moveTo(nMidpointX, nMidpointY) - vectorCtx.lineTo(nMidpointX + narrowX, nMidpointY - narrowY) - - } - - ///case 2 - arrow is pointing up and to the right - if (nGradient > 0 && lineEndPointY2 < lineEndPointY1) { - - //first half of arrow - - narrowX = Math.sin(remainingAngle) * arrowLength - narrowY = Math.cos(remainingAngle) * arrowLength - - vectorCtx.moveTo(nMidpointX, nMidpointY) - vectorCtx.lineTo(nMidpointX - narrowX, nMidpointY + narrowY) - - // second half of arrow - - narrowX = Math.cos(angleBetweenLinesInRadians - angleToHorizontal) * arrowLength - narrowY = Math.sin(angleBetweenLinesInRadians - angleToHorizontal) * arrowLength - - vectorCtx.moveTo(nMidpointX, nMidpointY) - vectorCtx.lineTo(nMidpointX - narrowX, nMidpointY - narrowY) - - } - - //gradient is 0 and pointing right - - - if (nGradient == 0 && lineEndPointX2 > lineEndPointX1) { - - //first half of arrow - - narrowX = Math.sin(remainingAngle) * arrowLength - narrowY = Math.cos(remainingAngle) * arrowLength - - vectorCtx.moveTo(nMidpointX, nMidpointY) - vectorCtx.lineTo(nMidpointX - narrowX, nMidpointY + narrowY) - - // second half of arrow - - narrowX = Math.cos(angleBetweenLinesInRadians - angleToHorizontal) * arrowLength - narrowY = Math.sin(angleBetweenLinesInRadians - angleToHorizontal) * arrowLength - - vectorCtx.moveTo(nMidpointX, nMidpointY) - vectorCtx.lineTo(nMidpointX - narrowX, nMidpointY - narrowY) - - } - - // gradient is - and pointing left - - if (nGradient == 0 && lineEndPointX2 < lineEndPointX1) { - - //first half of arrow - - narrowX = Math.sin(remainingAngle) * arrowLength - narrowY = Math.cos(remainingAngle) * arrowLength - - vectorCtx.moveTo(nMidpointX, nMidpointY) - vectorCtx.lineTo(nMidpointX + narrowX, nMidpointY + narrowY) - - // second half of arrow - - narrowX = Math.cos(angleBetweenLinesInRadians - angleToHorizontal) * arrowLength - narrowY = Math.sin(angleBetweenLinesInRadians - angleToHorizontal) * arrowLength - - vectorCtx.moveTo(nMidpointX, nMidpointY) - vectorCtx.lineTo(nMidpointX + narrowX, nMidpointY - narrowY) - - } - - ///case 3 - arrow is pointing down and to the right - if (nGradient < 0 && lineEndPointY2 > lineEndPointY1) { - - angleBetweenLinesInRadians = Math.PI - angleBetweenLinesInRadians - remainingAngle = Math.PI / 2 - angleBetweenLinesInRadians - angleToHorizontal; - - //first half of arrow - - narrowX = Math.sin(remainingAngle) * arrowLength - narrowY = Math.cos(remainingAngle) * arrowLength - - vectorCtx.moveTo(nMidpointX, nMidpointY) - vectorCtx.lineTo(nMidpointX + narrowX, nMidpointY + narrowY) - - // second half of arrow - - narrowX = Math.cos(angleBetweenLinesInRadians - angleToHorizontal) * arrowLength - narrowY = Math.sin(angleBetweenLinesInRadians - angleToHorizontal) * arrowLength - - vectorCtx.moveTo(nMidpointX, nMidpointY) - vectorCtx.lineTo(nMidpointX + narrowX, nMidpointY - narrowY) - - } - - ///case 4 - arrow is pointing down and to the left - if (nGradient > 0 && lineEndPointY2 > lineEndPointY1) { - - angleBetweenLinesInRadians = Math.PI - angleBetweenLinesInRadians - remainingAngle = Math.PI / 2 - angleBetweenLinesInRadians - angleToHorizontal; - - //first half of arrow - - narrowX = Math.sin(remainingAngle) * arrowLength - narrowY = Math.cos(remainingAngle) * arrowLength - - vectorCtx.moveTo(nMidpointX, nMidpointY) - vectorCtx.lineTo(nMidpointX - narrowX, nMidpointY + narrowY) - - // second half of arrow - - narrowX = Math.cos(angleBetweenLinesInRadians - angleToHorizontal) * arrowLength - narrowY = Math.sin(angleBetweenLinesInRadians - angleToHorizontal) * arrowLength - - vectorCtx.moveTo(nMidpointX, nMidpointY) - vectorCtx.lineTo(nMidpointX - narrowX, nMidpointY - narrowY) - - } - - vectorCtx.closePath(); - vectorCtx.stroke(); - -} -function measureAngle(object) { - // REQUIRED - var aPos = object.a; // array: [x,y] - var bPos = object.b; // array: [x,y] - var cPos = object.c; // array: [x,y] - - // OPTIONAL - var angleType = object.angleType || 'radians'; - - // Work out the angles seperately - measured in radians anti-clockwise from north - var m1 = (bPos[1] - aPos[1]) / (aPos[0] - bPos[0]); - var angle1 = (Math.PI / 2 - Math.atan(m1)); - if (aPos[0] <= bPos[0]) - angle1 += Math.PI; - if (aPos[0] == bPos[0]) { // if infinite gradient - if (aPos[1] < bPos[1]) { - angle1 = 0; - } else { - angle1 = Math.PI; - } - } - - var m2 = (cPos[1] - bPos[1]) / (bPos[0] - cPos[0]); - var angle2 = (Math.PI / 2 - Math.atan(m2)); - if (bPos[0] >= cPos[0]) - angle2 += Math.PI; - if (bPos[0] == cPos[0]) { // if infinite gradient - if (bPos[1] > cPos[1]) { - angle2 = 0; - } else { - angle2 = Math.PI; - } - } - - var angleDiff = angle2 - angle1; - if (angle1 > angle2) - angleDiff = angle2 - (angle1 - 2 * Math.PI); - if (angleType == 'degrees') - angleDiff = angleDiff * 180 / Math.PI; - - return angleDiff; -} -function drawAngle(obj) { - // REQUIRED - var ctx = obj.ctx || obj.context; - var aPos = obj.a; // array: [x,y] - var bPos = obj.b; // array: [x,y] - var cPos = obj.c; // array: [x,y] - - // OPTIONAL - if (typeof obj.sf !== 'undefined') { - var sf = obj.sf; - } else { - var sf = 1; - } - if (sf !== 1) { - aPos = [aPos[0] * sf, aPos[1] * sf]; - bPos = [bPos[0] * sf, bPos[1] * sf]; - cPos = [cPos[0] * sf, cPos[1] * sf]; - } - var labelCtx = obj.labelCtx || ctx; - var radius = obj.angleRadius * sf || obj.radius * sf || 35 * sf; - var forceRightAngle = boolean(obj.forceRightAngle, false); - var squareForRight = boolean(obj.squareForRight, true); - var labelIfRight = boolean(obj.labelIfRight, false); - - var drawLines = boolean(obj.drawLines, false); - var lineWidth = obj.lineWidth * sf || 4 * sf; - var armWidth = obj.armWidth * sf || lineWidth; - var lineColor = obj.lineColor || '#000'; - var armColor = obj.armColor || lineColor; - - var numOfCurves = obj.numOfCurves || 1; - var curveGap = obj.curveGap || 4 * sf + lineWidth; - - var drawCurve = boolean(obj.drawCurve, true); - var curveWidth = obj.curveWidth * sf || lineWidth; - var curveColor = obj.curveColor || lineColor; - - var fill = boolean(obj.fill, false); - var fillColor = obj.fillColor || '#CCF'; - if (fillColor == 'none') - fill = false; - - var label = obj.label || ['']; - var labelFont = obj.labelFont || 'Arial'; - var labelFontSize = obj.labelFontSize * sf || 30 * sf; - var labelColor = obj.labelColor || '#000'; - var labelRadius = obj.labelRadius * sf || radius * 1.1; - var labelBox = obj.labelBox || { - type: 'none' - }; - if (boolean(obj.labelBackFill, false) === true) { - labelBox = { - type: 'tight', - color: mainCanvasFillStyle, - borderColor: mainCanvasFillStyle, - padding: 0.1 - }; - } - - var labelMeasure = boolean(obj.labelMeasure, false); - var measureRoundTo = obj.measureRoundTo || 1; - var angleType = obj.angleType || 'degrees'; - - function lowerCaseTest(string) { - var upperCase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789lkhfdb'.split(''); - for (var i = 0; i < upperCase.length; i++) { - if (string.indexOf(upperCase[i]) > -1) - return false; - } - return true; - } - - // Work out the angles required - measured in radians anti-clockwise from north - var m1 = (bPos[1] - aPos[1]) / (aPos[0] - bPos[0]); - var angle1 = (Math.PI / 2 - Math.atan(m1)); - if (aPos[0] <= bPos[0]) - angle1 += Math.PI; - if (aPos[0] == bPos[0]) { // if infinite gradient - if (aPos[1] < bPos[1]) { - angle1 = 0; - } else { - angle1 = Math.PI; - } - } - - var m2 = (cPos[1] - bPos[1]) / (bPos[0] - cPos[0]); - var angle2 = (Math.PI / 2 - Math.atan(m2)); - if (bPos[0] >= cPos[0]) - angle2 += Math.PI; - if (bPos[0] == cPos[0]) { // if infinite gradient - if (bPos[1] > cPos[1]) { - angle2 = 0; - } else { - angle2 = Math.PI; - } - } - - var angleDiff = angle2 - angle1; - if (angle1 > angle2) angleDiff = angle2 - (angle1 - 2 * Math.PI); - - // test if right-angled - if (forceRightAngle == true || (squareForRight == true && roundToNearest(angleDiff * 180 / Math.PI, measureRoundTo) == 90)) { - var dAngle = angle1 + 0.5 * angleDiff; - if (angle1 > angle2) { - dAngle = (angle1 - 2 * Math.PI) + 0.5 * angleDiff; - } - var dPos = [bPos[0] + radius * Math.cos(dAngle - Math.PI / 2), bPos[1] + radius * Math.sin(dAngle - Math.PI / 2)]; - - // other vertices of the square - var abLength = Math.sqrt(Math.pow(bPos[0] - aPos[0], 2) + Math.pow(bPos[1] - aPos[1], 2)); - var aPos2 = [bPos[0] + (aPos[0] - bPos[0]) * radius / (abLength * Math.sqrt(2)), bPos[1] + (aPos[1] - bPos[1]) * radius / (abLength * Math.sqrt(2))]; - - var bcLength = Math.sqrt(Math.pow(bPos[0] - cPos[0], 2) + Math.pow(bPos[1] - cPos[1], 2)); - var cPos2 = [bPos[0] + (cPos[0] - bPos[0]) * radius / (bcLength * Math.sqrt(2)), bPos[1] + (cPos[1] - bPos[1]) * radius / (bcLength * Math.sqrt(2))]; - - if (fill == true) { - ctx.fillStyle = fillColor; - ctx.beginPath(); - ctx.moveTo(bPos[0], bPos[1]); - ctx.lineTo(aPos2[0], aPos2[1]); - ctx.lineTo(dPos[0], dPos[1]); - ctx.lineTo(cPos2[0], cPos2[1]); - ctx.closePath(); - ctx.fill(); - } - - if (drawLines == true) { - ctx.strokeStyle = armColor; - ctx.lineWidth = armWidth; - ctx.beginPath(); - ctx.joinCap = 'round'; - ctx.moveTo(aPos[0], aPos[1]); - ctx.lineTo(bPos[0], bPos[1]); - ctx.lineTo(cPos[0], cPos[1]); - ctx.stroke(); - } - - if (drawCurve == true) { - ctx.strokeStyle = curveColor; - ctx.lineWidth = curveWidth; - ctx.beginPath(); - ctx.moveTo(aPos2[0], aPos2[1]); - ctx.lineTo(dPos[0], dPos[1]); - ctx.lineTo(cPos2[0], cPos2[1]); - ctx.stroke(); - } - - if (labelIfRight == true) { - if (labelMeasure == true) { - var angleDiff2 = angleDiff; - if (angleType == 'degrees') - angleDiff2 = angleDiff2 * 180 / Math.PI; - angleDiff2 = roundToNearest(angleDiff2, measureRoundTo); - label = [String(angleDiff2)]; - if (angleType == 'degrees') { - label = [String(angleDiff2) + String.fromCharCode(0x00B0)] - }; - } - - // work out label position - // d is midPoint of ac - var dAngle = angle1 + 0.5 * angleDiff; - if (angle1 > angle2) { - dAngle = (angle1 - 2 * Math.PI) + 0.5 * angleDiff; - } - var dPos = [bPos[0] + 1.85 * radius * Math.cos(dAngle - Math.PI / 2), bPos[1] + 1.85 * radius * Math.sin(dAngle - Math.PI / 2)]; - - if (labelCtx == ctx) { - drawMathsText(labelCtx, label, labelFontSize, dPos[0], dPos[1] + 0.5 * labelFontSize, true, [], 'center', 'bottom'); - } else { - var labelCanvas = labelCtx.canvas; - var labelWidth = labelCanvas.width; - var labelHeight = labelCanvas.height; - //console.log(taskObject,pageIndex); - //var canvasNum = taskObject.indexOf(labelCanvas); - //var labelData = taskObjectData[canvasNum]; - - labelCtx.clearRect(0, 0, labelWidth, labelHeight); - - drawMathsText(labelCtx, label, labelFontSize, 0.5 * labelWidth, 0.5 * labelHeight + 0.5 * labelFontSize, true, [], 'center', 'bottom'); - labelCanvas.data[100] = dPos[0] - 0.5 * labelWidth; - labelCanvas.data[101] = dPos[1] - 0.5 * labelHeight; - resizeCanvas3(labelCanvas); - } - } else if (labelCtx !== ctx) { - var labelCanvas = labelCtx.canvas; - var labelWidth = labelCanvas.width; - var labelHeight = labelCanvas.height; - labelCtx.clearRect(0, 0, labelWidth, labelHeight); - } - - } else { - // points at the end of the arc drawn for the angle - var abLength = Math.sqrt(Math.pow(bPos[0] - aPos[0], 2) + Math.pow(bPos[1] - aPos[1], 2)); - var aPos2 = [bPos[0] + (aPos[0] - bPos[0]) * radius / abLength, bPos[1] + (aPos[1] - bPos[1]) * radius / abLength]; - - var bcLength = Math.sqrt(Math.pow(bPos[0] - cPos[0], 2) + Math.pow(bPos[1] - cPos[1], 2)); - var cPos2 = [bPos[0] + (cPos[0] - bPos[0]) * radius / bcLength, bPos[1] + (cPos[1] - bPos[1]) * radius / bcLength]; - - if (labelMeasure == true) { - var angleDiff2 = angleDiff; - if (angleType == 'degrees') - angleDiff2 = angleDiff2 * 180 / Math.PI; - angleDiff2 = roundToNearest(angleDiff2, measureRoundTo); - label = [String(angleDiff2)]; - if (angleType == 'degrees') { - label = [String(angleDiff2) + String.fromCharCode(0x00B0)] - }; - } - - // work out label position - // d is midPoint of ac - var dAngle = angle1 + 0.5 * angleDiff; - if (angle1 > angle2) { - dAngle = (angle1 - 2 * Math.PI) + 0.5 * angleDiff; - } - - var labelRadiusFactor = 1.5 + 0.11 * (removeTags(label[0]).length - 1); - var lowerCaseOnly = lowerCaseTest(removeTags(label[0])); - var lcHeightAdjust = 0; - if (lowerCaseOnly == true) - lcHeightAdjust = labelFontSize / 5; - - if (dAngle < Math.PI / 6 || dAngle > 11 * Math.PI / 6 || (dAngle > 5 * Math.PI / 6 && dAngle < 7 * Math.PI / 6)) { - labelRadiusFactor = labelRadiusFactor * 0.9; - } else if (dAngle < Math.PI / 4 || dAngle > 7 * Math.PI / 4 || (dAngle > 3 * Math.PI / 4 && dAngle < 5 * Math.PI / 4)) { - labelRadiusFactor = labelRadiusFactor * 0.95; - } - - var dPos = [bPos[0] + labelRadiusFactor * labelRadius * Math.cos(dAngle - Math.PI / 2), bPos[1] + labelRadiusFactor * labelRadius * Math.sin(dAngle - Math.PI / 2) - lcHeightAdjust]; - - /* draw a dot at dPos (for testing angle label position - ctx.fillStyle = '#F00'; - ctx.beginPath(); - ctx.arc(dPos[0],dPos[1],8,0,2*Math.PI); - ctx.closePath(); - ctx.fill(); - //*/ - - label.unshift('<><><>'); - - if (fill == true && boolean(obj.measureOnly, true) == true) { - ctx.fillStyle = fillColor; - ctx.beginPath(); - ctx.moveTo(bPos[0], bPos[1]); - ctx.lineTo(aPos2[0], aPos2[1]); - ctx.arc(bPos[0], bPos[1], radius, angle1 - 0.5 * Math.PI, angle2 - 0.5 * Math.PI); - ctx.lineTo(cPos2[0], cPos2[1]); - ctx.closePath(); - ctx.fill(); - } - - if (drawLines == true && boolean(obj.measureOnly, true) == true) { - ctx.strokeStyle = armColor; - ctx.lineWidth = armWidth; - ctx.joinCap = 'round'; - ctx.beginPath(); - ctx.moveTo(aPos[0], aPos[1]); - ctx.lineTo(bPos[0], bPos[1]); - ctx.lineTo(cPos[0], cPos[1]); - ctx.stroke(); - } - - if (drawCurve == true && boolean(obj.measureOnly, true) == true) { - ctx.strokeStyle = curveColor; - ctx.lineWidth = curveWidth; - if (numOfCurves == 1) { - ctx.beginPath(); - ctx.moveTo(aPos2[0], aPos2[1]); - ctx.arc(bPos[0], bPos[1], Math.abs(radius), angle1 - 0.5 * Math.PI, angle2 - 0.5 * Math.PI); - ctx.stroke(); - } else if (numOfCurves == 2) { - ctx.beginPath(); - ctx.arc(bPos[0], bPos[1], Math.abs(radius - curveGap / 2), angle1 - 0.5 * Math.PI, angle2 - 0.5 * Math.PI); - ctx.stroke(); - ctx.beginPath(); - ctx.arc(bPos[0], bPos[1], Math.abs(radius + curveGap / 2), angle1 - 0.5 * Math.PI, angle2 - 0.5 * Math.PI); - ctx.stroke(); - } else if (numOfCurves == 3) { - ctx.beginPath(); - ctx.arc(bPos[0], bPos[1], Math.abs(radius - curveGap), angle1 - 0.5 * Math.PI, angle2 - 0.5 * Math.PI); - ctx.stroke(); - ctx.beginPath(); - ctx.arc(bPos[0], bPos[1], Math.abs(radius), angle1 - 0.5 * Math.PI, angle2 - 0.5 * Math.PI); - ctx.stroke(); - ctx.beginPath(); - ctx.arc(bPos[0], bPos[1], Math.abs(radius + curveGap), angle1 - 0.5 * Math.PI, angle2 - 0.5 * Math.PI); - ctx.stroke(); - } - } - - if (labelCtx == ctx) { - if (boolean(obj.measureLabelOnly, false) == true) { - var angleLabelPos = [dPos[0] - 57.8 / 2, dPos[1] - 25, 57.8, 50]; - } else { - var angleLabelPos = text({ - ctx: labelCtx, - left: dPos[0] - 200, - top: dPos[1] - 200, - width: 400, - height: 400, - textArray: label, - align: 'center', - vertAlign: 'middle', - box: labelBox, - minTightWidth: 1, - minTightHeight: 1 - }).tightRect; - } - } else { - var labelCanvas = labelCtx.canvas; - var labelWidth = labelCanvas.width; - var labelHeight = labelCanvas.height; - //var canvasNum = taskObject[pageIndex].indexOf(labelCanvas); - //var labelData = taskObjectData[pageIndex][canvasNum]; - - labelCtx.clearRect(0, 0, labelWidth, labelHeight); - - drawMathsText(labelCtx, label, labelFontSize, 0.5 * labelWidth, 0.5 * labelHeight + 0.5 * labelFontSize, true, [], 'center', 'bottom'); - labelCanvas.data[100] = dPos[0] - 0.5 * labelWidth; - labelCanvas.data[101] = dPos[1] - 0.5 * labelHeight; - resizeCanvas3(labelCanvas); - //resize(); - } - } - return angleLabelPos; - -} -function getAngleMidAngle(obj) { - // Work out the angles required - measured in radians anti-clockwise from north - var m1 = (obj.b[1] - obj.a[1]) / (obj.a[0] - obj.b[0]); - var angle1 = (Math.PI / 2 - Math.atan(m1)); - if (obj.a[0] <= obj.b[0]) - angle1 += Math.PI; - if (obj.a[0] == obj.b[0]) { // if infinite gradient - if (obj.a[1] < obj.b[1]) { - angle1 = 0; - } else { - angle1 = Math.PI; - } - } - - var m2 = (obj.c[1] - obj.b[1]) / (obj.b[0] - obj.c[0]); - var angle2 = (Math.PI / 2 - Math.atan(m2)); - if (obj.b[0] >= obj.c[0]) - angle2 += Math.PI; - if (obj.b[0] == obj.c[0]) { // if infinite gradient - if (obj.b[1] > obj.c[1]) { - angle2 = 0; - } else { - angle2 = Math.PI; - } - } - - if (angle1 > angle2) { - var angleDiff = angle2 - (angle1 - 2 * Math.PI); - } else { - var angleDiff = angle2 - angle1; - } - - var dAngle = angle1 + 0.5 * angleDiff; - if (angle1 > angle2) { - dAngle = (angle1 - 2 * Math.PI) + 0.5 * angleDiff; - } - return dAngle - Math.PI / 2; -} -function getAngleLabelPos(obj,radius) { - var angle = getAngleMidAngle(obj); - return [obj.b[0]+radius*Math.cos(angle),obj.b[1]+radius*Math.sin(angle)] -} -function drawStar(obj) { - var ctx = obj.ctx; - var c = obj.center || obj.c; - var r = obj.radius || obj.r; - var p = obj.points || obj.p || 5; - var s = obj.step || obj.s || 2; - var vertices = []; - for (var i = 0; i < p; i++) { - var angle = -Math.PI / 2 + i * (2 * Math.PI) / p; - vertices.push([c[0] + r * Math.cos(angle), c[1] + r * Math.sin(angle)]); - } - ctx.moveTo(vertices[0][0], vertices[0][1]); - for (var i = p; i >= 0; i--) { - ctx.lineTo(vertices[(i * s) % p][0], vertices[(i * s) % p][1]); - } -} -function drawAnglesAroundPoint(obj) { - /* eg. - drawAnglesAroundPoint({ - ctx:ctx1, - center:[400,300], - points:[[300,300],[400,200],[450,250],[480,320]], - lineColor:'#000', - thickness:4, - angles:[{fill:true,fillColor:"#CFC",lineWidth:2,labelFontSize:25,labelMeasure:true,labelRadius:33,radius:30},{fill:false,fillColor:"#CFC",lineWidth:2,labelFontSize:25,labelMeasure:true,labelRadius:33,radius:30},{fill:true,fillColor:"#CFC",lineWidth:2,labelFontSize:25,labelMeasure:true,labelRadius:33,radius:30},{fill:false,fillColor:"#CFC",lineWidth:2,labelFontSize:25,labelMeasure:true,labelRadius:33,radius:30} - ] - }); - */ - - // required - var ctx = obj.ctx; - var points = obj.points; - var center = obj.center; - - // optional - var lineColor = obj.lineColor || obj.color || false; - var lineWidth = obj.lineWidth || obj.thickness || false; - var angles = obj.angles || []; - - ctx.save(); - ctx.lineJoin = 'round'; - ctx.lineCap = 'round'; - ctx.lineWidth = lineWidth; - ctx.strokeStye = lineColor; - - var angleLabelPos = []; - - for (var i = 0; i < points.length; i++) { - if (typeof angles[i] == 'object' && angles[i] !== null) { - angles[i].ctx = ctx; - angles[i].b = center; - angles[i].a = points[i]; - if (i == points.length - 1) { - angles[i].c = points[0]; - } else { - angles[i].c = points[i + 1]; - } - angles[i].drawLines = false; - if (typeof angles[i].lineWidth == 'undefined') - angles[i].lineWidth = ctx.lineWidth; - if (typeof angles[i].lineColor == 'undefined') - angles[i].lineColor = ctx.lineWidth; - if (typeof angles[i].labelColor == 'undefined') - angles[i].labelColor = ctx.strokeStyle; - angleLabelPos[i] = drawAngle(angles[i]); - } - } - - ctx.lineWidth = lineWidth; - ctx.strokeStye = lineColor; - ctx.beginPath(); - for (var p = 0; p < points.length; p++) { - ctx.moveTo(center[0], center[1]); - ctx.lineTo(points[p][0], points[p][1]); - } - ctx.stroke(); - ctx.restore(); - - return angleLabelPos; -} -function drawCylinder(obj) { - var ctx = obj.ctx; - var pos = obj.pos; // position of centre of base - var h = obj.h || obj.height; - var r = obj.r || obj.radius; - - var direction = obj.direction || obj.dir || 'vert'; // 'vert', 'horiz1' or 'horiz2' - var angle = obj.angle || Math.PI / 6; // for 'horiz2' only - - var lineWidth = obj.lineWidth || obj.thickness || false; - var lineColor = obj.lineColor || obj.color || false; - var lineDash = obj.lineDash || []; - - ctx.save(); - if (lineWidth !== false) - ctx.lineWidth = lineWidth; - if (lineColor !== false) - ctx.strokeStyle = lineColor; - ctx.lineJoin = 'round'; - ctx.lineCap = 'round'; - - var transparent = boolean(obj.transparent, true); - var backLineWidth = obj.lineWidth; - var backLineColor = obj.backLineWidth || getShades(ctx.strokeStyle)[8]; - var backLineDash = obj.backLineDash || [7, 10]; - - var fill = boolean(obj.fill, false); - if (typeof obj.fillColors !== 'undefined') { - var fillColors = obj.fillColors; - } else if (typeof obj.fillColor !== 'undefined') { - var fillColors = [obj.fillColor, obj.fillColor]; - } else { - var fillColors = ['#FCC', '#CFC']; - } - - ctx.translate(pos[0], pos[1]); - - if (direction == 'vert') { - ctx.scale(1, 0.4); - - // draw back of bottom ellipse - if (transparent == true && fill == false) { - ctx.save(); - ctx.lineWidth = backLineWidth; - ctx.strokeStyle = backLineColor; - ctx.setLineDash(backLineDash); - ctx.beginPath(); - ctx.arc(0, 0, r, Math.PI, 2 * Math.PI); - ctx.stroke(); - ctx.restore(); - } - - // draw front - ctx.beginPath(); - ctx.moveTo(r, 0); - ctx.arc(0, 0, r, 0, Math.PI); - ctx.lineTo(-r, -h / 0.4); - ctx.arc(0, -h / 0.4, r, Math.PI, 0, true); - ctx.lineTo(r, 0); - if (fill == true) { - ctx.fillStyle = fillColors[0]; - ctx.fill(); - } - ctx.stroke(); - - // draw top - ctx.beginPath(); - ctx.arc(0, -h / 0.4, r, 0, 2 * Math.PI); - if (fill == true && typeof fillColors[1] !== 'undefined' && fillColors[1] !== 'none' && fillColors[1] !== false) { - ctx.fillStyle = fillColors[1]; - ctx.fill(); - } - ctx.stroke(); - } else if (direction == 'horiz1') { - ctx.scale(0.4, 1); - - // draw back of right ellipse - if (transparent == true && fill == false) { - ctx.save(); - ctx.lineWidth = backLineWidth; - ctx.strokeStyle = backLineColor; - ctx.setLineDash(backLineDash); - ctx.beginPath(); - ctx.arc(0, 0, r, 0.5 * Math.PI, 1.5 * Math.PI); - ctx.stroke(); - ctx.restore(); - } - - // draw front - ctx.beginPath(); - ctx.moveTo(0, r); - ctx.arc(0, 0, r, 0.5 * Math.PI, 1.5 * Math.PI, true); - ctx.lineTo(-h / 0.4, -r); - ctx.arc(-h / 0.4, 0, r, 1.5 * Math.PI, 0.5 * Math.PI); - ctx.lineTo(0, r); - if (fill == true) { - ctx.fillStyle = fillColors[0]; - ctx.fill(); - } - ctx.stroke(); - - // draw left ellipse - ctx.beginPath(); - ctx.arc(-h / 0.4, 0, r, 0, 2 * Math.PI); - if (fill == true && typeof fillColors[1] !== 'undefined' && fillColors[1] !== 'none' && fillColors[1] !== false) { - ctx.fillStyle = fillColors[1]; - ctx.fill(); - } - ctx.stroke(); - } else if (direction == 'horiz2') { - var pos2 = [h * Math.cos(angle), -h * Math.sin(angle)]; - var angle1 = Math.PI / 2 - angle; - var angle2 = -angle - 0.5 * Math.PI; - var a = [r * Math.cos(angle1), r * Math.sin(angle1)]; - var b = [r * Math.cos(angle2), r * Math.sin(angle2)]; - var c = [pos2[0] + r * Math.cos(angle1), pos2[1] + r * Math.sin(angle1)]; - var d = [pos2[0] + r * Math.cos(angle2), pos2[1] + r * Math.sin(angle2)]; - - // draw back of right circle - if (transparent == true && fill == false) { - ctx.save(); - ctx.lineWidth = backLineWidth; - ctx.strokeStyle = backLineColor; - ctx.setLineDash(backLineDash); - ctx.beginPath(); - ctx.arc(pos2[0], pos2[1], r, angle1, angle2); - ctx.stroke(); - ctx.restore(); - } - - // front - ctx.beginPath(); - ctx.moveTo(d[0], d[1]); - ctx.arc(pos2[0], pos2[1], r, angle2, angle1); - ctx.lineTo(a[0], a[1]); - ctx.arc(0, 0, r, angle1, angle2, true); - ctx.lineTo(d[0], d[1]); - if (fill == true) { - ctx.fillStyle = fillColors[0]; - ctx.fill(); - } - ctx.stroke(); - - // front circle - ctx.beginPath(); - ctx.arc(0, 0, r, 0, 2 * Math.PI); - if (fill == true && typeof fillColors[1] !== 'undefined' && fillColors[1] !== 'none' && fillColors[1] !== false) { - ctx.fillStyle = fillColors[1]; - ctx.fill(); - } - ctx.stroke(); - } - - ctx.restore(); -} -function drawCuboid(obj) { - var ctx = obj.ctx; - var x = obj.x || obj.pos[0]; - var y = obj.y || obj.pos[1]; - var z = obj.z || obj.pos[2]; - var xd = obj.xd || obj.dims[0]; - var yd = obj.yd || obj.dims[1]; - var zd = obj.zd || obj.dims[2]; - - var labels = obj.labels; - var unitBaseVectors = obj.unitBaseVectors || [[Math.sqrt(3) / 2, -1 / 2], [-Math.sqrt(3) / 2, -1 / 2], [0, -1]]; - var unitLength = obj.unitLength || 15; - var baseVector = obj.baseVector || obj.baseVectors || [[unitLength * unitBaseVectors[0][0], unitLength * unitBaseVectors[0][1]], [unitLength * unitBaseVectors[1][0], unitLength * unitBaseVectors[1][1]], [unitLength * unitBaseVectors[2][0], unitLength * unitBaseVectors[2][1]]]; - var origin = obj.origin || [0, 700]; - var mag = obj.mag || 15; - - var lineWidth = obj.lineWidth || obj.thickness || false; - var lineColor = obj.lineColor || obj.color || false; - var lineDash = obj.lineDash || []; - - var showUnitCubes = boolean(obj.showUnitCubes, false); - - ctx.save(); - if (lineWidth !== false) - ctx.lineWidth = lineWidth; - if (lineColor !== false) - ctx.strokeStyle = lineColor; - ctx.lineJoin = 'round'; - ctx.lineCap = 'round'; - - var transparent = boolean(obj.transparent, true); - var backLineWidth = obj.lineWidth; - var backLineColor = obj.backLineWidth || getShades(ctx.strokeStyle)[8]; - var backLineDash = obj.backLineDash || [7, 10]; - - var fill = boolean(obj.fill, false); - if (typeof obj.fillColors !== 'undefined') { - var fillColors = obj.fillColors - } else if (typeof obj.fillColor !== 'undefined') { - var fillColors = [obj.fillColor, obj.fillColor, obj.fillColor]; - } else { - var fillColors = ['#FCC', '#CFC', '#CCF']; - } - - var cuboid = [[x, y, z], [x + xd, y, z], [x + xd, y + yd, z], [x, y + yd, z], [x, y, z + zd], [x + xd, y, z + zd], [x + xd, y + yd, z + zd], [x, y + yd, z + zd]]; - var cuboidPos = []; - for (var v = 0; v < cuboid.length; v++) { - cuboidPos[v] = []; - - cuboidPos[v][0] = origin[0]; - cuboidPos[v][0] += cuboid[v][0] * baseVector[0][0]; - cuboidPos[v][0] += cuboid[v][1] * baseVector[1][0]; - cuboidPos[v][0] += cuboid[v][2] * baseVector[2][0]; - - cuboidPos[v][1] = origin[1]; - cuboidPos[v][1] += cuboid[v][0] * baseVector[0][1]; - cuboidPos[v][1] += cuboid[v][1] * baseVector[1][1]; - cuboidPos[v][1] += cuboid[v][2] * baseVector[2][1]; - } - - if (fill == true) { - ctx.fillStyle = fillColors[0]; - if (baseVector[0][0] * baseVector[2][1] - baseVector[0][1] * baseVector[2][0] > 0) { - ctx.beginPath(); - ctx.moveTo(cuboidPos[3][0], cuboidPos[3][1]); - ctx.lineTo(cuboidPos[2][0], cuboidPos[2][1]); - ctx.lineTo(cuboidPos[6][0], cuboidPos[6][1]); - ctx.lineTo(cuboidPos[7][0], cuboidPos[7][1]); - ctx.lineTo(cuboidPos[3][0], cuboidPos[3][1]); - ctx.closePath(); - ctx.fill(); - ctx.stroke(); - } else { - ctx.beginPath(); - ctx.moveTo(cuboidPos[0][0], cuboidPos[0][1]); - ctx.lineTo(cuboidPos[1][0], cuboidPos[1][1]); - ctx.lineTo(cuboidPos[5][0], cuboidPos[5][1]); - ctx.lineTo(cuboidPos[4][0], cuboidPos[4][1]); - ctx.lineTo(cuboidPos[0][0], cuboidPos[0][1]); - ctx.closePath(); - ctx.fill(); - ctx.stroke(); - } - - ctx.fillStyle = fillColors[1]; - if (baseVector[0][0] * baseVector[1][1] - baseVector[0][1] * baseVector[1][0] > 0) { - ctx.beginPath(); - ctx.moveTo(cuboidPos[0][0], cuboidPos[0][1]); - ctx.lineTo(cuboidPos[1][0], cuboidPos[1][1]); - ctx.lineTo(cuboidPos[2][0], cuboidPos[2][1]); - ctx.lineTo(cuboidPos[3][0], cuboidPos[3][1]); - ctx.lineTo(cuboidPos[0][0], cuboidPos[0][1]); - ctx.closePath(); - ctx.fill(); - ctx.stroke(); - } else { - ctx.beginPath(); - ctx.moveTo(cuboidPos[4][0], cuboidPos[4][1]); - ctx.lineTo(cuboidPos[5][0], cuboidPos[5][1]); - ctx.lineTo(cuboidPos[6][0], cuboidPos[6][1]); - ctx.lineTo(cuboidPos[7][0], cuboidPos[7][1]); - ctx.lineTo(cuboidPos[4][0], cuboidPos[4][1]); - ctx.closePath(); - ctx.fill(); - ctx.stroke(); - } - - ctx.fillStyle = fillColors[2]; - if (baseVector[2][0] * baseVector[1][1] - baseVector[2][1] * baseVector[1][0] > 0) { - ctx.beginPath(); - ctx.moveTo(cuboidPos[2][0], cuboidPos[2][1]); - ctx.lineTo(cuboidPos[1][0], cuboidPos[1][1]); - ctx.lineTo(cuboidPos[5][0], cuboidPos[5][1]); - ctx.lineTo(cuboidPos[6][0], cuboidPos[6][1]); - ctx.lineTo(cuboidPos[2][0], cuboidPos[2][1]); - ctx.closePath(); - ctx.fill(); - ctx.stroke(); - } else { - ctx.beginPath(); - ctx.moveTo(cuboidPos[0][0], cuboidPos[0][1]); - ctx.lineTo(cuboidPos[3][0], cuboidPos[3][1]); - ctx.lineTo(cuboidPos[7][0], cuboidPos[7][1]); - ctx.lineTo(cuboidPos[4][0], cuboidPos[4][1]); - ctx.lineTo(cuboidPos[0][0], cuboidPos[0][1]); - ctx.closePath(); - ctx.fill(); - ctx.stroke(); - } - } - - if (fill == false && transparent == true) { - ctx.save(); - ctx.lineWidth = backLineWidth; - ctx.strokeStyle = backLineColor; - ctx.setLineDash(backLineDash); - ctx.beginPath(); - ctx.moveTo(cuboidPos[1][0], cuboidPos[1][1]); - ctx.lineTo(cuboidPos[2][0], cuboidPos[2][1]); - ctx.moveTo(cuboidPos[2][0], cuboidPos[2][1]); - ctx.lineTo(cuboidPos[3][0], cuboidPos[3][1]); - ctx.moveTo(cuboidPos[2][0], cuboidPos[2][1]); - ctx.lineTo(cuboidPos[6][0], cuboidPos[6][1]); - ctx.stroke(); - ctx.restore(); - } - - ctx.beginPath(); - //base - ctx.moveTo(cuboidPos[0][0], cuboidPos[0][1]); - ctx.lineTo(cuboidPos[1][0], cuboidPos[1][1]); - ctx.moveTo(cuboidPos[0][0], cuboidPos[0][1]); - ctx.lineTo(cuboidPos[3][0], cuboidPos[3][1]); - //sides - ctx.moveTo(cuboidPos[0][0], cuboidPos[0][1]); - ctx.lineTo(cuboidPos[4][0], cuboidPos[4][1]); - ctx.moveTo(cuboidPos[1][0], cuboidPos[1][1]); - ctx.lineTo(cuboidPos[5][0], cuboidPos[5][1]); - ctx.moveTo(cuboidPos[3][0], cuboidPos[3][1]); - ctx.lineTo(cuboidPos[7][0], cuboidPos[7][1]); - //top - ctx.moveTo(cuboidPos[4][0], cuboidPos[4][1]); - ctx.lineTo(cuboidPos[5][0], cuboidPos[5][1]); - ctx.lineTo(cuboidPos[6][0], cuboidPos[6][1]); - ctx.lineTo(cuboidPos[7][0], cuboidPos[7][1]); - ctx.lineTo(cuboidPos[4][0], cuboidPos[4][1]); - ctx.closePath(); - ctx.stroke(); - - /* - ctx.fillStyle = '#FFC'; - ctx.fillRect(0.5*(cuboidPos[0][0]+cuboidPos[1][0])+8,0.5*(cuboidPos[0][1]+cuboidPos[1][1])-5,19,40); - ctx.fillRect(0.5*(cuboidPos[0][0]+cuboidPos[3][0])-8,0.5*(cuboidPos[0][1]+cuboidPos[3][1])-5,-19,40); - ctx.fillRect(0.5*(cuboidPos[3][0]+cuboidPos[7][0])-8,0.5*(cuboidPos[3][1]+cuboidPos[7][1])-5,-79,40); - */ - - if (showUnitCubes == true) { - ctx.beginPath(); - - for (var i = 1; i < xd; i++) { - var pos1 = interpolateTwoPoints(cuboidPos[0], cuboidPos[1], i / xd); - var pos2 = interpolateTwoPoints(cuboidPos[4], cuboidPos[5], i / xd); - ctx.moveTo(pos1[0], pos1[1]); - ctx.lineTo(pos2[0], pos2[1]); - - var pos1 = interpolateTwoPoints(cuboidPos[4], cuboidPos[5], i / xd); - var pos2 = interpolateTwoPoints(cuboidPos[7], cuboidPos[6], i / xd); - ctx.moveTo(pos1[0], pos1[1]); - ctx.lineTo(pos2[0], pos2[1]); - } - - for (var i = 1; i < yd; i++) { - var pos1 = interpolateTwoPoints(cuboidPos[3], cuboidPos[0], i / yd); - var pos2 = interpolateTwoPoints(cuboidPos[7], cuboidPos[4], i / yd); - ctx.moveTo(pos1[0], pos1[1]); - ctx.lineTo(pos2[0], pos2[1]); - - var pos1 = interpolateTwoPoints(cuboidPos[6], cuboidPos[5], i / yd); - var pos2 = interpolateTwoPoints(cuboidPos[7], cuboidPos[4], i / yd); - ctx.moveTo(pos1[0], pos1[1]); - ctx.lineTo(pos2[0], pos2[1]); - } - - for (var i = 1; i < zd; i++) { - var pos1 = interpolateTwoPoints(cuboidPos[0], cuboidPos[4], i / zd); - var pos2 = interpolateTwoPoints(cuboidPos[1], cuboidPos[5], i / zd); - ctx.moveTo(pos1[0], pos1[1]); - ctx.lineTo(pos2[0], pos2[1]); - - var pos1 = interpolateTwoPoints(cuboidPos[0], cuboidPos[4], i / zd); - var pos2 = interpolateTwoPoints(cuboidPos[3], cuboidPos[7], i / zd); - ctx.moveTo(pos1[0], pos1[1]); - ctx.lineTo(pos2[0], pos2[1]); - } - - ctx.stroke(); - } - - if (typeof labels !== 'undefined') { - text({ - ctx: ctx, - left: 0.5 * (cuboidPos[0][0] + cuboidPos[1][0]) + 10, - top: 0.5 * (cuboidPos[0][1] + cuboidPos[1][1]) - 5, - width: 200, - textArray: labels[0] - }); - - text({ - ctx: ctx, - left: 0.5 * (cuboidPos[0][0] + cuboidPos[3][0]) - 210, - top: 0.5 * (cuboidPos[0][1] + cuboidPos[3][1]) - 5, - width: 200, - align: 'right', - textArray: labels[1] - }); - - text({ - ctx: ctx, - left: 0.5 * (cuboidPos[3][0] + cuboidPos[7][0]) - 210, - top: 0.5 * (cuboidPos[3][1] + cuboidPos[7][1]) - 5, - width: 200, - align: 'right', - textArray: labels[2] - }); - } - ctx.restore(); -} -function drawTreeDiagram(obj) { - var ctx = obj.ctx; - var left = obj.left; - var top = obj.top; - var width = obj.width; - var height = obj.height; - var branches = obj.branches || [2, 2]; - - /* - var endLabelFontSize = obj.endLabelFontSize || obj.fontSize || width/20; - var midLabelFontSize = obj.midLabelFontSize || obj.fontSize || width/20 - var labels = obj.labels || [[['win','lose']],[['win','lose],['win','lose']]]; - var probabilities = obj.probabilities || [[[[1,2],[1,2]]],[[[1,3],[2,3]],[[3,4],[1,4]]]]; - var branchColors = obj.branchColors || [[['#000','#000']],[[['#F00','#00F'],['#000','#000']]]]; - var endLabelColors = obj.endLabelColors || [[['#000','#000']],[[['#F00','#00F'],['#000','#000']]]]; - var midLabelColors = obj.midLabelColors || [[['#000','#000']],[[['#F00','#00F'],['#000','#000']]]]; - var branchLineWidths = obj.branchLineWidths || [[[3]],[[3,3],[3,3]]]; - */ - - var labels = obj.labels || [['<>win'], ['<>draw'], ['<>lose']] - var probabilities = obj.probabilities || [['<>', ['frac', ['1'], ['4']]], ['<>', ['frac', ['1'], ['2']]], ['<>', ['frac', ['1'], ['4']]]]; - - var hiddenCanvas = document.createElement('canvas'); - var ctx2 = hiddenCanvas.getContext('2d'); - var labelTightRects = []; - var maxLabelWidth = 0; - for (var i = 0; i < labels.length; i++) { - labelTightRects[i] = text({ - ctx: ctx2, - textArray: labels[i], - measureOnly: true - }).tightRect; - maxLabelWidth = Math.max(maxLabelWidth, labelTightRects[i][2] + 15); - } - - var branchWidth = (width - maxLabelWidth * branches.length) / branches.length; - - ctx.save(); - ctx.lineWidth = 3; - ctx.lineCap = 'round'; - ctx.lineJoin = 'round'; - - for (var i = 0; i < branches.length; i++) { // each vertical set of branches - var forkPoints = 1; - if (i > 0) { - for (var j = 0; j < i; j++) { - forkPoints = forkPoints * branches[j]; - } - } - var startX = left + i * branchWidth + i * maxLabelWidth; - var finX = startX + branchWidth; - var h = height / forkPoints; // height of surrouding rect for this fork point; - for (var j = 0; j < forkPoints; j++) { - var t = top + j * h; - var startY = t + 0.5 * h; - for (var k = 0; k < branches[i]; k++) { // each branch emanating from the fork point - if (branches[i] == 2) { - var finY = t + ((2 * k + 1) / 4) * h; - } else if (branches[i] == 3) { - var finY = t + ((2 * k + 1) / 6) * h; - } - //draw branch - ctx.beginPath(); - ctx.moveTo(startX, startY); - ctx.lineTo(finX, finY); - ctx.stroke(); - //draw endLabel - text({ - ctx: ctx, - textArray: labels[k], - left: finX, - top: finY - labelTightRects[k][3] / 2, - width: maxLabelWidth, - height: labelTightRects[k][3], - align: 'center', - horizAlign: 'middle', - box: { - type: 'none', - borderColor: '#00F', - padding: 0.001 - } - }); - //draw midLabel - var prob = probabilities[k]; - var measure = text({ - ctx: ctx2, - textArray: prob, - measureOnly: true - }).tightRect; - var l2 = (startX + finX) / 2 - measure[2] / 2; - if (k < branches[i] - 1) { - var t2 = (startY + finY) / 2 - measure[3] * 1.1; - } else { - var t2 = (startY + finY) / 2; ; - } - text({ - ctx: ctx, - textArray: prob, - left: l2, - top: t2, - width: measure[2], - height: measure[3], - align: 'center', - horizAlign: 'middle', - box: { - type: 'none', - borderColor: '#F00', - padding: 0.001 - } - }); - } - } - } - ctx.restore(); -} -function drawSpinner(context, center, radius, sectorAngles, sectorColors, arrowAngle, showArrow) { - if (typeof arrowAngle == 'undefined') - arrowAngle = -Math.PI / 4; - var show = boolean(showArrow, true); - - //work out angles in radians; - var vals = []; - var total = 0; - for (var val = 0; val < sectorAngles.length; val++) { - total += sectorAngles[val]; - } - var angles = [0]; // cumulative angle array - for (var val = 0; val < sectorAngles.length; val++) { - angles.push(angles[val] + (sectorAngles[val] / total) * 2 * Math.PI); - } - - context.lineWidth = 4; - context.strokeStyle = '#000'; - for (var val = 0; val < sectorAngles.length; val++) { - // draw a sector - context.fillStyle = sectorColors[val]; - context.beginPath(); - context.moveTo(center[0], center[1]); - context.arc(center[0], center[1], radius, angles[val], angles[val + 1]); - context.lineTo(center[0], center[1]); - context.closePath(); - context.fill(); - context.stroke(); - } - - if (show == true) { - context.strokeStyle = "#000"; - context.lineWidth = 4; - context.beginPath(); - context.moveTo(center[0], center[1]); - context.lineTo(center[0] + 0.75 * radius * Math.cos(arrowAngle), center[1] + 0.75 * radius * Math.sin(arrowAngle)); - context.stroke(); - drawArrow({ - context: context, - startX: center[0], - startY: center[1], - finX: center[0] + 0.75 * radius * Math.cos(arrowAngle), - finY: center[1] + 0.75 * radius * Math.sin(arrowAngle), - arrowLength: 13, - color: "#000000", - lineWidth: 4, - arrowLineWidth: 4, - fillArrow: true - }); - context.fillStyle = "#000"; - context.beginPath(); - context.arc(center[0], center[1], 5, 0, 2 * Math.PI); - context.fill(); - } -} -function vennDiagram(obj) { - var ctx = obj.ctx; - var l = obj.left || obj.l || 0; - var t = obj.top || obj.t || 0; - var w = obj.width || obj.w || 400; - var h = obj.height || obj.h || w * 0.65; - var radius = obj.radius || obj.r || w * 0.25; - var centerA = obj.centerA || [l + w * 0.35, t + h / 2]; - var centerB = obj.centerB || [l + w * 0.65, t + h / 2]; - var lineWidth = obj.lineWidth || 4; - var lineDash = obj.lineDash || []; - var strokeStyle = obj.strokeStyle || '#000'; - var colorA = obj.colorA || strokeStyle; - var colorB = obj.colorB || strokeStyle; - var labelA = obj.labelA || ['<>A']; - var labelB = obj.labelB || ['<>B']; - var fillStyle = obj.fillStyle || '#FCF'; - var shade = obj.shade || [false, false, false, false]; - - ctx.save(); - if (typeof ctx.setLineDash == 'undefined') - ctx.setLineDash = function () {}; - ctx.setLineDash(lineDash); - ctx.strokeStyle = strokeStyle; - ctx.lineWidth = lineWidth; - ctx.strokeRect(l, t, w, h); - - ctx.beginPath(); - ctx.strokeStyle = colorA; - ctx.arc(centerA[0], centerA[1], radius, 0, 2 * Math.PI); - ctx.stroke(); - - ctx.beginPath(); - ctx.strokeStyle = colorB; - ctx.arc(centerB[0], centerB[1], radius, 0, 2 * Math.PI); - ctx.stroke(); - - var xy = [centerA[0] - (radius * 1.25) * Math.cos(Math.PI / 4), centerA[1] - (radius * 1.25) * Math.cos(Math.PI / 4)]; - text({ - ctx: ctx, - textArray: labelA, - left: xy[0] - 100, - width: 200, - top: xy[1] - 100, - height: 200, - textAlign: 'center', - vertAlign: 'middle', - padding: 0.1, /*box:{type:'tight',color:mainCanvasFillStyle,borderColor:mainCanvasFillStyle}*/ - }); - - var xy = [centerB[0] + (radius * 1.25) * Math.cos(Math.PI / 4), centerB[1] - (radius * 1.25) * Math.cos(Math.PI / 4)]; - text({ - ctx: ctx, - textArray: labelB, - left: xy[0] - 100, - width: 200, - top: xy[1] - 100, - height: 200, - textAlign: 'center', - vertAlign: 'middle', - padding: 0.1, /*box:{type:'tight',color:mainCanvasFillStyle,borderColor:mainCanvasFillStyle}*/ - }); - - ctx.restore(); - - return { - ctx: ctx, - left: l, - top: t, - width: w, - height: h, - radius: radius, - centerA: centerA, - centerB: centerB, - lineWidth: lineWidth, - lineDash: lineDash, - strokeStyle: strokeStyle, - labelA: labelA, - labelB: labelB, - fillStyle: fillStyle, - shade: shade - }; -} -function vennDiagram3(obj) { - var ctx = obj.ctx; - var l = obj.left || obj.l || 0; - var t = obj.top || obj.t || 0; - var w = obj.width || obj.w || 400; - var h = obj.height || obj.h || w; - var radius = obj.radius || obj.r || w * 0.27; - var centerA = obj.centerA || [l + w * 0.5 + 0.6 * radius * Math.cos(Math.PI * (1 / 2 + 2 / 3)), t + h * 0.47 + 0.6 * radius * Math.sin(Math.PI * (1 / 2 + 2 / 3))]; - var centerB = obj.centerB || [l + w * 0.5 + 0.6 * radius * Math.cos(Math.PI * (1 / 2 + 4 / 3)), t + h * 0.47 + 0.6 * radius * Math.sin(Math.PI * (1 / 2 + 4 / 3))]; - var centerC = obj.centerC || [l + w * 0.5 + 0.6 * radius * Math.cos(Math.PI * (1 / 2)), t + h * 0.47 + 0.6 * radius * Math.sin(Math.PI * (1 / 2))]; - var lineWidth = obj.lineWidth || 4; - var lineDash = obj.lineDash || []; - var strokeStyle = obj.strokeStyle || '#000'; - var colorA = obj.colorA || strokeStyle; - var colorB = obj.colorB || strokeStyle; - var colorC = obj.colorC || strokeStyle; - var labelA = obj.labelA || ['<>A']; - var labelB = obj.labelB || ['<>B']; - var labelC = obj.labelC || ['<>C']; - var fillStyle = obj.fillStyle || '#FCF'; - var shade = obj.shade || [false, false, false, false, false, false, false, false]; - - ctx.save(); - if (typeof ctx.setLineDash == 'undefined') - ctx.setLineDash = function () {}; - ctx.setLineDash(lineDash); - ctx.strokeStyle = strokeStyle; - ctx.lineWidth = lineWidth; - ctx.strokeRect(l, t, w, h); - - ctx.beginPath(); - ctx.strokeStyle = colorA; - ctx.arc(centerA[0], centerA[1], radius, 0, 2 * Math.PI); - ctx.stroke(); - - ctx.beginPath(); - ctx.strokeStyle = colorB; - ctx.arc(centerB[0], centerB[1], radius, 0, 2 * Math.PI); - ctx.stroke(); - - ctx.beginPath(); - ctx.strokeStyle = colorC; - ctx.arc(centerC[0], centerC[1], radius, 0, 2 * Math.PI); - ctx.stroke(); - - var xy = [centerA[0] - (radius * 1.25) * Math.cos(Math.PI / 4), centerA[1] - (radius * 1.25) * Math.cos(Math.PI / 4)]; - text({ - ctx: ctx, - textArray: labelA, - left: xy[0] - 100, - width: 200, - top: xy[1] - 100, - height: 200, - textAlign: 'center', - vertAlign: 'middle', - padding: 0.1, /*box:{type:'tight',color:mainCanvasFillStyle,borderColor:mainCanvasFillStyle}*/ - }); - - var xy = [centerB[0] + (radius * 1.25) * Math.cos(Math.PI / 4), centerB[1] - (radius * 1.25) * Math.cos(Math.PI / 4)]; - text({ - ctx: ctx, - textArray: labelB, - left: xy[0] - 100, - width: 200, - top: xy[1] - 100, - height: 200, - textAlign: 'center', - vertAlign: 'middle', - padding: 0.1, /*box:{type:'tight',color:mainCanvasFillStyle,borderColor:mainCanvasFillStyle}*/ - }); - - var xy = [centerC[0] + (radius * 1.25) * Math.cos(Math.PI / 4), centerC[1] + (radius * 1.25) * Math.cos(Math.PI / 4)]; - text({ - ctx: ctx, - textArray: labelC, - left: xy[0] - 100, - width: 200, - top: xy[1] - 100, - height: 200, - textAlign: 'center', - vertAlign: 'middle', - padding: 0.1, /*box:{type:'tight',color:mainCanvasFillStyle,borderColor:mainCanvasFillStyle}*/ - }); - - ctx.restore(); - - return { - ctx: ctx, - left: l, - top: t, - width: w, - height: h, - radius: radius, - centerA: centerA, - centerB: centerB, - centerC: centerC, - lineWidth: lineWidth, - lineDash: lineDash, - strokeStyle: strokeStyle, - labelA: labelA, - labelB: labelB, - labelC: labelC, - fillStyle: fillStyle, - shade: shade - }; -} -function drawIsometricDotty(object) { - // required - var ctx = object.ctx || object.context; - - // options - var left = object.left || object.l || 0; - var top = object.top || object.t || 100; - var width = object.width || object.w || 1200; - var height = object.height || object.h || 700; - var spacingFactor = object.spacingFactor || 15; - var color = object.color || '#AAA'; - var origin = object.origin || [left + 0.5 * width, top + 0.5 * height]; - var radius = object.radius || 5; - - if (object.direction == 1) { - var baseVector = [ - [-5 * (1 / 2),5 * (Math.sqrt(3) / 2)], - [-5 * (1 / 2),-5 * (Math.sqrt(3) / 2)], - [5, 0] - ]; - } else { - var baseVector = [ - [5 * (Math.sqrt(3) / 2), -5 * (1 / 2)], - [-5 * (Math.sqrt(3) / 2), -5 * (1 / 2)], - [0, -5] - ]; - } - var points = []; - var x, - y; - - for (var i = 0; i < 2; i++) { - x = origin[0]; - y = origin[1]; - while (x >= left && y >= top && x <= left + width && y <= top + height) { - points.push([x, y]); - x += spacingFactor * baseVector[i][0]; - y += spacingFactor * baseVector[i][1]; - } - } - - for (var i = 0, lim = points.length; i < lim; i++) { - x = points[i][0]; - y = points[i][1]; - while (x >= left && y >= top && x <= left + width && y <= top + height) { - points.push([x, y]); - x += spacingFactor * baseVector[2][0]; - y += spacingFactor * baseVector[2][1]; - } - x = points[i][0]; - y = points[i][1]; - while (x >= left && y >= top && x <= left + width && y <= top + height) { - points.push([x, y]); - x -= spacingFactor * baseVector[2][0]; - y -= spacingFactor * baseVector[2][1]; - } - } - - // remove out-of-range and duplicate points - for (var i = points.length - 1; i >= 0; i--) { - for (var j = i - 1; j >= 0; j--) { - if (arraysEqual(points[i], points[j]) == true) { - points.splice(i, 1); - break; - } - } - } - - ctx.save(); - ctx.fillStyle = color; - for (var i = 0; i < points.length; i++) { - ctx.beginPath(); - ctx.arc(points[i][0], points[i][1], radius, 0, 2 * Math.PI); - ctx.fill(); - } - ctx.restore(); - return points; -} - -function drawSquareDotty(object) { - // required - var ctx = object.ctx || object.context; - - // options - var left = object.left || object.l || 0; - var top = object.top || object.t || 100; - var width = object.width || object.w || 1200; - var height = object.height || object.h || 700; - var spacingFactor = object.spacingFactor || 80; - var color = object.color || '#AAA'; - var origin = object.origin || [left + 0.5 * width, top + 0.5 * height]; - var radius = object.radius || 5; - - var points = []; - var x, - y; - - x = origin[0]; - y = origin[1]; - while (x >= left && y >= top && x <= left + width && y <= top + height) { - points.push([x, y]); - x += spacingFactor; - } - - x = origin[0] - spacingFactor; - while (x >= left && y >= top && x <= left + width && y <= top + height) { - points.push([x, y]); - x -= spacingFactor; - } - - for (var i = 0, lim = points.length; i < lim; i++) { - x = points[i][0]; - y = points[i][1] + spacingFactor; - while (x >= left && y >= top && x <= left + width && y <= top + height) { - points.push([x, y]); - y += spacingFactor; - } - y = points[i][1] - spacingFactor; - while (x >= left && y >= top && x <= left + width && y <= top + height) { - points.push([x, y]); - y -= spacingFactor; - } - } - - // remove duplicate points - for (var i = points.length - 1; i >= 0; i--) { - for (var j = i - 1; j >= 0; j--) { - if (arraysEqual(points[i], points[j]) == true) { - points.splice(i, 1); - break; - } - } - } - - ctx.save(); - ctx.fillStyle = color; - for (var i = 0; i < points.length; i++) { - ctx.beginPath(); - ctx.arc(points[i][0], points[i][1], radius, 0, 2 * Math.PI); - ctx.fill(); - } - ctx.restore(); - return points; -} -function drawNumberLine(object) { - var context = object.context; - var left = object.left; - var top = object.top; - var width = object.width; - var height = object.height; - var min = object.min; - var max = object.max; - var majorStep = object.majorStep; - var minorStep = object.minorStep; - - var minorYPos = [0.5, 0.75]; - if (typeof object.minorYPos == 'object') - minorYPos = object.minorYPos; - var majorYPos = [0.25, 0.75]; - if (typeof object.majorYPos == 'object') - majorYPos = object.majorYPos; - var minorWidth = object.minorWidth || 1.2; - var majorWidth = object.majorWidth || 2; - var minorColor = object.minorColor || '#CCC'; - var majorColor = object.majorColor || '#000'; - var lineWidth = object.lineWidth || 4; - var lineColor = object.lineColor || '#000'; - - var autoLabel = boolean(object.autoLabel, true); - var labels = object.labels; - var font = object.font || 'Arial'; - var fontSize = object.fontSize || 24; - var textColor = object.textColor || majorColor; - - var minorSpacing = (width * minorStep) / (max - min); - var majorSpacing = (width * majorStep) / (max - min); - - var x0 = left - (min * width) / (max - min); - - // draw minor markings - context.strokeStyle = minorColor; - context.lineWidth = minorWidth; - context.beginPath(); - var startValue = Math.abs(min % minorStep); - var axisPos = left; - while (axisPos - (left + width) <= 0.1) { - context.moveTo(axisPos, top + minorYPos[0] * height); - context.lineTo(axisPos, top + minorYPos[1] * height); - axisPos += minorSpacing; - } - context.stroke(); - // draw major markings - context.strokeStyle = majorColor; - context.lineWidth = majorWidth; - var startValue = Math.abs(min % majorStep); - var axisPos = left + startValue * majorSpacing; - var num = min + startValue; - var count = 0; - while (axisPos - (left + width) <= 0.1) { - context.moveTo(axisPos, top + majorYPos[0] * height); - context.lineTo(axisPos, top + majorYPos[1] * height); - if (autoLabel == true) { - text({ - context: context, - left: axisPos - 100, - width: 200, - top: top + 0.75 * height, - textArray: ['<><><><>' + num] - }) - } else if (typeof labels == 'object' && typeof labels[count] !== 'undefined') { - text({ - context: context, - left: axisPos - 100, - width: 200, - top: top + 0.75 * height, - textArray: ['<><><><>' + labels[count]] - }) - } - count++; - num += majorStep; - axisPos += majorSpacing; - } - context.stroke(); - context.strokeStyle = lineColor; - context.lineWidth = lineWidth; - context.moveTo(left, top + 0.5 * height); - context.lineTo(left + width, top + 0.5 * height); - context.stroke(); -} -function drawNumberLine2(obj) { - var ctx = obj.ctx || obj.context; - ctx.save(); - ctx.lineJoin = 'round'; - ctx.lineCap = 'round'; - var vertical = boolean(obj.vertical, false); - - if (un(obj.rect)) - obj.rect = []; - var left = obj.left || obj.rect[0]; - var top = obj.top || obj.rect[1]; - var width = obj.width || obj.rect[2]; - var height = obj.height || obj.rect[3]; - if (vertical == true) { - if (width > height) { - var temp = width; - width = height; - height = temp; - } - } - var min = Math.min(obj.min, obj.max); - var max = Math.max(obj.min, obj.max); - if (min >= max) { - console.log('Check numberline min & max.'); - return; - } - var minorStep = obj.minorStep; - var majorStep = obj.majorStep; - - var scaleOffset = obj.scaleOffset || 15; - - var minorYPos = [0.5, 0.75]; - if (typeof obj.minorYPos == 'object') - minorYPos = obj.minorYPos; - var majorYPos = [0.25, 0.75]; - if (typeof obj.majorYPos == 'object') - majorYPos = obj.majorYPos; - var minorWidth = obj.minorWidth || 1.2; - var majorWidth = obj.majorWidth || 2; - var minorColor = obj.minorColor || '#CCC'; - var majorColor = obj.majorColor || '#000'; - var lineWidth = obj.lineWidth || 4; - var lineColor = obj.lineColor || '#000'; - var backColor = obj.backColor || mainCanvasFillStyle; - - var autoLabel = boolean(obj.autoLabel, true); - var labels = obj.labels; - var font = obj.font || 'Arial'; - var fontSize = obj.fontSize || 24; - var textColor = obj.textColor || majorColor; - - if (vertical == true) { - drawNumberlineVertical(); - } else { - drawNumberlineHorizontal(); - } - - ctx.restore(); - - function drawNumberlineHorizontal() { - if (typeof obj.arrows == 'number') { - left += obj.arrows; - width -= 2 * obj.arrows; - } - var minorSpacing = (width * minorStep) / (max - min); - var majorSpacing = (width * majorStep) / (max - min); - var x0 = left - (min * width) / (max - min); - - if (boolean(obj.showMinorPos, true) == true) { - ctx.strokeStyle = minorColor; - ctx.lineWidth = minorWidth; - ctx.beginPath(); - var xAxisPoint = x0 + minorSpacing; - while (Math.round(xAxisPoint) <= Math.round(left + width)) { - if (Math.round(xAxisPoint) >= Math.round(left)) { - ctx.moveTo(xAxisPoint, top + minorYPos[0] * height); - ctx.lineTo(xAxisPoint, top + minorYPos[1] * height); - //console.log(xAxisPoint); - } - xAxisPoint += minorSpacing; - } - var xAxisPoint = x0 - minorSpacing; - while (Math.round(xAxisPoint) >= Math.round(left)) { - if (Math.round(xAxisPoint) <= Math.round(left + width)) { - ctx.moveTo(xAxisPoint, top + minorYPos[0] * height); - ctx.lineTo(xAxisPoint, top + minorYPos[1] * height); - //console.log(xAxisPoint); - } - xAxisPoint -= minorSpacing; - } - ctx.closePath(); - ctx.stroke(); - } - - // draw major lines - ctx.strokeStyle = majorColor; - ctx.lineWidth = majorWidth; - ctx.beginPath(); - var xAxisPoint = x0; - while (Math.round(xAxisPoint) <= Math.round(left + width)) { - if (Math.round(xAxisPoint) >= Math.round(left)) { - ctx.moveTo(xAxisPoint, top + majorYPos[0] * height); - ctx.lineTo(xAxisPoint, top + majorYPos[1] * height); - } - xAxisPoint += majorSpacing; - } - var xAxisPoint = x0 - majorSpacing; - while (Math.round(xAxisPoint) >= Math.round(left)) { - if (Math.round(xAxisPoint) <= Math.round(left + width)) { - ctx.moveTo(xAxisPoint, top + majorYPos[0] * height); - ctx.lineTo(xAxisPoint, top + majorYPos[1] * height); - } - xAxisPoint -= majorSpacing; - } - ctx.closePath(); - ctx.stroke(); - - if (boolean(obj.showScales, true) == true) { - // draw axes numbers - ctx.font = fontSize + 'px Arial'; - ctx.textAlign = "center"; - ctx.textBaseline = "top"; - - var xAxisPoint = x0; - var major = 0; - var placeValue = Math.pow(10, Math.floor(Math.log(majorStep) / Math.log(10))); - while (roundToNearest(xAxisPoint, 0.001) <= roundToNearest(left + width, 0.001)) { - if (xAxisPoint >= left) { - var value = roundToNearest(major * majorStep, placeValue); - var axisValue = [String(value)]; - var textWidth = ctx.measureText(String(axisValue)).width; - ctx.fillStyle = backColor; - ctx.fillRect(xAxisPoint - textWidth / 2, top + 0.5 * height + scaleOffset - 1, textWidth, fontSize * 1.1); - var labelText = drawMathsText(ctx, axisValue, fontSize, xAxisPoint, top + 0.5 * height + scaleOffset + 0.5 * fontSize, true, [], 'center', 'middle', majorColor); - } - major += 1; - xAxisPoint += majorSpacing; - } - - var xAxisPoint = x0 - majorSpacing; - var major = -1; - while (roundToNearest(xAxisPoint, 0.001) >= roundToNearest(left, 0.001)) { - if (xAxisPoint < left + width) { - var value = roundToNearest(major * majorStep, placeValue); - var axisValue = [String(value)]; - var textWidth = ctx.measureText(String(axisValue)).width; - ctx.fillStyle = backColor; - ctx.fillRect(xAxisPoint - textWidth / 2, top + 0.5 * height + scaleOffset - 1, textWidth, fontSize * 1.1); - var labelText = drawMathsText(ctx, axisValue, fontSize, xAxisPoint, top + 0.5 * height + scaleOffset + 0.5 * fontSize, true, [], 'center', 'middle', majorColor); - } - major -= 1; - xAxisPoint -= majorSpacing; - } - } - - if (typeof obj.arrows == 'number') { - drawArrow({ - ctx: ctx, - startX: left - obj.arrows, - startY: top + 0.5 * height, - finX: left + width + obj.arrows, - finY: top + 0.5 * height, - doubleEnded: true, - color: lineColor, - lineWidth: lineWidth, - fillArrow: true, - arrowLength: 12 - }); - } else { - // draw line - ctx.beginPath(); - ctx.strokeStyle = lineColor; - ctx.lineWidth = lineWidth; - ctx.moveTo(left, top + 0.5 * height); - ctx.lineTo(left + width, top + 0.5 * height); - ctx.closePath(); - ctx.stroke(); - } - - } - function drawNumberlineVertical() { - if (typeof obj.arrows == 'number') { - top += obj.arrows; - height -= 2 * obj.arrows; - } - var minorSpacing = (height * minorStep) / (max - min); - var majorSpacing = (height * majorStep) / (max - min); - var y0 = top - (min * height) / (max - min); - - if (boolean(obj.showMinorPos, true) == true) { - ctx.strokeStyle = minorColor; - ctx.lineWidth = minorWidth; - ctx.beginPath(); - var yAxisPoint = y0 + minorSpacing; - while (Math.round(yAxisPoint) <= Math.round(top + height)) { - if (Math.round(yAxisPoint) >= Math.round(top)) { - ctx.moveTo(left + minorYPos[0] * width, yAxisPoint); - ctx.lineTo(left + minorYPos[1] * width, yAxisPoint); - } - yAxisPoint += minorSpacing; - } - var yAxisPoint = y0 - minorSpacing; - while (Math.round(yAxisPoint) >= Math.round(top)) { - if (Math.round(yAxisPoint) <= Math.round(top + height)) { - ctx.moveTo(left + minorYPos[0] * width, yAxisPoint); - ctx.lineTo(left + minorYPos[1] * width, yAxisPoint); - } - yAxisPoint -= minorSpacing; - } - ctx.closePath(); - ctx.stroke(); - } - - // draw major lines - ctx.strokeStyle = majorColor; - ctx.lineWidth = majorWidth; - ctx.beginPath(); - var yAxisPoint = y0; - while (Math.round(yAxisPoint) <= Math.round(top + height)) { - if (Math.round(yAxisPoint) >= Math.round(top)) { - ctx.moveTo(left + majorYPos[0] * width, yAxisPoint); - ctx.lineTo(left + majorYPos[1] * width, yAxisPoint); - } - yAxisPoint += majorSpacing; - } - var yAxisPoint = y0 - majorSpacing; - while (Math.round(yAxisPoint) >= Math.round(top)) { - if (Math.round(yAxisPoint) <= Math.round(top + height)) { - ctx.moveTo(left + majorYPos[0] * width, yAxisPoint); - ctx.lineTo(left + majorYPos[1] * width, yAxisPoint); - } - yAxisPoint -= majorSpacing; - } - ctx.closePath(); - ctx.stroke(); - - if (boolean(obj.showScales, true) == true) { - ctx.font = fontSize + 'px Arial'; - ctx.textBaseline = "middle"; - ctx.textAlign = "right"; - - // positive y numbers - var yAxisPoint = y0; - var major = 0; - while (roundToNearest(yAxisPoint, 0.001) >= roundToNearest(top, 0.001)) { - if (yAxisPoint <= top + height) { - var axisValue = Number(roundToNearest(major * majorStep, 0.00001)); - var textWidth = ctx.measureText(String(axisValue)).width - var labelText = drawMathsText(ctx, String(axisValue), fontSize, left + majorYPos[0] * width - 10, yAxisPoint - 2, true, [], 'right', 'middle', '#000'); - } - major += 1; - yAxisPoint -= majorSpacing; - } - - // negative y numbers - var yAxisPoint = y0 + majorSpacing; - var major = -1; - while (roundToNearest(yAxisPoint, 0.001) <= roundToNearest(top + height, 0.001)) { - if (yAxisPoint >= top) { - var axisValue = Number(roundToNearest(major * majorStep, 0.00001)); - var textWidth = ctx.measureText(String(axisValue)).width - var labelText = drawMathsText(ctx, String(axisValue), fontSize, left + majorYPos[0] * width - 10, yAxisPoint - 2, true, [], 'right', 'middle', '#000'); - } - major -= 1; - yAxisPoint += majorSpacing; - - } - } - - if (typeof obj.arrows == 'number') { - drawArrow({ - ctx: ctx, - startX: left + 0.5 * width, - startY: top - obj.arrows, - finX: left + 0.5 * width, - finY: top + height + obj.arrows, - doubleEnded: true, - color: lineColor, - lineWidth: lineWidth, - fillArrow: true, - arrowLength: 12 - }); - } else { - // draw line - ctx.beginPath(); - ctx.strokeStyle = lineColor; - ctx.lineWidth = lineWidth; - ctx.moveTo(left + 0.5 * width, top); - ctx.lineTo(left + 0.5 * width, top + height); - ctx.closePath(); - ctx.stroke(); - } - - } - -} - -function isPointBetweenAngles(center, p1, p2, p3, cw) { - var a1 = posToAngle(p1[0], p1[1], center[0], center[1]); - var a2 = posToAngle(p2[0], p2[1], center[0], center[1]); - var a3 = posToAngle(p3[0], p3[1], center[0], center[1]); - if (anglesInOrder(a1, a2, a3), cw) { - return false; - } else { - return true; - } -} -function anglesInOrder(a1, a2, a3, cw) { // test if three angles are in order - while (a1 < 0) - a1 += 2 * Math.PI; - while (a2 < 0) - a2 += 2 * Math.PI; - while (a3 < 0) - a3 += 2 * Math.PI; - while (a1 > 2 * Math.PI) - a1 -= 2 * Math.PI; - while (a2 > 2 * Math.PI) - a2 -= 2 * Math.PI; - while (a3 > 2 * Math.PI) - a3 -= 2 * Math.PI; - if (boolean(cw, true) == true) { - if ((a1 <= a2 && a2 <= a3) || //123 - (a2 <= a3 && a3 <= a1) || //231 - (a3 <= a1 && a1 <= a2)) { //312 - return true; - } else { - return false; - } - } else { - if ((a3 <= a2 && a2 <= a1) || //321 - (a2 <= a1 && a1 <= a3) || //213 - (a1 <= a3 && a3 <= a2)) { //132 - return true; - } else { - return false; - } - } -} - -function roundedRect(context, left, top, width, height, roundingSize, lineThickness, lineColor, fillColor, dash) { - context.save(); - if (lineThickness) { - context.lineWidth = lineThickness - }; - if (lineColor) { - context.strokeStyle = lineColor - }; - if (fillColor) { - context.fillStyle = fillColor - }; - if (typeof dash == 'undefined') - dash = []; - if (typeof dash == 'object') { - if (!context.setLineDash) { - context.setLineDash = function () {} - } - context.setLineDash(dash); - } - context.beginPath(); - context.moveTo(left + roundingSize, top); - context.lineTo(left + width - roundingSize, top); - context.arc(left + width - roundingSize, top + roundingSize, roundingSize, 1.5 * Math.PI, 2 * Math.PI); - context.lineTo(left + width, top + height - roundingSize); - context.arc(left + width - roundingSize, top + height - roundingSize, roundingSize, 0, 0.5 * Math.PI); - context.lineTo(left + roundingSize, top + height); - context.arc(left + roundingSize, top + height - roundingSize, roundingSize, 0.5 * Math.PI, Math.PI); - context.lineTo(left, top + roundingSize); - context.arc(left + roundingSize, top + roundingSize, roundingSize, Math.PI, 1.5 * Math.PI); - context.closePath(); - if (typeof lineColor == 'string' && lineColor !== 'none') - context.stroke(); - if (typeof fillColor == 'string' && fillColor !== 'none') - context.fill(); - context.restore(); -} -function roundedRect2(context, left, top, width, height, roundingSize, lineThickness, lineColor, fillColor, dash) { - context.save(); - if (lineThickness) - context.lineWidth = lineThickness; - if (lineColor) - context.strokeStyle = lineColor; - if (fillColor) - context.fillStyle = fillColor; - if (typeof dash == 'undefined') - dash = []; - if (typeof dash == 'object') { - if (!context.setLineDash) { - context.setLineDash = function () {} - } - context.setLineDash(dash); - } - context.beginPath(); - context.moveTo(left + roundingSize, top); - context.lineTo(left + width - roundingSize, top); - context.arc(left + width - roundingSize, top + roundingSize, roundingSize, 1.5 * Math.PI, 2 * Math.PI); - context.lineTo(left + width, top + height - roundingSize); - context.arc(left + width - roundingSize, top + height - roundingSize, roundingSize, 0, 0.5 * Math.PI); - context.lineTo(left + roundingSize, top + height); - context.arc(left + roundingSize, top + height - roundingSize, roundingSize, 0.5 * Math.PI, Math.PI); - context.lineTo(left, top + roundingSize); - context.arc(left + roundingSize, top + roundingSize, roundingSize, Math.PI, 1.5 * Math.PI); - context.closePath(); - if (typeof fillColor == 'string' && fillColor !== 'none') - context.fill(); - if (typeof lineColor == 'string' && lineColor !== 'none') - context.stroke(); - context.restore(); -} -function roundedRect3(context, left, top, width, height, roundingSize, lineThickness, lineColor, fillColor, dash) { - context.save(); - if (lineThickness) { - context.lineWidth = lineThickness - }; - if (lineColor) { - context.strokeStyle = lineColor - }; - if (fillColor) { - context.fillStyle = fillColor - }; - if (typeof dash == 'undefined') - dash = []; - if (typeof dash == 'object') { - if (!context.setLineDash) { - context.setLineDash = function () {} - } - context.setLineDash(dash); - } - context.beginPath(); - context.moveTo(left + roundingSize[0], top); - context.lineTo(left + width - roundingSize[1], top); - context.arc(left + width - roundingSize[1], top + roundingSize[1], roundingSize[1], 1.5 * Math.PI, 2 * Math.PI); - context.lineTo(left + width, top + height - roundingSize[2]); - context.arc(left + width - roundingSize[2], top + height - roundingSize[2], roundingSize[2], 0, 0.5 * Math.PI); - context.lineTo(left + roundingSize[3], top + height); - context.arc(left + roundingSize[3], top + height - roundingSize[3], roundingSize[3], 0.5 * Math.PI, Math.PI); - context.lineTo(left, top + roundingSize[0]); - context.arc(left + roundingSize[0], top + roundingSize[0], roundingSize[0], Math.PI, 1.5 * Math.PI); - context.closePath(); - if (typeof fillColor == 'string' && fillColor !== 'none') { - context.fill() - }; - context.stroke(); - context.restore(); -} -function drawPath(object) { - var ctx = object.ctx; - var path = object.path; - ctx.save(); - if (typeof object.lineColor !== 'undefined') { - ctx.strokeStyle = object.lineColor - }; - if (typeof object.lineWidth !== 'undefined') { - ctx.lineWidth = object.lineWidth - }; - ctx.lineCap = 'round'; - ctx.lineJoin = 'round'; - ctx.beginPath(); - ctx.moveTo(path[0][0], path[0][1]); - for (var i = 1; i < path.length; i++) { - ctx.lineTo(path[i][0], path[i][1]); - } - if (typeof object.fillColor !== 'undefined' || object.closed == true) { - ctx.closePath() - }; - if (typeof object.fillColor !== 'undefined') { - ctx.fillStyle = object.fillColor; - ctx.fill(); - } - ctx.stroke(); - ctx.restore(); -} -function dashedLine(object) { - var context = object.context; - var startX = object.startX; - var startY = object.startY; - var finX = object.finX; - var finY = object.finY; - - if (startX > finX) { - var x1 = startX; - var y1 = startY; - var x2 = finX; - var y2 = finY; - startX = x2; - startY = y2; - finX = x1; - finY = y1; - } - - var dashSize = object.dashSize || 20; - var gapSize = object.gapSize || 10; - var color = object.color || '#000'; - var lineWidth = object.lineWidth || 2; - - var totalLength = Math.sqrt(Math.pow((finX - startX), 2) + Math.pow((finY - startY), 2)); - var numOfIncs = totalLength / (dashSize + gapSize); - - var dx = (finX - startX) / numOfIncs; - var dxDash = dx * dashSize / (dashSize + gapSize); - var dxGap = dx * gapSize / (dashSize + gapSize); - - var dy = (finY - startY) / numOfIncs; - var dyDash = dy * dashSize / (dashSize + gapSize); - var dyGap = dy * gapSize / (dashSize + gapSize); - - var xPos = startX; - var yPos = startY; - var incCount = 0; - - context.save(); - context.strokeStyle = color; - context.lineWidth = lineWidth; - context.beginPath(); - do { - context.moveTo(xPos, yPos); - xPos += dxDash; - yPos += dyDash; - context.lineTo(xPos, yPos); - xPos += dxGap; - yPos += dyGap; - incCount++; - } while (incCount <= numOfIncs - 1) - if ((startX < finX && xPos < finX) || (startX > finX && xPos > finX) || (startY < finY && yPos < finY) || (startY > finY && yPos > finY)) { - context.moveTo(xPos, yPos); - context.lineTo(finX, finY); - } - context.closePath(); - context.stroke(); - context.restore(); -} -function drawParallelArrow(object) { - // required - var context = object.context || object.ctx; - var startX = object.startX; - var startY = object.startY; - var finX = object.finX; - var finY = object.finY; - - // optional - var numOfArrows = object.numOfArrows || 1; - var arrowLength = object.arrowLength || 25; - var arrowAngle = object.arrowAngle || 0.5; - var color = object.color || '#000'; - var lineWidth = object.lineWidth || 2; - var fillArrow = boolean(object.fillArrow, false); - - context.save(); - if (numOfArrows == 1) { - - var fracPos = 0.5 + 0.5 * arrowLength * Math.cos(arrowAngle) / Math.sqrt(Math.pow((finX - startX), 2) + Math.pow((finY - startY), 2)) - drawArrow({ - context: context, - startX: startX, - startY: startY, - finX: startX + fracPos * (finX - startX), - finY: startY + fracPos * (finY - startY), - arrowLength: arrowLength, - angleBetweenLinesRads: arrowAngle, - color: color, - lineWidth: 0.1, - arrowLineWidth: lineWidth - }); - - } else if (numOfArrows == 2) { - - var fracPos1 = 0.5 + 0.75 * arrowLength * (Math.cos(arrowAngle) + 0.5) / Math.sqrt(Math.pow((finX - startX), 2) + Math.pow((finY - startY), 2)) - var fracPos2 = fracPos1 - 1 * arrowLength / Math.sqrt(Math.pow((finX - startX), 2) + Math.pow((finY - startY), 2)) - - drawArrow({ - context: context, - startX: startX, - startY: startY, - finX: startX + fracPos1 * (finX - startX), - finY: startY + fracPos1 * (finY - startY), - arrowLength: arrowLength, - angleBetweenLinesRads: arrowAngle, - color: color, - lineWidth: 0.1, - showLine: false, - arrowLineWidth: lineWidth - }); - drawArrow({ - context: context, - startX: startX, - startY: startY, - finX: startX + fracPos2 * (finX - startX), - finY: startY + fracPos2 * (finY - startY), - arrowLength: arrowLength, - angleBetweenLinesRads: arrowAngle, - color: color, - lineWidth: 0.1, - showLine: false, - arrowLineWidth: lineWidth - }); - } - context.restore(); -} -function labelLine(posA, posB, obj) { - var ctx = obj.ctx; - if (typeof hiddenCanvas == 'undefined') - hiddenCanvas = newcanvas({ - vis: false - }); - obj.ctx = hiddenCanvas.ctx; - obj.measureOnly = true; - var textDims = text(obj); - var w = textDims.tightRect[2]; - var h = textDims.tightRect[3]; - if (typeof obj.box == 'undefined' || obj.box.type !== 'tight') - w += 20; - var x1 = posA[0], - y1 = posA[1], - x2 = posB[0], - y2 = posB[1], - x4, - y4; - var x3 = (x1 + x2) / 2; - var y3 = (y1 + y2) / 2; - if (y1 == y2) { - x4 = x3 - w / 2; - if (x1 < x2) { - y4 = y3; - } else { - y4 = y3 - h; - } - } else if (x1 == x2) { - y4 = y3 - h / 2; - if (y1 < y2) { - x4 = x3 - w; - } else { - x4 = x3; - } - } else if (x1 < x2) { - if (y1 < y2) { - x4 = x3 - w; - y4 = y3; - } else { - x4 = x3; - y4 = y3; - } - } else if (x3 > x2) { - if (y3 < y2) { - x4 = x3 - w; - y4 = y3 - h; - } else { - - x4 = x3; - y4 = y3 - h; - } - } - obj.ctx = ctx; - obj.measureOnly = false; - obj.left = x4 - 10; - obj.top = y4 - 10; - obj.width = w + 20; - obj.height = h + 20; - obj.align = 'center'; - obj.vertAlign = 'middle'; - text(obj); -} -function drawDash(context, x1, y1, x2, y2, length) { - if (typeof length !== 'number') - length = 10; - var grad = - (x2 - x1) / (y2 - y1); - var midX = (x1 + x2) / 2; - var midY = (y1 + y2) / 2; - var end1X = midX - length * Math.cos(Math.atan(grad)); - var end1Y = midY - length * Math.sin(Math.atan(grad)); - var end2X = midX + length * Math.cos(Math.atan(grad)); - var end2Y = midY + length * Math.sin(Math.atan(grad)); - - context.beginPath(); - context.moveTo(end1X, end1Y); - context.lineTo(end2X, end2Y); - context.stroke(); -} -function drawDoubleDash(context, x1, y1, x2, y2, length, separation) { - if (typeof length !== 'number') - length = 10; - var sep = separation / 2 || context.lineWidth + 2 || 4; - var grad = - (x2 - x1) / (y2 - y1); - - // [unitX,unitY] is a unit vector in the direction of the line - var unitX = (x2 - x1) / Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); - var unitY = (y2 - y1) / Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2)); - - var midX = (x1 + x2) / 2; - var midY = (y1 + y2) / 2; - - var dashX1 = midX - sep * unitX; - var dashX2 = midX + sep * unitX; - var dashY1 = midY - sep * unitY; - var dashY2 = midY + sep * unitY; - - var end1X = dashX1 - length * Math.cos(Math.atan(grad)); - var end1Y = dashY1 - length * Math.sin(Math.atan(grad)); - var end2X = dashX1 + length * Math.cos(Math.atan(grad)); - var end2Y = dashY1 + length * Math.sin(Math.atan(grad)); - - var end3X = dashX2 - length * Math.cos(Math.atan(grad)); - var end3Y = dashY2 - length * Math.sin(Math.atan(grad)); - var end4X = dashX2 + length * Math.cos(Math.atan(grad)); - var end4Y = dashY2 + length * Math.sin(Math.atan(grad)); - - context.beginPath(); - context.moveTo(end1X, end1Y); - context.lineTo(end2X, end2Y); - context.moveTo(end3X, end3Y); - context.lineTo(end4X, end4Y); - context.stroke(); -} -function drawPrintIcon(ctx,rect,backColor) { - var w = rect[2]; - ctx.save(); - ctx.translate(rect[0],rect[1]); - ctx.lineJoin = 'round'; - ctx.lineCap = 'round'; - ctx.strokeStyle = '#000'; - ctx.fillStyle = '#000'; - ctx.lineWidth = 0.1*w; - - - roundedRect(ctx,0,0.3*w,w,0.45*w,0.1*w,0.1*w,'#000','#000'); - ctx.beginPath(); - ctx.fillStyle = backColor; - ctx.fillRect(0.22*w,0.65*w,0.56*w,0.15*w); - - roundedRect(ctx,0.22*w,0,0.56*w,w,0.1*w,0.1*w,'#000'); - - roundedRect(ctx,0.35*w,0.70*w,0.3*w,0.05*w,0,0.01*w,'#000','#000'); - roundedRect(ctx,0.35*w,0.82*w,0.2*w,0.05*w,0,0.01*w,'#000','#000'); - - ctx.beginPath(); - ctx.fillStyle = backColor; - ctx.arc(0.86*w,0.4*w,0.085*w,0,2*Math.PI); - ctx.fill(); - - ctx.translate(-rect[0],-rect[1]); - ctx.restore(); -} - -CanvasRenderingContext2D.prototype.setStroke = function (obj) { - var lineWidth = obj.lineWidth || obj.width || obj.w || obj.thickness || this.lineWidth; - var strokeStyle = obj.color || obj.strokeStyle || obj.style || this.strokeStyle; - var dash = obj.dash || obj.lineDash || this.getLineDash(); - var lineCap = obj.lineCap || obj.cap || 'round'; - var lineJoin = obj.lineJoin || obj.join || obj.cap || 'round'; - this.lineWidth = lineWidth; - this.strokeStyle = strokeStyle; - this.setLineDash(dash); - this.lineCap = lineCap; - this.lineJoin = lineJoin; -} -CanvasRenderingContext2D.prototype.setFill = function (obj) { - var color = obj.color || this.fillStyle; - this.fillStyle = obj.color; -} -CanvasRenderingContext2D.prototype.path = function (pathArray, close, obj) { - if (typeof obj == 'undefined') - obj = {}; - this.beginPath(); - this.moveTo(pathArray[0][0], pathArray[0][1]); - for (var i = 1; i < pathArray.length; i++) { - this.lineTo(pathArray[i][0], pathArray[i][1]); - } - if (boolean(close, false) === true) { - this.lineTo(pathArray[0][0], pathArray[0][1]); - } - if (typeof obj.fill !== 'undefined') { - this.setFill(obj.fill); - this.fill(); - } - if (typeof obj.lineDec !== 'undefined') {} - if (typeof obj.intAngles !== 'undefined') { - if (typeof obj.intAngles.show == 'undefined') { - obj.intAngles.show = []; - for (var i = 0; i < pathArray.length; i++) - obj.intAngles.show.push(true); - } - var angle = { - ctx: this - }; - angle.radius = obj.intAngles.radius || obj.intAngles.r || undefined; - angle.squareForRight = boolean(obj.intAngles.squareForRight, true); - angle.labelIfRight = boolean(obj.intAngles.labelIfRight, false); - angle.drawLines = boolean(obj.intAngles.drawLines, false); - angle.lineWidth = obj.intAngles.lineWidth || obj.intAngles.width || obj.intAngles.w || undefined; - angle.lineColor = obj.intAngles.lineColor || obj.intAngles.color || undefined; - angle.drawCurve = boolean(obj.intAngles.drawCurve, true); - angle.curveWidth = obj.intAngles.curveWidth || angle.lineWidth; - angle.curveColor = obj.intAngles.curveColor || angle.lineColor; - if (typeof obj.intAngles.fill == 'string') { - angle.fill = true; - angle.fillColor = obj.intAngles.fill; - } else { - angle.fill = boolean(obj.intAngles.fill, false); - angle.fillColor = obj.intAngles.fillColor || undefined; - } - angle.label = obj.intAngles.label || obj.intAngles.text || undefined; - angle.labelFont = obj.intAngles.labelFont || obj.intAngles.font || undefined; - angle.labelFontSize = obj.intAngles.labelFontSize || obj.intAngles.fontSize || undefined; - angle.labelColor = obj.intAngles.labelColor || angle.lineColor || undefined; - angle.labelRadius = obj.intAngles.labelRadius || undefined; - angle.labelMeasure = boolean(obj.intAngles.labelMeasure, false); - angle.measureRoundTo = obj.intAngles.measureRoundTo || obj.intAngles.roundTo || undefined; - angle.angleType = obj.intAngles.angleType || undefined; - for (var i = 0; i < pathArray.length; i++) { - if (obj.intAngles.show[i] === true) { - if (i === 0) { - angle.a = pathArray[pathArray.length - 1] - } else { - angle.a = pathArray[i - 1] - }; - angle.b = pathArray[i]; - if (i === pathArray.length - 1) { - angle.c = pathArray[0] - } else { - angle.c = pathArray[i + 1] - }; - if (typeof obj.intAngles.r == 'object') - angle.radius = obj.intAngles.r[i]; - if (typeof obj.intAngles.radius == 'object') - angle.radius = obj.intAngles.radius[i]; - if (typeof obj.intAngles.squareForRight == 'object') - angle.squareForRight = boolean(obj.intAngles.squareForRight[i], true); - if (typeof obj.intAngles.labelIfRight == 'object') - angle.labelIfRight = boolean(obj.intAngles.labelIfRight[i], false); - if (typeof obj.intAngles.drawLines == 'object') - angle.drawLines = boolean(obj.intAngles.drawLines[i], false); - if (typeof obj.intAngles.lineWidth == 'object') - angle.lineWidth = obj.intAngles.lineWidth[i]; - if (typeof obj.intAngles.width == 'object') - angle.lineWidth = obj.intAngles.width[i]; - if (typeof obj.intAngles.w == 'object') - angle.lineWidth = obj.intAngles.w[i]; - if (typeof obj.intAngles.lineColor == 'object') - angle.lineColor = obj.intAngles.lineColor[i]; - if (typeof obj.intAngles.color == 'object') - angle.lineWidth = obj.intAngles.color[i]; - if (typeof obj.intAngles.drawCurve == 'object') - angle.drawCurve = boolean(obj.intAngles.drawCurve[i], true); - if (typeof obj.intAngles.lineWidth == 'object') - angle.curveWidth = obj.intAngles.lineWidth[i]; - if (typeof obj.intAngles.curveWidth == 'object') - angle.curveWidth = obj.intAngles.curveWidth[i]; - if (typeof obj.intAngles.curveColor == 'object') - angle.curveColor = obj.intAngles.curveColor[i]; - if (typeof obj.intAngles.fill == 'object') { - if (typeof obj.intAngles.fill[i] == 'string') { - angle.fill = true; - angle.fillColor = obj.intAngles.fill[i]; - } else { - angle.fill = boolean(obj.intAngles.fill[i], false); - if (typeof obj.intAngles.fillColor == 'object') - angle.fillColor = obj.intAngles.fillColor[i]; - } - } - if (typeof obj.intAngles.label == 'object') - angle.label = obj.intAngles.label[i]; - if (typeof obj.intAngles.text == 'object') - angle.label = obj.intAngles.text[i]; - if (typeof obj.intAngles.labelFont == 'object') - angle.labelFont = obj.intAngles.curveColor[i]; - if (typeof obj.intAngles.font == 'object') - angle.labelFont = obj.intAngles.font[i]; - if (typeof obj.intAngles.labelFontSize == 'object') - angle.labelFontSize = obj.intAngles.labelFontSize[i]; - if (typeof obj.intAngles.fontSize == 'object') - angle.labelFontSize = obj.intAngles.fontSize[i]; - if (typeof obj.intAngles.lineColor == 'object') - angle.labelColor = obj.intAngles.lineColor[i]; - if (typeof obj.intAngles.labelColor == 'object') - angle.labelColor = obj.intAngles.labelColor[i]; - if (typeof obj.intAngles.labelRadius == 'object') - angle.labelRadius = obj.intAngles.labelRadius[i]; - if (typeof obj.intAngles.labelMeasure == 'object') - angle.labelMeasure = boolean(obj.intAngles.labelMeasure[i], false); - if (typeof obj.intAngles.measureRoundTo == 'object') - angle.measureRoundTo = obj.intAngles.measureRoundTo[i]; - if (typeof obj.intAngles.roundTo == 'object') - angle.measureRoundTo = obj.intAngles.roundTo[i]; - drawAngle(angle); - } - } - } - if (typeof obj.vertexLabels !== 'undefined') { - if (typeof obj.vertexLabels.show == 'undefined') { - obj.vertexLabels.show = []; - for (var i = 0; i < pathArray.length; i++) - obj.vertexLabels.show.push(true); - } - var angle = { - ctx: this - }; - angle.labelIfRight = true; - angle.drawLines = false; - angle.drawCurve = false; - angle.fill = false; - angle.label = obj.vertexLabels.label || obj.vertexLabels.text || undefined; - angle.labelFont = obj.vertexLabels.labelFont || obj.vertexLabels.font || undefined; - angle.labelFontSize = obj.vertexLabels.labelFontSize || obj.vertexLabels.fontSize || undefined; - angle.labelColor = obj.vertexLabels.labelColor || angle.lineColor || undefined; - angle.labelRadius = obj.vertexLabels.labelRadius || obj.vertexLabels.radius || obj.vertexLabels.r || undefined; - angle.labelMeasure = false; - for (var i = 0; i < pathArray.length; i++) { - if (obj.vertexLabels.show[i] === true) { - if (i === 0) { - angle.c = pathArray[pathArray.length - 1] - } else { - angle.c = pathArray[i - 1] - }; - angle.b = pathArray[i]; - if (i === pathArray.length - 1) { - angle.a = pathArray[0] - } else { - angle.a = pathArray[i + 1] - }; - if (typeof obj.vertexLabels.label == 'object') - angle.label = obj.vertexLabels.label[i]; - if (typeof obj.vertexLabels.text == 'object') - angle.label = obj.vertexLabels.text[i]; - if (typeof obj.vertexLabels.labelFont == 'object') - angle.labelFont = obj.vertexLabels.curveColor[i]; - if (typeof obj.vertexLabels.font == 'object') - angle.labelFont = obj.vertexLabels.font[i]; - if (typeof obj.vertexLabels.labelFontSize == 'object') - angle.labelFontSize = obj.vertexLabels.labelFontSize[i]; - if (typeof obj.vertexLabels.fontSize == 'object') - angle.labelFontSize = obj.vertexLabels.fontSize[i]; - if (typeof obj.vertexLabels.lineColor == 'object') - angle.labelColor = obj.vertexLabels.lineColor[i]; - if (typeof obj.vertexLabels.labelColor == 'object') - angle.labelColor = obj.vertexLabels.labelColor[i]; - if (typeof obj.vertexLabels.radius == 'object') - angle.labelRadius = obj.vertexLabels.radius[i]; - if (typeof obj.vertexLabels.r == 'object') - angle.labelRadius = obj.vertexLabels.r[i]; - if (typeof obj.vertexLabels.labelRadius == 'object') - angle.labelRadius = obj.vertexLabels.labelRadius[i]; - drawAngle(angle); - } - } - } - if (typeof obj.edgeLabels !== 'undefined') { - if (typeof obj.edgeLabels.show == 'undefined') { - obj.edgeLabels.show = []; - for (var i = 0; i < pathArray.length; i++) - obj.edgeLabels.show.push(true); - } - var label = { - ctx: this - }; - label.font = obj.edgeLabels.font || undefined; - label.fontSize = obj.edgeLabels.fontSize || undefined; - label.width = 1200; - for (var i = 0; i < pathArray.length; i++) { - if (obj.edgeLabels.show[i] === true) { - var a = pathArray[i]; - var b = pathArray[(i + 1) % pathArray.length]; - label.textArray = obj.edgeLabels.text[i]; - labelLine(a, b, label); - } - } - } - if (typeof obj.stroke !== 'undefined') { - this.beginPath(); - this.moveTo(pathArray[0][0], pathArray[0][1]); - for (var i = 1; i < pathArray.length; i++) { - this.lineTo(pathArray[i][0], pathArray[i][1]); - } - if (boolean(close, false) === true) { - this.lineTo(pathArray[0][0], pathArray[0][1]); - } - this.setStroke(obj.stroke); - this.stroke(); - } -} -CanvasRenderingContext2D.prototype.rect2 = function (obj) { - var obj = clone(obj); - if (un(obj.sf)) - obj.sf = 1; - this.save(); - var line = true; - this.lineWidth = def([obj.lineWidth, obj.thickness, this.lineWidth]) * obj.sf; - this.strokeStyle = def([obj.lineColor, obj.color, obj.strokeStyle, this.strokeStyle]); - if (obj.lineColor == 'none' || obj.color == 'none' || obj.strokeStyle == 'none') - line = false; - var fill = false; - if (!un(obj.fillColor) && obj.fillColor !== 'none') { - fill = true; - this.fillStyle = obj.fillColor; - } else if (!un(obj.fillStyle) && obj.fillStyle !== 'none') { - fill = true; - this.fillStyle = obj.fillStyle; - } - var dash = enlargeDash(def([obj.dash, this.getLineDash(), []]), this.sf); - if (!this.setLineDash) { - this.setLineDash = function () {} - } - this.setLineDash(dash); - if (!un(obj.rect)) { - obj.left = obj.rect[0]; - obj.top = obj.rect[1]; - obj.width = obj.rect[2]; - obj.height = obj.rect[3]; - } - var left = (obj.left || obj.l) * obj.sf; - var top = (obj.top || obj.t) * obj.sf; - var width = (obj.width || obj.w) * obj.sf; - var height = (obj.height || obj.h) * obj.sf; - this.beginPath(); - if (!un(obj.radius)) { - var radius = obj.radius * obj.sf; - this.moveTo(left + radius, top); - this.lineTo(left + width - radius, top); - this.arc(left + width - radius, top + radius, radius, 1.5 * Math.PI, 2 * Math.PI); - this.lineTo(left + width, top + height - radius); - this.arc(left + width - radius, top + height - radius, radius, 0, 0.5 * Math.PI); - this.lineTo(left + radius, top + height); - this.arc(left + radius, top + height - radius, radius, 0.5 * Math.PI, Math.PI); - this.lineTo(left, top + radius); - this.arc(left + radius, top + radius, radius, Math.PI, 1.5 * Math.PI); - this.closePath(); - if (fill == true) - this.fill(); - if (line == true) - this.stroke(); - } else { - if (fill == true) - this.fillRect(left, top, width, height); - if (line == true) - this.strokeRect(left, top, width, height); - } - this.restore(); -} -CanvasRenderingContext2D.prototype.clear = function () { - this.clearRect(0, 0, this.data[102], this.data[103]); -} -HTMLCanvasElement.prototype.setLeft = function (left) { - this.data[100] = left; - resizeCanvas2(this, this.data[100], this.data[101]); -} -HTMLCanvasElement.prototype.setTop = function (top) { - this.data[101] = top; - resizeCanvas2(this, this.data[100], this.data[101]); -} -HTMLCanvasElement.prototype.setPos = function (left, top) { - this.data[100] = left; - this.data[101] = top; - resizeCanvas2(this, this.data[100], this.data[101]); -} -HTMLCanvasElement.prototype.setWidth = function (width) { - this.data[102] = width; - resizeCanvas(this, this.data[100], this.data[101], this.data[102], this.data[103]); -} -HTMLCanvasElement.prototype.setHeight = function (height) { - this.data[103] = height; - resizeCanvas(this, this.data[100], this.data[101], this.data[102], this.data[103]); -} -HTMLCanvasElement.prototype.setDims = function (width, height) { - this.data[102] = width; - this.data[103] = height; - resizeCanvas(this, this.data[100], this.data[101], this.data[102], this.data[103]); -} -HTMLCanvasElement.prototype.setVis = function (vis) { - if (typeof vis == 'undefined') { - this.data[104] = !this.data[104]; - } else { - this.data[104] = vis; - } - if (this.data[104] == true) { - showObj(this); - } else { - hideObj(this); - } -} -HTMLCanvasElement.prototype.setPE = function (point) { - if (typeof point == 'undefined') { - this.data[106] = !this.data[106]; - } else { - this.data[106] = point; - } - if (this.data[106] == true) { - this.style.pointerEvents = 'auto'; - } else { - this.style.pointerEvents = 'none'; - } -} -HTMLCanvasElement.prototype.setZ = function (z) { - this.data[107] = z; - this.style.zIndex = z; -} -HTMLCanvasElement.prototype.setCursor = function (cursor) { - this.style.cursor = cursor || 'pointer'; -} -HTMLCanvasElement.prototype.setOpacity = function (opacity) { - this.style.opacity = opacity; -} - -function playButton(left, top, width, func, options) { - //visible,zIndex,fillColor,lineColor,lineWidth,radiusx - if (typeof options == 'undefined') - var options = {}; - var zIndex = options.zIndex || 2; - var button = createCanvas(left, top, width, width, boolean(options.visible, true), false, true, zIndex); - button.lineColor = options.lineColor || '#000'; - button.lineWidth = options.lineWidth || 4; - button.fillColor = options.fillColor || '#3FF'; - button.radius = options.radius || 8; - button.direction = 'right'; - if (options.dir == 'left') - button.direction = 'left'; - button.width = width; - button.left = left; - button.top = top; - button.draw = function () { - var ctx = this.ctx; - roundedRect2(ctx, this.lineWidth / 2, this.lineWidth / 2, this.width - this.lineWidth, this.width - this.lineWidth, this.radius, this.lineWidth, this.lineColor, this.fillColor); - ctx.fillStyle = this.lineColor; - ctx.lineCap = 'round'; - ctx.lineJoin = 'round'; - ctx.beginPath(); - if (this.direction == 'right') { - ctx.moveTo(this.width * 16 / 50, this.width * 14 / 50); - ctx.lineTo(this.width * 34 / 50, this.width * 25 / 50); - ctx.lineTo(this.width * 16 / 50, this.width * 36 / 50); - ctx.lineTo(this.width * 16 / 50, this.width * 14 / 50); - } else { - ctx.moveTo(this.width * 34 / 50, this.width * 14 / 50); - ctx.lineTo(this.width * 16 / 50, this.width * 25 / 50); - ctx.lineTo(this.width * 34 / 50, this.width * 36 / 50); - ctx.lineTo(this.width * 34 / 50, this.width * 14 / 50); - } - ctx.fill(); - } - button.draw(); - if (typeof func !== 'undefined') { - addListener(button, func); - } - return button; -} -function drawCalcAllowedButton(ctx, l, t, size, allowed, backColor) { - var w = size || 20; - var h = size || 20; - var color = backColor || '#FFC'; - ctx.save(); - ctx.strokeStyle = '#000'; - ctx.fillStyle = '#000'; - roundedRect(ctx, l, t, w, h, 2, 3, '#000', color); - roundedRect(ctx, l + 0.3 * w, t + 0.2 * h, w * 0.4, h * 0.6, 1, 3, '#000', '#000'); - roundedRect(ctx, l + 0.35 * w, t + 0.25 * h, w * 0.3, h * 0.15, 0.01, 3, '#000', color); - for (var i = 0; i < 3; i++) { - for (var j = 0; j < 3; j++) { - roundedRect(ctx, l + 0.35 * w + 0.12 * j * w, t + 0.45 * h + 0.12 * i * h, w * 0.08, h * 0.08, 0.01, 3, '#000', color); - } - } - if (boolean(allowed, true) == false) { - ctx.lineWidth = 0.1 * w; - ctx.lineCap = 'round'; - ctx.lineJoin = 'round'; - ctx.beginPath(); - ctx.strokeStyle = '#F00'; - ctx.moveTo(l + 0.85 * w, t + 0.15 * h); - ctx.lineTo(l + 0.15 * w, t + 0.85 * h); - ctx.stroke(); - } - ctx.restore(); -} -function drawCalcAllowedButton2(ctx, l, t, size, allowed, backColor, calcColor) { - var w = size || 20; - var h = size || 20; - var color = backColor || '#FFC'; - var color2 = calcColor || '#333'; - ctx.save(); - ctx.strokeStyle = color2; - ctx.fillStyle = color2; - roundedRect(ctx, l, t, w, h, 2, 3, '#000', color); - roundedRect(ctx, l + 0.3 * w, t + 0.2 * h, w * 0.4, h * 0.6, 1, 3, color2, color2); - roundedRect(ctx, l + 0.35 * w, t + 0.25 * h, w * 0.3, h * 0.15, 0.01, 3, color2, color); - for (var i = 0; i < 3; i++) { - for (var j = 0; j < 3; j++) { - roundedRect(ctx, l + 0.35 * w + 0.12 * j * w, t + 0.45 * h + 0.12 * i * h, w * 0.08, h * 0.08, 0.01, 3, color2, color); - } - } - if (boolean(allowed, true) == false) { - ctx.lineWidth = 0.08 * w; - ctx.lineCap = 'round'; - ctx.lineJoin = 'round'; - ctx.beginPath(); - ctx.strokeStyle = '#900'; - ctx.arc(l + 0.5 * w, t + 0.5 * h, 0.45 * w, 0, 2 * Math.PI); - ctx.stroke(); - ctx.beginPath(); - ctx.lineWidth = 0.12 * w; - ctx.moveTo(l + 0.5 * w + (1 / Math.sqrt(2)) * 0.42 * w, t + 0.5 * h - (1 / Math.sqrt(2)) * 0.42 * h); - ctx.lineTo(l + 0.5 * w - (1 / Math.sqrt(2)) * 0.42 * w, t + 0.5 * h + (1 / Math.sqrt(2)) * 0.42 * h); - //ctx.moveTo(l+0.15*w,t+0.15*h); - //ctx.lineTo(l+0.85*w,t+0.85*h); - ctx.stroke(); - - } - ctx.restore(); -} -function drawRefreshButton(ctx, l, t, size, backColor) { - var w = size || 20; - var h = size || 20; - var color = backColor || '#FFC'; - ctx.save(); - ctx.strokeStyle = '#000'; - ctx.fillStyle = '#000'; - ctx.lineCap = 'round'; - ctx.lineJoin = 'round'; - roundedRect(ctx, l, t, w, h, 8, 8, '#000', color); - ctx.lineWidth = 0.08 * w; - ctx.beginPath(); - ctx.arc(l + 0.5 * w, t + 0.5 * h, 0.22 * w, -1.8 * Math.PI, -0.2 * Math.PI); - ctx.stroke(); - ctx.beginPath(); - var l2 = l + 0.77 * w; - var t2 = t + 0.47 * h; - var arrowLength = 0.28 * w; - ctx.moveTo(l2, t2); - ctx.lineTo(l2 + arrowLength * Math.sin(1.06 * Math.PI), t2 + arrowLength * Math.cos(1.06 * Math.PI)); - ctx.lineTo(l2 + arrowLength * Math.cos(1.03 * Math.PI), t2 - arrowLength * Math.sin(1.03 * Math.PI)); - ctx.lineTo(l2, t2); - ctx.fill(); - ctx.restore(); -} -function drawRangeLabel(ctx, l, t, w, h, direction) { - var dir = 'bottom'; // default; - if (typeof direction == 'string') - dir = direction; - switch (dir) { - case 'bottom': - var p1 = [l, t]; - var p2 = [l + w / 2, t + h]; - var p3 = [l + w, t]; - var c1 = [l + w * (1 / 12), t + h * 1.3]; - var c2 = [l + w * (13 / 40), t + h * (-0.7)]; - var c3 = [l + w * (27 / 40), t + h * (-0.7)]; - var c4 = [l + w * (11 / 12), t + h * 1.3]; - break; - case 'top': - var p1 = [l, t + h]; - var p2 = [l + w / 2, t]; - var p3 = [l + w, t + h]; - var c1 = [l + w * (1 / 12), t + h - h * 1.3]; - var c2 = [l + w * (13 / 40), t + h - h * (-0.7)]; - var c3 = [l + w * (27 / 40), t + h - h * (-0.7)]; - var c4 = [l + w * (11 / 12), t + h - h * 1.3]; - break; - case 'right': - var p1 = [l, t]; - var p2 = [l + w, t + h / 2]; - var p3 = [l, t + h]; - var c1 = [l + w * 1.3, t + h * (1 / 12)]; - var c2 = [l + w * (-0.7), t + h * (13 / 40)]; - var c3 = [l + w * (-0.7), t + h * (27 / 40)]; - var c4 = [l + w * 1.3, t + h * (11 / 12)]; - break; - case 'left': - var p1 = [l + w, t]; - var p2 = [l, t + h / 2]; - var p3 = [l + w, t + h]; - var c1 = [l + w - w * 1.3, t + h * (1 / 12)]; - var c2 = [l + w - w * (-0.7), t + h * (13 / 40)]; - var c3 = [l + w - w * (-0.7), t + h * (27 / 40)]; - var c4 = [l + w - w * 1.3, t + h * (11 / 12)]; - break; - } - ctx.beginPath(); - ctx.moveTo(p1[0], p1[1]); - ctx.bezierCurveTo(c1[0], c1[1], c2[0], c2[1], p2[0], p2[1]); - ctx.bezierCurveTo(c3[0], c3[1], c4[0], c4[1], p3[0], p3[1]); - ctx.stroke(); -} - -var JSONfn = {}; -(function () { - JSONfn.stringify = function (obj) { - return JSON.stringify(obj, function (key, value) { - return (typeof value === 'function') ? value.toString() : value; - }); - } - JSONfn.parse = function (str) { - return JSON.parse(str, function (key, value) { - if (typeof value != 'string') - return value; - return (value.substring(0, 8) == 'function') ? eval('(' + value + ')') : value; - }); - } -} - ()); - -function replaceAll(string, find, replace) { - return string.replace(new RegExp(escapeRegExp(find), 'g'), replace); -} -function escapeRegExp(string) { - return string.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"); -} -function removeSpaces(string, opt_mathsInput) { - string = string.replace(/\s/g, ""); - if (typeof opt_mathsInput !== 'undefined') - setMathsInputText(opt_mathsInput, string, 0); - return string; -} -function stringTo2dArray(string, elemType) { - if (!elemType) - elemType = 'string'; - var start = string.indexOf("["); - - // replace commas with semi-colons inside array (level 1) - var bracket = 0; - for (j = start; j < string.length; j++) { - if (string.charAt(j) == "[") - bracket++; - if (string.charAt(j) == "]") - bracket--; - if (string.charAt(j) == "," && bracket == 1) { - string = string.slice(0, j) + ";" + string.slice(j + 1); - } - } - - var bracket = 0; - var fin; - for (j = start; j < string.length; j++) { - if (string.charAt(j) == "[") - bracket++; - if (string.charAt(j) == "]") - bracket--; - if (bracket == 0) { - fin = j + 1; - break; - } - } - - string = string.slice(start + 1, fin - 1); - var array = string.split(";"); - - for (j = 0; j < array.length; j++) { - var str = array[j]; - array[j] = array[j].slice(1, -1); - array[j] = array[j].split(','); - for (k = 0; k < array[j].length; k++) { - if (elemType == 'number') - array[j][k] = Number(array[j][k]); - } - } - - return array; -} -function textArrayReplace(textArray, findStr, replaceStr) { - if (typeof replaceStr == 'object') { - return textArrayReplace2(textArray, findStr, replaceStr); - } - replaceStr = String(replaceStr); - for (var i = 0; i < textArray.length; i++) { - if (typeof textArray[i] == 'string') { - textArray[i] = textStringReplace(textArray[i], findStr, replaceStr); - } else if (typeof textArray[i] == 'object') { - textArray[i] = textArrayReplace(textArray[i], findStr, replaceStr); - } - } - return textArray; -} -function textStringReplace(string, findStr, replaceStr) { - var re = new RegExp(findStr, "gi"); - return string.replace(re, replaceStr); -} -function textArrayReplace2(textArray, findStr, replacement) { - // replace string with array - for (var i = 0; i < textArray.length; i++) { - if (typeof textArray[i] == 'string') { - var pos = textArray[i].indexOf(findStr); - if (pos > -1) { - var newElems = clone(replacement); - newElems.unshift(textArray[i].slice(0, pos)); - newElems.push(textArray[i].slice(pos + findStr.length)); - textArray.splice(i, 1); - textArray.splice.apply(textArray, [i, 0].concat(newElems)); - break; - } - } else if (typeof textArray[i] == 'object') { - textArray[i] = textArrayReplace2(textArray[i], findStr, replacement); - } - } - return textArray; -} - -function getArrayCount(testArray, testValue) { - var count = 0; - for (var j = 0; j < testArray.length; j++) { - if (testArray[j] == testValue) { - count++; - } - } - return count; -} -function getArrayLessThanCount(testArray, testValue) { - var count = 0; - for (var j = 0; j < testArray.length; j++) { - if (testArray[j] < testValue) { - count++; - } - } - return count; -} -function shuffleArray(array) { - var newArray = []; - do { - var randomPos = Math.floor(Math.random() * array.length); - newArray.push(array[randomPos]); - array.splice(randomPos, 1); - } while (array.length > 0); - return newArray; -} -function buildArray(array, dim0, dim1, dim2, dim3, dim4, dim5) { - if ((typeof dim0 !== 'undefined') && (typeof array[dim0] == 'undefined')) { - array[dim0] = []; - } - if ((typeof dim1 !== 'undefined') && (typeof array[dim0][dim1] == 'undefined')) { - array[dim0][dim1] = []; - } - if ((typeof dim2 !== 'undefined') && (typeof array[dim0][dim1][dim2] == 'undefined')) { - array[dim0][dim1][dim2] = []; - } - if ((typeof dim3 !== 'undefined') && (typeof array[dim0][dim1][dim2][dim3] == 'undefined')) { - array[dim0][dim1][dim2][dim3] = []; - } - if ((typeof dim4 !== 'undefined') && (typeof array[dim0][dim1][dim2][dim3][dim4] == 'undefined')) { - array[dim0][dim1][dim2][dim3][dim4] = []; - } - if ((typeof dim5 !== 'undefined') && (typeof array[dim0][dim1][dim2][dim3][dim4][dim5] == 'undefined')) { - array[dim0][dim1][dim2][dim3][dim4][dim5] = []; - } -} -function arraySum(array) { - var sum = 0; - if (!un(array)) { - for (var a = 0, aMax = array.length; a < aMax; a++) { - sum += Number(array[a]); - } - } - return sum; -} -Array.prototype.alphanumSort = function (caseInsensitive) { - for (var z = 0, t; t = this[z]; z++) { - this[z] = [], - x = 0, - y = -1, - n = 0, - i, - j; - while (i = (j = t.charAt(x++)).charCodeAt(0)) { - var m = (i == 46 || (i >= 48 && i <= 57)); - if (m !== n) { - this[z][++y] = ""; - n = m; - } - this[z][y] += j; - } - } - - this.sort(function (a, b) { - for (var x = 0, aa, bb; (aa = a[x]) && (bb = b[x]); x++) { - if (caseInsensitive) { - aa = aa.toLowerCase(); - bb = bb.toLowerCase(); - } - if (aa !== bb) { - var c = Number(aa), - d = Number(bb); - if (c == aa && d == bb) { - return c - d; - } else - return (aa > bb) ? 1 : -1; - } - } - return a.length - b.length; - }); - - for (var z = 0; z < this.length; z++) - this[z] = this[z].join(""); -} -function compareVersion(data0, data1, levels) { - function getVersionHash(version) { - var value = 0; - version = version.split(".").map(function (a) { - var n = parseInt(a); - var letter = a.replace(n, ""); - if (letter) { - return n + letter[0].charCodeAt() / 0xFF; - } else { - return n; - } - }); - for (var i = 0; i < version.length; ++i) { - if (levels === i) - break; - value += version[i] / 0xFF * Math.pow(0xFF, levels - i + 1); - } - return value; - }; - var v1 = getVersionHash(data0); - var v2 = getVersionHash(data1); - return v1 === v2 ? -1 : v1 > v2 ? 0 : 1; -}; - -function mouseHitRect(l, t, w, h) { - var x = mouse.x; - var y = mouse.y; - if (x >= l && x <= (l + w) && y >= t && y <= (t + h)) { - return true; - } else { - return false; - } -} -function hitTestMouseOver(obj) { - if (un(obj)) - return; - var objBoundingRect = obj.getBoundingClientRect(); - var x = xCanvasToWindow(mouse.x); - var y = yCanvasToWindow(mouse.y); - if (x > objBoundingRect.left && x < objBoundingRect.right && y > objBoundingRect.top && y < objBoundingRect.bottom) { - return true; - } else { - return false; - } -} -function hitTestTwoObjects(obj1, obj2) { - var obj1BoundingRect = obj1.getBoundingClientRect(); - var obj2BoundingRect = obj2.getBoundingClientRect(); - if (obj1BoundingRect.left < obj2BoundingRect.right && obj1BoundingRect.top < obj2BoundingRect.bottom && obj1BoundingRect.right > obj2BoundingRect.left && obj1BoundingRect.bottom > obj2BoundingRect.top) { - return true - } else { - if (obj1BoundingRect.right > obj2BoundingRect.left && obj1BoundingRect.top < obj2BoundingRect.bottom && obj1BoundingRect.left < obj2BoundingRect.right && obj1BoundingRect.bottom > obj2BoundingRect.top) { - return true; - } else { - if (obj2BoundingRect.left < obj1BoundingRect.right && obj2BoundingRect.top < obj1BoundingRect.bottom && obj2BoundingRect.right > obj1BoundingRect.left && obj2BoundingRect.bottom > obj1BoundingRect.top) { - return true - } else { - if (obj2BoundingRect.right > obj1BoundingRect.left && obj2BoundingRect.top < obj1BoundingRect.bottom && obj2BoundingRect.left < obj1BoundingRect.right && obj2BoundingRect.bottom > obj1BoundingRect.top) { - return true; - } else { - return false - } - } - } - } -} -function hitTestRect(obj, left, top, width, height) { - var objBoundingRect = obj.getBoundingClientRect(); - var right = left + width; - var bottom = top + height; - left = xCanvasToWindow(left); - right = xCanvasToWindow(right); - top = yCanvasToWindow(top); - bottom = yCanvasToWindow(bottom); - if (objBoundingRect.left < right && objBoundingRect.top < bottom && objBoundingRect.right > left && objBoundingRect.bottom > top) { - return true; - } else { - if (objBoundingRect.right > left && objBoundingRect.top < bottom && objBoundingRect.left < right && objBoundingRect.bottom > top) { - return true; - } else { - if (left < objBoundingRect.right && top < objBoundingRect.bottom && right > objBoundingRect.left && bottom > objBoundingRect.top) { - return true; - } else { - if (right > objBoundingRect.left && top < objBoundingRect.bottom && left < objBoundingRect.right && bottom > objBoundingRect.top) { - return true; - } else { - return false; - } - } - } - } -} -function hitTestRect2(obj, left, top, width, height) { // tests if center of obj is in rect - var objBoundingRect = obj.getBoundingClientRect(); - var objX = objBoundingRect.left + 0.5 * (objBoundingRect.right - objBoundingRect.left); - var objY = objBoundingRect.top + 0.5 * (objBoundingRect.bottom - objBoundingRect.top); - var right = left + width; - var bottom = top + height; - left = xCanvasToWindow(left); - right = xCanvasToWindow(right); - top = yCanvasToWindow(top); - bottom = yCanvasToWindow(bottom); - if (objX < right && objY < bottom && objX > left && objY > top) { - return true; - } else { - return false; - } -} -function hitTestTwoRects(rect1, rect2) { - var xHit = false; - var yHit = false; - if ( - (rect2[0] <= rect1[0] && rect2[0] + rect2[2] >= rect1[0]) || - (rect2[0] <= rect1[0] + rect1[2] && rect2[0] + rect2[2] >= rect1[0] + rect1[2]) || - (rect2[0] >= rect1[0] && rect2[0] + rect2[2] <= rect1[0] + rect1[2])) { - xHit = true; - }; - if ( - (rect2[1] <= rect1[1] && rect2[1] + rect2[3] >= rect1[1]) || - (rect2[1] <= rect1[1] + rect1[3] && rect2[1] + rect2[3] >= rect1[1] + rect1[3]) || - (rect2[1] >= rect1[1] && rect2[1] + rect2[3] <= rect1[1] + rect1[3])) { - yHit = true; - }; - return (xHit && yHit); -} -function hitTestMouseOverRect(left, top, width, height) { // tests if mouse is in rect - REQUIRES mouse coords to have been updated - if (mouse.x < left + width && mouse.y < top + height && mouse.x > left && mouse.y > top) { - return true; - } else { - return false; - } -} -function hitTestCircle(obj, centreX, centreY, radius) { - var objBoundingRect = obj.getBoundingClientRect(); - centreX = xCanvasToWindow(centreX); - centreY = yCanvasToWindow(centreY); - if ((window.innerWidth / window.innerHeight) > (12 / 7)) { - radius = (radius / canvas.height) * window.innerHeight; - } else { - radius = (radius / canvas.width) * window.innerWidth; - } - var testPoint = []; - testPoint[0] = Math.pow((objBoundingRect.left - centreX), 2) + Math.pow((objBoundingRect.top - centreY), 2); - testPoint[1] = Math.pow((objBoundingRect.left - centreX), 2) + Math.pow((objBoundingRect.bottom - centreY), 2); - testPoint[2] = Math.pow((objBoundingRect.right - centreX), 2) + Math.pow((objBoundingRect.top - centreY), 2); - testPoint[3] = Math.pow((objBoundingRect.right - centreX), 2) + Math.pow((objBoundingRect.bottom - centreY), 2); - testPoint[4] = Math.pow((objBoundingRect.left - centreX), 2) + Math.pow(((objBoundingRect.top + objBoundingRect.bottom) / 2 - centreY), 2); - testPoint[5] = Math.pow((objBoundingRect.right - centreX), 2) + Math.pow(((objBoundingRect.top + objBoundingRect.bottom) / 2 - centreY), 2); - testPoint[6] = Math.pow(((objBoundingRect.left + objBoundingRect.right) / 2 - centreX), 2) + Math.pow((objBoundingRect.top - centreY), 2); - testPoint[7] = Math.pow(((objBoundingRect.left + objBoundingRect.right) / 2 - centreX), 2) + Math.pow((objBoundingRect.bottom - centreY), 2); - - if (getArrayLessThanCount(testPoint, Math.pow(radius, 2)) > 0) { - return true - } else { - return false - } -} -function hitTestCircle2(obj, centreX, centreY, radius) { // this one just requires the center of the object to be within the circle - var objBoundingRect = obj.getBoundingClientRect(); - centreX = xCanvasToWindow(centreX); - centreY = yCanvasToWindow(centreY); - if ((window.innerWidth / window.innerHeight) > (12 / 7)) { - radius = (radius / canvas.height) * window.innerHeight; - } else { - radius = (radius / canvas.width) * window.innerWidth; - } - var objX = objBoundingRect.left + 0.5 * objBoundingRect.width; - var objY = objBoundingRect.top + 0.5 * objBoundingRect.height; - if (Math.pow((objX - centreX), 2) + Math.pow((objY - centreY), 2) <= Math.pow(radius, 2)) { - return true - } else { - return false - } -} -function hitTestMouseOverPolygon(verticesArray) { - var x = mouse.x; - var y = mouse.y; - - // split n-agon into (n-2) triangles and test if (x,y) is in each triangle - var x1 = verticesArray[0][0]; - var y1 = verticesArray[0][1]; - - for (var i = 1; i <= verticesArray.length - 2; i++) { - var x2 = verticesArray[i][0]; - var y2 = verticesArray[i][1]; - var x3 = verticesArray[i + 1][0]; - var y3 = verticesArray[i + 1][1]; - // work out the barycentric coordinates for the triangle - // iff all are positive, (x, y) is in the triangle - var alpha = ((y2 - y3) * (x - x3) + (x3 - x2) * (y - y3)) / ((y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3)); - var beta = ((y3 - y1) * (x - x3) + (x1 - x3) * (y - y3)) / ((y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3)); - var gamma = 1 - alpha - beta; - if (alpha > 0 && beta > 0 && gamma > 0) { - return true; - } - } - return false; -} -function hitTestPolygon(point, verticesArray, includePerimeter) { - var x = point[0]; - var y = point[1]; - - // split n-agon into (n-2) triangles and test if (x,y) is in each triangle - var x1 = verticesArray[0][0]; - var y1 = verticesArray[0][1]; - - for (var i = 1; i <= verticesArray.length - 2; i++) { - var x2 = verticesArray[i][0]; - var y2 = verticesArray[i][1]; - var x3 = verticesArray[i + 1][0]; - var y3 = verticesArray[i + 1][1]; - // work out the barycentric coordinates for the triangle - // iff all are positive, (x, y) is in the triangle - var alpha = ((y2 - y3) * (x - x3) + (x3 - x2) * (y - y3)) / ((y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3)); - var beta = ((y3 - y1) * (x - x3) + (x1 - x3) * (y - y3)) / ((y2 - y3) * (x1 - x3) + (x3 - x2) * (y1 - y3)); - var gamma = 1 - alpha - beta; - if (boolean(includePerimeter, true) == true) { - if (alpha >= 0 && beta >= 0 && gamma >= 0) - return true; - } else { - if (alpha > 0 && beta > 0 && gamma > 0) - return true; - } - } - return false; -} -function hitTestPolygon2(point,pos) { - //https://stackoverflow.com/questions/8721406/how-to-determine-if-a-point-is-inside-a-2d-convex-polygon/23223947#23223947 - var result = false; - for (var i = 0, j = pos.length - 1; i < pos.length; j = i++) { - if ((pos[i][1] > point[1]) != (pos[j][1] > point[1]) && - (point[0] < (pos[j][0] - pos[i][0]) * (point[1] - pos[i][1]) / (pos[j][1]-pos[i][1]) + pos[i][0])) { - result = !result; - } - } - return result; -} -function hitTestPolygonBoundary(point,pos,tol) { - if (un(tol)) tol = 0.01; - for (var p = 0; p < pos.length; p++) { - var pos1 = pos[p]; - var pos2 = pos[(p+1)%pos.length]; - if (isPointOnLineSegment(point, pos1, pos2, tol) == true) return true; - } - return false; -} - -function motionPath(canvasData, startX, startY, finX, finY, rateType, rate) { // eg. rateType='time', rate=2000 (time in ms to complete motion) or rateType='speed', rate=200 (speed of motion in (canvas) pixels per second) - var xDistance = finX - startX; - var yDistance = finY - startY; - var distance = Math.sqrt(Math.pow(xDistance, 2) + Math.pow(yDistance, 2)); - var time; - if (rateType == 'speed') { - time = 1000 * distance / rate - }; - if (rateType == 'time') { - time = rate - }; - var dx = xDistance * 40 / time; - var dy = yDistance * 40 / time; - var frameCount = 0; - var totalFrames = Math.floor(time / 40); - var motion = setInterval(function () { - canvasData[100] += dx; - canvasData[101] += dy; - resize(); - frameCount++; - if (frameCount >= totalFrames) { - canvasData[100] = finX; - canvasData[101] = finY; - resize(); - clearInterval(motion) - }; - }, 40); -} -function motionResize(canvasData, newWidth, newHeight, time, coeX, coeY) { - //if not present, the coe will default to the centre of the object - if (!coeX) { - coeX = canvasData[100] + 0.5 * canvasData[102] - }; - if (!coeY) { - coeY = canvasData[101] + 0.5 * canvasData[103] - }; - var dw = (newWidth - canvasData[102]) * 40 / time; - var dh = (newHeight - canvasData[103]) * 40 / time; - var dx = 0.5 * (canvasData[102] - newWidth) * 40 / time; - var dy = 0.5 * (canvasData[103] - newHeight) * 40 / time; - var finX = canvasData[100] + 0.5 * (canvasData[102] - newWidth); - var finY = canvasData[101] + 0.5 * (canvasData[103] - newHeight); - var frameCount = 0; - var totalFrames = Math.floor(time / 40); - var motion = setInterval(function () { - canvasData[100] += dx; - canvasData[101] += dy; - canvasData[102] += dw; - canvasData[103] += dh; - resize(); - frameCount++; - if (frameCount >= totalFrames) { - canvasData[100] = finX; - canvasData[101] = finY; - canvasData[102] = newWidth; - canvasData[103] = newHeight; - resize(); - clearInterval(motion) - }; - }, 40); -} - -function ceiling(number, toNearest) { - // get the place value of toNearest - var decPointPos; - if (String(toNearest).indexOf('.') !== -1) { - decPointPos = String(toNearest).indexOf('.'); - } else { - decPointPos = String(toNearest).length - 1; - } - var placeValue; - for (ii = 0; ii < String(toNearest).length; ii++) { - if (String(toNearest).charAt(ii) !== "0" && String(toNearest).charAt(ii) !== ".") { - placeValue = decPointPos - ii; - } - } - // divide number and toNearesr by 10^placevalue - number = number / (Math.pow(10, placeValue)); - toNearest = toNearest / (Math.pow(10, placeValue)); - // divide number by toNearest - number = number / toNearest; - number = Math.ceil(number); - number = number * toNearest; - number = number * (Math.pow(10, placeValue)); - number = Math.round(number * 1000000000) / 1000000000; - return number; -} -function truncate(number, decPlaces) { - return + (Math.floor(number * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces)).toFixed(decPlaces); -} -function round2(number, decPlaces) { - return + (Math.round(number * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces)).toFixed(decPlaces); -} -function roundToNearest(number, toNearest) { - var testLog = Math.log(toNearest) / Math.log(10); - if (Math.abs(testLog - Math.round(testLog)) < 0.000001) { // powers of 10 - return round(number, toNearest); - } else { - // get the place value of toNearest - var decPointPos; - if (String(toNearest).indexOf('.') !== -1) { - decPointPos = String(toNearest).indexOf('.'); - } else { - decPointPos = String(toNearest).length - 1; - } - var placeValue; - for (var i = 0; i < String(toNearest).length; i++) { - if (String(toNearest).charAt(i) !== "0" && String(toNearest).charAt(i) !== ".") { - placeValue = decPointPos - i; - } - } - number = number / (Math.pow(10, placeValue)); - toNearest = toNearest / (Math.pow(10, placeValue)); - number = number / toNearest; - number = Math.round(number); - number = number * toNearest; - number = number * (Math.pow(10, placeValue)); - number = Math.round(number * 1000000000) / 1000000000; - return number; - } -} -function roundSF(number, sigFigs, showAllZeros) { - if (un(sigFigs)) sigFigs = 1; - var negative = number < 0 ? true : false; - number = Math.abs(number); - var pv = Math.floor(Math.log(number)/Math.log(10)) - (sigFigs-1); - var toNearest = Math.pow(10,pv); - var rounded = String(roundToNearest(number,toNearest)); - - var sfCount = 0; // check number of sf in answer - var dpPassed = false; - for (var d = 0; d < rounded.length; d++) { - if (rounded[d] == '-') continue; - if (rounded[d] == '.') { - if (sfCount >= sigFigs) { - rounded = rounded.slice(0,d); - break; - } else { - dpPassed = true; - continue; - } - } - if (sfCount == 0 && rounded[d] == '0') continue; - sfCount++; - if (dpPassed == true && sfCount == sigFigs) { - rounded = rounded.slice(0,d+1); - break; - } - } - if (negative == true) rounded = '-'+rounded; - return rounded; -} -function round(number, toNearest, returnAsString) { // toNearest must be a power of 10 - var sign = number < 0 ? '-' : ''; - var str = String(Math.abs(number)); - var decPos = str.indexOf('.') > -1 ? str.indexOf('.') : str.length; - var digits = []; - for (var n = 0; n < str.length; n++) { - if (isNaN(Number(str[n]))) - continue; - digits.push(Number(str[n])); - } - var roundPV = Math.round(Math.log(toNearest) / Math.log(10)); - var roundPos = Math.round(decPos - roundPV - 1); - if (roundPos >= digits.length) { - var addDigits = roundPos - digits.length; - for (var p = 0; p <= addDigits; p++) - digits.push(0); - } else { - if (roundPos == -1) { - if (digits[0] >= 5) { - digits.unshift(1); - roundPos++; - decPos++; - } else { - return 0; - } - } else if (digits[roundPos + 1] >= 5) { - if (digits[roundPos] < 9) { - digits[roundPos]++; - } else { - digits[roundPos] = 0; - var done = false; - var pos = roundPos - 1; - var count = 0; - while (done == false && count < 50) { - count++ - if (pos == -1) { - digits.unshift(1); - roundPos++; - decPos++; - done = true; - } else if (digits[pos] < 9) { - digits[pos]++; - done = true; - } else { - digits[pos] = 0; - pos--; - } - } - } - } - for (var p = roundPos + 1; p < digits.length; p++) - digits[p] = 0; - } - var str2 = sign; - for (var p = 0; p < digits.length; p++) { - if (p == decPos) { - if (roundPV < 0) { - str2 += '.'; - } else { - break; - } - } - if (p == roundPos + 1 && p > decPos) - break; - str2 += String(digits[p]); - } - if (Number(str2) == 0) - str2 = '0'; - - if (boolean(returnAsString, false) == true) { - return str2; - } else { - return Number(str2); - } - //console.log(sign,str,toNearest,decPos,digits,roundPV,roundPos,str2); -} - -function nthroot(x, n) { - try { - var negate = n % 2 == 1 && x < 0; - if (negate) - x = -x; - var possible = Math.pow(x, 1 / n); - n = Math.pow(possible, n); - if (Math.abs(x - n) < 1 && (x > 0 == n > 0)) - return negate ? -possible : possible; - } catch (e) {} -} -function hcf(x, y) { - x = Math.abs(x); - y = Math.abs(y); - // Apply Euclid's algorithm to the two numbers. - while (Math.max(x, y) % Math.min(x, y) != 0) { - if (x > y) { - x %= y; - } else { - y %= x; - } - } - // When the while loop finishes the minimum of x and y is the HCF. - return Math.min(x, y); -} -function ran(minNum, maxNum) { - return Math.floor((maxNum - minNum + 1) * Math.random()) + minNum; -} - -function clickToHide(canvas, canvasctx, canvasData, font, textColor) { - if (!font) { - font = '12px Arial' - }; - if (!textColor) { - textColor = '#333' - }; - canvasctx.font = font; - canvasctx.fillStyle = textColor; - canvasctx.textBaseline = 'bottom'; - canvasctx.textAlign = 'center'; - canvasctx.fillText('Click to close', canvasData[2] / 2, canvasData[3] - 3); - canvas.style.pointerEvents = 'auto'; - canvas.onclick = function () { - hideObj(canvas, canvasData); - } -} - -// rotates coordinates about the origin (or a given center) and rounds to nearest integer -function rotateCoords(x, y, degrees, opt_direction, opt_centerX, opt_centerY, opt_round) { - var round = true; - if (typeof opt_round == 'boolean') { - round = opt_round - } - var direction = opt_direction || 'anti-cw'; // use 'cw' or 'anti-cw' - var centerX = opt_centerX || 0; //optional centre of rotation - var centerY = opt_centerY || 0; - // convert to anti-cw and radians - if (direction == 'cw') - degrees = 360 - degrees; - var angleRads = degrees / 180 * Math.PI; - // transpose to origin - x -= centerX; - y -= centerY; - // apply matrix - if (round == true) { - var newX = Math.round(Math.cos(angleRads) * x - Math.sin(angleRads) * y); - var newY = Math.round(Math.sin(angleRads) * x + Math.cos(angleRads) * y); - } else { - var newX = Math.cos(angleRads) * x - Math.sin(angleRads) * y; - var newY = Math.sin(angleRads) * x + Math.cos(angleRads) * y; - } - // un-transpose - newX += centerX; - newY += centerY; - return { - x: newX, - y: newY - }; -} - -var variArray = ['a', 'b', 'c', 'd', 'g', 'h', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'y', 'y']; -function equivExpressions(string1, string2) { // checks if two algebraic expressions (as strings in x only) are equivalent - if (string1 == '' || string2 == '') { - return false; - } - var equivalent = true; - // select 100 * 2 random numbers of different magnitudes - for (mag = 0; mag < 10; mag++) { - for (num = 0; num < 10; num++) { - var x = Math.random() * Math.pow(10, mag); - var val1 = eval(string1); - var val2 = eval(string2); - // get percentage error between values - var pError = 0; - if (val1 !== 0) { - pError = Math.abs((val1 - val2) / val1); - } else if (val2 !== 0) { - pError = Math.abs((val1 - val2) / val2); - } - if (pError > 0.00001) { - equivalent = false; - } - x = -1 * x; - val1 = eval(string1); - val2 = eval(string2); - pError = 0; - if (val1 !== 0) { - pError = Math.abs((val1 - val2) / val1); - } else if (val2 !== 0) { - pError = Math.abs((val1 - val2) / val2); - } - if (pError > 0.00001) { - equivalent = false; - } - } - } - return equivalent -} - -function buildQuadraticExp(d, e, f, g, h, vari) { - if (un(h)) - h = 1; - var a = h * d * f; - var b = h * (d * g + e * f); - var c = h * e * g; - return buildQuadratic(a, b, c, d, e, f, g, h, vari); -} -function buildQuadratic(a, b, c, d, e, f, g, h, vari) { - // ax^2 + bx + c = h(dx + e)(fx + g) - if (!vari) { - var variNum = ran(0, 50); - vari = 'x'; - if (variNum < 19) - vari = variArray[variNum]; - } - var p, - q, - r, - exp, - fac, - compSq, - disc, - qText, - rText, - root1Text, - root2Text, - vertexText, - expJS, - factors = [], - factorisedForms = [], - expandedTerms = [], - expandedForms = []; - - // create the expanded form text - var aSign = ''; - var aFirstSign = ''; - var aTerm = String(Math.abs(a)) + vari; - var aTermJS = String(Math.abs(a)) + '*Math.pow(' + vari + ',2)'; - if (a > 0) - aSign = ' + '; - if (a < 0) - aSign = ' - '; - if (a < 0) - aFirstSign = '-'; - if (a == 1 || a == -1) - aTerm = vari; - if (a == 1) - aTermJS = 'Math.pow(' + vari + ',2)'; - if (a == -1) - aTermJS = '-Math.pow(' + vari + ',2)'; - if (a == 0) - aTerm = ''; - - var bSign = ''; - var bFirstSign = ''; - var bTerm = String((Math.abs(b))) + vari; - var bTermJS = String((Math.abs(b))) + '*' + vari; - if (b > 0) - bSign = ' + '; - if (b < 0) - bSign = ' - '; - if (b < 0) - bFirstSign = '-'; - if (b == 1 || b == -1) - bTerm = vari; - if (b == 1 || b == -1) - bTermJS = vari; - if (b == -1) - bTermJS = vari; - if (b == 0) - bTerm = ''; - if (b == 0) - bTermJS = ''; - - var cSign = ''; - var cFirstSign = ''; - var cTerm = String(Math.abs(c)); - var cTermJS = String(Math.abs(c)); - if (c > 0) - cSign = ' + '; - if (c < 0) - cSign = ' - '; - if (c < 0) - cFirstSign = '-'; - if (c == 0) - cTermJS = ''; - if (c == 0) - cTerm = ''; - - var expTermsMathsText = [[aFirstSign, aTerm], [bFirstSign, bTerm], [cFirstSign, cTerm]]; - var expFormsMathsText = [ - [aFirstSign + aTerm, ['power', false, '2'], bSign, bTerm, cSign, cTerm], - [aFirstSign + aTerm, ['power', false, '2'], cSign, cTerm, bSign, bTerm], - [bFirstSign + bTerm + aSign + aTerm, ['power', false, '2'], cSign + cTerm], - [bFirstSign + bTerm + cSign + cTerm + aSign + aTerm, ['power', false, '2']], - [cFirstSign + cTerm + aSign + aTerm, ['power', false, '2'], bSign + bTerm], - [cFirstSign + cTerm + bSign + bTerm + aSign + aTerm, ['power', false, '2']] - ]; - var expTermsJS = [aTermJS, bTermJS, cTermJS]; - var expFormsJS = [ - aFirstSign + aTermJS + bSign + bTermJS + cSign + cTermJS, - aFirstSign + aTermJS + cSign + cTermJS + bSign + bTermJS, - bFirstSign + bTermJS + aSign + aTermJS + cSign + cTermJS, - bFirstSign + bTermJS + cSign + cTermJS + aSign + aTermJS, - cFirstSign + cTermJS + aSign + aTermJS + bSign + bTermJS, - cFirstSign + cTermJS + bSign + bTermJS + aSign + aTermJS, - ] - - if (a > 0 || (a < 0 && b < 0 && c < 0)) { - exp = expFormsMathsText[0]; - expJS = expFormsJS[0]; - } else if (c > 0) { - exp = expFormsMathsText[5]; - expJS = expFormsJS[5]; - } else { - exp = expFormsMathsText[3]; - expJS = expFormsJS[3]; - } - - // create the factorised forms - var factors = constructFactors(h, d, e, f, g, vari); - var factorisedForms = constructFactorisedForms(factors); - - var hFactors = []; - for (var hF = h; hF > 1; hF--) { - if (h % hF == 0) - hFactors.push(hF); - } - - var compositeFactors = []; - var partiallyFactorisedForms = []; - - //construct sets of factors; - - if (typeof d !== 'undefined' && typeof e !== 'undefined' && typeof f !== 'undefined' && typeof g !== 'undefined') { - if (d < 0) { - bracket1 = '(' + e + " - "; - var dText = Math.abs(d); - if (d == -1) - dText = ''; - bracket1 += dText + vari + ')' - } else { - var eSign = " + "; - if (e < 0) { - eSign = " - " - }; - var dText = d; - if (d == 1) - dText = ""; - if (d == -1) - dText = "-"; - bracket1 = "(" + dText + vari + eSign + Math.abs(e) + ")"; - } - - if (f < 0) { - bracket2 = '(' + g + " - "; - var fText = Math.abs(f); - if (f == -1) - fText = ''; - bracket2 += fText + vari + ')' - } else { - var gSign = " + "; - if (g < 0) { - gSign = " - " - }; - var fText = f; - if (f == 1) - fText = ""; - if (f == -1) - fText = "-"; - bracket2 = "(" + fText + vari + gSign + Math.abs(g) + ")"; - } - - fac = bracket1 + bracket2; - if (Math.random() < 0.5) - fac = bracket2 + bracket1; - if (bracket1 == bracket2) { - fac = bracket1 + String.fromCharCode(0x00B2) - }; - - if (e == 0) { - var dText = d; - if (d == 1) - dText = ''; - if (d == -1) - dText = '-'; - bracket1 = dText + vari; - - } - - if (g == 0) { - var fText = f; - if (f == 1) - fText = ''; - if (f == -1) - fText = '-'; - bracket2 = fText + vari; - fac = bracket2 + bracket1; - } - - if (typeof h !== 'undefined') { - var hTerm = h; - if (h == 1) - hTerm = ''; - if (h == -1) - hTerm = '-'; - fac = hTerm + fac; - - } - } - - // create the completed square form text - p = a; - q = b / (2 * a); - r = c - (b * b) / (4 * a); - compSq = ''; - if (p > 0 || p < 0 && r <= 0) { - var pTerm = String(p); - if (p == 1) - pTerm = ''; - if (p == -1) - pTerm = '-'; - var qSign = " + "; - if (q < 0) - qSign = " - "; - var qTerm = toMathsText(b, 2 * a); - var rSign = " + "; - if (r < 0) - rSign = " - "; - var rTerm = toMathsText(4 * a * c - b * b, 4 * a); - if (r == 0) { - rSign = ''; - rTerm = ''; - } - compSq = [pTerm + '(' + vari + qSign, qTerm, ')', ['pow', '', '2'], rSign, rTerm]; - } else if (p < 0 && r > 0) { // r - p(x +- q)^2 - var rTerm = toMathsText(4 * a * c - b * b, 4 * a); - var qSign = " + "; - if (q < 0) - qSign = " - "; - var qTerm = toMathsText(b, 2 * a); - var pTerm = toMathsText(p); - if (p == -1) - pTerm = ''; - compSq = [rTerm, ' - ' + pTerm + '(' + vari + qSign, qTerm, ')', ['pow', '', '2']]; - } - - // makes qText, rText and vertexText - if (q < 0) { - qText = ["-", qTerm]; - if (r < 0) { - rText = ["-", rTerm]; - vertexText = ['(', qTerm, ', -', rTerm, ')']; - } else { - rText = rTerm; - vertexText = ['(', qTerm, ', ', rTerm, ')']; - } - } else { - qText = qTerm; - if (r < 0) { - rText = ["-", rTerm]; - vertexText = ['(-', qTerm, ', -', rTerm, ')']; - } else { - rText = rTerm; - vertexText = ['(-', qTerm, ', ', rTerm, ')']; - } - } - - disc = b * b - 4 * a * c; - - // solves ax^2 + bx + c = 0 - var root1 = (-1 * b + Math.pow(b * b - 4 * a * c, 0.5)) / (2 * a); - var root2 = (-1 * b - Math.pow(b * b - 4 * a * c, 0.5)) / (2 * a); - - // makes root1text and root2text - // if non-surd solutions - if (Math.pow(b * b - 4 * a * c, 0.5) == Math.round(Math.pow(b * b - 4 * a * c, 0.5))) { - var root1sign = ''; - if ((-1 * b + Math.pow(b * b - 4 * a * c, 0.5)) / (2 * a) < 0) - root1sign = '-'; - root1text = [root1sign, toMathsText((-1 * b + Math.pow(b * b - 4 * a * c, 0.5)), (2 * a))]; - var root2sign = ''; - if ((-1 * b - Math.pow(b * b - 4 * a * c, 0.5)) / (2 * a) < 0) - root2sign = '-'; - root2text = [root2sign, toMathsText((-1 * b - Math.pow(b * b - 4 * a * c, 0.5)), (2 * a))]; - } else { - var surd = simpSurd(b * b - 4 * a * c, 0.5); - root1text = [toMathsText((-1 * b), (2 * a)), ' + ', toMathsText(1, (2 * a)), surd.mathsText]; - root2text = [toMathsText((-1 * b), (2 * a)), ' - ', toMathsText(1, (2 * a)), surd.mathsText]; - } - - return { - exp: exp, - fac: fac, - compSq: compSq, - disc: disc, - a: a, - b: b, - c: c, - d: d, - e: e, - f: f, - g: g, - h: h, - p: p, - q: q, - r: r, - vari: vari, - root1: root1, - root2: root2, - qText: qText, - rText: rText, - vertexText: vertexText, - root1text: root1text, - root2text: root2text, - factors: factors, - factorisedForms: factorisedForms, - expTermsMathsText: expTermsMathsText, - expFormsMathsText: expFormsMathsText, - expTermsJS: expTermsJS, - expFormsJS: expFormsJS, - expJS: expJS - } -} -function quadratic(level, vari) { - if (!vari) { - var variNum = ran(0, 50); - vari = 'x'; - if (variNum < 19) - vari = variArray[variNum]; - } - // quadratic is (dx + e)(fx + g) = ax^2 + bx + c - var a, - b, - c, - d, - e, - f, - g, - h, - p, - q, - r, - exp, - fac, - compSq, - disc, - qText, - rText, - root1Text, - root2Text, - vertexText, - expJS; - var factors = []; - var factorisedForms = []; - var expandedTerms = []; - var expandedForms = []; - switch (level) { - case 1: - // (x +- e)(x +- g) || dx(fx +- g) - do { - d = 1; - e = ran(-10, 10); - f = 1; - g = ran(-10, 10); - } while (g == 0) - - if (e == 0) { - d = ran(1, 3); - do { - f = ran(1, 3); - } while (hcf(f, g) !== 1) - } - - a = d * f; - b = d * g + e * f; - c = e * g; - h = 1; - - break; - case 2: - // h(x +- e)(x +- g), where h > 1 - do { - d = 1; - e = ran(-10, 10); - f = 1; - g = ran(-10, 10); - } while (e == 0 || g == 0) - - a = d * f; - b = d * g + e * f; - c = e * g; - h = [2, 2, 3, 4, 5, 10][ran(0, 5)]; - break; - case 3: - // h(dx +- e)(fx +- g) where d = 1 or f = 1 but not both - do { - d = ran(1, 6); - e = ran(-10, 10); - f = ran(1, 6); - g = ran(-10, 10); - h = Math.max(1, ran(-15, 5)); - } while (e == 0 || g == 0 || (d == 1 && f == 1) || (d !== 1 && f !== 1) || hcf(d, e) > 1 || hcf(f, g) > 1) - - a = h * d * f; - b = h * (d * g + e * f); - c = h * e * g; - - break; - case 4: - // h(dx +- e)(fx +- g) where d >= 1 and f >= 1 - do { - d = ran(1, 6); - e = ran(-10, 10); - f = ran(1, 6); - g = ran(-10, 10); - h = Math.max(1, ran(-15, 5)); - } while (e == 0 || g == 0 || (d == 1 && f == 1) || hcf(d, e) > 1 || hcf(f, g) > 1) - - a = h * d * f; - b = h * (d * g + e * f); - c = h * e * g; - - break; - case 5: - // h(e - dx)(fx +- g) - do { - d = ran(-6, -1); - e = ran(1, 10); - f = ran(1, 6); - g = ran(-10, 10); - h = Math.max(1, ran(-15, 5)); - } while (g == 0 || hcf(d, e) > 1 || hcf(f, g) > 1) - - a = h * d * f; - b = h * (d * g + e * f); - c = h * e * g; - - break; - case 6: - // +-h(+-dx +- e)(+-fx +- g) where d >= 1 and f >= 1 - do { - d = ran(-3, 3); - e = ran(-10, 10); - f = ran(-3, 3); - g = ran(-10, 10); - h = ran(-3, 3); - } while (e == 0 || g == 0 || d == 0 || f == 0 || h == 0 || (d == 1 && f == 1) || hcf(d, e) > 1 || hcf(f, g) > 1) - - if (d < 0 && e < 0) { - d = -d; - e = -e; - h = -h; - } - if (f < 0 && g < 0) { - f = -f; - g = -g; - h = -h; - } - - a = h * d * f; - b = h * (d * g + e * f); - c = h * e * g; - - break; - case 7: - // generates a quadratic ax^2 +- bx +- c that doesn't factorise - do { - a = ran(1, 5); - b = ran(-100, 100); - c = ran(-100, 100); - var disc = Math.pow(b * b - 4 * a * c, 0.5); - } while (disc == Math.round(disc)); - h = 1; - - break; - case 8: - // generates a quadratic +-ax^2 +- bx +- c that doesn't factorise - do { - a = ran(-10, 10); - b = ran(-100, 100); - c = ran(-100, 100); - var disc = Math.pow(b * b - 4 * a * c, 0.5); - } while (a == 0 || disc == Math.round(disc) || (b == 0 && c == 0)); - h = 1; - - break; - - } - - return buildQuadratic(a, b, c, d, e, f, g, h, vari); -} -function sketchQuad(context, quad, gridLeft, gridTop, gridWidth, gridHeight, xMin, xMax, yMin, yMax, yIntLabel, xIntLabel, vertexLabel, opt_fontSize) { - // draws a sketch of the graph of a quadratic - if (typeof yIntLabel !== 'boolean') - yIntLabel = false; - if (typeof xIntLabel !== 'boolean') - xIntLabel = false; - if (typeof vertexLabel !== 'boolean') - vertexLabel = false; - if (quad.q == 0 && vertexLabel == true) - yIntLabel = true; - var fontSize = opt_fontSize || (Math.min(gridWidth, gridHeight) / 13); - - if (quad.a > 0) { - // need to solve ax^2 + bx + c = yMax - var maxVal = solveQuad(quad.a, quad.b, quad.c - yMax); - } else { - // need to solve ax^2 + bx + c = yMin - var maxVal = solveQuad(quad.a, quad.b, quad.c - yMin); - } - var xStart = Math.max(xMin, maxVal.x2); - var yStart = quad.a * xStart * xStart + quad.b * xStart + quad.c; - var xFin = Math.min(xMax, maxVal.x1); - var yFin = quad.a * xFin * xFin + quad.b * xFin + quad.c; - - var controlPoint = getBezierCurveForQuad(quad.a, quad.b, quad.c, xStart, yStart, xFin, yFin); - - var minPoint = { - x: -1 * quad.q, - y: quad.r - } - - var gridSta = convertGridCoordsToCanvas(xStart, yStart, gridLeft, gridTop, gridWidth, gridHeight, xMin, xMax, yMin, yMax); - var gridFin = convertGridCoordsToCanvas(xFin, yFin, gridLeft, gridTop, gridWidth, gridHeight, xMin, xMax, yMin, yMax); - var gridCon = convertGridCoordsToCanvas(controlPoint.x, controlPoint.y, gridLeft, gridTop, gridWidth, gridHeight, xMin, xMax, yMin, yMax); - var gridMin = convertGridCoordsToCanvas(minPoint.x, minPoint.y, gridLeft, gridTop, gridWidth, gridHeight, xMin, xMax, yMin, yMax); - var gridRoot1 = convertGridCoordsToCanvas(quad.root1, 0, gridLeft, gridTop, gridWidth, gridHeight, xMin, xMax, yMin, yMax); - var gridRoot2 = convertGridCoordsToCanvas(quad.root2, 0, gridLeft, gridTop, gridWidth, gridHeight, xMin, xMax, yMin, yMax); - var gridYInt = convertGridCoordsToCanvas(0, quad.c, gridLeft, gridTop, gridWidth, gridHeight, xMin, xMax, yMin, yMax); - - context.lineWidth = 1; - context.strokeStyle = '#666'; - context.beginPath(); - context.moveTo(gridLeft, gridTop + 0.5 * gridHeight); - context.lineTo(gridLeft + gridWidth, gridTop + 0.5 * gridHeight); - context.moveTo(gridLeft + gridWidth * 0.5, gridTop); - context.lineTo(gridLeft + gridWidth * 0.5, gridTop + gridHeight); - context.stroke(); - context.strokeStyle = '#000'; - context.beginPath() - context.moveTo(gridSta.x, gridSta.y); - context.quadraticCurveTo(gridCon.x, gridCon.y, gridFin.x, gridFin.y); - if (vertexLabel == true) { - context.moveTo(gridMin.x - 5, gridMin.y - 5); - context.lineTo(gridMin.x + 5, gridMin.y + 5); - context.moveTo(gridMin.x - 5, gridMin.y + 5); - context.lineTo(gridMin.x + 5, gridMin.y - 5); - } - context.stroke(); - - context.font = "14px Arial"; - context.textBaseline = "middle"; - context.fillStyle = "#000"; - context.textAlign = 'center'; - if (quad.disc == 0) { - if (xIntLabel == true || vertexLabel == true) - drawMathsText(context, quad.root1text, fontSize, gridRoot1.x, gridRoot1.y + 15, true, '', 'center', 'middle', '#000', 'draw', '#000'); - if (yIntLabel == true) - drawMathsText(context, [String(quad.c)], fontSize, gridYInt.x + 5, gridYInt.y, true, '', 'left', 'middle', '#000', 'draw', '#000'); - - } else if (quad.a > 0) { - if (xIntLabel == true) - drawMathsText(context, quad.root1text, fontSize, gridRoot1.x + 4, gridRoot1.y + 12, true, '', 'left', 'middle', '#000', 'draw'); - if (xIntLabel == true) - drawMathsText(context, quad.root2text, fontSize, gridRoot2.x - 4, gridRoot1.y + 12, true, '', 'right', 'middle', '#000', 'draw'); - if (quad.b !== 0) { - var vertexY = gridMin.y + 20; - if (xIntLabel == true && vertexY - (gridTop + 0.5 * gridHeight) < 40) - vertexY = gridTop + 0.5 * gridHeight + 40; - if (vertexLabel == true) - drawMathsText(context, quad.vertexText, fontSize, gridMin.x, vertexY, true, '', 'center', 'middle', '#000', 'draw'); - } - if (quad.c !== 0) { - if (quad.q <= 0) { - if (quad.b !== 0) { - if (yIntLabel == true) - drawMathsText(context, [String(quad.c)], fontSize, gridYInt.x - 5, gridYInt.y, true, '', 'right', 'middle', '#000', 'draw'); - } else { - if (yIntLabel == true) - drawMathsText(context, [String(quad.c)], fontSize, gridYInt.x - 5, gridYInt.y + 15, true, '', 'right', 'middle', '#000', 'draw'); - } - } else { - if (quad.b !== 0) { - if (yIntLabel == true) - drawMathsText(context, [String(quad.c)], fontSize, gridYInt.x + 5, gridYInt.y, true, '', 'left', 'middle', '#000', 'draw'); - } else { - if (yIntLabel == true) - drawMathsText(context, [String(quad.c)], fontSize, gridYInt.x + 5, gridYInt.y + 15, true, '', 'left', 'middle', '#000', 'draw'); - } - } - } - } else { - // quads with a < 0 - - } -} -function constructFactors(z0, z1, z2, z3, z4, vari) { - // z0 is h - var hSign = '+'; - var hOppSign = '-'; - var hFirstSign = ''; - var hOppFirstSign = '-'; - if (z0 < 0) { - hSign = '-'; - hOppSign = '+'; - hFirstSign = '-'; - hOppFirstSign = ''; - } - var hTerm = String(Math.abs(z0)); - if (z0 == 1 || z0 == -1) - hTerm = ''; - - // z1 is d (ie.dx) - var dSign = '+'; - var dOppSign = '-'; - var dFirstSign = ''; - var dOppFirstSign = '-'; - if (z1 < 0) { - dSign = '-'; - dOppSign = '+'; - dFirstSign = '-'; - dOppFirstSign = ''; - } - var dTerm = String(Math.abs(z1)) + vari; - if (z1 == 1 || z1 == -1) - dTerm = vari; - - // z2 is e - var eSign = '+'; - var eOppSign = '-'; - var eFirstSign = ''; - var eOppFirstSign = '-'; - if (z2 < 0) { - eSign = '-'; - eOppSign = '+'; - eFirstSign = '-'; - eOppFirstSign = ''; - } - var eTerm = String(Math.abs(z2)); - if (z2 == 0) { - eSign = ''; - eOppSign = ''; - eFirstSign = ''; - eOppFirstSign = ''; - eTerm = ''; - } - - // z3 is f (ie.fx) - var fSign = '+'; - var fOppSign = '-'; - var fFirstSign = ''; - var fOppFirstSign = '-'; - if (z3 < 0) { - fSign = '-'; - fOppSign = '+'; - fFirstSign = '-'; - fOppFirstSign = ''; - } - var fTerm = String(Math.abs(z3)) + vari; - if (z3 == 1 || z3 == -1) - fTerm = vari; - - // z4 is g - var gSign = '+'; - var gOppSign = '-'; - var gFirstSign = ''; - var gOppFirstSign = '-'; - if (z4 < 0) { - gSign = '-'; - gOppSign = '+'; - gFirstSign = '-'; - gOppFirstSign = ''; - } - var gTerm = String(Math.abs(z4)); - if (z4 == 0) { - gSign = ''; - gOppSign = ''; - gFirstSign = ''; - gOppFirstSign = ''; - gTerm = ''; - } - - return [ - - [hFirstSign + hTerm, dFirstSign + dTerm + eSign + eTerm, fFirstSign + fTerm + gSign + gTerm], - [hFirstSign + hTerm, eFirstSign + eTerm + dSign + dTerm, fFirstSign + fTerm + gSign + gTerm], - [hFirstSign + hTerm, dFirstSign + dTerm + eSign + eTerm, gFirstSign + gTerm + fSign + fTerm], - [hFirstSign + hTerm, eFirstSign + eTerm + dSign + dTerm, gFirstSign + gTerm + fSign + fTerm], - - [hOppFirstSign + hTerm, dOppFirstSign + dTerm + eOppSign + eTerm, fFirstSign + fTerm + gSign + gTerm], - [hOppFirstSign + hTerm, eOppFirstSign + eTerm + dOppSign + dTerm, fFirstSign + fTerm + gSign + gTerm], - [hOppFirstSign + hTerm, dOppFirstSign + dTerm + eOppSign + eTerm, gFirstSign + gTerm + fSign + fTerm], - [hOppFirstSign + hTerm, eOppFirstSign + eTerm + dOppSign + dTerm, gFirstSign + gTerm + fSign + fTerm], - - [hOppFirstSign + hTerm, dFirstSign + dTerm + eSign + eTerm, fOppFirstSign + fTerm + gOppSign + gTerm], - [hOppFirstSign + hTerm, eFirstSign + eTerm + dSign + dTerm, fOppFirstSign + fTerm + gOppSign + gTerm], - [hOppFirstSign + hTerm, dFirstSign + dTerm + eSign + eTerm, gOppFirstSign + gTerm + fOppSign + fTerm], - [hOppFirstSign + hTerm, eFirstSign + eTerm + dSign + dTerm, gOppFirstSign + gTerm + fOppSign + fTerm], - - [hFirstSign + hTerm, dOppFirstSign + dTerm + eOppSign + eTerm, fOppFirstSign + fTerm + gOppSign + gTerm], - [hFirstSign + hTerm, eOppFirstSign + eTerm + dOppSign + dTerm, fOppFirstSign + fTerm + gOppSign + gTerm], - [hFirstSign + hTerm, dOppFirstSign + dTerm + eOppSign + eTerm, gOppFirstSign + gTerm + fOppSign + fTerm], - [hFirstSign + hTerm, eOppFirstSign + eTerm + dOppSign + dTerm, gOppFirstSign + gTerm + fOppSign + fTerm], - - ] - -} -function constructFactorisedForms(factorsArray) { - var returnArray = []; - for (var set = 0; set < factorsArray.length; set++) { - var fac = [factorsArray[set][0], factorsArray[set][1], factorsArray[set][2]]; - var facBrac = ['(' + fac[0] + ')', '(' + fac[1] + ')', '(' + fac[2] + ')']; - var bracReqFirst = [false, true, true]; - var bracReq = [true, true, true]; - - for (br = 0; br < fac.length; br++) { - if (fac[br] == '-') - facBrac[br] = '(-1)'; - // if the factor doesn't contain + or -, no bracket required - if (fac[br].indexOf('-') == -1 && fac[br].indexOf('+') == -1) - bracReq[br] = false; - } - - var first; - var second; - var third; - - for (br1 = 0; br1 < 3; br1++) { - first = facBrac[br1]; - if (bracReqFirst[br1] == false) - first = fac[br1]; - for (br2 = 0; br2 < 3; br2++) { - if (br2 !== br1) { - second = facBrac[br2]; - if (bracReq[br2] == false) - second = fac[br2]; - for (br3 = 0; br3 < 3; br3++) { - if (br3 !== br1 && br3 !== br2) { - third = facBrac[br3]; - if (bracReq[br3] == false) - third = fac[br3]; - - if (returnArray.indexOf(first + second + third) == -1) { - returnArray.push(first + second + third); - } - if (first == second && second == third && first !== '') { - if (returnArray.indexOf('Math.pow(' + first + ',3)') == -1) - returnArray.push('Math.pow(' + first + ',3)'); - } - if (first == second && first !== '') { - if (returnArray.indexOf('Math.pow(' + first + ',2)' + second) == -1) - returnArray.push('Math.pow(' + first + ',2)' + second); - } - if (second == third && second !== '') { - if (returnArray.indexOf(first + 'Math.pow(' + second + ',2)') == -1) - returnArray.push(first + 'Math.pow(' + second + ',2)'); - } - } - } - } - } - } - } - return returnArray; -} -function toMathsText(num, num2) { - if (typeof num2 == 'undefined') { - num = Math.abs(num); - if (num == Math.round(num)) { - return String(num); - } else { - // if num is negative? - var frac = decToFrac(num); - return ['frac', String(frac.num), String(frac.denom)]; - } - } else { - if (num == 0) - return '0'; - var pos = true; - if (num / num2 < 0) - pos = false; - num = Math.abs(num) - num2 = Math.abs(num2); - var divisor = hcf(num, num2); - num = num / divisor; - num2 = num2 / divisor; - if (num2 == 1) { - if (pos == true) { - return String(num); - } else { - return "-" + String(num); - } - } else { - if (pos == true) { - return ['frac', [String(num)], [String(num2)]]; - } else { - return ['-', ['frac', [String(num)], [String(num2)]]]; - } - } - } -} -function addFracs(num1, denom1, num2, denom2) { - var denom = denom1 * denom2 / hcf(denom1, denom2); - var num = num1 * (denom / denom1) + num2 * (denom / denom2); - //console.log(num,denom); - return toMathsText(num, denom); -} -function simplifyFrac(object, textArrayOrObject) { - var textArray = boolean(textArrayOrObject, true); - - var positive = true; - if (object.num / object.denom < 0) - positive = false; - if (object.num == 0) { - if (textArray == true) { - return ["0"]; - } else { - return { - num: 0, - denom: 1 - }; - } - } - while (Math.round(object.num) !== object.num || Math.round(object.denom) !== object.denom) { - object.num = object.num * 10; - object.denom = object.denom * 10; - } - - var num = Math.abs(object.num); - var denom = Math.abs(object.denom); - var multOfPi = false; - if (typeof object.multOfPi == 'boolean') - multOfPi = object.multOfPi; - var newNum = num / hcf(num, denom); - var newDenom = denom / hcf(num, denom); - - if (textArray == true) { // if returning a textArray - if (multOfPi == false) { - if (newDenom == 1) { - if (positive == true) { - return String(newNum); - } else { - return "-" + String(newNum); - } - } else { - if (positive == true) { - return ['frac', [String(newNum)], [String(newDenom)]] - } else { - return ['-', ['frac', [String(newNum)], [String(newDenom)]]] - } - } - } else { - if (newDenom == 1) { - if (positive == true) { - if (newNum == 1) { - return String.fromCharCode(0x03C0); - } else { - return String(newNum) + String.fromCharCode(0x03C0); - } - } else { - if (newNum == 1) { - return "-" + String.fromCharCode(0x03C0); - } else { - return "-" + String(newNum) + String.fromCharCode(0x03C0); - } - } - } else { - if (positive == true) { - if (newNum == 1) { - return ['frac', [String.fromCharCode(0x03C0)], [String(newDenom)]]; - } else { - return ['frac', [String(newNum) + String.fromCharCode(0x03C0)], [String(newDenom)]]; - } - } else { - if (newNum == 1) { - return ["-", ['frac', [String.fromCharCode(0x03C0)], [String(newDenom)]]]; - } else { - return ["-", ['frac', [String(newNum) + String.fromCharCode(0x03C0)], [String(newDenom)]]]; - } - } - } - } - } else { // if returning an object - if (positive == true) { - return { - num: newNum, - denom: newDenom - }; - } else { - return { - num: -1 * newNum, - denom: newDenom - }; - } - } -} -function simplifyFrac2(frac) { - var positive = true; - if (frac[0] / frac[1] < 0) - positive = false; - if (frac[0] == 0) - return [0, 1]; - while (Math.round(frac[0]) !== frac[0] || Math.round(frac[1]) !== frac[1]) { - frac[0] = frac[0] * 10; - frac[1] = frac[1] * 10; - } - - var num = Math.abs(frac[0]); - var denom = Math.abs(frac[1]); - var newNum = num / hcf(num, denom); - var newDenom = denom / hcf(num, denom); - if (positive == true) { - return [newNum, newDenom]; - } else { - return [-1 * newNum, newDenom]; - } -} -function addFracs2(frac1, frac2) { - var denom = frac1[1] * frac2[1] / hcf(frac1[1], frac2[1]); - var num = frac1[0] * (denom / frac1[1]) + frac2[0] * (denom / frac2[1]); - return [num, denom]; -} -function simpSurd(c) { - //takes sqrt(c) and returns simplified: a*sqrt(b) - var a, - b, - mathsTextSurd; - - for (fac = 1; fac <= c; fac++) { - if (Math.sqrt(c / fac) == Math.round(Math.sqrt(c / fac))) { - a = Math.sqrt(c / fac); - b = fac; - break; - } - } - - var aTerm = String(a); - mathsTextSurd = [String(a), ['sqrt', [String(b)]]]; - if (a == 1 && b > 1) - mathsTextSurd = [['sqrt', [String(b)]]] - if (b == 1) - mathsTextSurd = [String(a)]; - - return { - a: a, - b: b, - mathsText: mathsTextSurd - }; -} -function primeFactors(num) { - var primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131]; - if (num == 1) - return ['1']; - if (num > 131) - return ['']; // too big! - if (primes.indexOf(num) > -1) - return [String(num)]; - var primeFactors = []; - do { - for (var i = 0; i < primes.length; i++) { - if (num % primes[i] == 0) { - primeFactors.push(primes[i]); - num = num / primes[i]; - break; - } - } - } while (num > 1); - var returnArray = []; - for (var i = 0; i < primeFactors.length; i++) { - var repeated = 1; - for (var j = i + 1; j < primeFactors.length; j++) { - if (primeFactors[i] == primeFactors[j]) - repeated++; - } - if (i > 0) - returnArray.push(String.fromCharCode(0x00D7)) - returnArray.push(String(primeFactors[i])); - if (repeated > 1) { - returnArray.push(['power', false, [String(repeated)]]); - i += repeated - 1; - } - } - return returnArray; -} -function cuberoot(x) { - var y = Math.pow(Math.abs(x), 1 / 3); - return x < 0 ? -y : y; -} -function solveCubic(a, b, c, d) { - if (Math.abs(a) < 1e-8) { // Quadratic case, ax^2+bx+c=0 - a = b; - b = c; - c = d; - if (Math.abs(a) < 1e-8) { // Linear case, ax+b=0 - a = b; - b = c; - if (Math.abs(a) < 1e-8) // Degenerate case - return []; - return [-b / a]; - } - - var D = b * b - 4 * a * c; - if (Math.abs(D) < 1e-8) - return [-b / (2 * a)]; - else if (D > 0) - return [(-b + Math.sqrt(D)) / (2 * a), (-b - Math.sqrt(D)) / (2 * a)]; - return []; - } - - // Convert to depressed cubic t^3+pt+q = 0 (subst x = t - b/3a) - var p = (3 * a * c - b * b) / (3 * a * a); - var q = (2 * b * b * b - 9 * a * b * c + 27 * a * a * d) / (27 * a * a * a); - var roots; - - if (Math.abs(p) < 1e-8) { // p = 0 -> t^3 = -q -> t = -q^1/3 - roots = [cuberoot(-q)]; - } else if (Math.abs(q) < 1e-8) { // q = 0 -> t^3 + pt = 0 -> t(t^2+p)=0 - roots = [0].concat(p < 0 ? [Math.sqrt(-p), -Math.sqrt(-p)] : []); - } else { - var D = q * q / 4 + p * p * p / 27; - if (Math.abs(D) < 1e-8) { // D = 0 -> two roots - roots = [-1.5 * q / p, 3 * q / p]; - } else if (D > 0) { // Only one real root - var u = cuberoot(-q / 2 - Math.sqrt(D)); - roots = [u - p / (3 * u)]; - } else { // D < 0, three roots, but needs to use complex numbers/trigonometric solution - var u = 2 * Math.sqrt(-p / 3); - var t = Math.acos(3 * q / p / u) / 3; // D < 0 implies p < 0 and acos argument in [-1..1] - var k = 2 * Math.PI / 3; - roots = [u * Math.cos(t), u * Math.cos(t - k), u * Math.cos(t - 2 * k)]; - } - } - - // Convert back from depressed cubic - for (var i = 0; i < roots.length; i++) - roots[i] -= b / (3 * a); - - return roots; -} - -function hitAndAlign(object, firstArray, secondArray, offsetX, offsetY) { - //this function aligns a dragged object to the x and y position of another object - //first array is draggable buttons - //second array is the things they are going to hit - //this works for buttons - if (typeof offsetX == 'undefined') { - offsetX = 0 - } else { - offsetX = Number(offsetX) - } - if (typeof offsetY == 'undefined') { - offsetY = 0 - } else { - offsetY = Number(offsetY) - } - var alreadyHitMe = false - for (var j = 0; j < firstArray.length; j++) { - - if (hitTestTwoObjects(object, firstArray[j]) == true && object !== firstArray[j]) { - alreadyHitMe = true - } - - } - - for (var j = 0; j < secondArray.length; j++) { - - if (hitTestTwoObjects(object, secondArray[j]) == true && alreadyHitMe == false) { - - var buttonArray = eval(String(taskTag) + 'button') - var buttonArrayData = eval(String(taskTag) + 'buttonData') - - var butNum = buttonArray.indexOf(object) - var butNum2 = buttonArray.indexOf(secondArray[j]) - - buttonArrayData[butNum][100] = buttonArrayData[butNum2][100] + Number(offsetX) - buttonArrayData[butNum][101] = buttonArrayData[butNum2][101] + Number(offsetY) - resize() - } - - } - -} -function hitAndAlignImages(object, firstArray, secondArray, offsetX, offsetY) { - - if (typeof offsetX == 'undefined') { - offsetX = 0 - } else { - offsetX = Number(offsetX) - } - if (typeof offsetY == 'undefined') { - offsetY = 0 - } else { - offsetY = Number(offsetY) - } - - var alreadyHitMe = false - for (var j = 0; j < firstArray.length; j++) { - - if (hitTestTwoObjects(object, firstArray[j]) == true && object !== firstArray[j]) { - alreadyHitMe = true - } - - } - - for (var j = 0; j < secondArray.length; j++) { - - if (hitTestTwoObjects(object, secondArray[j]) == true && alreadyHitMe == false) { - - var buttonArray = eval(String(taskTag) + 'imageCanvas') - var buttonArrayData = eval(String(taskTag) + 'imageCanvasData') - - var butNum = buttonArray.indexOf(object) - var butNum2 = buttonArray.indexOf(secondArray[j]) - - buttonArrayData[butNum][100] = buttonArrayData[butNum2][100] + Number(offsetX) - buttonArrayData[butNum][101] = buttonArrayData[butNum2][101] + Number(offsetY) - resize() - } - - } - -} -function shuffleImagePositions(arrayOfObjects) { - - var buttonArray = eval(String(taskTag) + 'imageCanvas') - var buttonArrayData = eval(String(taskTag) + 'imageCanvasData') - - currentX = [] - currentY = [] - - //get current x and y positions of all objects in array - - for (n201i = 0; n201i < arrayOfObjects.length; n201i++) { - var object = arrayOfObjects[n201i] - - var butNum = buttonArray.indexOf(object) - - currentX[n201i] = buttonArrayData[butNum][100] - currentY[n201i] = buttonArrayData[butNum][101] - - } - var mixedNumbers = [] - for (n201i = 0; n201i < arrayOfObjects.length; n201i++) { - mixedNumbers[n201i] = n201i - } - mixedNumbers = shuffleArray(mixedNumbers) - - for (n201i = 0; n201i < arrayOfObjects.length; n201i++) { - - //arrayOfObjects = shuffleArray(arrayOfObjects) - //choose random object from array - - var objectN = arrayOfObjects[mixedNumbers[n201i]] - var butNumN = buttonArray.indexOf(objectN) - - buttonArrayData[butNumN][100] = currentX[n201i] - buttonArrayData[butNumN][101] = currentY[n201i] - //arrayOfObjects = arrayOfObjects.splice(ran,1) - } - - resize() -} -function shuffleObjectPositions(arrayOfObjects) { - - var buttonArray = eval(String(taskTag) + 'button') - var buttonArrayData = eval(String(taskTag) + 'buttonData') - - currentX = [] - currentY = [] - - //get current x and y positions of all objects in array - - for (n201i = 0; n201i < arrayOfObjects.length; n201i++) { - var object = arrayOfObjects[n201i] - - var butNum = buttonArray.indexOf(object) - - currentX[n201i] = buttonArrayData[butNum][100] - currentY[n201i] = buttonArrayData[butNum][101] - - } - var mixedNumbers = [] - for (n201i = 0; n201i < arrayOfObjects.length; n201i++) { - mixedNumbers[n201i] = n201i - } - mixedNumbers = shuffleArray(mixedNumbers) - - for (n201i = 0; n201i < arrayOfObjects.length; n201i++) { - - //arrayOfObjects = shuffleArray(arrayOfObjects) - //choose random object from array - - var objectN = arrayOfObjects[mixedNumbers[n201i]] - var butNumN = buttonArray.indexOf(objectN) - - buttonArrayData[butNumN][100] = currentX[n201i] - buttonArrayData[butNumN][101] = currentY[n201i] - //arrayOfObjects = arrayOfObjects.splice(ran,1) - } - - resize() -} - -// array sorting function for key values -// use is: array = array.sort(keySort('/*key*/')); -function keySort(key, desc) { - return function (a, b) { - return desc ? ~~(a[key] < b[key]) : ~~(a[key] > b[key]); - } -} -function arrayMin(array) { - var min = array[0]; - for (var i = 1; i < array.length; i++) { - min = Math.min(min, array[i]); - } - return min; -} -function arrayMax(array) { - var max = array[0]; - for (var i = 1; i < array.length; i++) { - max = Math.max(max, array[i]); - } - return max; -} -function cloneArray(array) { - var newArray = []; - for (var i = 0; i < array.length; i++) { - newArray[i] = array[i].slice(0); - } - return newArray -} - -function hexToRgb(color) { - if (color.indexOf('rgba') > -1) { // if an rgba string - var result = color.substring(5, color.length - 1).replace(/ /g, '').split(','); - return result ? { - r: parseInt(result[0]), - g: parseInt(result[1]), - b: parseInt(result[2]) - } - : null; - } else if (color.indexOf('rgb') > -1) { // if an rgb string - var result = color.substring(5, color.length - 1).replace(/ /g, '').split(','); - return result ? { - r: parseInt(result[0]), - g: parseInt(result[1]), - b: parseInt(result[2]) - } - : null; - } else if (color.indexOf('#') > -1) { // if a hex string - // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF") - var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i; - color = color.replace(shorthandRegex, function (m, r, g, b) { - return r + r + g + g + b + b; - }); - var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(color); - return result ? { - r: parseInt(result[1], 16), - g: parseInt(result[2], 16), - b: parseInt(result[3], 16) - } - : null; - } else { - return color; - } -} -function colorA(color, alpha) { - var colorRGB = hexToRgb(color); - return "rgba(" + colorRGB.r + "," + colorRGB.g + "," + colorRGB.b + "," + alpha + ")"; -} -function invertColor(color) { - if (/^(#)((?:[A-Fa-f0-9]{3}){1,2})$/i.test(color) == true) - color = hexToRgb(color); // if hex, change to rgba - color.r = 255 - color.r; - color.g = 255 - color.g; - color.b = 255 - color.b; - var a = 1; - if (typeof color.a == 'number') - a = color.a; - return "rgba(" + color.r + "," + color.g + "," + color.b + "," + a + ")"; -} -function getShades(color, invert) { - var invert = boolean(invert, false); - if (invert == true) { - var color2 = hexToRgb(invertColor(color)); - } else { - var color2 = hexToRgb(color); - } - var r = color2.r; - var g = color2.g; - var b = color2.b; - - //var rgb = []; - var hex = []; - - if (r == 0 && g == 0 && b == 0) { // if the color is black, switch it to white - r = 255; - g = 255; - b = 255; - } - - // get brightest shade of rgb - if (Math.max(r, g, b) < 255) { - var m = 255 / Math.max(r, g, b); - r = r * m; - g = g * m; - b = b * m; - } - - for (var i = 0; i < 16; i++) { - var r2 = roundToNearest((i / 15) * r, 1); - var g2 = roundToNearest((i / 15) * g, 1); - var b2 = roundToNearest((i / 15) * b, 1); - //rgb[i] = "rgb("+String(r2)+","+String(g2)+","+String(b2)+")"; - var r3 = decToHex2Digits(r2); - var g3 = decToHex2Digits(g2); - var b3 = decToHex2Digits(b2); - hex[i] = "#" + r3 + g3 + b3; - } - - return hex; -} -function decToHex2Digits(num) { - num2 = num.toString(16); - if (num2.length == 1) { - num2 = "0" + num2; - } else if (num2.indexOf('.') == 1) { - num2 = "0" + num2.slice(0, 1); - } else { - num2 = num2.slice(0, 2); - } - return num2; -} -function testShades(ctx, color, invert) { - var colors = getShades(color, invert); - var ctx = draw.drawctx; - ctx.strokeStyle = '#000'; - for (var i = 0; i < 16; i++) { - ctx.fillStyle = colors[i]; - ctx.fillRect(50 + i * 50, 50, 50, 50); - ctx.strokeRect(50 + i * 50, 50, 50, 50); - } -} -function getColor(r, g, b, a) { - if (un(a)) - a = 1; - return 'rgba(' + r + ',' + g + ',' + b + ',' + a + ')'; -} -function getScaleColor(value,max,saturation) { - if (un(saturation)) saturation = 1; - var perc = Math.round((value / max) * 100); - var h = Math.floor(perc * 1.2); - var s = saturation; - var v = 1; - return hsv2rgb(h, s, v); -} -function hsv2rgb (h, s, v) { - // adapted from http://schinckel.net/2012/01/10/hsv-to-rgb-in-javascript/ - var rgb, i, data = []; - if (s === 0) { - rgb = [v,v,v]; - } else { - h = h / 60; - i = Math.floor(h); - data = [v*(1-s), v*(1-s*(h-i)), v*(1-s*(1-(h-i)))]; - switch(i) { - case 0: - rgb = [v, data[2], data[0]]; - break; - case 1: - rgb = [data[1], v, data[0]]; - break; - case 2: - rgb = [data[0], v, data[2]]; - break; - case 3: - rgb = [data[0], data[1], v]; - break; - case 4: - rgb = [data[2], data[0], v]; - break; - default: - rgb = [v, data[0], data[1]]; - break; - } - } - return '#' + rgb.map(function(x){ - return ("0" + Math.round(x*255).toString(16)).slice(-2); - }).join(''); -}; - -function collapseLines(lineArray) { - // collapses lines in an array such as: - // [ [[x1,y1],[x2,y2]], [[x3,y3],[x4,y4]], [[x5,y5],[x6,y6]] ] - do { - var joinFound = false; - for (var i = 0; i < lineArray.length; i++) { - if (joinFound == false) { - for (var j = i + 1; j < lineArray.length; j++) { - var x1 = lineArray[i][0][0]; - var y1 = lineArray[i][0][1]; - var x2 = lineArray[i][1][0]; - var y2 = lineArray[i][1][1]; - var x3 = lineArray[j][0][0]; - var y3 = lineArray[j][0][1]; - var x4 = lineArray[j][1][0]; - var y4 = lineArray[j][1][1]; - var m1 = (y2 - y1) / (x2 - x1); - var m2 = (y4 - y3) / (x4 - x3); - // if gradients are equal and point from line 1 is on line 2 - //console.log('x1,y1,x2,y2,x3,y3,x4,y4'); - //console.log('grad/grad: ',mMax/mMin); - //console.log('pointOnLine: ',isPointOnLine([x1,y1],[x3,y3],[x4,y4],3.5)); - if (((Math.abs(m1) == 'Infinity' && Math.abs(m2) == 'Infinity') || Math.abs(m1 - m2) < 0.0001) && isPointOnLine([x1, y1], [x3, y3], [x4, y4], 0.25) == true) { - // if one of the points is between the two points on the other line - if ((x1 >= Math.min(x3, x4) && x1 <= Math.max(x3, x4) && y1 >= Math.min(y3, y4) && y1 <= Math.max(y3, y4)) || (x2 >= Math.min(x3, x4) && x2 <= Math.max(x3, x4) && y2 >= Math.min(y3, y4) && y2 <= Math.max(y3, y4)) || (x3 >= Math.min(x1, x2) && x3 <= Math.max(x1, x2) && y3 >= Math.min(y1, y2) && y3 <= Math.max(y1, y2)) || (x4 >= Math.min(x1, x2) && x4 <= Math.max(x1, x2) && y4 >= Math.min(y1, y2) && y4 <= Math.max(y1, y2))) { - var xMin = Math.min(x1, x2, x3, x4); - var xMax = Math.max(x1, x2, x3, x4); - if (xMin == x1) - var yMin = y1; - if (xMin == x2) - var yMin = y2; - if (xMin == x3) - var yMin = y3; - if (xMin == x4) - var yMin = y4; - if (xMax == x1) - var yMax = y1; - if (xMax == x2) - var yMax = y2; - if (xMax == x3) - var yMax = y3; - if (xMax == x4) - var yMax = y4; - if (xMin == xMax) { - var yMin = Math.min(y1, y2, y3, y4); - var yMax = Math.max(y1, y2, y3, y4); - } - joinFound = true; - lineArray[i][0] = [xMin, yMin]; - lineArray[i][1] = [xMax, yMax]; - lineArray.splice(j, 1); - break; - } - } - } - } - } - } while (joinFound == true); - return lineArray; -} - -function drawBarChart(object) { - /* EXAMPLE USAGE: - drawBarChart({ - ctx:j324buttonctx[0], - left:200, - top:240, - width:500, - height:370, - data:[{value:['0'], freq:17},{value:['1'], freq:6},{value:['2'], freq:3},{value:['3'], freq:1},{value:['4'], freq:2},{value:['5'], freq:0},{value:['6'], freq:1}, - ], - barWidth:[2,1], // bar width to gap width ratio - barColor:'#FCF', - barOutlineColor:'#000', - barOutlineWidth:4, - xLabel:['number of days'], - yLabel:['frequency'], - title:['Number of days absent in a month for a class'], - titlePos:[450,260,200,90], - yMinor:{show:true,step:1,color:'#AAA',width:1,dash:[3,5]}, - yMajor:{show:true,step:2,color:'#888',width:2,dash:[]}, - yMin:0, - yMax:18, - }); - */ - - var ctx = object.ctx || object.context; - var left = object.left; - var top = object.top; - var width = object.width; - var height = object.height; - var data = object.data; - - var barWidth = object.barWidth || [2, 1]; - var barColor = object.barColor || '#FCF'; - var barOutlineColor = object.barOutlineColor || '#000'; - var barOutlineWidth = object.barOutlineWidth || 2; - var xLabel = object.xLabel || ['']; - var yLabel = object.yLabel || ['']; - var title = object.title || ['']; - var titlePos = object.titlePos || [left + 0.5 * width, top + 0.03 * height, 0.4 * width, 0.2 * height]; - - if (typeof object.yMinor == 'object') { - var yMinorShow = boolean(object.yMinor.show, false); - var yMinorStep = object.yMinor.step || 1; - var yMinorColor = object.yMinor.color || '#AAA'; - var yMinorWidth = object.yMinor.width || 1; - var yMinorDash = object.yMinor.dash || []; - } else { - var yMinorShow = false; - var yMinorStep = 1; - var yMinorColor = '#AAA'; - var yMinorWidth = 1; - var yMinorDash = []; - } - - if (typeof object.yMajor == 'object') { - var yMajorShow = boolean(object.yMajor.show, false); - var yMajorStep = object.yMajor.step || 1; - var yMajorColor = object.yMajor.color || '#888'; - var yMajorWidth = object.yMajor.width || 2; - var yMajorDash = object.yMajor.dash || []; - } else { - var yMajorShow = false; - var yMajorStep = 1; - var yMajorColor = '#888'; - var yMajorWidth = 2; - var yMajorDash = []; - } - - if (object.yMin == 'number') { - var yMin = object.yMin; - } else { - var yMin = 0; - } - - if (object.yMax == 'number') { - var yMax = object.yMax; - } else { - var yMax = 0; - for (var i = 0; i < data.length; i++) { - yMax = Math.max(yMax, data[i].freq + 1); - } - var steps = Math.floor(yMax / yMajorStep); - while (yMax % yMajorStep > 0 || yMax / yMajorStep < steps + 1) { - yMax++; - } - } - - // work out the spacing for minor and major steps - var yMinorSpacing = (height * yMinorStep) / (yMax - yMin); - var yMajorSpacing = (height * yMajorStep) / (yMax - yMin); - - // work out the coordinates of the origin - var x0 = left; - var y0 = top + (yMax * height) / (yMax - yMin); - - // work out the actual display position of the origin (ie. at the edge if it is off the grid) - var x0DisplayPos = left; - var y0DisplayPos = top + height; - - ctx.save(); - ctx.lineJoin = 'round'; - ctx.lineCap = 'round'; - if (yMinorShow == true) { - ctx.beginPath(); - ctx.strokeStyle = yMinorColor; - ctx.lineWidth = yMinorWidth; - if (!ctx.setLineDash) { - ctx.setLineDash = function () {} - } - ctx.setLineDash(yMinorDash); - var yAxisPoint = y0 - yMinorSpacing; - while (yAxisPoint > top) { - if (yAxisPoint < top + height) { - ctx.moveTo(left, yAxisPoint); - ctx.lineTo(left + width, yAxisPoint); - } - yAxisPoint -= yMinorSpacing; - } - var yAxisPoint = y0 + yMinorSpacing; - while (yAxisPoint <= top + height) { - if (yAxisPoint >= top) { - ctx.moveTo(left, yAxisPoint); - ctx.lineTo(left + width, yAxisPoint); - } - yAxisPoint += yMinorSpacing; - } - ctx.stroke(); - } - - if (yMajorShow == true) { - ctx.beginPath(); - ctx.strokeStyle = yMajorColor; - ctx.lineWidth = yMajorWidth; - if (!ctx.setLineDash) { - ctx.setLineDash = function () {} - } - ctx.setLineDash(yMajorDash); - var yAxisPoint = y0 - yMajorSpacing; - while (yAxisPoint > top - 0.00001) { - if (yAxisPoint < (top + height + 0.00001)) { - ctx.moveTo(left, yAxisPoint); - ctx.lineTo(left + width, yAxisPoint); - } - yAxisPoint -= yMajorSpacing; - } - var yAxisPoint = y0 + yMajorSpacing; - while (yAxisPoint < top + height + 0.00001) { - if (yAxisPoint > top - 0.00001) { - ctx.moveTo(left, yAxisPoint); - ctx.lineTo(left + width, yAxisPoint); - } - yAxisPoint += yMajorSpacing; - } - ctx.stroke(); - } - - // draw axes - ctx.beginPath(); - ctx.strokeStyle = '#000'; - ctx.lineWidth = 3; - if (!ctx.setLineDash) { - ctx.setLineDash = function () {} - } - ctx.setLineDash([]); - // if neccesary, draw x-Axis - if (y0 >= top && y0 <= top + height) { - ctx.moveTo(left, y0); - ctx.lineTo(left + width, y0); - } - ctx.stroke(); - ctx.beginPath(); - ctx.strokeStyle = '#000'; - ctx.lineWidth = 3; - // if neccesary, draw y-Axis - if (x0 >= left && x0 <= left + width) { - ctx.moveTo(x0, top); - ctx.lineTo(x0, top + height); - } - ctx.stroke(); - - // draw yAxes numbers - ctx.font = '24px Arial'; - ctx.textAlign = "center"; - ctx.textBaseline = "top"; - ctx.lineWidth = 2; - ctx.strokeStyle = yMajorColor; - ctx.textBaseline = "middle"; - ctx.textAlign = "right"; - ctx.fillStyle = '#000'; - var fontSize = 24; - - // positive y numbers - var yAxisPoint = y0; - var major = 0; - var placeValue = Math.pow(10, Math.floor(Math.log(yMajorStep) / Math.log(10))); - while (yAxisPoint >= top - 0.0001) { - if (yAxisPoint <= top + height) { - var axisValue = Number(roundSF(major * yMajorStep, 5)); - var textWidth = ctx.measureText(String(axisValue)).width - ctx.clearRect(x0DisplayPos - textWidth - 16, yAxisPoint - fontSize * 0.5, textWidth + 3, fontSize); - ctx.beginPath(); - ctx.moveTo(x0DisplayPos, yAxisPoint); - ctx.lineTo(x0DisplayPos - 8, yAxisPoint); - ctx.stroke(); - wrapText(ctx, String(axisValue), x0DisplayPos - 7, yAxisPoint - 2, 50, 40, fontSize + 'px Arial'); - } - major += 1; - yAxisPoint -= yMajorSpacing; - } - // negative y numbers - var yAxisPoint = y0 + yMajorSpacing; - var major = -1; - while (yAxisPoint <= top + height + 0.0001) { - if (yAxisPoint >= top) { - var axisValue = Number(roundSF(major * yMajorStep, 5)); - var textWidth = ctx.measureText(String(axisValue)).width - ctx.clearRect(x0DisplayPos - textWidth - 16, yAxisPoint - fontSize * 0.5, textWidth + 3, fontSize); - ctx.beginPath(); - ctx.moveTo(x0DisplayPos, yAxisPoint); - ctx.lineTo(x0DisplayPos - 8, yAxisPoint); - ctx.stroke(); - wrapText(ctx, String(axisValue), x0DisplayPos - 7, yAxisPoint - 2, 50, 40, fontSize + 'px Arial'); - } - major -= 1; - yAxisPoint += yMajorSpacing; - } - - // draw axes - ctx.strokeStyle = '#000'; - ctx.lineWidth = 4; - ctx.beginPath(); - ctx.moveTo(left, top); - ctx.lineTo(left, top + height); - ctx.lineTo(left + width, top + height); - ctx.stroke(); - - var ySpacing = height / (yMax - yMin); - var xSpacing = width / (data.length * barWidth[0] + (data.length + 1) * barWidth[1]); - var l = []; - - ctx.beginPath(); - for (var i = 0; i < data.length; i++) { - l[i] = left + i * barWidth[0] * xSpacing + (i + 1) * barWidth[1] * xSpacing; - drawMathsText(ctx, data[i].value, 24, l[i] + 0.5 * xSpacing * barWidth[0], top + height + 5, false, [], 'center', 'top', '#000'); - //ctx.moveTo(l[i]+0.5*xSpacing*barWidth[0],top+height); - //ctx.lineTo(l[i]+0.5*xSpacing*barWidth[0],top+height+5); - } - ctx.stroke(); - - ctx.lineWidth = barOutlineWidth; - ctx.strokeStyle = barOutlineColor; - ctx.fillStyle = barColor; - ctx.beginPath(); - - for (var i = 0; i < data.length; i++) { - var t = top + height - ySpacing * data[i].freq; - var h = ySpacing * data[i].freq; - ctx.fillRect(l[i], t, xSpacing * barWidth[0], h); - ctx.strokeRect(l[i], t, xSpacing * barWidth[0], h); - } - - if (arraysEqual(xLabel, ['']) == false) { - text({ - context: ctx, - textArray: ['<><><><>' + xLabel], - left: left + width - 200, - width: 200, - top: top + height + 30, - }); - } - - if (arraysEqual(yLabel, ['']) == false) { - text({ - context: ctx, - textArray: ['<><><><>' + yLabel], - left: left - 50 - 200, - width: 200, - top: top + height * 0.03, - }); - } - - if (arraysEqual(title, ['']) == false) { - text({ - context: ctx, - textArray: ['<><><><>' + title], - left: titlePos[0], - top: titlePos[1], - width: titlePos[2], - maxHeight: titlePos[3], - box: { - color: '#FFC', - dash: [], - border: '#000', - borderWidth: 3, - radius: 5, - pos: [titlePos[0] - 10, titlePos[1] - 5, titlePos[2] + 12, titlePos[3] + 10] - } - // box.pos may need tweaking when text has been improved - }); - } -} - -function isNode(o) { //Returns true if it is a DOM node - return ( - typeof Node === "object" ? o instanceof Node : - o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName === "string"); -} -function isElement(o) { //Returns true if it is a DOM element - return ( - typeof HTMLElement === "object" ? o instanceof HTMLElement : //DOM2 - o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName === "string"); -} - -/***************************/ -/* VECTOR GEOMETRY */ -/***************************/ - -function getVectorAB(a, b) { - return [b[0] - a[0], b[1] - a[1]]; -} -function getUnitVector(vector) { - var mag = Math.sqrt(Math.pow(vector[0], 2) + Math.pow(vector[1], 2)); - return [vector[0] / mag, vector[1] / mag]; -} -function setVectorMag(vector, mag) { - var unit = getUnitVector(vector); - return [unit[0] * mag, unit[1] * mag]; -} -function getDist(a, b) { - return Math.sqrt(Math.pow(b[0] - a[0], 2) + Math.pow(b[1] - a[1], 2)); -} -function getPerpVector(vector, dir) { - if (un(dir)) - dir = 1; - if (dir == 1) { - return [-1 * vector[1], vector[0]]; - } else { - return [vector[1], -1 * vector[0]]; - } -} -function pointAddVector(point, vector, scalarMult) { - if (un(scalarMult)) - scalarMult = 1; - return [point[0] + scalarMult * vector[0], point[1] + scalarMult * vector[1]]; -} -function getVectorMag(vector) { - return Math.sqrt(Math.pow(vector[0], 2) + Math.pow(vector[1], 2)); -} -function getVectorAngle(vector) { - var angle = Math.atan(vector[1] / vector[0]); - if (vector[0] >= 0 && vector[1] >= 0) - return angle; - if (vector[0] >= 0 && vector[1] < 0) - return angle + 2 * Math.PI; - if (vector[0] < 0) - return angle + Math.PI; -} -function angleToVector(angle, mag) { - if (un(mag)) mag = 1; - return [mag*Math.cos(angle),mag*Math.sin(angle)]; -} -function rotateVector(vector, angle) { - var mag = Math.sqrt(Math.pow(vector[0], 2) + Math.pow(vector[1], 2)); - var theta = getVectorAngle(vector) + angle; - return [mag * Math.cos(theta), mag * Math.sin(theta)]; -} -function getVectorLinesIntersection(p1, v1, p2, v2) { - var lambda = (p1[1] * v2[0] + p2[0] * v2[1] - p1[0] * v2[1] - p2[1] * v2[0]) / (v1[0] * v2[1] - v1[1] * v2[0]); - return pointAddVector(p1, v1, lambda); -} -function getMidpoint(p1, p2) { - return [(p1[0] + p2[0]) / 2, (p1[1] + p2[1]) / 2]; -} -function getFootOfPerp(p, v, q) { // foot of perp from point q to line p + kv - var lambda = (q[0] * v[0] + q[1] * v[1] - p[0] * v[0] - p[1] * v[1]) / (v[0] * v[0] + v[1] * v[1]); - return pointAddVector(p, v, lambda); -} -function getPerpDist(p, v, q) { // shortest dist from point q to line p + kv - var foot = getFootOfPerp(p, v, q); - return getDist(q, foot); -} - -var vector = { // generalised 3d versions - getVectorAB: function (a, b) { - if (a.length !== b.length) return null; - var v = []; - for (var i = 0; i < a.length; i++) v[i] = b[i] - a[i]; - return v; - }, - scalarMult: function (a, k) { - var r = []; - for (var i = 0; i < a.length; i++) - r[i] = a[i] * k; - return r; - }, - dotProduct: function (a, b) { - if (a.length !== b.length) - return null; - var p = 0; - for (var i = 0; i < a.length; i++) - p += b[i] * a[i]; - return p; - }, - crossProduct: function (a, b) { - if (a.length !== 3 || b.length !== 3) - return null; - return [ - a[1] * b[2] - a[2] * b[1], - a[2] * b[0] - a[0] * b[2], - a[0] * b[1] - a[1] * b[0] - ]; - }, - getMagnitude: function (a) { - var m = 0; - for (var i = 0; i < a.length; i++) - m += a[i] * a[i]; - return Math.sqrt(m); - }, - getUnitVector: function (a) { - var u = []; - var m = vector.getMagnitude(a); - for (var i = 0; i < a.length; i++) - u[i] = a[i] / m; - return u; - }, - setMagnitude: function (a, m) { - var b = []; - var unitVector = vector.getUnitVector(a); - for (var i = 0; i < a.length; i++) - b[i] = unitVector[i] * m; - return b; - }, - addVectors: function (a, b, k) { - if (a.length !== b.length) - return null; - if (un(k)) - k = 1; - var r = []; - for (var i = 0; i < a.length; i++) - r[i] = a[i] + b[i] * k; - return r; - }, - getAngleBetweenVectors: function (a, b) { - if (a.length !== b.length) - return null; - var dot = vector.dotProduct(a, b); - var mag1 = vector.getMagnitude(a); - var mag2 = vector.getMagnitude(b); - return Math.acos(dot / (mag1 * mag2)); - } -}; - -/***************************/ -/* POLYGONS */ -/***************************/ - -function drawPolygon(obj) { - // required - var ctx = obj.ctx; - var points = obj.points; - - // optional - var fillColor = obj.fillColor || obj.fillStyle || false; - var lineColor = obj.lineColor || obj.color || obj.strokeStyle || false; - var lineWidth = obj.lineWidth || obj.thickness || false; - var closed = boolean(obj.closed, true); - var lineDecoration = obj.lineDecoration || []; - var angles = obj.angles || []; - var outerAngles = obj.outerAngles || []; - var exteriorAngles = obj.exteriorAngles || []; - var clockwise = boolean(obj.clockwise, true) - var sf = obj.sf || 1; - var calcTextSnapPos = boolean(obj.calcTextSnapPos, false) - - //console.log(ctx,points,lineColor,lineWidth,closed); - - var angleLabelPos = []; - var outerAngleLabelPos = []; - var exteriorAngleLabelPos = []; - var prismPoints = []; - var textSnapPos = []; - - ctx.save(); - ctx.lineJoin = 'round'; - ctx.lineCap = 'round'; - - ctx.beginPath(); - - if (!un(obj.solidType)) { - if (obj.solidType == 'prism') { - var prismVector = obj.prismVector || [40, -40]; - var vectorAngle = getVectorAngle(prismVector); - var points2 = []; - var points2Vis = []; - var angles2 = []; - for (var p = 0; p < points.length; p++) { - points2[p] = pointAddVector(points[p], prismVector); - prismPoints[p] = points2[p]; - var prev = p - 1; - if (prev < 0) - prev = obj.points.length - 1; - var next = p + 1; - if (next > obj.points.length - 1) - next = 0; - angles2[p] = [ - posToAngle(obj.points[prev][0], obj.points[prev][1], obj.points[p][0], obj.points[p][1]), - posToAngle(obj.points[next][0], obj.points[next][1], obj.points[p][0], obj.points[p][1]) - ]; - if (anglesInOrder(angles2[p][1], vectorAngle, angles2[p][0]) == true) { - points2Vis[p] = false; - } else { - points2Vis[p] = true; - } - } - - if (closed == true && fillColor !== false && fillColor !== 'none') { - for (var p = 0; p < points.length; p++) { // fill polygons - var next = (p + 1) % (points.length); - ctx.moveTo(points[p][0], points[p][1]); - ctx.lineTo(points2[p][0], points2[p][1]); - ctx.lineTo(points2[next][0], points2[next][1]); - ctx.lineTo(points[next][0], points[next][1]); - ctx.closePath(); - ctx.fillStyle = fillColor; - ctx.fill(); - } - } - - for (var p = 0; p < points.length; p++) { // draw lines - ctx.save(); - if (points2Vis[p] == false || points2Vis[(p + 1) % (points.length)] == false) { - if (obj.solidShowAllLines == false) continue; - ctx.strokeStyle = getShades(ctx.strokeStyle)[12]; - } - ctx.beginPath(); - ctx.moveTo(points2[p][0], points2[p][1]); - ctx.lineTo(points2[(p + 1) % (points.length)][0], points2[(p + 1) % (points.length)][1]); - ctx.stroke(); - ctx.restore(); - } - - for (var p = 0; p < points.length; p++) { // draw lines - ctx.save(); - if (points2Vis[p] == false) { - if (obj.solidShowAllLines == false) continue; - ctx.strokeStyle = getShades(ctx.strokeStyle)[12]; - } - ctx.beginPath(); - ctx.moveTo(points[p][0], points[p][1]); - ctx.lineTo(points2[p][0], points2[p][1]); - ctx.stroke(); - ctx.restore(); - } - - } - } - - if (closed == true && fillColor !== false && fillColor !== 'none') { - ctx.moveTo(points[0][0], points[0][1]); - for (var i = 1; i < points.length; i++) { - ctx.lineTo(points[i][0], points[i][1]); - } - ctx.closePath(); - ctx.fillStyle = fillColor; - ctx.fill(); - } - - for (var i = 0; i < points.length; i++) { - var p1 = i == 0 ? points.last() : points[i-1]; - var p2 = points[i]; - var p3 = points[(i+1)%points.length]; - - var a1 = getAngleFromAToB(p2,p1); - var a2 = getAngleFromAToB(p2,p3); - if (a2 > a1) { - var a3 = (a1+a2)/2; - } else { - var a3 = (a1+a2+2*Math.PI)/2; - while (a3 > 2*Math.PI) { - a3 -= 2*Math.PI; - } - } - var n = Math.PI/8; - var align = [0,0]; - if (a3 < n || a3 >= 15*n) { - align = [-1,0]; - } else if (a3 < 3*n) { - align = [-1,-1]; - } else if (a3 < 5*n) { - align = [0,-1]; - } else if (a3 < 7*n) { - align = [1,-1]; - } else if (a3 < 9*n) { - align = [1,0]; - } else if (a3 < 11*n) { - align = [1,1]; - } else if (a3 < 13*n) { - align = [0,1]; - } else if (a3 < 15*n) { - align = [-1,1]; - } - - var vector = angleToVector(a3,5); - var labelPos = pointAddVector(p2,vector); - - if (calcTextSnapPos == true) textSnapPos.push({type:'polygonVertex',pos:labelPos,align:align,angle:a3,vertex:i,polygon:obj}); - - // side labels - var mid = midpoint(p2[0],p2[1],p3[0],p3[1]); - var ang = a2-0.5*Math.PI; - while (ang < 0) ang += 2*Math.PI; - - var align = [0,0]; - if (ang < n || ang >= 15*n) { - align = [-1,0]; - } else if (ang < 3*n) { - align = [-1,-1]; - } else if (ang < 5*n) { - align = [0,-1]; - } else if (ang < 7*n) { - align = [1,-1]; - } else if (ang < 9*n) { - align = [1,0]; - } else if (ang < 11*n) { - align = [1,1]; - } else if (ang < 13*n) { - align = [0,1]; - } else if (ang < 15*n) { - align = [-1,1]; - } - - var margin = align.indexOf(0) > -1 ? 10 : 5; - var vector = angleToVector(ang,margin); - var labelPos = pointAddVector(mid,vector); - - if (calcTextSnapPos == true) textSnapPos.push({type:'polygonSide',pos:labelPos,align:align,angle:ang,vertex:i,polygon:obj}); - } - - for (var i = 0; i < points.length; i++) { - if (typeof angles[i] == 'object' && angles[i] !== null) { - angle = clone(angles[i]); - } else { - continue; - angle = { - labelMeasure: true, - measureLabelOnly: true, - measureOnly: true - }; - } - angle.ctx = ctx; - angle.b = points[i]; - if (clockwise == false) { - angle.a = points[(i + 1) % (points.length)]; - if (i == 0) { - angle.c = points[points.length - 1]; - } else { - angle.c = points[i - 1]; - } - } else { - angle.c = points[(i + 1) % (points.length)]; - if (i == 0) { - angle.a = points[points.length - 1]; - } else { - angle.a = points[i - 1]; - } - } - angle.drawLines = false; - if (typeof angle.lineWidth == 'undefined') - angle.lineWidth = ctx.lineWidth; - if (typeof angle.lineColor == 'undefined') - angle.lineColor = ctx.lineWidth; - if (typeof angle.labelColor == 'undefined') - angle.labelColor = ctx.strokeStyle; - angleLabelPos[i] = drawAngle(angle); - } - - if (obj.anglesMode == 'outer' && (un(obj.solidType) || obj.solidType !== 'prism')) { - for (var i = 0; i < outerAngles.length; i++) { - if (typeof outerAngles[i] == 'object' && outerAngles[i] !== null) { - outerAngles[i].ctx = ctx; - outerAngles[i].b = points[i]; - if (clockwise == true) { - outerAngles[i].a = points[(i + 1) % (points.length)]; - if (i == 0) { - outerAngles[i].c = points[points.length - 1]; - } else { - outerAngles[i].c = points[i - 1]; - } - } else { - outerAngles[i].c = points[(i + 1) % (points.length)]; - if (i == 0) { - outerAngles[i].a = points[points.length - 1]; - } else { - outerAngles[i].a = points[i - 1]; - } - } - outerAngles[i].drawLines = false; - if (typeof outerAngles[i].lineWidth == 'undefined') - outerAngles[i].lineWidth = ctx.lineWidth; - if (typeof outerAngles[i].lineColor == 'undefined') - outerAngles[i].lineColor = ctx.lineWidth; - if (typeof outerAngles[i].labelColor == 'undefined') - outerAngles[i].labelColor = ctx.strokeStyle; - outerAngleLabelPos[i] = drawAngle(outerAngles[i]); - } - } - } - - ctx.lineJoin = 'round'; - ctx.lineCap = 'round'; - - if (lineColor !== false) { - ctx.strokeStyle = lineColor; - } - if (lineWidth !== false) { - ctx.lineWidth = lineWidth; - } - - if (obj.anglesMode == 'exterior' && (un(obj.solidType) || obj.solidType !== 'prism')) { - for (var i = 0; i < exteriorAngles.length; i++) { - if (typeof exteriorAngles[i] == 'object') { - exteriorAngleLabelPos[i] = []; - var ext = exteriorAngles[i]; - if (!un(ext.a1) && ext.a1 !== null) { - ext.a1.ctx = ctx; - ext.a1.c = points[(i + 1) % (points.length)]; - ext.a1.b = points[i]; - ext.a1.a = ext.line2.pos; - ext.a1.drawLines = false; - if (un(ext.a1.lineWidth)) - ext.a1.lineWidth = ctx.lineWidth; - if (un(ext.a1.lineColor)) - ext.a1.lineColor = ctx.lineWidth; - if (un(ext.a1.labelColor)) - ext.a1.labelColor = ctx.strokeStyle; - exteriorAngleLabelPos[i][0] = drawAngle(ext.a1); - } - if (!un(ext.a2) && ext.a2 !== null) { - ext.a2.ctx = ctx; - ext.a2.c = ext.line2.pos; - ext.a2.b = points[i]; - ext.a2.a = ext.line1.pos; - ext.a2.drawLines = false; - if (un(ext.a2.lineWidth)) - ext.a2.lineWidth = ctx.lineWidth; - if (un(ext.a2.lineColor)) - ext.a2.lineColor = ctx.lineWidth; - if (un(ext.a2.labelColor)) - ext.a2.labelColor = ctx.strokeStyle; - exteriorAngleLabelPos[i][1] = drawAngle(ext.a2); - } - if (!un(ext.a3) && ext.a3 !== null) { - ext.a3.ctx = ctx; - ext.a3.c = ext.line1.pos; - ext.a3.b = points[i]; - if (i > 0) { - ext.a3.a = points[i - 1]; - } else { - ext.a3.a = points[points.length - 1]; - } - ext.a3.drawLines = false; - if (un(ext.a3.lineWidth)) - ext.a3.lineWidth = ctx.lineWidth; - if (un(ext.a3.lineColor)) - ext.a3.lineColor = ctx.lineWidth; - if (un(ext.a3.labelColor)) - ext.a3.labelColor = ctx.strokeStyle; - exteriorAngleLabelPos[i][2] = drawAngle(ext.a3); - } - if (boolean(ext.line1.show, false)) { - ctx.save(); - ctx.lineWidth = lineWidth; - ctx.moveTo(points[i][0], points[i][1]); - ctx.lineTo(ext.line1.pos[0], ext.line1.pos[1]); - ctx.stroke(); - ctx.restore(); - } - if (boolean(ext.line2.show, false)) { - ctx.save(); - ctx.lineWidth = lineWidth; - ctx.moveTo(points[i][0], points[i][1]); - ctx.lineTo(ext.line2.pos[0], ext.line2.pos[1]); - ctx.stroke(); - ctx.restore(); - } - } - } - } - - ctx.beginPath(); - ctx.moveTo(points[0][0], points[0][1]); - for (var i = 1; i < points.length; i++) { - ctx.lineTo(points[i][0], points[i][1]); - } - if (closed == true) { - ctx.closePath(); - } - ctx.lineWidth = lineWidth; - if (obj.strokeStyle !== 'none') - ctx.stroke(); - - for (var i = 0; i < lineDecoration.length; i++) { - if (typeof lineDecoration[i] == 'object' && lineDecoration[i] !== null) { - switch (lineDecoration[i].type) { - case 'dash': - var dashLength = lineDecoration[i].length || 8 * sf; - var number = lineDecoration[i].number || 1; - if (number == 1) { - drawDash(ctx, points[i][0], points[i][1], points[(i + 1) % (points.length)][0], points[(i + 1) % (points.length)][1], dashLength); - } else if (number == 2) { - drawDoubleDash(ctx, points[i][0], points[i][1], points[(i + 1) % (points.length)][0], points[(i + 1) % (points.length)][1], dashLength); - } - break; - case 'arrow': - var arrowLength = lineDecoration[i].length || 12 * sf; - var number = lineDecoration[i].number || 1; - var direction = lineDecoration[i].direction || 1; - ctx.save(); - if (direction == 1) { - drawParallelArrow({ - context: ctx, - startX: points[i][0], - startY: points[i][1], - finX: points[(i + 1) % (points.length)][0], - finY: points[(i + 1) % (points.length)][1], - arrowLength: arrowLength, - lineWidth: ctx.lineWidth, - numOfArrows: number, - color: ctx.strokeStyle - }); - } else if (direction == -1) { - drawParallelArrow({ - context: ctx, - finX: points[i][0], - finY: points[i][1], - startX: points[(i + 1) % (points.length)][0], - startY: points[(i + 1) % (points.length)][1], - arrowLength: arrowLength, - lineWidth: ctx.lineWidth, - numOfArrows: number, - color: ctx.strokeStyle - }); - } - ctx.restore(); - break; - default: - break; - }; - } - } - - ctx.restore(); - return { - angleLabelPos: angleLabelPos, - outerAngleLabelPos: outerAngleLabelPos, - exteriorAngleLabelPos: exteriorAngleLabelPos, - prismPoints: prismPoints, - textSnapPos: textSnapPos - }; -} -function checkLinesForPolygon(lines, allowSelfIntersect) { - if (typeof allowSelfIntersect == 'undefined') allowSelfIntersect = false; - if (lines.length < 3) return false; - var lines = clone(lines); - lines = reduceLineSegments(lines); - - // remove lines with zero length - for (var l = lines.length - 1; l >= 0; l--) { - if (arraysEqual(lines[l][0], lines[l][1])) lines.splice(l, 1); - } - - var gradients = []; - for (var l = 0; l < lines.length; l++) { - var line = lines[l]; - gradients[l] = (line[1][1] - line[0][1]) / (line[1][0] - line[0][0]); - } - - function pointsEqual(p1, p2) { - if (p1[0] == p2[0] && p1[1] == p2[1]) return true; - return false; - } - - //console.clear(); - //console.log('lines:',clone(lines),lines.length); - //console.log('gradients:',gradients); - // test for overlapping parallel lines - for (var a = 0; a < lines.length - 1; a++) { - var lineA = lines[a]; - for (var b = a + 1; b < lines.length; b++) { - var lineB = lines[b]; - if (gradients[a] !== gradients[b]) continue; - var test1 = isPointOnLineSegment(lineB[0], lineA[0], lineA[1]); - var test2 = isPointOnLineSegment(lineB[1], lineA[0], lineA[1]); - var test3 = (pointsEqual(lineA[0], lineB[0]) || pointsEqual(lineA[0], lineB[1]) || pointsEqual(lineA[1], lineB[0]) || pointsEqual(lineA[1], lineB[1])) ? true : false; - if (test1 == false && test2 == false && test3 == false) continue; - - //console.log('a:',a,lineA[0],lineA[1],'b:',b,lineB[0],lineB[1],'gradient:',gradients[a],gradients[b]); //console.log(pointsEqual(lineA[0],lineB[0]),pointsEqual(lineA[0],lineB[1]),pointsEqual(lineA[1],lineB[0]),pointsEqual(lineA[1],lineB[1])); - //console.log(test1,test2,test3); - - // lines overlap - find most extreme of the 4 points - var pos = lineA.concat(lineB); - var min = pos[0]; - var max = pos[0]; - if (gradients[a] == Infinity || gradients[a] == -Infinity) { - for (var p = 1; p < pos.length; p++) { - if (pos[p][1] < min[1]) - min = pos[p]; - if (pos[p][1] > max[1]) - max = pos[p]; - } - } else { - for (var p = 1; p < pos.length; p++) { - if (pos[p][0] < min[0]) - min = pos[p]; - if (pos[p][0] > max[0]) - max = pos[p]; - } - } - lines[a] = [min, max]; - lines.splice(b, 1); - } - } - - var pos = []; - //console.log('reduced lines:'); - for (var l = 0; l < lines.length; l++) { - var line = lines[l]; - //console.log('('+line[0][0]+','+line[0][1]+')','('+line[1][0]+','+line[1][1]+')'); - var found = [false, false]; - for (var p = 0; p < pos.length; p++) { - if (pos[p].pos[0] == line[0][0] && pos[p].pos[1] == line[0][1]) { - pos[p].count++; - found[0] = true; - } - if (pos[p].pos[0] == line[1][0] && pos[p].pos[1] == line[1][1]) { - pos[p].count++; - found[1] = true; - } - } - if (found[0] == false) - pos.push({ - pos: clone(line[0]), - count: 1 - }); - if (found[1] == false) - pos.push({ - pos: clone(line[1]), - count: 1 - }); - //console.log(found,clone(pos)); - } - //console.log('pos:',pos); - - for (var p = 0; p < pos.length; p++) { - if (pos[p].count !== 2) return false; - } - - var polygon = [lines.shift()]; - while (lines.length > 0) { - var pos = polygon.last()[1]; - var found = false; - for (var l = 0; l < lines.length; l++) { - var line = lines[l]; - if (arraysEqual(line[0], pos)) { - polygon.push(line); - lines.splice(l, 1); - found = true; - break; - } else if (arraysEqual(line[1], pos)) { - polygon.push(line.reverse()); - lines.splice(l, 1); - found = true; - break; - } - } - //console.log(clone(polygon),clone(lines),found); - if (found == false) - return false; - } - for (var p = 0; p < polygon.length; p++) polygon[p] = polygon[p][0]; - //console.log('polygon:',polygon); - //if (allowSelfIntersect == false && polygonSelfIntersect2(polygon) == false) return false; - - return polygon; -} -/*function reduceLineSegments(lines) { - var lines = clone(lines); - - // remove lines with zero length - for (var l = lines.length - 1; l >= 0; l--) { - if (pointsEqual(lines[l][0], lines[l][1])) lines.splice(l, 1); - } - - var gradients = []; - for (var l = 0; l < lines.length; l++) { - var line = lines[l]; - gradients[l] = (line[1][1] - line[0][1]) / (line[1][0] - line[0][0]); - } - - function pointsEqual(p1, p2) { - if (p1[0] == p2[0] && p1[1] == p2[1]) return true; - return false; - } - - // test for overlapping parallel lines - for (var a = 0; a < lines.length - 1; a++) { - var lineA = lines[a]; - for (var b = a + 1; b < lines.length; b++) { - var lineB = lines[b]; - if (gradients[a] !== gradients[b]) continue; - var test1 = isPointOnLineSegment(lineB[0], lineA[0], lineA[1]); - var test2 = isPointOnLineSegment(lineB[1], lineA[0], lineA[1]); - var test3 = (pointsEqual(lineA[0], lineB[0]) || pointsEqual(lineA[0], lineB[1]) || pointsEqual(lineA[1], lineB[0]) || pointsEqual(lineA[1], lineB[1])) ? true : false; - if (test1 == false && test2 == false && test3 == false) continue; - - // lines overlap - find most extreme of the 4 points - var pos = lineA.concat(lineB); - var min = pos[0]; - var max = pos[0]; - if (gradients[a] == Infinity || gradients[a] == -Infinity) { - for (var p = 1; p < pos.length; p++) { - if (pos[p][1] < min[1]) - min = pos[p]; - if (pos[p][1] > max[1]) - max = pos[p]; - } - } else { - for (var p = 1; p < pos.length; p++) { - if (pos[p][0] < min[0]) - min = pos[p]; - if (pos[p][0] > max[0]) - max = pos[p]; - } - } - lines[a] = [min, max]; - lines.splice(b, 1); - } - } - - return lines; -}*/ -function reduceLineSegments(lines) { - var keepGoing = true; - while (keepGoing === true) { - keepGoing = false; - for (var l1 = 0; l1 < lines.length-1; l1++) { - var line1 = lines[l1]; - for (var l2 = l1+1; l2 < lines.length; l2++) { - var line2 = lines[l2]; - var x1 = line1[0][0]; - var y1 = line1[0][1]; - var x2 = line1[1][0]; - var y2 = line1[1][1]; - var x3 = line2[0][0]; - var y3 = line2[0][1]; - var x4 = line2[1][0]; - var y4 = line2[1][1]; - - if ((x1 === x2 && x1 === x3 && x1 === x4) || (Math.abs((y2 - y1) / (x2 - x1) - (y4 - y3) / (x4 - x3))) < 0.01) { // vertical or gradients equal - // if one of the points is between the two points on the other line - if ((x1 >= Math.min(x3,x4) && x1 <= Math.max(x3,x4) && y1 >= Math.min(y3,y4) && y1 <= Math.max(y3,y4)) || - (x2 >= Math.min(x3,x4) && x2 <= Math.max(x3,x4) && y2 >= Math.min(y3,y4) && y2 <= Math.max(y3,y4)) || - (x3 >= Math.min(x1,x2) && x3 <= Math.max(x1,x2) && y3 >= Math.min(y1,y2) && y3 <= Math.max(y1,y2)) || - (x4 >= Math.min(x1,x2) && x4 <= Math.max(x1,x2) && y4 >= Math.min(y1,y2) && y4 <= Math.max(y1,y2))) { - var x5 = Math.min(x1,x2,x3,x4); - var x6 = Math.max(x1,x2,x3,x4); - var y5 = x5 === x6 ? Math.min(y1,y2,y3,y4) : x5 === x1 ? y1 : x5 === x2 ? y2 : x5 === x3 ? y3 : y4; - var y6 = x5 === x6 ? Math.max(y1,y2,y3,y4) : x6 === x1 ? y1 : x6 === x2 ? y2 : x6 === x3 ? y3 : y4; - lines[l1] = [[x5,y5],[x6,y6]]; - lines.splice(l2, 1); - l2--; - keepGoing = true; - } - } - } - } - } - return lines; -} -function polygonConvexTest(polygon) { - var polygon = clone(polygon); - if (polygonClockwiseTest(polygon) == false) - polygon.reverse(); - for (var p = 0; p < polygon.length; p++) { - var angle = measureAngle({ - a: polygon[p], - b: polygon[(p + 1) % polygon.length], - c: polygon[(p + 2) % polygon.length] - }); - if (angle > Math.PI) - return false; - } - return true; -} -function polygonClockwiseTest(pos) { - if (pos.length < 3) - return null; - var sum = (pos[0][0] - pos.last()[0]) * (pos[0][1] + pos.last()[1]); - for (var i = 0; i < pos.length - 1; i++) { - sum += (pos[i + 1][0] - pos[i][0]) * (pos[i + 1][1] + pos[i][1]); - } - if (sum > 0) - return true; - return false; -}; -function getPolygonSideLabelPoints(polygon, gap) { - if (un(gap)) - gap = 25; - var points = []; - for (var i = 0; i < polygon.length; i++) { - var j = (i + 1) % polygon.length; - var mid = [(polygon[i][0] + polygon[j][0]) / 2, (polygon[i][1] + polygon[j][1]) / 2]; - var vec = getVectorAB(polygon[i], polygon[j]); - var perp = getPerpVector(vec); - var perpDist = setVectorMag(perp, gap); - var point = pointAddVector(mid, perpDist); - points.push(point); - } - return points; -} -function drawRegularPolygon(obj) { - var ctx = obj.ctx; - var c = obj.center || obj.c; - var r = obj.radius || obj.r; - var p = obj.points || obj.p || 3; - var s = obj.step || obj.s || 1; - var startAngle = -Math.PI / 2; - if (typeof obj.startAngle == 'number') - startAngle = obj.startAngle; - var vertices = []; - for (var i = 0; i < p; i++) { - var angle = startAngle + i * (2 * Math.PI) / p; - vertices.push([c[0] + r * Math.cos(angle), c[1] + r * Math.sin(angle)]); - } - ctx.moveTo(vertices[0][0], vertices[0][1]); - for (var i = p; i >= 0; i--) { - ctx.lineTo(vertices[(i * s) % p][0], vertices[(i * s) % p][1]); - } -} -function drawRegularPolygonEllipse(ctx, obj) { - var c = obj.center; - var rX = obj.radiusX; - var rY = obj.radiusY; - var p = obj.points; - var s = obj.step || 1; - var startAngle = -Math.PI / 2; - if (typeof obj.startAngle == 'number') - startAngle = obj.startAngle; - - var vertices = []; - for (var i = 0; i < p; i++) { - var angle = startAngle + i * (2 * Math.PI) / p; - vertices.push([c[0] + rX * Math.cos(angle), c[1] + rY * Math.sin(angle), angle]); - } - - ctx.beginPath(); - ctx.moveTo(vertices[0][0], vertices[0][1]); - for (var i = p; i >= 0; i--) { - ctx.lineTo(vertices[(i * s) % p][0], vertices[(i * s) % p][1]); - } - ctx.stroke(); - - return vertices; -} -function polygonIntersections(p1, p2) { - var intersections = []; - for (var i = 0; i < p1.length; i++) { - var line1 = [p1[i], p1[(i + 1) % p1.length]]; - for (var j = 0; j < p2.length; j++) { - var line2 = [p2[j], p2[(j + 1) % p2.length]]; - if (lineSegmentsIntersectionTest(line1, line2)) { - intersections.push({ - edges: [i, j], - intersection: linesIntersection(line1, line2) - }); - } - } - } - if (intersections.length == 0) - return false; - return intersections -} -function isPolygonInPolygon(p1, p2, includePerimeter) { - if (hitTestPolygon2(p1[0], p2) == false) return false; - for (var i = 0; i < p1.length; i++) { - var line1 = [p1[i], p1[(i + 1) % p1.length]]; - for (var j = 0; j < p2.length; j++) { - var line2 = [p2[j], p2[(j + 1) % p2.length]]; - if (lineSegmentsIntersectionTest(line1, line2) == true) { - if (includePerimeter == false) return false; - var p3 = isPointOnLineSegment(line1[0],line2[0],line2[1]); - var p4 = isPointOnLineSegment(line1[1],line2[0],line2[1]); - if (p3 == false && p4 == false) return false; - if (p3 == true && p4 == true) continue; // edge is part of edge - if (p3 == true && p4 == false && hitTestPolygon2(line1[1],p2) == false) return false; - if (p3 == false && p4 == true && hitTestPolygon2(line1[0],p2) == false) return false; - } - } - } - return true; -} -function polygonsIntersectionPolygon(p1, p2) { - var p = []; // polygon of intersecting region - - // add all edge-edge intersections - for (var i = 0; i < p1.length; i++) { - var line1 = [p1[i], p1[(i + 1) % p1.length]]; - for (var j = 0; j < p2.length; j++) { - var line2 = [p2[j], p2[(j + 1) % p2.length]]; - if (lineSegmentsIntersectionTest(line1, line2)) { - p.push(linesIntersection(line1, line2)); - } - } - } - - // get all vertices of p1 that are inside p2 - for (var i = 0; i < p1.length; i++) { - if (hitTestPolygon(p1[i], p2, false)) - p.push(p1[i]); - } - - // get all vertices of p1 that are inside p2 - for (var i = 0; i < p2.length; i++) { - if (hitTestPolygon(p2[i], p1, false)) - p.push(p2[i]); - } - - // get centre of p - var center = [0, 0]; - for (var i = 0; i < p.length; i++) { - center[0] += p[i][0]; - center[1] += p[i][1]; - } - center[0] = center[0] / p.length; - center[1] = center[1] / p.length; - - // order p - p.sort(function (a, b) { - var a1 = getAngleFromAToB(center, a); - var a2 = getAngleFromAToB(center, b); - return a2 - a1; - }); - - console.log(p, polygonClockwiseTest(p)); - - return p; -} -function polygonArea(verticesArray) { - verticesArray.push(verticesArray[0]); - var area = 0; - for (var i = 0; i < verticesArray.length - 1; i++) { - area += (verticesArray[i][0] * verticesArray[i + 1][1]) - (verticesArray[i][1] * verticesArray[i + 1][0]); - } - area = 0.5 * Math.abs(area); - return area; -} -function polygonCountSides(verticesArray) { - // collapses polygon (ie. finds any three points that are on a straight line and reduces to single line) - // returns number of sides/vertices of collapsed polygon - var verticesNum = verticesArray.length - 1; // given number of vertices - if (verticesNum < 3) - return verticesNum; - verticesArray.push(verticesArray[0]); - verticesArray.push(verticesArray[1]); - var verticesCount = 0; // return number of vertices - for (var i = 0; i <= verticesNum; i++) { - var point1 = verticesArray[i]; - var point2 = verticesArray[i + 1]; - var point3 = verticesArray[i + 2]; - var m1 = (point2[1] - point1[1]) / (point2[0] - point1[0]); - var m2 = (point3[1] - point2[1]) / (point3[0] - point2[0]); - var error = false; - if (point1[0] == point2[0] && point1[1] == point2[1]) - error = true; - if (point1[0] == point3[0] && point1[1] == point3[1]) - error = true; - if (point3[0] == point2[0] && point3[1] == point2[1]) - error = true; - if (m1 !== m2 && error == false) - verticesCount++; - } - verticesArray.splice(-2, 2); - logMe("verticesArray:", verticesArray, "polygon"); - return verticesCount; -} -function polygonSelfIntersect(verticesArray) { - // vertices array such as [[], [], [], []] - verticesArray = clone(verticesArray); - verticesArray.push(verticesArray[0]); // duplicate first vertex to last vertex - var segmentArray = []; - var events = []; - - // create segments array [[x1,y1,x2,y2],[...],...] where x1 <= x2 - for (var i = 0; i < verticesArray.length - 1; i++) { - segmentArray.push([verticesArray[i][0], verticesArray[i][1], verticesArray[i + 1][0], verticesArray[i + 1][1]]); - - // choose left-most end of segment to be 'start' - var order; - if (verticesArray[i][0] < verticesArray[i + 1][0]) { - order = 1; - } else if (verticesArray[i][0] > verticesArray[i + 1][0]) { - order = 2; - } else { - if (verticesArray[i][1] < verticesArray[i + 1][1]) { - order = 1; - } else { - order = 2; - } - } - - if (order == 1) { - events.push([verticesArray[i][0], verticesArray[i][1], i, 'start']); - events.push([verticesArray[i + 1][0], verticesArray[i + 1][1], i, 'end']); - } else { - events.push([verticesArray[i][0], verticesArray[i][1], i, 'end']); - events.push([verticesArray[i + 1][0], verticesArray[i + 1][1], i, 'start']); - } - } - - // sort the events by x value - events.sort(function (a, b) { - return a[0] - b[0] - }); - - var sweepLine = []; - - for (var j = 0; j < events.length; j++) { - if (events[j][3] == 'start') { - sweepLine.push([events[j][0], events[j][1], events[j][2]]); // x-value, y-value, lineSegmentId - sweepLine.sort(function (a, b) { - return a[1] - b[1] - }); // sort sweepLine by y-value - } else if (events[j][3] == 'end') { - // get position in sweepline (pos1) and segment id (seg1) - var pos1, - seg1; - for (var k = 0; k < sweepLine.length; k++) { - if (sweepLine[k][2] == events[j][2]) { - pos1 = k; - seg1 = segmentArray[k]; - break; - } - } - // if not the lowest line, check for intersection with line below - if (pos1 > 0) { - var pos2 = sweepLine[pos1 - 1][2]; - var seg2 = segmentArray[pos2]; - if (intersects(seg1[0], seg1[1], seg1[2], seg1[3], seg2[0], seg2[1], seg2[2], seg2[3]) == true) - return true; - } - if (pos1 < sweepLine.length - 1) { - var pos2 = sweepLine[pos1 + 1][2]; - var seg2 = segmentArray[pos2]; - if (intersects(seg1[0], seg1[1], seg1[2], seg1[3], seg2[0], seg2[1], seg2[2], seg2[3]) == true) - return true; - } - } - } - - return false; -} -function polygonSelfIntersect2(polygon) { - var edges = []; - for (var i = 0; i < polygon.length; i++) - edges.push([polygon[i], polygon[(i + 1) % polygon.length]]); - for (var i = 0; i < edges.length - 1; i++) { - for (var j = i + 1; j < edges.length; j++) { - if ( - arraysEqual(edges[i][0], edges[j][0]) || - arraysEqual(edges[i][0], edges[j][1]) || - arraysEqual(edges[i][1], edges[j][0]) || - arraysEqual(edges[i][1], edges[j][1])) { - continue; - } - if (intersects(edges[i][0][0], edges[i][0][1], edges[i][1][0], edges[i][1][1], edges[j][0][0], edges[j][0][1], edges[j][1][0], edges[j][1][1]) == true) { - return true; - } - } - } - return false; -} -function findMinPolygon(edgeVertices, lines, point) { - var edges = []; - var lines2 = []; - - edgeVertices.push(edgeVertices[0].slice()); - // split edges into smaller vectors according to intersection points with lines - for (var i = 0; i < edgeVertices.length - 1; i++) { - edges[i] = [{ - point: edgeVertices[i].slice(0), - dist: 0 - }, { - point: edgeVertices[i + 1].slice(0), - dist: dist(edgeVertices[i][0], edgeVertices[i][1], edgeVertices[i + 1][0], edgeVertices[i + 1][1]) - } - ]; - for (var j = 0; j < lines.length; j++) { - //console.log('edgeVertices:',edgeVertices[i][0],edgeVertices[i][1],edgeVertices[i+1][0],edgeVertices[i+1][1]); - // console.log('lineVertices:',lines[j][0][0],lines[j][0][1],lines[j][1][0],lines[j][1][1]); - // console.log('intersects2:',intersects2(lines[j][0][0],lines[j][0][1],lines[j][1][0],lines[j][1][1],edgeVertices[i][0],edgeVertices[i][1],edgeVertices[i+1][0],edgeVertices[i+1][1])); - if (intersects2(lines[j][0][0], lines[j][0][1], lines[j][1][0], lines[j][1][1], edgeVertices[i][0], edgeVertices[i][1], edgeVertices[i + 1][0], edgeVertices[i + 1][1])) { - - var int = intersection(edgeVertices[i][0], edgeVertices[i][1], edgeVertices[i + 1][0], edgeVertices[i + 1][1], lines[j][0][0], lines[j][0][1], lines[j][1][0], lines[j][1][1]); - - // check that the intersection point is not one of the end points of the edge - if ((int[0] == edgeVertices[i][0] && int[1] == edgeVertices[i][1]) || (int[0] == edgeVertices[i + 1][0] && int[1] == edgeVertices[i + 1][1])) { - //console.log('corner'); - } else { - edges[i].push({ - point: int, - dist: dist(edges[i][0].point[0], edges[i][0].point[1], int[0], int[1]) - }); - } - - if (typeof lines2[j] == 'undefined') { - lines2[j] = [{ - point: int.slice(0), - dist: 0 - } - ]; - } else { - lines2[j].push({ - point: int.slice(0), - dist: dist(int[0], int[1], lines2[j][0].point[0], lines2[j][0].point[1]) - }); - } - - } - } - } - for (var i = 0; i < lines.length - 1; i++) { - for (var j = i + 1; j < lines.length; j++) { - var int = intersection(lines[i][0][0], lines[i][0][1], lines[i][1][0], lines[i][1][1], lines[j][0][0], lines[j][0][1], lines[j][1][0], lines[j][1][1]); - if (hitTestPolygon(int, edgeVertices)) { - lines2[i].push({ - point: int.slice(0), - dist: dist(int[0], int[1], lines2[i][0].point[0], lines2[i][0].point[1]) - }); - lines2[j].push({ - point: int.slice(0), - dist: dist(int[0], int[1], lines2[j][0].point[0], lines2[j][0].point[1]) - }); - } - } - } - - for (var i = 0; i < edges.length; i++) { - edges[i].sortOn('dist'); - } - for (var i = 0; i < lines2.length; i++) { - lines2[i].sortOn('dist'); - } - - //console.log('edges:',edges.slice(0)); - //console.log('lines2:',lines2.slice(0)); - - // find duplicate points in lines2 and remove - for (var i = 0; i < lines2.length; i++) { - for (var j = 1; j < lines2[i].length; ) { - if (lines2[i][j - 1].dist == lines2[i][j].dist) { - lines2[i].splice(j, 1); - } else { - j++; - } - } - } - - var vectors = []; - - for (var i = 0; i < edges.length; i++) { - for (var j = 0; j < edges[i].length - 1; j++) { - vectors.push([edges[i][j].point.slice(0), edges[i][j + 1].point.slice(0)]); - } - } - - for (var i = 0; i < lines2.length; i++) { - for (var j = 0; j < lines2[i].length - 1; j++) { - vectors.push([lines2[i][j].point.slice(0), lines2[i][j + 1].point.slice(0)]); - } - } - - //console.log('vectors:',vectors.slice(0)); - //console.log('point:',point); - - var minDist = []; - // work out whish vector is closest to the point - for (var i = 0; i < vectors.length; i++) { - minDist[i] = distancePointToLineSegment(point, vectors[i][0], vectors[i][1]); - } - //console.log('minDist:',minDist); - - // start the polygon vertices array - var vertices = []; - var currVector = vectors[minDist.indexOf(minDist.min())]; - - // put the closest vector vertices into the array - if (measureAngle({ - a: point, - b: currVector[0], - c: currVector[1] - }) < measureAngle({ - a: point, - b: currVector[1], - c: currVector[0] - })) { - vertices.push(currVector[0].slice(0), currVector[1].slice(0)); - } else { - vertices.push(currVector[1].slice(0), currVector[0].slice(0)); - } - vectors.splice(minDist.indexOf(minDist.min()), 1); - //console.log('first vertices:',vertices[0],vertices[1]); - - // until the path is completed - do { - var currPoint = vertices[vertices.length - 1].slice(0); - // find all poss vectors from the current point - var possVectors = []; - var possVectorsAngle = []; - var possVectorsIndex = []; - for (var i = 0; i < vectors.length; i++) { - if (arraysEqual(vectors[i][0], currPoint)) { - //console.log('---possVector:',vectors[i].slice(0)); - possVectors.push(vectors[i].slice(0)); - possVectorsIndex.push(i); - possVectorsAngle.push(measureAngle({ - a: vertices[vertices.length - 2], - b: vertices[vertices.length - 1], - c: vectors[i][1] - })); - //console.log('angle:',measureAngle({a:vertices[vertices.length-2],b:vertices[vertices.length-1],c:vectors[i][1]})); - } else if (arraysEqual(vectors[i][1], currPoint)) { - //console.log('+++possVector:',[vectors[i][1].slice(0),vectors[i][0].slice(0)]); - possVectors.push([vectors[i][1].slice(0), vectors[i][0].slice(0)]); - possVectorsIndex.push(i); - possVectorsAngle.push(measureAngle({ - a: vertices[vertices.length - 2], - b: vertices[vertices.length - 1], - c: vectors[i][0] - })); - //console.log('angle:',measureAngle({a:vertices[vertices.length-2],b:vertices[vertices.length-1],c:vectors[i][0]})); - } - } - //console.log('possVectors:',possVectors); - //console.log('possVectorsAngle:',possVectorsAngle); - //console.log('possVectorsIndex:',possVectorsIndex); - // chose the vector with the smallest angle - var selVectorPos = possVectorsAngle.indexOf(possVectorsAngle.min()); - vertices.push(possVectors[selVectorPos][1].slice(0)); - selVectorPos = possVectorsIndex[selVectorPos]; - vectors.splice(selVectorPos, 1); - - //console.log('vertex:',vertices[vertices.length-1]); - } while (arraysEqual(vertices[0], vertices[vertices.length - 1]) == false); - - //console.log('vertices:',vertices); - - return vertices; -} -function samePolygons(verticesArray1, verticesArray2) { - var a = verticesArray1; - var b = verticesArray2; - if (a.length !== b.length) - return false; - for (var i = 0; i < a.length; i++) { - var found = false; - for (var j = 0; j < b.length; j++) { - if (roundToNearest(a[i][0], 0.0001) == roundToNearest(b[j][0], 0.0001) && roundToNearest(a[i][1], 0.0001) == roundToNearest(b[j][1], 0.0001)) { - found = true; - break; - } - } - if (found == false) - return false; - } - return true; -} -function polygonCongruenceTest(p1, p2, mode) { // mode 0 = any congruent shape, 1 = rotations allowed but not reflections, 2 = no rotations or reflectons allowed - if (typeof mode == 'undefined') - mode = 0 - if (p1.length !== p2.length) - return false; - var p1 = clone(p1); - var p2 = clone(p2); - if (polygonClockwiseTest(p1) == false) - p1.reverse(); - if (polygonClockwiseTest(p2) == false) - p2.reverse(); - if (mode == 2) { // test edge vectors are congruent - var vectors1 = [], - vectors2 = []; - for (var p = 0; p < p1.length; p++) { - var b = p1[p]; - var c = p == p1.length - 1 ? p1[0] : p1[p + 1]; - vectors1[p] = [c[0] - b[0], c[1] - b[1]]; - var b = p2[p]; - var c = p == p2.length - 1 ? p2[0] : p2[p + 1]; - vectors2[p] = [c[0] - b[0], c[1] - b[1]]; - } - //console.log(vectors1,vectors2); - - for (var p = 0; p < p1.length; p++) { - if (arraysEqual(vectors1[0], vectors2[p])) { - //console.log(p,vectors1[0],vectors2[p]); - var match = true; - for (var q = 1; q < p2.length; q++) { - var r = (p + q) % p2.length; - //console.log(q,vectors1[q],vectors2[r]); - if (arraysEqual(vectors1[q], vectors2[r]) == false) { - match = false; - break; - } - } - if (match == true) - return true; - } - } - return false; - } else { // test edge lengths and angles are congruent - var lengths1 = [], - lengths2 = []; - var angles1 = [], - angles2 = []; - for (var p = 0; p < p1.length; p++) { - var a = p == 0 ? p1.last() : p1[p - 1]; - var b = p1[p]; - var c = p == p1.length - 1 ? p1[0] : p1[p + 1]; - lengths1[p] = dist(b[0], b[1], c[0], c[1]); - angles1[p] = measureAngle({ - a: a, - b: b, - c: c - }); - } - for (var p = 0; p < p2.length; p++) { - var a = p == 0 ? p2.last() : p2[p - 1]; - var b = p2[p]; - var c = p == p2.length - 1 ? p2[0] : p2[p + 1]; - lengths2[p] = dist(b[0], b[1], c[0], c[1]); - angles2[p] = measureAngle({ - a: a, - b: b, - c: c - }); - } - - for (var p = 0; p < p1.length; p++) { - if (Math.abs(lengths1[0] - lengths2[p]) < 0.001 && Math.abs(angles1[0] - angles2[p]) < 0.001) { - var match = true; - for (var q = 1; q < p2.length; q++) { - var r = (p + q) % p2.length; - if (Math.abs(lengths1[q] - lengths2[r]) > 0.001 || Math.abs(angles1[q] - angles2[r]) > 0.001) { - match = false; - break; - } - } - if (match == true) - return true; - if (mode == 0) { // check for a match in reverse vertices direction ie. a reflection - for (var q = 1; q < p2.length; q++) { - var r = p - q; - if (r < 0) - r = p2.length + r; - if (Math.abs(lengths1[q] - lengths2[r]) > 0.001 || Math.abs(angles1[q] - angles2[r]) > 0.001) { - match = false; - break; - } - } - if (match == true) - return true; - } - } - } - return false; - } -} -function polygonGetCenter(polygon) { - var totals = [0,0]; - for (var p = 0; p < polygon.length; p++) { - totals[0] += polygon[p][0]; - totals[1] += polygon[p][1]; - if (polygon[p].length == 3) { - if (un(totals[2])) totals[2] = 0; - totals[2] += polygon[p][2]; - } - } - for (var t = 0; t < totals.length; t++) { - totals[t] /= polygon.length; - } - return totals; -} - -function lineSegmentsIntersectionTest(line1, line2) { - return intersects(line1[0][0], line1[0][1], line1[1][0], line1[1][1], line2[0][0], line2[0][1], line2[1][0], line2[1][1]); -} -function linesIntersection(line1, line2) { - return intersection(line1[0][0], line1[0][1], line1[1][0], line1[1][1], line2[0][0], line2[0][1], line2[1][0], line2[1][1]); -} -function intersects(a, b, c, d, p, q, r, s) { - // returns true iff the line segemnt from (a,b)->(c,d) intersects with the line segment from (p,q)->(r,s) - var det, - gamma, - lambda; - det = (c - a) * (s - q) - (r - p) * (d - b); - if (det === 0) { - return false; - } else { - lambda = ((s - q) * (r - a) + (p - r) * (s - b)) / det; - gamma = ((b - d) * (r - a) + (c - a) * (s - b)) / det; - return (0 < lambda && lambda < 1) && (0 < gamma && gamma < 1); - } -}; -function intersects2(a, b, c, d, p, q, r, s) { - // returns true iff the infinite line though (a,b) & (c,d) intersects with line segment (p,q)->(r,s) - var int = intersection(a, b, c, d, p, q, r, s); - return isPointOnLineSegment(int, [p, q], [r, s]); -}; -function intersection(aX, aY, bX, bY, cX, cY, dX, dY) { // finds and returns the intersection point of the lines AB and CD - if (aX instanceof Array) { - var a = aX, b = aY, c = bX, d = bY; - aX = a[0]; - aY = a[1]; - bX = b[0]; - bY = b[1]; - cX = c[0]; - cY = c[1]; - dX = d[0]; - dY = d[1]; - } - if (aX !== bX && cX !== dX) { - var m1 = (bY - aY) / (bX - aX); // gradient of AB; - var m2 = (dY - cY) / (dX - cX); // gradient of CD; - if (m1 == m2) - return 'parallel'; - var xIntersection = ((aY - aX * m1) - (cY - cX * m2)) / (m2 - m1); - var yIntersection = aY + m1 * (xIntersection - aX); - return [xIntersection, yIntersection]; - } else if (aX == bX && cX == dX) { - return 'parallel'; - } else if (aX == bX) { - // if AB is vertical - var m2 = (dY - cY) / (dX - cX); // gradient of CD; - var xIntersection = aX; - var yIntersection = cY + m2 * (xIntersection - cX); - return [xIntersection, yIntersection]; - } else if (cX == dX) { - // if CD is vertical - var m1 = (bY - aY) / (bX - aX); // gradient of AB; - var xIntersection = cX; - var yIntersection = aY + m1 * (xIntersection - aX); - return [xIntersection, yIntersection]; - } -} -function dist(x1, y1, x2, y2) { - if (x1 instanceof Array && y1 instanceof Array) return (dist(x1[0],x1[1],y1[0],y1[1])); - return Math.pow(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2), 0.5); -} -function midpoint(x1, y1, x2, y2) { - return [0.5 * (x1 + x2), 0.5 * (y1 + y2)]; -} -function collapsePath(path) { - var path1 = path.slice(0); - - do { - var joinFound = false; - for (var i = path1.length - 1; i >= 0; i--) { - if (joinFound == false) { - for (var j = i - 1; j >= 0; j--) { - if (path1[i].obj[0].type == path1[j].obj[0].type) { - if (path1[i].type == 'pen') {} - else if (path1[i].obj[0].type == 'line') { - var x1 = path1[i].obj[0].startPos[0]; - var y1 = path1[i].obj[0].startPos[1]; - var x2 = path1[i].obj[0].finPos[0]; - var y2 = path1[i].obj[0].finPos[1]; - var x3 = path1[j].obj[0].startPos[0]; - var y3 = path1[j].obj[0].startPos[1]; - var x4 = path1[j].obj[0].finPos[0]; - var y4 = path1[j].obj[0].finPos[1]; - var m1 = (y2 - y1) / (x2 - x1); - var m2 = (y4 - y3) / (x4 - x3); - if (Math.abs(m1) > Math.abs(m2)) { - var mMax = m1; - var mMin = m2; - } else { - var mMax = m2; - var mMin = m1; - } - // if gradients are equal and point from line 1 is on line 2 - //console.log('grad/grad: ',mMax/mMin); - //console.log('pointOnLine: ',isPointOnLine([x1,y1],[x3,y3],[x4,y4],3.5)); - if (((mMin >= 0 && mMax >= 0) || (mMin < 0 && mMax < 0)) && Math.abs(mMax / mMin) < 1.1 && isPointOnLine([x1, y1], [x3, y3], [x4, y4], 3.5) == true) { - // if one of the points is between the two points on the other line - if ((x1 >= Math.min(x3, x4) && x1 <= Math.max(x3, x4) && y1 >= Math.min(y3, y4) && y1 <= Math.max(y3, y4)) || (x2 >= Math.min(x3, x4) && x2 <= Math.max(x3, x4) && y2 >= Math.min(y3, y4) && y2 <= Math.max(y3, y4)) || (x3 >= Math.min(x1, x2) && x3 <= Math.max(x1, x2) && y3 >= Math.min(y1, y2) && y3 <= Math.max(y1, y2)) || (x4 >= Math.min(x1, x2) && x4 <= Math.max(x1, x2) && y4 >= Math.min(y1, y2) && y4 <= Math.max(y1, y2))) { - var xMin = Math.min(x1, x2, x3, x4); - var xMax = Math.max(x1, x2, x3, x4); - if (xMin == x1) - var yMin = y1; - if (xMin == x2) - var yMin = y2; - if (xMin == x3) - var yMin = y3; - if (xMin == x4) - var yMin = y4; - if (xMax == x1) - var yMax = y1; - if (xMax == x2) - var yMax = y2; - if (xMax == x3) - var yMax = y3; - if (xMax == x4) - var yMax = y4; - joinFound = true; - path1[i].startPos = [xMin, yMin]; - path1[i].finPos = [xMax, yMax]; - path1.splice(j, 1); - break; - } - } - } else if (path1[i].obj[0].type == 'arc') { - if (Math.abs(path1[i].obj[0].center[0] - path1[j].obj[0].center[0]) < 2 && Math.abs(path1[i].obj[0].center[1] - path1[j].obj[0].center[1]) < 2 && Math.abs(path1[i].obj[0].radius - path1[j].obj[0].radius) < 2) { - if ((path1[i].obj[0].startAngle >= path1[j].obj[0].startAngle && path1[i].obj[0].startAngle <= path1[j].obj[0].finAngle) || - /* if min angle of first is between min & max angle of second*/ - (path1[i].obj[0].finAngle >= path1[j].obj[0].startAngle && path1[i].obj[0].finAngle <= path1[j].obj[0].finAngle) || - /* if max angle of first is between min & max angle of second*/ - (path1[j].obj[0].startAngle >= path1[i].obj[0].startAngle && path1[j].obj[0].startAngle <= path1[i].obj[0].finAngle) || - /* if min angle of second is between min & max angle of first*/ - (path1[j].obj[0].finAngle >= path1[i].obj[0].startAngle && path1[j].obj[0].finAngle <= path1[i].obj[0].finAngle) || - /* if max angle of second is between min & max angle of first*/ - (path1[i].obj[0].startAngle <= path1[j].obj[0].startAngle && path1[i].obj[0].finAngle >= path1[j].obj[0].finAngle) || - /* if second is contained within first*/ - (path1[j].obj[0].startAngle <= path1[i].obj[0].startAngle && path1[j].obj[0].finAngle >= path1[i].obj[0].finAngle)) - /* if first is contained within second*/ - { - joinFound = true; - path1[i].obj[0].startAngle = Math.min(path1[i].obj[0].startAngle, path1[j].obj[0].startAngle); - path1[i].obj[0].finAngle = Math.max(path1[i].obj[0].finAngle, path1[j].obj[0].finAngle); - path1.splice(j, 1); - break; - } - } - } - } - } - } - } - } while (joinFound == true); - - return path1; -} -function getIntersectionPoints(path) { - // currently only handles line/line, line/arc and arc/arc intersections - var intPoints = []; - for (var i = 0; i < path.length; i++) { - if (typeof path[i].obj == 'undefined') - continue; - for (var j = 0; j < path[i].obj.length; j++) { - var obj1 = path[i].obj[j]; - if (obj1.drawing == true) - continue; - for (var k = i; k < path.length; k++) { - for (var l = 0; l < path[k].obj.length; l++) { - if (i == k && j == l) - continue; - var obj2 = path[k].obj[l]; - if (obj2.drawing == true) - continue; - if (obj1.type == 'line' && obj2.type == 'line') { - var int = intersection(obj1.startPos[0], obj1.startPos[1], obj1.finPos[0], obj1.finPos[1], obj2.startPos[0], obj2.startPos[1], obj2.finPos[0], obj2.finPos[1]); - if (isPointOnLineSegment(int, obj1.startPos, obj1.finPos) == true) - intPoints.push(int); - } else if (obj1.type == 'line' && obj2.type == 'arc') { - var int = lineCircleIntersections(obj1.startPos, obj1.finPos, obj2.center, obj2.radius); - for (var m = 0; m < int.length; m++) { - if (isPointOnLineSegment(int[m], obj1.startPos, obj1.finPos) == true && isAngleInPath(obj2, obj2.center, obj2.radius, int[m][2], 1) == true) - intPoints.push(int[m]); - } - } else if (obj1.type == 'arc' && obj2.type == 'line') { - var int = lineCircleIntersections(obj2.startPos, obj2.finPos, obj1.center, obj1.radius); - for (var m = 0; m < int.length; m++) { - if (isPointOnLineSegment(int[m], obj2.startPos, obj2.finPos) == true && isAngleInPath(obj1, obj1.center, obj1.radius, int[m][2], 1) == true) - intPoints.push(int[m]); - } - } else if (obj1.type == 'arc' && obj2.type == 'arc') { - var int = circleIntersections(obj1.center[0], obj1.center[1], obj1.radius, obj2.center[0], obj2.center[1], obj2.radius); - for (var m = 0; m < int.length; m++) { - var a = isPointOnArc(int[m], obj1); - var b = isPointOnArc(int[m], obj2); - if (a == true && b == true) - intPoints.push(int[m]); - } - } - } - } - } - } - return intPoints; -} -function getEndPoints(path) { - // currently only handles pen, line and arc paths - var endPoints = []; - for (var i = 0; i < path.length; i++) { - if (typeof path[i].obj == 'undefined') - continue; - for (var j = 0; j < path[i].obj.length; j++) { - if (path[i].obj[j].drawing == true) - continue; - switch (path[i].obj[j].type) { - case 'line': - endPoints.push(path[i].obj[j].startPos, path[i].obj[j].finPos); - break; - case 'arc': - var arcEnds = getEndPointsOfArc(path[i].obj[j]); - for (var k = 0; k < arcEnds.length; k++) { - endPoints.push(arcEnds[k]); - } - break; - } - } - } - return endPoints; -} -function isAngleInPath(arcPath, center, radius, angle, tolerance) { - if (dist(arcPath.center[0], arcPath.center[1], center[0], center[1]) > tolerance) - return false; - if (Math.abs(arcPath.radius - radius) > tolerance) - return false; - var startAngle = arcPath.startAngle; - var finAngle = arcPath.finAngle; - if (arcPath.clockwise == true) { - if (startAngle < angle && finAngle > angle) - return true; - if (startAngle + 2 * Math.PI < angle && finAngle + 2 * Math.PI > angle) - return true; - if (startAngle - 2 * Math.PI < angle && finAngle - 2 * Math.PI > angle) - return true; - } else { - if (startAngle < finAngle) - startAngle += 2 * Math.PI; - if (startAngle > angle && finAngle < angle) - return true; - if (startAngle + 2 * Math.PI > angle && finAngle + 2 * Math.PI < angle) - return true; - if (startAngle - 2 * Math.PI > angle && finAngle - 2 * Math.PI < angle) - return true; - } - return false; -} -function doesArcIncludeAngle(arc, angle) { - while (angle < 0) { - angle += 2 * Math.PI; - } - angle = angle % (2 * Math.PI); - if (arc.clockwise == false) { - if (arc.finAngle > arc.startAngle) { - if (angle <= arc.startAngle || angle >= arc.finAngle) - return true; - } else { - if (angle >= arc.finAngle && angle <= arc.startAngle) - return true; - } - } else { - if (arc.finAngle > arc.startAngle) { - if (angle >= arc.startAngle || angle <= arc.finAngle) - return true; - } else { - if (angle <= arc.finAngle && angle >= arc.startAngle) - return true; - } - } - return false; -} -function distancePointToPath(point, path) { - if (path.length > 1) { - var closestDist = distancePointToLineSegment(point, path[0], path[1]); - for (var i = 1; i < path.length - 1; i++) { - closestDist = Math.min(closestDist, distancePointToLineSegment(point, path[i], path[i + 1])); - } - return closestDist; - } else if (path.length == 1) { - return dist(point[0], point[1], path[0][0], path[0][1]); - } else { - return 100000000000; - } - -} -function isPointOnLine(point, linePos1, linePos2, tolerance) { - if (un(tolerance)) - tolerance = 0.001; - var closestPos = closestPointOnLine(point, linePos1, linePos2); - var distance = dist(closestPos[0], closestPos[1], point[0], point[1]); - if (distance <= tolerance) - return true; - return false; -} -function closestPointOnLine(point, linePos1, linePos2) { - var dirVector = [linePos2[0] - linePos1[0], linePos2[1] - linePos1[1]]; - var lambda = ((point[0] - linePos1[0]) * dirVector[0] + (point[1] - linePos1[1]) * dirVector[1]) / (Math.pow(dirVector[0], 2) + Math.pow(dirVector[1], 2)); - return [linePos1[0] + lambda * dirVector[0], linePos1[1] + lambda * dirVector[1]]; -} -function distancePointToLine(point, linePos1, linePos2) { - var closest = closestPointOnLine(point, linePos1, linePos2); - return dist(point[0], point[1], closest[0], closest[1]); -} -function closestPointOnLineSegment(point, linePos1, linePos2) { - var dirVector = [linePos2[0] - linePos1[0], linePos2[1] - linePos1[1]]; - var lambda = ((point[0] - linePos1[0]) * dirVector[0] + (point[1] - linePos1[1]) * dirVector[1]) / (Math.pow(dirVector[0], 2) + Math.pow(dirVector[1], 2)); - if (lambda <= 0) { - return linePos1; - } else if (lambda >= 1) { - return linePos2; - } else { - return [linePos1[0] + lambda * dirVector[0], linePos1[1] + lambda * dirVector[1]]; - } -} -function distancePointToLineSegment(point, linePos1, linePos2) { - var closest = closestPointOnLineSegment(point, linePos1, linePos2); - return dist(point[0], point[1], closest[0], closest[1]); -} -function checkPathForLine(path, x1, y1, isEnd1, x2, y2, isEnd2, tolerance) { - for (var i = 0; i < path.length; i++) { - for (var k = 0; k < path[i].obj.length; k++) { - if (path[i].obj[k].type == 'line' && lineCheck(x1, y1, isEnd1, x2, y2, isEnd2, tolerance, path[i].obj[k].startPos[0], path[i].obj[k].startPos[1], path[i].obj[k].finPos[0], path[i].obj[k].finPos[1]) == true) - return true; - } - } - return false; -} -function isPointOnLineSegment(point, linePos1, linePos2, tolerance) { - if (un(tolerance)) tolerance = 0.001; - return distancePointToLineSegment(point, linePos1, linePos2) < tolerance; -} -/*function isPointOnLineSegment(point,linePos1,linePos2) { -var dirVector = [linePos2[0]-linePos1[0],linePos2[1]-linePos1[1]]; -var lambda = ((point[0]-linePos1[0])*dirVector[0]+(point[1]-linePos1[1])*dirVector[1])/(Math.pow(dirVector[0],2)+Math.pow(dirVector[1],2)); -if (lambda >= 0 && lambda <= 1) { -return true; -} else { -return false; -} -}*/ -function isPointInSector(point, dims) { - if (dist(point[0], point[1], dims[0], dims[1]) > dims[2]) - return false; - var a1 = dims[3]; - var a2 = getAngleTwoPoints([dims[0], dims[1]], point); - var a3 = dims[4]; - return anglesInOrder(a1, a2, a3); -} - -function sameLine(line1, line2) { - return (isPointOnLine(line1[0], line2[0], line2[1], 0) && isPointOnLine(line1[1], line2[0], line2[1], 0)); -} - -function lineCheck(x1, y1, isEnd1, x2, y2, isEnd2, tolerance, xTest1, yTest1, xTest2, yTest2) { - //console.log(x1,y1,isEnd1,x2,y2,isEnd2,tolerance,xTest1,yTest1,xTest2,yTest2); - // if points should be ends of the line, test if they are - if (isEnd1 == true && dist(x1, y1, xTest1, yTest1) > tolerance && dist(x1, y1, xTest2, yTest2) > tolerance) { - return false; - } - if (isEnd2 == true && dist(x2, y2, xTest1, yTest1) > tolerance && dist(x2, y2, xTest2, yTest2) > tolerance) { - return false; - } - // test if the points are on the line, with the given tolerance - if (isPointOnLine([x1, y1], [xTest1, yTest1], [xTest2, yTest2], tolerance) == false || isPointOnLine([x2, y2], [xTest1, yTest1], [xTest2, yTest2], tolerance) == false) { - return false; - } - // test if the line has been drawn far enough - var mag = dist(x1, y1, x2, y2); - var minPos1 = [x1 + 2 * tolerance / mag * (x2 - x1), y1 + 2 * tolerance / mag * (y2 - y1)]; - var minPos2 = [x2 + 2 * tolerance / mag * (x1 - x2), y2 + 2 * tolerance / mag * (y1 - y2)]; - - /* - console.log('pos1:'+x1+','+y1); - console.log('pos2:'+x2+','+y2); - console.log('minPos1:'+minPos1[0]+','+minPos1[1]); - console.log('minPos2:'+minPos2[0]+','+minPos2[1]); - console.log('testPos1:'+xTest1+','+yTest1); - console.log('testPos2:'+xTest2+','+yTest2); - console.log('dist to min pos, dist to actual pos:'); - console.log('pos1,testPos1:',dist(minPos1[0],minPos1[1],xTest1,yTest1),dist(x1,y1,xTest1,yTest1),dist(minPos1[0],minPos1[1],xTest1,yTest1)>dist(x1,y1,xTest1,yTest1)); - console.log('pos2,testPos2:',dist(minPos2[0],minPos2[1],xTest2,yTest2),dist(x2,y2,xTest2,yTest2),dist(minPos2[0],minPos2[1],xTest2,yTest2)>dist(x2,y2,xTest2,yTest2)); - console.log('pos1,testPos2:',dist(minPos1[0],minPos1[1],xTest2,yTest2),dist(x1,y1,xTest2,yTest2),dist(minPos1[0],minPos1[1],xTest2,yTest2)>dist(x1,y1,xTest2,yTest2)); - console.log('pos2,testPos1:',dist(minPos2[0],minPos2[1],xTest1,yTest1),dist(x2,y2,xTest1,yTest1),dist(minPos2[0],minPos2[1],xTest1,yTest1)>dist(x2,y2,xTest1,yTest1)); - //*/ - - // if both points are closer to minPos than to either of the actual points - if ((dist(minPos1[0], minPos1[1], xTest1, yTest1) > dist(x1, y1, xTest1, yTest1) - && dist(minPos1[0], minPos1[1], xTest2, yTest2) > dist(x1, y1, xTest2, yTest2)) - - || (dist(minPos2[0], minPos2[1], xTest1, yTest1) > dist(x2, y2, xTest1, yTest1) - && dist(minPos2[0], minPos2[1], xTest2, yTest2) > dist(x2, y2, xTest2, yTest2))) { - return false; - } - return true; -} -function getAngleTwoPoints(pos1, pos2) { // returns the angle in rad from pos1 to pos2 - var m = (pos2[1] - pos1[1]) / (pos2[0] - pos1[0]); - var a = Math.atan(m); - if (pos1[1] == pos2[1]) { // horizontal - if (pos1[0] < pos2[0]) { - return 0; - } else { - return Math.PI; - } - } - if (pos1[0] == pos2[0]) { // vertical - if (pos1[1] < pos2[1]) { - return Math.PI / 2; - } else { - return 3 * Math.PI / 2; - } - } - if (m > 0) { - if (pos2[0] > pos1[0]) { - return a; - } else { - return a + Math.PI; - } - } else { - if (pos2[0] > pos1[0]) { - return a; - } else { - return a + Math.PI; - } - } -} -function interpolateTwoPoints(pos1, pos2, proportion) { - if (typeof proportion == 'undefined') - proportion = 0.5; - return [pos1[0] + proportion * (pos2[0] - pos1[0]), pos1[1] + proportion * (pos2[1] - pos1[1])]; -} -function angleToPos(angle, centerX, centerY, radius, opt_angleType) { - if (opt_angleType == 'degrees') - angle = angle * Math.PI / 180; - return [centerX + Math.cos(angle) * radius, centerY - Math.sin(angle) * radius]; -} -function posToAngle(posX, posY, centerX, centerY, radius) { - if (un(radius)) - radius = dist(posX, posY, centerX, centerY); - var cosTheta = (posX - centerX) / radius; - var sinTheta = (posY - centerY) / radius; - if (sinTheta >= 0) - return Math.acos(cosTheta); - if (sinTheta < 0) - return 2 * Math.PI - Math.acos(cosTheta); -} -function extendLine(pos1, pos2, extLength) { - var m = (pos2[1] - pos1[1]) / (pos2[0] - pos1[0]); - var angle = Math.atan(m); - if (pos1[1] == pos2[1]) { // horizontal - if (pos1[0] < pos2[0]) { - return [pos2[0] + extLength, pos2[1]]; - } else { - return [pos2[0] - extLength, pos2[1]]; - } - } - if (pos1[0] == pos2[0]) { // vertical - if (pos1[1] < pos2[1]) { - return [pos2[0], pos2[1] + extLength]; - } else { - return [pos2[0], pos2[1] - extLength]; - } - } - if (m > 0) { - if (pos2[0] >= pos1[0]) { - return ([pos2[0] + extLength * Math.cos(angle), pos2[1] + extLength * Math.sin(angle)]); - } else { - return ([pos2[0] - extLength * Math.cos(angle), pos2[1] - extLength * Math.sin(angle)]); - } - } else { - if (pos2[0] <= pos1[0]) { - return ([pos2[0] - extLength * Math.cos(angle), pos2[1] - extLength * Math.sin(angle)]); - } else { - return ([pos2[0] + extLength * Math.cos(angle), pos2[1] + extLength * Math.sin(angle)]); - } - } -} - -function isPointOnEllipse(point, center, radiusX, radiusY, tolerance) { - if (typeof tolerance == 'undefined') { - if (roundToNearest(Math.pow((point[0] - center[0]) / radiusX, 2) + Math.pow((point[1] - center[1]) / radiusY, 2), 0.0001) == 1) { - return true; - } else { - return false; - } - } else { - var max = Math.pow((point[0] - center[0]) / (radiusX + tolerance), 2) + Math.pow((point[1] - center[1]) / (radiusY + tolerance), 2); - var min = Math.pow((point[0] - center[0]) / (radiusX - tolerance), 2) + Math.pow((point[1] - center[1]) / (radiusY - tolerance), 2); - if (Math.max(min, max) >= 1 && Math.min(min, max) <= 1) { - return true; - } else { - return false; - } - } -} -function isPointInEllipse(point, center, radiusX, radiusY) { - if (roundToNearest(Math.pow((point[0] - center[0]) / radiusX, 2) + Math.pow((point[1] - center[1]) / radiusY, 2), 0.0001) <= 1) { - return true; - } else { - return false; - } -} -function isPointInRect(point, left, top, width, height) { - if (point[0] >= left && point[0] <= left + width && point[1] >= top && point[1] <= top + height) { - return true; - } else { - return false; - } -} -function distPointToRect(point, left, top, width, height) { - if (isPointInRect(point, left, top, width, height) == true) - return 0; - return Math.min( - distancePointToLineSegment(point, [left, top], [left + width, top]), - distancePointToLineSegment(point, [left + width, top], [left + width, top + height]), - distancePointToLineSegment(point, [left + width, top + height], [left, top + height]), - distancePointToLineSegment(point, [left, top + height], [left + width, top])) -} -function lineCircleIntersections(linePoint1, linePoint2, circleCenter, circleRadius) { - var a = linePoint1[0]; - var b = linePoint1[1]; - var c = linePoint2[0]; - var d = linePoint2[1]; - var p = circleCenter[0]; - var q = circleCenter[1]; - var r = circleRadius; - - var m = (d - b) / (c - a); - var s = m * m + 1; - var t = -2 * p + 2 * m * (-m * a + b - q); - var u = p * p + (-m * a + b - q) * (-m * a + b - q) - r * r; - var discrim = t * t - 4 * s * u; - if (discrim < 0) { - return []; - } else if (discrim == 0) { - var x = (-t + Math.sqrt(discrim)) / (2 * s); - var y = m * (x - a) + b; - if (x >= p) { - if (y >= q) { - var angle = Math.atan((y - q) / (x - p)); - } else { - var angle = 2 * Math.PI + Math.atan((y - q) / (x - p)); - } - } else { - var angle = Math.PI + Math.atan((y - q) / (x - p)); - } - return [[x, y, angle]]; - } else { - var x1 = (-t + Math.sqrt(discrim)) / (2 * s); - var y1 = m * (x1 - a) + b; - if (x1 >= p) { - if (y1 >= q) { - var angle1 = Math.atan((y1 - q) / (x1 - p)); - } else { - var angle1 = 2 * Math.PI + Math.atan((y1 - q) / (x1 - p)); - } - } else { - var angle1 = Math.PI + Math.atan((y1 - q) / (x1 - p)); - } - var x2 = (-t - Math.sqrt(discrim)) / (2 * s); - var y2 = m * (x2 - a) + b; - if (x2 >= p) { - if (y2 >= q) { - var angle2 = Math.atan((y2 - q) / (x2 - p)); - } else { - var angle2 = 2 * Math.PI + Math.atan((y2 - q) / (x2 - p)); - } - } else { - var angle2 = Math.PI + Math.atan((y2 - q) / (x2 - p)); - } - return [[x1, y1, angle1], [x2, y2, angle2]]; - } -} -function circleIntersections(x0, y0, r0, x1, y1, r1) { - var a, - dx, - dy, - d, - h, - rx, - ry; - var x2, - y2; - /* dx and dy are the vertical and horizontal distances between the circle centers. */ - dx = x1 - x0; - dy = y1 - y0; - /* Determine the straight-line distance between the centers. */ - d = Math.sqrt((dy * dy) + (dx * dx)); - /* Check for solvability. */ - if (d > (r0 + r1)) { - /* no solution. circles do not intersect. */ - return []; - } - if (d < Math.abs(r0 - r1)) { - /* no solution. one circle is contained in the other */ - return []; - } - /* 'point 2' is the point where the line through the circle intersection points crosses the line between the circle centers. */ - /* Determine the distance from point 0 to point 2. */ - a = ((r0 * r0) - (r1 * r1) + (d * d)) / (2 * d); - /* Determine the coordinates of point 2. */ - x2 = x0 + (dx * a / d); - y2 = y0 + (dy * a / d); - /* Determine the distance from point 2 to either of the intersection points. */ - h = Math.sqrt((r0 * r0) - (a * a)); - /* Now determine the offsets of the intersection points from point 2. */ - rx = -dy * (h / d); - ry = dx * (h / d); - /* Determine the absolute intersection points. */ - var xi = x2 + rx; - var xii = x2 - rx; - var yi = y2 + ry; - var yii = y2 - ry; - return [[xi, yi], [xii, yii]]; -} -function isPointOnArc(point, arcPath, tolerance) { - if (!tolerance) - tolerance = 0.00001; - var rad = dist(point[0], point[1], arcPath.center[0], arcPath.center[1]); - if (rad < arcPath.radius - tolerance || rad > arcPath.radius + tolerance) - return false; - if (Math.abs(arcPath.startAngle - arcPath.finAngle) + 0.00001 >= 2 * Math.PI) - return true; - var angle = getAngleFromAToB(arcPath.center, point); - var angle1 = simplifyAngle(arcPath.startAngle); - var angle2 = simplifyAngle(arcPath.finAngle); - var a = arcPath.clockwise; - var b = angle1 < angle2; - var c = angle >= angle1 && angle <= angle2; - /* - if (a && b && c) return true; - if (a && b && !c) return false; - if (a && !b && c) return true; - if (a && !b && !c) return false; - if (!a && b && c) return false; - if (!a && b && !c) return true; - if (!a && !b && c) return false; - if (!a && !b && !c) return true; - /*/ - if (a == true) { - if (b == true) { - if (c == true) { - return true; - } else { - return false; - } - } else { - if (c == true) { - return true; - } else { - return false; - } - } - } else { - if (b == true) { - if (c == true) { - return false; - } else { - return true; - } - } else { - if (c == true) { - return false; - } else { - return true; - } - } - } - //*/ -} - -function simplifyAngle(angle) { - while (angle < 0) { - angle += (2 * Math.PI) - }; - angle = angle % (2 * Math.PI); - return angle; -} -function getAngleFromAToB(a, b) { - // angle as measured anticlockwise from positive x-direction (upside down on canvas) - A is in the centre - var angle = Math.atan((b[1] - a[1]) / (b[0] - a[0])); - if (b[0] >= a[0] && b[1] >= a[1]) - return angle; - if (b[0] >= a[0] && b[1] < a[1]) - return angle + 2 * Math.PI; - if (b[0] < a[0]) - return angle + Math.PI; -} -function getEndPointsOfArc(arcPath) { - // if closed circle, return empty - if (Math.abs(arcPath.startAngle - arcPath.finAngle) % (2 * Math.PI) == 0) - return []; - return [ - [arcPath.center[0] + arcPath.radius * Math.cos(arcPath.startAngle), arcPath.center[1] + arcPath.radius * Math.sin(arcPath.startAngle)], - [arcPath.center[0] + arcPath.radius * Math.cos(arcPath.finAngle), arcPath.center[1] + arcPath.radius * Math.sin(arcPath.finAngle)] - ] -} -function vectorFromAToB(a, b) { - return [b[0] - a[0], b[1] - a[1]]; -} - -function snapToPoints(point, snapPoints, tolerance) { - var minDist = []; - for (var i = 0; i < snapPoints.length; i++) { - minDist.push(dist(point[0], point[1], snapPoints[i][0], snapPoints[i][1])); - } - if (arrayMin(minDist) < tolerance) { - return snapPoints[minDist.indexOf(arrayMin(minDist))].slice(0); - } else { - return point.slice(0); - } -} -function snapToGrid(point, snapGrid) { - //snapGrid should contain: {left,top,width,height,dx,dy} -} - -function getBezierPoints(p1, p2, p3, density) { - if (!density) - density = 10; - var length = quadraticBezierLength(p1, p2, p3); - var points = [p1]; - for (var i = density; i < length; i += density) { - points.push(getQuadraticCurvePoint(p1[0], p1[1], p2[0], p2[1], p3[0], p3[1], i / length)); - } - points.push(p3); - return points; -} -function getQBezierValue(t, p1, p2, p3) { // called by getQuadraticCurvePoint, src: http://jsfiddle.net/QA6VG/ - var iT = 1 - t; - return iT * iT * p1 + 2 * iT * t * p2 + t * t * p3; -} -function getQuadraticCurvePoint(startX, startY, cpX, cpY, endX, endY, position) { // called by getBezierPoints, src: http://jsfiddle.net/QA6VG/ - return [getQBezierValue(position, startX, cpX, endX), getQBezierValue(position, startY, cpY, endY)]; -} -function quadraticBezierLength(p0, p1, p2) { // called by getBezierPoints, src: https://gist.github.com/tunght13488/6744e77c242cc7a94859 - function Point(x, y) { - this.x = x; - this.y = y; - } - var a = new Point( - p0[0] - 2 * p1[0] + p2[0], - p0[1] - 2 * p1[1] + p2[1]); - var b = new Point( - 2 * p1[0] - 2 * p0[0], - 2 * p1[1] - 2 * p0[1]); - var A = 4 * (a.x * a.x + a.y * a.y); - var B = 4 * (a.x * b.x + a.y * b.y); - var C = b.x * b.x + b.y * b.y; - - var Sabc = 2 * Math.sqrt(A + B + C); - var A_2 = Math.sqrt(A); - var A_32 = 2 * A * A_2; - var C_2 = 2 * Math.sqrt(C); - var BA = B / A_2; - - return (A_32 * Sabc + A_2 * B * (Sabc - C_2) + (4 * C * A - B * B) * Math.log((2 * A_2 + BA + Sabc) / (BA + C_2))) / (4 * A_32); -} - -function drawTextBox(canvas, canvasctx, canvasData, backgroundColor, borderColor, borderWidth, font, textColor, textAlign, textLine1, textLine2) { - var polygon = false; - if (typeof canvasData[41] !== 'undefined') - polygon = true; - canvasctx.clearRect(0, 0, canvasData[2], canvasData[3]); - canvasctx.fillStyle = backgroundColor; - canvasctx.strokeStyle = borderColor; - canvasctx.lineWidth = borderWidth; - if (polygon == true) { - canvasctx.beginPath(); - canvasctx.moveTo(canvasData[41][0][0], canvasData[41][0][1]); - for (j = 0; j < canvasData[41].length; j++) { - if (j > 0) - canvasctx.lineTo(canvasData[41][j][0], canvasData[41][j][1]); - } - canvasctx.closePath(); - canvasctx.fill(); - canvasctx.stroke(); - } else { - if (backgroundColor !== '') - canvasctx.fillRect(0, 0, canvasData[2], canvasData[3]); - if (borderColor !== '') - canvasctx.strokeRect(0, 0, canvasData[2], canvasData[3]); - } - canvasctx.font = font; - canvasctx.fillStyle = textColor; - canvasctx.textAlign = textAlign; - canvasctx.textBaseline = "middle"; - if (!textLine2) { - canvasctx.fillText(textLine1, 0.5 * canvasData[2], 0.5 * canvasData[3]); - } else { - canvasctx.fillText(textLine1, 0.5 * canvasData[2], 0.3 * canvasData[3]); - canvasctx.fillText(textLine2, 0.5 * canvasData[2], 0.7 * canvasData[3]); - } -} -function drawMathsTextBox(canvasctx, canvasData, textArray, object) { - // optional object can contain: backColor, algText, fontSize, borderColor, borderWidth, textColor, textAlign - if (!object) { - var fontSize = 0.45 * canvasData[3]; - var horizAlign = 'center'; - var algText = true; - var textColor = '#000'; - var backgroundColor = '#6F9'; - var borderColor = '#000'; - var borderWidth = 4; - } else { - var fontSize = object.fontSize || 0.45 * canvasData[3]; - var horizAlign = object.textAlign || 'center'; - var algText = true; - if (typeof object.algText == 'boolean') - algText = object.algText; - var textColor = object.textColor || '#000'; - var backgroundColor = object.backColor || '#6F9'; - var borderColor = object.borderColor || '#000'; - var borderWidth = object.borderWidth || 4; - } - var horizPos = 0.5 * canvasData[2]; - if (horizAlign == 'left') - horizPos = 5; - if (horizAlign == 'right') - horizPos = canvasData[2] - 5; - canvasctx.clearRect(0, 0, canvasData[2], canvasData[3]); - canvasctx.fillStyle = backgroundColor; - canvasctx.strokeStyle = borderColor; - canvasctx.lineWidth = borderWidth; - canvasctx.fillRect(0, 0, canvasData[2], canvasData[3]); - canvasctx.strokeRect(borderWidth * 0.5, borderWidth * 0.5, canvasData[2] - borderWidth, canvasData[3] - borderWidth); - drawMathsText(canvasctx, textArray, fontSize, horizPos, 0.47 * canvasData[3], algText, [], horizAlign, 'middle', textColor, 'draw'); -} -function wrapText(context, text, x, y, maxWidth, lineHeight, font, fillStyle) { - context.font = font; - context.fillStyle = fillStyle; - var words = text.split(' '); - var line = ''; - for (var n = 0; n < words.length; n++) { - var testLine = line + words[n] + ' '; - var metrics = context.measureText(testLine); - var testWidth = metrics.width; - if (testWidth > maxWidth && n > 0) { - context.fillText(line, x, y); - line = words[n] + ' '; - y += lineHeight; - } else { - line = testLine; - } - } - context.fillText(line, x, y); -} -function drawFrac(context, font, x, y, horizAlign, numerator, denominator) { - context.save(); - context.font = font; - var fractionWidth = Math.max(context.measureText(numerator).width, context.measureText(denominator).width); - context.textAlign = 'center'; - context.textBaseline = 'bottom'; - switch (horizAlign) { - case 'right': - context.fillText(numerator, x - 2 - 0.5 * fractionWidth, y - 5); - context.textBaseline = 'top'; - context.fillText(denominator, x - 2 - 0.5 * fractionWidth, y + 5); - context.strokeStyle = textColor; - context.lineWidth = 3; - context.moveTo(x - 4 - fractionWidth, y); - context.lineTo(x, y); - break; - case 'center': - context.fillText(numerator, x, y - 5); - context.textBaseline = 'top'; - context.fillText(denominator, x, y + 5); - context.strokeStyle = textColor; - context.lineWidth = 3; - context.moveTo(x - 2 - 0.5 * fractionWidth, y); - context.lineTo(x + 2 + 0.5 * fractionWidth, y); - break; - default: - context.fillText(numerator, x + 2 + 0.5 * fractionWidth, y - 5); - context.textBaseline = 'top'; - context.fillText(denominator, x + 2 + 0.5 * fractionWidth, y + 5); - context.strokeStyle = textColor; - context.lineWidth = 3; - context.moveTo(x, y); - context.lineTo(x + 4 + fractionWidth, y); - break; - } - context.stroke(); - context.restore(); -} - -function generateNormalData(mean, sd, n) { - var normal = gaussian(mean, sd); - var data = []; - var groups = []; - for (var i = 0; i < 8; i++) - groups[i] = { - min: roundToNearest(mean + (i - 4) * sd, 0.00001), - max: roundToNearest(mean + (i - 3) * sd, 0.00001), - frequency: 0 - }; - for (var i = 0; i < n; i++) { - var value = normal() - data.push(value); - for (var g = 0; g < 8; g++) { - if (value >= groups[g].min && value <= groups[g].max) { - groups[g].frequency++; - break; - } - } - } - return { - data: data, - grouped: groups - }; -} -// returns a gaussian random function with the given mean and stdev. -function gaussian(mean, stdev) { - var y2; - var use_last = false; - return function () { - var y1; - if (use_last) { - y1 = y2; - use_last = false; - } else { - var x1, - x2, - w; - do { - x1 = 2.0 * Math.random() - 1.0; - x2 = 2.0 * Math.random() - 1.0; - w = x1 * x1 + x2 * x2; - } while (w >= 1.0); - w = Math.sqrt((-2.0 * Math.log(w)) / w); - y1 = x1 * w; - y2 = x2 * w; - use_last = true; - } - - var retval = mean + stdev * y1; - if (retval > 0) - return retval; - return -retval; - } -} -function phi(x) { // for normal distribution - var a1 = 0.254829592; - var a2 = -0.284496736; - var a3 = 1.421413741; - var a4 = -1.453152027; - var a5 = 1.061405429; - var p = 0.3275911; - - var sign = 1 - if (x < 0) - sign = -1 - x = Math.abs(x) / Math.sqrt(2) - - // A&S formula 7.1.26 - var t = 1 / (1 + p * x) - var y = 1 - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * Math.exp(-x * x) - - return 0.5 * (1 + sign * y) -} -function enlargeDash(dash, sf) { - if (typeof sf == 'undefined') - return dash; - for (var i = 0; i < dash.length; i++) { - dash[i] = dash[i] * sf; - } - return dash; -} - -function numberToString(n, commaForThousand) { - var decPart = roundToNearest(n - Math.floor(n), 0.00001); - var str = Math.floor(n).toString(); - if (str.length < 4 || (str.length == 4 && boolean(commaForThousand, false) == false)) {} - else { - var count = 0; - for (var i = str.length; i >= 1; i--) { - if (count == 3) { - str = str.slice(0, i) + ',' + str.slice(i); - count = 0; - } - count++; - } - } - if (decPart > 0) { - var str2 = String(decPart); - str = str + str2.slice(1); - } - return str; -} -function stringToNumber(str) { - var str = replaceAll(str, ',', ''); - var str = replaceAll(str, ' ', ''); - return parseInt(str); -} -function numberToWords(n, capFirstLetter) { - var string = n.toString(), - units, - tens, - scales, - start, - end, - chunks, - chunksLen, - chunk, - ints, - i, - word, - words, - and = 'and'; - if (parseInt(string) === 0) - return 'zero'; - - units = ['', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen']; - - tens = ['', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety']; - - scales = ['', 'thousand', 'million', 'billion', 'trillion', 'quadrillion', 'quintillion', 'sextillion', 'septillion', 'octillion', 'nonillion', 'decillion', 'undecillion', 'duodecillion', 'tredecillion', 'quatttuor-decillion', 'quindecillion', 'sexdecillion', 'septen-decillion', 'octodecillion', 'novemdecillion', 'vigintillion', 'centillion']; - - start = string.length; /* Split user arguemnt into 3 digit chunks from right to left */ - chunks = []; - while (start > 0) { - end = start; - chunks.push(string.slice((start = Math.max(0, start - 3)), end)); - } - - chunksLen = chunks.length; /* Check if function has enough scale words to be able to stringify the user argument */ - if (chunksLen > scales.length) { - return ''; - } - - words = []; /* Stringify each integer in each chunk */ - for (i = 0; i < chunksLen; i++) { - chunk = parseInt(chunks[i]); - if (chunk) { - - /* Split chunk into array of individual integers */ - ints = chunks[i].split('').reverse().map(parseFloat); - - /* If tens integer is 1, i.e. 10, then add 10 to units integer */ - if (ints[1] === 1) { - ints[0] += 10; - } - - if (i > 0) - words.push(','); - - /* Add scale word if chunk is not zero and array item exists */ - if ((word = scales[i])) { - words.push(word); - } - - /* Add unit word if array item exists */ - if ((word = units[ints[0]])) { - words.push(word); - } - - /* Add tens word if array item exists */ - if ((word = tens[ints[1]])) { - words.push(word); - } - - /* Add 'and' string after units or tens integer if: */ - if (ints[0] || ints[1]) { - - /* Chunk has a hundreds integer or chunk is the first of multiple chunks */ - if (ints[2] || !i && chunksLen) { - words.push(and); - } - - } - - /* Add hundreds word if array item exists */ - if ((word = units[ints[2]])) { - words.push(word + ' hundred'); - } - - } - - } - - var str = words.reverse().join(' '); - str = replaceAll(str, ' ,', ','); - str = replaceAll(str, ', and', ' and'); - if (str.slice(0, 4) == 'and ') - str = str.slice(4); - if (str.slice(-1) == ',') - str = str.slice(0, -1); - if (boolean(capFirstLetter, true)) - str = str.charAt(0).toUpperCase() + str.slice(1); - return str; -} diff --git a/tools/i2/_style.css b/tools/i2/_style.css deleted file mode 100644 index ec60650..0000000 --- a/tools/i2/_style.css +++ /dev/null @@ -1,186 +0,0 @@ -@charset "utf-8"; -/* CSS Document */ - -@media screen { - html, body { - width: 100%; - height: 100%; - margin: auto auto auto auto; - background-color: #9C9AFF; - border: 0; - text-align: center; - overflow: hidden; /* Disable scrollbars */ - } -} -@media print { - size: auto; - margin: 0mm; -} - -@font-face { - font-family: 'Hobo'; - src: url('fonts/hobo-webfont.woff') format('woff'), - url('fonts/hobo-webfontd41d.eot?#iefix') format('embedded-opentype'), - url('fonts/hobo-webfont.eot'), - url('fonts/hobo-webfont.ttf') format('truetype'), - url('fonts/hobo-webfont.svg#hoboregular') format('svg'); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: 'segoePrint'; - src:url('fonts/segeo-print-webfont.woff') format('woff'), - url('fonts/segeo-print-webfont.ttf') format('truetype'), - url('fonts/segeo-print-webfont.svg#SegoePrintRegular') format('svg'), - url('fonts/segeo-print-webfont-2.svg#SegoePrintRegular') format('svg'), - url('fonts/segeo-print-webfont.eot'); - font-weight: normal; - font-style: normal; -} -@font-face { - font-family: 'smileyMonster'; - src:url('fonts/smileymonster.woff') format('woff'), - url('fonts/smileymonster.ttf') format('truetype'), - url('fonts/smileymonster.svg#Smiley-Monster') format('svg'), - url('fonts/smileymonster.eot'), - url('fonts/smileymonsterd41d.eot?#iefix') format('embedded-opentype'); - font-weight: normal; - font-style: normal; -} - -.wrapper { - display: table; - padding: 0; - width: 100%; - height: 100%; - position: absolute; -} -.container { - display: table-cell; - vertical-align: middle; - user-select: none; - -moz-user-select: none; - -khtml-user-select: none; - -webkit-user-select: none; - -o-user-select: none; -} -.canvas-container { - position: relative; - margin: 0 auto; -} -#canvas { - width: 100%; - height: auto; - position: relative; - tabindex: 1; - touch-action: none; - -ms-touch-action: none; - -webkit-tap-highlight-color: rgba(0,0,0,0); - -webkit-tap-highlight-color: transparent; -} -#inactiveBox { - position: absolute; - z-index: 900000; - left: 0; - top: 0; - -ms-touch-action: none; - -webkit-tap-highlight-color: rgba(0,0,0,0); - -webkit-tap-highlight-color: transparent; -} -.holderButton { - position: absolute; - z-index: 800000; - left: 0; - top: 0; - touch-action: none; - -ms-touch-action: none; - cursor: pointer; - -webkit-tap-highlight-color: rgba(0,0,0,0); - -webkit-tap-highlight-color: transparent; -} -.hideMe { - overflow: hidden; - visibility: hidden; - height: 0; - width: 0; -} -#videoMask { - position: absolute; - z-index: 510; - cursor: auto; - tabindex: 2; - touch-action: none; - -ms-touch-action: none; - -webkit-tap-highlight-color: rgba(0,0,0,0); - -webkit-tap-highlight-color: transparent; -} -.buttonClass { - position: absolute; - z-index: 2; - cursor: pointer; - tabindex: 2; - touch-action: none; - -ms-touch-action: none; - -webkit-tap-highlight-color: rgba(0,0,0,0); - -webkit-tap-highlight-color: transparent; -} -.drawDivCanvas { - position: absolute; - z-index: 2; - cursor: pointer; - tabindex: 2; - left:0px; - top:0px; - width:100%; - touch-action: none; - -ms-touch-action: none; - -webkit-tap-highlight-color: rgba(0,0,0,0); - -webkit-tap-highlight-color: transparent; -} -.page-div { - position: relative; - margin-bottom: 10px; -} -.keyClass { - position: absolute; - z-index: 800000; - cursor: auto; - border-radius: 5px; - tabindex: 2; - touch-action: none; - -ms-touch-action: none; - -webkit-tap-highlight-color: rgba(0,0,0,0); - -webkit-tap-highlight-color: transparent; -} -.inputClass { - position: absolute; - z-index: 2; - font-size: 42px; - text-align: center; - margin: 0; - width: 50px; - height: 50px; - cursor: text; - touch-action: none; - -ms-touch-action: none; - -webkit-tap-highlight-color: rgba(0,0,0,0); - -webkit-tap-highlight-color: transparent; -} -.gridCanvasClass { - position: absolute; - z-index: 2; - tabindex: 2; - -ms-touch-action: none; - -webkit-tap-highlight-color: rgba(0,0,0,0); - -webkit-tap-highlight-color: transparent; -} -.videoClass { - position: absolute; - z-index: 500; - cursor: auto; - tabindex: 2; - touch-action: none; - -ms-touch-action: none; - -webkit-tap-highlight-color: rgba(0,0,0,0); - -webkit-tap-highlight-color: transparent; -} \ No newline at end of file diff --git a/tools/i2/_text2.js b/tools/i2/_text2.js deleted file mode 100644 index ee72766..0000000 --- a/tools/i2/_text2.js +++ /dev/null @@ -1,925 +0,0 @@ -//js - -var defaultTags = { - font:'Arial', - fontSize:20, - bold:false, - italic:false, - color:'#000', - selected:false, - backColor:'none', - align:[0,0], - lineSpacingFactor:1.2, - lineSpacingStyle:'variable' -} -function updateTagsFromText(arr,startTags) { - var tags = clone(startTags); - if (typeof arr == 'string') { - var str = arr.slice(0); - while (str.indexOf('<<') > -1) { - str = str.slice(str.indexOf('<<')); - var type = str.slice(2,str.indexOf(':')); - var value = str.slice(str.indexOf(':')+1,str.indexOf('>>')); - if (type == 'align') { - if (value == 'left') tags.align[0] = -1; - if (value == 'center') tags.align[0] = 0; - if (value == 'right') tags.align[0] = 1; - } else { - if (!isNaN(Number(value))) value = Number(value); - if (value == 'true') value = true; - if (value == 'false') value = false; - tags[type] = value; - } - str = str.slice(str.indexOf('>>')+2); - } - } else if (typeof arr == 'object') { - for (var i = 0; i < arr.length; i++) { - tags = updateTagsFromText(arr[i],tags); - } - } - return tags; -} -function getAlignFromText(arr,fallback) { - var align = fallback; - if (typeof arr == 'string') { - var str = arr.slice(0); - if (str.indexOf('< -1) { - str = str.slice(str.indexOf('<>')); - } - } else if (typeof arr == 'object') { - for (var i = 0; i < arr.length; i++) { - align = getAlignFromText(arr[i],align); - } - } - if (align == 'left') align = -1; - if (align == 'center') align = 0; - if (align == 'right') align = 1; - return align; -} - -function splitTextByTags(textStr) { - // find markup tags and split text - var splitPoints = [0]; - for (var ch1 = 0; ch1 < textStr.length; ch1++) { - if (textStr.slice(ch1).indexOf('<<') == 0 && textStr.slice(ch1).indexOf('<<<') !== 0) { - for (var ch2 = ch1; ch2 < textStr.length; ch2++) { - if (textStr.slice(ch2).indexOf('>>') == 0) { - splitPoints.push(ch1,ch2+2); - break; - } - } - } - } - splitPoints.push(textStr.length); - var splitText = []; - for (var ch = 0; ch < splitPoints.length-1; ch++) { - splitText.push(textStr.slice(splitPoints[ch],splitPoints[ch+1])) - } - return splitText; -} -function textArrayCombineAdjacentText(arr) { - for (var gg = arr.length - 1; gg >= 0; gg--) { - if (typeof arr[gg] == 'object') { - textArrayCombineAdjacentText(arr[gg]); - } else { - if (gg < arr.length - 1 && typeof arr[gg] == 'string' && typeof arr[gg+1] == 'string') { - arr[gg] += arr[gg+1]; - arr.splice(gg+1,1);; - } - } - } - return arr; -} -function textTagGetTypeValue(tagStr) { - if (tagStr.indexOf('<<') == -1) { - return null; - } else if (tagStr.indexOf('<<') > 0) { - tagStr = tagStr.slice(tagStr.indexOf('<<')) - } - var type = tagStr.slice(2,tagStr.indexOf(':')); - var value = tagStr.slice(tagStr.indexOf(':')+1,tagStr.indexOf('>>')); - if (!isNaN(Number(value))) value = Number(value); - if (value == 'false') value = false; - if (value == 'true') value = true; - return {type:type,value:value}; -} -function simplifyText(arr) { - var arr = textArrayCombineAdjacentText(arr); - var arr = textArrayRemoveRedundantTagsA(arr); - var arr = textArrayRemoveRedundantTagsB(arr); - var arr = textArrayRemoveRedundantAlignTags(arr); - return arr; -} -function textArrayRemoveRedundantTagsA(arr) { - // removes tags of the same type with no characters between them - var tags = {bold:null,italic:null,fontSize:null,font:null,color:null,backColor:null,selected:null}; - var char = {bold:true,italic:true,fontSize:true,font:true,color:true,backColor:true,selected:true}; - - if (typeof arr == 'object') { - arr = arrayHandler(arr); - } else if (typeof arr == 'string') { - arr = stringHandler(arr); - } - - function arrayHandler(arr) { - for (var l = arr.length - 1; l >= 0; l--) { - if (typeof arr[l] == 'string') { - arr[l] = stringHandler(arr[l]); - } else if (typeof arr[l] == 'object') { - for (var prop in char) char[prop] = true; - arr[l] = arrayHandler(arr[l]); - } - } - return arr; - } - - function stringHandler(str) { - var split = splitTextByTags(str); - for (var j = split.length - 1; j >= 0; j--) { - if (split[j].indexOf('<<') == 0) { - var tag = textTagGetTypeValue(split[j]); - if (tag.type == 'align') continue; - if (char[tag.type] == false) { - split.splice(j,1); - } else { - tags[tag.type] = tag.value; - char[tag.type] = false; - } - } else if (split[j].length > 0) { - for (var prop in char) char[prop] = true; - } - } - var str = ''; - for (var j = 0; j < split.length; j++) str += split[j]; - return str; - } - return arr; -} -function textArrayRemoveRedundantTagsB(arr) { - // removes redundant repeated tags - var tags = {bold:null,italic:null,fontSize:null,font:null,color:null,backColor:null,selected:null}; - - if (typeof arr == 'object') { - arr = arrayHandler(arr); - } else if (typeof arr == 'string') { - arr = stringHandler(arr); - } - - function arrayHandler(arr) { - for (var l = 0; l < arr.length; l++) { - if (typeof arr[l] == 'string') { - arr[l] = stringHandler(arr[l]); - } else if (typeof arr[l] == 'object') { - arr[l] = arrayHandler(arr[l]); - } - } - return arr; - } - - function stringHandler(str) { - var split = splitTextByTags(str); - for (var j = 0; j < split.length; j++) { - if (split[j].indexOf('<<') == 0) { - var tag = textTagGetTypeValue(split[j]); - if (tag.type == 'align') continue; - if (tags[tag.type] == tag.value) { - split.splice(j,1); - } else { - tags[tag.type] = tag.value; - } - } - } - var str = ''; - for (var j = 0; j < split.length; j++) str += split[j]; - return str; - } - return arr; -} -function textArrayRemoveRedundantAlignTags(arr) { - var alignSet = false; - - if (typeof arr == 'object') { - arr = arrayHandler(arr); - } else if (typeof arr == 'string') { - arr = stringHandler(arr); - } - - function arrayHandler(arr) { - for (var l = 0; l < arr.length; l++) { - if (typeof arr[l] == 'string') { - arr[l] = stringHandler(arr[l]); - } else if (typeof arr[l] == 'object') { - arr[l] = arrayHandler(arr[l]); - } - } - return arr; - } - - function stringHandler(str) { - var split = splitTextByTags(str); - for (var j = 0; j < split.length; j++) { - if (split[j].indexOf('< -1) { - alignSet = false; - } - } - var str = ''; - for (var j = 0; j < split.length; j++) str += split[j]; - return str; - } - return arr; -} -function textArrayReplace(arr,find,replace) { - //if (find == '<
>') console.log(clone(arr),arr,find,replace); - if (typeof arr == 'string') { - arr = replaceAll(arr,find,replace); - } else if (typeof arr == 'object') { - for (var i = 0; i < arr.length; i++) { - arr[i] = textArrayReplace(arr[i],find,replace); - } - } - return arr; -} -function textArrayFontSizeAdjust(arr,sf) { - if (typeof arr == 'string') { - for (var c = 0; c < arr.length; c++) { - var sliced = arr.slice(c); - if (sliced.indexOf('<>'); - var after = sliced.slice(d+2); - var num = arr.slice(c+11); - num = num.slice(0,num.indexOf('>>')); - num = Number(num); - if (!isNaN(num)) { - num = Math.round(num*sf); - arr = before+'<>'+after; - } - } - } - } else if (arr instanceof Array) { - for (var i = 0; i < arr.length; i++) { - arr[i] = textArrayFontSizeAdjust(arr[i],sf); - } - } else if (typeof arr == 'object') { - for (var i in arr) { - arr[i] = textArrayFontSizeAdjust(arr[i],sf); - } - } - return arr; -} -function textArrayFind(arr,str,found,depth) { - if (un(found)) found = false; - if (un(depth)) depth = 0; - if (typeof arr == 'string') { - if (arr.indexOf(str) > -1) found = true; - } else if (typeof arr == 'object') { - for (var i = 0; i < arr.length; i++) { - if (depth > 0 && i === 0 && ['frac','pow','sqrt','root','power','sub','subs','subscript','sin','cos','tan','log','ln','sin-1','cos-1','tan-1','logBase','abs','exp','int1','sigma1','sigma2','int2','recurring','vectorArrow','bar','hat','colVector2d','colVector3d','mixedNum','lim'].indexOf(arr[i]) > -1) continue; - found = textArrayFind(arr[i],str,found,depth+1); - } - } - return found; -} -function textArrayRemoveDefaultTags(arr,tags) { //also removes redundant tags at end - if (un(tags)) tags = defaultTags; - var sp = splitTextByTags(arr[0]); - arr[0] = ''; - var stop = false; - for (var s = 0; s < sp.length; s++) { - if (sp[s].length == 0) continue; - if (stop == true || (sp[s].indexOf('<<') !== 0)) { - arr[0] += sp[s]; - stop = true; - } else { - var type = sp[s].slice(2,sp[s].indexOf(':')); - var value = sp[s].slice(sp[s].indexOf(':')+1,-2); - if (!isNaN(Number(value))) value = Number(value); - if (value == 'true') value = true; - if (value == 'false') value = false; - if (tags[type] !== value || type == 'align') arr[0] += sp[s]; - } - } - - if (typeof arr[arr.length-1] == 'string') { - var sp = splitTextByTags(arr[arr.length-1]); - arr[arr.length-1] = ''; - var stop = false; - for (var s = sp.length-1; s >= 0; s--) { - if (sp[s].length == 0) continue; - if (stop == true || (sp[s].indexOf('<<') !== 0)) { - arr[arr.length-1] = sp[s] + arr[arr.length-1]; - stop = true; - } else { - var type = sp[s].slice(2,sp[s].indexOf(':')); - if (type == 'align') arr[arr.length-1] = sp[s] + arr[arr.length-1]; - } - } - } - return arr; -} -function textArrayCheckIfEmpty(arr) { - for (var i = 0; i < arr.length; i++) { - if (typeof arr[i] == 'object') return false; - var sp = splitTextByTags(arr[i]); - for (var s = 0; s < sp.length; s++) { - if (sp[s].length == 0 || sp[s].indexOf('<<') == 0) continue; - return false; - } - } - return true; -} -function removeTags(elem) { - if (typeof elem == 'string') { - //remove markup tags - for (var char = elem.length-1; char > -1; char--) { - if (elem.slice(char).indexOf('>>') == 0 && elem.slice(char-1).indexOf('>>>') !== 0) { - for (var char2 = char-2; char2 > -1; char2--) { - if (elem.slice(char2).indexOf('<<') == 0) { - elem = elem.slice(0,char2) + elem.slice(char+2); - char = char2; - break; - } - } - } - } - } else { - for (var i = 0; i < elem.length; i++) { - elem[i] = removeTags(elem[i]); - } - } - return elem; -} -function textArrayGetStartTags(arr) { - var str = (typeof arr == 'string') ? arr : arr[0]; - - var splitPoints = [0]; - for (var c = 0; c < str.length; c++) { - if (str.slice(c).indexOf('<<') == 0 && str.slice(c).indexOf('<<<') !== 0) { - for (var c2 = c; c2 < str.length; c2++) { - if (str.slice(c2).indexOf('>>') == 0) { - splitPoints.push(c,c2+2); - break; - } - } - } - } - splitPoints.push(str.length); - var tags = ''; - for (var c = 0; c < splitPoints.length-1; c++) { - var subStr = str.slice(splitPoints[c],splitPoints[c+1]); - if (subStr.indexOf('<<') == 0) { - tags += subStr; - } else if (subStr !== '') { - break; - } - } - - return tags; -} -function textArrayToLowerCase(arr) { - if (typeof arr == 'string') { - arr = arr.toLowerCase(); - } else if (typeof arr == 'object') { - for (var i = 0; i < arr.length; i++) { - arr[i] = textArrayToLowerCase(arr[i]); - } - } - return arr; -} - -function removeTagsOfType(textArray,tagType) { - var stringHandler = function(string) { - for (var j = string.length - 1; j >= 0; j--) { - var slice = string.slice(j); - if (slice.indexOf('<<'+tagType+':') == 0) { - string = string.slice(0,j)+string.slice(j+slice.indexOf('>>')+2); - } - } - return string; - } - - var arrayHandler = function(array) { - for (var l = array.length - 1; l >= 0; l--) { - if (typeof array[l] == 'string') { - array[l] = stringHandler(array[l]); - } else { - array[l] = arrayHandler(array[l]); - } - } - return array; - } - - if (typeof textArray == 'object') { - return arrayHandler(textArray); - } else if (typeof textArray == 'string') { - return stringHandler(textArray); - } -} -function getDateString() { - var monthNames = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]; - //var dayNames = ["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]; - //var monthNames = ["January","February","March","April","May","June","July","August","September","October","November","December"]; - //var dayNames = ["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]; - var dateNow = new Date(); - var dateNum = dateNow.getDate(); - var dateString = String(dateNum) + ([1,21,31].includes(dateNum) ? 'st' : [2,22].includes(dateNum) ? 'nd' : [3,23].includes(dateNum) ? 'rd' : 'th'); - //dateString = dayNames[dateNow.getDay()]+' '+dateString+' '+monthNames[dateNow.getMonth()]; - return dateString+' '+monthNames[dateNow.getMonth()]; -} - -function text(obj) { - // Required - var ctx = obj.context || obj.ctx; - ctx.beginPath(); - var textArray = obj.textArray || obj.text || []; - if (typeof textArray == 'number') { - textArray = [String(textArray)]; - } else if (typeof textArray == 'string') { - textArray = [textArray]; - } - textArray = textArrayReplace(textArray,'<
>',br); - - if (typeof mode !== 'undefined' && mode == 'present') textArray = textArrayReplace(clone(textArray),'{date}',getDateString()); - - var measureOnly = boolean(obj.measureOnly,false); - //var sf = obj.sf || 1; - var sf = 1; - - if (!un(obj.tags)) { - var startTags = clone(obj.tags); - } else { - var startTags = clone(defaultTags); - for (var key in startTags) { - if (key !== 'align'); - startTags[key] = def([obj[key],defaultTags[key]]); - } - } - var tabWidth = obj.tabWidth || 20; - - // Text Placing, Spacing & Alignment - if (un(obj.rect)) { - obj.rect = [ - def([obj.left,obj.l,0]), - def([obj.top,obj.t,0]), - def([obj.maxWidth,obj.width,obj.w,ctx.canvas.width]), - def([obj.maxHeight,obj.height,obj.h,ctx.canvas.height]) - ]; - } - var left = obj.rect[0]; - var top = obj.rect[1]; - var maxWidth = obj.rect[2]; - var maxHeight = obj.rect[3]; - var leftLoose = left; - var maxWidthLoose = maxWidth; - if (!un(obj.marginLeft)) { - left += obj.marginLeft; - maxWidth -= obj.marginLeft; - } - if (!un(obj.marginRight)) { - maxWidth -= obj.marginRight; - } - - if (typeof obj.align !== 'object') { - var align = clone(defaultTags.align); - align[0] = def([obj.align,obj.textAlign,obj.horizAlign,-1]); - align[1] = def([obj.vertAlign,-1]); - if (align[0] == 'left') align[0] = -1; - if (align[0] == 'center') align[0] = 0; - if (align[0] == 'right') align[0] = 1; - if (align[1] == 'top') align[1] = -1; - if (align[1] == 'middle') align[1] = 0; - if (align[1] == 'bottom') align[1] = 1; - } else { - var align = obj.align; - } - var allowSpaces = boolean(obj.allowSpaces,false); - - var minTightWidth = obj.minTightWidth || 50; - var minTightHeight = obj.minTightHeight || 50; - - var fracScale = obj.fracScale || obj._fracScale || 0.7; - var algPadding = obj.algPadding || obj._algPadding || 'default'; - - //var alignEquals = boolean(obj.alignEquals, false); - //var equalsCenter = obj.equalsLeft || left + 0.5 * maxWidth; - - var lineSpacingFactor = obj.lineSpacingFactor || 1.2; - var lineSpacingStyle = obj.lineSpacingStyle || obj.spacingStyle || 'variable'; - - var box = {}; - var padding = obj.padding || 0; - if (un(obj.box) || obj.box.type == 'none') { - box.type = 'none'; - } else { - box.type = obj.box.type || 'loose'; - box.color = obj.box.color || obj.box.backgroundColor || '#FFC'; - box.borderColor = obj.box.borderColor || obj.borderColor || '#000'; - box.borderWidth = obj.box.borderWidth || obj.borderWidth || 4*sf; - box.dash = obj.box.dash || []; - box.radius = obj.box.rounded || obj.box.radius || 0; - box.dir = obj.box.dir || 'right'; - box.arrowWidth = obj.box.arrowWidth || 40; - var padding = obj.box.padding || obj.padding || 10*sf; - } - var tags = clone(startTags); - - var backgroundColor = obj.backgroundColor || '#FFF'; // determines selection color - if (box.type !== 'none' && !un(box.color) && box.color !== 'none') backgroundColor = box.color; - - //console.log(ctx.canvas,textArray,align,obj.rect); - - var words = [[]]; - var arr = clone(textArray); - for (var i = 0; i < arr.length; i++) { - if (typeof arr[i] == 'string') { - do { - var s = arr[i].indexOf(" "); - var t = arr[i].indexOf(tab); - var b = arr[i].indexOf(br); - if (s == -1 && t == -1 && b == -1) { - words[words.length-1].push(arr[i]); - arr[i] = ''; - } else if (b > -1 && (t == -1 || b < t) && (s == -1 || b < s)) { - words[words.length-1].push(arr[i].slice(0,b),br); - arr[i] = arr[i].slice(b+1); - if (arr[i].length == 0 && i == arr.length-1) words[words.length-1].push(''); - } else if (s > -1 && (t == -1 || s < t)) { - words[words.length-1].push(arr[i].slice(0,s)," "); - arr[i] = arr[i].slice(s+1); - } else if (t > -1 && (s == -1 || t < s)) { - words[words.length-1].push(arr[i].slice(0,t),tab); - arr[i] = arr[i].slice(t+1); - } - } while (arr[i].length > 0); - } else { - words[words.length-1].push(arr[i]); - } - } - //console.log(words); - - var subWords = [[]]; - for (var l = 0; l < words.length; l++) { - for (var w = 0; w < words[l].length; w++) { - var sub = words[l][w]; - if (sub == br || sub == " " || sub == tab) { - subWords.push([sub],[]); - } else { - subWords[subWords.length-1].push(sub); - } - } - } - - if (obj.log) console.log(words); - - var lines = []; - var line; - newLine(); - function newLine() { - line = {width:0,height:tags.fontSize,words:[],text:[]}; - lines.push(line); - } - - for (var w = 0; w < subWords.length; w++) { - var subWord = subWords[w]; - subWords[w] = {text:subWords[w],width:0,tags:clone(tags)}; - if (arraysEqual(subWord,[br])) { - line.hardBreak = true; - newLine(); - } else if (arraysEqual(subWord,[tab])) { - if (w > 1 && subWords[w-1].text.length == 1 && subWords[w-2].tab == true) { - var dw = tabWidth; - } else { - var dw = (Math.ceil(line.width/tabWidth))*tabWidth - line.width; - } - line.words.push(subWords[w]); - line.text = line.text.concat(subWords[w].text); - subWords[w].width = dw; - subWords[w].tab = true; - line.width += dw; - if (line.width > maxWidth) newLine(); - } else if (subWord.length == 0) { - - } else { - var measure = drawMathsText(ctx,subWords[w].text,tags.fontSize,left,top,false,[],align,'middle',tags.color,'measure',tags.backColor,tags.bold,tags.italic,tags.font,tags.selected,sf,'none',fracScale,algPadding); - subWords[w].width = measure[0]; - subWords[w].height = measure[1]; - - tags = updateTagsFromText(subWords[w].text,tags); - - if (line.width > 0 && line.width + subWords[w].width > maxWidth) newLine(); - - //if (allowSpaces == true || line.width > 0 || !arraysEqual(subWord,[" "])) { - line.words.push(subWords[w]); - line.text = line.text.concat(subWords[w].text); - line.width += subWords[w].width; - line.height = Math.max(line.height,subWords[w].height); - //} - - } - } - - if (obj.log) console.log(lines); - - //console.log('subWords:',subWords); - - var maxLineHeight = 0; - var totalLineHeight = 0; - - for (var l = 0; l < lines.length; l++) { - var line = lines[l]; - // test for spaces at the end of line and remove - /*if (allowSpaces == false) { - for (var e = line.words.length-1; e >= 0; e--) { - var word = line.words[e]; - if (arraysEquals(word[e],[' ']) { - - } else { - - } - if (typeof elem == 'string' && elem.length > 0) { - var sub = splitTextByTags(elem); - console.log(sub); - - if (elem[elem.length-1] == " ") { - elem = elem.slice(0,elem.length-1); - // get the width of this space and reduce line width - var font = line.font; - var fontSize = line.fontSize; - var bold = line.bold; - var italic = line.italic; - // work forwards through line to get the styling at the point of the space - for (var elem2 = 0; elem2 < eleme; elem2++) { - if (typeof line.text[elem2] == 'string' && line.text[elem2].indexOf('<<') == 0) { - markupTag(line.text[elem2]); - } - } - var styledText = styleElement(" "); - var spaceWidth = drawMathsText(ctx, styledText, fontSize, left, top, false, [], align, 'middle', color, 'measure')[0]; - line.width -= spaceWidth; - } - break; - } else if (typeof elem == 'object') { - break; - } - } - }*/ - - var alignFromText = getAlignFromText(line.text); - if (!un(alignFromText)) { - line.align = alignFromText; - } else if (l > 0 && lines[l-1].hardBreak !== true) { - line.align = lines[l-1].align; - } else { - line.align = align[0]; - } - - //if (lines.length > 3) console.log('line'+l+':',line); - - // fix x - if (line.align == -1) line.x = left + padding; - if (line.align == 0) line.x = left + 0.5 * maxWidth; - if (line.align == 1) line.x = left + maxWidth - padding; - - // sort relative vertical spacing (assuming variable) - if (l > 0) { - line.relY = lines[l-1].relY + (0.5 * lines[l-1].height + 0.5 * line.height) * lineSpacingFactor; - } else { - line.relY = 0.5 * line.height * lineSpacingFactor; - } - maxLineHeight = Math.max(maxLineHeight, line.height); - totalLineHeight += line.height * lineSpacingFactor; - } - - if (lineSpacingStyle == 'fixed') { - for (var l = 0; l < lines.length; l++) { - lines[l].relY = (l + 0.5) * maxLineHeight * lineSpacingFactor; - } - totalLineHeight = lines.length * maxLineHeight * lineSpacingFactor; - } - - // work out where the top of the text will actually be - var topPos = top + padding; - - if (align[1] == 0) { - topPos = top + 0.5 * maxHeight - 0.5 * totalLineHeight; - } else if (align[1] == 1) { - topPos = top + maxHeight - padding - totalLineHeight; - } - - /* - if (alignEquals == true) { - var leftOfEqualsWidth = []; - var rightOfEqualsWidth = []; - var equalsWidth = []; - for (var line = 0; line < textLine.length; line++) { - var leftOfEquals = []; - var rightOfEquals = []; - var equalsFound = false; - // locate equals sign in each line - for (var elem = 0; elem < textLine[line].text.length; elem++) { - if (equalsFound == true) { - rightOfEquals.push(textLine[line].text[elem]); - } else { - if (typeof textLine[line].text[elem] == 'string') { - var equalsPos; - for (var pos = 0; pos < textLine[line].text[elem].length; pos++) { - if (textLine[line].text[elem][pos] == "=") { - equalsPos = pos; - equalsFound = true; - } - } - if (equalsFound == true) { - leftOfEquals.push(textLine[line].text[elem].slice(0, equalsPos)); - rightOfEquals.push(textLine[line].text[elem].slice(equalsPos+1)); - } else { - leftOfEquals.push(textLine[line].text[elem]); - } - } else { - leftOfEquals.push(textLine[line].text[elem]); - } - } - } - if (equalsFound == true) { - // measure left of equals sign - var styledLine1 = leftOfEquals.slice(0); - styledLine1.unshift('<><><><><><>'); - leftOfEqualsWidth[line] = drawMathsText(ctx, styledLine1, fontSize, x, y, false, [], textLine[line].align, 'middle', '#000', 'measure')[0]; - - // measure equals sign - styledLine1.push("="); - equalsWidth[line] = drawMathsText(ctx, styledLine1, fontSize, x, y, false, [], textLine[line].align, 'middle', '#000', 'measure')[0] - leftOfEqualsWidth[line]; - - // measure right of equals sign - styledLine1 = styledLine1.concat(rightOfEquals); - rightOfEqualsWidth[line] = drawMathsText(ctx, styledLine1, fontSize, x, y, false, [], textLine[line].align, 'middle', '#000', 'measure')[0] - equalsWidth[line] - leftOfEqualsWidth[line]; - - // loop through rows and set x value accordingly - textLine[line].alignEquals = true; - textLine[line].align = 'left'; - textLine[line].x = equalsCenter - 0.5 * equalsWidth[line] - leftOfEqualsWidth[line]; - - } else { - textLine[line].alignEquals = false; - } - } - } - */ - - // calc tight rect - if (lines[0].align == -1) { - var l = lines[0].x - padding; - var r = lines[0].x + lines[0].width + padding; - } else if (lines[0].align == 0) { - var l = lines[0].x - 0.5 * lines[0].width - padding; - var r = lines[0].x + 0.5 * lines[0].width + padding; - } else if (lines[0].align == 1) { - var l = lines[0].x - lines[0].width - padding; - var r = lines[0].x + padding; - } - var t = topPos - padding; - var b = topPos + totalLineHeight + padding; - for (var i = 1; i < lines.length; i++) { - if (lines[i].align == -1) { - l = Math.min(l, lines[i].x - padding); - r = Math.max(r, lines[i].x + lines[i].width + padding); - } else if (lines[i].align == 0) { - l = Math.min(l, lines[i].x - 0.5 * lines[i].width - padding); - r = Math.max(r, lines[i].x + 0.5 * lines[i].width + padding); - } else if (lines[i].align == 1) { - l = Math.min(l, lines[i].x - lines[i].width - padding); - r = Math.max(r, lines[i].x + padding); - } - } - if (r - l < minTightWidth) { - var alterBy = minTightWidth - (r - l); - l -= alterBy / 2; - r += alterBy / 2; - } - if (b - t < minTightHeight) { - var alterBy = minTightHeight - (b - t); - t -= alterBy / 2; - b += alterBy / 2; - } - - if (box.type == 'loose') { - roundedRect2(ctx,leftLoose,top,maxWidthLoose,maxHeight,box.radius,box.borderWidth,box.borderColor,box.color,box.dash); - } else if (box.type == 'tight') { - roundedRect2(ctx,l,t,r-l,b-t,box.radius,box.borderWidth,box.borderColor,box.color,box.dash); - } else if (box.type == 'flowArrow') { - var left = leftLoose; - var right = left + maxWidthLoose; - var bottom = top + maxHeight; - if (box.dir == 'left') { - var points = [[right,top],[left+box.arrowWidth/2,top],[left-box.arrowWidth/2,(top+bottom)/2],[left+box.arrowWidth/2,bottom],[right,bottom]]; - } else { - var points = [[left,top],[right-box.arrowWidth/2,top],[right+box.arrowWidth/2,(top+bottom)/2],[right-box.arrowWidth/2,bottom],[left,bottom]]; - } - drawPolygon({ctx:ctx,points:points,fillColor:box.color,lineColor:box.borderColor,lineWidth:box.borderWidth,dash:box.dash}); - } - var tightRect = [l,t,r-l,b-t]; - - var returnTextLoc = []; - var returnTextLoc2 = []; - var lineRects = []; - var totalTextWidth = 0; - var lineLocs = []; - - if (boolean(obj.showText,true) == true) { - for (var l = 0; l < lines.length; l++) { - var line = lines[l]; - //console.log(l,line); - - totalTextWidth += line.width; - var y = topPos + line.relY; - if (!un(line.words[0])) { - var style = line.words[0].tags; - } else { - var style = defaultTags; - } - var align2 = line.align == 1 ? 'right' : line.align == 0 ? 'center' : 'left'; - line.text = textArrayCombineAdjacentText(line.text); - - var measure = drawMathsText(ctx,line.text,style.fontSize,line.x,y,false,[],align2,'middle',style.color,'draw',style.backColor,style.bold,style.italic,style.font,style.selected,sf,backgroundColor,fracScale,algPadding); - - lineRects[l] = measure.tightRect; - var textLoc = measure.textLoc; - - for (var i = 0; i < textLoc.length; i++) { - arrayProcess(textLoc[i]); - } - function arrayProcess(arr) { - for (var j = 0; j < arr.length; j++) { - if (arr[j] instanceof Array) { - arrayProcess(arr[j]); - } else if (typeof arr[j] == 'object') { - arr[j].lineNum = l; - } - } - } - - if (line.hardBreak !== true && typeof line.text.last() == 'string' && line.text.last().slice(-1) == ' ' && l < lines.length-1) { - line.softBreakSpace = true; - textLoc[textLoc.length-1].pop(); - } - - var textLoc2Map = mapArray(textLoc,true); - lineLocs[l] = textLoc2Map.length; - - returnTextLoc2 = returnTextLoc2.concat(textLoc); - - /*//if (lines.length > 1) console.log('+',l,textLoc); - if (returnTextLoc.length > 0) { - //console.log('+',l,textLoc[0]); - if (textLoc[0].length == 1) { - returnTextLoc[returnTextLoc.length-1] = returnTextLoc[returnTextLoc.length-1].concat(textLoc[0]); - textLoc.shift(); - } - //console.log(textLoc); - returnTextLoc = returnTextLoc.concat(textLoc); - } else { - returnTextLoc = textLoc.slice(0); - }*/ - } - } - //if (lines.length > 1) console.log('-',returnTextLoc); - - for (var i = returnTextLoc2.length-1; i >= 1; i--) { - if (typeof returnTextLoc2[i][0] == 'object' && typeof returnTextLoc2[i-1][0] == 'object') { - returnTextLoc2[i-1] = returnTextLoc2[i-1].concat(returnTextLoc2[i]); - returnTextLoc2.splice(i,1); - } - } - //if (lines.length > 1) console.log('-',returnTextLoc2); - - var breakCount = 0; - var softBreaks = []; - var softBreakSpaces = []; - var hardBreaks = []; - for (var i = 0; i < lineLocs.length-1; i++) { - breakCount += lineLocs[i]; - if (lines[i].hardBreak == true) { - hardBreaks.push(breakCount); - } else if (lines[i].softBreakSpace == true) { - softBreakSpaces.push(breakCount); - } else { - softBreaks.push(breakCount); - } - } - - //console.log({textLoc:returnTextLoc,tightRect:tightRect,totalTextWidth:totalTextWidth,maxWordWidth:maxWordWidth,softBreaks:softBreaks,hardBreaks:hardBreaks}); - - return { - textLoc:returnTextLoc2, - tightRect:tightRect, - totalTextWidth:totalTextWidth, - //maxWordWidth:maxWordWidth, - softBreaks:softBreaks, - softBreakSpaces:softBreakSpaces, - hardBreaks:hardBreaks, - lineRects:lineRects - }; -} \ No newline at end of file diff --git a/tools/i2/construct.html b/tools/i2/construct.html deleted file mode 100644 index ef3205c..0000000 --- a/tools/i2/construct.html +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - Constructions Tool - - - - - - -
.
-
.
-
.
-
-
-
- -
-
-
- - - - - - \ No newline at end of file diff --git a/tools/i2/fonts/hobo-webfont.eot b/tools/i2/fonts/hobo-webfont.eot deleted file mode 100644 index 1912144..0000000 Binary files a/tools/i2/fonts/hobo-webfont.eot and /dev/null differ diff --git a/tools/i2/fonts/hobo-webfont.svg b/tools/i2/fonts/hobo-webfont.svg deleted file mode 100644 index 11c9be6..0000000 --- a/tools/i2/fonts/hobo-webfont.svg +++ /dev/null @@ -1,706 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tools/i2/fonts/hobo-webfont.ttf b/tools/i2/fonts/hobo-webfont.ttf deleted file mode 100644 index 0651065..0000000 Binary files a/tools/i2/fonts/hobo-webfont.ttf and /dev/null differ diff --git a/tools/i2/fonts/hobo-webfont.woff b/tools/i2/fonts/hobo-webfont.woff deleted file mode 100644 index fe4e4fa..0000000 Binary files a/tools/i2/fonts/hobo-webfont.woff and /dev/null differ diff --git a/tools/i2/fonts/hobo-webfontd41d.eot b/tools/i2/fonts/hobo-webfontd41d.eot deleted file mode 100644 index 1912144..0000000 Binary files a/tools/i2/fonts/hobo-webfontd41d.eot and /dev/null differ diff --git a/tools/i2/fonts/segeo-print-webfont-2.svg b/tools/i2/fonts/segeo-print-webfont-2.svg deleted file mode 100644 index b303e54..0000000 --- a/tools/i2/fonts/segeo-print-webfont-2.svg +++ /dev/null @@ -1,249 +0,0 @@ - - - - -This is a custom SVG webfont generated by Font Squirrel. -Copyright : 2008 The Monotype Corporation All Rights Reserved -Foundry : Microsoft Corporation -Foundry URL : httpwwwmicrosoftcomtypography - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/tools/i2/fonts/segeo-print-webfont.eot b/tools/i2/fonts/segeo-print-webfont.eot deleted file mode 100644 index 823b603..0000000 Binary files a/tools/i2/fonts/segeo-print-webfont.eot and /dev/null differ diff --git a/tools/i2/fonts/segeo-print-webfont.svg b/tools/i2/fonts/segeo-print-webfont.svg deleted file mode 100644 index 2f3181c..0000000 Binary files a/tools/i2/fonts/segeo-print-webfont.svg and /dev/null differ diff --git a/tools/i2/fonts/segeo-print-webfont.ttf b/tools/i2/fonts/segeo-print-webfont.ttf deleted file mode 100644 index c32e039..0000000 Binary files a/tools/i2/fonts/segeo-print-webfont.ttf and /dev/null differ diff --git a/tools/i2/fonts/segeo-print-webfont.woff b/tools/i2/fonts/segeo-print-webfont.woff deleted file mode 100644 index c1ebf42..0000000 Binary files a/tools/i2/fonts/segeo-print-webfont.woff and /dev/null differ diff --git a/tools/i2/fonts/smileymonster.eot b/tools/i2/fonts/smileymonster.eot deleted file mode 100644 index 0cd367e..0000000 Binary files a/tools/i2/fonts/smileymonster.eot and /dev/null differ diff --git a/tools/i2/fonts/smileymonster.svg b/tools/i2/fonts/smileymonster.svg deleted file mode 100644 index 2569e34..0000000 --- a/tools/i2/fonts/smileymonster.svg +++ /dev/null @@ -1,279 +0,0 @@ - - - - -Created by FontForge 20090914 at Fri Feb 24 06:29:58 2012 - By root -Typeface © (Fonts For Peas). 2006. All Rights Reserved http://www.geocities.com/fontsforpeas Free for personal use, contact for commercial use: fontsforpeas@yahoo.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tools/i2/fonts/smileymonster.ttf b/tools/i2/fonts/smileymonster.ttf deleted file mode 100644 index 3f1ec2b..0000000 Binary files a/tools/i2/fonts/smileymonster.ttf and /dev/null differ diff --git a/tools/i2/fonts/smileymonster.woff b/tools/i2/fonts/smileymonster.woff deleted file mode 100644 index 81c75cf..0000000 Binary files a/tools/i2/fonts/smileymonster.woff and /dev/null differ diff --git a/tools/i2/fonts/smileymonsterd41d.eot b/tools/i2/fonts/smileymonsterd41d.eot deleted file mode 100644 index 0cd367e..0000000 Binary files a/tools/i2/fonts/smileymonsterd41d.eot and /dev/null differ