xml-hint.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. (function() {
  2. CodeMirror.xmlHints = [];
  3. CodeMirror.xmlHint = function(cm, simbol) {
  4. if(simbol.length > 0) {
  5. var cursor = cm.getCursor();
  6. cm.replaceSelection(simbol);
  7. cursor = {line: cursor.line, ch: cursor.ch + 1};
  8. cm.setCursor(cursor);
  9. }
  10. // dirty hack for simple-hint to receive getHint event on space
  11. var getTokenAt = editor.getTokenAt;
  12. editor.getTokenAt = function() { return 'disabled'; };
  13. CodeMirror.simpleHint(cm, getHint);
  14. editor.getTokenAt = getTokenAt;
  15. };
  16. var getHint = function(cm) {
  17. var cursor = cm.getCursor();
  18. if (cursor.ch > 0) {
  19. var text = cm.getRange({line: 0, ch: 0}, cursor);
  20. var typed = '';
  21. var simbol = '';
  22. for(var i = text.length - 1; i >= 0; i--) {
  23. if(text[i] == ' ' || text[i] == '<') {
  24. simbol = text[i];
  25. break;
  26. }
  27. else {
  28. typed = text[i] + typed;
  29. }
  30. }
  31. text = text.slice(0, text.length - typed.length);
  32. var path = getActiveElement(cm, text) + simbol;
  33. var hints = CodeMirror.xmlHints[path];
  34. if(typeof hints === 'undefined')
  35. hints = [''];
  36. else {
  37. hints = hints.slice(0);
  38. for (var i = hints.length - 1; i >= 0; i--) {
  39. if(hints[i].indexOf(typed) != 0)
  40. hints.splice(i, 1);
  41. }
  42. }
  43. return {
  44. list: hints,
  45. from: { line: cursor.line, ch: cursor.ch - typed.length },
  46. to: cursor
  47. };
  48. };
  49. };
  50. var getActiveElement = function(codeMirror, text) {
  51. var element = '';
  52. if(text.length >= 0) {
  53. var regex = new RegExp('<([^!?][^\\s/>]*).*?>', 'g');
  54. var matches = [];
  55. var match;
  56. while ((match = regex.exec(text)) != null) {
  57. matches.push({
  58. tag: match[1],
  59. selfclose: (match[0].slice(match[0].length - 2) === '/>')
  60. });
  61. }
  62. for (var i = matches.length - 1, skip = 0; i >= 0; i--) {
  63. var item = matches[i];
  64. if (item.tag[0] == '/')
  65. {
  66. skip++;
  67. }
  68. else if (item.selfclose == false)
  69. {
  70. if (skip > 0)
  71. {
  72. skip--;
  73. }
  74. else
  75. {
  76. element = '<' + item.tag + '>' + element;
  77. }
  78. }
  79. }
  80. element += getOpenTag(text);
  81. }
  82. return element;
  83. };
  84. var getOpenTag = function(text) {
  85. var open = text.lastIndexOf('<');
  86. var close = text.lastIndexOf('>');
  87. if (close < open)
  88. {
  89. text = text.slice(open);
  90. if(text != '<') {
  91. var space = text.indexOf(' ');
  92. if(space < 0)
  93. space = text.indexOf('\t');
  94. if(space < 0)
  95. space = text.indexOf('\n');
  96. if (space < 0)
  97. space = text.length;
  98. return text.slice(0, space);
  99. }
  100. }
  101. return '';
  102. };
  103. })();