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: }