diff --git a/www/js/hugvey_console.js b/www/js/hugvey_console.js index 0b4614d..b278048 100644 --- a/www/js/hugvey_console.js +++ b/www/js/hugvey_console.js @@ -28,7 +28,7 @@ class Panopticon { }, loadNarrative: function( code, file ) { panopticon.hugveys.selectedId = null; - + if(panopticon.hasGraph) { return panopticon.loadNarrative( code, file ); } @@ -79,16 +79,16 @@ class Panopticon { this.socket = new ReconnectingWebSocket( "ws://localhost:8888/ws", null, { debug: false, reconnectInterval: 3000 } ); - + if(this.hasGraph) { this.graph = new Graph(); } - - + + this.socket.addEventListener( 'open', ( e ) => { this.send( { action: 'init' } ); } ); - + // request close before unloading window.addEventListener('beforeunload', function(){ panopticon.socket.close(); @@ -102,7 +102,7 @@ class Panopticon { console.log("Websocket connected") return; } - + let msg = JSON.parse( e.data ); if ( typeof msg['alert'] !== 'undefined' ) { alert( msg['alert'] ); @@ -112,9 +112,9 @@ class Panopticon { console.error( "not a valid message: " + e.data ); return; } - + console.debug(msg); - + switch ( msg['action'] ) { case 'status': @@ -134,28 +134,28 @@ class Panopticon { } } ); } - + updateSelectedHugvey() { let hv = null; - + if(this.hugveys.selectedId) { hv = this.getHugvey(this.hugveys.selectedId); - + if(this.hasGraph) { if(hv.language && this.graph.language_code != hv.language) { this.loadNarrative(hv.language); } } - + // let varEl = document.getElementById("variables"); // varEl.innerHTML = ""; } - + if(this.hasGraph) { this.graph.updateHugveyStatus(hv); } } - + getHugvey(id) { for(let hv of this.hugveys.hugveys) { if(hv.id == id) { @@ -206,7 +206,7 @@ class Panopticon { let graph = this.graph; req.addEventListener( "load", function( e ) { graph.loadData( JSON.parse( this.response ), code ); - // console.log(, e); + // console.log(, e); } ); req.open( "GET", "/local/" + file ); req.send(); @@ -236,7 +236,7 @@ class Panopticon { console.log("Light", hv_id, light_id); this.send( { action: 'change_light', hugvey: hv_id, light_id: light_id } ); } - + playFromSelected(msg_id, reloadStory) { if(!this.hugveys.selectedId) { alert('No hugvey selected'); @@ -337,17 +337,17 @@ class Graph { // used eg. after a condition creation. this.showMsg( this.selectedMsg ); } - + getAudioUrlForMsg(msg) { let isVariable = msg['text'].includes('$') ? '1' : '0'; let lang = panopticon.graph.language_code; return `http://localhost:8888/voice?text=${encodeURIComponent(msg['text'])}&variable=${isVariable}&lang=${lang}&filename=0`; } - + getConfig() { - + } - + getNumericId(prefix) { let id, i = 0; let hasId= function(a, id) { @@ -362,10 +362,10 @@ class Graph { id = prefix + i; i++; } while(hasId(this.data, id)) - + return id; } - + createDiversion(type) { let div = { "@id": this.getNumericId(this.language_code.substring( 0, 2 ) + `-div-${type}#`), @@ -373,7 +373,7 @@ class Graph { 'type': type, 'params': {} } - + if(type == 'no_response') { div['params']['consecutiveSilences'] = 3; div['params']['timesOccured'] = 0; @@ -399,33 +399,33 @@ class Graph { div['params']['msgId'] = ""; } else if(type == 'repeat') { - div['params']['regex'] = "can you repeat that\\?"; + div['params']['regex'] = "can you repeat that\\?"; } else { console.log("invalid type", type); alert('invalid type for diversion'); } - + if(type != 'repeat' && type != 'interrupt') { div['params']['notAfterMsgId'] = ""; } - + this.data.push( div ); this.updateFromData(); this.build(); - + this.showDiversions(); return msg; } - + deleteDiversion(div) { this._rmNode( div ); this.showDiversions( ); } - + showDiversions( ) { let msgEl = document.getElementById( 'msg' ); msgEl.innerHTML = ""; - + let divsNoResponse =[], divsRepeat = [], divsReplyContains = [], divsTimeouts = [], divsInterrupts = []; for(let div of this.diversions) { @@ -448,7 +448,7 @@ class Graph { }}, ...notMsgOptions) ); } - + if(div['type'] == 'no_response') { let returnAttrs = { 'type': 'checkbox', @@ -468,7 +468,7 @@ class Graph { } msgOptions.push(crel('option', optionParams , startMsg['@id'])); } - + divsNoResponse.push(crel( 'div', { 'class': 'diversion', @@ -539,7 +539,7 @@ class Graph { } msgOptions.push(crel('option', optionParams , startMsg['@id'])); } - + divsReplyContains.push(crel( 'div', { 'class': 'diversion', @@ -606,7 +606,7 @@ class Graph { ), notAfterMsgIdEl )); - } + } if(div['type'] == 'timeout') { let returnAttrs = { 'type': 'checkbox', @@ -617,7 +617,7 @@ class Graph { if(div['params']['returnAfterStrand']) { returnAttrs['checked'] = 'checked'; } - + let totalOrLocalAttrs = { 'type': 'checkbox', 'on': { @@ -627,7 +627,7 @@ class Graph { if(div['params']['fromLastMessage']) { totalOrLocalAttrs['checked'] = 'checked'; } - + let msgOptions = [crel('option',"")]; let starts = this.messages.filter( m => m.hasOwnProperty('start') && m['start'] == true); for(let startMsg of starts) { @@ -637,7 +637,7 @@ class Graph { } msgOptions.push(crel('option', optionParams , startMsg['@id'])); } - + divsTimeouts.push(crel( 'div', { 'class': 'diversion', @@ -734,7 +734,7 @@ class Graph { } msgOptions.push(crel('option', optionParams , startMsg['@id'])); } - + divsInterrupts.push(crel( 'div', {'class': 'diversion'}, crel('h3', div['@id']), @@ -753,9 +753,9 @@ class Graph { )); } } - + console.log(divsReplyContains, divsNoResponse, divsRepeat, divsTimeouts, divsInterrupts); - + let divEl = crel( 'div', { @@ -797,7 +797,7 @@ class Graph { 'on': { 'click': (e) => this.createDiversion('repeat') } - }, + }, 'New case for repeat' ) ), @@ -810,7 +810,7 @@ class Graph { 'on': { 'click': (e) => this.createDiversion('timeout') } - }, + }, 'New case for timeout' ) ) @@ -824,12 +824,12 @@ class Graph { // 'on': { // 'click': (e) => this.createDiversion('interrupt') // } -// }, +// }, // 'New case for Interrupt' // ) // ) ); - + msgEl.appendChild(divEl); } @@ -891,19 +891,19 @@ class Graph { }) ) ); - + document.getElementById("interface").appendChild(configEl); } showMsg( msg ) { let msgEl = document.getElementById( 'msg' ); msgEl.innerHTML = ""; - + if(msg == null){ return; } - - + + let startAttributes = { 'name': msg['@id'] + '-start', // 'readonly': 'readonly', @@ -926,7 +926,7 @@ class Graph { if ( msg['beginning'] == true ) { beginningAttributes['checked'] = 'checked'; } - + // chapter marker: let chapterAttributes = { 'name': msg['@id'] + '-chapterStart', @@ -939,14 +939,14 @@ class Graph { if ( typeof msg['chapterStart'] !== 'undefined' && msg['chapterStart'] == true ) { chapterAttributes['checked'] = 'checked'; } - + let params = {}; if(msg.hasOwnProperty('params')) { params = msg['params']; } else { msg['params'] = {}; } - + let audioSrcEl = crel('source', {'src': msg['audio'] ? msg['audio']['file'] : this.getAudioUrlForMsg(msg)}); let audioSpan = crel( 'span', @@ -1092,7 +1092,7 @@ class Graph { } } ) ), - + // color for beter overview crel( 'label', @@ -1110,9 +1110,9 @@ class Graph { ) ); msgEl.appendChild( msgInfoEl ); - - + + if(panopticon.hugveys.selectedId) { msgEl.appendChild(crel( 'div', @@ -1148,9 +1148,9 @@ class Graph { "Continue on #" + panopticon.hugveys.selectedId ) )); - + } - + // let directionHEl = document.createElement('h2'); // directionHEl.innerHTML = "Directions"; @@ -1207,13 +1207,13 @@ class Graph { 'on': { 'click': ( e ) => { if(confirm("Do you want to remove this direction and its conditions?")) { - g.rmDirection( direction ); + g.rmDirection( direction ); } } } }, 'disconnect') ); - + for ( let conditionId of direction['conditions'] ) { let condition = this.getNodeById( conditionId ); directionEl.appendChild( this.getEditConditionFormEl( condition, direction ) ); @@ -1233,7 +1233,7 @@ class Graph { 'click': ( e ) => { if(confirm("Do you want to remove this condition?")) { // console.log('remove condition for direction', condition, direction); - panopticon.graph.rmCondition( condition, direction ); + panopticon.graph.rmCondition( condition, direction ); } } } @@ -1251,7 +1251,7 @@ class Graph { } ); labelLabel.appendChild( labelInput ); conditionEl.appendChild( labelLabel ); - + // for ( let v in condition['vars'] ) { // let varLabel = document.createElement( 'label' ); @@ -1296,14 +1296,14 @@ class Graph { } }; } - + getConditionInputsForType( type, conditionId, values ) { let inputs = []; let vars = this.getConditionTypes()[type]; for ( let v in vars ) { let attr = vars[v]; let inputType = attr.hasOwnProperty('tag') ? attr['tag'] : 'input'; - + attr['name'] = typeof conditionId == 'undefined' ? v : `${conditionId}-vars.${v}`; if(typeof values != 'undefined') { let value = this._getValueForPath(v, values); @@ -1313,12 +1313,12 @@ class Graph { } attr['value'] = typeof value == 'undefined' ? "": value; attr['on'] = { - 'change': this.getEditEventListener() + 'change': this.getEditEventListener() } ; } else { // console.log(attr); } - + inputs.push( crel( 'label', crel( 'span', { @@ -1339,7 +1339,7 @@ class Graph { conditionForm.appendChild(i); } } - + _getValueForPath(path, vars) { path = path.split( '.' ); // use vars.test to set ['vars']['test'] = value let v = vars; @@ -1359,7 +1359,7 @@ class Graph { } return result; } - + /** * Save an array path (string) with a value to an object. Used to turn * strings into nested arrays @@ -1408,7 +1408,7 @@ class Graph { form.delete( 'type' ); let label = form.get( 'label' ); form.delete( 'label' ); - + // checkboxes to true/false let defs = g.getConditionTypes()[type]; // console.log(defs); @@ -1419,13 +1419,13 @@ class Graph { form.set(field, form.has(field)); } } - + let vars = {}; for ( var pair of form.entries() ) { // FormData only has strings & blobs, we want booleans: if(pair[1] === 'true') pair[1] = true; - if(pair[1] === 'false') pair[1] = false; - + if(pair[1] === 'false') pair[1] = false; + vars = g._formPathToVars(pair[0], pair[1], vars); } // TODO: checkboxes @@ -1468,7 +1468,7 @@ class Graph { return addConditionEl; } - + /** * remove condition from the graph or merely from the given direction * @param {any} condition The condition to remove @@ -1483,7 +1483,7 @@ class Graph { if(pos > -1) { direction['conditions'].splice(pos, 1); } - + for(let dir of this.directions) { // console.log('check if condition exists for dir', dir) if(dir['conditions'].indexOf(id) > -1) { @@ -1534,14 +1534,14 @@ class Graph { "afterrunTime": 0.5, } this.data.push( msg ); - + console.log("skip or not to skip?", skipRebuild); if(typeof skipRebuild == 'undefined' || !skipRebuild) { this.updateFromData(); this.build(); this.selectMsg(msg); } - + return msg; } @@ -1598,7 +1598,7 @@ class Graph { "conditions": [] } this.data.push( dir ); - + let skipDistances; // orphaned target and source has no other destinations. We can copy the vertical position: if(this.getDirectionsFrom( source ).length < 1 && this.getDirectionsFrom( target ).length < 1 && this.getDirectionsTo( target ).length < 1) { @@ -1607,11 +1607,11 @@ class Graph { let d = [distance[0] + 1, distance[1]]; // create a distance based on source's position // this saves us from running the slow calculateDistancesFromStart - this.distances[target['@id']] = d; + this.distances[target['@id']] = d; } else { skipDistances = false; } - + this.updateFromData(skipDistances); this.build(); return dir; @@ -1626,18 +1626,18 @@ class Graph { this.addMsg(); this.build(); } - + createConnectedMsg(sourceMsg) { console.time('createConnected'); console.time("Add"); let newMsg = this.addMsg(true); // skipRebuild = true, as addDirection() already rebuilds the graph this.getNodeById(newMsg['@id']).y = this.getNodeById(sourceMsg['@id']).y; - + if(this.getNodeById(sourceMsg['@id']).hasOwnProperty('color')){ - this.getNodeById(newMsg['@id']).color = this.getNodeById(sourceMsg['@id']).color + this.getNodeById(newMsg['@id']).color = this.getNodeById(sourceMsg['@id']).color } console.timeEnd("Add"); - + console.time("direction"); this.addDirection(sourceMsg, newMsg); console.timeEnd("direction"); @@ -1664,15 +1664,15 @@ class Graph { let graph = this; let el = function( e ) { console.info("Changed", e); - let parts = e.srcElement.name.split( '-' ); + let parts = e.target.name.split( '-' ); let field = parts.pop(); let id = parts.join('-'); let node = graph.getNodeById( id ); let path = field.split( '.' ); // use vars.test to set ['vars']['test'] = value var res = node; - let value = e.srcElement.value - if(e.srcElement.type == 'checkbox') { - value = e.srcElement.checked; + let value = e.target.value + if(e.target.type == 'checkbox') { + value = e.target.checked; } for ( var i = 0; i < path.length; i++ ) { if ( i == ( path.length - 1 ) ) { @@ -1685,7 +1685,7 @@ class Graph { // node[field] = e.srcElement.value; graph.build(); - + if(typeof callback !== 'undefined'){ callback(); } @@ -1756,11 +1756,11 @@ class Graph { console.info("Save json", formData ); var request = new XMLHttpRequest(); request.open( "POST", "http://localhost:8888/upload" ); - + if(callback) { request.addEventListener( "load", callback); } - + request.send( formData ); } @@ -1776,13 +1776,13 @@ class Graph { this.directions = this.data.filter(( node ) => node['@type'] == 'Direction' ); this.conditions = this.data.filter(( node ) => node['@type'] == 'Condition' ); this.diversions = this.data.filter(( node ) => node['@type'] == 'Diversion' ); - + let configurations = this.data.filter(( node ) => node['@type'] == 'Configuration' ); this.configuration = configurations.length > 0 ? configurations[0] : { "@id": "config", "@type": "Configuration" }; - + document.getElementById('current_lang').innerHTML = ""; document.getElementById('current_lang').appendChild(crel('span', { 'class': 'flag-icon ' + this.language_code @@ -1790,7 +1790,7 @@ class Graph { let storyEl = document.getElementById('story'); storyEl.classList.remove(... panopticon.languages.map((l) => l['code'])) storyEl.classList.add(this.language_code); - + if(typeof skipDistances == 'undefined' || !skipDistances) { this.distances = this.calculateDistancesFromStart(); } @@ -1798,7 +1798,7 @@ class Graph { // save state; this.saveState(); } - + updateHugveyStatus(hv) { let els = document.getElementsByClassName('beenHit'); while(els.length > 0) { @@ -1807,11 +1807,11 @@ class Graph { if(!hv || typeof hv['history'] == 'undefined') { return; } - + if(hv['history'].hasOwnProperty('messages')){ for(let msg of hv['history']['messages']) { document.getElementById(msg[0]['id']).classList.add('beenHit'); - } + } } if(hv['history'].hasOwnProperty('directions')){ for(let msg of hv['history']['directions']) { @@ -1844,7 +1844,7 @@ class Graph { return fx; }).strength(50)) .force( "forceY", d3.forceY(function(m){ -// if(panopticon.graph.distances[m['@id']] !== null ) +// if(panopticon.graph.distances[m['@id']] !== null ) // console.log(panopticon.graph.distances[m['@id']][1]); let fy = panopticon.graph.distances[m['@id']] !== null ? panopticon.graph.distances[m['@id']][1] * panopticon.graph.nodeSize * 3: 0 // console.log('fx', m['@id'], panopticon.graph.distances[m['@id']], fx); @@ -1859,7 +1859,7 @@ class Graph { .selectAll( "g" ) .data( this.messages, n => n['@id'] ) ; - + // Update existing nodes let newNode = node.enter(); @@ -1874,7 +1874,7 @@ class Graph { .attr( 'r', this.nodeSize ) // .text(d => d.id) ; - + let textId = newNodeG.append( "text" ).attr( 'class', 'msg_id' ); let textContent = newNodeG.append( "text" ).attr( 'class', 'msg_txt' ); let statusIcon = newNodeG.append( "image" ) @@ -1888,7 +1888,7 @@ class Graph { // remove node.exit().remove(); node = node.merge( newNodeG ); - + // for all existing nodes: node.attr( 'class', msg => { @@ -1903,9 +1903,9 @@ class Graph { return classes.join( ' ' ); } ) - + .on(".drag", null) - .call( + .call( d3.drag( this.simulation ) .on("start", function(d){ if (!d3.event.active) panopticon.graph.simulation.alphaTarget(0.3).restart(); @@ -1922,9 +1922,9 @@ class Graph { d.fy = null; }) // .container(document.getElementById('container')) - + ); - + node.select('circle').attr('style', (d) => 'fill: ' + (d.hasOwnProperty('color') ? d['color'] : '#77618e')); let link = this.linkG @@ -1934,7 +1934,7 @@ class Graph { let newLink = link.enter() .append( "line" ) ; - + //remove link.exit().remove(); link = link.merge( newLink ); @@ -2019,7 +2019,7 @@ class Graph { } return this.svg.node(); } - + calculateDistancesFromStart() { console.time('calculateDistancesFromStart'); let starts = this.messages.filter( m => m.hasOwnProperty('start') && m['start'] == true); @@ -2027,26 +2027,26 @@ class Graph { console.error("No start set"); return; } - + //initiate distances let distances = {}; for(let msg of this.messages) { // distances[msg['@id']] = msg === startMsg ? 0 : null; distances[msg['@id']] = null; } - + let targetsPerMsg = {}; let sourcesPerMsg = {}; // console.log("dir", this.directions); for(let direction of this.directions) { let from = typeof direction['source'] == "string" ? direction['source'] : direction['source']['@id']; let to = typeof direction['target'] == "string" ? direction['target'] : direction['target']['@id']; - + if(!targetsPerMsg.hasOwnProperty(from)) { targetsPerMsg[from] = []; } targetsPerMsg[from].push(to); - + if(!sourcesPerMsg.hasOwnProperty(to)) { sourcesPerMsg[to] = []; @@ -2061,21 +2061,21 @@ class Graph { // end of trail return yPos; } - - + + let i = 0, y =0; for(let childMsgId of msgsPerMsg[msgId]) { if(distances[childMsgId] !== null){ continue; } if(distances[childMsgId] === null || (goingDown && distances[childMsgId][0] > depth)) { - + if(distances[childMsgId] === null) { if(i > 0){ yPos++; } i++; - + console.log('set for id', childMsgId, goingDown, depth, yPos); distances[childMsgId] = [depth, yPos]; @@ -2093,7 +2093,7 @@ class Graph { if(distances[childMsgId] === null) { distances[childMsgId] = [depth, yPos]; } - + // console.log('a', depth); yPos = traverseMsg(childMsgId, depth - 1, goingDown, yPos); } else { @@ -2101,7 +2101,7 @@ class Graph { } } - + // if( i == 0 && y == 1) { // // we reached an item that branches back into the tree // return yPos -1; @@ -2109,7 +2109,7 @@ class Graph { // console.log('yPos',msgId,yPos); return yPos; } - + let yPos = 0; console.time('step1'); for(let startMsg of starts) { @@ -2135,7 +2135,7 @@ class Graph { console.timeEnd('polish: '+ msgId); } console.timeEnd('step2'); - + // let additionalsDepth = 0; //// now the secondary strands: // for(let msgId in distances) { @@ -2145,11 +2145,11 @@ class Graph { // } // distances[msgId] = additionalsDepth; // traverseMsg(msgId, additionalsDepth+1, true); -// +// // } console.timeEnd("calculateDistancesFromStart"); return distances; } } // -// \ No newline at end of file +//