From d50148591b9a8bf7a49f873e1eaf5f8af364cb70 Mon Sep 17 00:00:00 2001 From: Sebastian Markbage Date: Tue, 2 Jul 2013 18:26:54 -0700 Subject: [PATCH] Introduce a supported way to slice children Introduces a counterpart to mapChildren. It excludes empty children just as mapChildren for compatibility. With might introduce something like sliceChildrenIncludingEmptyValues at some point. --- src/utils/__tests__/sliceChildren-test.js | 119 ++++++++++++++++++++++ src/utils/sliceChildren.js | 59 +++++++++++ 2 files changed, 178 insertions(+) create mode 100644 src/utils/__tests__/sliceChildren-test.js create mode 100644 src/utils/sliceChildren.js diff --git a/src/utils/__tests__/sliceChildren-test.js b/src/utils/__tests__/sliceChildren-test.js new file mode 100644 index 0000000..8ff3b95 --- /dev/null +++ b/src/utils/__tests__/sliceChildren-test.js @@ -0,0 +1,119 @@ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @emails react-core + * @jsx React.DOM + */ + +"use strict"; + +describe('sliceChildren', function() { + + var React; + var ReactTestUtils; + + var sliceChildren; + var reactComponentExpect; + + var Partial; + + beforeEach(function() { + React = require('React'); + ReactTestUtils = require('ReactTestUtils'); + + sliceChildren = require('sliceChildren'); + reactComponentExpect = require('reactComponentExpect'); + + Partial = React.createClass({ + render: function() { + return ( +
+ {sliceChildren( + this.props.children, + this.props.start, + this.props.end + )} +
+ ); + } + }); + }); + + function renderAndSlice(set, start, end) { + var instance = {set}; + ReactTestUtils.renderIntoDocument(instance); + var rendered = reactComponentExpect(instance) + .expectRenderedChild() + .instance(); + return rendered.props.children; + } + + it('should render the whole set if start zero is supplied', function() { + var fullSet = [ +
, +
, +
+ ]; + var children = renderAndSlice(fullSet, 0); + expect(children).toEqual({ + '[A]': fullSet[0], + '[B]': fullSet[1], + '[C]': fullSet[2] + }); + }); + + it('should render the remaining set if no end index is supplied', function() { + var fullSet = [ +
, +
, +
+ ]; + var children = renderAndSlice(fullSet, 1); + expect(children).toEqual({ + '[B]': fullSet[1], + '[C]': fullSet[2] + }); + }); + + it('should exclude everything at or after the end index', function() { + var fullSet = [ +
, +
, +
, +
+ ]; + var children = renderAndSlice(fullSet, 1, 2); + expect(children).toEqual({ + '[B]': fullSet[1] + }); + }); + + it('should allow static children to be sliced', function() { + var a =
; + var b =
; + var c =
; + + var instance = {a}{b}{c}; + ReactTestUtils.renderIntoDocument(instance); + var rendered = reactComponentExpect(instance) + .expectRenderedChild() + .instance(); + + expect(rendered.props.children).toEqual({ + '[1]': b + }); + }); + +}); diff --git a/src/utils/sliceChildren.js b/src/utils/sliceChildren.js new file mode 100644 index 0000000..7cd01c1 --- /dev/null +++ b/src/utils/sliceChildren.js @@ -0,0 +1,59 @@ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @providesModule sliceChildren + */ + +"use strict"; + +var flattenChildren = require('flattenChildren'); + +/** + * Slice children that are typically specified as `props.children`. This version + * of slice children ignores empty child components. + * + * @param {*} children The children set to filter. + * @param {number} start The first zero-based index to include in the subset. + * @param {?number} end The non-inclusive last index of the subset. + * @return {object} mirrored array with mapped children + */ +function sliceChildren(children, start, end) { + if (children == null) { + return children; + } + + var slicedChildren = {}; + var flattenedMap = flattenChildren(children); + var ii = 0; + for (var key in flattenedMap) { + if (!flattenedMap.hasOwnProperty(key)) { + continue; + } + var child = flattenedMap[key]; + // In this version of slice children we ignore empty children. + if (child !== null) { + if (ii >= start) { + slicedChildren[key] = child; + } + ii++; + if (end != null && ii >= end) { + break; + } + } + } + return slicedChildren; +} + +module.exports = sliceChildren;