From 75faaef71beaaf56645f35c069882f73c39b45f7 Mon Sep 17 00:00:00 2001 From: Corey Burrows Date: Fri, 1 Nov 2019 13:46:52 -0500 Subject: [PATCH] Update onFirstVisibleItemChange callback to provide the item index in addition to the item. --- docs/VirtualList.js | 2 +- pkg/VirtualList.js | 2 +- spec/VirtualList_spec.js | 2 +- src/VirtualList.jsx | 12 ++++++------ 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/VirtualList.js b/docs/VirtualList.js index ba984b5..9a8e897 100644 --- a/docs/VirtualList.js +++ b/docs/VirtualList.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("prop-types"),require("react")):"function"==typeof define&&define.amd?define(["prop-types","react"],e):"object"==typeof exports?exports.VirtualList=e(require("prop-types"),require("react")):t.VirtualList=e(t["prop-types"],t.react)}(window,function(t,e){return function(t){var e={};function o(n){if(e[n])return e[n].exports;var i=e[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,o),i.l=!0,i.exports}return o.m=t,o.c=e,o.d=function(t,e,n){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(t,e){if(1&e&&(t=o(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)o.d(n,i,function(e){return t[e]}.bind(null,i));return n},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="",o(o.s=2)}([function(e,o){e.exports=t},function(t,o){t.exports=e},function(t,e,o){"use strict";o.r(e);var n=o(1),i=o.n(n),r=o(0),s=o.n(r);function l(t){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function c(t,e){for(var o=0;o2?o-2:0),i=2;i=i)return e[n+r]}},{key:"handleDownwardScroll",value:function(t,e){for(var o=this.content.childNodes,n=this.props.items,i=this.state,r=i.winSize,s=i.avgRowHeight,l=Math.max(0,n.length-r),a=this.state,c=a.winStart,u=a.scrollTop,h=u+=t,f=0;f=0&&(s>0&&i[c].offsetTop-l>n.offsetHeight);c--)s--,a++;this.setState({winStart:s,scrollTop:l},function(){for(var t=o.content.childNodes,n=o.state.avgRowHeight,i=o.state.scrollTop,r=0;ro?this.handleLongScroll(t,e):t>0?this.handleDownwardScroll(t,e):t<0&&this.handleUpwardScroll(t,e),this}},{key:"scrollToIndex",value:function(t,e){var o=this.props.items,n=this.state,i=n.winSize,r=n.avgRowHeight,s=Math.max(0,o.length-i),l=Math.min(s,t),a=l*r;this.setState({winStart:l,scrollTop:a},e)}},{key:"scrollToItem",value:function(t,e){var o=this.props.items.indexOf(t);return o>=0&&this.scrollToIndex(o,e),this}},{key:"scrollToTop",value:function(t){return this.scrollToIndex(0,t)}},{key:"itemsMutated",value:function(t){var e=this.props.items,o=this.state,n=o.winStart,i=o.winSize,r=Math.max(0,e.length-i);return n>r?this.setState({winStart:r},t):this.forceUpdate(t),this}},{key:"onScroll",value:function(t){t.persist(),t.target.scrollTop===this.state.scrollTop&&this.props.onScroll&&this.props.onScroll(t),this.debouncedOnScroll(t)}},{key:"debouncedOnScroll",value:function(t){var e=this.node,o=this.state.scrollTop;e.scrollTop!==o&&this.scroll(e.scrollTop-o),this.props.onScroll&&this.props.onScroll(t)}},{key:"render",value:function(){for(var t,e=this,o=this.props,n=o.items,r=o.getItem,s=o.getItemKey,l=o.scrollbarOffset,a=this.state,c=a.winStart,u=a.winSize,h=a.avgRowHeight,f=Math.min(n.length-1,c+u-1),p=c*h,d=Math.max((n.length-c-u)*h,0),m=Object.assign({position:"absolute",top:0,right:l,bottom:0,left:0,overflowY:"auto",overflowX:l?"hidden":void 0},this.props.style),y={paddingTop:p,paddingBottom:d,marginRight:-l},g=i.a.Children.only(this.props.children),b=[],w=c;w<=f;w++)t=r(n,w),b.push(i.a.createElement(v,{key:s(t,w),itemIndex:w,itemView:g,item:t}));return i.a.createElement("div",{ref:function(t){e.node=t},className:"VirtualList",tabIndex:"-1",style:m,onScroll:this.onScroll},i.a.createElement("div",{ref:function(t){e.content=t},className:"VirtualList-content",style:y},b))}}]),e}();g.propTypes={items:s.a.array.isRequired,getItem:s.a.func,getItemKey:s.a.func,onFirstVisibleItemChange:s.a.func,onScroll:s.a.func,buffer:s.a.number,scrollbarOffset:s.a.number,resizeInterval:s.a.number,style:s.a.object,debounce:s.a.bool},g.defaultProps={getItem:function(t,e){return t[e]},getItemKey:function(t,e){return e},buffer:4,scrollbarOffset:0,resizeInterval:1e3,debounce:!1},e.default=g}])}); \ No newline at end of file +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("prop-types"),require("react")):"function"==typeof define&&define.amd?define(["prop-types","react"],e):"object"==typeof exports?exports.VirtualList=e(require("prop-types"),require("react")):t.VirtualList=e(t["prop-types"],t.react)}(window,function(t,e){return function(t){var e={};function n(o){if(e[o])return e[o].exports;var i=e[o]={i:o,l:!1,exports:{}};return t[o].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(o,i,function(e){return t[e]}.bind(null,i));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=2)}([function(e,n){e.exports=t},function(t,n){t.exports=e},function(t,e,n){"use strict";n.r(e);var o=n(1),i=n.n(o),r=n(0),s=n.n(r);function l(t){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function c(t,e){for(var n=0;n2?n-2:0),i=2;i=o)return n+i}},{key:"handleDownwardScroll",value:function(t,e){for(var n=this.content.childNodes,o=this.props.items,i=this.state,r=i.winSize,s=i.avgRowHeight,l=Math.max(0,o.length-r),a=this.state,c=a.winStart,u=a.scrollTop,h=u+=t,f=0;f=0&&(s>0&&i[c].offsetTop-l>o.offsetHeight);c--)s--,a++;this.setState({winStart:s,scrollTop:l},function(){for(var t=n.content.childNodes,o=n.state.avgRowHeight,i=n.state.scrollTop,r=0;rn?this.handleLongScroll(t,e):t>0?this.handleDownwardScroll(t,e):t<0&&this.handleUpwardScroll(t,e),this}},{key:"scrollToIndex",value:function(t,e){var n=this.props.items,o=this.state,i=o.winSize,r=o.avgRowHeight,s=Math.max(0,n.length-i),l=Math.min(s,t),a=l*r;this.setState({winStart:l,scrollTop:a},e)}},{key:"scrollToItem",value:function(t,e){var n=this.props.items.indexOf(t);return n>=0&&this.scrollToIndex(n,e),this}},{key:"scrollToTop",value:function(t){return this.scrollToIndex(0,t)}},{key:"itemsMutated",value:function(t){var e=this.props.items,n=this.state,o=n.winStart,i=n.winSize,r=Math.max(0,e.length-i);return o>r?this.setState({winStart:r},t):this.forceUpdate(t),this}},{key:"onScroll",value:function(t){t.persist(),t.target.scrollTop===this.state.scrollTop&&this.props.onScroll&&this.props.onScroll(t),this.debouncedOnScroll(t)}},{key:"debouncedOnScroll",value:function(t){var e=this.node,n=this.state.scrollTop;e.scrollTop!==n&&this.scroll(e.scrollTop-n),this.props.onScroll&&this.props.onScroll(t)}},{key:"render",value:function(){for(var t,e=this,n=this.props,o=n.items,r=n.getItem,s=n.getItemKey,l=n.scrollbarOffset,a=this.state,c=a.winStart,u=a.winSize,h=a.avgRowHeight,f=Math.min(o.length-1,c+u-1),p=c*h,d=Math.max((o.length-c-u)*h,0),m=Object.assign({position:"absolute",top:0,right:l,bottom:0,left:0,overflowY:"auto",overflowX:l?"hidden":void 0},this.props.style),y={paddingTop:p,paddingBottom:d,marginRight:-l},g=i.a.Children.only(this.props.children),b=[],w=c;w<=f;w++)t=r(o,w),b.push(i.a.createElement(v,{key:s(t,w),itemIndex:w,itemView:g,item:t}));return i.a.createElement("div",{ref:function(t){e.node=t},className:"VirtualList",tabIndex:"-1",style:m,onScroll:this.onScroll},i.a.createElement("div",{ref:function(t){e.content=t},className:"VirtualList-content",style:y},b))}}]),e}();g.propTypes={items:s.a.array.isRequired,getItem:s.a.func,getItemKey:s.a.func,onFirstVisibleItemChange:s.a.func,onScroll:s.a.func,buffer:s.a.number,scrollbarOffset:s.a.number,resizeInterval:s.a.number,style:s.a.object,debounce:s.a.bool},g.defaultProps={getItem:function(t,e){return t[e]},getItemKey:function(t,e){return e},buffer:4,scrollbarOffset:0,resizeInterval:1e3,debounce:!1},e.default=g}])}); \ No newline at end of file diff --git a/pkg/VirtualList.js b/pkg/VirtualList.js index ba984b5..9a8e897 100644 --- a/pkg/VirtualList.js +++ b/pkg/VirtualList.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("prop-types"),require("react")):"function"==typeof define&&define.amd?define(["prop-types","react"],e):"object"==typeof exports?exports.VirtualList=e(require("prop-types"),require("react")):t.VirtualList=e(t["prop-types"],t.react)}(window,function(t,e){return function(t){var e={};function o(n){if(e[n])return e[n].exports;var i=e[n]={i:n,l:!1,exports:{}};return t[n].call(i.exports,i,i.exports,o),i.l=!0,i.exports}return o.m=t,o.c=e,o.d=function(t,e,n){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(t,e){if(1&e&&(t=o(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)o.d(n,i,function(e){return t[e]}.bind(null,i));return n},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="",o(o.s=2)}([function(e,o){e.exports=t},function(t,o){t.exports=e},function(t,e,o){"use strict";o.r(e);var n=o(1),i=o.n(n),r=o(0),s=o.n(r);function l(t){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function c(t,e){for(var o=0;o2?o-2:0),i=2;i=i)return e[n+r]}},{key:"handleDownwardScroll",value:function(t,e){for(var o=this.content.childNodes,n=this.props.items,i=this.state,r=i.winSize,s=i.avgRowHeight,l=Math.max(0,n.length-r),a=this.state,c=a.winStart,u=a.scrollTop,h=u+=t,f=0;f=0&&(s>0&&i[c].offsetTop-l>n.offsetHeight);c--)s--,a++;this.setState({winStart:s,scrollTop:l},function(){for(var t=o.content.childNodes,n=o.state.avgRowHeight,i=o.state.scrollTop,r=0;ro?this.handleLongScroll(t,e):t>0?this.handleDownwardScroll(t,e):t<0&&this.handleUpwardScroll(t,e),this}},{key:"scrollToIndex",value:function(t,e){var o=this.props.items,n=this.state,i=n.winSize,r=n.avgRowHeight,s=Math.max(0,o.length-i),l=Math.min(s,t),a=l*r;this.setState({winStart:l,scrollTop:a},e)}},{key:"scrollToItem",value:function(t,e){var o=this.props.items.indexOf(t);return o>=0&&this.scrollToIndex(o,e),this}},{key:"scrollToTop",value:function(t){return this.scrollToIndex(0,t)}},{key:"itemsMutated",value:function(t){var e=this.props.items,o=this.state,n=o.winStart,i=o.winSize,r=Math.max(0,e.length-i);return n>r?this.setState({winStart:r},t):this.forceUpdate(t),this}},{key:"onScroll",value:function(t){t.persist(),t.target.scrollTop===this.state.scrollTop&&this.props.onScroll&&this.props.onScroll(t),this.debouncedOnScroll(t)}},{key:"debouncedOnScroll",value:function(t){var e=this.node,o=this.state.scrollTop;e.scrollTop!==o&&this.scroll(e.scrollTop-o),this.props.onScroll&&this.props.onScroll(t)}},{key:"render",value:function(){for(var t,e=this,o=this.props,n=o.items,r=o.getItem,s=o.getItemKey,l=o.scrollbarOffset,a=this.state,c=a.winStart,u=a.winSize,h=a.avgRowHeight,f=Math.min(n.length-1,c+u-1),p=c*h,d=Math.max((n.length-c-u)*h,0),m=Object.assign({position:"absolute",top:0,right:l,bottom:0,left:0,overflowY:"auto",overflowX:l?"hidden":void 0},this.props.style),y={paddingTop:p,paddingBottom:d,marginRight:-l},g=i.a.Children.only(this.props.children),b=[],w=c;w<=f;w++)t=r(n,w),b.push(i.a.createElement(v,{key:s(t,w),itemIndex:w,itemView:g,item:t}));return i.a.createElement("div",{ref:function(t){e.node=t},className:"VirtualList",tabIndex:"-1",style:m,onScroll:this.onScroll},i.a.createElement("div",{ref:function(t){e.content=t},className:"VirtualList-content",style:y},b))}}]),e}();g.propTypes={items:s.a.array.isRequired,getItem:s.a.func,getItemKey:s.a.func,onFirstVisibleItemChange:s.a.func,onScroll:s.a.func,buffer:s.a.number,scrollbarOffset:s.a.number,resizeInterval:s.a.number,style:s.a.object,debounce:s.a.bool},g.defaultProps={getItem:function(t,e){return t[e]},getItemKey:function(t,e){return e},buffer:4,scrollbarOffset:0,resizeInterval:1e3,debounce:!1},e.default=g}])}); \ No newline at end of file +!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("prop-types"),require("react")):"function"==typeof define&&define.amd?define(["prop-types","react"],e):"object"==typeof exports?exports.VirtualList=e(require("prop-types"),require("react")):t.VirtualList=e(t["prop-types"],t.react)}(window,function(t,e){return function(t){var e={};function n(o){if(e[o])return e[o].exports;var i=e[o]={i:o,l:!1,exports:{}};return t[o].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,o){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:o})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var i in t)n.d(o,i,function(e){return t[e]}.bind(null,i));return o},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=2)}([function(e,n){e.exports=t},function(t,n){t.exports=e},function(t,e,n){"use strict";n.r(e);var o=n(1),i=n.n(o),r=n(0),s=n.n(r);function l(t){return(l="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function a(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function c(t,e){for(var n=0;n2?n-2:0),i=2;i=o)return n+i}},{key:"handleDownwardScroll",value:function(t,e){for(var n=this.content.childNodes,o=this.props.items,i=this.state,r=i.winSize,s=i.avgRowHeight,l=Math.max(0,o.length-r),a=this.state,c=a.winStart,u=a.scrollTop,h=u+=t,f=0;f=0&&(s>0&&i[c].offsetTop-l>o.offsetHeight);c--)s--,a++;this.setState({winStart:s,scrollTop:l},function(){for(var t=n.content.childNodes,o=n.state.avgRowHeight,i=n.state.scrollTop,r=0;rn?this.handleLongScroll(t,e):t>0?this.handleDownwardScroll(t,e):t<0&&this.handleUpwardScroll(t,e),this}},{key:"scrollToIndex",value:function(t,e){var n=this.props.items,o=this.state,i=o.winSize,r=o.avgRowHeight,s=Math.max(0,n.length-i),l=Math.min(s,t),a=l*r;this.setState({winStart:l,scrollTop:a},e)}},{key:"scrollToItem",value:function(t,e){var n=this.props.items.indexOf(t);return n>=0&&this.scrollToIndex(n,e),this}},{key:"scrollToTop",value:function(t){return this.scrollToIndex(0,t)}},{key:"itemsMutated",value:function(t){var e=this.props.items,n=this.state,o=n.winStart,i=n.winSize,r=Math.max(0,e.length-i);return o>r?this.setState({winStart:r},t):this.forceUpdate(t),this}},{key:"onScroll",value:function(t){t.persist(),t.target.scrollTop===this.state.scrollTop&&this.props.onScroll&&this.props.onScroll(t),this.debouncedOnScroll(t)}},{key:"debouncedOnScroll",value:function(t){var e=this.node,n=this.state.scrollTop;e.scrollTop!==n&&this.scroll(e.scrollTop-n),this.props.onScroll&&this.props.onScroll(t)}},{key:"render",value:function(){for(var t,e=this,n=this.props,o=n.items,r=n.getItem,s=n.getItemKey,l=n.scrollbarOffset,a=this.state,c=a.winStart,u=a.winSize,h=a.avgRowHeight,f=Math.min(o.length-1,c+u-1),p=c*h,d=Math.max((o.length-c-u)*h,0),m=Object.assign({position:"absolute",top:0,right:l,bottom:0,left:0,overflowY:"auto",overflowX:l?"hidden":void 0},this.props.style),y={paddingTop:p,paddingBottom:d,marginRight:-l},g=i.a.Children.only(this.props.children),b=[],w=c;w<=f;w++)t=r(o,w),b.push(i.a.createElement(v,{key:s(t,w),itemIndex:w,itemView:g,item:t}));return i.a.createElement("div",{ref:function(t){e.node=t},className:"VirtualList",tabIndex:"-1",style:m,onScroll:this.onScroll},i.a.createElement("div",{ref:function(t){e.content=t},className:"VirtualList-content",style:y},b))}}]),e}();g.propTypes={items:s.a.array.isRequired,getItem:s.a.func,getItemKey:s.a.func,onFirstVisibleItemChange:s.a.func,onScroll:s.a.func,buffer:s.a.number,scrollbarOffset:s.a.number,resizeInterval:s.a.number,style:s.a.object,debounce:s.a.bool},g.defaultProps={getItem:function(t,e){return t[e]},getItemKey:function(t,e){return e},buffer:4,scrollbarOffset:0,resizeInterval:1e3,debounce:!1},e.default=g}])}); \ No newline at end of file diff --git a/spec/VirtualList_spec.js b/spec/VirtualList_spec.js index 2444739..732657f 100644 --- a/spec/VirtualList_spec.js +++ b/spec/VirtualList_spec.js @@ -221,7 +221,7 @@ describe('VirtualList', function() { expect(this.onFirstVisibleItemChange.calls.count()).toBe(1); this.list.scroll(2, () => { expect(this.onFirstVisibleItemChange.calls.count()).toBe(2); - expect(this.onFirstVisibleItemChange).toHaveBeenCalledWith(this.items[1]); + expect(this.onFirstVisibleItemChange).toHaveBeenCalledWith(this.items[1], 1); done(); }); }); diff --git a/src/VirtualList.jsx b/src/VirtualList.jsx index ecb1c1c..acc01ed 100644 --- a/src/VirtualList.jsx +++ b/src/VirtualList.jsx @@ -185,22 +185,22 @@ class VirtualList extends React.Component { return; } - const first = this.findFirstVisibleItem(); + const idx = this.findFirstVisibleItemIndex(); - if (this._first !== first) { - this.props.onFirstVisibleItemChange(first); - this._first = first; + if (this._firstIndex !== idx) { + this.props.onFirstVisibleItemChange(this.props.items[idx], idx); + this._firstIndex = idx; } } - findFirstVisibleItem() { + findFirstVisibleItemIndex() { const childNodes = this.content.childNodes; const { items } = this.props; const { winStart, scrollTop } = this.state; for (let i = 0; i < childNodes.length; i++) { if (childNodes[i].offsetTop + childNodes[i].offsetHeight >= scrollTop) { - return items[winStart + i]; + return winStart + i; } }