editor-live.js 101 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453
  1. "use strict";
  2. // Copyright 2012 United States Government, as represented by the Secretary of Defense, Under
  3. // Secretary of Defense (Personnel & Readiness).
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
  6. // in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed under the License
  11. // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
  12. // or implied. See the License for the specific language governing permissions and limitations under
  13. // the License.
  14. /// vwf/view/editor creates a view interface for editor functions.
  15. ///
  16. /// @module vwf/view/editor
  17. /// @requires version
  18. /// @requires vwf/view
  19. /// @requires vwf/utility
  20. define( [
  21. "module",
  22. "version",
  23. "vwf/view",
  24. "vwf/utility",
  25. "vwf/view/lib/ace/ace",
  26. "jquery",
  27. "jquery-ui",
  28. "jquery-encoder-0.1.0"
  29. ], function( module, version, view, utility, ace, $ ) {
  30. return view.load( module, {
  31. // == Module Definition ====================================================================
  32. initialize: function() {
  33. var self = this;
  34. this.ace = window.ace;
  35. this.nodes = {};
  36. this.scenes = {};
  37. this.allScripts = {};
  38. // EDITOR CLOSED --> 0
  39. // HIERARCHY OPEN --> 1
  40. // USER LIST OPEN --> 2
  41. // TIMELINE OPEN --> 3
  42. // ABOUT OPEN --> 4
  43. this.editorView = 0;
  44. this.editorOpen = false;
  45. this.timelineInit = false;
  46. this.aboutInit = false;
  47. this.codeEditorInit = false;
  48. this.modelsInit = false;
  49. this.editingScript = false;
  50. this.topdownName = '#topdown_a';
  51. this.topdownTemp = '#topdown_b';
  52. this.clientList = '#client_list';
  53. this.timeline = '#time_control';
  54. this.about = '#about_tab';
  55. this.codeEditor = '#codeEditor_tab';
  56. this.models = '#model_a';
  57. this.modelsTemp = '#model_b';
  58. this.currentNodeID = '';
  59. this.currentModelID = '';
  60. this.currentModelURL = '';
  61. this.highlightedChild = '';
  62. this.intervalTimer = 0;
  63. this.activeCameraID = undefined;
  64. $(document.head).append('<style type="text/css" media="screen"> #editorlive { height: 500px; width: 800px; } </style>');
  65. $('body').append(
  66. "<div id='editor' class='relClass'>\n" +
  67. " <div class='uiContainer'>\n" +
  68. " <div class='editor-tabs' id='tabs'>\n" +
  69. " <img id='x' style='display:none' src='images/tab_X.png' alt='x' />\n" +
  70. " <img id='hierarchy' src='images/tab_Application.png' alt='application' />\n" +
  71. " <img id='userlist' src='images/tab_Users.png' alt='users' />\n" +
  72. " <img id='timeline' src='images/tab_Time.png' alt='time' />\n" +
  73. " <img id='models' src='images/tab_Models.png' alt='models' />\n" +
  74. " <img id='about' src='images/tab_About.png' alt='about' />\n" +
  75. " <img id='codeEditor' src='images/tab_CodeEditor.png' alt='code' />\n" +
  76. " </div>\n" +
  77. " </div>\n" +
  78. "</div>" +
  79. "<div class='relClass'><div class='uiContainer'><div class='vwf-tree' id='topdown_a'></div></div></div>" +
  80. "<div class='relClass'><div class='uiContainer'><div class='vwf-tree' id='topdown_b'></div></div></div>" +
  81. "<div class='relClass'><div class='uiContainer'><div class='vwf-tree' id='client_list'></div></div></div>" +
  82. "<div class='relClass'><div class='uiContainer'><div class='vwf-tree' id='time_control'></div></div></div>" +
  83. "<div class='relClass'><div class='uiContainer'><div class='vwf-tree' id='about_tab'></div></div></div>" +
  84. "<div class='relClass'><div class='uiContainer'><div class='vwf-tree' id='codeEditor_tab'></div></div></div>" +
  85. "<div class='relClass'><div class='uiContainer'><div class='vwf-tree' id='model_a'></div></div></div>" +
  86. "<div class='relClass'><div class='uiContainer'><div class='vwf-tree' id='model_b'></div></div></div>"
  87. );
  88. $('#tabs').stop().animate({ opacity:0.0 }, 0);
  89. $('#tabs').mouseenter( function(evt) {
  90. evt.stopPropagation();
  91. $('#tabs').stop().animate({ opacity:1.0 }, 175);
  92. return false;
  93. });
  94. $('#tabs').mouseleave( function(evt) {
  95. evt.stopPropagation();
  96. $('#tabs').stop().animate({ opacity:0.0 }, 175);
  97. return false;
  98. });
  99. $('#hierarchy').click ( function(evt) {
  100. openEditor.call(self, 1);
  101. });
  102. $('#userlist').click ( function(evt) {
  103. openEditor.call(self, 2);
  104. });
  105. $('#timeline').click ( function(evt) {
  106. openEditor.call(self, 3);
  107. });
  108. $('#about').click ( function(evt) {
  109. openEditor.call(self, 4);
  110. });
  111. $('#models').click ( function(evt) {
  112. openEditor.call(self, 5);
  113. });
  114. $('#codeEditor').click ( function(evt) {
  115. openEditor.call(self, 6);
  116. });
  117. $('#x').click ( function(evt) {
  118. closeEditor.call(self);
  119. });
  120. $('#topdown_a').hide();
  121. $('#topdown_b').hide();
  122. $('#client_list').hide();
  123. $('#time_control').hide();
  124. $('#about_tab').hide();
  125. $('#codeEditor_tab').hide();
  126. $('#model_a').hide();
  127. $('#model_b').hide();
  128. var canvas = document.getElementById(vwf_view.kernel.find("", "/")[0]);
  129. if ( canvas ) {
  130. $('#topdown_a').height(canvas.height);
  131. $('#topdown_b').height(canvas.height);
  132. $('#client_list').height(canvas.height);
  133. $('#time_control').height(canvas.height);
  134. $('#about_tab').height(canvas.height);
  135. $('#codeEditor_tab').height(canvas.height);
  136. $('#model_a').height(canvas.height);
  137. $('#model_b').height(canvas.height);
  138. }
  139. else
  140. {
  141. $('#topdown_a').height(window.innerHeight-20);
  142. $('#topdown_b').height(window.innerHeight-20);
  143. $('#client_list').height(window.innerHeight-20);
  144. $('#time_control').height(window.innerHeight-20);
  145. $('#about_tab').height(window.innerHeight-20);
  146. $('#codeEditor_tab').height(window.innerHeight-20);
  147. $('#model_a').height(window.innerHeight-20);
  148. $('#model_b').height(window.innerHeight-20);
  149. }
  150. },
  151. createdNode: function( nodeID, childID, childExtendsID, childImplementsIDs,
  152. childSource, childType, childIndex, childName, callback /* ( ready ) */ ) {
  153. var nodeIDAttribute = $.encoder.encodeForHTMLAttribute("id", nodeID, true);
  154. var childIDAttribute = $.encoder.encodeForHTMLAttribute("id", childID, true);
  155. var childIDAlpha = $.encoder.encodeForAlphaNumeric(childID);
  156. var kernel = this.kernel;
  157. var self = this;
  158. var parent = this.nodes[ nodeID ];
  159. var node = this.nodes[ childID ] = {
  160. children: [],
  161. properties: [],
  162. events: {},
  163. methods: {},
  164. parent: parent,
  165. parentID: nodeID,
  166. ID: childID,
  167. extendsID: childExtendsID,
  168. implementsIDs: childImplementsIDs,
  169. source: childSource,
  170. name: childName,
  171. };
  172. if ( parent ) {
  173. parent.children.push( node );
  174. }
  175. if ( childID == vwf_view.kernel.find("", "/")[0] && childExtendsID && this.kernel.test( childExtendsID,
  176. "self::element(*,'http://vwf.example.com/aframe/ascene.vwf')", childExtendsID ) ) {
  177. this.scenes[ childID ] = node;
  178. }
  179. if ( nodeID === this.currentNodeID && this.editingScript == false )
  180. {
  181. $('#children > div:last').css('border-bottom-width', '1px');
  182. $("#children").append("<div id='" + childIDAlpha + "' data-nodeID='" + childIDAttribute + "' class='childContainer'><div class='childEntry'><b>" + $.encoder.encodeForHTML(childName) + "</b></div></div>");
  183. $('#' + childIDAlpha).click( function(evt) {
  184. drillDown.call(self, $(this).attr("data-nodeID"), nodeIDAttribute);
  185. });
  186. $('#children > div:last').css('border-bottom-width', '3px');
  187. }
  188. if ( nodeID === this.kernel.application() && childName === 'camera' ) {
  189. this.activeCameraID = childID;
  190. }
  191. },
  192. createdProperty: function (nodeID, propertyName, propertyValue) {
  193. return this.initializedProperty(nodeID, propertyName, propertyValue);
  194. },
  195. initializedProperty: function (nodeID, propertyName, propertyValue) {
  196. var node = this.nodes[ nodeID ];
  197. if ( ! node ) return; // TODO: patch until full-graph sync is working; drivers should be able to assume that nodeIDs refer to valid objects
  198. var property = node.properties[ propertyName ] = createProperty.call( this, node, propertyName, propertyValue );
  199. node.properties.push( property );
  200. },
  201. deletedNode: function (nodeID) {
  202. var node = this.nodes[ nodeID ];
  203. node.parent.children.splice( node.parent.children.indexOf(node), 1 );
  204. delete this.nodes[ nodeID ];
  205. var nodeIDAttribute = $.encoder.encodeForAlphaNumeric(nodeID); // $.encoder.encodeForHTMLAttribute("id", nodeID, true);
  206. $('#' + nodeIDAttribute).remove();
  207. $('#children > div:last').css('border-bottom-width', '3px');
  208. },
  209. //addedChild: [ /* nodeID, childID, childName */ ],
  210. //removedChild: [ /* nodeID, childID */ ],
  211. satProperty: function (nodeID, propertyName, propertyValue) {
  212. var node = this.nodes[ nodeID ];
  213. if ( ! node ) return; // TODO: patch until full-graph sync is working; drivers should be able to assume that nodeIDs refer to valid objects
  214. // It is possible for a property to have satProperty called for it without ever getting an
  215. // initializedProperty (if that property delegated to itself or another on replication)
  216. // Catch that case here and create the property
  217. if ( ! node.properties[ propertyName ] ) {
  218. var property = node.properties[ propertyName ] = createProperty.call( this, node, propertyName, propertyValue );
  219. node.properties.push( property );
  220. }
  221. if ( propertyName === "activeCamera" ) {
  222. if ( this.nodes[ propertyValue ] !== undefined ) {
  223. this.activeCameraID = propertyValue;
  224. }
  225. }
  226. try {
  227. propertyValue = utility.transform( propertyValue, utility.transforms.transit );
  228. node.properties[ propertyName ].value = JSON.stringify( propertyValue );
  229. node.properties[ propertyName ].rawValue = propertyValue ;
  230. } catch (e) {
  231. this.logger.warnx( "satProperty", nodeID, propertyName, propertyValue,
  232. "stringify error:", e.message );
  233. node.properties[ propertyName ].value = propertyValue;
  234. }
  235. if ( ( this.editorView == 1 ) && ( this.currentNodeID == nodeID ) ) {
  236. var nodeIDAttribute = $.encoder.encodeForAlphaNumeric(nodeID); // $.encoder.encodeForHTMLAttribute("id", nodeID, true);
  237. var propertyNameAttribute = $.encoder.encodeForAlphaNumeric("id", propertyName, true);
  238. // No need to escape propertyValue, because .val does its own escaping
  239. $( '#input-' + nodeIDAttribute + '-' + propertyNameAttribute ).val( node.properties[ propertyName ].getValue() );
  240. }
  241. },
  242. //gotProperty: [ /* nodeID, propertyName, propertyValue */ ],
  243. createdMethod: function( nodeID, methodName, methodParameters, methodBody ){
  244. var node = this.nodes[ nodeID ];
  245. if ( node ) {
  246. node.methods[ methodName ] = methodParameters;
  247. }
  248. },
  249. //calledMethod: function( nodeID, methodName, methodParameters, methodValue ) {
  250. //},
  251. createdEvent: function( nodeID, eventName, eventParameters ) {
  252. var node = this.nodes[ nodeID ];
  253. if ( node ) {
  254. node.events[ eventName ] = eventParameters;
  255. }
  256. },
  257. firedEvent: function ( nodeID, eventName, eventParameters ) {
  258. if(eventName == "pointerHover") {
  259. highlightChildInHierarchy.call(this, nodeID);
  260. }
  261. },
  262. executed: function( nodeID, scriptText, scriptType ) {
  263. // var nodeScript = {
  264. // text: scriptText,
  265. // type: scriptType,
  266. // };
  267. // if ( !this.allScripts[ nodeID ] ) {
  268. // var nodeScripts = new Array();
  269. // nodeScripts.push(nodeScript);
  270. // this.allScripts[ nodeID ] = nodeScripts;
  271. // }
  272. // else {
  273. // this.allScripts[ nodeID ].push(nodeScript);
  274. // }
  275. },
  276. //ticked: [ /* time */ ],
  277. } );
  278. // -- getChildByName --------------------------------------------------------------------
  279. function getChildByName( node, childName ) {
  280. var childNode = undefined;
  281. for ( var i = 0; i < node.children.length && childNode === undefined; i++ ) {
  282. if ( node.children[i].name == childName ) {
  283. childNode = node.children[i];
  284. }
  285. }
  286. return childNode;
  287. };
  288. function updateCameraProperties () {
  289. if ( this.currentNodeID == this.activeCameraID ) {
  290. if ( !this.intervalTimer ) {
  291. var self = this;
  292. this.intervalTimer = setInterval( function() { updateProperties.call( self, self.activeCameraID ) }, 200 );
  293. }
  294. }
  295. else {
  296. if ( this.intervalTimer ) {
  297. clearInterval( this.intervalTimer );
  298. this.intervalTimer = 0;
  299. }
  300. }
  301. }
  302. function updateProperties( nodeName ) {
  303. var nodeID = nodeName;
  304. var properties = getProperties.call( this, this.kernel, nodeID );
  305. for ( var i in properties ) {
  306. try {
  307. var propertyName = properties[i].prop.name;
  308. var propertyValue = JSON.stringify( utility.transform( vwf.getProperty( nodeID, propertyName, [] ), utility.transforms.transit ));
  309. } catch ( e ) {
  310. this.logger.warnx( "satProperty", nodeID, propertyName, propertyValue, "stringify error:", e.message );
  311. }
  312. if ( propertyValue ) {
  313. var nodeIDAttribute = $.encoder.encodeForAlphaNumeric( nodeID );
  314. var propertyNameAttribute = $.encoder.encodeForHTMLAttribute( "id", propertyName, true );
  315. var inputElement$ = $( '#input-' + nodeIDAttribute + '-' + propertyNameAttribute );
  316. // Only update if property value input is not in focus
  317. // If in focus, change font style to italic
  318. if ( ! inputElement$.is(":focus") ) {
  319. inputElement$.val( propertyValue );
  320. inputElement$.css( "font-style", "normal");
  321. } else {
  322. inputElement$.css( "font-style", "italic");
  323. }
  324. }
  325. }
  326. }
  327. // -- openEditor ------------------------------------------------------------------------
  328. function openEditor(eView) // invoke with the view as "this"
  329. {
  330. if(eView == 0)
  331. {
  332. closeEditor.call(this);
  333. }
  334. if(this.editorView != eView)
  335. {
  336. // Hierarchy
  337. if(eView == 1)
  338. {
  339. var topdownName = this.topdownName;
  340. var topdownTemp = this.topdownTemp;
  341. if( !this.currentNodeID )
  342. {
  343. this.currentNodeID = vwf_view.kernel.find("", "/")[0];
  344. }
  345. drill.call(this, this.currentNodeID, undefined);
  346. $(this.clientList).hide();
  347. $(this.timeline).hide();
  348. $(this.about).hide();
  349. $(this.codeEditor).hide();
  350. $(this.models).hide();
  351. if(this.editorOpen)
  352. {
  353. $(topdownName).hide();
  354. $(topdownTemp).show();
  355. }
  356. else
  357. {
  358. $(topdownTemp).show('slide', {direction: 'right'}, 175);
  359. }
  360. this.topdownName = topdownTemp;
  361. this.topdownTemp = topdownName;
  362. }
  363. else if (this.editingScript)
  364. {
  365. // Reset width if on script
  366. this.editingScript = false;
  367. $('#editor').animate({ 'left' : "-260px" }, 175);
  368. $('.vwf-tree').animate({ 'width' : "260px" }, 175);
  369. }
  370. // User List
  371. if(eView == 2)
  372. {
  373. $(this.topdownName).hide();
  374. $(this.topdownTemp).hide();
  375. $(this.timeline).hide();
  376. $(this.about).hide();
  377. $(this.codeEditor).hide();
  378. $(this.models).hide();
  379. $(this.modelsTemp).hide();
  380. showUserList.call(this);
  381. }
  382. // Timeline
  383. else if(eView == 3)
  384. {
  385. $(this.topdownName).hide();
  386. $(this.topdownTemp).hide();
  387. $(this.clientList).hide();
  388. $(this.about).hide();
  389. $(this.codeEditor).hide();
  390. $(this.models).hide();
  391. $(this.modelsTemp).hide();
  392. showTimeline.call(this);
  393. }
  394. // About
  395. else if(eView == 4)
  396. {
  397. $(this.topdownName).hide();
  398. $(this.topdownTemp).hide();
  399. $(this.clientList).hide();
  400. $(this.timeline).hide();
  401. $(this.models).hide();
  402. $(this.modelsTemp).hide();
  403. $(this.codeEditor).hide();
  404. showAboutTab.call(this);
  405. }
  406. // Models
  407. else if(eView == 5)
  408. {
  409. var models = this.models;
  410. var modelsTemp = this.modelsTemp;
  411. showModelsTab.call(this, this.currentModelID, this.currentModelURL);
  412. $(this.topdownName).hide();
  413. $(this.topdownTemp).hide();
  414. $(this.clientList).hide();
  415. $(this.timeline).hide();
  416. $(this.about).hide();
  417. $(this.codeEditor).hide();
  418. if(this.editorOpen)
  419. {
  420. $(models).hide();
  421. $(modelsTemp).show();
  422. }
  423. else
  424. {
  425. $(modelsTemp).show('slide', {direction: 'right'}, 175);
  426. }
  427. this.models = modelsTemp;
  428. this.modelsTemp = models;
  429. }
  430. // Code Editor
  431. else if(eView == 6)
  432. {
  433. $(this.topdownName).hide();
  434. $(this.topdownTemp).hide();
  435. $(this.clientList).hide();
  436. $(this.timeline).hide();
  437. $(this.models).hide();
  438. $(this.modelsTemp).hide();
  439. $(this.about).hide();
  440. showCodeEditorTab.call(this);
  441. }
  442. if(this.editorView == 0)
  443. {
  444. $('#vwf-root').animate({ 'left' : "-=260px" }, 175);
  445. $('#editor').animate({ 'left' : "-260px" }, 175);
  446. $('#x').delay(1000).css({ 'display' : 'inline' });
  447. }
  448. this.editorView = eView;
  449. this.editorOpen = true;
  450. }
  451. }
  452. // -- closeEditor -----------------------------------------------------------------------
  453. function closeEditor() // invoke with the view as "this"
  454. {
  455. var topdownName = this.topdownName;
  456. if (this.editorOpen && this.editorView == 1) // Hierarchy view open
  457. {
  458. $(topdownName).hide('slide', {direction: 'right'}, 175);
  459. $(topdownName).empty();
  460. $(this.clientList).hide();
  461. $(this.timeline).hide();
  462. $(this.about).hide();
  463. $(this.codeEditor).hide();
  464. $(this.models).hide();
  465. }
  466. else if (this.editorOpen && this.editorView == 2) // Client list open
  467. {
  468. $(this.clientList).hide('slide', {direction: 'right'}, 175);
  469. $(topdownName).hide();
  470. $(this.timeline).hide();
  471. $(this.about).hide();
  472. $(this.codeEditor).hide();
  473. $(this.models).hide();
  474. }
  475. else if (this.editorOpen && this.editorView == 3) // Timeline open
  476. {
  477. $(this.timeline).hide('slide', {direction: 'right'}, 175);
  478. $(topdownName).hide();
  479. $(this.clientList).hide();
  480. $(this.about).hide();
  481. $(this.models).hide();
  482. }
  483. else if (this.editorOpen && this.editorView == 4) // About open
  484. {
  485. $(this.about).hide('slide', {direction: 'right'}, 175);
  486. $(this.codeEditor).hide();
  487. $(topdownName).hide();
  488. $(this.clientList).hide();
  489. $(this.timeline).hide();
  490. $(this.models).hide();
  491. }
  492. else if (this.editorOpen && this.editorView == 5) // Models open
  493. {
  494. $(this.models).hide('slide', {direction: 'right'}, 175);
  495. $(topdownName).hide();
  496. $(this.clientList).hide();
  497. $(this.timeline).hide();
  498. $(this.about).hide();
  499. $(this.codeEditor).hide();
  500. }
  501. else if (this.editorOpen && this.editorView == 6) // Code Editor open
  502. {
  503. $(this.codeEditor).hide('slide', {direction: 'right'}, 175);
  504. $(this.about).hide();
  505. $(topdownName).hide();
  506. $(this.clientList).hide();
  507. $(this.timeline).hide();
  508. $(this.models).hide();
  509. }
  510. $('#vwf-root').animate({ 'left' : "+=260px" }, 175);
  511. $('#editor').animate({ 'left' : "0px" }, 175);
  512. $('#x').css({ 'display' : 'none' });
  513. this.editorView = 0;
  514. this.editorOpen = false;
  515. }
  516. // -- showUserList ----------------------------------------------------------------------
  517. function showUserList() // invoke with the view as "this"
  518. {
  519. var clientList = this.clientList;
  520. viewClients.call(this);
  521. if (!this.editorOpen)
  522. {
  523. $(clientList).show('slide', {direction: 'right'}, 175);
  524. }
  525. else
  526. {
  527. $(clientList).show();
  528. }
  529. }
  530. // -- viewClients -----------------------------------------------------------------------
  531. function viewClients() {
  532. var self = this;
  533. var app = window.location.pathname;
  534. var pathSplit = app.split('/');
  535. if ( pathSplit[0] == "" ) {
  536. pathSplit.shift();
  537. }
  538. if ( pathSplit[ pathSplit.length - 1 ] == "" ) {
  539. pathSplit.pop();
  540. }
  541. var instIndex = pathSplit.length - 1;
  542. if ( pathSplit.length > 2 ) {
  543. if ( pathSplit[ pathSplit.length - 2 ] == "load" ) {
  544. instIndex = pathSplit.length - 3;
  545. }
  546. }
  547. if ( pathSplit.length > 3 ) {
  548. if ( pathSplit[ pathSplit.length - 3 ] == "load" ) {
  549. instIndex = pathSplit.length - 4;
  550. }
  551. }
  552. var root = "";
  553. for ( var i=0; i < instIndex; i++ ) {
  554. if ( root != "" ) {
  555. root = root + "/";
  556. }
  557. root = root + pathSplit[i];
  558. }
  559. if(root.indexOf('.vwf') != -1) root = root.substring(0, root.lastIndexOf('/'));
  560. var clients$ = $(this.clientList);
  561. var node = this.nodes[ "http://vwf.example.com/clients.vwf" ];
  562. clients$.html("<div class='header'>Connected Clients</div>");
  563. // Add node children
  564. clients$.append("<div id='clientsChildren'></div>");
  565. for ( var i = 0; i < node.children.length; i++ ) {
  566. var nodeChildIDAttribute = $.encoder.encodeForHTMLAttribute("id", node.children[i].ID, true);
  567. var nodeChildIDAlpha = $.encoder.encodeForAlphaNumeric(node.children[i].ID);
  568. var nodeChildNameHTML = $.encoder.encodeForHTML(node.children[i].name);
  569. $('#clientsChildren').append("<div id='" + nodeChildIDAlpha + "' data-nodeID='" + nodeChildIDAttribute + "' class='childContainer'><div class='childEntry'><b>" + nodeChildNameHTML + "</b></div></div>");
  570. $('#' + nodeChildIDAlpha).click( function(evt) {
  571. viewClient.call(self, $(this).attr("data-nodeID"));
  572. });
  573. }
  574. // Login Information
  575. clients$.append("<div style='padding:6px'><input class='filename_entry' type='text' id='userName' placeholder='Username' /><!-- <input class='filename_entry' type='password' id='password' placeholder='Password'/> --><input class='update_button' type='button' id='login' value='Login' /></div>");
  576. clients$.append("<hr/>");
  577. $('#userName').keydown( function(evt) {
  578. evt.stopPropagation();
  579. });
  580. $('#userName').keypress( function(evt) {
  581. evt.stopPropagation();
  582. });
  583. $('#userName').keyup( function(evt) {
  584. evt.stopPropagation();
  585. });
  586. $('#password').keydown( function(evt) {
  587. evt.stopPropagation();
  588. });
  589. $('#password').keypress( function(evt) {
  590. evt.stopPropagation();
  591. });
  592. $('#password').keyup( function(evt) {
  593. evt.stopPropagation();
  594. });
  595. $('#login').click(function(evt) {
  596. // Future call to validate username and password
  597. //login.call(self, $('#userName').val(), $('#password').val());
  598. var moniker = vwf_view.kernel.moniker();
  599. var clients = vwf_view.kernel.findClients("", "/*");
  600. var client = undefined;
  601. for (var i=0; i < clients.length; i++)
  602. {
  603. if ( clients[i].indexOf(moniker) != -1 )
  604. {
  605. client = clients[i];
  606. break;
  607. }
  608. }
  609. // var client = vwf_view.kernel.findClients("", "/" + moniker)[0];
  610. if ( client ) {
  611. vwf_view.kernel.setProperty( client, "displayName", $('#userName').val() );
  612. }
  613. });
  614. // clients$.append("<div style='padding:6px'><input class='live_button' type='button' id='liveeditor' value='Open Code Editor' /></div>");
  615. // $('#liveeditor').click(function(evt) {
  616. // openLiveEditor.call(self);
  617. // });
  618. // Save / Load
  619. clients$.append("<div style='padding:6px'><input class='filename_entry' type='text' id='fileName' /><input class='update_button' type='button' id='save' value='Save' /></div>");
  620. $('#fileName').keydown( function(evt) {
  621. evt.stopPropagation();
  622. });
  623. $('#fileName').keypress( function(evt) {
  624. evt.stopPropagation();
  625. });
  626. $('#fileName').keyup( function(evt) {
  627. evt.stopPropagation();
  628. });
  629. $('#save').click(function(evt) {
  630. saveStateAsFile.call(self, $('#fileName').val());
  631. });
  632. clients$.append("<div style='padding:6px'><select class='filename_select' id='fileToLoad' /></select></div>");
  633. $('#fileToLoad').append("<option value='none'></option>");
  634. $.getJSON( "/" + root + "/listallsaves", function( data ) {
  635. $.each( data, function( key, value ) {
  636. var applicationName = value[ 'applicationpath' ].split( "/" );
  637. if ( applicationName.length > 0 ) {
  638. applicationName = applicationName[ applicationName.length - 1 ];
  639. }
  640. if ( applicationName.length > 0 ) {
  641. applicationName = applicationName.charAt(0).toUpperCase() + applicationName.slice(1);
  642. }
  643. if ( value['latestsave'] ) {
  644. $('#fileToLoad').append("<option value='"+value['savename']+"' applicationpath='"+value['applicationpath']+"'>"+applicationName+": "+value['savename']+"</option>");
  645. }
  646. else {
  647. $('#fileToLoad').append("<option value='"+value['savename']+"' applicationpath='"+value['applicationpath']+"' revision='"+value['revision']+"'>"+applicationName+": "+value['savename']+" Rev(" + value['revision'] + ")</option>");
  648. }
  649. } );
  650. } );
  651. clients$.append("<div style='padding:6px'><input class='update_button' type='button' id='load' value='Load' /></div>");
  652. $('#load').click(function(evt) {
  653. loadSavedState.call(self, $('#fileToLoad').val(), $('#fileToLoad').find(':selected').attr('applicationpath'), $('#fileToLoad').find(':selected').attr('revision'));
  654. });
  655. }
  656. // -- editor ---
  657. function openLiveEditor(value) {
  658. //this.liveditor = document.createElement('div');
  659. //this.liveditor.setAttribute('id', "editorlive");
  660. // $('body').append(this.liveditor);
  661. var editor = this.ace.edit("editorlive");
  662. editor.setTheme("ace/theme/monokai");
  663. editor.getSession().setMode("ace/mode/javascript");
  664. }
  665. // -- viewClient ------------------------------------------------------------------------
  666. function viewClient( clientID ) {
  667. var self = this;
  668. var clients$ = $(this.clientList);
  669. var node = this.nodes[ clientID ];
  670. clients$.html("<div class='header'><img src='images/back.png' id='back' alt='back'/> " + $.encoder.encodeForHTML(node.name) + "</div>");
  671. $('#back').click ( function(evt) {
  672. viewClients.call( self );
  673. });
  674. // Add node properties
  675. clients$.append("<div id='clientProperties'></div>");
  676. var displayedProperties = {};
  677. for ( var i = 0; i < node.properties.length; i++ ) {
  678. if ( !displayedProperties[ node.properties[i].name ] ) {
  679. displayedProperties[ node.properties[i].name ] = "instance";
  680. var nodeIDAlpha = $.encoder.encodeForAlphaNumeric(clientID);
  681. var propertyNameAttribute = $.encoder.encodeForHTMLAttribute("id", node.properties[i].name, true);
  682. var propertyNameAlpha = $.encoder.encodeForAlphaNumeric(node.properties[i].name);
  683. var propertyNameHTML = $.encoder.encodeForHTML(node.properties[i].name);
  684. var propertyValueAttribute = $.encoder.encodeForHTMLAttribute("val", node.properties[i].getValue(), true);
  685. $('#clientProperties').append("<div id='" + nodeIDAlpha + "-" + propertyNameAlpha + "' class='propEntry'><table><tr><td><b>" + propertyNameHTML + " </b></td><td><input type='text' class='input_text' id='input-" + nodeIDAlpha + "-" + propertyNameAlpha + "' value='" + propertyValueAttribute + "' data-propertyName='" + propertyNameAttribute + "' readonly></td></tr></table></div>");
  686. }
  687. }
  688. }
  689. // -- drillDown -------------------------------------------------------------------------
  690. function drillDown(nodeID, drillBackID) // invoke with the view as "this"
  691. {
  692. var topdownName = this.topdownName;
  693. var topdownTemp = this.topdownTemp;
  694. drill.call(this, nodeID, drillBackID);
  695. if(nodeID != vwf_view.kernel.find("", "/")[0]) $(topdownName).hide('slide', {direction: 'left'}, 175);
  696. $(topdownTemp).show('slide', {direction: 'right'}, 175);
  697. this.topdownName = topdownTemp;
  698. this.topdownTemp = topdownName;
  699. }
  700. // -- drillUp ---------------------------------------------------------------------------
  701. function drillUp(nodeID) // invoke with the view as "this"
  702. {
  703. var topdownName = this.topdownName;
  704. var topdownTemp = this.topdownTemp;
  705. drill.call(this, nodeID, undefined);
  706. $(topdownName).hide('slide', {direction: 'right'}, 175);
  707. $(topdownTemp).show('slide', {direction: 'left'}, 175);
  708. this.topdownName = topdownTemp;
  709. this.topdownTemp = topdownName;
  710. }
  711. // -- drillBack---------------------------------------------------------------------------
  712. function drillBack(nodeID) // invoke with the view as "this"
  713. {
  714. var topdownName = this.topdownName;
  715. var topdownTemp = this.topdownTemp;
  716. drill.call(this, nodeID, undefined);
  717. // No slide motion, when resizing script window back to normal
  718. $(topdownName).hide();
  719. $(topdownTemp).show();
  720. this.topdownName = topdownTemp;
  721. this.topdownTemp = topdownName;
  722. }
  723. // -- drill -----------------------------------------------------------------------------
  724. function drill(nodeID, drillBackID) // invoke with the view as "this"
  725. {
  726. var node = this.nodes[ nodeID ];
  727. if ( !node ) {
  728. this.logger.errorx( "drill: Cannot find node '" + nodeID + "'" );
  729. return;
  730. }
  731. var self = this;
  732. var topdownName = this.topdownName;
  733. var topdownTemp = this.topdownTemp;
  734. var nodeIDAlpha = $.encoder.encodeForAlphaNumeric(nodeID);
  735. $(topdownName).html(''); // Clear alternate div first to ensure content is added correctly
  736. this.currentNodeID = nodeID;
  737. if(!drillBackID) drillBackID = node.parentID;
  738. if(nodeID == vwf_view.kernel.find("", "/")[0])
  739. {
  740. $(topdownTemp).html("<div class='header'>index</div>");
  741. }
  742. else
  743. {
  744. $(topdownTemp).html("<div class='header'><img src='images/back.png' id='" + nodeIDAlpha + "-back' alt='back'/> " + $.encoder.encodeForHTML(node.name) + "</div>");
  745. $('#' + nodeIDAlpha + '-back').click ( function(evt) {
  746. drillUp.call(self, drillBackID);
  747. });
  748. }
  749. // Add node children
  750. $(topdownTemp).append("<div id='children'></div>");
  751. for ( var i = 0; i < node.children.length; i++ ) {
  752. var nodeChildIDAttribute = $.encoder.encodeForHTMLAttribute("id", node.children[i].ID, true);
  753. var nodeChildIDAlpha = $.encoder.encodeForAlphaNumeric(node.children[i].ID);
  754. $('#children').append("<div id='" + nodeChildIDAlpha + "' data-nodeID='" + nodeChildIDAttribute + "' class='childContainer'><div class='childEntry'><b>" + $.encoder.encodeForHTML(node.children[i].name) + "</b></div></div>");
  755. $('#' + nodeChildIDAlpha).click( function(evt) {
  756. drillDown.call(self, $(this).attr("data-nodeID"), nodeID);
  757. });
  758. }
  759. $('#children > div:last').css('border-bottom-width', '3px');
  760. // Add prototype children
  761. // TODO: Commented out until prototype children inherit from prototypes
  762. /*
  763. $(topdownTemp).append("<div id='prototypeChildren'></div>");
  764. var prototypeChildren = getChildren.call( this, this.kernel, node.extendsID );
  765. for ( var key in prototypeChildren)
  766. {
  767. var child = prototypeChildren[key];
  768. var prototypeChildIDAttribute = $.encoder.encodeForHTMLAttribute("id", child.ID, true);
  769. var prototypeChildIDAlpha = $.encoder.encodeForAlphaNumeric(child.ID);
  770. $('#prototypeChildren').append("<div id='" + prototypeChildIDAlpha + "' data-nodeID='" + prototypeChildIDAttribute + "' class='childContainer'><div class='childEntry'><b>" + $.encoder.encodeForHTML(child.name) + "</b></div></div>");
  771. $('#' + prototypeChildIDAlpha).click( function(evt) {
  772. drillDown.call(self, $(this).attr("data-nodeID"), nodeID);
  773. });
  774. }
  775. */ // END TODO:
  776. $('#prototypeChildren > div:last').css('border-bottom-width', '3px');
  777. // Add node properties
  778. $(topdownTemp).append("<div id='properties'></div>");
  779. var displayedProperties = {};
  780. for ( var i = 0; i < node.properties.length; i++ ) {
  781. if ( !displayedProperties[ node.properties[i].name ] && node.properties[i].name.indexOf('$') === -1) {
  782. displayedProperties[ node.properties[i].name ] = "instance";
  783. var propertyNameAttribute = $.encoder.encodeForHTMLAttribute("id", node.properties[i].name, true);
  784. var propertyNameAlpha = $.encoder.encodeForAlphaNumeric(node.properties[i].name);
  785. var propertyNameHTML = $.encoder.encodeForHTML(node.properties[i].name);
  786. var propertyValueAttribute = $.encoder.encodeForHTMLAttribute("val", node.properties[i].getValue(), true);
  787. if (propertyNameAlpha.indexOf("semantics") > -1) {
  788. } else if (propertyNameAlpha.indexOf("grammar") > -1) {
  789. } else if (propertyNameAlpha.indexOf("ohm") > -1) {
  790. let propName = propertyNameAlpha;
  791. let propValue = node.properties[i].rawValue;
  792. $(topdownTemp).append("<div id='" + nodeIDAlpha + "-" + propertyNameAlpha + "'></div>");
  793. $('#' + nodeIDAlpha + '-' + propertyNameAlpha).append("<div class='childContainer'><div class='childEntry'><b>"+propertyNameHTML+"</div></div>");
  794. $('#' + nodeIDAlpha + '-' + propertyNameAlpha).click( function (evt) {
  795. editOhmLang.call(self, nodeID, propName, propValue);
  796. });
  797. // $('#properties').append("<div id='" + nodeIDAlpha + "-" + propertyNameAlpha + "' class='propEntry'><table><tr><td><b>" + propertyNameHTML + " </b></td><td><input type='text' class='input_text' id='input-" + nodeIDAlpha + "-" + propertyNameAlpha + "' value='" + propertyValueAttribute + "' data-propertyName='" + propertyNameAttribute + "'></td></tr></table></div>");
  798. } else {
  799. $('#properties').append("<div id='" + nodeIDAlpha + "-" + propertyNameAlpha + "' class='propEntry'><table><tr><td><b>" + propertyNameHTML + " </b></td><td><input type='text' class='input_text' id='input-" + nodeIDAlpha + "-" + propertyNameAlpha + "' value='" + propertyValueAttribute + "' data-propertyName='" + propertyNameAttribute + "'></td></tr></table></div>");
  800. }
  801. $('#input-' + nodeIDAlpha + '-' + propertyNameAttribute).change( function(evt) {
  802. var propName = $.encoder.canonicalize($(this).attr("data-propertyName"));
  803. var propValue = $(this).val();
  804. try {
  805. propValue = JSON.parse($.encoder.canonicalize(propValue));
  806. self.kernel.setProperty(nodeID, propName, propValue);
  807. } catch (e) {
  808. // restore the original value on error
  809. $(this).val(propValue);
  810. }
  811. } );
  812. $('#input-' + nodeIDAlpha + '-' + propertyNameAlpha).keydown( function(evt) {
  813. evt.stopPropagation();
  814. });
  815. $('#input-' + nodeIDAlpha + '-' + propertyNameAlpha).keypress( function(evt) {
  816. evt.stopPropagation();
  817. });
  818. $('#input-' + nodeIDAlpha + '-' + propertyNameAlpha).keyup( function(evt) {
  819. evt.stopPropagation();
  820. });
  821. }
  822. }
  823. $('#properties > div:last').css('border-bottom-width', '3px');
  824. this.logger.info(self + " " + nodeID);
  825. // Add prototype properties
  826. $(topdownTemp).append("<div id='prototypeProperties'></div>");
  827. var prototypeProperties = getProperties.call( this, this.kernel, node.extendsID );
  828. for ( var key in prototypeProperties ) {
  829. var prop = prototypeProperties[key].prop;
  830. if ( !displayedProperties[ prop.name ] ) {
  831. displayedProperties[ prop.name ] = prototypeProperties[key].prototype;
  832. if(prop.value == undefined)
  833. {
  834. prop.value = JSON.stringify( utility.transform( vwf.getProperty( nodeID, prop.name, []), utility.transforms.transit ) );
  835. }
  836. var propertyNameAttribute = $.encoder.encodeForHTMLAttribute("id", prop.name, true);
  837. var propertyNameAlpha = $.encoder.encodeForAlphaNumeric(prop.name);
  838. var propertyNameHTML = $.encoder.encodeForHTML(prop.name);
  839. var propertyValueAttribute = $.encoder.encodeForHTMLAttribute("val", prop.value, true);
  840. $('#prototypeProperties').append("<div id='" + nodeIDAlpha + "-" + propertyNameAlpha + "' class='propEntry'><table><tr><td><b>" + propertyNameHTML + " </b></td><td><input type='text' class='input_text' id='input-" + nodeIDAlpha + "-" + propertyNameAlpha + "' value='" + propertyValueAttribute + "' data-propertyName='" + propertyNameAttribute + "'></td></tr></table></div>");
  841. $('#input-' + nodeIDAlpha + '-' + propertyNameAlpha).change( function(evt) {
  842. var propName = $.encoder.canonicalize($(this).attr("data-propertyName"));
  843. var propValue = $(this).val();
  844. try {
  845. propValue = JSON.parse($.encoder.canonicalize(propValue));
  846. self.kernel.setProperty(nodeID, propName, propValue);
  847. } catch (e) {
  848. // restore the original value on error
  849. $(this).val(propValue);
  850. }
  851. } );
  852. $('#input-' + nodeIDAlpha + '-' + propertyNameAlpha).keydown( function(evt) {
  853. evt.stopPropagation();
  854. });
  855. $('#input-' + nodeIDAlpha + '-' + propertyNameAlpha).keypress( function(evt) {
  856. evt.stopPropagation();
  857. });
  858. $('#input-' + nodeIDAlpha + '-' + propertyNameAlpha).keyup( function(evt) {
  859. evt.stopPropagation();
  860. });
  861. }
  862. }
  863. $('#prototypeProperties > div:last').css('border-bottom-width', '3px');
  864. // Add node methods
  865. $(topdownTemp).append("<div id='methods'></div>");
  866. for ( var key in node.methods ) {
  867. var method = node.methods[key];
  868. var methodNameAlpha = $.encoder.encodeForAlphaNumeric(key);
  869. var methodNameAttribute = $.encoder.encodeForHTMLAttribute("id", key, true);
  870. var methodNameHTML = $.encoder.encodeForHTML(key);
  871. $('#methods').append("<div id='" + methodNameAlpha + "' class='methodEntry'><table><tr><td><b>" + methodNameHTML + " </b></td><td style='text-align:right;overflow:visible'><div id='rollover-" + methodNameAlpha + "' style='position:relative;left:12px'><input type='button' class='input_button_call' id='call-" + methodNameAlpha + "' value='Call' data-methodName='" + methodNameAttribute + "'><img id='param-" + methodNameAlpha + "' data-methodName='" + methodNameAttribute + "' src='images/arrow.png' alt='arrow' style='position:relative;top:4px;left:2px;visibility:hidden'></div></td></tr></table></div>");
  872. $('#rollover-' + methodNameAlpha).mouseover( function(evt) {
  873. $('#param-' + $(this).attr("id").substring(9)).css('visibility', 'visible');
  874. });
  875. $('#rollover-' + methodNameAlpha).mouseleave( function(evt) {
  876. $('#param-' + $(this).attr("id").substring(9)).css('visibility', 'hidden');
  877. });
  878. $('#call-' + methodNameAlpha).click( function(evt) {
  879. self.kernel.callMethod( nodeID, $.encoder.canonicalize($(this).attr("data-methodName")) );
  880. });
  881. $('#param-' + methodNameAlpha).click( function(evt) {
  882. setParams.call(self, $.encoder.canonicalize($(this).attr("data-methodName")), method, nodeID);
  883. });
  884. }
  885. $('#methods > div:last').css('border-bottom-width', '3px');
  886. // Add prototype methods
  887. $(topdownTemp).append("<div id='prototypeMethods'></div>");
  888. var prototypeMethods = getMethods.call( this, this.kernel, node.extendsID );
  889. for ( var key in prototypeMethods ) {
  890. var method = prototypeMethods[key];
  891. var prototypeMethodNameAlpha = $.encoder.encodeForAlphaNumeric(key);
  892. var prototypeMethodNameAttribute = $.encoder.encodeForHTMLAttribute("id", key, true);
  893. var prototypeMethodNameHTML = $.encoder.encodeForHTML(key);
  894. $('#prototypeMethods').append("<div id='" + prototypeMethodNameAlpha + "' class='methodEntry'><table><tr><td><b>" + prototypeMethodNameHTML + " </b></td><td style='text-align:right;overflow:visible'><div id='rollover-" + prototypeMethodNameAlpha + "' style='position:relative;left:12px'><input type='button' class='input_button_call' id='call-" + prototypeMethodNameAlpha + "' value='Call' data-methodName='" + prototypeMethodNameAttribute + "'><img id='param-" + prototypeMethodNameAlpha + "' data-methodName='" + prototypeMethodNameAttribute + "' src='images/arrow.png' alt='arrow' style='position:relative;top:4px;left:2px;visibility:hidden'></div></td></tr></table></div>");
  895. $('#rollover-' + prototypeMethodNameAlpha).mouseover( function(evt) {
  896. $('#param-' + $(this).attr("id").substring(9)).css('visibility', 'visible');
  897. });
  898. $('#rollover-' + prototypeMethodNameAlpha).mouseleave( function(evt) {
  899. $('#param-' + $(this).attr("id").substring(9)).css('visibility', 'hidden');
  900. });
  901. $('#call-' + prototypeMethodNameAlpha).click( function(evt) {
  902. self.kernel.callMethod( nodeID, $.encoder.canonicalize($(this).attr("data-methodName")) );
  903. });
  904. $('#param-' + prototypeMethodNameAlpha).click( function(evt) {
  905. setParams.call(self, $.encoder.canonicalize($(this).attr("data-methodName")), method, nodeID);
  906. });
  907. }
  908. $('#prototypeMethods > div:last').css('border-bottom-width', '3px');
  909. // Add node events
  910. $(topdownTemp).append("<div id='events'></div>");
  911. for ( var key in node.events ) {
  912. var nodeEvent = node.events[key];
  913. var eventNameAlpha = $.encoder.encodeForAlphaNumeric(key);
  914. var eventNameAttribute = $.encoder.encodeForHTMLAttribute("id", key, true);
  915. var eventNameHTML = $.encoder.encodeForHTML(key);
  916. $('#events').append("<div id='" + eventNameAlpha + "' class='methodEntry'><table><tr><td><b>" + eventNameHTML + " </b></td><td style='text-align:right;overflow:visible'><div id='rollover-" + eventNameAlpha + "' style='position:relative;left:12px'><input type='button' class='input_button_call' id='fire-" + eventNameAlpha + "' value='Fire' data-eventName='" + eventNameAttribute + "'><img id='arg-" + eventNameAlpha + "' data-eventName='" + eventNameAttribute + "' src='images/arrow.png' alt='arrow' style='position:relative;top:4px;left:2px;visibility:hidden'></div></td></tr></table></div>");
  917. $('#rollover-' + eventNameAlpha).mouseover( function(evt) {
  918. $('#arg-' + $(this).attr("id").substring(9)).css('visibility', 'visible');
  919. });
  920. $('#rollover-' + eventNameAlpha).mouseleave( function(evt) {
  921. $('#arg-' + $(this).attr("id").substring(9)).css('visibility', 'hidden');
  922. });
  923. $('#fire-' + eventNameAlpha).click( function(evt) {
  924. self.kernel.fireEvent( nodeID, $.encoder.canonicalize($(this).attr("data-eventName")) );
  925. });
  926. $('#arg-' + eventNameAlpha).click( function(evt) {
  927. setArgs.call(self, $.encoder.canonicalize($(this).attr("data-eventName")), nodeEvent, nodeID);
  928. });
  929. }
  930. $('#events > div:last').css('border-bottom-width', '3px');
  931. // Add prototype events
  932. $(topdownTemp).append("<div id='prototypeEvents'></div>");
  933. var prototypeEvents = getEvents.call( this, this.kernel, node.extendsID );
  934. for ( var key in prototypeEvents ) {
  935. var nodeEvent = prototypeEvents[key];
  936. var prototypeEventNameAlpha = $.encoder.encodeForAlphaNumeric(key);
  937. var prototypeEventNameAttribute = $.encoder.encodeForHTMLAttribute("id", key, true);
  938. var prototypeEventNameHTML = $.encoder.encodeForHTML(key);
  939. $('#prototypeEvents').append("<div id='" + prototypeEventNameAlpha + "' class='methodEntry'><table><tr><td><b>" + prototypeEventNameHTML + " </b></td><td style='text-align:right;overflow:visible'><div id='rollover-" + prototypeEventNameAlpha + "' style='position:relative;left:12px'><input type='button' class='input_button_call' id='fire-" + prototypeEventNameAlpha + "' value='Fire' data-eventName='" + prototypeEventNameAttribute + "'><img id='arg-" + prototypeEventNameAlpha + "' data-eventName='" + prototypeEventNameAttribute + "' src='images/arrow.png' alt='arrow' style='position:relative;top:4px;left:2px;visibility:hidden'></div></td></tr></table></div>");
  940. $('#rollover-' + prototypeEventNameAlpha).mouseover( function(evt) {
  941. $('#arg-' + $(this).attr("id").substring(9)).css('visibility', 'visible');
  942. });
  943. $('#rollover-' + prototypeEventNameAlpha).mouseleave( function(evt) {
  944. $('#arg-' + $(this).attr("id").substring(9)).css('visibility', 'hidden');
  945. });
  946. $('#fire-' + prototypeEventNameAlpha).click( function(evt) {
  947. self.kernel.fireEvent( nodeID, $.encoder.canonicalize($(this).attr("data-eventName")) );
  948. });
  949. $('#arg-' + prototypeEventNameAlpha).click( function(evt) {
  950. setArgs.call(self, $.encoder.canonicalize($(this).attr("data-eventName")), nodeEvent, nodeID);
  951. });
  952. }
  953. $('#prototypeEvents > div:last').css('border-bottom-width', '3px');
  954. // Add node behaviors
  955. $(topdownTemp).append("<div id='behaviors'></div>");
  956. for ( var i = 0; i < node.implementsIDs.length; i++ ) {
  957. var nodeImplementsIDAlpha = $.encoder.encodeForAlphaNumeric(node.implementsIDs[i]);
  958. var nodeImplementsIDHTML = $.encoder.encodeForHTML(node.implementsIDs[i]);
  959. $('#behaviors').append("<div class='propEntry'><table><tr><td style='width:92%'><b>" + nodeImplementsIDHTML + "</b></td><td><input id='" + nodeImplementsIDAlpha + "-enable' type='checkbox' checked='checked' disabled='disabled' /></td></tr></table></div>");
  960. /*
  961. //Placeholder to Enable/Disable behaviors
  962. $('#' + node.implementsID[i] + '-enable').change( function(evt) {
  963. });
  964. */
  965. }
  966. $('#behaviors > div:last').css('border-bottom-width', '3px');
  967. // Add prototype behaviors
  968. $(topdownTemp).append("<div id='prototypeBehaviors'></div>");
  969. var prototypeNode = this.nodes[ node.extendsID ];
  970. for ( var i=0; i < prototypeNode.implementsIDs.length; i++)
  971. {
  972. var prototypeImplementsIDAlpha = $.encoder.encodeForAlphaNumeric(prototypeNode.implementsIDs[i]);
  973. var prototypeImplementsIDHTML = $.encoder.encodeForHTML(prototypeNode.implementsIDs[i]);
  974. $('#prototypeBehaviors').append("<div class='propEntry'><table><tr><td style='width:92%'><b>" + prototypeImplementsIDHTML + "</b></td><td><input id='" + prototypeImplementsIDAlpha + "-enable' type='checkbox' checked='checked' disabled='disabled' /></td></tr></table></div>");
  975. }
  976. $('#prototypeBehaviors > div:last').css('border-bottom-width', '3px');
  977. // Create new method
  978. $(topdownTemp).append("<div id='createMethodID'></div>");
  979. $('#createMethodID').append("<div class='childContainer'><div class='childEntry'><b>New Method</div></div>");
  980. $('#createMethodID').click( function (evt) {
  981. createMethod.call(self, nodeID);
  982. });
  983. // Create new Event
  984. $(topdownTemp).append("<div id='createEventID'></div>");
  985. $('#createEventID').append("<div class='childContainer'><div class='childEntry'><b>New Event</div></div>");
  986. $('#createEventID').click( function (evt) {
  987. createEvent.call(self, nodeID);
  988. });
  989. // Create new script
  990. $(topdownTemp).append("<div id='createScript'></div>");
  991. $('#createScript').append("<div class='childContainer'><div class='childEntry'><b>New Script</div></div>");
  992. $('#createScript').click( function (evt) {
  993. createScript.call(self, nodeID);
  994. });
  995. $('#createScript > div:last').css('border-bottom-width', '3px');
  996. if ( this.allScripts[ nodeID ] !== undefined ) {
  997. // Add node scripts
  998. $(topdownTemp).append("<div id='scripts'></div>");
  999. for( var i=0; i < this.allScripts[ nodeID ].length; i++ )
  1000. {
  1001. var scriptFull = this.allScripts[nodeID][i].text;
  1002. if(scriptFull != undefined)
  1003. {
  1004. var scriptName = scriptFull.substring(0, scriptFull.indexOf('='));
  1005. $('#scripts').append("<div id='script-" + nodeIDAlpha + "-" + i + "' class='childContainer'><div class='childEntry'><b>script </b>" + scriptName + "</div></div>");
  1006. $('#script-' + nodeIDAlpha + "-" + i).click( function(evt) {
  1007. var scriptID = $(this).attr("id").substring($(this).attr("id").lastIndexOf('-')+1);
  1008. viewScript.call(self, nodeID, scriptID, undefined);
  1009. });
  1010. }
  1011. }
  1012. $('#scripts > div:last').css('border-bottom-width', '3px');
  1013. }
  1014. if ( this.allScripts[ node.extendsID ] !== undefined ) {
  1015. // Add prototype scripts
  1016. $(topdownTemp).append("<div id='prototypeScripts'></div>");
  1017. for( var i=0; i < this.allScripts[ node.extendsID ].length; i++ )
  1018. {
  1019. var scriptFull = this.allScripts[node.extendsID][i].text;
  1020. if(scriptFull != undefined)
  1021. {
  1022. var nodeExtendsIDAlpha = $.encoder.encodeForAlphaNumeric(node.extendsID);
  1023. var nodeExtendsIDAttribute = $.encoder.encodeForHTMLAttribute("id", node.extendsID, true);
  1024. var scriptName = scriptFull.substring(0, scriptFull.indexOf('='));
  1025. $('#prototypeScripts').append("<div id='script-" + nodeExtendsIDAlpha + "-" + i + "' class='childContainer' data-nodeExtendsID='" + nodeExtendsIDAttribute + "'><div class='childEntry'><b>script </b>" + scriptName + "</div></div>");
  1026. $('#script-' + nodeExtendsIDAlpha + "-" + i).click( function(evt) {
  1027. var extendsId = $.encoder.canonicalize($(this).attr("data-nodeExtendsID"));
  1028. var scriptID = $(this).attr("id").substring($(this).attr("id").lastIndexOf('-')+1);
  1029. viewScript.call(self, nodeID, scriptID, extendsId);
  1030. });
  1031. }
  1032. }
  1033. $('#prototypeScripts > div:last').css('border-bottom-width', '3px');
  1034. }
  1035. updateCameraProperties.call(self);
  1036. }
  1037. // createEvent
  1038. function createEvent (nodeID) // invoke with the view as "this"
  1039. {
  1040. var self = this;
  1041. var topdownName = this.topdownName;
  1042. var topdownTemp = this.topdownTemp;
  1043. var nodeIDAlpha = $.encoder.encodeForAlphaNumeric(nodeID);
  1044. $(topdownTemp).html("<div class='header'><img src='images/back.png' id='script-" + nodeIDAlpha + "-back' alt='back'/> New event</div>");
  1045. $('#script-' + nodeIDAlpha + '-back').click ( function(evt) {
  1046. self.editingScript = false;
  1047. drillBack.call(self, nodeID);
  1048. // Return editor to normal width
  1049. $('#editor').animate({ 'left' : "-260px" }, 175);
  1050. $('.vwf-tree').animate({ 'width' : "260px" }, 175);
  1051. });
  1052. $(topdownTemp).append("<div id='cm'>Name:<br/><input type='text' class='input_text' id='eventName'/><br/>Parameters:<br/><input type='text' class='input_text' id='eventParams'/></div><hr><input class='update_button' type='button' id='createEvent' value='Create' />");
  1053. $("#createEvent").click ( function(evt) {
  1054. console.log("not yet created");
  1055. if( $('#eventName').val() )
  1056. {
  1057. var eventName = $('#eventName').val();
  1058. //prmtr = JSON.parse(JSON.stringify($.encoder.canonicalize(prmtr)));
  1059. console.log(eventName);
  1060. if( $('#eventParams').val() )
  1061. {
  1062. var params = $('#eventParams').val();
  1063. params = params.split(',');
  1064. var cleanParams = [];
  1065. for (var i = 0; i < params.length; i++) {
  1066. params[i] = $.trim(params[i]);
  1067. if (params[i] != '' && params[i] != null && params[i] !== undefined)
  1068. cleanParams.push(params[i]);
  1069. }
  1070. console.log(cleanParams);
  1071. //prmtr = JSON.parse(JSON.stringify($.encoder.canonicalize(prmtr)));
  1072. }
  1073. let body = '';
  1074. self.kernel.createEvent(nodeID, eventName, cleanParams);
  1075. }
  1076. //self.kernel.execute( nodeID, editor.getValue() );
  1077. // self.kernel.execute( nodeID, $("#newScriptArea").val() );
  1078. });
  1079. $(topdownName).hide();
  1080. $(topdownTemp).show();
  1081. this.topdownName = topdownTemp;
  1082. this.topdownTemp = topdownName;
  1083. }
  1084. // -- createMethod
  1085. function createMethod (nodeID) // invoke with the view as "this"
  1086. {
  1087. var self = this;
  1088. var topdownName = this.topdownName;
  1089. var topdownTemp = this.topdownTemp;
  1090. var nodeIDAlpha = $.encoder.encodeForAlphaNumeric(nodeID);
  1091. $(topdownTemp).html("<div class='header'><img src='images/back.png' id='script-" + nodeIDAlpha + "-back' alt='back'/> New method</div>");
  1092. $('#script-' + nodeIDAlpha + '-back').click ( function(evt) {
  1093. self.editingScript = false;
  1094. drillBack.call(self, nodeID);
  1095. // Return editor to normal width
  1096. $('#editor').animate({ 'left' : "-260px" }, 175);
  1097. $('.vwf-tree').animate({ 'width' : "260px" }, 175);
  1098. });
  1099. $(topdownTemp).append("<div id='cm'>Name:<br/><input type='text' class='input_text' id='methodName'/><br/>Parameters:<br/><input type='text' class='input_text' id='methodParams'/></div><hr><input class='update_button' type='button' id='createMethod' value='Create' />");
  1100. $("#createMethod").click ( function(evt) {
  1101. console.log("not yet created");
  1102. if( $('#methodName').val() )
  1103. {
  1104. var methodName = $('#methodName').val();
  1105. //prmtr = JSON.parse(JSON.stringify($.encoder.canonicalize(prmtr)));
  1106. console.log(methodName);
  1107. if( $('#methodParams').val() )
  1108. {
  1109. var params = $('#methodParams').val();
  1110. params = params.split(',');
  1111. var cleanParams = [];
  1112. for (var i = 0; i < params.length; i++) {
  1113. params[i] = $.trim(params[i]);
  1114. if (params[i] != '' && params[i] != null && params[i] !== undefined)
  1115. cleanParams.push(params[i]);
  1116. }
  1117. console.log(cleanParams);
  1118. //prmtr = JSON.parse(JSON.stringify($.encoder.canonicalize(prmtr)));
  1119. }
  1120. let body = '';
  1121. self.kernel.createMethod(nodeID, methodName, cleanParams, body);
  1122. }
  1123. //self.kernel.execute( nodeID, editor.getValue() );
  1124. // self.kernel.execute( nodeID, $("#newScriptArea").val() );
  1125. });
  1126. $(topdownName).hide();
  1127. $(topdownTemp).show();
  1128. this.topdownName = topdownTemp;
  1129. this.topdownTemp = topdownName;
  1130. }
  1131. // -- createScript ----------------------------------------------------------------------
  1132. function createScript (nodeID) // invoke with the view as "this"
  1133. {
  1134. var self = this;
  1135. var topdownName = this.topdownName;
  1136. var topdownTemp = this.topdownTemp;
  1137. var allScripts = this.allScripts;
  1138. var nodeIDAlpha = $.encoder.encodeForAlphaNumeric(nodeID);
  1139. $(topdownTemp).html("<div class='header'><img src='images/back.png' id='script-" + nodeIDAlpha + "-back' alt='back'/> script</div>");
  1140. $('#script-' + nodeIDAlpha + '-back').click ( function(evt) {
  1141. self.editingScript = false;
  1142. drillBack.call(self, nodeID);
  1143. // Return editor to normal width
  1144. $('#editor').animate({ 'left' : "-260px" }, 175);
  1145. $('.vwf-tree').animate({ 'width' : "260px" }, 175);
  1146. });
  1147. // $(topdownTemp).append("<div class='scriptEntry'><pre class='scriptCode'><textarea id='newScriptArea' class='scriptEdit' spellcheck='false' wrap='off'></textarea></pre><input class='update_button' type='button' id='create-" + nodeIDAlpha + "' value='Create' /></div><hr>");
  1148. $(topdownTemp).append("<div class='scriptEntry'><pre class='scriptCode'> <div id='editorlive'></div></pre><input class='update_button' type='button' id='create-" + nodeIDAlpha + "' value='Create' /></div><hr>");
  1149. var editor = createAceEditor(self, nodeID);
  1150. $("#create-" + nodeIDAlpha).click ( function(evt) {
  1151. self.kernel.execute( nodeID, editor.getValue() );
  1152. // self.kernel.execute( nodeID, $("#newScriptArea").val() );
  1153. });
  1154. // $('#newScriptArea').focus( function(evt) {
  1155. // // Expand the script editor
  1156. // self.editingScript = true;
  1157. // $('#editor').animate({ 'left' : "-500px" }, 175);
  1158. // $('.vwf-tree').animate({ 'width' : "500px" }, 175);
  1159. // });
  1160. $('#editorlive').keydown( function(evt) {
  1161. evt.stopPropagation();
  1162. });
  1163. $(topdownName).hide();
  1164. $(topdownTemp).show();
  1165. this.topdownName = topdownTemp;
  1166. this.topdownTemp = topdownName;
  1167. }
  1168. // -- viewScript ------------------------------------------------------------------------
  1169. function createAceEditor(view, nodeID) {
  1170. var editor = view.ace.edit("editorlive");
  1171. editor.setTheme("ace/theme/monokai");
  1172. editor.setFontSize(16);
  1173. editor.getSession().setMode("ace/mode/javascript");
  1174. editor.commands.addCommand({
  1175. name: "doit",
  1176. bindKey: { win: "Ctrl-e", mac: "Command-e" },
  1177. exec: function() {
  1178. codeEditorDoit(editor, nodeID);
  1179. }
  1180. });
  1181. editor.commands.addCommand({
  1182. name: "printit",
  1183. bindKey: { win: "Ctrl-b", mac: "Command-b" },
  1184. exec: function() {
  1185. codeEditorPrintit(editor, nodeID);
  1186. }
  1187. });
  1188. editor.on('focus', function (event, editor) {
  1189. // Expand the script editor
  1190. self.editingScript = true;
  1191. $('#editor').animate({ 'left': "-800px" }, 175);
  1192. $('.vwf-tree').animate({ 'width': "800px" }, 175);
  1193. });
  1194. editor.on('blur', function (event, editor) {
  1195. // $('#editor').animate({ 'left' : "-260px" }, 175);
  1196. // $('.vwf-tree').animate({ 'width' : "260px" }, 175);
  1197. });
  1198. return editor;
  1199. }
  1200. function editOhmLang (nodeID, propertyName, propertyValue) {
  1201. var self = this;
  1202. var topdownName = this.topdownName;
  1203. var topdownTemp = this.topdownTemp;
  1204. var nodeIDAlpha = $.encoder.encodeForAlphaNumeric(nodeID);
  1205. $(topdownTemp).html("<div class='header'><img src='images/back.png' id='script-" + nodeIDAlpha + "-back' alt='back'/> script</div>");
  1206. $('#script-' + nodeIDAlpha + '-back').click ( function(evt) {
  1207. self.editingScript = false;
  1208. drillBack.call(self, nodeID);
  1209. // Return editor to normal width
  1210. $('#editor').animate({ 'left' : "-260px" }, 175);
  1211. $('.vwf-tree').animate({ 'width' : "260px" }, 175);
  1212. });
  1213. if(propertyValue != undefined)
  1214. {
  1215. var propText = propertyValue;
  1216. // var propText = propertyValue.split("\n").map($.trim).filter(function(line) { return line != "" }).join("\n");
  1217. $(topdownTemp).append("<div style='padding:6px'><input class='live_button' type='button' id='update-" + nodeIDAlpha + "-" + propertyName + "' value='Update' /></div>");
  1218. $(topdownTemp).append("<div class='scriptEntry'><pre class='scriptCode'> <div id='editorlive'> </div></pre></div><hr>");
  1219. var editor = createAceEditor(self, nodeID);
  1220. editor.setValue(propText);
  1221. $("#update-" + nodeIDAlpha + "-" + propertyName).click ( function(evt) {
  1222. var evalText = editor.getValue();
  1223. self.kernel.setProperty( nodeID, propertyName, evalText);
  1224. });
  1225. $('#editorlive').keydown( function(evt) {
  1226. evt.stopPropagation();
  1227. });
  1228. }
  1229. $(topdownName).hide();
  1230. $(topdownTemp).show();
  1231. this.topdownName = topdownTemp;
  1232. this.topdownTemp = topdownName;
  1233. }
  1234. function viewScript (nodeID, scriptID, extendsID) // invoke with the view as "this"
  1235. {
  1236. var self = this;
  1237. var topdownName = this.topdownName;
  1238. var topdownTemp = this.topdownTemp;
  1239. var allScripts = this.allScripts;
  1240. var nodeIDAlpha = $.encoder.encodeForAlphaNumeric(nodeID);
  1241. $(topdownTemp).html("<div class='header'><img src='images/back.png' id='script-" + nodeIDAlpha + "-back' alt='back'/> script</div>");
  1242. $('#script-' + nodeIDAlpha + '-back').click ( function(evt) {
  1243. self.editingScript = false;
  1244. drillBack.call(self, nodeID);
  1245. // Return editor to normal width
  1246. $('#editor').animate({ 'left' : "-260px" }, 175);
  1247. $('.vwf-tree').animate({ 'width' : "260px" }, 175);
  1248. });
  1249. if(extendsID) {
  1250. nodeID = extendsID;
  1251. nodeIDAlpha = $.encoder.encodeForAlphaNumeric(extendsID);
  1252. }
  1253. var scriptText = self.allScripts[nodeID][scriptID].text;
  1254. if(scriptText != undefined)
  1255. {
  1256. // $(topdownTemp).append("<div class='scriptEntry'><pre class='scriptCode'><textarea id='scriptTextArea' class='scriptEdit' spellcheck='false' wrap='off'>" + scriptText + "</textarea></pre><input class='update_button' type='button' id='update-" + nodeIDAlpha + "-" + scriptID + "' value='Update' /></div><hr>");
  1257. //Open Live Editor
  1258. $(topdownTemp).append("<div style='padding:6px'><input class='live_button' type='button' id='printit' value='Print It' /><span> </span><input class='live_button' type='button' id='doit-" + nodeIDAlpha + "-" + scriptID + "' value='DoIt' /><span> </span><input class='live_button' type='button' id='update-" + nodeIDAlpha + "-" + scriptID + "' value='Update' /></div>");
  1259. $(topdownTemp).append("<div class='scriptEntry'><pre class='scriptCode'> <div id='editorlive'>" + scriptText + "</div></pre></div><hr>");
  1260. var editor = createAceEditor(self, nodeID);
  1261. // $(topdownTemp).append("<div style='padding:6px'><input class='live_button' type='button' id='doit' value='DoIt' /></div>");
  1262. $("#doit-" + nodeIDAlpha + "-" + scriptID).click(function(evt) {
  1263. var s_id = $(this).attr("id").substring($(this).attr("id").lastIndexOf('-') + 1);
  1264. self.allScripts[nodeID][s_id].text = undefined;;
  1265. codeEditorDoit.call(self, editor, nodeID);
  1266. });
  1267. $("#printit").click(function(evt) {
  1268. codeEditorPrintit.call(self, editor, nodeID);
  1269. });
  1270. $("#update-" + nodeIDAlpha + "-" + scriptID).click ( function(evt) {
  1271. var s_id = $(this).attr("id").substring($(this).attr("id").lastIndexOf('-') + 1);
  1272. self.allScripts[nodeID][s_id].text = undefined;
  1273. var evalText = editor.getValue();
  1274. self.kernel.execute( nodeID, evalText );
  1275. });
  1276. // $('#editorlive').focus( function(evt) {
  1277. // // Expand the script editor
  1278. // self.editingScript = true;
  1279. // $('#editor').animate({ 'left' : "-500px" }, 175);
  1280. // $('.vwf-tree').animate({ 'width' : "500px" }, 175);
  1281. // });
  1282. $('#editorlive').keydown( function(evt) {
  1283. evt.stopPropagation();
  1284. });
  1285. }
  1286. $(topdownName).hide();
  1287. $(topdownTemp).show();
  1288. this.topdownName = topdownTemp;
  1289. this.topdownTemp = topdownName;
  1290. }
  1291. // -- setParams -------------------------------------------------------------------------
  1292. function setParams (methodName, methodParams, nodeID) // invoke with the view as "this"
  1293. {
  1294. var self = this;
  1295. var topdownName = this.topdownName;
  1296. var topdownTemp = this.topdownTemp;
  1297. var methodNameAlpha = $.encoder.encodeForAlphaNumeric(methodName);
  1298. var methodNameHTML = $.encoder.encodeForHTML(methodName);
  1299. $(topdownTemp).html("<div class='header'><img src='images/back.png' id='" + methodNameAlpha + "-back' alt='back'/> " + methodNameHTML + "</div>");
  1300. $('#' + methodNameAlpha + '-back').click ( function(evt) {
  1301. self.editingScript = false;
  1302. drillUp.call(self, nodeID);
  1303. // Return editor to normal width
  1304. $('#editor').animate({ 'left' : "-260px" }, 175);
  1305. $('.vwf-tree').animate({ 'width' : "260px" }, 175);
  1306. });
  1307. var nodeIDAlpha = $.encoder.encodeForAlphaNumeric(nodeID);
  1308. var method = vwf.getMethod(nodeID, methodNameAlpha);
  1309. $(topdownTemp).append("<div style='padding:6px'><input class='live_button' type='button' id='printit' value='Print It' /><span> </span><input class='live_button' type='button' id='doit' value='Do It' /><span> </span><input class='live_button' type='button' id='update-" + nodeIDAlpha + "-" + methodNameAlpha + "' value='Update' /><span> </span> <input class='live_button' type='button' id='call' value='Call' /></div>");
  1310. //$(topdownTemp).append("<input class='update_button' type='button' id='call' value='Call' />");
  1311. $(topdownTemp).append("<div id='editorlive'>" + method.body + "</div>");
  1312. var editor = createAceEditor(self, nodeID);
  1313. $("#printit").click(function(evt) {
  1314. codeEditorPrintit.call(self, editor, nodeID);
  1315. });
  1316. $("#doit").click(function(evt) {
  1317. codeEditorDoit.call(self, editor, nodeID);
  1318. });
  1319. $("#update-" + nodeIDAlpha + "-" + methodNameAlpha).click ( function(evt) {
  1320. var evalText = editor.getValue();
  1321. self.kernel.setMethod( nodeID, methodNameAlpha,
  1322. { body: evalText, type: "application/javascript", parameters: method.parameters } );
  1323. });
  1324. var params = [];
  1325. if (method.parameters) {
  1326. params = method.parameters.length
  1327. };
  1328. if (params >= 1) {
  1329. for(var i=1; i<=params; i++)
  1330. {
  1331. $(topdownTemp).append("<div id='param" + i + "' class='propEntry'><table><tr><td><b>" + method.parameters[i-1] + ": " + i + ": </b></td><td><input type='text' class='input_text' id='input-param" + i + "'></td></tr></table></div>");
  1332. $('#input-param'+ i).keydown( function(evt) {
  1333. evt.stopPropagation();
  1334. });
  1335. $('#input-param'+ i).keypress( function(evt) {
  1336. evt.stopPropagation();
  1337. });
  1338. $('#input-param'+ i).keyup( function(evt) {
  1339. evt.stopPropagation();
  1340. });
  1341. }
  1342. }
  1343. $('#call').click ( function (evt) {
  1344. if (params >= 1) {
  1345. var parameters = new Array();
  1346. for(var i=1; i<=params; i++)
  1347. {
  1348. if( $('#input-param'+ i).val() )
  1349. {
  1350. var prmtr = $('#input-param'+ i).val();
  1351. try {
  1352. prmtr = JSON.parse(JSON.stringify($.encoder.canonicalize(prmtr)));
  1353. parameters.push( prmtr );
  1354. } catch (e) {
  1355. self.logger.error('Invalid Value');
  1356. }
  1357. }
  1358. }
  1359. }
  1360. self.kernel.callMethod(nodeID, methodName, parameters);
  1361. });
  1362. $(topdownName).hide('slide', {direction: 'left'}, 175);
  1363. $(topdownTemp).show('slide', {direction: 'right'}, 175);
  1364. this.topdownName = topdownTemp;
  1365. this.topdownTemp = topdownName;
  1366. }
  1367. // -- setArgs ---------------------------------------------------------------------------
  1368. function setArgs (eventName, eventArgs, nodeID) // invoke with the view as "this"
  1369. {
  1370. var self = this;
  1371. var topdownName = this.topdownName;
  1372. var topdownTemp = this.topdownTemp;
  1373. var eventNameAlpha = $.encoder.encodeForAlphaNumeric(eventName);
  1374. var eventNameHTML = $.encoder.encodeForHTML(eventName);
  1375. $(topdownTemp).html("<div class='header'><img src='images/back.png' id='" + eventNameAlpha + "-back' alt='back'/> " + eventNameHTML + "<input type='button' class='input_button_call' id='fire' value='Fire' style='float:right;position:relative;top:5px;right:33px'></input></div>");
  1376. $('#' + eventNameAlpha + '-back').click ( function(evt) {
  1377. drillUp.call(self, nodeID);
  1378. });
  1379. for(var i=1; i<=8; i++)
  1380. {
  1381. $(topdownTemp).append("<div id='arg" + i + "' class='propEntry'><table><tr><td><b>Argument " + i + ": </b></td><td><input type='text' class='input_text' id='input-arg" + i + "'></td></tr></table></div>");
  1382. $('#input-arg'+ i).keydown( function(evt) {
  1383. evt.stopPropagation();
  1384. });
  1385. $('#input-arg'+ i).keypress( function(evt) {
  1386. evt.stopPropagation();
  1387. });
  1388. $('#input-arg'+ i).keyup( function(evt) {
  1389. evt.stopPropagation();
  1390. });
  1391. }
  1392. $(topdownTemp).append("<div style='font-weight:bold;text-align:right;padding-right:10px'></div>");
  1393. $('#fire').click ( function (evt) {
  1394. var args = new Array();
  1395. for(var i=1; i<=8; i++)
  1396. {
  1397. if( $('#input-arg'+ i).val() )
  1398. {
  1399. var arg = $('#input-arg'+ i).val();
  1400. try {
  1401. arg = JSON.parse($.encoder.canonicalize(arg));
  1402. args.push( arg );
  1403. } catch (e) {
  1404. self.logger.error('Invalid Value');
  1405. }
  1406. }
  1407. }
  1408. self.kernel.fireEvent(nodeID, eventName, args);
  1409. });
  1410. $(topdownName).hide('slide', {direction: 'left'}, 175);
  1411. $(topdownTemp).show('slide', {direction: 'right'}, 175);
  1412. this.topdownName = topdownTemp;
  1413. this.topdownTemp = topdownName;
  1414. }
  1415. function getPrototypes( kernel, extendsID ) {
  1416. var prototypes = [];
  1417. var id = extendsID;
  1418. while ( id !== undefined ) {
  1419. prototypes.push( id );
  1420. id = kernel.prototype( id );
  1421. }
  1422. return prototypes;
  1423. }
  1424. function getPrototypes( kernel, extendsID ) {
  1425. var prototypes = [];
  1426. var id = extendsID;
  1427. while ( id !== undefined ) {
  1428. prototypes.push( id );
  1429. id = kernel.prototype( id );
  1430. }
  1431. return prototypes;
  1432. }
  1433. function createProperty( node, propertyName, propertyValue ) {
  1434. var property = {
  1435. name: propertyName,
  1436. rawValue: propertyValue,
  1437. value: undefined,
  1438. getValue: function() {
  1439. var propertyValue;
  1440. if ( this.value == undefined ) {
  1441. try {
  1442. propertyValue = utility.transform( this.rawValue, utility.transforms.transit );
  1443. this.value = JSON.stringify( propertyValue );
  1444. } catch (e) {
  1445. this.logger.warnx( "createdProperty", nodeID, this.propertyName, this.rawValue,
  1446. "stringify error:", e.message );
  1447. this.value = this.rawValue;
  1448. }
  1449. }
  1450. return this.value;
  1451. }
  1452. };
  1453. return property;
  1454. }
  1455. function getProperties( kernel, extendsID ) {
  1456. var pTypes = getPrototypes( kernel, extendsID );
  1457. var pProperties = {};
  1458. if ( pTypes ) {
  1459. for ( var i=0; i < pTypes.length; i++ ) {
  1460. var nd = this.nodes[ pTypes[i] ];
  1461. if ( nd && nd.properties ) {
  1462. for ( var key in nd.properties ) {
  1463. pProperties[ key ] = { "prop": nd.properties[ key ], "prototype": pTypes[i] };
  1464. }
  1465. }
  1466. }
  1467. }
  1468. return pProperties;
  1469. }
  1470. function getChildren( kernel, extendsID ) {
  1471. var pTypes = getPrototypes( kernel, extendsID );
  1472. var pChildren = {};
  1473. if ( pTypes ) {
  1474. for ( var i=0; i < pTypes.length; i++ ) {
  1475. var nd = this.nodes[ pTypes[i] ];
  1476. if ( nd && nd.children ) {
  1477. for ( var key in nd.children ) {
  1478. pChildren[ key ] = nd.children[key];
  1479. }
  1480. }
  1481. }
  1482. }
  1483. return pChildren;
  1484. }
  1485. function getEvents( kernel, extendsID ) {
  1486. var pTypes = getPrototypes( kernel, extendsID );
  1487. var events = {};
  1488. if ( pTypes ) {
  1489. for ( var i = 0; i < pTypes.length; i++ ) {
  1490. var nd = this.nodes[ pTypes[i] ];
  1491. if ( nd && nd.events ) {
  1492. for ( var key in nd.events ) {
  1493. events[ key ] = nd.events[key];
  1494. }
  1495. }
  1496. }
  1497. }
  1498. return events;
  1499. }
  1500. function getMethods( kernel, extendsID ) {
  1501. var pTypes = getPrototypes( kernel, extendsID );
  1502. var methods = {};
  1503. if ( pTypes ) {
  1504. for ( var i = 0; i < pTypes.length; i++ ) {
  1505. var nd = this.nodes[ pTypes[i] ];
  1506. if ( nd && nd.methods ) {
  1507. for ( var key in nd.methods ) {
  1508. methods[ key ] = nd.methods[key];
  1509. }
  1510. }
  1511. }
  1512. }
  1513. return methods;
  1514. }
  1515. function highlightChildInHierarchy(nodeID) {
  1516. if (this.editorOpen && this.editorView == 1) // Hierarchy view open
  1517. {
  1518. var childDiv = $("div[id='" + nodeID +"']");
  1519. if(childDiv.length > 0) {
  1520. var previousChild = $("div[id='" + this.highlightedChild +"']");
  1521. if(previousChild.length > 0) {
  1522. previousChild.removeClass('childContainerHighlight');
  1523. }
  1524. childDiv.addClass('childContainerHighlight');
  1525. this.highlightedChild = nodeID;
  1526. }
  1527. }
  1528. }
  1529. // -- showTimeline ----------------------------------------------------------------------
  1530. function showTimeline() // invoke with the view as "this"
  1531. {
  1532. var timeline = this.timeline;
  1533. if(!this.timelineInit)
  1534. {
  1535. $('#time_control').append("<div class='header'>Timeline</div>" +
  1536. "<div style='text-align:center;padding-top:10px'><span><button id='play'></button><button id='stop'></button></span>" +
  1537. "<span><span class='rate slider'></span>&nbsp;" +
  1538. "<span class='rate vwf-label' style='display: inline-block; width:8ex'></span></span></div>");
  1539. var options = {};
  1540. [ "play", "pause", "stop" ].forEach( function( state ) {
  1541. options[state] = { icons: { primary: "ui-icon-" + state }, label: state, text: false };
  1542. } );
  1543. options.rate = { value: 0, min: -2, max: 2, step: 0.1, };
  1544. var state = {};
  1545. $.get(
  1546. "admin/state",
  1547. undefined,
  1548. function( data ) {
  1549. state = data;
  1550. $( "button#play" ).button( "option", state.playing ? options.pause : options.play );
  1551. $( "button#stop" ).button( "option", "disabled", state.stopped );
  1552. $( ".rate.slider" ).slider( "value", Math.log( state.rate ) / Math.LN10 );
  1553. if ( state.rate < 1.0 ) {
  1554. var label_rate = 1.0 / state.rate;
  1555. }
  1556. else {
  1557. var label_rate = state.rate;
  1558. }
  1559. var label = label_rate.toFixed(2).toString().replace( /(\.\d*?)0+$/, "$1" ).replace( /\.$/, "" );
  1560. if ( state.rate < 1.0 ) {
  1561. label = "&#x2215; " + label;
  1562. } else {
  1563. label = label + " &times;";
  1564. }
  1565. $( ".rate.vwf-label" ).html( label );
  1566. },
  1567. "json"
  1568. );
  1569. $( "button#play" ).button(
  1570. options.pause
  1571. ). click( function() {
  1572. $.post(
  1573. state.playing ? "admin/pause" : "admin/play",
  1574. undefined,
  1575. function( data ) {
  1576. state = data;
  1577. $( "button#play" ).button( "option", state.playing ? options.pause : options.play );
  1578. $( "button#stop" ).button( "option", "disabled", state.stopped );
  1579. },
  1580. "json"
  1581. );
  1582. } );
  1583. $( "button#stop" ).button(
  1584. options.stop
  1585. ). click( function() {
  1586. $.post(
  1587. "admin/stop",
  1588. undefined,
  1589. function( data ) {
  1590. state = data;
  1591. $( "button#play" ).button( "option", state.playing ? options.pause : options.play );
  1592. $( "button#stop" ).button( "option", "disabled", state.stopped );
  1593. },
  1594. "json"
  1595. );
  1596. } );
  1597. $( ".rate.slider" ).slider(
  1598. options.rate
  1599. ) .bind( "slide", function( event, ui ) {
  1600. $.get(
  1601. "admin/state",
  1602. { "rate": Math.pow( 10, Number(ui.value) ) },
  1603. function( data ) {
  1604. state = data;
  1605. $( ".rate.slider" ).slider( "value", Math.log( state.rate ) / Math.LN10 );
  1606. if ( state.rate < 1.0 ) {
  1607. var label_rate = 1.0 / state.rate;
  1608. }
  1609. else {
  1610. var label_rate = state.rate;
  1611. }
  1612. var label = label_rate.toFixed(2).toString().replace( /(\.\d*?)0+$/, "$1" ).replace( /\.$/, "" );
  1613. if ( state.rate < 1.0 ) {
  1614. label = "&#x2215; " + label;
  1615. } else {
  1616. label = label + " &times;";
  1617. }
  1618. $( ".rate.vwf-label" ).html( label );
  1619. },
  1620. "json"
  1621. );
  1622. } );
  1623. this.timelineInit = true;
  1624. }
  1625. if (!this.editorOpen)
  1626. {
  1627. $(timeline).show('slide', {direction: 'right'}, 175);
  1628. }
  1629. else
  1630. {
  1631. $(timeline).show();
  1632. }
  1633. }
  1634. // -- Show Code Editor tab
  1635. function showCodeEditorTab() // invoke with the view as "this"
  1636. {
  1637. var self = this;
  1638. var codeEditor= this.codeEditor;
  1639. if(!this.codeEditorInit)
  1640. {
  1641. $('#codeEditor_tab').append("<div class='header'>Live Code Editor</div>");
  1642. $('#codeEditor_tab').append("<div style='padding:6px'><input type='button' id='min' value='Min Window' /><span> </span><input class='live_button' type='button' id='printit' value='Print It' /><span> </span><input class='live_button' type='button' id='doit' value='Do It' /></div>");
  1643. $("#doit").click(function(evt) {
  1644. codeEditorDoit.call(self, editor, sceneID);
  1645. });
  1646. $("#printit").click(function(evt) {
  1647. codeEditorPrintit.call(self, editor, sceneID);
  1648. });
  1649. // $('#codeEditor_tab').append("<div style='padding:6px'></div>");
  1650. $('#min').click(function(evt) {
  1651. $('#editor').animate({ 'left' : "-260px" }, 175);
  1652. $('.vwf-tree').animate({ 'width' : "260px" }, 175);
  1653. });
  1654. //Open Live Editor
  1655. $('#codeEditor_tab').append('<div id="editorlive">console.log("test")</div>');
  1656. var sceneID = self.kernel.application();
  1657. var editor = createAceEditor(self, sceneID);
  1658. editor.on('blur', function (event, editor) {
  1659. // $('#editor').animate({ 'left' : "-260px" }, 175);
  1660. // $('.vwf-tree').animate({ 'width' : "260px" }, 175);
  1661. });
  1662. this.codeEditorInit = true;
  1663. }
  1664. if (!this.editorOpen)
  1665. {
  1666. $(codeEditor).show('slide', {direction: 'right'}, 175);
  1667. }
  1668. else
  1669. {
  1670. $(codeEditor).show();
  1671. // $('#editor').animate({ 'left' : "-500px" }, 175);
  1672. // $('.vwf-tree').animate({ 'width' : "500px" }, 175);
  1673. }
  1674. }
  1675. function codeEditorDoit(editor, nodeID)
  1676. {
  1677. var selectedText = editor.getSession().doc.getTextRange(editor.selection.getRange());
  1678. if (selectedText == "") {
  1679. var currline = editor.getSelectionRange().start.row;
  1680. var selectedText = editor.session.getLine(currline);
  1681. }
  1682. //console.log(selectedText);
  1683. //var sceneID = self.kernel.application();
  1684. vwf_view.kernel.execute(nodeID, selectedText);
  1685. }
  1686. function codeEditorPrintit(editor, nodeID)
  1687. {
  1688. var selectedText = editor.getSession().doc.getTextRange(editor.selection.getRange());
  1689. if (selectedText == "") {
  1690. var currline = editor.getSelectionRange().start.row;
  1691. var selectedText = editor.session.getLine(currline);
  1692. }
  1693. //console.log(selectedText);
  1694. //var sceneID = self.kernel.application();
  1695. let scriptText = 'console.log('+selectedText+');'
  1696. self.kernel.execute(nodeID, scriptText);
  1697. }
  1698. // -- showAboutTab ----------------------------------------------------------------------
  1699. function showAboutTab() // invoke with the view as "this"
  1700. {
  1701. var about = this.about;
  1702. if(!this.aboutInit)
  1703. {
  1704. $('#about_tab').append("<div class='header'>About</div>" +
  1705. "<div class='about'><p style='font:bold 12pt Arial'>Virtual World Framework & LiveCode editor</p>" +
  1706. "<p><b>Version: </b> 0.1 <b>VWF version: </b>" + version.toString() + "</p>" +
  1707. "<p><b>This project site: </b><a href='http://demo.krestianstvo.org' target='_blank'>http://demo.krestianstvo.org</a></p>" +
  1708. "<p><b>Site VWF: </b><a href='http://virtualworldframework.com' target='_blank'>http://virtualworldframework.com</a></p>" +
  1709. "<p><b>Project source: </b><a href='https://github.com/NikolaySuslov/vwf/tree/aframe' target='_blank'>https://github.com/NikolaySuslov/vwf/tree/aframe</a></p></div>");
  1710. this.aboutInit = true;
  1711. }
  1712. if (!this.editorOpen)
  1713. {
  1714. $(about).show('slide', {direction: 'right'}, 175);
  1715. }
  1716. else
  1717. {
  1718. $(about).show();
  1719. }
  1720. }
  1721. // -- showModelsTab ----------------------------------------------------------------------
  1722. function showModelsTab(modelID, modelURL) // invoke with the view as "this"
  1723. {
  1724. var self = this;
  1725. var models = this.models;
  1726. var modelsTemp = this.modelsTemp;
  1727. this.currentModelID = modelID;
  1728. this.currentModelURL = modelURL;
  1729. $(models).html("");
  1730. if(modelID == "") {
  1731. $(modelsTemp).html("<div class='header'>Models</div>");
  1732. $.getJSON("admin/models", function( data ) {
  1733. if(data.length > 0) {
  1734. $.each( data, function( key, value ) {
  1735. var fileName = encodeURIComponent(value['basename']);
  1736. var divId = fileName;
  1737. if(divId.indexOf('.') != -1) {
  1738. divId = divId.replace(/\./g, "_");
  1739. }
  1740. var url = value['url'];
  1741. $(modelsTemp).append("<div class='childContainer'><div id='" + divId + "' class='modelEntry' data-url='" + url + "'>"
  1742. + fileName + "</div></div>");
  1743. $("#" + divId).click(function(e) {
  1744. modelDrillDown.call(self, e.target.textContent, e.target.getAttribute("data-url"));
  1745. })
  1746. });
  1747. }
  1748. else {
  1749. $(modelsTemp).append("<div class='childEntry'><p style='font:bold 12pt Arial'>No Models Found</p></div>");
  1750. }
  1751. } );
  1752. }
  1753. else {
  1754. var divId = modelID;
  1755. if(divId.indexOf('.') != -1) {
  1756. divId = divId.replace(/\./g, "_");
  1757. }
  1758. $(modelsTemp).html("<div id='" + divId + "-backDiv' class='header'><img src='images/back.png' id='" + divId + "-back' alt='back'/>" + modelID + "</div>");
  1759. $("#" + divId + "-back").click(function(e) {
  1760. modelDrillUp.call(self, '');
  1761. });
  1762. $(modelsTemp).append("<div id='" + divId + "-rotation' class='propEntry'><table><tr><td><b>Rotation</b></td><td>" +
  1763. "<input type='text' class='input_text' id='input-" + divId + "-rotation' value='[1,0,0,0]'></td></tr></table></div>");
  1764. $('#input-' + divId + '-rotation').keydown( function(evt) {
  1765. evt.stopPropagation();
  1766. });
  1767. $('#input-' + divId + '-rotation').keypress( function(evt) {
  1768. evt.stopPropagation();
  1769. });
  1770. $('#input-' + divId + '-rotation').keyup( function(evt) {
  1771. evt.stopPropagation();
  1772. });
  1773. $(modelsTemp).append("<div id='" + divId + "-scale' class='propEntry'><table><tr><td><b>Scale</b></td><td>" +
  1774. "<input type='text' class='input_text' id='input-" + divId + "-scale' value='[1,1,1]'></td></tr></table></div>");
  1775. $('#input-' + divId + '-scale').keydown( function(evt) {
  1776. evt.stopPropagation();
  1777. });
  1778. $('#input-' + divId + '-scale').keypress( function(evt) {
  1779. evt.stopPropagation();
  1780. });
  1781. $('#input-' + divId + '-scale').keyup( function(evt) {
  1782. evt.stopPropagation();
  1783. });
  1784. $(modelsTemp).append("<div id='" + divId + "-translation' class='propEntry'><table><tr><td><b>Translation Offset</b></td><td>" +
  1785. "<input type='text' class='input_text' id='input-" + divId + "-translation' value='[0,0,0]'></td></tr></table></div>");
  1786. $('#input-' + divId + '-translation').keydown( function(evt) {
  1787. evt.stopPropagation();
  1788. });
  1789. $('#input-' + divId + '-translation').keypress( function(evt) {
  1790. evt.stopPropagation();
  1791. });
  1792. $('#input-' + divId + '-translation').keyup( function(evt) {
  1793. evt.stopPropagation();
  1794. });
  1795. $(modelsTemp).append("<div class='drag'><div id='" + divId + "-drag' class='modelEntry' draggable='true' data-escaped-name='" + divId +"' data-url='" + modelURL + "'>Drag To Create</div></div>");
  1796. $("#" + divId + "-drag").on("dragstart", function (e) {
  1797. var fileName = $("#" + e.target.getAttribute("data-escaped-name") + "-backDiv").text();
  1798. var rotation = encodeURIComponent($("#input-" + e.target.getAttribute("data-escaped-name") + "-rotation").val());
  1799. var scale = encodeURIComponent($("#input-" + e.target.getAttribute("data-escaped-name") + "-scale").val());
  1800. var translation = encodeURIComponent($("#input-" + e.target.getAttribute("data-escaped-name") + "-translation").val());
  1801. var fileData = "{\"fileName\":\""+fileName+"\", \"fileUrl\":\""+e.target.getAttribute("data-url")+"\", " +
  1802. "\"rotation\":\"" + rotation + "\", \"scale\":\"" + scale + "\", \"translation\":\"" + translation + "\"}";
  1803. e.originalEvent.dataTransfer.setData('text/plain', fileData);
  1804. e.originalEvent.dataTransfer.setDragImage(e.target, 0, 0);
  1805. return true;
  1806. });
  1807. }
  1808. }
  1809. // -- Model drillDown -------------------------------------------------------------------------
  1810. function modelDrillDown(modelID, modelURL) // invoke with the view as "this"
  1811. {
  1812. var models = this.models;
  1813. var modelsTemp = this.modelsTemp;
  1814. showModelsTab.call(this, modelID, modelURL);
  1815. if(modelID != "") $(models).hide('slide', {direction: 'left'}, 175);
  1816. $(modelsTemp).show('slide', {direction: 'right'}, 175);
  1817. this.models = modelsTemp;
  1818. this.modelsTemp = models;
  1819. }
  1820. // -- Model drillUp ---------------------------------------------------------------------------
  1821. function modelDrillUp(modelID) // invoke with the view as "this"
  1822. {
  1823. var models = this.models;
  1824. var modelsTemp = this.modelsTemp;
  1825. showModelsTab.call(this, modelID);
  1826. $(models).hide('slide', {direction: 'right'}, 175);
  1827. $(modelsTemp).show('slide', {direction: 'left'}, 175);
  1828. this.models = modelsTemp;
  1829. this.modelsTemp = models;
  1830. }
  1831. // -- SaveStateAsFile -------------------------------------------------------------------------
  1832. function saveStateAsFile(filename) // invoke with the view as "this"
  1833. {
  1834. this.logger.info("Saving: " + filename);
  1835. if(supportAjaxUploadWithProgress.call(this))
  1836. {
  1837. var xhr = new XMLHttpRequest();
  1838. // Save State Information
  1839. var state = vwf.getState();
  1840. var timestamp = state["queue"].time;
  1841. timestamp = Math.round(timestamp * 1000);
  1842. var objectIsTypedArray = function( candidate ) {
  1843. var typedArrayTypes = [
  1844. Int8Array,
  1845. Uint8Array,
  1846. // Uint8ClampedArray,
  1847. Int16Array,
  1848. Uint16Array,
  1849. Int32Array,
  1850. Uint32Array,
  1851. Float32Array,
  1852. Float64Array
  1853. ];
  1854. var isTypedArray = false;
  1855. if ( typeof candidate == "object" && candidate != null ) {
  1856. typedArrayTypes.forEach( function( typedArrayType ) {
  1857. isTypedArray = isTypedArray || candidate instanceof typedArrayType;
  1858. } );
  1859. }
  1860. return isTypedArray;
  1861. };
  1862. var transitTransformation = function( object ) {
  1863. return objectIsTypedArray( object ) ?
  1864. Array.prototype.slice.call( object ) : object;
  1865. };
  1866. var json = JSON.stringify(
  1867. require("vwf/utility").transform(
  1868. state, transitTransformation
  1869. )
  1870. );
  1871. json = $.encoder.encodeForURL(json);
  1872. var path = window.location.pathname;
  1873. var pathSplit = path.split('/');
  1874. if ( pathSplit[0] == "" ) {
  1875. pathSplit.shift();
  1876. }
  1877. if ( pathSplit[ pathSplit.length - 1 ] == "" ) {
  1878. pathSplit.pop();
  1879. }
  1880. var inst = undefined;
  1881. var instIndex = pathSplit.length - 1;
  1882. if ( pathSplit.length > 2 ) {
  1883. if ( pathSplit[ pathSplit.length - 2 ] == "load" ) {
  1884. instIndex = pathSplit.length - 3;
  1885. }
  1886. }
  1887. if ( pathSplit.length > 3 ) {
  1888. if ( pathSplit[ pathSplit.length - 3 ] == "load" ) {
  1889. instIndex = pathSplit.length - 4;
  1890. }
  1891. }
  1892. inst = pathSplit[ instIndex ];
  1893. var root = "";
  1894. for ( var i=0; i < instIndex; i++ ) {
  1895. if ( root != "" ) {
  1896. root = root + "/";
  1897. }
  1898. root = root + pathSplit[i];
  1899. }
  1900. if(filename == '') filename = inst;
  1901. if(root.indexOf('.vwf') != -1) root = root.substring(0, root.lastIndexOf('/'));
  1902. xhr.open("POST", "/"+root+"/save/"+filename, true);
  1903. xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  1904. xhr.send("root="+root+"/"+filename+"&filename=saveState&inst="+inst+"&timestamp="+timestamp+"&extension=.vwf.json"+"&jsonState="+json);
  1905. // Save Config Information
  1906. var config = {"info":{}, "model":{}, "view":{} };
  1907. // Save browser title
  1908. config["info"]["title"] = $('title').html();
  1909. // Save model drivers
  1910. Object.keys(vwf_view.kernel.kernel.models).forEach(function(modelDriver) {
  1911. if(modelDriver.indexOf('vwf/model/') != -1) config["model"][modelDriver] = "";
  1912. });
  1913. // If neither glge or threejs model drivers are defined, specify nodriver
  1914. if(config["model"]["vwf/model/glge"] === undefined && config["model"]["vwf/model/threejs"] === undefined) config["model"]["nodriver"] = "";
  1915. // Save view drivers and associated parameters, if any
  1916. Object.keys(vwf_view.kernel.kernel.views).forEach(function(viewDriver) {
  1917. if(viewDriver.indexOf('vwf/view/') != -1)
  1918. {
  1919. if( vwf_view.kernel.kernel.views[viewDriver].parameters )
  1920. {
  1921. config["view"][viewDriver] = vwf_view.kernel.kernel.views[viewDriver].parameters;
  1922. }
  1923. else config["view"][viewDriver] = "";
  1924. }
  1925. });
  1926. var jsonConfig = $.encoder.encodeForURL( JSON.stringify( config ) );
  1927. // Save config file to server
  1928. var xhrConfig = new XMLHttpRequest();
  1929. xhrConfig.open("POST", "/"+root+"/save/"+filename, true);
  1930. xhrConfig.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  1931. xhrConfig.send("root="+root+"/"+filename+"&filename=saveState&inst="+inst+"&timestamp="+timestamp+"&extension=.vwf.config.json"+"&jsonState="+jsonConfig);
  1932. }
  1933. else
  1934. {
  1935. console.error("Unable to save state.");
  1936. }
  1937. }
  1938. // -- LoadSavedState --------------------------------------------------------------------------
  1939. function loadSavedState(filename, applicationpath, revision)
  1940. {
  1941. this.logger.info("Loading: " + filename);
  1942. // Redirect until setState ID conflict is resolved
  1943. var path = window.location.pathname;
  1944. var inst = path.substring(path.length-17, path.length-1);
  1945. var pathSplit = path.split('/');
  1946. if ( pathSplit[0] == "" ) {
  1947. pathSplit.shift();
  1948. }
  1949. if ( pathSplit[ pathSplit.length - 1 ] == "" ) {
  1950. pathSplit.pop();
  1951. }
  1952. var inst = undefined;
  1953. var instIndex = pathSplit.length - 1;
  1954. if ( pathSplit.length > 2 ) {
  1955. if ( pathSplit[ pathSplit.length - 2 ] == "load" ) {
  1956. instIndex = pathSplit.length - 3;
  1957. }
  1958. }
  1959. if ( pathSplit.length > 3 ) {
  1960. if ( pathSplit[ pathSplit.length - 3 ] == "load" ) {
  1961. instIndex = pathSplit.length - 4;
  1962. }
  1963. }
  1964. inst = pathSplit[ instIndex ];
  1965. if ( revision ) {
  1966. window.location.pathname = applicationpath + "/" + inst + '/load/' + filename + '/' + revision + '/';
  1967. }
  1968. else {
  1969. window.location.pathname = applicationpath + "/" + inst + '/load/' + filename + '/';
  1970. }
  1971. // $.get(filename,function(data,status){
  1972. // vwf.setState(data);
  1973. // });
  1974. }
  1975. // -- SupportAjax -----------------------------------------------------------------------------
  1976. function supportAjaxUploadWithProgress()
  1977. {
  1978. return supportAjaxUploadProgressEvents();
  1979. function supportAjaxUploadProgressEvents()
  1980. {
  1981. var xhr = new XMLHttpRequest();
  1982. return !! (xhr && ('upload' in xhr) && ('onprogress' in xhr.upload));
  1983. }
  1984. }
  1985. } );