Skip to content

Commit

Permalink
Kick off hawtio-editor directive and upgrade to latest CodeMirror
Browse files Browse the repository at this point in the history
  • Loading branch information
gashcrumb committed May 2, 2013
1 parent ff33da1 commit 10b062b
Show file tree
Hide file tree
Showing 75 changed files with 8,266 additions and 2,226 deletions.
3 changes: 3 additions & 0 deletions hawtio-web/src/main/webapp/app/ui/html/editor.html
@@ -0,0 +1,3 @@
<div class="editor-autoresize">
<textarea name="{{name}}" ng-model="text"></textarea>
</div>
14 changes: 14 additions & 0 deletions hawtio-web/src/main/webapp/app/ui/html/test.html
Expand Up @@ -90,9 +90,23 @@
</div>
</div>
</div>
</div>
</div>


<div>
Pager
<div class="row-fluid">


</div>
</div>

<div>
CodeMirror
<div class="row-fluid">
<div hawtio-editor="someText" mode="javascript"></div>
<div>Text : {{someText}}</div>
</div>
</div>

Expand Down
79 changes: 79 additions & 0 deletions hawtio-web/src/main/webapp/app/ui/js/editorDirective.ts
@@ -0,0 +1,79 @@
module UI {

export class Editor {

public restrict = 'A';
public replace = true;

public templateUrl = UI.templatePath + "editor.html";

public scope = {
text: '=hawtioEditor',
mode: '@',
name: '@',
readonly: '@',
id: '@'
};

public controller = ($scope, $element, $attrs) => {

$scope.codeMirror = null;
$scope.options = [];

observe($scope, $attrs, 'name', 'editor');
observe($scope, $attrs, 'mode', 'text');
observe($scope, $attrs, 'readonly', 'false');

$scope.applyOptions = () => {
if ($scope.codeMirror) {
$scope.options.each(function(option) {
$scope.codeMirror.setOption(option.key, option['value']);
});
$scope.options = [];
}
}

};

public link = ($scope, $element, $attrs) => {

$scope.$watch('options.length', $scope.applyOptions);

$scope.$watch('text', function() {
if (!$scope.codeMirror) {

var options:any = {
value: $scope.text
};

options = CodeEditor.createEditorSettings(options);
$scope.codeMirror = CodeMirror.fromTextArea($element.find('textarea').get(0), options);
$scope.applyOptions();
$scope.doc = $scope.codeMirror.getDoc();
$scope.codeMirror.on('change', function(changeObj) {
$scope.text = $scope.doc.getValue();
$scope.$apply();
});
}
});

$scope.$watch('mode', function() {
if ($scope.mode) {
$scope.options.push({
key: 'mode',
'value': $scope.mode
});
}
});

$scope.$watch('readonly', function() {
$scope.options.push({
key: 'readonly',
'value': $scope.readonly
});
});
};


}
}
8 changes: 8 additions & 0 deletions hawtio-web/src/main/webapp/app/ui/js/testController.ts
Expand Up @@ -18,6 +18,14 @@ module UI {
$scope.showSlideoutRight = false;
$scope.showSlideoutLeft = false;

$scope.someText = "var someValue = 0;\n" +
"var someFunc = function() {\n" +
" return \"Hello World!;\n" +
"}\n";

$scope.$watch('someText', function() {
console.log("Some text: ", $scope.someText);
});

}

Expand Down
3 changes: 3 additions & 0 deletions hawtio-web/src/main/webapp/app/ui/js/uiPlugin.ts
Expand Up @@ -17,6 +17,9 @@ module UI {
}).
directive('hawtioPager', function() {
return new UI.TablePager();
}).
directive('hawtioEditor', function() {
return new UI.Editor();
});


