Script.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. for ( var i = 0; i < widgets.length; i ++ ) {
  66. codemirror.removeLineWidget( widgets[ i ] );
  67. }
  68. widgets.length = 0;
  69. //
  70. try {
  71. syntax = esprima.parse( string, { tolerant: true } );
  72. errors = syntax.errors;
  73. for ( var i = 0; i < errors.length; i ++ ) {
  74. var error = errors[ i ];
  75. var message = document.createElement( 'div' );
  76. message.className = 'esprima-error';
  77. message.textContent = error.message.replace(/Line [0-9]+: /, '');
  78. var lineNumber = error.lineNumber - 1;
  79. errorLines.push( lineNumber );
  80. codemirror.addLineClass( lineNumber, 'background', 'errorLine' );
  81. var widget = codemirror.addLineWidget(
  82. lineNumber,
  83. message
  84. );
  85. widgets.push( widget );
  86. }
  87. } catch ( error ) {
  88. var message = document.createElement( 'div' );
  89. message.className = 'esprima-error';
  90. message.textContent = error.message.replace(/Line [0-9]+: /, '');
  91. var lineNumber = error.lineNumber - 1;
  92. errorLines.push( lineNumber );
  93. codemirror.addLineClass( lineNumber, 'background', 'errorLine' );
  94. var widget = codemirror.addLineWidget(
  95. lineNumber,
  96. message
  97. );
  98. widgets.push( widget );
  99. }
  100. return errorLines.length === 0;
  101. });
  102. };
  103. //
  104. signals.editorCleared.add( function () {
  105. container.setDisplay( 'none' );
  106. } );
  107. signals.editScript.add( function ( object, script ) {
  108. container.setDisplay( '' );
  109. currentScript = script;
  110. title.setValue( object.name + ' / ' + script.name );
  111. codemirror.setValue( script.source );
  112. } );
  113. return container;
  114. };