3 // Declare app level module which depends on filters, and services
4 angular.module('bck2brwsr', []).
5 directive('uiCodemirror', ['$timeout', function($timeout) {
8 var events = ["cursorActivity", "viewportChange", "gutterClick", "focus", "blur", "scroll", "update"];
12 link: function(scope, elm, attrs, ngModel) {
13 var options, opts, onChange, deferCodeMirror, codeMirror, timeoutId, val;
15 if (elm[0].type !== 'textarea') {
16 throw new Error('uiCodemirror3 can only be applied to a textarea element');
19 options = /* uiConfig.codemirror || */ {};
20 opts = angular.extend({}, options, scope.$eval(attrs.uiCodemirror));
22 onChange = function(instance, changeObj) {
23 val = instance.getValue();
24 $timeout.cancel(timeoutId);
25 timeoutId = $timeout(function() {
26 ngModel.$setViewValue(val);
30 deferCodeMirror = function() {
31 codeMirror = CodeMirror.fromTextArea(elm[0], opts);
32 elm[0].codeMirror = codeMirror;
33 // codeMirror.on("change", onChange(opts.onChange));
34 codeMirror.on("change", onChange);
36 for (var i = 0, n = events.length, aEvent; i < n; ++i) {
37 aEvent = opts["on" + events[i].charAt(0).toUpperCase() + events[i].slice(1)];
38 if (aEvent === void 0)
40 if (typeof aEvent !== "function")
43 var bound = _.bind( aEvent, scope );
45 codeMirror.on(events[i], bound);
48 // CodeMirror expects a string, so make sure it gets one.
49 // This does not change the model.
50 ngModel.$formatters.push(function(value) {
51 if (angular.isUndefined(value) || value === null) {
54 else if (angular.isObject(value) || angular.isArray(value)) {
55 throw new Error('ui-codemirror cannot use an object or an array as a model');
60 // Override the ngModelController $render method, which is what gets called when the model is updated.
61 // This takes care of the synchronizing the codeMirror element with the underlying model, in the case that it is changed by something else.
62 ngModel.$render = function() {
63 codeMirror.setValue(ngModel.$viewValue);
68 $timeout(deferCodeMirror);
74 function DevCtrl( $scope, $http ) {
77 " <input data-bind=\"value: value, valueUpdate: 'afterkeydown'\" \n" +
78 " value=\"0\" type=\"number\">\n" +
80 " * <span data-bind=\"text: value\">0</span> \n" +
81 " = <span data-bind=\"text: powerValue\">0</span>\n" +
83 " <button id='dupl'>Duplicate!</button>\n" +
84 " <button id=\"clear\">Clear!</button>" +
106 " <script src=\"/bck2brwsr.js\"></script>\n" +
107 " <script type=\"text/javascript\">\n" +
108 " function ldCls(res) {\n" +
109 " var request = new XMLHttpRequest();\n" +
110 " request.open('GET', '/classes/' + res, false);\n" +
111 " request.send();\n" +
112 " var arr = eval('(' + request.responseText + ')');\n" +
115 " var vm = bck2brwsr(ldCls);\n" +
116 " vm.loadClass('${fqn}');\n" +
120 "package bck2brwsr.demo;\n" +
121 "import org.apidesign.bck2brwsr.htmlpage.api.*;\n" +
122 "import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;\n" +
124 "@Page(xhtml=\"index.html\", className=\"Index\", properties={\n" +
125 " @Property(name=\"value\", type=int.class)\n" +
127 "class YourFirstHTML5PageInRealLanguage {\n" +
128 " static { new Index().applyBindings(); }\n" +
129 " @On(event=CLICK, id=\"dupl\") static void duplicateValue(Index m) {\n" +
130 " m.setValue(m.getValue() * 2);\n" +
132 " @On(event=CLICK, id=\"clear\") static void zeroTheValue(Index m) {\n" +
133 " m.setValue(0);;\n" +
135 " @ComputedProperty static int powerValue(int value) {\n" +
136 " return value * value;\n" +
141 $scope.makeMarker = function( editor, line ) {
142 var marker = document.createElement("div");
143 marker.innerHTML = " ";
144 marker.className = "issue";
146 var info = editor.lineInfo(line);
147 editor.setGutterMarker(line, "issues", info.markers ? null : marker);
153 // Returns a function, that, as long as it continues to be invoked, will not
154 // be triggered. The function will be called after it stops being called for
155 // N milliseconds. If `immediate` is passed, trigger the function on the
156 // leading edge, instead of the trailing.
157 $scope.debounce = function(func, wait, immediate) {
160 var context = this, args = arguments;
161 var later = function() {
163 if (!immediate) result = func.apply(context, args);
165 var callNow = immediate && !timeout;
166 clearTimeout(timeout);
167 timeout = setTimeout(later, wait);
168 if (callNow) result = func.apply(context, args);
173 $scope.reload = function() {
174 $scope.errors = null;
175 var frame = document.getElementById("result");
176 frame.src = "result.html";
177 frame.contentDocument.location.reload(true);
178 frame.contentWindow.location.reload();
179 document.getElementById("editorJava").codeMirror.clearGutter("issues");
182 $scope.fail = function( data ) {
183 $scope.errors = eval( data );
184 var editor = document.getElementById("editorJava").codeMirror;
185 editor.clearGutter( "issues" );
187 for( var i = 0; i < $scope.errors.length; i ++ ) {
188 $scope.makeMarker( editor, $scope.errors[i].line - 1 );
193 $scope.post = function() {
194 return $http({url: ".",
196 //headers: this.headers,
197 data: { html : $scope.html, java : $scope.java}
198 }).success( $scope.reload ).error( $scope.fail );
201 $scope.errorClass = function( kind ) {
210 $scope.gotoError = function( line, col ) {
211 var editor = document.getElementById("editorJava").codeMirror;
212 editor.setCursor({ line: line - 1, ch : col - 1 });
217 $scope.html= templateHtml;
218 $scope.java = templateJava;
220 $scope.$watch( "html", $scope.debounce( $scope.post, 2000 ) );
221 $scope.$watch( "java", $scope.debounce( $scope.post, 2000 ) );