PageRenderTime 96ms CodeModel.GetById 34ms RepoModel.GetById 1ms app.codeStats 3ms

/node_modules/node-inspector/front-end/devtools.js

https://bitbucket.org/E_lexy/jmonitor
JavaScript | 18673 lines | 15945 code | 2253 blank | 475 comment | 1502 complexity | a4c4924773b2b5e2f953e62c60f1ad5e MD5 | raw file
Possible License(s): MIT, Apache-2.0, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. String.prototype.hasSubstring = function(string, caseInsensitive)
  2. {
  3. if (!caseInsensitive)
  4. return this.indexOf(string) !== -1;
  5. return this.match(new RegExp(string.escapeForRegExp(), "i"));
  6. }
  7. String.prototype.findAll = function(string)
  8. {
  9. var matches = [];
  10. var i = this.indexOf(string);
  11. while (i !== -1) {
  12. matches.push(i);
  13. i = this.indexOf(string, i + string.length);
  14. }
  15. return matches;
  16. }
  17. String.prototype.lineEndings = function()
  18. {
  19. if (!this._lineEndings) {
  20. this._lineEndings = this.findAll("\n");
  21. this._lineEndings.push(this.length);
  22. }
  23. return this._lineEndings;
  24. }
  25. String.prototype.escapeCharacters = function(chars)
  26. {
  27. var foundChar = false;
  28. for (var i = 0; i < chars.length; ++i) {
  29. if (this.indexOf(chars.charAt(i)) !== -1) {
  30. foundChar = true;
  31. break;
  32. }
  33. }
  34. if (!foundChar)
  35. return this;
  36. var result = "";
  37. for (var i = 0; i < this.length; ++i) {
  38. if (chars.indexOf(this.charAt(i)) !== -1)
  39. result += "\\";
  40. result += this.charAt(i);
  41. }
  42. return result;
  43. }
  44. String.prototype.escapeForRegExp = function()
  45. {
  46. return this.escapeCharacters("^[]{}()\\.$*+?|");
  47. }
  48. String.prototype.escapeHTML = function()
  49. {
  50. return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
  51. }
  52. String.prototype.collapseWhitespace = function()
  53. {
  54. return this.replace(/[\s\xA0]+/g, " ");
  55. }
  56. String.prototype.trimMiddle = function(maxLength)
  57. {
  58. if (this.length <= maxLength)
  59. return this;
  60. var leftHalf = maxLength >> 1;
  61. var rightHalf = maxLength - leftHalf - 1;
  62. return this.substr(0, leftHalf) + "\u2026" + this.substr(this.length - rightHalf, rightHalf);
  63. }
  64. String.prototype.trimEnd = function(maxLength)
  65. {
  66. if (this.length <= maxLength)
  67. return this;
  68. return this.substr(0, maxLength - 1) + "\u2026";
  69. }
  70. String.prototype.trimURL = function(baseURLDomain)
  71. {
  72. var result = this.replace(/^(https|http|file):\/\//i, "");
  73. if (baseURLDomain)
  74. result = result.replace(new RegExp("^" + baseURLDomain.escapeForRegExp(), "i"), "");
  75. return result;
  76. }
  77. String.prototype.removeURLFragment = function()
  78. {
  79. var fragmentIndex = this.indexOf("#");
  80. if (fragmentIndex == -1)
  81. fragmentIndex = this.length;
  82. return this.substring(0, fragmentIndex);
  83. }
  84. String.prototype.startsWith = function(substring)
  85. {
  86. return !this.lastIndexOf(substring, 0);
  87. }
  88. String.prototype.endsWith = function(substring)
  89. {
  90. return this.indexOf(substring, this.length - substring.length) !== -1;
  91. }
  92. Number.constrain = function(num, min, max)
  93. {
  94. if (num < min)
  95. num = min;
  96. else if (num > max)
  97. num = max;
  98. return num;
  99. }
  100. Date.prototype.toISO8601Compact = function()
  101. {
  102. function leadZero(x)
  103. {
  104. return x > 9 ? '' + x : '0' + x
  105. }
  106. return this.getFullYear() +
  107. leadZero(this.getMonth() + 1) +
  108. leadZero(this.getDate()) + 'T' +
  109. leadZero(this.getHours()) +
  110. leadZero(this.getMinutes()) +
  111. leadZero(this.getSeconds());
  112. }
  113. Object.defineProperty(Array.prototype, "remove",
  114. {
  115. value: function(value, onlyFirst)
  116. {
  117. if (onlyFirst) {
  118. var index = this.indexOf(value);
  119. if (index !== -1)
  120. this.splice(index, 1);
  121. return;
  122. }
  123. var length = this.length;
  124. for (var i = 0; i < length; ++i) {
  125. if (this[i] === value)
  126. this.splice(i, 1);
  127. }
  128. }
  129. });
  130. Object.defineProperty(Array.prototype, "keySet",
  131. {
  132. value: function()
  133. {
  134. var keys = {};
  135. for (var i = 0; i < this.length; ++i)
  136. keys[this[i]] = true;
  137. return keys;
  138. }
  139. });
  140. Object.defineProperty(Array.prototype, "upperBound",
  141. {
  142. value: function(value)
  143. {
  144. var first = 0;
  145. var count = this.length;
  146. while (count > 0) {
  147. var step = count >> 1;
  148. var middle = first + step;
  149. if (value >= this[middle]) {
  150. first = middle + 1;
  151. count -= step + 1;
  152. } else
  153. count = step;
  154. }
  155. return first;
  156. }
  157. });
  158. Object.defineProperty(Uint32Array.prototype, "sort", {
  159. value: Array.prototype.sort
  160. });
  161. (function() {
  162. var partition = {
  163. value: function(comparator, left, right, pivotIndex)
  164. {
  165. function swap(array, i1, i2)
  166. {
  167. var temp = array[i1];
  168. array[i1] = array[i2];
  169. array[i2] = temp;
  170. }
  171. var pivotValue = this[pivotIndex];
  172. swap(this, right, pivotIndex);
  173. var storeIndex = left;
  174. for (var i = left; i < right; ++i) {
  175. if (comparator(this[i], pivotValue) < 0) {
  176. swap(this, storeIndex, i);
  177. ++storeIndex;
  178. }
  179. }
  180. swap(this, right, storeIndex);
  181. return storeIndex;
  182. }
  183. };
  184. Object.defineProperty(Array.prototype, "partition", partition);
  185. Object.defineProperty(Uint32Array.prototype, "partition", partition);
  186. var sortRange = {
  187. value: function(comparator, leftBound, rightBound, k)
  188. {
  189. function quickSortFirstK(array, comparator, left, right, k)
  190. {
  191. if (right <= left)
  192. return;
  193. var pivotIndex = Math.floor(Math.random() * (right - left)) + left;
  194. var pivotNewIndex = array.partition(comparator, left, right, pivotIndex);
  195. quickSortFirstK(array, comparator, left, pivotNewIndex - 1, k);
  196. if (pivotNewIndex < left + k - 1)
  197. quickSortFirstK(array, comparator, pivotNewIndex + 1, right, k);
  198. }
  199. if (leftBound === 0 && rightBound === (this.length - 1) && k === this.length)
  200. this.sort(comparator);
  201. else
  202. quickSortFirstK(this, comparator, leftBound, rightBound, k);
  203. return this;
  204. }
  205. }
  206. Object.defineProperty(Array.prototype, "sortRange", sortRange);
  207. Object.defineProperty(Uint32Array.prototype, "sortRange", sortRange);
  208. })();
  209. Object.defineProperty(Array.prototype, "qselect",
  210. {
  211. value: function(k, comparator)
  212. {
  213. if (k < 0 || k >= this.length)
  214. return;
  215. if (!comparator)
  216. comparator = function(a, b) { return a - b; }
  217. var low = 0;
  218. var high = this.length - 1;
  219. for (;;) {
  220. var pivotPosition = this.partition(comparator, low, high, Math.floor((high + low) / 2));
  221. if (pivotPosition === k)
  222. return this[k];
  223. else if (pivotPosition > k)
  224. high = pivotPosition - 1;
  225. else
  226. low = pivotPosition + 1;
  227. }
  228. }
  229. });
  230. function binarySearch(object, array, comparator)
  231. {
  232. var first = 0;
  233. var last = array.length - 1;
  234. while (first <= last) {
  235. var mid = (first + last) >> 1;
  236. var c = comparator(object, array[mid]);
  237. if (c > 0)
  238. first = mid + 1;
  239. else if (c < 0)
  240. last = mid - 1;
  241. else
  242. return mid;
  243. }
  244. return -(first + 1);
  245. }
  246. Object.defineProperty(Array.prototype, "binaryIndexOf",
  247. {
  248. value: function(value, comparator)
  249. {
  250. var result = binarySearch(value, this, comparator);
  251. return result >= 0 ? result : -1;
  252. }
  253. });
  254. function insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunction)
  255. {
  256. var index = binarySearch(anObject, aList, aFunction);
  257. if (index < 0)
  258. return -index - 1;
  259. else {
  260. while (index > 0 && aFunction(anObject, aList[index - 1]) === 0)
  261. index--;
  262. return index;
  263. }
  264. }
  265. Array.diff = function(left, right)
  266. {
  267. var o = left;
  268. var n = right;
  269. var ns = {};
  270. var os = {};
  271. for (var i = 0; i < n.length; i++) {
  272. if (ns[n[i]] == null)
  273. ns[n[i]] = { rows: [], o: null };
  274. ns[n[i]].rows.push(i);
  275. }
  276. for (var i = 0; i < o.length; i++) {
  277. if (os[o[i]] == null)
  278. os[o[i]] = { rows: [], n: null };
  279. os[o[i]].rows.push(i);
  280. }
  281. for (var i in ns) {
  282. if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) {
  283. n[ns[i].rows[0]] = { text: n[ns[i].rows[0]], row: os[i].rows[0] };
  284. o[os[i].rows[0]] = { text: o[os[i].rows[0]], row: ns[i].rows[0] };
  285. }
  286. }
  287. for (var i = 0; i < n.length - 1; i++) {
  288. if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && n[i + 1] == o[n[i].row + 1]) {
  289. n[i + 1] = { text: n[i + 1], row: n[i].row + 1 };
  290. o[n[i].row + 1] = { text: o[n[i].row + 1], row: i + 1 };
  291. }
  292. }
  293. for (var i = n.length - 1; i > 0; i--) {
  294. if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null &&
  295. n[i - 1] == o[n[i].row - 1]) {
  296. n[i - 1] = { text: n[i - 1], row: n[i].row - 1 };
  297. o[n[i].row - 1] = { text: o[n[i].row - 1], row: i - 1 };
  298. }
  299. }
  300. return { left: o, right: n };
  301. }
  302. Array.convert = function(list)
  303. {
  304. return Array.prototype.slice.call(list);
  305. }
  306. String.sprintf = function(format, var_arg)
  307. {
  308. return String.vsprintf(format, Array.prototype.slice.call(arguments, 1));
  309. }
  310. String.tokenizeFormatString = function(format, formatters)
  311. {
  312. var tokens = [];
  313. var substitutionIndex = 0;
  314. function addStringToken(str)
  315. {
  316. tokens.push({ type: "string", value: str });
  317. }
  318. function addSpecifierToken(specifier, precision, substitutionIndex)
  319. {
  320. tokens.push({ type: "specifier", specifier: specifier, precision: precision, substitutionIndex: substitutionIndex });
  321. }
  322. function isDigit(c)
  323. {
  324. return !!/[0-9]/.exec(c);
  325. }
  326. var index = 0;
  327. for (var precentIndex = format.indexOf("%", index); precentIndex !== -1; precentIndex = format.indexOf("%", index)) {
  328. addStringToken(format.substring(index, precentIndex));
  329. index = precentIndex + 1;
  330. if (isDigit(format[index])) {
  331. var number = parseInt(format.substring(index), 10);
  332. while (isDigit(format[index]))
  333. ++index;
  334. if (number > 0 && format[index] === "$") {
  335. substitutionIndex = (number - 1);
  336. ++index;
  337. }
  338. }
  339. var precision = -1;
  340. if (format[index] === ".") {
  341. ++index;
  342. precision = parseInt(format.substring(index), 10);
  343. if (isNaN(precision))
  344. precision = 0;
  345. while (isDigit(format[index]))
  346. ++index;
  347. }
  348. if (!(format[index] in formatters)) {
  349. addStringToken(format.substring(precentIndex, index + 1));
  350. ++index;
  351. continue;
  352. }
  353. addSpecifierToken(format[index], precision, substitutionIndex);
  354. ++substitutionIndex;
  355. ++index;
  356. }
  357. addStringToken(format.substring(index));
  358. return tokens;
  359. }
  360. String.standardFormatters = {
  361. d: function(substitution)
  362. {
  363. return !isNaN(substitution) ? substitution : 0;
  364. },
  365. f: function(substitution, token)
  366. {
  367. if (substitution && token.precision > -1)
  368. substitution = substitution.toFixed(token.precision);
  369. return !isNaN(substitution) ? substitution : (token.precision > -1 ? Number(0).toFixed(token.precision) : 0);
  370. },
  371. s: function(substitution)
  372. {
  373. return substitution;
  374. }
  375. }
  376. String.vsprintf = function(format, substitutions)
  377. {
  378. return String.format(format, substitutions, String.standardFormatters, "", function(a, b) { return a + b; }).formattedResult;
  379. }
  380. String.format = function(format, substitutions, formatters, initialValue, append)
  381. {
  382. if (!format || !substitutions || !substitutions.length)
  383. return { formattedResult: append(initialValue, format), unusedSubstitutions: substitutions };
  384. function prettyFunctionName()
  385. {
  386. return "String.format(\"" + format + "\", \"" + substitutions.join("\", \"") + "\")";
  387. }
  388. function warn(msg)
  389. {
  390. console.warn(prettyFunctionName() + ": " + msg);
  391. }
  392. function error(msg)
  393. {
  394. console.error(prettyFunctionName() + ": " + msg);
  395. }
  396. var result = initialValue;
  397. var tokens = String.tokenizeFormatString(format, formatters);
  398. var usedSubstitutionIndexes = {};
  399. for (var i = 0; i < tokens.length; ++i) {
  400. var token = tokens[i];
  401. if (token.type === "string") {
  402. result = append(result, token.value);
  403. continue;
  404. }
  405. if (token.type !== "specifier") {
  406. error("Unknown token type \"" + token.type + "\" found.");
  407. continue;
  408. }
  409. if (token.substitutionIndex >= substitutions.length) {
  410. error("not enough substitution arguments. Had " + substitutions.length + " but needed " + (token.substitutionIndex + 1) + ", so substitution was skipped.");
  411. result = append(result, "%" + (token.precision > -1 ? token.precision : "") + token.specifier);
  412. continue;
  413. }
  414. usedSubstitutionIndexes[token.substitutionIndex] = true;
  415. if (!(token.specifier in formatters)) {
  416. warn("unsupported format character \u201C" + token.specifier + "\u201D. Treating as a string.");
  417. result = append(result, substitutions[token.substitutionIndex]);
  418. continue;
  419. }
  420. result = append(result, formatters[token.specifier](substitutions[token.substitutionIndex], token));
  421. }
  422. var unusedSubstitutions = [];
  423. for (var i = 0; i < substitutions.length; ++i) {
  424. if (i in usedSubstitutionIndexes)
  425. continue;
  426. unusedSubstitutions.push(substitutions[i]);
  427. }
  428. return { formattedResult: result, unusedSubstitutions: unusedSubstitutions };
  429. }
  430. function createSearchRegex(query, caseSensitive, isRegex)
  431. {
  432. var regexFlags = caseSensitive ? "g" : "gi";
  433. var regexObject;
  434. if (isRegex) {
  435. try {
  436. regexObject = new RegExp(query, regexFlags);
  437. } catch (e) {
  438. }
  439. }
  440. if (!regexObject)
  441. regexObject = createPlainTextSearchRegex(query, regexFlags);
  442. return regexObject;
  443. }
  444. function createPlainTextSearchRegex(query, flags)
  445. {
  446. var regexSpecialCharacters = "[](){}+-*.,?\\^$|";
  447. var regex = "";
  448. for (var i = 0; i < query.length; ++i) {
  449. var c = query.charAt(i);
  450. if (regexSpecialCharacters.indexOf(c) != -1)
  451. regex += "\\";
  452. regex += c;
  453. }
  454. return new RegExp(regex, flags || "");
  455. }
  456. function countRegexMatches(regex, content)
  457. {
  458. var text = content;
  459. var result = 0;
  460. var match;
  461. while (text && (match = regex.exec(text))) {
  462. if (match[0].length > 0)
  463. ++result;
  464. text = text.substring(match.index + 1);
  465. }
  466. return result;
  467. }
  468. function numberToStringWithSpacesPadding(value, symbolsCount)
  469. {
  470. var numberString = value.toString();
  471. var paddingLength = Math.max(0, symbolsCount - numberString.length);
  472. var paddingString = Array(paddingLength + 1).join("\u00a0");
  473. return paddingString + numberString;
  474. }
  475. function TextDiff()
  476. {
  477. this.added = [];
  478. this.removed = [];
  479. this.changed = [];
  480. }
  481. TextDiff.compute = function(baseContent, newContent)
  482. {
  483. var oldLines = baseContent.split(/\r?\n/);
  484. var newLines = newContent.split(/\r?\n/);
  485. var diff = Array.diff(oldLines, newLines);
  486. var diffData = new TextDiff();
  487. var offset = 0;
  488. var right = diff.right;
  489. for (var i = 0; i < right.length; ++i) {
  490. if (typeof right[i] === "string") {
  491. if (right.length > i + 1 && right[i + 1].row === i + 1 - offset)
  492. diffData.changed.push(i);
  493. else {
  494. diffData.added.push(i);
  495. offset++;
  496. }
  497. } else
  498. offset = i - right[i].row;
  499. }
  500. return diffData;
  501. }
  502. var Map = function()
  503. {
  504. this._map = {};
  505. }
  506. Map._lastObjectIdentifier = 0;
  507. Map.prototype = {
  508. put: function(key, value)
  509. {
  510. var objectIdentifier = key.__identifier;
  511. if (!objectIdentifier) {
  512. objectIdentifier = ++Map._lastObjectIdentifier;
  513. key.__identifier = objectIdentifier;
  514. }
  515. this._map[objectIdentifier] = value;
  516. },
  517. remove: function(key)
  518. {
  519. var result = this._map[key.__identifier];
  520. delete this._map[key.__identifier];
  521. return result;
  522. },
  523. values: function()
  524. {
  525. var result = [];
  526. for (var objectIdentifier in this._map)
  527. result.push(this._map[objectIdentifier]);
  528. return result;
  529. },
  530. get: function(key)
  531. {
  532. return this._map[key.__identifier];
  533. },
  534. clear: function()
  535. {
  536. this._map = {};
  537. }
  538. }
  539. Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, direction)
  540. {
  541. var startNode;
  542. var startOffset = 0;
  543. var endNode;
  544. var endOffset = 0;
  545. if (!stayWithinNode)
  546. stayWithinNode = this;
  547. if (!direction || direction === "backward" || direction === "both") {
  548. var node = this;
  549. while (node) {
  550. if (node === stayWithinNode) {
  551. if (!startNode)
  552. startNode = stayWithinNode;
  553. break;
  554. }
  555. if (node.nodeType === Node.TEXT_NODE) {
  556. var start = (node === this ? (offset - 1) : (node.nodeValue.length - 1));
  557. for (var i = start; i >= 0; --i) {
  558. if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
  559. startNode = node;
  560. startOffset = i + 1;
  561. break;
  562. }
  563. }
  564. }
  565. if (startNode)
  566. break;
  567. node = node.traversePreviousNode(stayWithinNode);
  568. }
  569. if (!startNode) {
  570. startNode = stayWithinNode;
  571. startOffset = 0;
  572. }
  573. } else {
  574. startNode = this;
  575. startOffset = offset;
  576. }
  577. if (!direction || direction === "forward" || direction === "both") {
  578. node = this;
  579. while (node) {
  580. if (node === stayWithinNode) {
  581. if (!endNode)
  582. endNode = stayWithinNode;
  583. break;
  584. }
  585. if (node.nodeType === Node.TEXT_NODE) {
  586. var start = (node === this ? offset : 0);
  587. for (var i = start; i < node.nodeValue.length; ++i) {
  588. if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
  589. endNode = node;
  590. endOffset = i;
  591. break;
  592. }
  593. }
  594. }
  595. if (endNode)
  596. break;
  597. node = node.traverseNextNode(stayWithinNode);
  598. }
  599. if (!endNode) {
  600. endNode = stayWithinNode;
  601. endOffset = stayWithinNode.nodeType === Node.TEXT_NODE ? stayWithinNode.nodeValue.length : stayWithinNode.childNodes.length;
  602. }
  603. } else {
  604. endNode = this;
  605. endOffset = offset;
  606. }
  607. var result = this.ownerDocument.createRange();
  608. result.setStart(startNode, startOffset);
  609. result.setEnd(endNode, endOffset);
  610. return result;
  611. }
  612. Node.prototype.traverseNextTextNode = function(stayWithin)
  613. {
  614. var node = this.traverseNextNode(stayWithin);
  615. if (!node)
  616. return;
  617. while (node && node.nodeType !== Node.TEXT_NODE)
  618. node = node.traverseNextNode(stayWithin);
  619. return node;
  620. }
  621. Node.prototype.rangeBoundaryForOffset = function(offset)
  622. {
  623. var node = this.traverseNextTextNode(this);
  624. while (node && offset > node.nodeValue.length) {
  625. offset -= node.nodeValue.length;
  626. node = node.traverseNextTextNode(this);
  627. }
  628. if (!node)
  629. return { container: this, offset: 0 };
  630. return { container: node, offset: offset };
  631. }
  632. Element.prototype.removeStyleClass = function(className)
  633. {
  634. this.classList.remove(className);
  635. }
  636. Element.prototype.removeMatchingStyleClasses = function(classNameRegex)
  637. {
  638. var regex = new RegExp("(^|\\s+)" + classNameRegex + "($|\\s+)");
  639. if (regex.test(this.className))
  640. this.className = this.className.replace(regex, " ");
  641. }
  642. Element.prototype.addStyleClass = function(className)
  643. {
  644. this.classList.add(className);
  645. }
  646. Element.prototype.hasStyleClass = function(className)
  647. {
  648. return this.classList.contains(className);
  649. }
  650. Element.prototype.positionAt = function(x, y)
  651. {
  652. this.style.left = x + "px";
  653. this.style.top = y + "px";
  654. }
  655. Element.prototype.pruneEmptyTextNodes = function()
  656. {
  657. var sibling = this.firstChild;
  658. while (sibling) {
  659. var nextSibling = sibling.nextSibling;
  660. if (sibling.nodeType === this.TEXT_NODE && sibling.nodeValue === "")
  661. this.removeChild(sibling);
  662. sibling = nextSibling;
  663. }
  664. }
  665. Element.prototype.isScrolledToBottom = function()
  666. {
  667. return this.scrollTop + this.clientHeight === this.scrollHeight;
  668. }
  669. Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray)
  670. {
  671. for (var node = this; node && node !== this.ownerDocument; node = node.parentNode)
  672. for (var i = 0; i < nameArray.length; ++i)
  673. if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase())
  674. return node;
  675. return null;
  676. }
  677. Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName)
  678. {
  679. return this.enclosingNodeOrSelfWithNodeNameInArray([nodeName]);
  680. }
  681. Node.prototype.enclosingNodeOrSelfWithClass = function(className)
  682. {
  683. for (var node = this; node && node !== this.ownerDocument; node = node.parentNode)
  684. if (node.nodeType === Node.ELEMENT_NODE && node.hasStyleClass(className))
  685. return node;
  686. return null;
  687. }
  688. Node.prototype.enclosingNodeWithClass = function(className)
  689. {
  690. if (!this.parentNode)
  691. return null;
  692. return this.parentNode.enclosingNodeOrSelfWithClass(className);
  693. }
  694. Element.prototype.query = function(query)
  695. {
  696. return this.ownerDocument.evaluate(query, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  697. }
  698. Element.prototype.removeChildren = function()
  699. {
  700. if (this.firstChild)
  701. this.textContent = "";
  702. }
  703. Element.prototype.isInsertionCaretInside = function()
  704. {
  705. var selection = window.getSelection();
  706. if (!selection.rangeCount || !selection.isCollapsed)
  707. return false;
  708. var selectionRange = selection.getRangeAt(0);
  709. return selectionRange.startContainer.isSelfOrDescendant(this);
  710. }
  711. Element.prototype.createChild = function(elementName, className)
  712. {
  713. var element = this.ownerDocument.createElement(elementName);
  714. if (className)
  715. element.className = className;
  716. this.appendChild(element);
  717. return element;
  718. }
  719. DocumentFragment.prototype.createChild = Element.prototype.createChild;
  720. Element.prototype.totalOffsetLeft = function()
  721. {
  722. return this.totalOffset().left;
  723. }
  724. Element.prototype.totalOffsetTop = function()
  725. {
  726. return this.totalOffset().top;
  727. }
  728. Element.prototype.totalOffset = function()
  729. {
  730. var totalLeft = 0;
  731. var totalTop = 0;
  732. for (var element = this; element; element = element.offsetParent) {
  733. totalLeft += element.offsetLeft;
  734. totalTop += element.offsetTop;
  735. if (this !== element) {
  736. totalLeft += element.clientLeft - element.scrollLeft;
  737. totalTop += element.clientTop - element.scrollTop;
  738. }
  739. }
  740. return { left: totalLeft, top: totalTop };
  741. }
  742. Element.prototype.scrollOffset = function()
  743. {
  744. var curLeft = 0;
  745. var curTop = 0;
  746. for (var element = this; element; element = element.scrollParent) {
  747. curLeft += element.scrollLeft;
  748. curTop += element.scrollTop;
  749. }
  750. return { left: curLeft, top: curTop };
  751. }
  752. function AnchorBox(x, y, width, height)
  753. {
  754. this.x = x || 0;
  755. this.y = y || 0;
  756. this.width = width || 0;
  757. this.height = height || 0;
  758. }
  759. Element.prototype.offsetRelativeToWindow = function(targetWindow)
  760. {
  761. var elementOffset = new AnchorBox();
  762. var curElement = this;
  763. var curWindow = this.ownerDocument.defaultView;
  764. while (curWindow && curElement) {
  765. elementOffset.x += curElement.totalOffsetLeft();
  766. elementOffset.y += curElement.totalOffsetTop();
  767. if (curWindow === targetWindow)
  768. break;
  769. curElement = curWindow.frameElement;
  770. curWindow = curWindow.parent;
  771. }
  772. return elementOffset;
  773. }
  774. Element.prototype.boxInWindow = function(targetWindow)
  775. {
  776. targetWindow = targetWindow || this.ownerDocument.defaultView;
  777. var anchorBox = this.offsetRelativeToWindow(window);
  778. anchorBox.width = Math.min(this.offsetWidth, window.innerWidth - anchorBox.x);
  779. anchorBox.height = Math.min(this.offsetHeight, window.innerHeight - anchorBox.y);
  780. return anchorBox;
  781. }
  782. Element.prototype.setTextAndTitle = function(text)
  783. {
  784. this.textContent = text;
  785. this.title = text;
  786. }
  787. KeyboardEvent.prototype.__defineGetter__("data", function()
  788. {
  789. switch (this.type) {
  790. case "keypress":
  791. if (!this.ctrlKey && !this.metaKey)
  792. return String.fromCharCode(this.charCode);
  793. else
  794. return "";
  795. case "keydown":
  796. case "keyup":
  797. if (!this.ctrlKey && !this.metaKey && !this.altKey)
  798. return String.fromCharCode(this.which);
  799. else
  800. return "";
  801. }
  802. });
  803. Event.prototype.consume = function(preventDefault)
  804. {
  805. this.stopImmediatePropagation();
  806. if (preventDefault)
  807. this.preventDefault();
  808. this.handled = true;
  809. }
  810. Text.prototype.select = function(start, end)
  811. {
  812. start = start || 0;
  813. end = end || this.textContent.length;
  814. if (start < 0)
  815. start = end + start;
  816. var selection = this.ownerDocument.defaultView.getSelection();
  817. selection.removeAllRanges();
  818. var range = this.ownerDocument.createRange();
  819. range.setStart(this, start);
  820. range.setEnd(this, end);
  821. selection.addRange(range);
  822. return this;
  823. }
  824. Element.prototype.selectionLeftOffset = function()
  825. {
  826. var selection = window.getSelection();
  827. if (!selection.containsNode(this, true))
  828. return null;
  829. var leftOffset = selection.anchorOffset;
  830. var node = selection.anchorNode;
  831. while (node !== this) {
  832. while (node.previousSibling) {
  833. node = node.previousSibling;
  834. leftOffset += node.textContent.length;
  835. }
  836. node = node.parentNode;
  837. }
  838. return leftOffset;
  839. }
  840. Node.prototype.isAncestor = function(node)
  841. {
  842. if (!node)
  843. return false;
  844. var currentNode = node.parentNode;
  845. while (currentNode) {
  846. if (this === currentNode)
  847. return true;
  848. currentNode = currentNode.parentNode;
  849. }
  850. return false;
  851. }
  852. Node.prototype.isDescendant = function(descendant)
  853. {
  854. return !!descendant && descendant.isAncestor(this);
  855. }
  856. Node.prototype.isSelfOrAncestor = function(node)
  857. {
  858. return !!node && (node === this || this.isAncestor(node));
  859. }
  860. Node.prototype.isSelfOrDescendant = function(node)
  861. {
  862. return !!node && (node === this || this.isDescendant(node));
  863. }
  864. Node.prototype.traverseNextNode = function(stayWithin)
  865. {
  866. var node = this.firstChild;
  867. if (node)
  868. return node;
  869. if (stayWithin && this === stayWithin)
  870. return null;
  871. node = this.nextSibling;
  872. if (node)
  873. return node;
  874. node = this;
  875. while (node && !node.nextSibling && (!stayWithin || !node.parentNode || node.parentNode !== stayWithin))
  876. node = node.parentNode;
  877. if (!node)
  878. return null;
  879. return node.nextSibling;
  880. }
  881. Node.prototype.traversePreviousNode = function(stayWithin)
  882. {
  883. if (stayWithin && this === stayWithin)
  884. return null;
  885. var node = this.previousSibling;
  886. while (node && node.lastChild)
  887. node = node.lastChild;
  888. if (node)
  889. return node;
  890. return this.parentNode;
  891. }
  892. HTMLTextAreaElement.prototype.moveCursorToEnd = function()
  893. {
  894. var length = this.value.length;
  895. this.setSelectionRange(length, length);
  896. }
  897. function isEnterKey(event) {
  898. return event.keyCode !== 229 && event.keyIdentifier === "Enter";
  899. }
  900. function consumeEvent(e)
  901. {
  902. e.consume();
  903. }
  904. function TreeOutline(listNode, nonFocusable)
  905. {
  906. this.children = [];
  907. this.selectedTreeElement = null;
  908. this._childrenListNode = listNode;
  909. this.childrenListElement = this._childrenListNode;
  910. this._childrenListNode.removeChildren();
  911. this.expandTreeElementsWhenArrowing = false;
  912. this.root = true;
  913. this.hasChildren = false;
  914. this.expanded = true;
  915. this.selected = false;
  916. this.treeOutline = this;
  917. this.comparator = null;
  918. this.searchable = false;
  919. this.searchInputElement = null;
  920. this.setFocusable(!nonFocusable);
  921. this._childrenListNode.addEventListener("keydown", this._treeKeyDown.bind(this), true);
  922. this._childrenListNode.addEventListener("keypress", this._treeKeyPress.bind(this), true);
  923. this._treeElementsMap = new Map();
  924. this._expandedStateMap = new Map();
  925. }
  926. TreeOutline.prototype.setFocusable = function(focusable)
  927. {
  928. if (focusable)
  929. this._childrenListNode.setAttribute("tabIndex", 0);
  930. else
  931. this._childrenListNode.removeAttribute("tabIndex");
  932. }
  933. TreeOutline.prototype.appendChild = function(child)
  934. {
  935. var insertionIndex;
  936. if (this.treeOutline.comparator)
  937. insertionIndex = insertionIndexForObjectInListSortedByFunction(child, this.children, this.treeOutline.comparator);
  938. else
  939. insertionIndex = this.children.length;
  940. this.insertChild(child, insertionIndex);
  941. }
  942. TreeOutline.prototype.insertChild = function(child, index)
  943. {
  944. if (!child)
  945. throw("child can't be undefined or null");
  946. var previousChild = (index > 0 ? this.children[index - 1] : null);
  947. if (previousChild) {
  948. previousChild.nextSibling = child;
  949. child.previousSibling = previousChild;
  950. } else {
  951. child.previousSibling = null;
  952. }
  953. var nextChild = this.children[index];
  954. if (nextChild) {
  955. nextChild.previousSibling = child;
  956. child.nextSibling = nextChild;
  957. } else {
  958. child.nextSibling = null;
  959. }
  960. this.children.splice(index, 0, child);
  961. this.hasChildren = true;
  962. child.parent = this;
  963. child.treeOutline = this.treeOutline;
  964. child.treeOutline._rememberTreeElement(child);
  965. var current = child.children[0];
  966. while (current) {
  967. current.treeOutline = this.treeOutline;
  968. current.treeOutline._rememberTreeElement(current);
  969. current = current.traverseNextTreeElement(false, child, true);
  970. }
  971. if (child.hasChildren && typeof(child.treeOutline._expandedStateMap.get(child.representedObject)) !== "undefined")
  972. child.expanded = child.treeOutline._expandedStateMap.get(child.representedObject);
  973. if (!this._childrenListNode) {
  974. this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
  975. this._childrenListNode.parentTreeElement = this;
  976. this._childrenListNode.classList.add("children");
  977. if (this.hidden)
  978. this._childrenListNode.classList.add("hidden");
  979. }
  980. child._attach();
  981. if (this.treeOutline.onadd)
  982. this.treeOutline.onadd(child);
  983. }
  984. TreeOutline.prototype.removeChildAtIndex = function(childIndex)
  985. {
  986. if (childIndex < 0 || childIndex >= this.children.length)
  987. throw("childIndex out of range");
  988. var child = this.children[childIndex];
  989. this.children.splice(childIndex, 1);
  990. var parent = child.parent;
  991. if (child.deselect()) {
  992. if (child.previousSibling)
  993. child.previousSibling.select();
  994. else if (child.nextSibling)
  995. child.nextSibling.select();
  996. else
  997. parent.select();
  998. }
  999. if (child.previousSibling)
  1000. child.previousSibling.nextSibling = child.nextSibling;
  1001. if (child.nextSibling)
  1002. child.nextSibling.previousSibling = child.previousSibling;
  1003. if (child.treeOutline) {
  1004. child.treeOutline._forgetTreeElement(child);
  1005. child.treeOutline._forgetChildrenRecursive(child);
  1006. }
  1007. child._detach();
  1008. child.treeOutline = null;
  1009. child.parent = null;
  1010. child.nextSibling = null;
  1011. child.previousSibling = null;
  1012. }
  1013. TreeOutline.prototype.removeChild = function(child)
  1014. {
  1015. if (!child)
  1016. throw("child can't be undefined or null");
  1017. var childIndex = this.children.indexOf(child);
  1018. if (childIndex === -1)
  1019. throw("child not found in this node's children");
  1020. this.removeChildAtIndex.call(this, childIndex);
  1021. }
  1022. TreeOutline.prototype.removeChildren = function()
  1023. {
  1024. for (var i = 0; i < this.children.length; ++i) {
  1025. var child = this.children[i];
  1026. child.deselect();
  1027. if (child.treeOutline) {
  1028. child.treeOutline._forgetTreeElement(child);
  1029. child.treeOutline._forgetChildrenRecursive(child);
  1030. }
  1031. child._detach();
  1032. child.treeOutline = null;
  1033. child.parent = null;
  1034. child.nextSibling = null;
  1035. child.previousSibling = null;
  1036. }
  1037. this.children = [];
  1038. }
  1039. TreeOutline.prototype._rememberTreeElement = function(element)
  1040. {
  1041. if (!this._treeElementsMap.get(element.representedObject))
  1042. this._treeElementsMap.put(element.representedObject, []);
  1043. var elements = this._treeElementsMap.get(element.representedObject);
  1044. if (elements.indexOf(element) !== -1)
  1045. return;
  1046. elements.push(element);
  1047. }
  1048. TreeOutline.prototype._forgetTreeElement = function(element)
  1049. {
  1050. if (this._treeElementsMap.get(element.representedObject))
  1051. this._treeElementsMap.get(element.representedObject).remove(element, true);
  1052. }
  1053. TreeOutline.prototype._forgetChildrenRecursive = function(parentElement)
  1054. {
  1055. var child = parentElement.children[0];
  1056. while (child) {
  1057. this._forgetTreeElement(child);
  1058. child = child.traverseNextTreeElement(false, parentElement, true);
  1059. }
  1060. }
  1061. TreeOutline.prototype.getCachedTreeElement = function(representedObject)
  1062. {
  1063. if (!representedObject)
  1064. return null;
  1065. var elements = this._treeElementsMap.get(representedObject);
  1066. if (elements && elements.length)
  1067. return elements[0];
  1068. return null;
  1069. }
  1070. TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent)
  1071. {
  1072. if (!representedObject)
  1073. return null;
  1074. var cachedElement = this.getCachedTreeElement(representedObject);
  1075. if (cachedElement)
  1076. return cachedElement;
  1077. var item;
  1078. var found = false;
  1079. for (var i = 0; i < this.children.length; ++i) {
  1080. item = this.children[i];
  1081. if (item.representedObject === representedObject || isAncestor(item.representedObject, representedObject)) {
  1082. found = true;
  1083. break;
  1084. }
  1085. }
  1086. if (!found)
  1087. return null;
  1088. var ancestors = [];
  1089. var currentObject = representedObject;
  1090. while (currentObject) {
  1091. ancestors.unshift(currentObject);
  1092. if (currentObject === item.representedObject)
  1093. break;
  1094. currentObject = getParent(currentObject);
  1095. }
  1096. for (var i = 0; i < ancestors.length; ++i) {
  1097. if (ancestors[i] === representedObject)
  1098. continue;
  1099. item = this.findTreeElement(ancestors[i], isAncestor, getParent);
  1100. if (item)
  1101. item.onpopulate();
  1102. }
  1103. return this.getCachedTreeElement(representedObject);
  1104. }
  1105. TreeOutline.prototype._treeElementDidChange = function(treeElement)
  1106. {
  1107. if (treeElement.treeOutline !== this)
  1108. return;
  1109. if (this.onchange)
  1110. this.onchange(treeElement);
  1111. }
  1112. TreeOutline.prototype.treeElementFromPoint = function(x, y)
  1113. {
  1114. var node = this._childrenListNode.ownerDocument.elementFromPoint(x, y);
  1115. if (!node)
  1116. return null;
  1117. var listNode = node.enclosingNodeOrSelfWithNodeNameInArray(["ol", "li"]);
  1118. if (listNode)
  1119. return listNode.parentTreeElement || listNode.treeElement;
  1120. return null;
  1121. }
  1122. TreeOutline.prototype._treeKeyPress = function(event)
  1123. {
  1124. if (!this.searchable || WebInspector.isBeingEdited(this._childrenListNode))
  1125. return;
  1126. var searchText = String.fromCharCode(event.charCode);
  1127. if (searchText.trim() !== searchText)
  1128. return;
  1129. this._startSearch(searchText);
  1130. event.consume(true);
  1131. }
  1132. TreeOutline.prototype._treeKeyDown = function(event)
  1133. {
  1134. if (event.target !== this._childrenListNode)
  1135. return;
  1136. if (!this.selectedTreeElement || event.shiftKey || event.metaKey || event.ctrlKey)
  1137. return;
  1138. var handled = false;
  1139. var nextSelectedElement;
  1140. if (event.keyIdentifier === "Up" && !event.altKey) {
  1141. nextSelectedElement = this.selectedTreeElement.traversePreviousTreeElement(true);
  1142. while (nextSelectedElement && !nextSelectedElement.selectable)
  1143. nextSelectedElement = nextSelectedElement.traversePreviousTreeElement(!this.expandTreeElementsWhenArrowing);
  1144. handled = nextSelectedElement ? true : false;
  1145. } else if (event.keyIdentifier === "Down" && !event.altKey) {
  1146. nextSelectedElement = this.selectedTreeElement.traverseNextTreeElement(true);
  1147. while (nextSelectedElement && !nextSelectedElement.selectable)
  1148. nextSelectedElement = nextSelectedElement.traverseNextTreeElement(!this.expandTreeElementsWhenArrowing);
  1149. handled = nextSelectedElement ? true : false;
  1150. } else if (event.keyIdentifier === "Left") {
  1151. if (this.selectedTreeElement.expanded) {
  1152. if (event.altKey)
  1153. this.selectedTreeElement.collapseRecursively();
  1154. else
  1155. this.selectedTreeElement.collapse();
  1156. handled = true;
  1157. } else if (this.selectedTreeElement.parent && !this.selectedTreeElement.parent.root) {
  1158. handled = true;
  1159. if (this.selectedTreeElement.parent.selectable) {
  1160. nextSelectedElement = this.selectedTreeElement.parent;
  1161. while (nextSelectedElement && !nextSelectedElement.selectable)
  1162. nextSelectedElement = nextSelectedElement.parent;
  1163. handled = nextSelectedElement ? true : false;
  1164. } else if (this.selectedTreeElement.parent)
  1165. this.selectedTreeElement.parent.collapse();
  1166. }
  1167. } else if (event.keyIdentifier === "Right") {
  1168. if (!this.selectedTreeElement.revealed()) {
  1169. this.selectedTreeElement.reveal();
  1170. handled = true;
  1171. } else if (this.selectedTreeElement.hasChildren) {
  1172. handled = true;
  1173. if (this.selectedTreeElement.expanded) {
  1174. nextSelectedElement = this.selectedTreeElement.children[0];
  1175. while (nextSelectedElement && !nextSelectedElement.selectable)
  1176. nextSelectedElement = nextSelectedElement.nextSibling;
  1177. handled = nextSelectedElement ? true : false;
  1178. } else {
  1179. if (event.altKey)
  1180. this.selectedTreeElement.expandRecursively();
  1181. else
  1182. this.selectedTreeElement.expand();
  1183. }
  1184. }
  1185. } else if (event.keyCode === 8 || event.keyCode === 46 ) {
  1186. if (this.selectedTreeElement.ondelete)
  1187. handled = this.selectedTreeElement.ondelete();
  1188. } else if (isEnterKey(event)) {
  1189. if (this.selectedTreeElement.onenter)
  1190. handled = this.selectedTreeElement.onenter();
  1191. } else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Space.code) {
  1192. if (this.selectedTreeElement.onspace)
  1193. handled = this.selectedTreeElement.onspace();
  1194. }
  1195. if (nextSelectedElement) {
  1196. nextSelectedElement.reveal();
  1197. nextSelectedElement.select(false, true);
  1198. }
  1199. if (handled)
  1200. event.consume(true);
  1201. }
  1202. TreeOutline.prototype.expand = function()
  1203. {
  1204. }
  1205. TreeOutline.prototype.collapse = function()
  1206. {
  1207. }
  1208. TreeOutline.prototype.revealed = function()
  1209. {
  1210. return true;
  1211. }
  1212. TreeOutline.prototype.reveal = function()
  1213. {
  1214. }
  1215. TreeOutline.prototype.select = function()
  1216. {
  1217. }
  1218. TreeOutline.prototype.revealAndSelect = function(omitFocus)
  1219. {
  1220. }
  1221. TreeOutline.prototype._startSearch = function(searchText)
  1222. {
  1223. if (!this.searchInputElement || !this.searchable)
  1224. return;
  1225. this._searching = true;
  1226. if (this.searchStarted)
  1227. this.searchStarted();
  1228. this.searchInputElement.value = searchText;
  1229. function focusSearchInput()
  1230. {
  1231. this.searchInputElement.focus();
  1232. }
  1233. window.setTimeout(focusSearchInput.bind(this), 0);
  1234. this._searchTextChanged();
  1235. this._boundSearchTextChanged = this._searchTextChanged.bind(this);
  1236. this.searchInputElement.addEventListener("paste", this._boundSearchTextChanged);
  1237. this.searchInputElement.addEventListener("cut", this._boundSearchTextChanged);
  1238. this.searchInputElement.addEventListener("keypress", this._boundSearchTextChanged);
  1239. this._boundSearchInputKeyDown = this._searchInputKeyDown.bind(this);
  1240. this.searchInputElement.addEventListener("keydown", this._boundSearchInputKeyDown);
  1241. this._boundSearchInputBlur = this._searchInputBlur.bind(this);
  1242. this.searchInputElement.addEventListener("blur", this._boundSearchInputBlur);
  1243. }
  1244. TreeOutline.prototype._searchTextChanged = function()
  1245. {
  1246. function updateSearch()
  1247. {
  1248. var nextSelectedElement = this._nextSearchMatch(this.searchInputElement.value, this.selectedTreeElement, false);
  1249. if (!nextSelectedElement)
  1250. nextSelectedElement = this._nextSearchMatch(this.searchInputElement.value, this.children[0], false);
  1251. this._showSearchMatchElement(nextSelectedElement);
  1252. }
  1253. window.setTimeout(updateSearch.bind(this), 0);
  1254. }
  1255. TreeOutline.prototype._showSearchMatchElement = function(treeElement)
  1256. {
  1257. this._currentSearchMatchElement = treeElement;
  1258. if (treeElement) {
  1259. this._childrenListNode.classList.add("search-match-found");
  1260. this._childrenListNode.classList.remove("search-match-not-found");
  1261. treeElement.revealAndSelect(true);
  1262. } else {
  1263. this._childrenListNode.classList.remove("search-match-found");
  1264. this._childrenListNode.classList.add("search-match-not-found");
  1265. }
  1266. }
  1267. TreeOutline.prototype._searchInputKeyDown = function(event)
  1268. {
  1269. if (event.shiftKey || event.metaKey || event.ctrlKey || event.altKey)
  1270. return;
  1271. var handled = false;
  1272. var nextSelectedElement;
  1273. if (event.keyIdentifier === "Down") {
  1274. nextSelectedElement = this._nextSearchMatch(this.searchInputElement.value, this.selectedTreeElement, true);
  1275. handled = true;
  1276. } else if (event.keyIdentifier === "Up") {
  1277. nextSelectedElement = this._previousSearchMatch(this.searchInputElement.value, this.selectedTreeElement);
  1278. handled = true;
  1279. } else if (event.keyCode === 27 ) {
  1280. this._searchFinished();
  1281. handled = true;
  1282. } else if (isEnterKey(event)) {
  1283. var lastSearchMatchElement = this._currentSearchMatchElement;
  1284. this._searchFinished();
  1285. if (lastSearchMatchElement && lastSearchMatchElement.onenter)
  1286. lastSearchMatchElement.onenter();
  1287. handled = true;
  1288. }
  1289. if (nextSelectedElement)
  1290. this._showSearchMatchElement(nextSelectedElement);
  1291. if (handled)
  1292. event.consume(true);
  1293. else
  1294. window.setTimeout(this._boundSearchTextChanged, 0);
  1295. }
  1296. TreeOutline.prototype._nextSearchMatch = function(searchText, startTreeElement, skipStartTreeElement)
  1297. {
  1298. var currentTreeElement = startTreeElement;
  1299. var skipCurrentTreeElement = skipStartTreeElement;
  1300. while (currentTreeElement && (skipCurrentTreeElement || !currentTreeElement.matchesSearchText || !currentTreeElement.matchesSearchText(searchText))) {
  1301. currentTreeElement = currentTreeElement.traverseNextTreeElement(true, null, true);
  1302. skipCurrentTreeElement = false;
  1303. }
  1304. return currentTreeElement;
  1305. }
  1306. TreeOutline.prototype._previousSearchMatch = function(searchText, startTreeElement)
  1307. {
  1308. var currentTreeElement = startTreeElement;
  1309. var skipCurrentTreeElement = true;
  1310. while (currentTreeElement && (skipCurrentTreeElement || !currentTreeElement.matchesSearchText || !currentTreeElement.matchesSearchText(searchText))) {
  1311. currentTreeElement = currentTreeElement.traversePreviousTreeElement(true, true);
  1312. skipCurrentTreeElement = false;
  1313. }
  1314. return currentTreeElement;
  1315. }
  1316. TreeOutline.prototype._searchInputBlur = function(event)
  1317. {
  1318. this._searchFinished();
  1319. }
  1320. TreeOutline.prototype._searchFinished = function()
  1321. {
  1322. if (!this._searching)
  1323. return;
  1324. delete this._searching;
  1325. this._childrenListNode.classList.remove("search-match-found");
  1326. this._childrenListNode.classList.remove("search-match-not-found");
  1327. delete this._currentSearchMatchElement;
  1328. this.searchInputElement.value = "";
  1329. this.searchInputElement.removeEventListener("paste", this._boundSearchTextChanged);
  1330. this.searchInputElement.removeEventListener("cut", this._boundSearchTextChanged);
  1331. delete this._boundSearchTextChanged;
  1332. this.searchInputElement.removeEventListener("keydown", this._boundSearchInputKeyDown);
  1333. delete this._boundSearchInputKeyDown;
  1334. this.searchInputElement.removeEventListener("blur", this._boundSearchInputBlur);
  1335. delete this._boundSearchInputBlur;
  1336. if (this.searchFinished)
  1337. this.searchFinished();
  1338. this.treeOutline._childrenListNode.focus();
  1339. }
  1340. TreeOutline.prototype.stopSearch = function()
  1341. {
  1342. this._searchFinished();
  1343. }
  1344. function TreeElement(title, representedObject, hasChildren)
  1345. {
  1346. this._title = title;
  1347. this.representedObject = (representedObject || {});
  1348. this._hidden = false;
  1349. this._selectable = true;
  1350. this.expanded = false;
  1351. this.selected = false;
  1352. this.hasChildren = hasChildren;
  1353. this.children = [];
  1354. this.treeOutline = null;
  1355. this.parent = null;
  1356. this.previousSibling = null;
  1357. this.nextSibling = null;
  1358. this._listItemNode = null;
  1359. }
  1360. TreeElement.prototype = {
  1361. arrowToggleWidth: 10,
  1362. get selectable() {
  1363. if (this._hidden)
  1364. return false;
  1365. return this._selectable;
  1366. },
  1367. set selectable(x) {
  1368. this._selectable = x;
  1369. },
  1370. get listItemElement() {
  1371. return this._listItemNode;
  1372. },
  1373. get childrenListElement() {
  1374. return this._childrenListNode;
  1375. },
  1376. get title() {
  1377. return this._title;
  1378. },
  1379. set title(x) {
  1380. this._title = x;
  1381. this._setListItemNodeContent();
  1382. this.didChange();
  1383. },
  1384. get tooltip() {
  1385. return this._tooltip;
  1386. },
  1387. set tooltip(x) {
  1388. this._tooltip = x;
  1389. if (this._listItemNode)
  1390. this._listItemNode.title = x ? x : "";
  1391. this.didChange();
  1392. },
  1393. get hasChildren() {
  1394. return this._hasChildren;
  1395. },
  1396. set hasChildren(x) {
  1397. if (this._hasChildren === x)
  1398. return;
  1399. this._hasChildren = x;
  1400. if (!this._listItemNode)
  1401. return;
  1402. if (x)
  1403. this._listItemNode.classList.add("parent");
  1404. else {
  1405. this._listItemNode.classList.remove("parent");
  1406. this.collapse();
  1407. }
  1408. this.didChange();
  1409. },
  1410. get hidden() {
  1411. return this._hidden;
  1412. },
  1413. set hidden(x) {
  1414. if (this._hidden === x)
  1415. return;
  1416. this._hidden = x;
  1417. if (x) {
  1418. if (this._listItemNode)
  1419. this._listItemNode.classList.add("hidden");
  1420. if (this._childrenListNode)
  1421. this._childrenListNode.classList.add("hidden");
  1422. } else {
  1423. if (this._listItemNode)
  1424. this._listItemNode.classList.remove("hidden");
  1425. if (this._childrenListNode)
  1426. this._childrenListNode.classList.remove("hidden");
  1427. }
  1428. },
  1429. get shouldRefreshChildren() {
  1430. return this._shouldRefreshChildren;
  1431. },
  1432. set shouldRefreshChildren(x) {
  1433. this._shouldRefreshChildren = x;
  1434. if (x && this.expanded)
  1435. this.expand();
  1436. },
  1437. _fireDidChange: function()
  1438. {
  1439. delete this._didChangeTimeoutIdentifier;
  1440. if (this.treeOutline)
  1441. this.treeOutline._treeElementDidChange(this);
  1442. },
  1443. didChange: function()
  1444. {
  1445. if (!this.treeOutline)
  1446. return;
  1447. if (!this._didChangeTimeoutIdentifier)
  1448. this._didChangeTimeoutIdentifier = setTimeout(this._fireDidChange.bind(this), 0);
  1449. },
  1450. _setListItemNodeContent: function()
  1451. {
  1452. if (!this._listItemNode)
  1453. return;
  1454. if (typeof this._title === "string")
  1455. this._listItemNode.textContent = this._title;
  1456. else {
  1457. this._listItemNode.removeChildren();
  1458. if (this._title)
  1459. this._listItemNode.appendChild(this._title);
  1460. }
  1461. }
  1462. }
  1463. TreeElement.prototype.appendChild = TreeOutline.prototype.appendChild;
  1464. TreeElement.prototype.insertChild = TreeOutline.prototype.insertChild;
  1465. TreeElement.prototype.removeChild = TreeOutline.prototype.removeChild;
  1466. TreeElement.prototype.removeChildAtIndex = TreeOutline.prototype.removeChildAtIndex;
  1467. TreeElement.prototype.removeChildren = TreeOutline.prototype.removeChildren;
  1468. TreeElement.prototype._attach = function()
  1469. {
  1470. if (!this._listItemNode || this.parent._shouldRefreshChildren) {
  1471. if (this._listItemNode && this._listItemNode.parentNode)
  1472. this._listItemNode.parentNode.removeChild(this._listItemNode);
  1473. this._listItemNode = this.treeOutline._childrenListNode.ownerDocument.createElement("li");
  1474. this._listItemNode.treeElement = this;
  1475. this._setListItemNodeContent();
  1476. this._listItemNode.title = this._tooltip ? this._tooltip : "";
  1477. if (this.hidden)
  1478. this._listItemNode.classList.add("hidden");
  1479. if (this.hasChildren)
  1480. this._listItemNode.classList.add("parent");
  1481. if (this.expanded)
  1482. this._listItemNode.classList.add("expanded");
  1483. if (this.selected)
  1484. this._listItemNode.classList.add("selected");
  1485. this._listItemNode.addEventListener("mousedown", TreeElement.treeElementMouseDown, false);
  1486. this._listItemNode.addEventListener("click", TreeElement.treeElementToggled, false);
  1487. this._listItemNode.addEventListener("dblclick", TreeElement.treeElementDoubleClicked, false);
  1488. if (this.onattach)
  1489. this.onattach(this);
  1490. }
  1491. var nextSibling = null;
  1492. if (this.nextSibling && this.nextSibling._listItemNode && this.nextSibling._listItemNode.parentNode === this.parent._childrenListNode)
  1493. nextSibling = this.nextSibling._listItemNode;
  1494. this.parent._childrenListNode.insertBefore(this._listItemNode, nextSibling);
  1495. if (this._childrenListNode)
  1496. this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
  1497. if (this.selected)
  1498. this.select();
  1499. if (this.expanded)
  1500. this.expand();
  1501. }
  1502. TreeElement.prototype._detach = function()
  1503. {
  1504. if (this._listItemNode && this._listItemNode.parentNode)
  1505. this._listItemNode.parentNode.removeChild(this._listItemNode);
  1506. if (this._childrenListNode && this._childrenListNode.parentNode)
  1507. this._childrenListNode.parentNode.removeChild(this._childrenListNode);
  1508. }
  1509. TreeElement.treeElementMouseDown = function(event)
  1510. {
  1511. var element = event.currentTarget;
  1512. if (!element || !element.treeElement || !element.treeElement.selectable)
  1513. return;
  1514. if (element.treeElement.isEventWithinDisclosureTriangle(event))
  1515. return;
  1516. element.treeElement.selectOnMouseDown(event);
  1517. }
  1518. TreeElement.treeElementToggled = function(event)
  1519. {
  1520. var element = event.currentTarget;
  1521. if (!element || !element.treeElement)
  1522. return;
  1523. var toggleOnClick = element.treeElement.toggleOnClick && !element.treeElement.selectable;
  1524. var isInTriangle = element.treeElement.isEventWithinDisclosureTriangle(event);
  1525. if (!toggleOnClick && !isInTriangle)
  1526. return;
  1527. if (element.treeElement.expanded) {
  1528. if (event.altKey)
  1529. element.treeElement.collapseRecursively();
  1530. else
  1531. element.treeElement.collapse();
  1532. } else {
  1533. if (event.altKey)
  1534. element.treeElement.expandRecursively();
  1535. else
  1536. element.treeElement.expand();
  1537. }
  1538. event.consume();
  1539. }
  1540. TreeElement.treeElementDoubleClicked = function(event)
  1541. {
  1542. var element = event.currentTarget;
  1543. if (!element || !element.treeElement)
  1544. return;
  1545. if (element.treeElement.ondblclick) {
  1546. var handled = element.treeElement.ondblclick.call(element.treeElement, event);
  1547. if (handled)
  1548. return;
  1549. } else if (element.treeElement.hasChildren && !element.treeElement.expanded)
  1550. element.treeElement.expand();
  1551. }
  1552. TreeElement.prototype.collapse = function()
  1553. {
  1554. if (this._listItemNode)
  1555. this._listItemNode.classList.remove("expanded");
  1556. if (this._childrenListNode)
  1557. this._childrenListNode.classList.remove("expanded");
  1558. this.expanded = false;
  1559. if (this.treeOutline)
  1560. this.treeOutline._expandedStateMap.put(this.representedObject, false);
  1561. if (this.oncollapse)
  1562. this.oncollapse(this);
  1563. }
  1564. TreeElement.prototype.collapseRecursively = function()
  1565. {
  1566. var item = this;
  1567. while (item) {
  1568. if (item.expanded)
  1569. item.collapse();
  1570. item = item.traverseNextTreeElement(false, this, true);
  1571. }
  1572. }
  1573. TreeElement.prototype.expand = function()
  1574. {
  1575. if (!this.hasChildren || (this.expanded && !this._shouldRefreshChildren && this._childrenListNode))
  1576. return;
  1577. this.expanded = true;
  1578. if (this.treeOutline)
  1579. this.treeOutline._expandedStateMap.put(this.representedObject, true);
  1580. if (this.treeOutline && (!this._childrenListNode || this._shouldRefreshChildren)) {
  1581. if (this._childrenListNode && this._childrenListNode.parentNode)
  1582. this._childrenListNode.parentNode.removeChild(this._childrenListNode);
  1583. this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
  1584. this._childrenListNode.parentTreeElement = this;
  1585. this._childrenListNode.classList.add("children");
  1586. if (this.hidden)
  1587. this._childrenListNode.classList.add("hidden");
  1588. this.onpopulate();
  1589. for (var i = 0; i < this.children.length; ++i)
  1590. this.children[i]._attach();
  1591. delete this._shouldRefreshChildren;
  1592. }
  1593. if (this._listItemNode) {
  1594. this._listItemNode.classList.add("expanded");
  1595. if (this._childrenListNode && this._childrenListNode.parentNode != this._listItemNode.parentNode)
  1596. this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
  1597. }
  1598. if (this._childrenListNode)
  1599. this._childrenListNode.classList.add("expanded");
  1600. if (this.onexpand)
  1601. this.onexpand(this);
  1602. }
  1603. TreeElement.prototype.expandRecursively = function(maxDepth)
  1604. {
  1605. var item = this;
  1606. var info = {};
  1607. var depth = 0;
  1608. if (typeof maxDepth === "undefined" || typeof maxDepth === "null")
  1609. maxDepth = 3;
  1610. while (item) {
  1611. if (depth < maxDepth)
  1612. item.expand();
  1613. item = item.traverseNextTreeElement(false, this, (depth >= maxDepth), info);
  1614. depth += info.depthChange;
  1615. }
  1616. }
  1617. TreeElement.prototype.hasAncestor = function(ancestor) {
  1618. if (!ancestor)
  1619. return false;
  1620. var currentNode = this.parent;
  1621. while (currentNode) {
  1622. if (ancestor === currentNode)
  1623. return true;
  1624. currentNode = currentNode.parent;
  1625. }
  1626. return false;
  1627. }
  1628. TreeElement.prototype.reveal = function()
  1629. {
  1630. var currentAncestor = this.parent;
  1631. while (currentAncestor && !currentAncestor.root) {
  1632. if (!currentAncestor.expanded)
  1633. currentAncestor.expand();
  1634. currentAncestor = currentAncestor.parent;
  1635. }
  1636. if (this.onreveal)
  1637. this.onreveal(this);
  1638. }
  1639. TreeElement.prototype.revealed = function()
  1640. {
  1641. var currentAncestor = this.parent;
  1642. while (currentAncestor && !currentAncestor.root) {
  1643. if (!currentAncestor.expanded)
  1644. return false;
  1645. currentAncestor = currentAncestor.parent;
  1646. }
  1647. return true;
  1648. }
  1649. TreeElement.prototype.selectOnMouseDown = function(event)
  1650. {
  1651. if (this.select(false, true))
  1652. event.consume(true);
  1653. }
  1654. TreeElement.prototype.select = function(omitFocus, selectedByUser)
  1655. {
  1656. if (!this.treeOutline || !this.selectable || this.selected)
  1657. return false;
  1658. if (this.treeOutline.selectedTreeElement)
  1659. this.treeOutline.selectedTreeElement.deselect();
  1660. this.selected = true;
  1661. if(!omitFocus)
  1662. this.treeOutline._childrenListNode.focus();
  1663. if (!this.treeOutline)
  1664. return false;
  1665. this.treeOutline.selectedTreeElement = this;
  1666. if (this._listItemNode)
  1667. this._listItemNode.classList.add("selected");
  1668. if (this.onselect)
  1669. return this.onselect(this, selectedByUser);
  1670. return false;
  1671. }
  1672. TreeElement.prototype.revealAndSelect = function(omitFocus)
  1673. {
  1674. this.reveal();
  1675. this.select(omitFocus);
  1676. }
  1677. TreeElement.prototype.deselect = function(supressOnDeselect)
  1678. {
  1679. if (!this.treeOutline || this.treeOutline.selectedTreeElement !== this || !this.selected)
  1680. return false;
  1681. this.selected = false;
  1682. this.treeOutline.selectedTreeElement = null;
  1683. if (this._listItemNode)
  1684. this._listItemNode.classList.remove("selected");
  1685. if (this.ondeselect && !supressOnDeselect)
  1686. this.ondeselect(this);
  1687. return true;
  1688. }
  1689. TreeElement.prototype.onpopulate = function()
  1690. {
  1691. }
  1692. TreeElement.prototype.traverseNextTreeElement = function(skipUnrevealed, stayWithin, dontPopulate, info)
  1693. {
  1694. if (!dontPopulate && this.hasChildren)
  1695. this.onpopulate();
  1696. if (info)
  1697. info.depthChange = 0;
  1698. var element = skipUnrevealed ? (this.revealed() ? this.children[0] : null) : this.children[0];
  1699. if (element && (!skipUnrevealed || (skipUnrevealed && this.expanded))) {
  1700. if (info)
  1701. info.depthChange = 1;
  1702. return element;
  1703. }
  1704. if (this === stayWithin)
  1705. return null;
  1706. element = skipUnrevealed ? (this.revealed() ? this.nextSibling : null) : this.nextSibling;
  1707. if (element)
  1708. return element;
  1709. element = this;
  1710. while (element && !element.root && !(skipUnrevealed ? (element.revealed() ? element.nextSibling : null) : element.nextSibling) && element.parent !== stayWithin) {
  1711. if (info)
  1712. info.depthChange -= 1;
  1713. element = element.parent;
  1714. }
  1715. if (!element)
  1716. return null;
  1717. return (skipUnrevealed ? (element.revealed() ? element.nextSibling : null) : element.nextSibling);
  1718. }
  1719. TreeElement.prototype.traversePreviousTreeElement = function(skipUnrevealed, dontPopulate)
  1720. {
  1721. var element = skipUnrevealed ? (this.revealed() ? this.previousSibling : null) : this.previousSibling;
  1722. if (!dontPopulate && element && element.hasChildren)
  1723. element.onpopulate();
  1724. while (element && (skipUnrevealed ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1])) {
  1725. if (!dontPopulate && element.hasChildren)
  1726. element.onpopulate();
  1727. element = (skipUnrevealed ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.childre

Large files files are truncated, but you can click here to view the full file