a zip code crypto-currency system good for red ONLY

virtual-util.js 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. (function (factory) {
  2. if (typeof module === "object" && typeof module.exports === "object") {
  3. var v = factory(require, exports);
  4. if (v !== undefined) module.exports = v;
  5. }
  6. else if (typeof define === "function" && define.amd) {
  7. define(["require", "exports"], factory);
  8. }
  9. })(function (require, exports) {
  10. "use strict";
  11. Object.defineProperty(exports, "__esModule", { value: true });
  12. var PREVIOUS_CELL = {
  13. row: 0,
  14. width: 0,
  15. height: 0,
  16. top: 0,
  17. left: 0,
  18. tmpl: -1
  19. };
  20. /**
  21. * NO DOM
  22. */
  23. function processRecords(stopAtHeight, records, cells, headerFn, footerFn, data) {
  24. var record;
  25. var startRecordIndex;
  26. var previousCell;
  27. var tmpData;
  28. var lastRecordIndex = records ? (records.length - 1) : -1;
  29. if (cells.length) {
  30. // we already have cells
  31. previousCell = cells[cells.length - 1];
  32. if (previousCell.top + previousCell.height > stopAtHeight) {
  33. return;
  34. }
  35. startRecordIndex = (previousCell.record + 1);
  36. }
  37. else {
  38. // no cells have been created yet
  39. previousCell = PREVIOUS_CELL;
  40. startRecordIndex = 0;
  41. }
  42. var processedTotal = 0;
  43. for (var recordIndex = startRecordIndex; recordIndex <= lastRecordIndex; recordIndex++) {
  44. record = records[recordIndex];
  45. if (headerFn) {
  46. tmpData = headerFn(record, recordIndex, records);
  47. if (tmpData !== null) {
  48. // add header data
  49. previousCell = addCell(previousCell, recordIndex, 1 /* Header */, tmpData, data.hdrWidth, data.hdrHeight, data.viewWidth);
  50. cells.push(previousCell);
  51. }
  52. }
  53. // add item data
  54. previousCell = addCell(previousCell, recordIndex, 0 /* Item */, null, data.itmWidth, data.itmHeight, data.viewWidth);
  55. cells.push(previousCell);
  56. if (footerFn) {
  57. tmpData = footerFn(record, recordIndex, records);
  58. if (tmpData !== null) {
  59. // add footer data
  60. previousCell = addCell(previousCell, recordIndex, 2 /* Footer */, tmpData, data.ftrWidth, data.ftrHeight, data.viewWidth);
  61. cells.push(previousCell);
  62. }
  63. }
  64. if (previousCell.record === lastRecordIndex) {
  65. previousCell.isLast = true;
  66. }
  67. // should always process at least 3 records
  68. processedTotal++;
  69. if (previousCell.top + previousCell.height + data.itmHeight > stopAtHeight && processedTotal > 3) {
  70. return;
  71. }
  72. }
  73. }
  74. exports.processRecords = processRecords;
  75. function addCell(previousCell, recordIndex, tmpl, tmplData, cellWidth, cellHeight, viewportWidth) {
  76. var newCell = {
  77. record: recordIndex,
  78. tmpl: tmpl,
  79. width: cellWidth,
  80. height: cellHeight,
  81. reads: 0
  82. };
  83. if (previousCell.left + previousCell.width + cellWidth > viewportWidth) {
  84. // add a new cell in a new row
  85. newCell.row = (previousCell.row + 1);
  86. newCell.top = (previousCell.top + previousCell.height);
  87. newCell.left = 0;
  88. }
  89. else {
  90. // add a new cell in the same row
  91. newCell.row = previousCell.row;
  92. newCell.top = previousCell.top;
  93. newCell.left = (previousCell.left + previousCell.width);
  94. }
  95. if (tmplData) {
  96. newCell.data = tmplData;
  97. }
  98. return newCell;
  99. }
  100. /**
  101. * NO DOM
  102. */
  103. function populateNodeData(startCellIndex, endCellIndex, scrollingDown, cells, records, nodes, viewContainer, itmTmp, hdrTmp, ftrTmp) {
  104. if (!records || records.length === 0) {
  105. nodes.length = 0;
  106. viewContainer.clear();
  107. return true;
  108. }
  109. var recordsLength = records.length;
  110. var hasChanges = false;
  111. // let node: VirtualNode;
  112. var availableNode;
  113. var cell;
  114. var viewInsertIndex = null;
  115. var totalNodes = nodes.length;
  116. var templateRef;
  117. startCellIndex = Math.max(startCellIndex, 0);
  118. endCellIndex = Math.min(endCellIndex, cells.length - 1);
  119. var usedNodes = [];
  120. for (var cellIndex = startCellIndex; cellIndex <= endCellIndex; cellIndex++) {
  121. cell = cells[cellIndex];
  122. availableNode = null;
  123. // find the first one that's available
  124. var existingNode = nodes.find(function (n) { return n.cell === cellIndex && n.tmpl === cell.tmpl; });
  125. if (existingNode) {
  126. if (existingNode.view.context.$implicit === records[cell.record]) {
  127. usedNodes.push(existingNode);
  128. continue; // optimization: node data is the same no need to update
  129. }
  130. (void 0) /* console.debug */;
  131. availableNode = existingNode; // update existing node
  132. }
  133. else {
  134. (void 0) /* console.debug */;
  135. for (var i = 0; i < totalNodes; i++) {
  136. var node = nodes[i];
  137. if (cell.tmpl !== node.tmpl || i === 0 && cellIndex !== 0) {
  138. // the cell must use the correct template
  139. // first node can only be used by the first cell (css :first-child reasons)
  140. // this node is never available to be reused
  141. continue;
  142. }
  143. if (node.cell < startCellIndex || node.cell > endCellIndex) {
  144. if (!availableNode) {
  145. // havent gotten an available node yet
  146. availableNode = node;
  147. (void 0) /* console.debug */;
  148. }
  149. else if (scrollingDown) {
  150. // scrolling down
  151. if (node.cell < availableNode.cell) {
  152. availableNode = node;
  153. (void 0) /* console.debug */;
  154. }
  155. }
  156. else {
  157. // scrolling up
  158. if (node.cell > availableNode.cell) {
  159. availableNode = node;
  160. (void 0) /* console.debug */;
  161. }
  162. }
  163. }
  164. }
  165. }
  166. if (!availableNode) {
  167. // did not find an available node to put the cell data into
  168. // insert a new node after existing ones
  169. if (viewInsertIndex === null) {
  170. viewInsertIndex = -1;
  171. for (var j = totalNodes - 1; j >= 0; j--) {
  172. var node = nodes[j];
  173. if (node) {
  174. viewInsertIndex = viewContainer.indexOf(node.view);
  175. break;
  176. }
  177. }
  178. }
  179. // select which templateRef should be used for this cell
  180. templateRef = cell.tmpl === 1 /* Header */ ? hdrTmp : cell.tmpl === 2 /* Footer */ ? ftrTmp : itmTmp;
  181. if (!templateRef) {
  182. console.error("virtual" + (cell.tmpl === 1 /* Header */ ? 'Header' : cell.tmpl === 2 /* Footer */ ? 'Footer' : 'Item') + " template required");
  183. continue;
  184. }
  185. availableNode = {
  186. tmpl: cell.tmpl,
  187. view: viewContainer.createEmbeddedView(templateRef, new VirtualContext(null, null, null), viewInsertIndex)
  188. };
  189. totalNodes = nodes.push(availableNode);
  190. }
  191. // assign who's the new cell index for this node
  192. availableNode.cell = cellIndex;
  193. // apply the cell's data to this node
  194. var context = availableNode.view.context;
  195. context.$implicit = cell.data || records[cell.record];
  196. context.index = cellIndex;
  197. context.count = recordsLength;
  198. availableNode.hasChanges = true;
  199. availableNode.lastTransform = null;
  200. hasChanges = true;
  201. usedNodes.push(availableNode);
  202. }
  203. var unusedNodes = nodes.filter(function (n) { return usedNodes.indexOf(n) < 0; });
  204. unusedNodes.forEach(function (node) {
  205. var index = viewContainer.indexOf(node.view);
  206. viewContainer.remove(index);
  207. var removeIndex = nodes.findIndex(function (n) { return n === node; });
  208. nodes.splice(removeIndex, 1);
  209. });
  210. usedNodes.length = 0;
  211. unusedNodes.length = 0;
  212. return hasChanges;
  213. }
  214. exports.populateNodeData = populateNodeData;
  215. /**
  216. * DOM READ
  217. */
  218. function initReadNodes(plt, nodes, cells, data) {
  219. if (nodes.length && cells.length) {
  220. // first node
  221. // ******** DOM READ ****************
  222. var ele = getElement(nodes[0]);
  223. var firstCell = cells[0];
  224. firstCell.top = ele.clientTop;
  225. firstCell.left = ele.clientLeft;
  226. firstCell.row = 0;
  227. // ******** DOM READ ****************
  228. updateDimensions(plt, nodes, cells, data, true);
  229. }
  230. }
  231. exports.initReadNodes = initReadNodes;
  232. /**
  233. * DOM READ
  234. */
  235. function updateDimensions(plt, nodes, cells, data, initialUpdate) {
  236. var node;
  237. var element;
  238. var cell;
  239. var previousCell;
  240. var totalCells = cells.length;
  241. for (var i = 0; i < nodes.length; i++) {
  242. node = nodes[i];
  243. cell = cells[node.cell];
  244. // read element dimensions if they haven't been checked enough times
  245. if (cell && cell.reads < REQUIRED_DOM_READS) {
  246. element = getElement(node);
  247. // ******** DOM READ ****************
  248. readElements(plt, cell, element);
  249. if (initialUpdate) {
  250. // update estimated dimensions with more accurate dimensions
  251. if (cell.tmpl === 1 /* Header */) {
  252. data.hdrHeight = cell.height;
  253. if (cell.left === 0) {
  254. data.hdrWidth = cell.width;
  255. }
  256. }
  257. else if (cell.tmpl === 2 /* Footer */) {
  258. data.ftrHeight = cell.height;
  259. if (cell.left === 0) {
  260. data.ftrWidth = cell.width;
  261. }
  262. }
  263. else {
  264. data.itmHeight = cell.height;
  265. if (cell.left === 0) {
  266. data.itmWidth = cell.width;
  267. }
  268. }
  269. }
  270. cell.reads++;
  271. }
  272. }
  273. // figure out which cells are currently viewable within the viewport
  274. var viewableBottom = (data.scrollTop + data.viewHeight);
  275. data.topViewCell = totalCells;
  276. data.bottomViewCell = 0;
  277. if (totalCells > 0) {
  278. // completely realign position to ensure they're all accurately placed
  279. cell = cells[0];
  280. previousCell = {
  281. row: 0,
  282. width: 0,
  283. height: 0,
  284. top: cell.top,
  285. left: 0,
  286. tmpl: -1
  287. };
  288. for (var i_1 = 0; i_1 < totalCells; i_1++) {
  289. cell = cells[i_1];
  290. if (previousCell.left + previousCell.width + cell.width > data.viewWidth) {
  291. // new row
  292. cell.row++;
  293. cell.top = (previousCell.top + previousCell.height);
  294. cell.left = 0;
  295. }
  296. else {
  297. // same row
  298. cell.row = previousCell.row;
  299. cell.top = previousCell.top;
  300. cell.left = (previousCell.left + previousCell.width);
  301. }
  302. // figure out which cells are viewable within the viewport
  303. if (cell.top + cell.height > data.scrollTop && i_1 < data.topViewCell) {
  304. data.topViewCell = i_1;
  305. }
  306. else if (cell.top < viewableBottom && i_1 > data.bottomViewCell) {
  307. data.bottomViewCell = i_1;
  308. }
  309. previousCell = cell;
  310. }
  311. }
  312. }
  313. exports.updateDimensions = updateDimensions;
  314. function updateNodeContext(nodes, cells, data) {
  315. // ensure each node has the correct bounds in its context
  316. var node;
  317. var cell;
  318. var bounds;
  319. for (var i = 0, ilen = nodes.length; i < ilen; i++) {
  320. node = nodes[i];
  321. cell = cells[node.cell];
  322. if (node && cell) {
  323. bounds = node.view.context.bounds;
  324. bounds.top = cell.top + data.viewTop;
  325. bounds.bottom = bounds.top + cell.height;
  326. bounds.left = cell.left + data.viewLeft;
  327. bounds.right = bounds.left + cell.width;
  328. bounds.width = cell.width;
  329. bounds.height = cell.height;
  330. }
  331. }
  332. }
  333. exports.updateNodeContext = updateNodeContext;
  334. /**
  335. * DOM READ
  336. */
  337. function readElements(plt, cell, element) {
  338. // ******** DOM READ ****************
  339. var styles = plt.getElementComputedStyle(element);
  340. // ******** DOM READ ****************
  341. cell.left = (element.clientLeft - parseFloat(styles.marginLeft));
  342. // ******** DOM READ ****************
  343. cell.width = (element.offsetWidth + parseFloat(styles.marginLeft) + parseFloat(styles.marginRight));
  344. // ******** DOM READ ****************
  345. cell.height = (element.offsetHeight + parseFloat(styles.marginTop) + parseFloat(styles.marginBottom));
  346. }
  347. /**
  348. * DOM WRITE
  349. */
  350. function writeToNodes(plt, nodes, cells, totalRecords) {
  351. var node;
  352. var element;
  353. var cell;
  354. var transform;
  355. var totalCells = Math.max(totalRecords, cells.length);
  356. for (var i = 0, ilen = nodes.length; i < ilen; i++) {
  357. node = nodes[i];
  358. cell = cells[node.cell];
  359. transform = "translate3d(" + cell.left + "px," + cell.top + "px,0px)";
  360. if (node.lastTransform !== transform) {
  361. element = getElement(node);
  362. if (element) {
  363. // ******** DOM WRITE ****************
  364. element.style[plt.Css.transform] = node.lastTransform = transform;
  365. // ******** DOM WRITE ****************
  366. element.classList.add('virtual-position');
  367. // https://www.w3.org/TR/wai-aria/states_and_properties#aria-posinset
  368. // ******** DOM WRITE ****************
  369. element.setAttribute('aria-posinset', node.cell + 1);
  370. // https://www.w3.org/TR/wai-aria/states_and_properties#aria-setsize
  371. // ******** DOM WRITE ****************
  372. element.setAttribute('aria-setsize', totalCells);
  373. }
  374. }
  375. }
  376. }
  377. exports.writeToNodes = writeToNodes;
  378. /**
  379. * NO DOM
  380. */
  381. function adjustRendered(cells, data) {
  382. var maxRenderHeight = (data.renderHeight - data.itmHeight);
  383. var totalCells = cells.length;
  384. var viewableRenderedPadding = (data.itmHeight < 90 ? VIEWABLE_RENDERED_PADDING : 0);
  385. if (data.scrollDiff > 0) {
  386. // scrolling down
  387. data.topCell = Math.max(data.topViewCell - viewableRenderedPadding, 0);
  388. data.bottomCell = data.topCell;
  389. var cellsRenderHeight = 0;
  390. for (var i = data.topCell; i < totalCells; i++) {
  391. cellsRenderHeight += cells[i].height;
  392. if (i > data.bottomCell)
  393. data.bottomCell = i;
  394. if (cellsRenderHeight >= maxRenderHeight)
  395. break;
  396. }
  397. if (cellsRenderHeight < maxRenderHeight) {
  398. // there are no more cells at the bottom, so move topCell to a smaller index
  399. for (var i = data.topCell - 1; i >= 0; i--) {
  400. cellsRenderHeight += cells[i].height;
  401. data.topCell = i;
  402. if (cellsRenderHeight >= maxRenderHeight)
  403. break;
  404. }
  405. }
  406. }
  407. else {
  408. // scroll up
  409. data.bottomCell = Math.min(data.bottomViewCell + viewableRenderedPadding, totalCells - 1);
  410. data.topCell = data.bottomCell;
  411. var cellsRenderHeight = 0;
  412. (void 0) /* assert */;
  413. for (var i = data.bottomCell; i >= 0; i--) {
  414. cellsRenderHeight += cells[i].height;
  415. if (i < data.topCell)
  416. data.topCell = i;
  417. if (cellsRenderHeight >= maxRenderHeight)
  418. break;
  419. }
  420. if (cellsRenderHeight < maxRenderHeight) {
  421. // there are no more cells at the top, so move bottomCell to a higher index
  422. for (var i = data.bottomCell; i < totalCells; i++) {
  423. cellsRenderHeight += cells[i].height;
  424. data.bottomCell = i;
  425. if (cellsRenderHeight >= maxRenderHeight)
  426. break;
  427. }
  428. }
  429. }
  430. }
  431. exports.adjustRendered = adjustRendered;
  432. /**
  433. * NO DOM
  434. */
  435. function getVirtualHeight(totalRecords, lastCell) {
  436. if (lastCell.record >= totalRecords - 1) {
  437. return (lastCell.top + lastCell.height);
  438. }
  439. var unknownRecords = (totalRecords - lastCell.record - 1);
  440. var knownHeight = (lastCell.top + lastCell.height);
  441. return Math.ceil(knownHeight + ((knownHeight / (totalRecords - unknownRecords)) * unknownRecords));
  442. }
  443. exports.getVirtualHeight = getVirtualHeight;
  444. /**
  445. * NO DOM
  446. */
  447. function estimateHeight(totalRecords, lastCell, existingHeight, difference) {
  448. if (!totalRecords || !lastCell) {
  449. return 0;
  450. }
  451. var newHeight = getVirtualHeight(totalRecords, lastCell);
  452. var percentToBottom = (lastCell.record / (totalRecords - 1));
  453. var diff = Math.abs(existingHeight - newHeight);
  454. if ((diff > (newHeight * difference)) ||
  455. (percentToBottom > .995)) {
  456. return newHeight;
  457. }
  458. return existingHeight;
  459. }
  460. exports.estimateHeight = estimateHeight;
  461. /**
  462. * DOM READ
  463. */
  464. function calcDimensions(data, virtualScrollElement, approxItemWidth, approxItemHeight, appoxHeaderWidth, approxHeaderHeight, approxFooterWidth, approxFooterHeight, bufferRatio) {
  465. // get the parent container's viewport bounds
  466. var viewportElement = virtualScrollElement.parentElement;
  467. // ******** DOM READ ****************
  468. data.viewWidth = viewportElement.offsetWidth;
  469. // ******** DOM READ ****************
  470. data.viewHeight = viewportElement.offsetHeight;
  471. // get the virtual scroll element's offset data
  472. // ******** DOM READ ****************
  473. data.viewTop = virtualScrollElement.offsetTop;
  474. // ******** DOM READ ****************
  475. data.viewLeft = virtualScrollElement.offsetLeft;
  476. // the height we'd like to render, which is larger than viewable
  477. data.renderHeight = (data.viewHeight * bufferRatio);
  478. if (data.viewWidth > 0 && data.viewHeight > 0) {
  479. data.itmWidth = calcWidth(data.viewWidth, approxItemWidth);
  480. data.itmHeight = calcHeight(data.viewHeight, approxItemHeight);
  481. data.hdrWidth = calcWidth(data.viewWidth, appoxHeaderWidth);
  482. data.hdrHeight = calcHeight(data.viewHeight, approxHeaderHeight);
  483. data.ftrWidth = calcWidth(data.viewWidth, approxFooterWidth);
  484. data.ftrHeight = calcHeight(data.viewHeight, approxFooterHeight);
  485. data.valid = true;
  486. }
  487. }
  488. exports.calcDimensions = calcDimensions;
  489. /**
  490. * NO DOM
  491. */
  492. function calcWidth(viewportWidth, approxWidth) {
  493. if (approxWidth.indexOf('%') > 0) {
  494. return (viewportWidth * (parseFloat(approxWidth) / 100));
  495. }
  496. else if (approxWidth.indexOf('px') > 0) {
  497. return parseFloat(approxWidth);
  498. }
  499. throw new Error('virtual scroll width can only use "%" or "px" units');
  500. }
  501. /**
  502. * NO DOM
  503. */
  504. function calcHeight(_viewportHeight, approxHeight) {
  505. if (approxHeight.indexOf('px') > 0) {
  506. return parseFloat(approxHeight);
  507. }
  508. throw new Error('virtual scroll height must use "px" units');
  509. }
  510. /**
  511. * NO DOM
  512. */
  513. function getElement(node) {
  514. var rootNodes = node.view.rootNodes;
  515. for (var i = 0; i < rootNodes.length; i++) {
  516. if (rootNodes[i].nodeType === 1) {
  517. return rootNodes[i];
  518. }
  519. }
  520. return null;
  521. }
  522. var VirtualContext = (function () {
  523. function VirtualContext($implicit, index, count) {
  524. this.$implicit = $implicit;
  525. this.index = index;
  526. this.count = count;
  527. this.bounds = {};
  528. }
  529. Object.defineProperty(VirtualContext.prototype, "first", {
  530. get: function () { return this.index === 0; },
  531. enumerable: true,
  532. configurable: true
  533. });
  534. Object.defineProperty(VirtualContext.prototype, "last", {
  535. get: function () { return this.index === this.count - 1; },
  536. enumerable: true,
  537. configurable: true
  538. });
  539. Object.defineProperty(VirtualContext.prototype, "even", {
  540. get: function () { return this.index % 2 === 0; },
  541. enumerable: true,
  542. configurable: true
  543. });
  544. Object.defineProperty(VirtualContext.prototype, "odd", {
  545. get: function () { return !this.even; },
  546. enumerable: true,
  547. configurable: true
  548. });
  549. return VirtualContext;
  550. }());
  551. exports.VirtualContext = VirtualContext;
  552. var VIEWABLE_RENDERED_PADDING = 3;
  553. var REQUIRED_DOM_READS = 2;
  554. });
  555. //# sourceMappingURL=virtual-util.js.map