Expand Down
Expand Up @@ -25,13 +25,17 @@
var inp = dialog.getElementsByTagName("input")[0], button;
if (inp) {
CodeMirror.on(inp, "keydown", function(e) {
if (options && options.onKeyDown && options.onKeyDown(e, inp.value, close)) { return; }
if (e.keyCode == 13 || e.keyCode == 27) {
CodeMirror.e_stop(e);
close();
me.focus();
if (e.keyCode == 13) callback(inp.value);
}
});
if (options && options.onKeyUp) {
CodeMirror.on(inp, "keyup", function(e) {options.onKeyUp(e, inp.value, close);});
}
if (options && options.value) inp.value = options.value;
inp.focus();
CodeMirror.on(inp, "blur", close);
Expand Down
@@ -0,0 +1,54 @@
(function() {
CodeMirror.defineOption("placeholder", "", function(cm, val, old) {
var prev = old && old != CodeMirror.Init;
if (val && !prev) {
cm.on("focus", onFocus);
cm.on("blur", onBlur);
cm.on("change", onChange);
onChange(cm);
} else if (!val && prev) {
cm.off("focus", onFocus);
cm.off("blur", onBlur);
cm.off("change", onChange);
clearPlaceholder(cm);
var wrapper = cm.getWrapperElement();
wrapper.className = wrapper.className.replace(" CodeMirror-empty", "");
}

if (val && !cm.hasFocus()) onBlur(cm);
});

function clearPlaceholder(cm) {
if (cm._placeholder) {
cm._placeholder.parentNode.removeChild(cm._placeholder);
cm._placeholder = null;
}
}
function setPlaceholder(cm) {
clearPlaceholder(cm);
var elt = cm._placeholder = document.createElement("pre");
elt.style.cssText = "height: 0; overflow: visible";
elt.className = "CodeMirror-placeholder";
elt.appendChild(document.createTextNode(cm.getOption("placeholder")));
cm.display.lineSpace.insertBefore(elt, cm.display.lineSpace.firstChild);
}

function onFocus(cm) {
clearPlaceholder(cm);
}
function onBlur(cm) {
if (isEmpty(cm)) setPlaceholder(cm);
}
function onChange(cm) {
var wrapper = cm.getWrapperElement(), empty = isEmpty(cm);
wrapper.className = wrapper.className.replace(" CodeMirror-empty", "") + (empty ? " CodeMirror-empty" : "");

if (cm.hasFocus()) return;
if (empty) setPlaceholder(cm);
else clearPlaceholder(cm);
}

function isEmpty(cm) {
return (cm.lineCount() === 1) && (cm.getLine(0) === "");
}
})();
@@ -0,0 +1,54 @@
(function() {
var DEFAULT_BRACKETS = "()[]{}''\"\"";
var SPACE_CHAR_REGEX = /\s/;

CodeMirror.defineOption("autoCloseBrackets", false, function(cm, val, old) {
var wasOn = old && old != CodeMirror.Init;
if (val && !wasOn)
cm.addKeyMap(buildKeymap(typeof val == "string" ? val : DEFAULT_BRACKETS));
else if (!val && wasOn)
cm.removeKeyMap("autoCloseBrackets");
});

function buildKeymap(pairs) {
var map = {
name : "autoCloseBrackets",
Backspace: function(cm) {
if (cm.somethingSelected()) return CodeMirror.Pass;
var cur = cm.getCursor(), line = cm.getLine(cur.line);
if (cur.ch && cur.ch < line.length &&
pairs.indexOf(line.slice(cur.ch - 1, cur.ch + 1)) % 2 == 0)
cm.replaceRange("", CodeMirror.Pos(cur.line, cur.ch - 1), CodeMirror.Pos(cur.line, cur.ch + 1));
else
return CodeMirror.Pass;
}
};
var closingBrackets = [];
for (var i = 0; i < pairs.length; i += 2) (function(left, right) {
if (left != right) closingBrackets.push(right);
function surround(cm) {
var selection = cm.getSelection();
cm.replaceSelection(left + selection + right);
}
function maybeOverwrite(cm) {
var cur = cm.getCursor(), ahead = cm.getRange(cur, CodeMirror.Pos(cur.line, cur.ch + 1));
if (ahead != right || cm.somethingSelected()) return CodeMirror.Pass;
else cm.execCommand("goCharRight");
}
map["'" + left + "'"] = function(cm) {
if (left == "'" && cm.getTokenAt(cm.getCursor()).type == "comment")
return CodeMirror.Pass;
if (cm.somethingSelected()) return surround(cm);
if (left == right && maybeOverwrite(cm) != CodeMirror.Pass) return;
var cur = cm.getCursor(), ahead = CodeMirror.Pos(cur.line, cur.ch + 1);
var line = cm.getLine(cur.line), nextChar = line.charAt(cur.ch);
if (line.length == cur.ch || closingBrackets.indexOf(nextChar) >= 0 || SPACE_CHAR_REGEX.test(nextChar))
cm.replaceSelection(left + right, {head: ahead, anchor: ahead});
else
return CodeMirror.Pass;
};
if (left != right) map["'" + right + "'"] = maybeOverwrite;
})(pairs.charAt(i), pairs.charAt(i + 1));
return map;
}
})();
17 changes: 9 additions & 8 deletions hawtio-web/src/main/webapp/lib/codemirror/addon/edit/closetag.js
Expand Up @@ -27,9 +27,9 @@
if (val && (old == CodeMirror.Init || !old)) {
var map = {name: "autoCloseTags"};
if (typeof val != "object" || val.whenClosing)
map["'/'"] = function(cm) { autoCloseTag(cm, '/'); };
map["'/'"] = function(cm) { return autoCloseTag(cm, '/'); };
if (typeof val != "object" || val.whenOpening)
map["'>'"] = function(cm) { autoCloseTag(cm, '>'); };
map["'>'"] = function(cm) { return autoCloseTag(cm, '>'); };
cm.addKeyMap(map);
} else if (!val && (old != CodeMirror.Init && old)) {
cm.removeKeyMap("autoCloseTags");
Expand All @@ -44,7 +44,7 @@
function autoCloseTag(cm, ch) {
var pos = cm.getCursor(), tok = cm.getTokenAt(pos);
var inner = CodeMirror.innerMode(cm.getMode(), tok.state), state = inner.state;
if (inner.mode.name != "xml") throw CodeMirror.Pass;
if (inner.mode.name != "xml") return CodeMirror.Pass;

var opt = cm.getOption("autoCloseTags"), html = inner.mode.configuration == "html";
var dontCloseTags = (typeof opt == "object" && opt.dontCloseTags) || (html && htmlDontClose);
Expand All @@ -56,24 +56,25 @@
var lowerTagName = tagName.toLowerCase();
// Don't process the '>' at the end of an end-tag or self-closing tag
if (tok.type == "tag" && state.type == "closeTag" ||
/\/\s*$/.test(tok.string) ||
tok.string.indexOf("/") == (tok.string.length - 1) || // match something like <someTagName />
dontCloseTags && indexOf(dontCloseTags, lowerTagName) > -1)
throw CodeMirror.Pass;
return CodeMirror.Pass;

var doIndent = indentTags && indexOf(indentTags, lowerTagName) > -1;
var curPos = doIndent ? CodeMirror.Pos(pos.line + 1, 0) : CodeMirror.Pos(pos.line, pos.ch + 1);
cm.replaceSelection(">" + (doIndent ? "\n\n" : "") + "</" + tagName + ">",
doIndent ? {line: pos.line + 1, ch: 0} : {line: pos.line, ch: pos.ch + 1});
{head: curPos, anchor: curPos});
if (doIndent) {
cm.indentLine(pos.line + 1);
cm.indentLine(pos.line + 2);
}
return;
} else if (ch == "/" && tok.type == "tag" && tok.string == "<") {
} else if (ch == "/" && tok.string == "<") {
var tagName = state.context && state.context.tagName;
if (tagName) cm.replaceSelection("/" + tagName + ">", "end");
return;
}
throw CodeMirror.Pass;
return CodeMirror.Pass;
}

