Script.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. /**
  2. * @author mrdoob / http://mrdoob.com/
  3. */
  4. var Script = function ( editor ) {
  5. var signals = editor.signals;
  6. var container = new UI.Panel();
  7. container.setId( 'script' );
  8. container.setPosition( 'absolute' );
  9. container.setBackgroundColor( '#272822' );
  10. container.setDisplay( 'none' );
  11. var header = new UI.Panel();
  12. header.setPadding( '10px' );
  13. container.add( header );
  14. var title = new UI.Text().setColor( '#fff' );
  15. header.add( title );
  16. var buttonSVG = ( function () {
  17. var svg = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' );
  18. svg.setAttribute( 'width', 32 );
  19. svg.setAttribute( 'height', 32 );
  20. var path = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' );
  21. path.setAttribute( 'd', 'M 12,12 L 22,22 M 22,12 12,22' );
  22. path.setAttribute( 'stroke', '#fff' );
  23. svg.appendChild( path );
  24. return svg;
  25. } )();
  26. var close = new UI.Element( buttonSVG );
  27. close.setPosition( 'absolute' );
  28. close.setTop( '3px' );
  29. close.setRight( '1px' );
  30. close.setCursor( 'pointer' );
  31. close.onClick( function () {
  32. container.setDisplay( 'none' );
  33. } );
  34. header.add( close );
  35. var delay;
  36. var currentScript;
  37. var codemirror = CodeMirror( container.dom, {
  38. value: '',
  39. lineNumbers: true,
  40. matchBrackets: true,
  41. indentWithTabs: true,
  42. tabSize: 4,
  43. indentUnit: 4
  44. } );
  45. codemirror.setOption( 'theme', 'monokai' );
  46. codemirror.on( 'change', function () {
  47. clearTimeout( delay );
  48. delay = setTimeout( function () {
  49. var value = codemirror.getValue();
  50. if ( validate( value ) ) {
  51. currentScript.source = value;
  52. signals.scriptChanged.dispatch( currentScript );
  53. }
  54. }, 300 );
  55. });
  56. // validate
  57. var errorLines = [];
  58. var widgets = [];
  59. var validate = function ( string ) {
  60. var syntax, errors;
  61. return codemirror.operation( function () {
  62. while ( errorLines.length > 0 ) {
  63. codemirror.removeLineClass( errorLines.shift(), 'background', 'errorLine' );
  64. }
  65. while ( widgets.length > 0 ) {
  66. codemirror.removeLineWidget( widgets.shift() );
  67. }
  68. //
  69. try {
  70. syntax = esprima.parse( string, { tolerant: true } );
  71. errors = syntax.errors;
  72. for ( var i = 0; i < errors.length; i ++ ) {
  73. var error = errors[ i ];
  74. var message = document.createElement( 'div' );
  75. message.className = 'esprima-error';
  76. message.textContent = error.message.replace(/Line [0-9]+: /, '');
  77. var lineNumber = error.lineNumber - 1;
  78. errorLines.push( lineNumber );
  79. codemirror.addLineClass( lineNumber, 'background', 'errorLine' );
  80. var widget = codemirror.addLineWidget(
  81. lineNumber,
  82. message
  83. );
  84. widgets.push( widget );
  85. }
  86. } catch ( error ) {
  87. var message = document.createElement( 'div' );
  88. message.className = 'esprima-error';
  89. message.textContent = error.message.replace(/Line [0-9]+: /, '');
  90. var lineNumber = error.lineNumber - 1;
  91. errorLines.push( lineNumber );
  92. codemirror.addLineClass( lineNumber, 'background', 'errorLine' );
  93. var widget = codemirror.addLineWidget(
  94. lineNumber,
  95. message
  96. );
  97. widgets.push( widget );
  98. }
  99. return errorLines.length === 0;
  100. });
  101. };
  102. //
  103. signals.editorCleared.add( function () {
  104. container.setDisplay( 'none' );
  105. } );
  106. signals.editScript.add( function ( object, script ) {
  107. container.setDisplay( '' );
  108. currentScript = script;
  109. title.setValue( object.name + ' / ' + script.name );
  110. codemirror.setValue( script.source );
  111. } );
  112. return container;
  113. };