phrebejk@460: // 'use strict'; phrebejk@460: phrebejk@460: // Declare app level module which depends on filters, and services phrebejk@460: angular.module('bck2brwsr', []). phrebejk@460: directive('uiCodemirror', ['$timeout', function($timeout) { phrebejk@460: 'use strict'; phrebejk@460: phrebejk@460: var events = ["cursorActivity", "viewportChange", "gutterClick", "focus", "blur", "scroll", "update"]; phrebejk@460: return { phrebejk@460: restrict: 'A', phrebejk@460: require: 'ngModel', phrebejk@460: link: function(scope, elm, attrs, ngModel) { phrebejk@460: var options, opts, onChange, deferCodeMirror, codeMirror, timeoutId, val; phrebejk@460: phrebejk@460: if (elm[0].type !== 'textarea') { phrebejk@460: throw new Error('uiCodemirror3 can only be applied to a textarea element'); phrebejk@460: } phrebejk@460: phrebejk@460: options = /* uiConfig.codemirror || */ {}; phrebejk@460: opts = angular.extend({}, options, scope.$eval(attrs.uiCodemirror)); phrebejk@460: phrebejk@460: onChange = function(instance, changeObj) { phrebejk@460: val = instance.getValue(); phrebejk@460: $timeout.cancel(timeoutId); phrebejk@460: timeoutId = $timeout(function() { phrebejk@460: ngModel.$setViewValue(val); phrebejk@460: }, 500); phrebejk@460: }; phrebejk@460: phrebejk@460: deferCodeMirror = function() { phrebejk@460: codeMirror = CodeMirror.fromTextArea(elm[0], opts); phrebejk@541: elm[0].codeMirror = codeMirror; phrebejk@460: // codeMirror.on("change", onChange(opts.onChange)); phrebejk@460: codeMirror.on("change", onChange); phrebejk@460: phrebejk@460: for (var i = 0, n = events.length, aEvent; i < n; ++i) { phrebejk@460: aEvent = opts["on" + events[i].charAt(0).toUpperCase() + events[i].slice(1)]; phrebejk@460: if (aEvent === void 0) phrebejk@460: continue; phrebejk@460: if (typeof aEvent !== "function") phrebejk@460: continue; phrebejk@460: phrebejk@460: var bound = _.bind( aEvent, scope ); phrebejk@460: phrebejk@460: codeMirror.on(events[i], bound); phrebejk@460: } phrebejk@460: phrebejk@460: // CodeMirror expects a string, so make sure it gets one. phrebejk@460: // This does not change the model. phrebejk@460: ngModel.$formatters.push(function(value) { phrebejk@460: if (angular.isUndefined(value) || value === null) { phrebejk@460: return ''; phrebejk@460: } phrebejk@460: else if (angular.isObject(value) || angular.isArray(value)) { phrebejk@460: throw new Error('ui-codemirror cannot use an object or an array as a model'); phrebejk@460: } phrebejk@460: return value; phrebejk@460: }); phrebejk@460: phrebejk@460: // Override the ngModelController $render method, which is what gets called when the model is updated. phrebejk@460: // This takes care of the synchronizing the codeMirror element with the underlying model, in the case that it is changed by something else. phrebejk@460: ngModel.$render = function() { phrebejk@460: codeMirror.setValue(ngModel.$viewValue); phrebejk@460: }; phrebejk@460: phrebejk@460: }; phrebejk@460: phrebejk@460: $timeout(deferCodeMirror); phrebejk@460: phrebejk@460: } phrebejk@460: }; phrebejk@460: }]); phrebejk@460: phrebejk@461: function DevCtrl( $scope, $http ) { jaroslav@545: var templateHtml = jaroslav@545: "\n" + jaroslav@545: " \n" + jaroslav@545: " \n" + jaroslav@545: " * 0 \n" + jaroslav@545: " = 0\n" + jaroslav@545: "
\n" + jaroslav@545: " \n" + jaroslav@545: " " + jaroslav@545: "
\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: "\n" + jaroslav@545: " \n" + jaroslav@545: " \n" + jaroslav@545: ""; jaroslav@545: var templateJava = jaroslav@545: "package bck2brwsr.demo;\n" + jaroslav@545: "import org.apidesign.bck2brwsr.htmlpage.api.*;\n" + jaroslav@545: "import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;\n" + jaroslav@545: "\n" + jaroslav@545: "@Page(xhtml=\"index.html\", className=\"Index\", properties={\n" + jaroslav@545: " @Property(name=\"value\", type=int.class)\n" + jaroslav@545: "})\n" + jaroslav@545: "class YourFirstHTML5PageInRealLanguage {\n" + jaroslav@545: " static { new Index().applyBindings(); }\n" + jaroslav@545: " @On(event=CLICK, id=\"dupl\") static void duplicateValue(Index m) {\n" + jaroslav@545: " m.setValue(m.getValue() * 2);\n" + jaroslav@545: " }\n" + jaroslav@545: " @On(event=CLICK, id=\"clear\") static void zeroTheValue(Index m) {\n" + jaroslav@545: " m.setValue(0);;\n" + jaroslav@545: " }\n" + jaroslav@545: " @ComputedProperty static int powerValue(int value) {\n" + jaroslav@545: " return value * value;\n" + jaroslav@545: " }\n" + jaroslav@545: "}"; jaroslav@466: phrebejk@460: phrebejk@542: $scope.makeMarker = function( editor, line ) { phrebejk@542: var marker = document.createElement("div"); phrebejk@542: marker.innerHTML = " "; phrebejk@542: marker.className = "issue"; phrebejk@542: phrebejk@542: var info = editor.lineInfo(line); phrebejk@542: editor.setGutterMarker(line, "issues", info.markers ? null : marker); phrebejk@542: phrebejk@542: return marker; phrebejk@542: }; phrebejk@542: phrebejk@542: phrebejk@542: // Returns a function, that, as long as it continues to be invoked, will not phrebejk@542: // be triggered. The function will be called after it stops being called for phrebejk@542: // N milliseconds. If `immediate` is passed, trigger the function on the phrebejk@542: // leading edge, instead of the trailing. phrebejk@542: $scope.debounce = function(func, wait, immediate) { phrebejk@542: var timeout, result; phrebejk@542: return function() { phrebejk@542: var context = this, args = arguments; phrebejk@542: var later = function() { phrebejk@542: timeout = null; phrebejk@542: if (!immediate) result = func.apply(context, args); phrebejk@542: }; phrebejk@542: var callNow = immediate && !timeout; phrebejk@542: clearTimeout(timeout); phrebejk@542: timeout = setTimeout(later, wait); phrebejk@542: if (callNow) result = func.apply(context, args); phrebejk@542: return result; phrebejk@542: }; phrebejk@542: }; phrebejk@542: phrebejk@541: $scope.reload = function() { phrebejk@541: $scope.errors = null; phrebejk@461: var frame = document.getElementById("result"); phrebejk@461: frame.src = "result.html"; phrebejk@461: frame.contentDocument.location.reload(true); phrebejk@461: frame.contentWindow.location.reload(); phrebejk@542: document.getElementById("editorJava").codeMirror.clearGutter("issues"); phrebejk@461: }; phrebejk@461: phrebejk@541: $scope.fail = function( data ) { phrebejk@541: $scope.errors = eval( data ); phrebejk@542: var editor = document.getElementById("editorJava").codeMirror; phrebejk@542: editor.clearGutter( "issues" ); phrebejk@542: phrebejk@542: for( var i = 0; i < $scope.errors.length; i ++ ) { phrebejk@542: $scope.makeMarker( editor, $scope.errors[i].line - 1 ); phrebejk@542: } phrebejk@542: phrebejk@541: }; phrebejk@541: phrebejk@542: $scope.post = function() { phrebejk@461: return $http({url: ".", phrebejk@461: method: "POST", phrebejk@461: //headers: this.headers, phrebejk@461: data: { html : $scope.html, java : $scope.java} phrebejk@541: }).success( $scope.reload ).error( $scope.fail ); phrebejk@541: }; phrebejk@541: phrebejk@541: $scope.errorClass = function( kind ) { phrebejk@541: switch( kind ) { phrebejk@541: case "ERROR" : phrebejk@541: return "error"; phrebejk@541: default : phrebejk@541: return "warning"; phrebejk@541: } phrebejk@541: }; phrebejk@541: phrebejk@541: $scope.gotoError = function( line, col ) { phrebejk@541: var editor = document.getElementById("editorJava").codeMirror; phrebejk@542: editor.setCursor({ line: line - 1, ch : col - 1 }); phrebejk@541: editor.focus(); phrebejk@460: }; phrebejk@460: phrebejk@460: $scope.tab = "html"; jaroslav@466: $scope.html= templateHtml; jaroslav@466: $scope.java = templateJava; phrebejk@460: phrebejk@542: $scope.$watch( "html", $scope.debounce( $scope.post, 2000 ) ); phrebejk@542: $scope.$watch( "java", $scope.debounce( $scope.post, 2000 ) ); jaroslav@466: $scope.post(); phrebejk@460: phrebejk@460: }