function indexOf(collection, elt) {
Expand Down
Expand Up @@ -5,14 +5,14 @@
blockCommentEnd: "*/",
blockCommentContinue: " * "});

CodeMirror.commands.newlineAndIndentContinueComment = function(cm) {
function continueComment(cm) {
var pos = cm.getCursor(), token = cm.getTokenAt(pos);
var mode = CodeMirror.innerMode(cm.getMode(), token.state).mode;
var space;

if (token.type == "comment" && mode.blockCommentStart) {
var end = token.string.indexOf(mode.blockCommentEnd);
var full = cm.getRange({line: pos.line, ch: 0}, {line: pos.line, ch: token.end}), found;
var full = cm.getRange(CodeMirror.Pos(pos.line, 0), CodeMirror.Pos(pos.line, token.end)), found;
if (end != -1 && end == token.string.length - mode.blockCommentEnd.length) {
// Comment ended, don't continue it
} else if (token.string.indexOf(mode.blockCommentStart) == 0) {
Expand All @@ -31,6 +31,14 @@
if (space != null)
cm.replaceSelection("\n" + space + mode.blockCommentContinue, "end");
else
cm.execCommand("newlineAndIndent");
};
return CodeMirror.Pass;
}

CodeMirror.defineOption("continueComments", null, function(cm, val, prev) {
if (prev && prev != CodeMirror.Init)
cm.removeKeyMap("continueComment");
var map = {name: "continueComment"};
map[typeof val == "string" ? val : "Enter"] = continueComment;
cm.addKeyMap(map);
});
})();
@@ -1,28 +1,25 @@
(function() {
'use strict';

var listRE = /^(\s*)([*+-]|(\d+)\.)(\s*)/,
unorderedBullets = '*+-';

CodeMirror.commands.newlineAndIndentContinueMarkdownList = function(cm) {
var pos = cm.getCursor(), token = cm.getTokenAt(pos);
var space;
if (token.className == "string") {
var full = cm.getRange({line: pos.line, ch: 0}, {line: pos.line, ch: token.end});
var listStart = /\*|\d+\./, listContinue;
if (token.string.search(listStart) == 0) {
var reg = /^[\W]*(\d+)\./g;
var matches = reg.exec(full);
if(matches)
listContinue = (parseInt(matches[1]) + 1) + ". ";
else
listContinue = "* ";
space = full.slice(0, token.start);
if (!/^\s*$/.test(space)) {
space = "";
for (var i = 0; i < token.start; ++i) space += " ";
}
}
var pos = cm.getCursor(),
inList = cm.getStateAfter(pos.line).list,
match;

if (!inList || !(match = cm.getLine(pos.line).match(listRE))) {
cm.execCommand('newlineAndIndent');
return;
}

if (space != null)
cm.replaceSelection("\n" + space + listContinue, "end");
else
cm.execCommand("newlineAndIndent");
var indent = match[1], after = match[4];
var bullet = unorderedBullets.indexOf(match[2]) >= 0
? match[2]
: (parseInt(match[3], 10) + 1) + '.';

cm.replaceSelection('\n' + indent + bullet + after, 'end');
};
})();

}());

0 comments on commit 10b062b

Please sign in to comment.