├── .gitignore
├── src
├── img
│ └── arrow_icons.png
├── js
│ ├── directives
│ │ └── ngReactGridDirective.js
│ ├── main.js
│ ├── factories
│ │ ├── ngReactGridCheckboxFieldFactory.js
│ │ ├── ngReactGridTextFieldFactory.js
│ │ ├── ngReactGridSelectFieldFactory.js
│ │ └── ngReactGridCheckboxFactory.js
│ ├── vendors
│ │ └── miniUnderscore.js
│ └── classes
│ │ ├── NgReactGridEditManager.js
│ │ ├── NgReactGridReactManager.js
│ │ └── ngReactGrid.js
├── jsx
│ ├── reactGridTextField.jsx
│ ├── reactGridCheckboxField.jsx
│ ├── reactGridSelectField.jsx
│ ├── reactGridCheckbox.jsx
│ └── reactGrid.jsx
└── css
│ └── ngReactGrid.css
├── bower.json
├── package.json
├── LICENSE
├── gulpfile.js
├── README.md
└── examples
├── basic.html
└── dataSet.js
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | node_modules
3 | .DS_Store
--------------------------------------------------------------------------------
/src/img/arrow_icons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/josebalius/ngReactGrid/HEAD/src/img/arrow_icons.png
--------------------------------------------------------------------------------
/src/js/directives/ngReactGridDirective.js:
--------------------------------------------------------------------------------
1 | var ngReactGrid = require("../classes/NgReactGrid");
2 |
3 | var ngReactGridDirective = function ($rootScope) {
4 | return {
5 | restrict: "E",
6 | scope : {
7 | grid : "="
8 | },
9 | link: function (scope, element, attrs) {
10 | new ngReactGrid(scope, element, attrs, $rootScope);
11 | }
12 | }
13 | };
14 |
15 | module.exports = ngReactGridDirective;
16 |
17 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ngReactGrid",
3 | "version": "0.7.0",
4 | "description": "A really fast Angular grid using the power of React to render",
5 | "homepage": "https://github.com/josebalius/ngReactGrid",
6 | "authors": [
7 | "Jose Garcia - jose.balius@gmail.com"
8 | ],
9 | "main": [
10 | "build/js/ngReactGrid.min.js",
11 | "build/css/ngReactGrid.css",
12 | "build/img/arrow_icons.png"
13 | ],
14 | "ignore": [
15 | "**/.*",
16 | "node_modules",
17 | "bower_components",
18 | "test",
19 | "tests"
20 | ]
21 | }
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ngReactGrid",
3 | "version": "0.7.0",
4 | "description": "A really fast Angular grid using the power of React to render",
5 | "scripts": {
6 | "test": "echo \"Error: no test specified\" && exit 1",
7 | "gulp": "gulp"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/josebalius/ngReactGrid.git"
12 | },
13 | "author": "Jose Garcia - jose.balius@gmail.com",
14 | "license": "MIT",
15 | "bugs": {
16 | "url": "https://github.com/josebalius/ngReactGrid/issues"
17 | },
18 | "homepage": "http://josebalius.github.io/ngReactGrid/",
19 | "devDependencies": {
20 | "gulp": "^3.6.2",
21 | "gulp-react": "2.0.0",
22 | "gulp-concat": "2.2.0",
23 | "gulp-filter": "0.4.1",
24 | "gulp-uglify": "0.3.0",
25 | "gulp-rename": "1.2.0",
26 | "gulp-replace": "0.3.0",
27 | "gulp-browserify": "0.5.0"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/js/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var ngReactGridDirective = require('./directives/ngReactGridDirective');
4 | var ngReactGridCheckboxFactory = require('./factories/ngReactGridCheckboxFactory');
5 | var ngReactGridTextFieldFactory = require("./factories/ngReactGridTextFieldFactory");
6 | var ngReactGridCheckboxFieldFactory = require("./factories/ngReactGridCheckboxFieldFactory");
7 | var ngReactGridSelectFieldFactory = require("./factories/ngReactGridSelectFieldFactory");
8 |
9 | angular.module('ngReactGrid', [])
10 | .factory("ngReactGridCheckbox", ['$rootScope', ngReactGridCheckboxFactory])
11 | .factory("ngReactGridTextField", ['$rootScope', ngReactGridTextFieldFactory])
12 | .factory("ngReactGridCheckboxField", [ngReactGridCheckboxFieldFactory])
13 | .factory("ngReactGridSelectField", ['$rootScope', ngReactGridSelectFieldFactory])
14 | .directive("ngReactGrid", ['$rootScope', ngReactGridDirective]);
15 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Jose Garcia
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/src/js/factories/ngReactGridCheckboxFieldFactory.js:
--------------------------------------------------------------------------------
1 | var NgReactGridReactManager = require("../classes/NgReactGridReactManager");
2 |
3 | var ngReactGridCheckboxFieldFactory = function() {
4 |
5 | var ngReactGridCheckboxField = function(record, field, updateNotification) {
6 | this.record = record;
7 | this.field = field;
8 | this.updateNotification = updateNotification;
9 |
10 | var value = NgReactGridReactManager.getObjectPropertyByString(this.record, this.field);
11 | var ngReactGridCheckboxFieldElement = React.createFactory(NgReactGridCheckboxFieldComponent);
12 | return ngReactGridCheckboxFieldElement({value: value, updateValue: this.updateValue.bind(this)});
13 | };
14 |
15 | ngReactGridCheckboxField.prototype.updateValue = function(newValue) {
16 | NgReactGridReactManager.updateObjectPropertyByString(this.record, this.field, newValue);
17 |
18 | if(this.updateNotification) {
19 | this.updateNotification(this.record);
20 | }
21 | };
22 |
23 | return ngReactGridCheckboxField;
24 |
25 | };
26 |
27 | module.exports = ngReactGridCheckboxFieldFactory;
--------------------------------------------------------------------------------
/src/jsx/reactGridTextField.jsx:
--------------------------------------------------------------------------------
1 | var NgReactGridTextFieldComponent = (function() {
2 | var NgReactGridTextFieldComponent = React.createClass({
3 | getInitialState: function() {
4 | return {
5 | defaultValue: ""
6 | };
7 | },
8 | handleChange: function() {
9 | var value = this.refs.textField.getDOMNode().value;
10 | this.props.updateValue(value);
11 | this.setState({
12 | defaultValue: value
13 | });
14 | },
15 | componentWillReceiveProps: function(nextProps) {
16 | this.setState({
17 | defaultValue: nextProps.value
18 | });
19 | },
20 | componentWillMount: function() {
21 | this.setState({
22 | defaultValue: this.props.value
23 | });
24 | },
25 | render: function() {
26 | return (
27 |
28 | )
29 | }
30 | });
31 |
32 | return NgReactGridTextFieldComponent;
33 | })();
--------------------------------------------------------------------------------
/src/jsx/reactGridCheckboxField.jsx:
--------------------------------------------------------------------------------
1 | var NgReactGridCheckboxFieldComponent = (function() {
2 | var NgReactGridCheckboxFieldComponent = React.createClass({
3 | getInitialState: function() {
4 | return {
5 | checked: false
6 | }
7 | },
8 | handleClick: function() {
9 | var newState = {
10 | checked: (this.state.checked) ? false : true
11 | };
12 |
13 | this.setState(newState);
14 |
15 | this.props.updateValue(newState.checked);
16 | },
17 | componentWillReceiveProps: function(nextProps) {
18 | this.setState({
19 | checked: (nextProps.value) ? true : false
20 | });
21 | },
22 | componentWillMount: function() {
23 | this.setState({
24 | checked: (this.props.value === true) ? true : false
25 | });
26 | },
27 | render: function() {
28 | return (
29 |
30 | )
31 | }
32 | });
33 |
34 | return NgReactGridCheckboxFieldComponent;
35 | })();
--------------------------------------------------------------------------------
/src/js/vendors/miniUnderscore.js:
--------------------------------------------------------------------------------
1 | var _ = {
2 | nativeForEach: Array.prototype.forEach,
3 | each: function (obj, iterator, context) {
4 | if (obj == null) return obj;
5 | if (this.nativeForEach && obj.forEach === this.nativeForEach) {
6 | obj.forEach(iterator, context);
7 | } else if (obj.length === +obj.length) {
8 | for (var i = 0, length = obj.length; i < length; i++) {
9 | if (iterator.call(context, obj[i], i, obj) === breaker) return;
10 | }
11 | } else {
12 | var keys = _.keys(obj);
13 | for (var i = 0, length = keys.length; i < length; i++) {
14 | if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return;
15 | }
16 | }
17 | return obj;
18 | },
19 | slice: Array.prototype.slice,
20 | extend: function (obj) {
21 | this.each(this.slice.call(arguments, 1), function (source) {
22 | if (source) {
23 | for (var prop in source) {
24 | obj[prop] = source[prop];
25 | }
26 | }
27 | });
28 | return obj;
29 | }
30 | };
31 |
32 | module.exports = _;
33 |
--------------------------------------------------------------------------------
/src/js/factories/ngReactGridTextFieldFactory.js:
--------------------------------------------------------------------------------
1 | var NgReactGridReactManager = require("../classes/NgReactGridReactManager");
2 |
3 | var ngReactGridTextFieldFactory = function($rootScope) {
4 |
5 | var ngReactGridTextField = function(record, field, updateNotification) {
6 | this.record = record;
7 | this.field = field;
8 | this.updateNotification = updateNotification;
9 |
10 | var value = NgReactGridReactManager.getObjectPropertyByString(this.record, this.field);
11 |
12 | var ngReactGridTextFieldElement = React.createFactory(NgReactGridTextFieldComponent);
13 | return ngReactGridTextFieldElement({value: value, updateValue: this.updateValue.bind(this)});
14 | };
15 |
16 | ngReactGridTextField.prototype.updateValue = function(newValue) {
17 | NgReactGridReactManager.updateObjectPropertyByString(this.record, this.field, newValue);
18 |
19 | if(this.updateNotification) {
20 | if($rootScope.$$phase) {
21 | this.updateNotification(this.record);
22 | } else {
23 | $rootScope.$apply(function () {
24 | this.updateNotification(this.record);
25 | }.bind(this));
26 | }
27 | }
28 | };
29 |
30 | return ngReactGridTextField;
31 |
32 | };
33 |
34 | module.exports = ngReactGridTextFieldFactory;
35 |
--------------------------------------------------------------------------------
/src/jsx/reactGridSelectField.jsx:
--------------------------------------------------------------------------------
1 | var NgReactGridSelectFieldComponent = (function() {
2 |
3 | var NgReactGridSelectFieldComponent = React.createClass({
4 | getInitialState: function() {
5 | return {
6 | defaultValue: {
7 | id: "",
8 | name: ""
9 | }
10 | };
11 | },
12 | handleChange: function(e) {
13 | var value = e.target.value;
14 | this.props.updateValue(value);
15 | this.setState({
16 | defaultValue: {
17 | id: value
18 | }
19 | });
20 | },
21 | componentWillReceiveProps: function(nextProps) {
22 | this.setState({
23 | defaultValue: nextProps.value || {}
24 | });
25 | },
26 | componentWillMount: function() {
27 | this.setState({
28 | defaultValue: this.props.value || {}
29 | });
30 | },
31 | render: function() {
32 |
33 | if(!this.props.referenceData) {
34 | this.props.referenceData = [];
35 | }
36 |
37 | var options = this.props.referenceData.map(function(option) {
38 | return (
39 | {option.name}
40 | )
41 | });
42 |
43 | return (
44 |
45 | {options}
46 |
47 | )
48 | }
49 | });
50 |
51 | return NgReactGridSelectFieldComponent;
52 |
53 | })();
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var react = require('gulp-react');
3 | var concat = require('gulp-concat');
4 | var gulpFilter = require('gulp-filter');
5 | var uglify = require('gulp-uglify');
6 | var rename = require('gulp-rename');
7 | var replace = require('gulp-replace');
8 | var browserify = require('gulp-browserify');
9 | var packageJSON = require('./package.json');
10 |
11 | gulp.task('css', function () {
12 | return gulp.src('./src/css/**.css')
13 | .pipe(concat('ngReactGrid.css'))
14 | .pipe(gulp.dest('./build/css'));
15 | });
16 |
17 | gulp.task('img', function () {
18 | return gulp.src('./src/img/**.png')
19 | .pipe(gulp.dest('./build/img'));
20 | });
21 |
22 | gulp.task('build-grid', function () {
23 | var jsxFilter = gulpFilter('**/*.jsx');
24 | var jsFilter = gulpFilter("**/*.js");
25 | return gulp.src(['./src/js/main.js', './src/jsx/**.jsx'])
26 | .pipe(jsFilter)
27 | .pipe(browserify())
28 | .pipe(jsFilter.restore())
29 | .pipe(jsxFilter)
30 | .pipe(react())
31 | .pipe(jsxFilter.restore())
32 | .pipe(concat('ngReactGrid.js'))
33 | .pipe(replace(/{\$version}/g, packageJSON.version))
34 | .pipe(gulp.dest('./build/js/'))
35 | });
36 |
37 | gulp.task('uglify-build', ['build-grid'], function () {
38 | return gulp.src(['./build/js/ngReactGrid.js'])
39 | .pipe(uglify({
40 | preserveComments: 'some'
41 | }))
42 | .pipe(rename('ngReactGrid.min.js'))
43 | .pipe(gulp.dest('./build/js'))
44 | });
45 |
46 | gulp.task('build', ['build-grid', 'uglify-build', 'css', 'img']);
47 |
48 | gulp.task('default', ['build'], function () {
49 | gulp.watch('./src/**', ['build']);
50 | });
51 |
--------------------------------------------------------------------------------
/src/js/factories/ngReactGridSelectFieldFactory.js:
--------------------------------------------------------------------------------
1 | var NgReactGridReactManager = require("../classes/NgReactGridReactManager");
2 |
3 | var ngReactGridSelectFieldFactory = function($rootScope) {
4 |
5 | var ngReactGridSelectField = function(record, field, referenceData, updateNotification) {
6 | this.record = record;
7 | this.field = field;
8 | this.updateNotification = updateNotification;
9 | this.referenceData = referenceData;
10 |
11 | var value = NgReactGridReactManager.getObjectPropertyByString(this.record, this.field);
12 |
13 | var ngReactGridSelectFieldElement = React.createFactory(NgReactGridSelectFieldComponent);
14 |
15 | return ngReactGridSelectFieldElement({value: value, updateValue: this.updateValue.bind(this), referenceData: (referenceData || [])});
16 | };
17 |
18 | ngReactGridSelectField.prototype.updateValue = function(newValue) {
19 |
20 | var updateValue = {};
21 |
22 | for(var i in this.referenceData) {
23 | var option = this.referenceData[i];
24 |
25 | if(option.id == newValue) {
26 | updateValue = option;
27 | }
28 | }
29 |
30 | NgReactGridReactManager.updateObjectPropertyByString(this.record, this.field, updateValue);
31 |
32 | if(this.updateNotification) {
33 | if($rootScope.$$phase) {
34 | this.updateNotification(this.record);
35 | } else {
36 | $rootScope.$apply(function () {
37 | this.updateNotification(this.record);
38 | }.bind(this));
39 | }
40 | }
41 | };
42 |
43 | return ngReactGridSelectField;
44 |
45 | };
46 |
47 | module.exports = ngReactGridSelectFieldFactory;
--------------------------------------------------------------------------------
/src/js/classes/NgReactGridEditManager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This class manages the editing/saving/reverting functionality to ngReactGrid
3 | * @param ngReactGrid
4 | * @constructor
5 | */
6 | var NgReactGridEditManager = function(ngReactGrid) {
7 | this.ngReactGrid = ngReactGrid;
8 | this.dataCopy = [];
9 | };
10 |
11 | /**
12 | * This function is used to add the edit/save/cancel API to the grid object created by the user.
13 | * @param gridObject
14 | */
15 | NgReactGridEditManager.prototype.mixinAPI = function(gridObject) {
16 | var self = this;
17 |
18 | /**
19 | * This is the function that puts the grid into edit mode
20 | */
21 | gridObject.edit = function() {
22 | return self.edit.call(self);
23 | };
24 |
25 | /**
26 | * This is the function that will persist the modified data to the original model
27 | */
28 | gridObject.save = function() {
29 | return self.save.call(self);
30 | };
31 |
32 | /**
33 | * This function is called whenever the modifications need to be reverted
34 | */
35 | gridObject.cancel = function() {
36 | return self.cancel.call(self);
37 | };
38 |
39 | /**
40 | * This function is called whenever the modifications need to be reverted
41 | */
42 | gridObject.getEditedData = function() {
43 | return self.getEditedData.call(self);
44 | };
45 |
46 | };
47 |
48 | /**
49 | * This is the function that puts the grid into edit mode
50 | */
51 | NgReactGridEditManager.prototype.getEditedData = function() {
52 | return this.ngReactGrid.react.originalData;
53 | };
54 |
55 | /**
56 | * This is the function that puts the grid into edit mode
57 | */
58 | NgReactGridEditManager.prototype.edit = function() {
59 | this.ngReactGrid.editing = true;
60 | this.dataCopy = this.copyData(this.ngReactGrid.react.originalData);
61 | this.ngReactGrid.render();
62 | };
63 |
64 | /**
65 | * This is the function that will persist the modified data to the original model
66 | */
67 | NgReactGridEditManager.prototype.save = function() {
68 | this.ngReactGrid.editing = false;
69 |
70 | this.ngReactGrid.update(this.ngReactGrid.events.DATA, {
71 | data: this.ngReactGrid.react.originalData
72 | });
73 |
74 | return this.ngReactGrid.react.originalData;
75 | };
76 |
77 | /**
78 | * This function is called whenever the modifications need to be reverted
79 | */
80 | NgReactGridEditManager.prototype.cancel = function() {
81 | this.ngReactGrid.editing = false;
82 |
83 | this.ngReactGrid.update(this.ngReactGrid.events.DATA, {
84 | data: this.dataCopy
85 | });
86 | };
87 |
88 | NgReactGridEditManager.prototype.copyData = function(data) {
89 | return JSON.parse(JSON.stringify(data));
90 | };
91 |
92 | module.exports = NgReactGridEditManager;
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ngReactGrid
2 | ===========
3 |
4 | NOTE: Active development of this project has stopped. All new development is being done on the https://github.com/josebalius/react-grid project which will contain most of ngReactGrid's functionality with adapters for Angular 1.x, 2.x and KnockoutJS.
5 |
6 |
7 | ngReactGrid is an Angular directive that can be used to render an enhanced HTML table or grid of data very fast using React as the rendering engine.
8 |
9 | The API of the grid is similar to that of ng-grid's, and the table architecture (3 tables per grid) is similar to that of jQuery DataTables.
10 |
11 | Please refer to: http://josebalius.github.io/ngReactGrid/ for documentation.
12 |
13 | Bower
14 | -----
15 |
16 | ```
17 | bower install ngReactGrid
18 | ```
19 |
20 | Features
21 | --------
22 | * Fast, awesome performance
23 | * Fixed headers
24 | * Server side hooks
25 | * Sorting
26 | * Pagination
27 | * Page size
28 | * Search
29 | * Horizontal scrolling
30 | * Custom width / height
31 | * Custom cell rendering
32 | * Checkbox selection column
33 |
34 | Todo
35 | ----
36 | * Editable cells - In Progress
37 | * Resizeable columns - In Progress
38 | * Column Filtering - In Progress
39 | * Column pinning
40 | * Don't see your feature? I am accepting pull requests. Please contribute.
41 |
42 | Develop
43 | -------
44 |
45 | ```bash
46 | # Clone this repo (or your fork).
47 | git clone https://github.com/josebalius/ngReactGrid.git
48 | cd ngReactGrid
49 |
50 | # Install all the the dev dependencies
51 | npm install
52 |
53 | # Run gulp inside the ngReactGrid to watch your files and build
54 | npm run gulp
55 | ```
56 |
57 | I use examples/basic.html to implement features, it is my "sandbox" environment. This file however is always changing (with whatever it is that I am working on) so beware. I suggest you copy this file and set it up your way. I will be creating more examples when I have some time.
58 |
59 | Please remember that there is also a documentation site: http://josebalius.github.io/ngReactGrid/
60 |
61 | Good luck!
62 |
63 | License
64 | ----------
65 | The MIT License (MIT)
66 |
67 | Copyright (c) 2014 Jose Garcia
68 |
69 | Permission is hereby granted, free of charge, to any person obtaining a copy
70 | of this software and associated documentation files (the "Software"), to deal
71 | in the Software without restriction, including without limitation the rights
72 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
73 | copies of the Software, and to permit persons to whom the Software is
74 | furnished to do so, subject to the following conditions:
75 |
76 | The above copyright notice and this permission notice shall be included in all
77 | copies or substantial portions of the Software.
78 |
79 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
80 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
81 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
82 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
83 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
84 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
85 | SOFTWARE.
86 |
87 | [](http://githalytics.com/josebalius/ngReactGrid)
88 |
--------------------------------------------------------------------------------
/src/jsx/reactGridCheckbox.jsx:
--------------------------------------------------------------------------------
1 | var NgReactGridCheckboxComponent = (function() {
2 | var NgReactGridCheckboxComponent = React.createClass({
3 | getInitialState: function() {
4 | var disableCheckboxField = this.props.options.disableCheckboxField;
5 | var disableCheckboxFieldValue = this.props.utils.getObjectPropertyByStringFn(this.props.row, disableCheckboxField);
6 | return {
7 | checked: false,
8 | disabled: disableCheckboxFieldValue ? disableCheckboxFieldValue : false
9 | }
10 | },
11 |
12 | handleClick: function(e) {
13 | var checkedStateValue = this.state.checked ? false : true;
14 | this.setState({
15 | checked: checkedStateValue
16 | });
17 | this.props.handleToggle(e, checkedStateValue);
18 | },
19 | setNgReactGridCheckboxStateFromEvent: function(e) {
20 | if (!this.state.disabled) {
21 | // Target rows with specified field value
22 | if (e.detail.targetCheckboxes.key) {
23 | var checkedStateValue = this.state.checked;
24 | var fieldValue =
25 | this.props.utils.getObjectPropertyByStringFn(
26 | this.props.row,
27 | e.detail.targetCheckboxes.key
28 | );
29 | if (fieldValue && fieldValue === e.detail.targetCheckboxes.value) {
30 | checkedStateValue = e.detail.checked;
31 | }
32 | this.setState({
33 | checked: checkedStateValue
34 | });
35 | this.props.handleToggle(e, checkedStateValue);
36 | } else { // Target all rows
37 | this.setState({
38 | checked: e.detail.checked
39 | });
40 | this.props.handleToggle(e, e.detail.checked);
41 | }
42 | }
43 | },
44 | componentWillReceiveProps: function(nextProps) {
45 | var disableCheckboxField = nextProps.options.disableCheckboxField;
46 | var disableCheckboxFieldValue = nextProps.utils.getObjectPropertyByStringFn(nextProps.row, disableCheckboxField);
47 | this.setState({
48 | checked: (nextProps.selectionTarget.indexOf(nextProps.row) === -1) ? false : true,
49 | disabled: disableCheckboxFieldValue ? disableCheckboxFieldValue : false
50 | });
51 | },
52 | componentDidMount: function() {
53 | window.addEventListener("setNgReactGridCheckboxStateFromEvent", this.setNgReactGridCheckboxStateFromEvent);
54 | },
55 | componentWillUnmount: function() {
56 | window.removeEventListener("setNgReactGridCheckboxStateFromEvent", this.setNgReactGridCheckboxStateFromEvent);
57 | },
58 | render: function() {
59 | var hideDisabledCheckboxField = this.props.options.hideDisabledCheckboxField;
60 |
61 | if (this.state.disabled && hideDisabledCheckboxField) {
62 | return (
63 |
64 | )
65 | } else {
66 | return (
67 |
68 |
69 |
70 | )
71 | }
72 | }
73 | });
74 |
75 | return NgReactGridCheckboxComponent;
76 | })();
77 |
--------------------------------------------------------------------------------
/src/js/factories/ngReactGridCheckboxFactory.js:
--------------------------------------------------------------------------------
1 | var _ = require('../vendors/miniUnderscore');
2 | var NgReactGridReactManager = require("../classes/NgReactGridReactManager");
3 |
4 | var ngReactGridCheckboxFactory = function($rootScope) {
5 | var ngReactGridCheckbox = function(selectionTarget, options) {
6 | var defaultOptions = {
7 | disableCheckboxField: '',
8 | hideDisabledCheckboxField: false,
9 | batchToggle: false,
10 | headerStyle: {
11 | textAlign: "center"
12 | }
13 | };
14 | var _options = _.extend({}, defaultOptions, options);
15 | var utils = {
16 | getObjectPropertyByStringFn: NgReactGridReactManager.getObjectPropertyByString,
17 | };
18 |
19 | return {
20 | field: "",
21 | fieldName: "",
22 | displayName: "",
23 | title: "Select/Deselect All",
24 | options: _options,
25 | utils: utils,
26 | setAllCheckboxStates: this.setAllCheckboxStates,
27 | setHeaderCheckboxState: this.setHeaderCheckboxState,
28 | setVisibleCheckboxState: this.setVisibleCheckboxState,
29 | inputType: (_options.batchToggle) ? "checkbox" : undefined,
30 | handleHeaderClick: function(checkedValue, data) {
31 | this.setVisibleCheckboxState(checkedValue);
32 |
33 | // Empties bounded selected target or populates with
34 | // non-disabled checkbox rows data
35 | $rootScope.$apply(function() {
36 | while (selectionTarget.length) {selectionTarget.pop();}
37 | if (checkedValue) {
38 | data.forEach(function(row) {
39 | if (!utils.getObjectPropertyByStringFn(row, _options.disableCheckboxField)) {
40 | selectionTarget.push(row);
41 | }
42 | });
43 | }
44 | });
45 | },
46 | render: function(row) {
47 | var handleToggle = (function(e, checkedValue) {
48 | e.stopPropagation();
49 |
50 | // Sends event to uncheck header 'batch toggle' checkbox
51 | this.setHeaderCheckboxState(false);
52 |
53 | var index = selectionTarget.indexOf(row);
54 | if(index === -1) {
55 | if (checkedValue) {selectionTarget.push(row);}
56 | } else {
57 | if (!checkedValue) {selectionTarget.splice(index, 1);}
58 | }
59 | }).bind(this);
60 | var ngReactGridCheckboxElement = React.createFactory(NgReactGridCheckboxComponent);
61 | return ngReactGridCheckboxElement({selectionTarget: selectionTarget, handleToggle: handleToggle, row: row, utils: this.utils, options: this.options});;
62 | },
63 | sort: false,
64 | width: 1
65 | }
66 | };
67 |
68 | ngReactGridCheckbox.prototype.setHeaderCheckboxState = function(checkedValue) {
69 | window.dispatchEvent(new CustomEvent("setNgReactGridCheckboxHeaderStateFromEvent", {detail: {checked: checkedValue}}));
70 | };
71 |
72 | ngReactGridCheckbox.prototype.setVisibleCheckboxState = function(checkedValue, options) {
73 | var defaultOptions = {
74 | checked: checkedValue,
75 | targetCheckboxes: {
76 | key: null,
77 | value: null
78 | }
79 | };
80 | var _options = _.extend({}, defaultOptions, options);
81 | window.dispatchEvent(new CustomEvent("setNgReactGridCheckboxStateFromEvent", {detail: _options}));
82 | };
83 |
84 | return ngReactGridCheckbox;
85 | };
86 |
87 | module.exports = ngReactGridCheckboxFactory;
88 |
--------------------------------------------------------------------------------
/examples/basic.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ngReactGrid Basic Example
5 |
6 |
7 |
8 |
9 |
10 | Toggle Visible Checkboxes
11 | Edit Grid
12 | Save Grid
13 | Cancel
14 |
15 | Selections: {{selections}}
16 | Clicked On Record: {{clickedOnRecord}}
17 |
18 |
19 |
21 |
22 |
23 |
24 |
137 |
138 |
139 |
--------------------------------------------------------------------------------
/src/css/ngReactGrid.css:
--------------------------------------------------------------------------------
1 | .ngReactGrid {
2 | font-size: 12px;
3 | font-family: "Open Sans", "Helvetica Neue", "Helvetica", "Arial", "Droid Arabic Kufi","Droid Sans";
4 | padding: 5px;
5 | }
6 |
7 | .ngReactGrid table {
8 | position: relative;
9 | table-layout: fixed;
10 | background-color: #FFF;
11 | margin: 0;
12 | padding: 0;
13 | color: #555555;
14 | display: table;
15 | border: 1px solid #CCC;
16 | border-spacing: 0;
17 | width: 100%;
18 | }
19 |
20 | .ngReactGrid .ngReactGridViewPort {
21 | overflow-y: scroll;
22 | overflow-x: scroll;
23 | }
24 |
25 | .ngReactGrid .ngReactGridHeader {
26 | overflow-x: hidden;
27 | position: relative;
28 | overflow-y: hidden;
29 | }
30 |
31 | .ngReactGrid .ngGridHeaderCellText {
32 | display:inline-block;
33 | width: 90%;
34 | float: left;
35 | -webkit-touch-callout: none;
36 | -webkit-user-select: none;
37 | -khtml-user-select: none;
38 | -moz-user-select: none;
39 | -ms-user-select: none;
40 | user-select: none;
41 | }
42 |
43 | .ngReactGrid .ngGridHeaderCellResize {
44 | width: 5%;
45 | float: left;
46 | text-align: right;
47 | }
48 |
49 | .ngReactGrid .ngReactGridHeaderToolbarWrapper {
50 | overflow: auto;
51 | }
52 |
53 | .ngReactGrid .ngReactGridShowPerPage {
54 | float: left;
55 | width: 50%;
56 | }
57 |
58 | .ngReactGrid .ngReactGridSearch {
59 | float: left;
60 | width: 50%;
61 | text-align: right;
62 | }
63 |
64 | .ngReactGrid .ngReactGridSearch input {
65 | width: 50%;
66 | border-radius: 15px;
67 | border: 1px solid #CCC;
68 | padding: 5px;
69 | padding-left: 9px;
70 | outline: none;
71 | }
72 |
73 | .ngReactGrid .ngReactGridHeaderWrapper {
74 | margin-top: 5px;
75 | }
76 |
77 | .ngReactGrid .ngReactGridHeaderInner {
78 | overflow-x: hidden;
79 | overflow-y: hidden;
80 | }
81 |
82 | .ngReactGrid .ngReactGridHeaderInner table {
83 | line-height: 15px;
84 | }
85 |
86 | .ngReactGrid .ngReactGridHeaderInner table thead {
87 | font-style: normal;
88 | }
89 |
90 | .ngReactGrid .ngReactGridBody table {
91 | border-top: none;
92 | border-bottom: none;
93 | }
94 |
95 | .ngReactGrid table tr {
96 | border-collapse: collapse;
97 | -webkit-box-sizing: border-box;
98 | -moz-box-sizing: border-box;
99 | -ms-box-sizing: border-box;
100 | box-sizing: border-box;
101 | -webkit-transition: all .1s ease-out;
102 | -moz-transition: all .1s ease-out;
103 | transition: all .1s ease-out;
104 | }
105 |
106 | .ngReactGrid table td, .ngReactGrid table th {
107 | border-left: 1px solid #CCC;
108 | vertical-align: top;
109 | }
110 |
111 | .ngReactGrid table th {
112 | cursor: auto;
113 | text-align: left;
114 | color: rgba(0,0,0,.8);
115 | padding: 0px;
116 | padding: 5px;
117 | display: table-cell;
118 | }
119 |
120 | .ngReactGrid table th div {
121 | white-space: nowrap;
122 | overflow: hidden;
123 | text-overflow: ellipsis;
124 | }
125 |
126 | .ngReactGrid table td {
127 | padding: 0px;
128 | vertical-align: middle;
129 | text-align: left;
130 | padding: 5px;
131 | display: table-cell;
132 | word-wrap: break-word;
133 | }
134 |
135 | .ngReactGrid table tr:nth-child(odd) td {
136 | background: #f5f5f5;
137 | }
138 |
139 | .ngReactGrid table tr:last-child td {
140 | border-bottom: 1px solid #CCC;
141 | }
142 |
143 | .ngReactGrid table tr td:first-child, .ngReactGrid table tr th:first-child {
144 | border-left: none;
145 | }
146 |
147 | .ngReactGrid .ngReactGridFooter, .ngReactGrid table th, .ngReactGrid h1, .ngReactGrid .ngReactGridHeaderWrapper {
148 | background: #ffffff; /* Old browsers */
149 | background: -moz-linear-gradient(top, #ffffff 0%, #eeeeee 100%, #7db9e8 100%); /* FF3.6+ */
150 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#ffffff), color-stop(100%,#eeeeee), color-stop(100%,#7db9e8)); /* Chrome,Safari4+ */
151 | background: -webkit-linear-gradient(top, #ffffff 0%,#eeeeee 100%,#7db9e8 100%); /* Chrome10+,Safari5.1+ */
152 | background: -o-linear-gradient(top, #ffffff 0%,#eeeeee 100%,#7db9e8 100%); /* Opera 11.10+ */
153 | background: -ms-linear-gradient(top, #ffffff 0%,#eeeeee 100%,#7db9e8 100%); /* IE10+ */
154 | background: linear-gradient(to bottom, #ffffff 0%,#eeeeee 100%,#7db9e8 100%); /* W3C */
155 | filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#7db9e8',GradientType=0 ); /* IE6-9 */
156 | }
157 |
158 | .ngReactGrid .ngReactGridFooter {
159 | border: 1px solid #CCC;
160 | padding: 5px;
161 | font-size: 11px;
162 | overflow: auto;
163 | }
164 |
165 | .icon-arrows {
166 | display: inline-block;
167 | margin-top: 1px;
168 | line-height: 14px;
169 | vertical-align: text-top;
170 | background-image: url("../img/glyphicons-halflings.png");
171 | background-repeat: no-repeat;
172 | background-image: url('../img/arrow_icons.png');
173 | background-repeat: no-repeat;
174 | width: 7px;
175 | height: 10px;
176 | }
177 |
178 | .icon-both {
179 | background-position: -128px 2px;
180 | }
181 |
182 | .icon-asc {
183 | background-position: 0 0;
184 | }
185 |
186 | .icon-desc {
187 | background-position: -65px 0;
188 | }
189 |
190 | .ngReactGrid .ngReactGridStatus {
191 | float: left;
192 | width: 50%;
193 | padding-top: 4px;
194 | }
195 |
196 | .ngReactGrid .ngReactGridPagination {
197 | float: left;
198 | width: 50%;
199 | }
200 |
201 | .ngReactGridPagination ul {
202 | display: inline-block;
203 | padding-left: 0;
204 | margin: 0;
205 | border-radius: 4px;
206 | float: right;
207 | }
208 |
209 | .ngReactGridPagination ul li {
210 | display: inline;
211 | }
212 |
213 | .ngReactGridPagination ul li:hover a {
214 | background: #EEE;
215 | }
216 |
217 | .ngReactGridPagination ul li.active a {
218 | background: #428bca;
219 | color: #FFF;
220 | }
221 |
222 | .ngReactGridPagination ul li a {
223 | position: relative;
224 | float: left;
225 | padding: 3px 9px;
226 | line-height: 1.42857143;
227 | text-decoration: none;
228 | color: #428bca;
229 | background-color: #fff;
230 | border: 1px solid #ddd;
231 | margin-left: -1px;
232 | font-size:11px;
233 | }
234 |
235 | .ngReactTextField {
236 | margin:0;
237 | width: calc(90% - 4px);
238 | outline: none;
239 | padding: 4px;
240 | }
241 |
242 | .ngReactGridSelectField {
243 | width: calc(100% - 4px);
244 | }
245 |
--------------------------------------------------------------------------------
/src/js/classes/NgReactGridReactManager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This class is the bridge between the ngReactGrid class and React
3 | * @param ngReactGrid
4 | * @constructor
5 | */
6 | var NgReactGridReactManager = function (ngReactGrid) {
7 | /**
8 | * Reference to the ngReactGrid main class
9 | */
10 | this.ngReactGrid = ngReactGrid;
11 |
12 | /**
13 | * How many records we are currently showing with filters, search, pageSize and pagination applied
14 | * @type {number}
15 | */
16 | this.showingRecords = 0;
17 |
18 | /**
19 | * The starting index by which we are filtering the local data
20 | * @type {number}
21 | */
22 | this.startIndex = 0;
23 |
24 | /**
25 | * The end index by which we are filtering local data
26 | * @type {number}
27 | */
28 | this.endIndex = 0;
29 |
30 | /**
31 | * This is a copy of the data given to ngReactGrid (local data only)
32 | * @type {Array}
33 | */
34 | this.originalData = [];
35 |
36 | /**
37 | * This is a copy of the data given to ngReactGrid whenever it is filtered (local data only)
38 | * @type {Array}
39 | */
40 | this.filteredData = [];
41 |
42 | /**
43 | * Values of all filter fields
44 | * @type {Object}
45 | */
46 | this.filterValues = {};
47 |
48 | /**
49 | * This is a copy of the pagination-independent viewable data in table that
50 | * can be affected by filter and sort
51 | * @type {Array}
52 | */
53 | this.filteredAndSortedData = [];
54 |
55 | /**
56 | * Loading indicator
57 | * @type {boolean}
58 | */
59 | this.loading = false;
60 |
61 | /**
62 | * Instance pointer to a static function
63 | * @type {Function}
64 | */
65 | this.getObjectPropertyByString = NgReactGridReactManager.getObjectPropertyByString;
66 | };
67 |
68 | /**
69 | * This function is used to add API to the grid object created by the user.
70 | * @param gridObject
71 | */
72 | NgReactGridReactManager.prototype.mixinAPI = function(gridObject) {
73 | var self = this;
74 |
75 | /**
76 | * Get filtered and sorted data
77 | */
78 | gridObject.getFilteredAndSortedData = function() {
79 | return self.getFilteredAndSortedData.call(self);
80 | };
81 | };
82 |
83 | /**
84 | * Get table data wrapper
85 | */
86 | NgReactGridReactManager.prototype.getFilteredAndSortedData = function() {
87 | return this.filteredAndSortedData;
88 | };
89 |
90 | /**
91 | * Page size setter, this is called for the NgReactGridComponent (React class)
92 | * @param pageSize
93 | */
94 | NgReactGridReactManager.prototype.setPageSize = function (pageSize) {
95 |
96 | var update = {
97 | pageSize: pageSize,
98 | currentPage: 1
99 | };
100 |
101 | /*
102 | * Is there a search in place
103 | */
104 | if (this.ngReactGrid.isSearching()) {
105 | update.data = this.filteredData;
106 | }
107 |
108 | /**
109 | * Send the update event to the main class
110 | */
111 | this.ngReactGrid.update(this.ngReactGrid.events.PAGESIZE, update);
112 |
113 | /**
114 | * If we are in server mode, call getData
115 | */
116 | if (this.ngReactGrid.isServerMode()) {
117 | this.ngReactGrid.getData();
118 | }
119 | };
120 |
121 | /**
122 | * Sorting callback, this is called from the NgReactGridComponent whenever a header cell is clicked (and is sortable)
123 | * @param field
124 | */
125 | NgReactGridReactManager.prototype.setSortField = function (field) {
126 |
127 | /**
128 | * The initial update to the grid
129 | * @type {{sortInfo: {field: string, dir: string}}}
130 | */
131 | var update = {
132 | sortInfo: {
133 | field: field,
134 | dir: ""
135 | }
136 | };
137 |
138 | /**
139 | * Are we sorting on a new field
140 | */
141 | if (this.ngReactGrid.sortInfo.field !== field) {
142 | update.sortInfo.dir = "asc";
143 | } else {
144 | /**
145 | * Switch the sorting direction
146 | */
147 | if (this.ngReactGrid.sortInfo.dir === "asc") {
148 | update.sortInfo.dir = "desc";
149 | } else {
150 | update.sortInfo.dir = "asc";
151 | }
152 |
153 | }
154 |
155 | /**
156 | * Call getData for Server Mode or perform a local sort
157 | */
158 | if (this.ngReactGrid.isServerMode()) {
159 | this.ngReactGrid.update(this.ngReactGrid.events.SORTING, update);
160 | this.ngReactGrid.getData();
161 | } else {
162 | this.performLocalSort(update);
163 | }
164 | };
165 |
166 | /**
167 | * Simple asc -> desc, desc -> asc sorting, used for local data, resets the current page to 1
168 | * @param update
169 | */
170 | NgReactGridReactManager.prototype.performLocalSort = function (update) {
171 | var copy;
172 |
173 | if (this.ngReactGrid.isSearching()) {
174 | copy = this.filteredData;
175 | } else {
176 | copy = this.originalData.slice(0);
177 | }
178 |
179 | var isAsc = update.sortInfo.dir === "asc";
180 |
181 | copy.sort(function (a, b) {
182 | var aField = this.getObjectPropertyByString(a, update.sortInfo.field);
183 | var bField = this.getObjectPropertyByString(b, update.sortInfo.field);
184 |
185 | if (isAsc) {
186 | return aField <= bField ? -1 : 1;
187 | } else {
188 | return aField >= bField ? -1 : 1;
189 | }
190 | }.bind(this));
191 |
192 | update.data = copy;
193 | update.currentPage = 1;
194 |
195 | this.ngReactGrid.update(this.ngReactGrid.events.SORTING, update);
196 | };
197 |
198 | /**
199 | * This is a recursive search function that will transverse an object searching for an index of a string
200 | * @param obj
201 | * @param search
202 | * @param (Optional) column
203 | * @returns {boolean}
204 | */
205 | NgReactGridReactManager.prototype.deepSearch = function(obj, search, column) {
206 | var found = false;
207 |
208 | if (obj) {
209 | for (var i in obj) {
210 | if (obj.hasOwnProperty(i)) {
211 |
212 | var prop = obj[i];
213 |
214 | if (typeof prop === "object") {
215 | found = this.deepSearch(prop, search, column);
216 | if (found === true) break;
217 | } else {
218 | if (column && column !== '_global') {
219 | if (i !== column.split('.').pop()) continue;
220 | }
221 | if (String(obj[i]).toLowerCase().indexOf(search.toLowerCase()) !== -1) {
222 | found = true;
223 | break;
224 | }
225 | }
226 |
227 |
228 | }
229 | }
230 | }
231 |
232 | return found;
233 | };
234 |
235 | /**
236 | * Search callback for everytime the user updates the search box.
237 | * Supports local mode and server mode; local mode only for column search.
238 | * @param search
239 | * @param (Optional) column
240 | */
241 | NgReactGridReactManager.prototype.setSearch = function (search, column) {
242 | var column = column ? column : '_global';
243 | this.filterValues[column] = search;
244 |
245 | var update = {
246 | search: search
247 | };
248 |
249 | if (this.ngReactGrid.isLocalMode()) {
250 | this.filteredData = this.originalData.slice(0);
251 | for (var column in this.filterValues) {
252 | if (this.filterValues.hasOwnProperty(column)) {
253 | this.filteredData = this.filteredData.filter(function (obj) {
254 | var found = false;
255 | found = this.deepSearch(obj, this.filterValues[column], column);
256 | return found;
257 | }.bind(this));
258 | }
259 | }
260 |
261 | update.data = this.filteredData;
262 | update.currentPage = 1;
263 |
264 | this.ngReactGrid.update(this.ngReactGrid.events.SEARCH, update);
265 | } else {
266 | this.ngReactGrid.search = search;
267 | this.ngReactGrid.getData();
268 | }
269 | };
270 |
271 | /**
272 | * Pagination call back, called every time a pagination change is made
273 | * @param page
274 | */
275 | NgReactGridReactManager.prototype.goToPage = function (page) {
276 |
277 | var update = {
278 | currentPage: page
279 | };
280 |
281 | this.ngReactGrid.update(this.ngReactGrid.events.PAGINATION, update);
282 |
283 | if (this.ngReactGrid.isServerMode()) {
284 | this.ngReactGrid.getData();
285 | }
286 | };
287 |
288 | /**
289 | * Row click callback
290 | * @param row
291 | */
292 | NgReactGridReactManager.prototype.rowClick = function(row) {
293 | this.ngReactGrid.rowClick(row);
294 | };
295 |
296 | /**
297 | * This function is called from React to make sure that any callbacks being passed into react cell components, update the
298 | * angular scope
299 | * @param cell
300 | * @returns {*}
301 | */
302 | NgReactGridReactManager.prototype.wrapFunctionsInAngular = function (cell) {
303 | for (var key in cell.props) {
304 | if (cell.props.hasOwnProperty(key)) {
305 | if (key === "children" && cell.props[key]) {
306 | this.wrapFunctionsInAngular(cell.props[key]);
307 | } else if (typeof cell.props[key] === 'function') {
308 | cell.props[key] = this.wrapWithRootScope(cell.props[key]);
309 | }
310 | }
311 |
312 | }
313 | return cell;
314 | };
315 |
316 | /**
317 | * This is the wrapping function on all callbacks passed into the React cell components for ngReactGrid
318 | * @param func
319 | * @returns {Function}
320 | */
321 | NgReactGridReactManager.prototype.wrapWithRootScope = function (func) {
322 | var self = this;
323 | return function () {
324 | var args = arguments;
325 | var phase = self.ngReactGrid.rootScope.$$phase;
326 |
327 | if (phase == '$apply' || phase == '$digest') {
328 | func.apply(null, args);
329 | } else {
330 | self.ngReactGrid.rootScope.$apply(function () {
331 | func.apply(null, args);
332 | });
333 | }
334 | };
335 | };
336 |
337 | /**
338 | * This function allows you to get a property from any object, no matter how many levels deep it is
339 | * MOVE THIS FUNCTION INTO ITS OWN CLASS
340 | * @param object
341 | * @param str
342 | * @static
343 | * @returns {*}
344 | */
345 | NgReactGridReactManager.getObjectPropertyByString = function (object, str) {
346 |
347 | /**
348 | * Convert indexes to properties
349 | */
350 | str = str.replace(/\[(\w+)\]/g, '.$1');
351 |
352 | /**
353 | * Strip a leading dot
354 | */
355 | str = str.replace(/^\./, '');
356 | var a = str.split('.');
357 | while (a.length) {
358 | var n = a.shift();
359 | if (object != null && n in object) {
360 | object = object[n];
361 | } else {
362 | return;
363 | }
364 | }
365 | return object;
366 | };
367 |
368 | /**
369 | * Updates an object property given a specified path, it will create the object if it doesn't exist
370 | * @static
371 | * @param obj
372 | * @param path
373 | * @param value
374 | */
375 | NgReactGridReactManager.updateObjectPropertyByString = function(obj, path, value) {
376 | var a = path.split('.');
377 | var o = obj;
378 | for (var i = 0; i < a.length - 1; i++) {
379 | var n = a[i];
380 | if (n in o) {
381 | o = o[n];
382 | } else {
383 | o[n] = {};
384 | o = o[n];
385 | }
386 | }
387 | o[a[a.length - 1]] = value;
388 | };
389 |
390 | module.exports = NgReactGridReactManager;
391 |
--------------------------------------------------------------------------------
/src/js/classes/ngReactGrid.js:
--------------------------------------------------------------------------------
1 | var _ = require('../vendors/miniUnderscore');
2 | var NgReactGridReactManager = require("./NgReactGridReactManager");
3 | var NgReactGridEditManager = require("./NgReactGridEditManager");
4 | var NO_GET_DATA_CALLBACK_ERROR = "localMode is false, please implement the getData function on the grid object";
5 |
6 | /**
7 | * NgReactGrid - Main class
8 | * @param scope
9 | * @param element
10 | * @param attrs
11 | * @param $rootScope
12 | * @constructor
13 | */
14 | var NgReactGrid = function (scope, element, attrs, $rootScope) {
15 | this.columnDefs = scope.grid.columnDefs || [];
16 | this.data = [];
17 | this.height = 400;
18 | this.localMode = true;
19 | this.editing = false;
20 | this.singleLineCell = false;
21 | this.totalCount = 0;
22 | this.totalPages = 0;
23 | this.currentPage = 1;
24 | this.rowClick = function() {};
25 | this.pageSize = 25;
26 | this.pageSizes = [25, 50, 100, 500];
27 | this.sortInfo = {field: "", dir: ""};
28 | this.showGridSearch = true;
29 | this.showGridShowPerPage = true;
30 | this.search = "";
31 | this.horizontalScroll = false;
32 | this.scrollbarWidth = this.getScrollbarWidth();
33 | this.scope = scope;
34 | this.element = element;
35 | this.attrs = attrs;
36 | this.rootScope = $rootScope;
37 |
38 | /**
39 | * Initialize the NgReactGridReact class
40 | */
41 | this.react = new NgReactGridReactManager(this);
42 | this.editManager = new NgReactGridEditManager(this);
43 |
44 | /**
45 | * Initialize events
46 | */
47 | this.setupUpdateEvents();
48 |
49 | /**
50 | * Initialize scope watchers
51 | */
52 | this.initWatchers();
53 |
54 | /**
55 | * Init the grid
56 | */
57 | this.init();
58 | };
59 |
60 | /**
61 | * Init function for NgReactGrid, decides whether to getData or render with local data
62 | */
63 | NgReactGrid.prototype.init = function () {
64 |
65 | /**
66 | * Check if getData is set, override with our own and keep a private copy
67 | */
68 | if (typeof this.scope.grid.localMode && this.scope.grid.localMode === false) {
69 | if (this.scope.grid.getData) {
70 | this._getData = this.scope.grid.getData;
71 | delete this.scope.grid.getData;
72 | } else {
73 | throw new Error(NO_GET_DATA_CALLBACK_ERROR);
74 | }
75 | }
76 |
77 | _.extend(this, this.scope.grid);
78 |
79 | /**
80 | * Provide API interfaces
81 | */
82 | this.react.mixinAPI(this.scope.grid);
83 | this.editManager.mixinAPI(this.scope.grid);
84 |
85 | /**
86 | * If we are in server mode, perform the first call to load the data, and add refresh API
87 | */
88 | if (this.isServerMode()) {
89 | this.getData();
90 | this.addRefreshAPI();
91 | } else {
92 | this.updateData({
93 | data: this.data
94 | });
95 | }
96 |
97 | this.render();
98 |
99 | };
100 |
101 | /**
102 | * Get data wrapper, at the moment it doesn't do much but expect some hooks and functionality being added in the future
103 | */
104 | NgReactGrid.prototype.getData = function () {
105 | this.react.loading = true;
106 | this._getData(this);
107 | this.render();
108 | };
109 |
110 | /**
111 | * This function mixes in the "refresh" API method that can be used in server mode grids.
112 | */
113 | NgReactGrid.prototype.addRefreshAPI = function () {
114 | var self = this;
115 |
116 | this.scope.grid.refresh = function () {
117 | self.getData.call(self);
118 | };
119 | };
120 |
121 | /**
122 | * This is called once during initialization to figure out the width of the scrollbars
123 | * @returns {number}
124 | */
125 | NgReactGrid.prototype.getScrollbarWidth = function () {
126 | var outer = document.createElement("div");
127 | outer.style.visibility = "hidden";
128 | outer.style.width = "100px";
129 |
130 | /**
131 | * Needed for WinJS apps
132 | * @type {string}
133 | */
134 | outer.style.msOverflowStyle = "scrollbar";
135 |
136 | document.body.appendChild(outer);
137 |
138 | var widthNoScroll = outer.offsetWidth;
139 |
140 | /*
141 | * Force scroll bars
142 | */
143 | outer.style.overflow = "scroll";
144 |
145 | /*
146 | * Add innerDiv
147 | */
148 | var inner = document.createElement("div");
149 | inner.style.width = "100%";
150 | outer.appendChild(inner);
151 |
152 | var widthWithScroll = inner.offsetWidth;
153 |
154 | /**
155 | * Remove divs
156 | */
157 | outer.parentNode.removeChild(outer);
158 |
159 | return widthNoScroll - widthWithScroll;
160 | };
161 |
162 | /**
163 | * Returns whether there is an active search on the grid
164 | * @returns {string|boolean}
165 | */
166 | NgReactGrid.prototype.isSearching = function () {
167 | return this.search && this.search.length > 0;
168 | };
169 |
170 | /**
171 | * Returns whether the grid is in local mode
172 | * @returns {boolean|*}
173 | */
174 | NgReactGrid.prototype.isLocalMode = function () {
175 | return this.localMode;
176 | };
177 |
178 | /**
179 | * Returns whether the grid is in server mode
180 | * @returns {boolean}
181 | */
182 | NgReactGrid.prototype.isServerMode = function () {
183 | return !this.localMode;
184 | };
185 |
186 | /**
187 | * Manages the different events that can update the grid
188 | */
189 | NgReactGrid.prototype.setupUpdateEvents = function () {
190 | this.events = {
191 | COLUMN_DEF: "COLUMN_DEF",
192 | PAGESIZE: "PAGESIZE",
193 | SORTING: "SORTING",
194 | SEARCH: "SEARCH",
195 | PAGINATION: "PAGINATION",
196 | DATA: "DATA",
197 | TOTALCOUNT: "TOTALCOUNT",
198 | COLUMNS: "COLUMNS"
199 | };
200 | };
201 |
202 | /**
203 | * Initializes the scope watchers needed for the grid
204 | */
205 | NgReactGrid.prototype.initWatchers = function () {
206 | this.scope.$watchCollection("grid.data", function (newValue, oldValue) {
207 | if (newValue !== oldValue) {
208 | if (this.isServerMode() && this.react.loading) {
209 | this.react.loading = false;
210 | }
211 |
212 | this.update(this.events.DATA, {
213 | data: newValue
214 | });
215 | }
216 | }.bind(this));
217 |
218 | this.scope.$watchCollection("grid.columnDefs", function (newValue, oldValue) {
219 | if (newValue !== oldValue) {
220 | this.update(this.events.COLUMN_DEF, {
221 | // Resets column filter fields
222 | filterValues: {}
223 | });
224 | this.update(this.events.COLUMNS, {columnDefs: newValue});
225 | }
226 | }.bind(this), true);
227 |
228 | this.scope.$watch("grid.totalCount", function (newValue) {
229 | if (newValue) {
230 | this.update(this.events.TOTALCOUNT, {totalCount: newValue});
231 | }
232 | }.bind(this));
233 | };
234 |
235 | /**
236 | * Updates the grid model, re-renders the react component
237 | * @param updateEvent
238 | * @param updates
239 | */
240 | NgReactGrid.prototype.update = function (updateEvent, updates) {
241 | switch (updateEvent) {
242 | case this.events.COLUMN_DEF:
243 | this.updateColumnDef(updates);
244 | break;
245 |
246 | case this.events.DATA:
247 | this.updateData(updates);
248 | break;
249 |
250 | case this.events.PAGESIZE:
251 | this.updatePageSize(updates);
252 | break;
253 |
254 | case this.events.PAGINATION:
255 | this.updatePagination(updates);
256 | break;
257 |
258 | case this.events.SEARCH:
259 | this.updateSearch(updates);
260 | break;
261 |
262 | case this.events.SORTING:
263 | this.updateSorting(updates);
264 | break;
265 |
266 | case this.events.TOTALCOUNT:
267 | this.updateTotalCount(updates);
268 | break;
269 |
270 | case this.events.COLUMNS:
271 | this.updateColumns(updates);
272 | break;
273 | }
274 |
275 | this.render();
276 |
277 | };
278 |
279 | /**
280 | * This function updates the necessary properties for a successful column def update
281 | * @param updates
282 | */
283 | NgReactGrid.prototype.updateColumnDef = function (updates) {
284 | this.react.filterValues = updates.filterValues;
285 | };
286 |
287 | /**
288 | * This function takes care of updating all data related properties. The second param will not the update the originalData
289 | * property in the react manager
290 | * @param updates
291 | * @param updateContainsData
292 | */
293 | NgReactGrid.prototype.updateData = function (updates, updateContainsData) {
294 |
295 | this.react.startIndex = (this.currentPage - 1) * this.pageSize;
296 | this.react.endIndex = (this.pageSize * this.currentPage);
297 |
298 | if (this.isLocalMode()) {
299 | if (updateContainsData) {
300 |
301 | this.data = updates.data.slice(this.react.startIndex, this.react.endIndex);
302 | this.react.filteredAndSortedData = updates.data.slice(0);
303 | this.totalCount = updates.data.length;
304 |
305 | } else {
306 | this.react.originalData = updates.data.slice(0);
307 | this.totalCount = this.react.originalData.length;
308 | this.data = this.react.originalData.slice(this.react.startIndex, this.react.endIndex);
309 | this.react.filteredAndSortedData = this.react.originalData.slice(0);
310 | }
311 |
312 | } else {
313 | this.data = updates.data;
314 | this.react.filteredAndSortedData = this.data.slice(0);
315 | }
316 |
317 | this.react.showingRecords = this.data.length;
318 |
319 | this.totalPages = Math.ceil(this.totalCount / this.pageSize);
320 | };
321 |
322 | /**
323 | * This function updates the necessary properties for a successful page size update
324 | * @param updates
325 | */
326 | NgReactGrid.prototype.updatePageSize = function (updates) {
327 | this.pageSize = updates.pageSize;
328 | this.currentPage = updates.currentPage;
329 | this.updateData({
330 | data: this.react.filteredAndSortedData ? this.react.filteredAndSortedData : this.react.originalData
331 | }, true);
332 | };
333 |
334 | /**
335 | * This function updates the necessary properties for a successful pagination update
336 | * @param updates
337 | */
338 | NgReactGrid.prototype.updatePagination = function (updates) {
339 | this.currentPage = updates.currentPage;
340 | this.updateData({
341 | data: this.react.filteredAndSortedData ? this.react.filteredAndSortedData : this.react.originalData
342 | }, true);
343 | };
344 |
345 | /**
346 | * This function updates the necessary properties for a successful search update
347 | * @param updates
348 | */
349 | NgReactGrid.prototype.updateSearch = function (updates) {
350 | this.search = updates.search;
351 | this.currentPage = 1;
352 | this.updateData({
353 | data: updates.data
354 | }, true);
355 | };
356 |
357 | /**
358 | * This function updates the necessary properties for a successful sorting update
359 | * @param updates
360 | */
361 | NgReactGrid.prototype.updateSorting = function (updates) {
362 | this.sortInfo = updates.sortInfo;
363 |
364 | if (updates.data) {
365 | this.currentPage = 1;
366 | this.updateData({
367 | data: updates.data
368 | }, true);
369 | }
370 | };
371 |
372 | /**
373 | * This function updates the necessary properties for a successful total count update
374 | * @param updates
375 | */
376 | NgReactGrid.prototype.updateTotalCount = function (updates) {
377 | this.totalCount = updates.totalCount;
378 | this.totalPages = Math.ceil(this.totalCount / this.pageSize);
379 | };
380 |
381 | /**
382 | * This function updates requested visible columns ( columnDefs object )
383 | * @param updates
384 | */
385 | NgReactGrid.prototype.updateColumns = function (updates) {
386 | this.columnDefs = updates.columnDefs;
387 | };
388 |
389 | /**
390 | * Calls React to render the grid component on the given element
391 | */
392 | NgReactGrid.prototype.render = function () {
393 | // React.renderComponent(ngReactGridComponent({grid: this}), this.element[0]);
394 | var ngReactGridElement = React.createFactory(NgReactGridComponent);
395 | React.render(ngReactGridElement({grid: this}), this.element[0]);
396 | };
397 |
398 | module.exports = NgReactGrid;
399 |
--------------------------------------------------------------------------------
/src/jsx/reactGrid.jsx:
--------------------------------------------------------------------------------
1 | /**
2 | * NgReactGridComponent - React Component
3 | **/
4 | var NgReactGridComponent = (function() {
5 | var windowInnerWidth = window.innerWidth, windowInnerHeight = window.innerHeight;
6 |
7 | var setCellWidthPixels = function(cell) {
8 |
9 | var width = String(cell.width).replace("px", "");
10 | var isPercent = width.indexOf("%") !== -1;
11 |
12 | if(isPercent) {
13 |
14 | var widthInPixels = Math.floor((parseInt(width) * windowInnerWidth) / 100);
15 | cell.width = widthInPixels;
16 |
17 | }
18 |
19 | };
20 |
21 | var setCellWidth = function(grid, cell, cellStyle, isLast, bodyCell) {
22 |
23 | if(!cell.width) {
24 | cell.width = "10%";
25 | }
26 |
27 | if(grid.horizontalScroll) {
28 | setCellWidthPixels(cell);
29 | }
30 |
31 | cellStyle.width = cell.width;
32 | };
33 |
34 | var NgReactGridHeader = (function() {
35 | var hasColumnFilter = function(grid) {
36 | return grid.columnDefs.some(function(cell) {
37 | return cell.columnFilter;
38 | });
39 | };
40 |
41 | var NgGridColumnFilterCell = React.createClass({
42 | handleSearchInputChange: function() {
43 | this.props.onSearchInput(this.refs[this.props.cell.field].getDOMNode().value,
44 | this.props.cell.field);
45 | },
46 | render: function() {
47 | return (
48 |
49 |
53 |
54 | )
55 | }
56 | });
57 |
58 | // For input in header. Expandable to additional types.
59 | var NgGridHeaderCellInput = React.createClass({
60 | getInitialState: function() {
61 | return {
62 | checked: false
63 | };
64 | },
65 | setNgReactGridCheckboxHeaderStateFromEvent: function(e) {
66 | this.setState({
67 | checked: e.detail.checked
68 | });
69 | },
70 | componentDidMount: function() {
71 | window.addEventListener("setNgReactGridCheckboxHeaderStateFromEvent", this.setNgReactGridCheckboxHeaderStateFromEvent);
72 | },
73 | componentWillUnmount: function() {
74 | window.removeEventListener("setNgReactGridCheckboxHeaderStateFromEvent", this.setNgReactGridCheckboxHeaderStateFromEvent);
75 | },
76 | handleCheckboxClick: function(e) {
77 | e.stopPropagation();
78 | var newCheckedValue = (this.state.checked) ? false : true;
79 | this.props.cell.handleHeaderClick(newCheckedValue, this.props.grid.react.getFilteredAndSortedData());
80 | this.setState({
81 | checked: newCheckedValue
82 | });
83 | },
84 | render: function() {
85 | var headerStyle = this.props.cell.options ?
86 | (this.props.cell.options.headerStyle || {}) : {};
87 | if (this.props.cell.inputType !== undefined) {
88 | switch (this.props.cell.inputType) {
89 | case "checkbox":
90 | return (
91 |
92 |
93 |
94 | );
95 | break;
96 | default:
97 | return (
);
98 | }
99 | } else {
100 | return (
);
101 | }
102 | }
103 | });
104 |
105 | var NgGridHeaderCell = React.createClass({
106 | getInitialState: function() {
107 | return {
108 | width: 0
109 | };
110 | },
111 | cellStyle: {},
112 | handleClick: function() {
113 | if (this.props.cell.sort !== false) {
114 | this.props.grid.react.setSortField(this.props.cell.field);
115 | }
116 | },
117 | componentWillReceiveProps: function() {
118 | setCellWidth(this.props.grid, this.props.cell, this.cellStyle, this.props.last);
119 | this.setState({
120 | width: this.cellStyle.width
121 | });
122 | },
123 | componentWillMount: function() {
124 | setCellWidth(this.props.grid, this.props.cell, this.cellStyle, this.props.last);
125 | this.setState({
126 | width: this.cellStyle.width
127 | });
128 | },
129 | resize: function(delta) {
130 | // resize functionality coming soon
131 | },
132 | componentDidMount: function() {
133 | // resize functionality coming soon
134 | },
135 | render: function() {
136 | this.cellStyle.cursor = (this.props.cell.sort !== false) ? "pointer" : "default";
137 | var cellStyle = this.cellStyle;
138 |
139 | var sortStyle = {
140 | cursor: "pointer",
141 | width: "8%",
142 | "float": "left",
143 | textAlign: "right",
144 | display: (this.props.cell.sort === false) ? "none": "inline-block",
145 | overflow: "visible"
146 | };
147 |
148 | var arrowStyle = {
149 | marginTop: 2
150 | };
151 |
152 | var sortClassName = "icon-arrows";
153 |
154 | if(this.props.grid.sortInfo.field === this.props.cell.field) {
155 | if(this.props.grid.sortInfo.dir === "asc") {
156 | sortClassName += " icon-asc";
157 | } else {
158 | sortClassName += " icon-desc";
159 | }
160 |
161 | arrowStyle.marginTop = 5;
162 | } else {
163 | sortClassName += " icon-both";
164 | }
165 |
166 | var resizeStyle = {
167 | height: "21px",
168 | marginTop: "-4px",
169 | width: "1px",
170 | background: "#999999",
171 | borderRight: "1px solid #FFF",
172 | "float": "right"
173 | };
174 |
175 | var resizeWrapperStyle = {
176 | width: "2%",
177 | cursor: "col-resize",
178 | display: "none"
179 | };
180 |
181 | return (
182 |
183 |
184 | {this.props.cell.displayName}
185 |
186 |
187 |
188 |
191 |
192 | )
193 | }
194 | });
195 |
196 | var NgReactGridShowPerPage = React.createClass({
197 | handleChange: function() {
198 | this.props.grid.react.setPageSize(this.refs.showPerPage.getDOMNode().value);
199 | },
200 | render: function() {
201 |
202 | var options = this.props.grid.pageSizes.map(function(pageSize, key) {
203 | return ({pageSize} )
204 | }.bind(this));
205 |
206 | if (this.props.grid.showGridShowPerPage) {
207 | return (
208 |
209 | Show {options} entries
210 |
211 | )
212 | } else {
213 | return (
)
214 | }
215 | }
216 | });
217 |
218 | var NgReactGridSearch = React.createClass({
219 | handleSearch: function() {
220 | this.props.grid.react.setSearch(this.refs.searchField.getDOMNode().value);
221 | },
222 | render: function() {
223 | if (this.props.grid.showGridSearch) {
224 | return (
225 |
226 |
227 |
228 | )
229 | } else {
230 | return (
)
231 | }
232 | }
233 | });
234 |
235 | var NgReactGridColumnFilter = React.createClass({
236 | handleSearch: function(search, column) {
237 | this.props.grid.react.setSearch(search, column);
238 | },
239 | render: function() {
240 | if (hasColumnFilter(this.props.grid) && this.props.grid.localMode) {
241 | var cells = this.props.grid.columnDefs.map(function(cell, key) {
242 | if (cell.columnFilter) {
243 | return ( )
244 | } else {
245 | return ()
246 | }
247 | }.bind(this));
248 |
249 | return (
250 |
251 | {cells}
252 |
253 | )
254 | } else {
255 | return ( )
256 | }
257 | }
258 | });
259 |
260 | var NgReactGridHeader = React.createClass({
261 | render: function() {
262 |
263 | var columnsLength = this.props.grid.columnDefs.length;
264 | var cells = this.props.grid.columnDefs.map(function(cell, key) {
265 | var last = (columnsLength - 1) === key;
266 | return ( )
267 | }.bind(this));
268 |
269 | var tableStyle = {
270 | width: "calc(100% - " + this.props.grid.scrollbarWidth + "px)"
271 | };
272 |
273 | var ngReactGridHeader = {
274 | paddingRight: (this.props.grid.horizontalScroll) ? this.props.grid.scrollbarWidth : 0,
275 | height: hasColumnFilter(this.props.grid) ? "auto" : "27px"
276 | };
277 |
278 | return (
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 | {cells}
291 |
292 |
293 |
294 |
295 |
296 |
297 |
298 |
299 | );
300 | }
301 | });
302 |
303 | return NgReactGridHeader;
304 | })();
305 |
306 | var NgReactGridBody = (function() {
307 |
308 | var NgReactGridBodyRowCell = React.createClass({
309 | cell: function(cellText, cellStyle) {
310 | cellTextType = typeof cellText;
311 |
312 | if(cellTextType === 'string') {
313 | return ({cellText} )
314 | } else if(cellTextType === 'object') {
315 |
316 | cellText = this.props.grid.react.wrapFunctionsInAngular(cellText);
317 |
318 | return (
319 |
320 | {cellText}
321 |
322 | );
323 | } else {
324 | return this.defaultCell;
325 | }
326 | },
327 | render: function() {
328 | var cellText = this.props.grid.react.getObjectPropertyByString(this.props.row, this.props.cell.field);
329 | var cellStyle = {};
330 | setCellWidth(this.props.grid, this.props.cell, cellStyle, this.props.last, true);
331 |
332 | if(this.props.grid.singleLineCell) {
333 | cellStyle.overflow = "hidden";
334 | cellStyle.textOverflow = "ellipsis";
335 | cellStyle.whiteSpace = "nowrap";
336 | }
337 |
338 | if (cellText === null || typeof cellText == 'undefined') {
339 | cellText = '';
340 | }
341 |
342 | this.defaultCell = (
343 |
344 | {String(cellText)}
345 |
346 | );
347 |
348 | if(this.props.grid.editing && this.props.cell.edit) {
349 | cellText = this.props.cell.edit(this.props.row);
350 | return this.cell(cellText, cellStyle);
351 | } else if(this.props.cell.render) {
352 | cellText = this.props.cell.render(this.props.row);
353 | return this.cell(cellText, cellStyle);
354 | } else {
355 | return this.defaultCell;
356 | }
357 |
358 |
359 | }
360 | });
361 |
362 | var NgReactGridBodyRow = React.createClass({
363 | handleClick: function(e) {
364 | // Prevents triggering 'rowClick' event when toggling checkboxes
365 | if (e.target.type !== 'checkbox') {
366 | this.props.grid.react.rowClick(this.props.row);
367 | }
368 | },
369 | render: function() {
370 |
371 | var columnsLength = this.props.grid.columnDefs.length;
372 | var cells = this.props.grid.columnDefs.map(function(cell, key) {
373 | var last = (columnsLength - 1) === key;
374 | return
375 | }.bind(this));
376 |
377 | return (
378 |
379 | {cells}
380 |
381 | )
382 | }
383 | });
384 |
385 |
386 | var NgReactGridBody = React.createClass({
387 | getInitialState: function() {
388 | return {
389 | fullRender: false,
390 | needsUpdate: false
391 | }
392 | },
393 | calculateIfNeedsUpdate: function() {
394 | if(this.props.grid.data.length > 100) {
395 | this.setState({
396 | needsUpdate: true
397 | });
398 | }
399 | },
400 | performFullRender: function() {
401 | if(this.state.needsUpdate) {
402 | setTimeout(function() {
403 | this.setState({
404 | fullRender: true,
405 | needsUpdate: false
406 | });
407 | }.bind(this), 0);
408 | }
409 | },
410 | componentWillMount: function() {
411 | this.calculateIfNeedsUpdate();
412 | },
413 | componentWillReceiveProps: function() {
414 | this.calculateIfNeedsUpdate();
415 | },
416 | componentDidMount: function() {
417 | var domNode = this.getDOMNode();
418 | var domContainer = domNode.parentNode;
419 | var header = domContainer.querySelector(".ngReactGridHeaderInner");
420 | var viewPort = domContainer.querySelector(".ngReactGridViewPort");
421 |
422 | domNode.firstChild.addEventListener('scroll', function(e) {
423 | header.scrollLeft = viewPort.scrollLeft;
424 | });
425 |
426 | this.performFullRender();
427 | },
428 | componentDidUpdate: function() {
429 | this.performFullRender();
430 | },
431 | render: function() {
432 |
433 | var mapRows = function(row, index) {
434 | return
435 | }.bind(this);
436 |
437 | var rows;
438 |
439 | if(this.props.grid.react.loading) {
440 |
441 | var loadingStyle = {
442 | textAlign: "center"
443 | };
444 |
445 | rows = (
446 |
447 |
448 | Loading...
449 |
450 |
451 | )
452 | } else {
453 | if(!this.state.fullRender) {
454 | rows = this.props.grid.data.slice(0, 100).map(mapRows);
455 | } else {
456 | rows = this.props.grid.data.map(mapRows);
457 | }
458 |
459 | if(this.props.grid.react.showingRecords === 0) {
460 | var noDataStyle = {
461 | textAlign: "center"
462 | };
463 |
464 | rows = (
465 |
466 |
467 | No records found
468 |
469 |
470 | )
471 | }
472 | }
473 |
474 |
475 | var ngReactGridViewPortStyle = {
476 | maxHeight: this.props.grid.height,
477 | minHeight: this.props.grid.height
478 | };
479 |
480 | var tableStyle = {};
481 |
482 | if(!this.props.grid.horizontalScroll) {
483 | ngReactGridViewPortStyle.overflowX = "hidden";
484 | } else {
485 | tableStyle.width = "calc(100% - " + this.props.grid.scrollbarWidth + "px)";
486 | }
487 |
488 | return (
489 |
490 |
491 |
492 |
493 |
494 | {rows}
495 |
496 |
497 |
498 |
499 |
500 | );
501 | }
502 | });
503 |
504 | return NgReactGridBody;
505 | })();
506 |
507 | var NgReactGridFooter = (function() {
508 |
509 | var NgReactGridStatus = React.createClass({
510 | render: function() {
511 |
512 | return (
513 |
514 |
Page {this.props.grid.currentPage} of {this.props.grid.totalPages} - Showing {this.props.grid.react.showingRecords} of {this.props.grid.totalCount} records
515 |
516 | )
517 | }
518 | });
519 |
520 | var NgReactGridPagination = React.createClass({
521 | goToPage: function(page) {
522 | this.props.grid.react.goToPage(page);
523 | },
524 | goToLastPage: function() {
525 | this.goToPage(this.props.grid.totalPages);
526 | },
527 | goToFirstPage: function() {
528 | this.goToPage(1);
529 | },
530 | goToNextPage: function() {
531 | var nextPage = (this.props.grid.currentPage + 1);
532 | var diff = this.props.grid.totalPages - nextPage;
533 |
534 | if(diff >= 0) {
535 | this.goToPage(nextPage);
536 | }
537 | },
538 | goToPrevPage: function() {
539 | var prevPage = (this.props.grid.currentPage - 1);
540 | if(prevPage > 0) {
541 | this.goToPage(prevPage);
542 | }
543 | },
544 | render: function() {
545 |
546 | var pagerNum = 2;
547 | var totalPages = this.props.grid.totalPages;
548 | var currentPage = this.props.grid.currentPage;
549 | var indexStart = (currentPage - pagerNum) <= 0 ? 1 : (currentPage - pagerNum);
550 | var indexFinish = (currentPage + pagerNum) >= totalPages ? totalPages : (currentPage + pagerNum);
551 | var pages = [];
552 |
553 | for(var i = indexStart; i <= indexFinish; i++) {
554 | pages.push(i);
555 | }
556 |
557 | pages = pages.map(function(page, key) {
558 | var pageClass = (page === this.props.grid.currentPage) ? "active" : "";
559 | return {page} ;
560 | }.bind(this));
561 |
562 | return (
563 |
572 | )
573 | }
574 | });
575 |
576 | var NgReactGridFooter = React.createClass({
577 | render: function() {
578 | if (this.props.grid.totalCount == 0) {
579 | return null;
580 | }
581 | return (
582 |
583 |
584 |
585 |
586 | )
587 | }
588 | });
589 |
590 | return NgReactGridFooter;
591 | })();
592 |
593 | var NgReactGrid = React.createClass({
594 | render: function() {
595 | return (
596 |
597 |
598 |
599 |
600 |
601 | )
602 | }
603 | });
604 |
605 | return NgReactGrid;
606 | })();
607 |
--------------------------------------------------------------------------------
/examples/dataSet.js:
--------------------------------------------------------------------------------
1 | var dataSet = [{"firstName":"Jose0","lastName":"Garcia0","city":"New York0","state":"New York0","zip":"192030","country":"United States0","phone":"123-455-67530","email":"test@gmail.com0"},{"firstName":"Jose1","lastName":"Garcia1","city":"New York1","state":"New York1","zip":"192031","country":"United States1","phone":"123-455-67531","email":"test@gmail.com1"},{"firstName":"Jose2","lastName":"Garcia2","city":"New York2","state":"New York2","zip":"192032","country":"United States2","phone":"123-455-67532","email":"test@gmail.com2"},{"firstName":"Jose3","lastName":"Garcia3","city":"New York3","state":"New York3","zip":"192033","country":"United States3","phone":"123-455-67533","email":"test@gmail.com3"},{"firstName":"Jose4","lastName":"Garcia4","city":"New York4","state":"New York4","zip":"192034","country":"United States4","phone":"123-455-67534","email":"test@gmail.com4"},{"firstName":"Jose5","lastName":"Garcia5","city":"New York5","state":"New York5","zip":"192035","country":"United States5","phone":"123-455-67535","email":"test@gmail.com5"},{"firstName":"Jose6","lastName":"Garcia6","city":"New York6","state":"New York6","zip":"192036","country":"United States6","phone":"123-455-67536","email":"test@gmail.com6"},{"firstName":"Jose7","lastName":"Garcia7","city":"New York7","state":"New York7","zip":"192037","country":"United States7","phone":"123-455-67537","email":"test@gmail.com7"},{"firstName":"Jose8","lastName":"Garcia8","city":"New York8","state":"New York8","zip":"192038","country":"United States8","phone":"123-455-67538","email":"test@gmail.com8"},{"firstName":"Jose9","lastName":"Garcia9","city":"New York9","state":"New York9","zip":"192039","country":"United States9","phone":"123-455-67539","email":"test@gmail.com9"},{"firstName":"Jose10","lastName":"Garcia10","city":"New York10","state":"New York10","zip":"1920310","country":"United States10","phone":"123-455-675310","email":"test@gmail.com10"},{"firstName":"Jose11","lastName":"Garcia11","city":"New York11","state":"New York11","zip":"1920311","country":"United States11","phone":"123-455-675311","email":"test@gmail.com11"},{"firstName":"Jose12","lastName":"Garcia12","city":"New York12","state":"New York12","zip":"1920312","country":"United States12","phone":"123-455-675312","email":"test@gmail.com12"},{"firstName":"Jose13","lastName":"Garcia13","city":"New York13","state":"New York13","zip":"1920313","country":"United States13","phone":"123-455-675313","email":"test@gmail.com13"},{"firstName":"Jose14","lastName":"Garcia14","city":"New York14","state":"New York14","zip":"1920314","country":"United States14","phone":"123-455-675314","email":"test@gmail.com14"},{"firstName":"Jose15","lastName":"Garcia15","city":"New York15","state":"New York15","zip":"1920315","country":"United States15","phone":"123-455-675315","email":"test@gmail.com15"},{"firstName":"Jose16","lastName":"Garcia16","city":"New York16","state":"New York16","zip":"1920316","country":"United States16","phone":"123-455-675316","email":"test@gmail.com16"},{"firstName":"Jose17","lastName":"Garcia17","city":"New York17","state":"New York17","zip":"1920317","country":"United States17","phone":"123-455-675317","email":"test@gmail.com17"},{"firstName":"Jose18","lastName":"Garcia18","city":"New York18","state":"New York18","zip":"1920318","country":"United States18","phone":"123-455-675318","email":"test@gmail.com18"},{"firstName":"Jose19","lastName":"Garcia19","city":"New York19","state":"New York19","zip":"1920319","country":"United States19","phone":"123-455-675319","email":"test@gmail.com19"},{"firstName":"Jose20","lastName":"Garcia20","city":"New York20","state":"New York20","zip":"1920320","country":"United States20","phone":"123-455-675320","email":"test@gmail.com20"},{"firstName":"Jose21","lastName":"Garcia21","city":"New York21","state":"New York21","zip":"1920321","country":"United States21","phone":"123-455-675321","email":"test@gmail.com21"},{"firstName":"Jose22","lastName":"Garcia22","city":"New York22","state":"New York22","zip":"1920322","country":"United States22","phone":"123-455-675322","email":"test@gmail.com22"},{"firstName":"Jose23","lastName":"Garcia23","city":"New York23","state":"New York23","zip":"1920323","country":"United States23","phone":"123-455-675323","email":"test@gmail.com23"},{"firstName":"Jose24","lastName":"Garcia24","city":"New York24","state":"New York24","zip":"1920324","country":"United States24","phone":"123-455-675324","email":"test@gmail.com24"},{"firstName":"Jose25","lastName":"Garcia25","city":"New York25","state":"New York25","zip":"1920325","country":"United States25","phone":"123-455-675325","email":"test@gmail.com25"},{"firstName":"Jose26","lastName":"Garcia26","city":"New York26","state":"New York26","zip":"1920326","country":"United States26","phone":"123-455-675326","email":"test@gmail.com26"},{"firstName":"Jose27","lastName":"Garcia27","city":"New York27","state":"New York27","zip":"1920327","country":"United States27","phone":"123-455-675327","email":"test@gmail.com27"},{"firstName":"Jose28","lastName":"Garcia28","city":"New York28","state":"New York28","zip":"1920328","country":"United States28","phone":"123-455-675328","email":"test@gmail.com28"},{"firstName":"Jose29","lastName":"Garcia29","city":"New York29","state":"New York29","zip":"1920329","country":"United States29","phone":"123-455-675329","email":"test@gmail.com29"},{"firstName":"Jose30","lastName":"Garcia30","city":"New York30","state":"New York30","zip":"1920330","country":"United States30","phone":"123-455-675330","email":"test@gmail.com30"},{"firstName":"Jose31","lastName":"Garcia31","city":"New York31","state":"New York31","zip":"1920331","country":"United States31","phone":"123-455-675331","email":"test@gmail.com31"},{"firstName":"Jose32","lastName":"Garcia32","city":"New York32","state":"New York32","zip":"1920332","country":"United States32","phone":"123-455-675332","email":"test@gmail.com32"},{"firstName":"Jose33","lastName":"Garcia33","city":"New York33","state":"New York33","zip":"1920333","country":"United States33","phone":"123-455-675333","email":"test@gmail.com33"},{"firstName":"Jose34","lastName":"Garcia34","city":"New York34","state":"New York34","zip":"1920334","country":"United States34","phone":"123-455-675334","email":"test@gmail.com34"},{"firstName":"Jose35","lastName":"Garcia35","city":"New York35","state":"New York35","zip":"1920335","country":"United States35","phone":"123-455-675335","email":"test@gmail.com35"},{"firstName":"Jose36","lastName":"Garcia36","city":"New York36","state":"New York36","zip":"1920336","country":"United States36","phone":"123-455-675336","email":"test@gmail.com36"},{"firstName":"Jose37","lastName":"Garcia37","city":"New York37","state":"New York37","zip":"1920337","country":"United States37","phone":"123-455-675337","email":"test@gmail.com37"},{"firstName":"Jose38","lastName":"Garcia38","city":"New York38","state":"New York38","zip":"1920338","country":"United States38","phone":"123-455-675338","email":"test@gmail.com38"},{"firstName":"Jose39","lastName":"Garcia39","city":"New York39","state":"New York39","zip":"1920339","country":"United States39","phone":"123-455-675339","email":"test@gmail.com39"},{"firstName":"Jose40","lastName":"Garcia40","city":"New York40","state":"New York40","zip":"1920340","country":"United States40","phone":"123-455-675340","email":"test@gmail.com40"},{"firstName":"Jose41","lastName":"Garcia41","city":"New York41","state":"New York41","zip":"1920341","country":"United States41","phone":"123-455-675341","email":"test@gmail.com41"},{"firstName":"Jose42","lastName":"Garcia42","city":"New York42","state":"New York42","zip":"1920342","country":"United States42","phone":"123-455-675342","email":"test@gmail.com42"},{"firstName":"Jose43","lastName":"Garcia43","city":"New York43","state":"New York43","zip":"1920343","country":"United States43","phone":"123-455-675343","email":"test@gmail.com43"},{"firstName":"Jose44","lastName":"Garcia44","city":"New York44","state":"New York44","zip":"1920344","country":"United States44","phone":"123-455-675344","email":"test@gmail.com44"},{"firstName":"Jose45","lastName":"Garcia45","city":"New York45","state":"New York45","zip":"1920345","country":"United States45","phone":"123-455-675345","email":"test@gmail.com45"},{"firstName":"Jose46","lastName":"Garcia46","city":"New York46","state":"New York46","zip":"1920346","country":"United States46","phone":"123-455-675346","email":"test@gmail.com46"},{"firstName":"Jose47","lastName":"Garcia47","city":"New York47","state":"New York47","zip":"1920347","country":"United States47","phone":"123-455-675347","email":"test@gmail.com47"},{"firstName":"Jose48","lastName":"Garcia48","city":"New York48","state":"New York48","zip":"1920348","country":"United States48","phone":"123-455-675348","email":"test@gmail.com48"},{"firstName":"Jose49","lastName":"Garcia49","city":"New York49","state":"New York49","zip":"1920349","country":"United States49","phone":"123-455-675349","email":"test@gmail.com49"},{"firstName":"Jose50","lastName":"Garcia50","city":"New York50","state":"New York50","zip":"1920350","country":"United States50","phone":"123-455-675350","email":"test@gmail.com50"},{"firstName":"Jose51","lastName":"Garcia51","city":"New York51","state":"New York51","zip":"1920351","country":"United States51","phone":"123-455-675351","email":"test@gmail.com51"},{"firstName":"Jose52","lastName":"Garcia52","city":"New York52","state":"New York52","zip":"1920352","country":"United States52","phone":"123-455-675352","email":"test@gmail.com52"},{"firstName":"Jose53","lastName":"Garcia53","city":"New York53","state":"New York53","zip":"1920353","country":"United States53","phone":"123-455-675353","email":"test@gmail.com53"},{"firstName":"Jose54","lastName":"Garcia54","city":"New York54","state":"New York54","zip":"1920354","country":"United States54","phone":"123-455-675354","email":"test@gmail.com54"},{"firstName":"Jose55","lastName":"Garcia55","city":"New York55","state":"New York55","zip":"1920355","country":"United States55","phone":"123-455-675355","email":"test@gmail.com55"},{"firstName":"Jose56","lastName":"Garcia56","city":"New York56","state":"New York56","zip":"1920356","country":"United States56","phone":"123-455-675356","email":"test@gmail.com56"},{"firstName":"Jose57","lastName":"Garcia57","city":"New York57","state":"New York57","zip":"1920357","country":"United States57","phone":"123-455-675357","email":"test@gmail.com57"},{"firstName":"Jose58","lastName":"Garcia58","city":"New York58","state":"New York58","zip":"1920358","country":"United States58","phone":"123-455-675358","email":"test@gmail.com58"},{"firstName":"Jose59","lastName":"Garcia59","city":"New York59","state":"New York59","zip":"1920359","country":"United States59","phone":"123-455-675359","email":"test@gmail.com59"},{"firstName":"Jose60","lastName":"Garcia60","city":"New York60","state":"New York60","zip":"1920360","country":"United States60","phone":"123-455-675360","email":"test@gmail.com60"},{"firstName":"Jose61","lastName":"Garcia61","city":"New York61","state":"New York61","zip":"1920361","country":"United States61","phone":"123-455-675361","email":"test@gmail.com61"},{"firstName":"Jose62","lastName":"Garcia62","city":"New York62","state":"New York62","zip":"1920362","country":"United States62","phone":"123-455-675362","email":"test@gmail.com62"},{"firstName":"Jose63","lastName":"Garcia63","city":"New York63","state":"New York63","zip":"1920363","country":"United States63","phone":"123-455-675363","email":"test@gmail.com63"},{"firstName":"Jose64","lastName":"Garcia64","city":"New York64","state":"New York64","zip":"1920364","country":"United States64","phone":"123-455-675364","email":"test@gmail.com64"},{"firstName":"Jose65","lastName":"Garcia65","city":"New York65","state":"New York65","zip":"1920365","country":"United States65","phone":"123-455-675365","email":"test@gmail.com65"},{"firstName":"Jose66","lastName":"Garcia66","city":"New York66","state":"New York66","zip":"1920366","country":"United States66","phone":"123-455-675366","email":"test@gmail.com66"},{"firstName":"Jose67","lastName":"Garcia67","city":"New York67","state":"New York67","zip":"1920367","country":"United States67","phone":"123-455-675367","email":"test@gmail.com67"},{"firstName":"Jose68","lastName":"Garcia68","city":"New York68","state":"New York68","zip":"1920368","country":"United States68","phone":"123-455-675368","email":"test@gmail.com68"},{"firstName":"Jose69","lastName":"Garcia69","city":"New York69","state":"New York69","zip":"1920369","country":"United States69","phone":"123-455-675369","email":"test@gmail.com69"},{"firstName":"Jose70","lastName":"Garcia70","city":"New York70","state":"New York70","zip":"1920370","country":"United States70","phone":"123-455-675370","email":"test@gmail.com70"},{"firstName":"Jose71","lastName":"Garcia71","city":"New York71","state":"New York71","zip":"1920371","country":"United States71","phone":"123-455-675371","email":"test@gmail.com71"},{"firstName":"Jose72","lastName":"Garcia72","city":"New York72","state":"New York72","zip":"1920372","country":"United States72","phone":"123-455-675372","email":"test@gmail.com72"},{"firstName":"Jose73","lastName":"Garcia73","city":"New York73","state":"New York73","zip":"1920373","country":"United States73","phone":"123-455-675373","email":"test@gmail.com73"},{"firstName":"Jose74","lastName":"Garcia74","city":"New York74","state":"New York74","zip":"1920374","country":"United States74","phone":"123-455-675374","email":"test@gmail.com74"},{"firstName":"Jose75","lastName":"Garcia75","city":"New York75","state":"New York75","zip":"1920375","country":"United States75","phone":"123-455-675375","email":"test@gmail.com75"},{"firstName":"Jose76","lastName":"Garcia76","city":"New York76","state":"New York76","zip":"1920376","country":"United States76","phone":"123-455-675376","email":"test@gmail.com76"},{"firstName":"Jose77","lastName":"Garcia77","city":"New York77","state":"New York77","zip":"1920377","country":"United States77","phone":"123-455-675377","email":"test@gmail.com77"},{"firstName":"Jose78","lastName":"Garcia78","city":"New York78","state":"New York78","zip":"1920378","country":"United States78","phone":"123-455-675378","email":"test@gmail.com78"},{"firstName":"Jose79","lastName":"Garcia79","city":"New York79","state":"New York79","zip":"1920379","country":"United States79","phone":"123-455-675379","email":"test@gmail.com79"},{"firstName":"Jose80","lastName":"Garcia80","city":"New York80","state":"New York80","zip":"1920380","country":"United States80","phone":"123-455-675380","email":"test@gmail.com80"},{"firstName":"Jose81","lastName":"Garcia81","city":"New York81","state":"New York81","zip":"1920381","country":"United States81","phone":"123-455-675381","email":"test@gmail.com81"},{"firstName":"Jose82","lastName":"Garcia82","city":"New York82","state":"New York82","zip":"1920382","country":"United States82","phone":"123-455-675382","email":"test@gmail.com82"},{"firstName":"Jose83","lastName":"Garcia83","city":"New York83","state":"New York83","zip":"1920383","country":"United States83","phone":"123-455-675383","email":"test@gmail.com83"},{"firstName":"Jose84","lastName":"Garcia84","city":"New York84","state":"New York84","zip":"1920384","country":"United States84","phone":"123-455-675384","email":"test@gmail.com84"},{"firstName":"Jose85","lastName":"Garcia85","city":"New York85","state":"New York85","zip":"1920385","country":"United States85","phone":"123-455-675385","email":"test@gmail.com85"},{"firstName":"Jose86","lastName":"Garcia86","city":"New York86","state":"New York86","zip":"1920386","country":"United States86","phone":"123-455-675386","email":"test@gmail.com86"},{"firstName":"Jose87","lastName":"Garcia87","city":"New York87","state":"New York87","zip":"1920387","country":"United States87","phone":"123-455-675387","email":"test@gmail.com87"},{"firstName":"Jose88","lastName":"Garcia88","city":"New York88","state":"New York88","zip":"1920388","country":"United States88","phone":"123-455-675388","email":"test@gmail.com88"},{"firstName":"Jose89","lastName":"Garcia89","city":"New York89","state":"New York89","zip":"1920389","country":"United States89","phone":"123-455-675389","email":"test@gmail.com89"},{"firstName":"Jose90","lastName":"Garcia90","city":"New York90","state":"New York90","zip":"1920390","country":"United States90","phone":"123-455-675390","email":"test@gmail.com90"},{"firstName":"Jose91","lastName":"Garcia91","city":"New York91","state":"New York91","zip":"1920391","country":"United States91","phone":"123-455-675391","email":"test@gmail.com91"},{"firstName":"Jose92","lastName":"Garcia92","city":"New York92","state":"New York92","zip":"1920392","country":"United States92","phone":"123-455-675392","email":"test@gmail.com92"},{"firstName":"Jose93","lastName":"Garcia93","city":"New York93","state":"New York93","zip":"1920393","country":"United States93","phone":"123-455-675393","email":"test@gmail.com93"},{"firstName":"Jose94","lastName":"Garcia94","city":"New York94","state":"New York94","zip":"1920394","country":"United States94","phone":"123-455-675394","email":"test@gmail.com94"},{"firstName":"Jose95","lastName":"Garcia95","city":"New York95","state":"New York95","zip":"1920395","country":"United States95","phone":"123-455-675395","email":"test@gmail.com95"},{"firstName":"Jose96","lastName":"Garcia96","city":"New York96","state":"New York96","zip":"1920396","country":"United States96","phone":"123-455-675396","email":"test@gmail.com96"},{"firstName":"Jose97","lastName":"Garcia97","city":"New York97","state":"New York97","zip":"1920397","country":"United States97","phone":"123-455-675397","email":"test@gmail.com97"},{"firstName":"Jose98","lastName":"Garcia98","city":"New York98","state":"New York98","zip":"1920398","country":"United States98","phone":"123-455-675398","email":"test@gmail.com98"},{"firstName":"Jose99","lastName":"Garcia99","city":"New York99","state":"New York99","zip":"1920399","country":"United States99","phone":"123-455-675399","email":"test@gmail.com99"},{"firstName":"Jose100","lastName":"Garcia100","city":"New York100","state":"New York100","zip":"19203100","country":"United States100","phone":"123-455-6753100","email":"test@gmail.com100"},{"firstName":"Jose101","lastName":"Garcia101","city":"New York101","state":"New York101","zip":"19203101","country":"United States101","phone":"123-455-6753101","email":"test@gmail.com101"},{"firstName":"Jose102","lastName":"Garcia102","city":"New York102","state":"New York102","zip":"19203102","country":"United States102","phone":"123-455-6753102","email":"test@gmail.com102"},{"firstName":"Jose103","lastName":"Garcia103","city":"New York103","state":"New York103","zip":"19203103","country":"United States103","phone":"123-455-6753103","email":"test@gmail.com103"},{"firstName":"Jose104","lastName":"Garcia104","city":"New York104","state":"New York104","zip":"19203104","country":"United States104","phone":"123-455-6753104","email":"test@gmail.com104"},{"firstName":"Jose105","lastName":"Garcia105","city":"New York105","state":"New York105","zip":"19203105","country":"United States105","phone":"123-455-6753105","email":"test@gmail.com105"},{"firstName":"Jose106","lastName":"Garcia106","city":"New York106","state":"New York106","zip":"19203106","country":"United States106","phone":"123-455-6753106","email":"test@gmail.com106"},{"firstName":"Jose107","lastName":"Garcia107","city":"New York107","state":"New York107","zip":"19203107","country":"United States107","phone":"123-455-6753107","email":"test@gmail.com107"},{"firstName":"Jose108","lastName":"Garcia108","city":"New York108","state":"New York108","zip":"19203108","country":"United States108","phone":"123-455-6753108","email":"test@gmail.com108"},{"firstName":"Jose109","lastName":"Garcia109","city":"New York109","state":"New York109","zip":"19203109","country":"United States109","phone":"123-455-6753109","email":"test@gmail.com109"},{"firstName":"Jose110","lastName":"Garcia110","city":"New York110","state":"New York110","zip":"19203110","country":"United States110","phone":"123-455-6753110","email":"test@gmail.com110"},{"firstName":"Jose111","lastName":"Garcia111","city":"New York111","state":"New York111","zip":"19203111","country":"United States111","phone":"123-455-6753111","email":"test@gmail.com111"},{"firstName":"Jose112","lastName":"Garcia112","city":"New York112","state":"New York112","zip":"19203112","country":"United States112","phone":"123-455-6753112","email":"test@gmail.com112"},{"firstName":"Jose113","lastName":"Garcia113","city":"New York113","state":"New York113","zip":"19203113","country":"United States113","phone":"123-455-6753113","email":"test@gmail.com113"},{"firstName":"Jose114","lastName":"Garcia114","city":"New York114","state":"New York114","zip":"19203114","country":"United States114","phone":"123-455-6753114","email":"test@gmail.com114"},{"firstName":"Jose115","lastName":"Garcia115","city":"New York115","state":"New York115","zip":"19203115","country":"United States115","phone":"123-455-6753115","email":"test@gmail.com115"},{"firstName":"Jose116","lastName":"Garcia116","city":"New York116","state":"New York116","zip":"19203116","country":"United States116","phone":"123-455-6753116","email":"test@gmail.com116"},{"firstName":"Jose117","lastName":"Garcia117","city":"New York117","state":"New York117","zip":"19203117","country":"United States117","phone":"123-455-6753117","email":"test@gmail.com117"},{"firstName":"Jose118","lastName":"Garcia118","city":"New York118","state":"New York118","zip":"19203118","country":"United States118","phone":"123-455-6753118","email":"test@gmail.com118"},{"firstName":"Jose119","lastName":"Garcia119","city":"New York119","state":"New York119","zip":"19203119","country":"United States119","phone":"123-455-6753119","email":"test@gmail.com119"},{"firstName":"Jose120","lastName":"Garcia120","city":"New York120","state":"New York120","zip":"19203120","country":"United States120","phone":"123-455-6753120","email":"test@gmail.com120"},{"firstName":"Jose121","lastName":"Garcia121","city":"New York121","state":"New York121","zip":"19203121","country":"United States121","phone":"123-455-6753121","email":"test@gmail.com121"},{"firstName":"Jose122","lastName":"Garcia122","city":"New York122","state":"New York122","zip":"19203122","country":"United States122","phone":"123-455-6753122","email":"test@gmail.com122"},{"firstName":"Jose123","lastName":"Garcia123","city":"New York123","state":"New York123","zip":"19203123","country":"United States123","phone":"123-455-6753123","email":"test@gmail.com123"},{"firstName":"Jose124","lastName":"Garcia124","city":"New York124","state":"New York124","zip":"19203124","country":"United States124","phone":"123-455-6753124","email":"test@gmail.com124"},{"firstName":"Jose125","lastName":"Garcia125","city":"New York125","state":"New York125","zip":"19203125","country":"United States125","phone":"123-455-6753125","email":"test@gmail.com125"},{"firstName":"Jose126","lastName":"Garcia126","city":"New York126","state":"New York126","zip":"19203126","country":"United States126","phone":"123-455-6753126","email":"test@gmail.com126"},{"firstName":"Jose127","lastName":"Garcia127","city":"New York127","state":"New York127","zip":"19203127","country":"United States127","phone":"123-455-6753127","email":"test@gmail.com127"},{"firstName":"Jose128","lastName":"Garcia128","city":"New York128","state":"New York128","zip":"19203128","country":"United States128","phone":"123-455-6753128","email":"test@gmail.com128"},{"firstName":"Jose129","lastName":"Garcia129","city":"New York129","state":"New York129","zip":"19203129","country":"United States129","phone":"123-455-6753129","email":"test@gmail.com129"},{"firstName":"Jose130","lastName":"Garcia130","city":"New York130","state":"New York130","zip":"19203130","country":"United States130","phone":"123-455-6753130","email":"test@gmail.com130"},{"firstName":"Jose131","lastName":"Garcia131","city":"New York131","state":"New York131","zip":"19203131","country":"United States131","phone":"123-455-6753131","email":"test@gmail.com131"},{"firstName":"Jose132","lastName":"Garcia132","city":"New York132","state":"New York132","zip":"19203132","country":"United States132","phone":"123-455-6753132","email":"test@gmail.com132"},{"firstName":"Jose133","lastName":"Garcia133","city":"New York133","state":"New York133","zip":"19203133","country":"United States133","phone":"123-455-6753133","email":"test@gmail.com133"},{"firstName":"Jose134","lastName":"Garcia134","city":"New York134","state":"New York134","zip":"19203134","country":"United States134","phone":"123-455-6753134","email":"test@gmail.com134"},{"firstName":"Jose135","lastName":"Garcia135","city":"New York135","state":"New York135","zip":"19203135","country":"United States135","phone":"123-455-6753135","email":"test@gmail.com135"},{"firstName":"Jose136","lastName":"Garcia136","city":"New York136","state":"New York136","zip":"19203136","country":"United States136","phone":"123-455-6753136","email":"test@gmail.com136"},{"firstName":"Jose137","lastName":"Garcia137","city":"New York137","state":"New York137","zip":"19203137","country":"United States137","phone":"123-455-6753137","email":"test@gmail.com137"},{"firstName":"Jose138","lastName":"Garcia138","city":"New York138","state":"New York138","zip":"19203138","country":"United States138","phone":"123-455-6753138","email":"test@gmail.com138"},{"firstName":"Jose139","lastName":"Garcia139","city":"New York139","state":"New York139","zip":"19203139","country":"United States139","phone":"123-455-6753139","email":"test@gmail.com139"},{"firstName":"Jose140","lastName":"Garcia140","city":"New York140","state":"New York140","zip":"19203140","country":"United States140","phone":"123-455-6753140","email":"test@gmail.com140"},{"firstName":"Jose141","lastName":"Garcia141","city":"New York141","state":"New York141","zip":"19203141","country":"United States141","phone":"123-455-6753141","email":"test@gmail.com141"},{"firstName":"Jose142","lastName":"Garcia142","city":"New York142","state":"New York142","zip":"19203142","country":"United States142","phone":"123-455-6753142","email":"test@gmail.com142"},{"firstName":"Jose143","lastName":"Garcia143","city":"New York143","state":"New York143","zip":"19203143","country":"United States143","phone":"123-455-6753143","email":"test@gmail.com143"},{"firstName":"Jose144","lastName":"Garcia144","city":"New York144","state":"New York144","zip":"19203144","country":"United States144","phone":"123-455-6753144","email":"test@gmail.com144"},{"firstName":"Jose145","lastName":"Garcia145","city":"New York145","state":"New York145","zip":"19203145","country":"United States145","phone":"123-455-6753145","email":"test@gmail.com145"},{"firstName":"Jose146","lastName":"Garcia146","city":"New York146","state":"New York146","zip":"19203146","country":"United States146","phone":"123-455-6753146","email":"test@gmail.com146"},{"firstName":"Jose147","lastName":"Garcia147","city":"New York147","state":"New York147","zip":"19203147","country":"United States147","phone":"123-455-6753147","email":"test@gmail.com147"},{"firstName":"Jose148","lastName":"Garcia148","city":"New York148","state":"New York148","zip":"19203148","country":"United States148","phone":"123-455-6753148","email":"test@gmail.com148"},{"firstName":"Jose149","lastName":"Garcia149","city":"New York149","state":"New York149","zip":"19203149","country":"United States149","phone":"123-455-6753149","email":"test@gmail.com149"},{"firstName":"Jose150","lastName":"Garcia150","city":"New York150","state":"New York150","zip":"19203150","country":"United States150","phone":"123-455-6753150","email":"test@gmail.com150"},{"firstName":"Jose151","lastName":"Garcia151","city":"New York151","state":"New York151","zip":"19203151","country":"United States151","phone":"123-455-6753151","email":"test@gmail.com151"},{"firstName":"Jose152","lastName":"Garcia152","city":"New York152","state":"New York152","zip":"19203152","country":"United States152","phone":"123-455-6753152","email":"test@gmail.com152"},{"firstName":"Jose153","lastName":"Garcia153","city":"New York153","state":"New York153","zip":"19203153","country":"United States153","phone":"123-455-6753153","email":"test@gmail.com153"},{"firstName":"Jose154","lastName":"Garcia154","city":"New York154","state":"New York154","zip":"19203154","country":"United States154","phone":"123-455-6753154","email":"test@gmail.com154"},{"firstName":"Jose155","lastName":"Garcia155","city":"New York155","state":"New York155","zip":"19203155","country":"United States155","phone":"123-455-6753155","email":"test@gmail.com155"},{"firstName":"Jose156","lastName":"Garcia156","city":"New York156","state":"New York156","zip":"19203156","country":"United States156","phone":"123-455-6753156","email":"test@gmail.com156"},{"firstName":"Jose157","lastName":"Garcia157","city":"New York157","state":"New York157","zip":"19203157","country":"United States157","phone":"123-455-6753157","email":"test@gmail.com157"},{"firstName":"Jose158","lastName":"Garcia158","city":"New York158","state":"New York158","zip":"19203158","country":"United States158","phone":"123-455-6753158","email":"test@gmail.com158"},{"firstName":"Jose159","lastName":"Garcia159","city":"New York159","state":"New York159","zip":"19203159","country":"United States159","phone":"123-455-6753159","email":"test@gmail.com159"},{"firstName":"Jose160","lastName":"Garcia160","city":"New York160","state":"New York160","zip":"19203160","country":"United States160","phone":"123-455-6753160","email":"test@gmail.com160"},{"firstName":"Jose161","lastName":"Garcia161","city":"New York161","state":"New York161","zip":"19203161","country":"United States161","phone":"123-455-6753161","email":"test@gmail.com161"},{"firstName":"Jose162","lastName":"Garcia162","city":"New York162","state":"New York162","zip":"19203162","country":"United States162","phone":"123-455-6753162","email":"test@gmail.com162"},{"firstName":"Jose163","lastName":"Garcia163","city":"New York163","state":"New York163","zip":"19203163","country":"United States163","phone":"123-455-6753163","email":"test@gmail.com163"},{"firstName":"Jose164","lastName":"Garcia164","city":"New York164","state":"New York164","zip":"19203164","country":"United States164","phone":"123-455-6753164","email":"test@gmail.com164"},{"firstName":"Jose165","lastName":"Garcia165","city":"New York165","state":"New York165","zip":"19203165","country":"United States165","phone":"123-455-6753165","email":"test@gmail.com165"},{"firstName":"Jose166","lastName":"Garcia166","city":"New York166","state":"New York166","zip":"19203166","country":"United States166","phone":"123-455-6753166","email":"test@gmail.com166"},{"firstName":"Jose167","lastName":"Garcia167","city":"New York167","state":"New York167","zip":"19203167","country":"United States167","phone":"123-455-6753167","email":"test@gmail.com167"},{"firstName":"Jose168","lastName":"Garcia168","city":"New York168","state":"New York168","zip":"19203168","country":"United States168","phone":"123-455-6753168","email":"test@gmail.com168"},{"firstName":"Jose169","lastName":"Garcia169","city":"New York169","state":"New York169","zip":"19203169","country":"United States169","phone":"123-455-6753169","email":"test@gmail.com169"},{"firstName":"Jose170","lastName":"Garcia170","city":"New York170","state":"New York170","zip":"19203170","country":"United States170","phone":"123-455-6753170","email":"test@gmail.com170"},{"firstName":"Jose171","lastName":"Garcia171","city":"New York171","state":"New York171","zip":"19203171","country":"United States171","phone":"123-455-6753171","email":"test@gmail.com171"},{"firstName":"Jose172","lastName":"Garcia172","city":"New York172","state":"New York172","zip":"19203172","country":"United States172","phone":"123-455-6753172","email":"test@gmail.com172"},{"firstName":"Jose173","lastName":"Garcia173","city":"New York173","state":"New York173","zip":"19203173","country":"United States173","phone":"123-455-6753173","email":"test@gmail.com173"},{"firstName":"Jose174","lastName":"Garcia174","city":"New York174","state":"New York174","zip":"19203174","country":"United States174","phone":"123-455-6753174","email":"test@gmail.com174"},{"firstName":"Jose175","lastName":"Garcia175","city":"New York175","state":"New York175","zip":"19203175","country":"United States175","phone":"123-455-6753175","email":"test@gmail.com175"},{"firstName":"Jose176","lastName":"Garcia176","city":"New York176","state":"New York176","zip":"19203176","country":"United States176","phone":"123-455-6753176","email":"test@gmail.com176"},{"firstName":"Jose177","lastName":"Garcia177","city":"New York177","state":"New York177","zip":"19203177","country":"United States177","phone":"123-455-6753177","email":"test@gmail.com177"},{"firstName":"Jose178","lastName":"Garcia178","city":"New York178","state":"New York178","zip":"19203178","country":"United States178","phone":"123-455-6753178","email":"test@gmail.com178"},{"firstName":"Jose179","lastName":"Garcia179","city":"New York179","state":"New York179","zip":"19203179","country":"United States179","phone":"123-455-6753179","email":"test@gmail.com179"},{"firstName":"Jose180","lastName":"Garcia180","city":"New York180","state":"New York180","zip":"19203180","country":"United States180","phone":"123-455-6753180","email":"test@gmail.com180"},{"firstName":"Jose181","lastName":"Garcia181","city":"New York181","state":"New York181","zip":"19203181","country":"United States181","phone":"123-455-6753181","email":"test@gmail.com181"},{"firstName":"Jose182","lastName":"Garcia182","city":"New York182","state":"New York182","zip":"19203182","country":"United States182","phone":"123-455-6753182","email":"test@gmail.com182"},{"firstName":"Jose183","lastName":"Garcia183","city":"New York183","state":"New York183","zip":"19203183","country":"United States183","phone":"123-455-6753183","email":"test@gmail.com183"},{"firstName":"Jose184","lastName":"Garcia184","city":"New York184","state":"New York184","zip":"19203184","country":"United States184","phone":"123-455-6753184","email":"test@gmail.com184"},{"firstName":"Jose185","lastName":"Garcia185","city":"New York185","state":"New York185","zip":"19203185","country":"United States185","phone":"123-455-6753185","email":"test@gmail.com185"},{"firstName":"Jose186","lastName":"Garcia186","city":"New York186","state":"New York186","zip":"19203186","country":"United States186","phone":"123-455-6753186","email":"test@gmail.com186"},{"firstName":"Jose187","lastName":"Garcia187","city":"New York187","state":"New York187","zip":"19203187","country":"United States187","phone":"123-455-6753187","email":"test@gmail.com187"},{"firstName":"Jose188","lastName":"Garcia188","city":"New York188","state":"New York188","zip":"19203188","country":"United States188","phone":"123-455-6753188","email":"test@gmail.com188"},{"firstName":"Jose189","lastName":"Garcia189","city":"New York189","state":"New York189","zip":"19203189","country":"United States189","phone":"123-455-6753189","email":"test@gmail.com189"},{"firstName":"Jose190","lastName":"Garcia190","city":"New York190","state":"New York190","zip":"19203190","country":"United States190","phone":"123-455-6753190","email":"test@gmail.com190"},{"firstName":"Jose191","lastName":"Garcia191","city":"New York191","state":"New York191","zip":"19203191","country":"United States191","phone":"123-455-6753191","email":"test@gmail.com191"},{"firstName":"Jose192","lastName":"Garcia192","city":"New York192","state":"New York192","zip":"19203192","country":"United States192","phone":"123-455-6753192","email":"test@gmail.com192"},{"firstName":"Jose193","lastName":"Garcia193","city":"New York193","state":"New York193","zip":"19203193","country":"United States193","phone":"123-455-6753193","email":"test@gmail.com193"},{"firstName":"Jose194","lastName":"Garcia194","city":"New York194","state":"New York194","zip":"19203194","country":"United States194","phone":"123-455-6753194","email":"test@gmail.com194"},{"firstName":"Jose195","lastName":"Garcia195","city":"New York195","state":"New York195","zip":"19203195","country":"United States195","phone":"123-455-6753195","email":"test@gmail.com195"},{"firstName":"Jose196","lastName":"Garcia196","city":"New York196","state":"New York196","zip":"19203196","country":"United States196","phone":"123-455-6753196","email":"test@gmail.com196"},{"firstName":"Jose197","lastName":"Garcia197","city":"New York197","state":"New York197","zip":"19203197","country":"United States197","phone":"123-455-6753197","email":"test@gmail.com197"},{"firstName":"Jose198","lastName":"Garcia198","city":"New York198","state":"New York198","zip":"19203198","country":"United States198","phone":"123-455-6753198","email":"test@gmail.com198"},{"firstName":"Jose199","lastName":"Garcia199","city":"New York199","state":"New York199","zip":"19203199","country":"United States199","phone":"123-455-6753199","email":"test@gmail.com199"},{"firstName":"Jose200","lastName":"Garcia200","city":"New York200","state":"New York200","zip":"19203200","country":"United States200","phone":"123-455-6753200","email":"test@gmail.com200"},{"firstName":"Jose201","lastName":"Garcia201","city":"New York201","state":"New York201","zip":"19203201","country":"United States201","phone":"123-455-6753201","email":"test@gmail.com201"},{"firstName":"Jose202","lastName":"Garcia202","city":"New York202","state":"New York202","zip":"19203202","country":"United States202","phone":"123-455-6753202","email":"test@gmail.com202"},{"firstName":"Jose203","lastName":"Garcia203","city":"New York203","state":"New York203","zip":"19203203","country":"United States203","phone":"123-455-6753203","email":"test@gmail.com203"},{"firstName":"Jose204","lastName":"Garcia204","city":"New York204","state":"New York204","zip":"19203204","country":"United States204","phone":"123-455-6753204","email":"test@gmail.com204"},{"firstName":"Jose205","lastName":"Garcia205","city":"New York205","state":"New York205","zip":"19203205","country":"United States205","phone":"123-455-6753205","email":"test@gmail.com205"},{"firstName":"Jose206","lastName":"Garcia206","city":"New York206","state":"New York206","zip":"19203206","country":"United States206","phone":"123-455-6753206","email":"test@gmail.com206"},{"firstName":"Jose207","lastName":"Garcia207","city":"New York207","state":"New York207","zip":"19203207","country":"United States207","phone":"123-455-6753207","email":"test@gmail.com207"},{"firstName":"Jose208","lastName":"Garcia208","city":"New York208","state":"New York208","zip":"19203208","country":"United States208","phone":"123-455-6753208","email":"test@gmail.com208"},{"firstName":"Jose209","lastName":"Garcia209","city":"New York209","state":"New York209","zip":"19203209","country":"United States209","phone":"123-455-6753209","email":"test@gmail.com209"},{"firstName":"Jose210","lastName":"Garcia210","city":"New York210","state":"New York210","zip":"19203210","country":"United States210","phone":"123-455-6753210","email":"test@gmail.com210"},{"firstName":"Jose211","lastName":"Garcia211","city":"New York211","state":"New York211","zip":"19203211","country":"United States211","phone":"123-455-6753211","email":"test@gmail.com211"},{"firstName":"Jose212","lastName":"Garcia212","city":"New York212","state":"New York212","zip":"19203212","country":"United States212","phone":"123-455-6753212","email":"test@gmail.com212"},{"firstName":"Jose213","lastName":"Garcia213","city":"New York213","state":"New York213","zip":"19203213","country":"United States213","phone":"123-455-6753213","email":"test@gmail.com213"},{"firstName":"Jose214","lastName":"Garcia214","city":"New York214","state":"New York214","zip":"19203214","country":"United States214","phone":"123-455-6753214","email":"test@gmail.com214"},{"firstName":"Jose215","lastName":"Garcia215","city":"New York215","state":"New York215","zip":"19203215","country":"United States215","phone":"123-455-6753215","email":"test@gmail.com215"},{"firstName":"Jose216","lastName":"Garcia216","city":"New York216","state":"New York216","zip":"19203216","country":"United States216","phone":"123-455-6753216","email":"test@gmail.com216"},{"firstName":"Jose217","lastName":"Garcia217","city":"New York217","state":"New York217","zip":"19203217","country":"United States217","phone":"123-455-6753217","email":"test@gmail.com217"},{"firstName":"Jose218","lastName":"Garcia218","city":"New York218","state":"New York218","zip":"19203218","country":"United States218","phone":"123-455-6753218","email":"test@gmail.com218"},{"firstName":"Jose219","lastName":"Garcia219","city":"New York219","state":"New York219","zip":"19203219","country":"United States219","phone":"123-455-6753219","email":"test@gmail.com219"},{"firstName":"Jose220","lastName":"Garcia220","city":"New York220","state":"New York220","zip":"19203220","country":"United States220","phone":"123-455-6753220","email":"test@gmail.com220"},{"firstName":"Jose221","lastName":"Garcia221","city":"New York221","state":"New York221","zip":"19203221","country":"United States221","phone":"123-455-6753221","email":"test@gmail.com221"},{"firstName":"Jose222","lastName":"Garcia222","city":"New York222","state":"New York222","zip":"19203222","country":"United States222","phone":"123-455-6753222","email":"test@gmail.com222"},{"firstName":"Jose223","lastName":"Garcia223","city":"New York223","state":"New York223","zip":"19203223","country":"United States223","phone":"123-455-6753223","email":"test@gmail.com223"},{"firstName":"Jose224","lastName":"Garcia224","city":"New York224","state":"New York224","zip":"19203224","country":"United States224","phone":"123-455-6753224","email":"test@gmail.com224"},{"firstName":"Jose225","lastName":"Garcia225","city":"New York225","state":"New York225","zip":"19203225","country":"United States225","phone":"123-455-6753225","email":"test@gmail.com225"},{"firstName":"Jose226","lastName":"Garcia226","city":"New York226","state":"New York226","zip":"19203226","country":"United States226","phone":"123-455-6753226","email":"test@gmail.com226"},{"firstName":"Jose227","lastName":"Garcia227","city":"New York227","state":"New York227","zip":"19203227","country":"United States227","phone":"123-455-6753227","email":"test@gmail.com227"},{"firstName":"Jose228","lastName":"Garcia228","city":"New York228","state":"New York228","zip":"19203228","country":"United States228","phone":"123-455-6753228","email":"test@gmail.com228"},{"firstName":"Jose229","lastName":"Garcia229","city":"New York229","state":"New York229","zip":"19203229","country":"United States229","phone":"123-455-6753229","email":"test@gmail.com229"},{"firstName":"Jose230","lastName":"Garcia230","city":"New York230","state":"New York230","zip":"19203230","country":"United States230","phone":"123-455-6753230","email":"test@gmail.com230"},{"firstName":"Jose231","lastName":"Garcia231","city":"New York231","state":"New York231","zip":"19203231","country":"United States231","phone":"123-455-6753231","email":"test@gmail.com231"},{"firstName":"Jose232","lastName":"Garcia232","city":"New York232","state":"New York232","zip":"19203232","country":"United States232","phone":"123-455-6753232","email":"test@gmail.com232"},{"firstName":"Jose233","lastName":"Garcia233","city":"New York233","state":"New York233","zip":"19203233","country":"United States233","phone":"123-455-6753233","email":"test@gmail.com233"},{"firstName":"Jose234","lastName":"Garcia234","city":"New York234","state":"New York234","zip":"19203234","country":"United States234","phone":"123-455-6753234","email":"test@gmail.com234"},{"firstName":"Jose235","lastName":"Garcia235","city":"New York235","state":"New York235","zip":"19203235","country":"United States235","phone":"123-455-6753235","email":"test@gmail.com235"},{"firstName":"Jose236","lastName":"Garcia236","city":"New York236","state":"New York236","zip":"19203236","country":"United States236","phone":"123-455-6753236","email":"test@gmail.com236"},{"firstName":"Jose237","lastName":"Garcia237","city":"New York237","state":"New York237","zip":"19203237","country":"United States237","phone":"123-455-6753237","email":"test@gmail.com237"},{"firstName":"Jose238","lastName":"Garcia238","city":"New York238","state":"New York238","zip":"19203238","country":"United States238","phone":"123-455-6753238","email":"test@gmail.com238"},{"firstName":"Jose239","lastName":"Garcia239","city":"New York239","state":"New York239","zip":"19203239","country":"United States239","phone":"123-455-6753239","email":"test@gmail.com239"},{"firstName":"Jose240","lastName":"Garcia240","city":"New York240","state":"New York240","zip":"19203240","country":"United States240","phone":"123-455-6753240","email":"test@gmail.com240"},{"firstName":"Jose241","lastName":"Garcia241","city":"New York241","state":"New York241","zip":"19203241","country":"United States241","phone":"123-455-6753241","email":"test@gmail.com241"},{"firstName":"Jose242","lastName":"Garcia242","city":"New York242","state":"New York242","zip":"19203242","country":"United States242","phone":"123-455-6753242","email":"test@gmail.com242"},{"firstName":"Jose243","lastName":"Garcia243","city":"New York243","state":"New York243","zip":"19203243","country":"United States243","phone":"123-455-6753243","email":"test@gmail.com243"},{"firstName":"Jose244","lastName":"Garcia244","city":"New York244","state":"New York244","zip":"19203244","country":"United States244","phone":"123-455-6753244","email":"test@gmail.com244"},{"firstName":"Jose245","lastName":"Garcia245","city":"New York245","state":"New York245","zip":"19203245","country":"United States245","phone":"123-455-6753245","email":"test@gmail.com245"},{"firstName":"Jose246","lastName":"Garcia246","city":"New York246","state":"New York246","zip":"19203246","country":"United States246","phone":"123-455-6753246","email":"test@gmail.com246"},{"firstName":"Jose247","lastName":"Garcia247","city":"New York247","state":"New York247","zip":"19203247","country":"United States247","phone":"123-455-6753247","email":"test@gmail.com247"},{"firstName":"Jose248","lastName":"Garcia248","city":"New York248","state":"New York248","zip":"19203248","country":"United States248","phone":"123-455-6753248","email":"test@gmail.com248"},{"firstName":"Jose249","lastName":"Garcia249","city":"New York249","state":"New York249","zip":"19203249","country":"United States249","phone":"123-455-6753249","email":"test@gmail.com249"},{"firstName":"Jose250","lastName":"Garcia250","city":"New York250","state":"New York250","zip":"19203250","country":"United States250","phone":"123-455-6753250","email":"test@gmail.com250"},{"firstName":"Jose251","lastName":"Garcia251","city":"New York251","state":"New York251","zip":"19203251","country":"United States251","phone":"123-455-6753251","email":"test@gmail.com251"},{"firstName":"Jose252","lastName":"Garcia252","city":"New York252","state":"New York252","zip":"19203252","country":"United States252","phone":"123-455-6753252","email":"test@gmail.com252"},{"firstName":"Jose253","lastName":"Garcia253","city":"New York253","state":"New York253","zip":"19203253","country":"United States253","phone":"123-455-6753253","email":"test@gmail.com253"},{"firstName":"Jose254","lastName":"Garcia254","city":"New York254","state":"New York254","zip":"19203254","country":"United States254","phone":"123-455-6753254","email":"test@gmail.com254"},{"firstName":"Jose255","lastName":"Garcia255","city":"New York255","state":"New York255","zip":"19203255","country":"United States255","phone":"123-455-6753255","email":"test@gmail.com255"},{"firstName":"Jose256","lastName":"Garcia256","city":"New York256","state":"New York256","zip":"19203256","country":"United States256","phone":"123-455-6753256","email":"test@gmail.com256"},{"firstName":"Jose257","lastName":"Garcia257","city":"New York257","state":"New York257","zip":"19203257","country":"United States257","phone":"123-455-6753257","email":"test@gmail.com257"},{"firstName":"Jose258","lastName":"Garcia258","city":"New York258","state":"New York258","zip":"19203258","country":"United States258","phone":"123-455-6753258","email":"test@gmail.com258"},{"firstName":"Jose259","lastName":"Garcia259","city":"New York259","state":"New York259","zip":"19203259","country":"United States259","phone":"123-455-6753259","email":"test@gmail.com259"},{"firstName":"Jose260","lastName":"Garcia260","city":"New York260","state":"New York260","zip":"19203260","country":"United States260","phone":"123-455-6753260","email":"test@gmail.com260"},{"firstName":"Jose261","lastName":"Garcia261","city":"New York261","state":"New York261","zip":"19203261","country":"United States261","phone":"123-455-6753261","email":"test@gmail.com261"},{"firstName":"Jose262","lastName":"Garcia262","city":"New York262","state":"New York262","zip":"19203262","country":"United States262","phone":"123-455-6753262","email":"test@gmail.com262"},{"firstName":"Jose263","lastName":"Garcia263","city":"New York263","state":"New York263","zip":"19203263","country":"United States263","phone":"123-455-6753263","email":"test@gmail.com263"},{"firstName":"Jose264","lastName":"Garcia264","city":"New York264","state":"New York264","zip":"19203264","country":"United States264","phone":"123-455-6753264","email":"test@gmail.com264"},{"firstName":"Jose265","lastName":"Garcia265","city":"New York265","state":"New York265","zip":"19203265","country":"United States265","phone":"123-455-6753265","email":"test@gmail.com265"},{"firstName":"Jose266","lastName":"Garcia266","city":"New York266","state":"New York266","zip":"19203266","country":"United States266","phone":"123-455-6753266","email":"test@gmail.com266"},{"firstName":"Jose267","lastName":"Garcia267","city":"New York267","state":"New York267","zip":"19203267","country":"United States267","phone":"123-455-6753267","email":"test@gmail.com267"},{"firstName":"Jose268","lastName":"Garcia268","city":"New York268","state":"New York268","zip":"19203268","country":"United States268","phone":"123-455-6753268","email":"test@gmail.com268"},{"firstName":"Jose269","lastName":"Garcia269","city":"New York269","state":"New York269","zip":"19203269","country":"United States269","phone":"123-455-6753269","email":"test@gmail.com269"},{"firstName":"Jose270","lastName":"Garcia270","city":"New York270","state":"New York270","zip":"19203270","country":"United States270","phone":"123-455-6753270","email":"test@gmail.com270"},{"firstName":"Jose271","lastName":"Garcia271","city":"New York271","state":"New York271","zip":"19203271","country":"United States271","phone":"123-455-6753271","email":"test@gmail.com271"},{"firstName":"Jose272","lastName":"Garcia272","city":"New York272","state":"New York272","zip":"19203272","country":"United States272","phone":"123-455-6753272","email":"test@gmail.com272"},{"firstName":"Jose273","lastName":"Garcia273","city":"New York273","state":"New York273","zip":"19203273","country":"United States273","phone":"123-455-6753273","email":"test@gmail.com273"},{"firstName":"Jose274","lastName":"Garcia274","city":"New York274","state":"New York274","zip":"19203274","country":"United States274","phone":"123-455-6753274","email":"test@gmail.com274"},{"firstName":"Jose275","lastName":"Garcia275","city":"New York275","state":"New York275","zip":"19203275","country":"United States275","phone":"123-455-6753275","email":"test@gmail.com275"},{"firstName":"Jose276","lastName":"Garcia276","city":"New York276","state":"New York276","zip":"19203276","country":"United States276","phone":"123-455-6753276","email":"test@gmail.com276"},{"firstName":"Jose277","lastName":"Garcia277","city":"New York277","state":"New York277","zip":"19203277","country":"United States277","phone":"123-455-6753277","email":"test@gmail.com277"},{"firstName":"Jose278","lastName":"Garcia278","city":"New York278","state":"New York278","zip":"19203278","country":"United States278","phone":"123-455-6753278","email":"test@gmail.com278"},{"firstName":"Jose279","lastName":"Garcia279","city":"New York279","state":"New York279","zip":"19203279","country":"United States279","phone":"123-455-6753279","email":"test@gmail.com279"},{"firstName":"Jose280","lastName":"Garcia280","city":"New York280","state":"New York280","zip":"19203280","country":"United States280","phone":"123-455-6753280","email":"test@gmail.com280"},{"firstName":"Jose281","lastName":"Garcia281","city":"New York281","state":"New York281","zip":"19203281","country":"United States281","phone":"123-455-6753281","email":"test@gmail.com281"},{"firstName":"Jose282","lastName":"Garcia282","city":"New York282","state":"New York282","zip":"19203282","country":"United States282","phone":"123-455-6753282","email":"test@gmail.com282"},{"firstName":"Jose283","lastName":"Garcia283","city":"New York283","state":"New York283","zip":"19203283","country":"United States283","phone":"123-455-6753283","email":"test@gmail.com283"},{"firstName":"Jose284","lastName":"Garcia284","city":"New York284","state":"New York284","zip":"19203284","country":"United States284","phone":"123-455-6753284","email":"test@gmail.com284"},{"firstName":"Jose285","lastName":"Garcia285","city":"New York285","state":"New York285","zip":"19203285","country":"United States285","phone":"123-455-6753285","email":"test@gmail.com285"},{"firstName":"Jose286","lastName":"Garcia286","city":"New York286","state":"New York286","zip":"19203286","country":"United States286","phone":"123-455-6753286","email":"test@gmail.com286"},{"firstName":"Jose287","lastName":"Garcia287","city":"New York287","state":"New York287","zip":"19203287","country":"United States287","phone":"123-455-6753287","email":"test@gmail.com287"},{"firstName":"Jose288","lastName":"Garcia288","city":"New York288","state":"New York288","zip":"19203288","country":"United States288","phone":"123-455-6753288","email":"test@gmail.com288"},{"firstName":"Jose289","lastName":"Garcia289","city":"New York289","state":"New York289","zip":"19203289","country":"United States289","phone":"123-455-6753289","email":"test@gmail.com289"},{"firstName":"Jose290","lastName":"Garcia290","city":"New York290","state":"New York290","zip":"19203290","country":"United States290","phone":"123-455-6753290","email":"test@gmail.com290"},{"firstName":"Jose291","lastName":"Garcia291","city":"New York291","state":"New York291","zip":"19203291","country":"United States291","phone":"123-455-6753291","email":"test@gmail.com291"},{"firstName":"Jose292","lastName":"Garcia292","city":"New York292","state":"New York292","zip":"19203292","country":"United States292","phone":"123-455-6753292","email":"test@gmail.com292"},{"firstName":"Jose293","lastName":"Garcia293","city":"New York293","state":"New York293","zip":"19203293","country":"United States293","phone":"123-455-6753293","email":"test@gmail.com293"},{"firstName":"Jose294","lastName":"Garcia294","city":"New York294","state":"New York294","zip":"19203294","country":"United States294","phone":"123-455-6753294","email":"test@gmail.com294"},{"firstName":"Jose295","lastName":"Garcia295","city":"New York295","state":"New York295","zip":"19203295","country":"United States295","phone":"123-455-6753295","email":"test@gmail.com295"},{"firstName":"Jose296","lastName":"Garcia296","city":"New York296","state":"New York296","zip":"19203296","country":"United States296","phone":"123-455-6753296","email":"test@gmail.com296"},{"firstName":"Jose297","lastName":"Garcia297","city":"New York297","state":"New York297","zip":"19203297","country":"United States297","phone":"123-455-6753297","email":"test@gmail.com297"},{"firstName":"Jose298","lastName":"Garcia298","city":"New York298","state":"New York298","zip":"19203298","country":"United States298","phone":"123-455-6753298","email":"test@gmail.com298"},{"firstName":"Jose299","lastName":"Garcia299","city":"New York299","state":"New York299","zip":"19203299","country":"United States299","phone":"123-455-6753299","email":"test@gmail.com299"},{"firstName":"Jose300","lastName":"Garcia300","city":"New York300","state":"New York300","zip":"19203300","country":"United States300","phone":"123-455-6753300","email":"test@gmail.com300"},{"firstName":"Jose301","lastName":"Garcia301","city":"New York301","state":"New York301","zip":"19203301","country":"United States301","phone":"123-455-6753301","email":"test@gmail.com301"},{"firstName":"Jose302","lastName":"Garcia302","city":"New York302","state":"New York302","zip":"19203302","country":"United States302","phone":"123-455-6753302","email":"test@gmail.com302"},{"firstName":"Jose303","lastName":"Garcia303","city":"New York303","state":"New York303","zip":"19203303","country":"United States303","phone":"123-455-6753303","email":"test@gmail.com303"},{"firstName":"Jose304","lastName":"Garcia304","city":"New York304","state":"New York304","zip":"19203304","country":"United States304","phone":"123-455-6753304","email":"test@gmail.com304"},{"firstName":"Jose305","lastName":"Garcia305","city":"New York305","state":"New York305","zip":"19203305","country":"United States305","phone":"123-455-6753305","email":"test@gmail.com305"},{"firstName":"Jose306","lastName":"Garcia306","city":"New York306","state":"New York306","zip":"19203306","country":"United States306","phone":"123-455-6753306","email":"test@gmail.com306"},{"firstName":"Jose307","lastName":"Garcia307","city":"New York307","state":"New York307","zip":"19203307","country":"United States307","phone":"123-455-6753307","email":"test@gmail.com307"},{"firstName":"Jose308","lastName":"Garcia308","city":"New York308","state":"New York308","zip":"19203308","country":"United States308","phone":"123-455-6753308","email":"test@gmail.com308"},{"firstName":"Jose309","lastName":"Garcia309","city":"New York309","state":"New York309","zip":"19203309","country":"United States309","phone":"123-455-6753309","email":"test@gmail.com309"},{"firstName":"Jose310","lastName":"Garcia310","city":"New York310","state":"New York310","zip":"19203310","country":"United States310","phone":"123-455-6753310","email":"test@gmail.com310"},{"firstName":"Jose311","lastName":"Garcia311","city":"New York311","state":"New York311","zip":"19203311","country":"United States311","phone":"123-455-6753311","email":"test@gmail.com311"},{"firstName":"Jose312","lastName":"Garcia312","city":"New York312","state":"New York312","zip":"19203312","country":"United States312","phone":"123-455-6753312","email":"test@gmail.com312"},{"firstName":"Jose313","lastName":"Garcia313","city":"New York313","state":"New York313","zip":"19203313","country":"United States313","phone":"123-455-6753313","email":"test@gmail.com313"},{"firstName":"Jose314","lastName":"Garcia314","city":"New York314","state":"New York314","zip":"19203314","country":"United States314","phone":"123-455-6753314","email":"test@gmail.com314"},{"firstName":"Jose315","lastName":"Garcia315","city":"New York315","state":"New York315","zip":"19203315","country":"United States315","phone":"123-455-6753315","email":"test@gmail.com315"},{"firstName":"Jose316","lastName":"Garcia316","city":"New York316","state":"New York316","zip":"19203316","country":"United States316","phone":"123-455-6753316","email":"test@gmail.com316"},{"firstName":"Jose317","lastName":"Garcia317","city":"New York317","state":"New York317","zip":"19203317","country":"United States317","phone":"123-455-6753317","email":"test@gmail.com317"},{"firstName":"Jose318","lastName":"Garcia318","city":"New York318","state":"New York318","zip":"19203318","country":"United States318","phone":"123-455-6753318","email":"test@gmail.com318"},{"firstName":"Jose319","lastName":"Garcia319","city":"New York319","state":"New York319","zip":"19203319","country":"United States319","phone":"123-455-6753319","email":"test@gmail.com319"},{"firstName":"Jose320","lastName":"Garcia320","city":"New York320","state":"New York320","zip":"19203320","country":"United States320","phone":"123-455-6753320","email":"test@gmail.com320"},{"firstName":"Jose321","lastName":"Garcia321","city":"New York321","state":"New York321","zip":"19203321","country":"United States321","phone":"123-455-6753321","email":"test@gmail.com321"},{"firstName":"Jose322","lastName":"Garcia322","city":"New York322","state":"New York322","zip":"19203322","country":"United States322","phone":"123-455-6753322","email":"test@gmail.com322"},{"firstName":"Jose323","lastName":"Garcia323","city":"New York323","state":"New York323","zip":"19203323","country":"United States323","phone":"123-455-6753323","email":"test@gmail.com323"},{"firstName":"Jose324","lastName":"Garcia324","city":"New York324","state":"New York324","zip":"19203324","country":"United States324","phone":"123-455-6753324","email":"test@gmail.com324"},{"firstName":"Jose325","lastName":"Garcia325","city":"New York325","state":"New York325","zip":"19203325","country":"United States325","phone":"123-455-6753325","email":"test@gmail.com325"},{"firstName":"Jose326","lastName":"Garcia326","city":"New York326","state":"New York326","zip":"19203326","country":"United States326","phone":"123-455-6753326","email":"test@gmail.com326"},{"firstName":"Jose327","lastName":"Garcia327","city":"New York327","state":"New York327","zip":"19203327","country":"United States327","phone":"123-455-6753327","email":"test@gmail.com327"},{"firstName":"Jose328","lastName":"Garcia328","city":"New York328","state":"New York328","zip":"19203328","country":"United States328","phone":"123-455-6753328","email":"test@gmail.com328"},{"firstName":"Jose329","lastName":"Garcia329","city":"New York329","state":"New York329","zip":"19203329","country":"United States329","phone":"123-455-6753329","email":"test@gmail.com329"},{"firstName":"Jose330","lastName":"Garcia330","city":"New York330","state":"New York330","zip":"19203330","country":"United States330","phone":"123-455-6753330","email":"test@gmail.com330"},{"firstName":"Jose331","lastName":"Garcia331","city":"New York331","state":"New York331","zip":"19203331","country":"United States331","phone":"123-455-6753331","email":"test@gmail.com331"},{"firstName":"Jose332","lastName":"Garcia332","city":"New York332","state":"New York332","zip":"19203332","country":"United States332","phone":"123-455-6753332","email":"test@gmail.com332"},{"firstName":"Jose333","lastName":"Garcia333","city":"New York333","state":"New York333","zip":"19203333","country":"United States333","phone":"123-455-6753333","email":"test@gmail.com333"},{"firstName":"Jose334","lastName":"Garcia334","city":"New York334","state":"New York334","zip":"19203334","country":"United States334","phone":"123-455-6753334","email":"test@gmail.com334"},{"firstName":"Jose335","lastName":"Garcia335","city":"New York335","state":"New York335","zip":"19203335","country":"United States335","phone":"123-455-6753335","email":"test@gmail.com335"},{"firstName":"Jose336","lastName":"Garcia336","city":"New York336","state":"New York336","zip":"19203336","country":"United States336","phone":"123-455-6753336","email":"test@gmail.com336"},{"firstName":"Jose337","lastName":"Garcia337","city":"New York337","state":"New York337","zip":"19203337","country":"United States337","phone":"123-455-6753337","email":"test@gmail.com337"},{"firstName":"Jose338","lastName":"Garcia338","city":"New York338","state":"New York338","zip":"19203338","country":"United States338","phone":"123-455-6753338","email":"test@gmail.com338"},{"firstName":"Jose339","lastName":"Garcia339","city":"New York339","state":"New York339","zip":"19203339","country":"United States339","phone":"123-455-6753339","email":"test@gmail.com339"},{"firstName":"Jose340","lastName":"Garcia340","city":"New York340","state":"New York340","zip":"19203340","country":"United States340","phone":"123-455-6753340","email":"test@gmail.com340"},{"firstName":"Jose341","lastName":"Garcia341","city":"New York341","state":"New York341","zip":"19203341","country":"United States341","phone":"123-455-6753341","email":"test@gmail.com341"},{"firstName":"Jose342","lastName":"Garcia342","city":"New York342","state":"New York342","zip":"19203342","country":"United States342","phone":"123-455-6753342","email":"test@gmail.com342"},{"firstName":"Jose343","lastName":"Garcia343","city":"New York343","state":"New York343","zip":"19203343","country":"United States343","phone":"123-455-6753343","email":"test@gmail.com343"},{"firstName":"Jose344","lastName":"Garcia344","city":"New York344","state":"New York344","zip":"19203344","country":"United States344","phone":"123-455-6753344","email":"test@gmail.com344"},{"firstName":"Jose345","lastName":"Garcia345","city":"New York345","state":"New York345","zip":"19203345","country":"United States345","phone":"123-455-6753345","email":"test@gmail.com345"},{"firstName":"Jose346","lastName":"Garcia346","city":"New York346","state":"New York346","zip":"19203346","country":"United States346","phone":"123-455-6753346","email":"test@gmail.com346"},{"firstName":"Jose347","lastName":"Garcia347","city":"New York347","state":"New York347","zip":"19203347","country":"United States347","phone":"123-455-6753347","email":"test@gmail.com347"},{"firstName":"Jose348","lastName":"Garcia348","city":"New York348","state":"New York348","zip":"19203348","country":"United States348","phone":"123-455-6753348","email":"test@gmail.com348"},{"firstName":"Jose349","lastName":"Garcia349","city":"New York349","state":"New York349","zip":"19203349","country":"United States349","phone":"123-455-6753349","email":"test@gmail.com349"},{"firstName":"Jose350","lastName":"Garcia350","city":"New York350","state":"New York350","zip":"19203350","country":"United States350","phone":"123-455-6753350","email":"test@gmail.com350"},{"firstName":"Jose351","lastName":"Garcia351","city":"New York351","state":"New York351","zip":"19203351","country":"United States351","phone":"123-455-6753351","email":"test@gmail.com351"},{"firstName":"Jose352","lastName":"Garcia352","city":"New York352","state":"New York352","zip":"19203352","country":"United States352","phone":"123-455-6753352","email":"test@gmail.com352"},{"firstName":"Jose353","lastName":"Garcia353","city":"New York353","state":"New York353","zip":"19203353","country":"United States353","phone":"123-455-6753353","email":"test@gmail.com353"},{"firstName":"Jose354","lastName":"Garcia354","city":"New York354","state":"New York354","zip":"19203354","country":"United States354","phone":"123-455-6753354","email":"test@gmail.com354"},{"firstName":"Jose355","lastName":"Garcia355","city":"New York355","state":"New York355","zip":"19203355","country":"United States355","phone":"123-455-6753355","email":"test@gmail.com355"},{"firstName":"Jose356","lastName":"Garcia356","city":"New York356","state":"New York356","zip":"19203356","country":"United States356","phone":"123-455-6753356","email":"test@gmail.com356"},{"firstName":"Jose357","lastName":"Garcia357","city":"New York357","state":"New York357","zip":"19203357","country":"United States357","phone":"123-455-6753357","email":"test@gmail.com357"},{"firstName":"Jose358","lastName":"Garcia358","city":"New York358","state":"New York358","zip":"19203358","country":"United States358","phone":"123-455-6753358","email":"test@gmail.com358"},{"firstName":"Jose359","lastName":"Garcia359","city":"New York359","state":"New York359","zip":"19203359","country":"United States359","phone":"123-455-6753359","email":"test@gmail.com359"},{"firstName":"Jose360","lastName":"Garcia360","city":"New York360","state":"New York360","zip":"19203360","country":"United States360","phone":"123-455-6753360","email":"test@gmail.com360"},{"firstName":"Jose361","lastName":"Garcia361","city":"New York361","state":"New York361","zip":"19203361","country":"United States361","phone":"123-455-6753361","email":"test@gmail.com361"},{"firstName":"Jose362","lastName":"Garcia362","city":"New York362","state":"New York362","zip":"19203362","country":"United States362","phone":"123-455-6753362","email":"test@gmail.com362"},{"firstName":"Jose363","lastName":"Garcia363","city":"New York363","state":"New York363","zip":"19203363","country":"United States363","phone":"123-455-6753363","email":"test@gmail.com363"},{"firstName":"Jose364","lastName":"Garcia364","city":"New York364","state":"New York364","zip":"19203364","country":"United States364","phone":"123-455-6753364","email":"test@gmail.com364"},{"firstName":"Jose365","lastName":"Garcia365","city":"New York365","state":"New York365","zip":"19203365","country":"United States365","phone":"123-455-6753365","email":"test@gmail.com365"},{"firstName":"Jose366","lastName":"Garcia366","city":"New York366","state":"New York366","zip":"19203366","country":"United States366","phone":"123-455-6753366","email":"test@gmail.com366"},{"firstName":"Jose367","lastName":"Garcia367","city":"New York367","state":"New York367","zip":"19203367","country":"United States367","phone":"123-455-6753367","email":"test@gmail.com367"},{"firstName":"Jose368","lastName":"Garcia368","city":"New York368","state":"New York368","zip":"19203368","country":"United States368","phone":"123-455-6753368","email":"test@gmail.com368"},{"firstName":"Jose369","lastName":"Garcia369","city":"New York369","state":"New York369","zip":"19203369","country":"United States369","phone":"123-455-6753369","email":"test@gmail.com369"},{"firstName":"Jose370","lastName":"Garcia370","city":"New York370","state":"New York370","zip":"19203370","country":"United States370","phone":"123-455-6753370","email":"test@gmail.com370"},{"firstName":"Jose371","lastName":"Garcia371","city":"New York371","state":"New York371","zip":"19203371","country":"United States371","phone":"123-455-6753371","email":"test@gmail.com371"},{"firstName":"Jose372","lastName":"Garcia372","city":"New York372","state":"New York372","zip":"19203372","country":"United States372","phone":"123-455-6753372","email":"test@gmail.com372"},{"firstName":"Jose373","lastName":"Garcia373","city":"New York373","state":"New York373","zip":"19203373","country":"United States373","phone":"123-455-6753373","email":"test@gmail.com373"},{"firstName":"Jose374","lastName":"Garcia374","city":"New York374","state":"New York374","zip":"19203374","country":"United States374","phone":"123-455-6753374","email":"test@gmail.com374"},{"firstName":"Jose375","lastName":"Garcia375","city":"New York375","state":"New York375","zip":"19203375","country":"United States375","phone":"123-455-6753375","email":"test@gmail.com375"},{"firstName":"Jose376","lastName":"Garcia376","city":"New York376","state":"New York376","zip":"19203376","country":"United States376","phone":"123-455-6753376","email":"test@gmail.com376"},{"firstName":"Jose377","lastName":"Garcia377","city":"New York377","state":"New York377","zip":"19203377","country":"United States377","phone":"123-455-6753377","email":"test@gmail.com377"},{"firstName":"Jose378","lastName":"Garcia378","city":"New York378","state":"New York378","zip":"19203378","country":"United States378","phone":"123-455-6753378","email":"test@gmail.com378"},{"firstName":"Jose379","lastName":"Garcia379","city":"New York379","state":"New York379","zip":"19203379","country":"United States379","phone":"123-455-6753379","email":"test@gmail.com379"},{"firstName":"Jose380","lastName":"Garcia380","city":"New York380","state":"New York380","zip":"19203380","country":"United States380","phone":"123-455-6753380","email":"test@gmail.com380"},{"firstName":"Jose381","lastName":"Garcia381","city":"New York381","state":"New York381","zip":"19203381","country":"United States381","phone":"123-455-6753381","email":"test@gmail.com381"},{"firstName":"Jose382","lastName":"Garcia382","city":"New York382","state":"New York382","zip":"19203382","country":"United States382","phone":"123-455-6753382","email":"test@gmail.com382"},{"firstName":"Jose383","lastName":"Garcia383","city":"New York383","state":"New York383","zip":"19203383","country":"United States383","phone":"123-455-6753383","email":"test@gmail.com383"},{"firstName":"Jose384","lastName":"Garcia384","city":"New York384","state":"New York384","zip":"19203384","country":"United States384","phone":"123-455-6753384","email":"test@gmail.com384"},{"firstName":"Jose385","lastName":"Garcia385","city":"New York385","state":"New York385","zip":"19203385","country":"United States385","phone":"123-455-6753385","email":"test@gmail.com385"},{"firstName":"Jose386","lastName":"Garcia386","city":"New York386","state":"New York386","zip":"19203386","country":"United States386","phone":"123-455-6753386","email":"test@gmail.com386"},{"firstName":"Jose387","lastName":"Garcia387","city":"New York387","state":"New York387","zip":"19203387","country":"United States387","phone":"123-455-6753387","email":"test@gmail.com387"},{"firstName":"Jose388","lastName":"Garcia388","city":"New York388","state":"New York388","zip":"19203388","country":"United States388","phone":"123-455-6753388","email":"test@gmail.com388"},{"firstName":"Jose389","lastName":"Garcia389","city":"New York389","state":"New York389","zip":"19203389","country":"United States389","phone":"123-455-6753389","email":"test@gmail.com389"},{"firstName":"Jose390","lastName":"Garcia390","city":"New York390","state":"New York390","zip":"19203390","country":"United States390","phone":"123-455-6753390","email":"test@gmail.com390"},{"firstName":"Jose391","lastName":"Garcia391","city":"New York391","state":"New York391","zip":"19203391","country":"United States391","phone":"123-455-6753391","email":"test@gmail.com391"},{"firstName":"Jose392","lastName":"Garcia392","city":"New York392","state":"New York392","zip":"19203392","country":"United States392","phone":"123-455-6753392","email":"test@gmail.com392"},{"firstName":"Jose393","lastName":"Garcia393","city":"New York393","state":"New York393","zip":"19203393","country":"United States393","phone":"123-455-6753393","email":"test@gmail.com393"},{"firstName":"Jose394","lastName":"Garcia394","city":"New York394","state":"New York394","zip":"19203394","country":"United States394","phone":"123-455-6753394","email":"test@gmail.com394"},{"firstName":"Jose395","lastName":"Garcia395","city":"New York395","state":"New York395","zip":"19203395","country":"United States395","phone":"123-455-6753395","email":"test@gmail.com395"},{"firstName":"Jose396","lastName":"Garcia396","city":"New York396","state":"New York396","zip":"19203396","country":"United States396","phone":"123-455-6753396","email":"test@gmail.com396"},{"firstName":"Jose397","lastName":"Garcia397","city":"New York397","state":"New York397","zip":"19203397","country":"United States397","phone":"123-455-6753397","email":"test@gmail.com397"},{"firstName":"Jose398","lastName":"Garcia398","city":"New York398","state":"New York398","zip":"19203398","country":"United States398","phone":"123-455-6753398","email":"test@gmail.com398"},{"firstName":"Jose399","lastName":"Garcia399","city":"New York399","state":"New York399","zip":"19203399","country":"United States399","phone":"123-455-6753399","email":"test@gmail.com399"},{"firstName":"Jose400","lastName":"Garcia400","city":"New York400","state":"New York400","zip":"19203400","country":"United States400","phone":"123-455-6753400","email":"test@gmail.com400"},{"firstName":"Jose401","lastName":"Garcia401","city":"New York401","state":"New York401","zip":"19203401","country":"United States401","phone":"123-455-6753401","email":"test@gmail.com401"},{"firstName":"Jose402","lastName":"Garcia402","city":"New York402","state":"New York402","zip":"19203402","country":"United States402","phone":"123-455-6753402","email":"test@gmail.com402"},{"firstName":"Jose403","lastName":"Garcia403","city":"New York403","state":"New York403","zip":"19203403","country":"United States403","phone":"123-455-6753403","email":"test@gmail.com403"},{"firstName":"Jose404","lastName":"Garcia404","city":"New York404","state":"New York404","zip":"19203404","country":"United States404","phone":"123-455-6753404","email":"test@gmail.com404"},{"firstName":"Jose405","lastName":"Garcia405","city":"New York405","state":"New York405","zip":"19203405","country":"United States405","phone":"123-455-6753405","email":"test@gmail.com405"},{"firstName":"Jose406","lastName":"Garcia406","city":"New York406","state":"New York406","zip":"19203406","country":"United States406","phone":"123-455-6753406","email":"test@gmail.com406"},{"firstName":"Jose407","lastName":"Garcia407","city":"New York407","state":"New York407","zip":"19203407","country":"United States407","phone":"123-455-6753407","email":"test@gmail.com407"},{"firstName":"Jose408","lastName":"Garcia408","city":"New York408","state":"New York408","zip":"19203408","country":"United States408","phone":"123-455-6753408","email":"test@gmail.com408"},{"firstName":"Jose409","lastName":"Garcia409","city":"New York409","state":"New York409","zip":"19203409","country":"United States409","phone":"123-455-6753409","email":"test@gmail.com409"},{"firstName":"Jose410","lastName":"Garcia410","city":"New York410","state":"New York410","zip":"19203410","country":"United States410","phone":"123-455-6753410","email":"test@gmail.com410"},{"firstName":"Jose411","lastName":"Garcia411","city":"New York411","state":"New York411","zip":"19203411","country":"United States411","phone":"123-455-6753411","email":"test@gmail.com411"},{"firstName":"Jose412","lastName":"Garcia412","city":"New York412","state":"New York412","zip":"19203412","country":"United States412","phone":"123-455-6753412","email":"test@gmail.com412"},{"firstName":"Jose413","lastName":"Garcia413","city":"New York413","state":"New York413","zip":"19203413","country":"United States413","phone":"123-455-6753413","email":"test@gmail.com413"},{"firstName":"Jose414","lastName":"Garcia414","city":"New York414","state":"New York414","zip":"19203414","country":"United States414","phone":"123-455-6753414","email":"test@gmail.com414"},{"firstName":"Jose415","lastName":"Garcia415","city":"New York415","state":"New York415","zip":"19203415","country":"United States415","phone":"123-455-6753415","email":"test@gmail.com415"},{"firstName":"Jose416","lastName":"Garcia416","city":"New York416","state":"New York416","zip":"19203416","country":"United States416","phone":"123-455-6753416","email":"test@gmail.com416"},{"firstName":"Jose417","lastName":"Garcia417","city":"New York417","state":"New York417","zip":"19203417","country":"United States417","phone":"123-455-6753417","email":"test@gmail.com417"},{"firstName":"Jose418","lastName":"Garcia418","city":"New York418","state":"New York418","zip":"19203418","country":"United States418","phone":"123-455-6753418","email":"test@gmail.com418"},{"firstName":"Jose419","lastName":"Garcia419","city":"New York419","state":"New York419","zip":"19203419","country":"United States419","phone":"123-455-6753419","email":"test@gmail.com419"},{"firstName":"Jose420","lastName":"Garcia420","city":"New York420","state":"New York420","zip":"19203420","country":"United States420","phone":"123-455-6753420","email":"test@gmail.com420"},{"firstName":"Jose421","lastName":"Garcia421","city":"New York421","state":"New York421","zip":"19203421","country":"United States421","phone":"123-455-6753421","email":"test@gmail.com421"},{"firstName":"Jose422","lastName":"Garcia422","city":"New York422","state":"New York422","zip":"19203422","country":"United States422","phone":"123-455-6753422","email":"test@gmail.com422"},{"firstName":"Jose423","lastName":"Garcia423","city":"New York423","state":"New York423","zip":"19203423","country":"United States423","phone":"123-455-6753423","email":"test@gmail.com423"},{"firstName":"Jose424","lastName":"Garcia424","city":"New York424","state":"New York424","zip":"19203424","country":"United States424","phone":"123-455-6753424","email":"test@gmail.com424"},{"firstName":"Jose425","lastName":"Garcia425","city":"New York425","state":"New York425","zip":"19203425","country":"United States425","phone":"123-455-6753425","email":"test@gmail.com425"},{"firstName":"Jose426","lastName":"Garcia426","city":"New York426","state":"New York426","zip":"19203426","country":"United States426","phone":"123-455-6753426","email":"test@gmail.com426"},{"firstName":"Jose427","lastName":"Garcia427","city":"New York427","state":"New York427","zip":"19203427","country":"United States427","phone":"123-455-6753427","email":"test@gmail.com427"},{"firstName":"Jose428","lastName":"Garcia428","city":"New York428","state":"New York428","zip":"19203428","country":"United States428","phone":"123-455-6753428","email":"test@gmail.com428"},{"firstName":"Jose429","lastName":"Garcia429","city":"New York429","state":"New York429","zip":"19203429","country":"United States429","phone":"123-455-6753429","email":"test@gmail.com429"},{"firstName":"Jose430","lastName":"Garcia430","city":"New York430","state":"New York430","zip":"19203430","country":"United States430","phone":"123-455-6753430","email":"test@gmail.com430"},{"firstName":"Jose431","lastName":"Garcia431","city":"New York431","state":"New York431","zip":"19203431","country":"United States431","phone":"123-455-6753431","email":"test@gmail.com431"},{"firstName":"Jose432","lastName":"Garcia432","city":"New York432","state":"New York432","zip":"19203432","country":"United States432","phone":"123-455-6753432","email":"test@gmail.com432"},{"firstName":"Jose433","lastName":"Garcia433","city":"New York433","state":"New York433","zip":"19203433","country":"United States433","phone":"123-455-6753433","email":"test@gmail.com433"},{"firstName":"Jose434","lastName":"Garcia434","city":"New York434","state":"New York434","zip":"19203434","country":"United States434","phone":"123-455-6753434","email":"test@gmail.com434"},{"firstName":"Jose435","lastName":"Garcia435","city":"New York435","state":"New York435","zip":"19203435","country":"United States435","phone":"123-455-6753435","email":"test@gmail.com435"},{"firstName":"Jose436","lastName":"Garcia436","city":"New York436","state":"New York436","zip":"19203436","country":"United States436","phone":"123-455-6753436","email":"test@gmail.com436"},{"firstName":"Jose437","lastName":"Garcia437","city":"New York437","state":"New York437","zip":"19203437","country":"United States437","phone":"123-455-6753437","email":"test@gmail.com437"},{"firstName":"Jose438","lastName":"Garcia438","city":"New York438","state":"New York438","zip":"19203438","country":"United States438","phone":"123-455-6753438","email":"test@gmail.com438"},{"firstName":"Jose439","lastName":"Garcia439","city":"New York439","state":"New York439","zip":"19203439","country":"United States439","phone":"123-455-6753439","email":"test@gmail.com439"},{"firstName":"Jose440","lastName":"Garcia440","city":"New York440","state":"New York440","zip":"19203440","country":"United States440","phone":"123-455-6753440","email":"test@gmail.com440"},{"firstName":"Jose441","lastName":"Garcia441","city":"New York441","state":"New York441","zip":"19203441","country":"United States441","phone":"123-455-6753441","email":"test@gmail.com441"},{"firstName":"Jose442","lastName":"Garcia442","city":"New York442","state":"New York442","zip":"19203442","country":"United States442","phone":"123-455-6753442","email":"test@gmail.com442"},{"firstName":"Jose443","lastName":"Garcia443","city":"New York443","state":"New York443","zip":"19203443","country":"United States443","phone":"123-455-6753443","email":"test@gmail.com443"},{"firstName":"Jose444","lastName":"Garcia444","city":"New York444","state":"New York444","zip":"19203444","country":"United States444","phone":"123-455-6753444","email":"test@gmail.com444"},{"firstName":"Jose445","lastName":"Garcia445","city":"New York445","state":"New York445","zip":"19203445","country":"United States445","phone":"123-455-6753445","email":"test@gmail.com445"},{"firstName":"Jose446","lastName":"Garcia446","city":"New York446","state":"New York446","zip":"19203446","country":"United States446","phone":"123-455-6753446","email":"test@gmail.com446"},{"firstName":"Jose447","lastName":"Garcia447","city":"New York447","state":"New York447","zip":"19203447","country":"United States447","phone":"123-455-6753447","email":"test@gmail.com447"},{"firstName":"Jose448","lastName":"Garcia448","city":"New York448","state":"New York448","zip":"19203448","country":"United States448","phone":"123-455-6753448","email":"test@gmail.com448"},{"firstName":"Jose449","lastName":"Garcia449","city":"New York449","state":"New York449","zip":"19203449","country":"United States449","phone":"123-455-6753449","email":"test@gmail.com449"},{"firstName":"Jose450","lastName":"Garcia450","city":"New York450","state":"New York450","zip":"19203450","country":"United States450","phone":"123-455-6753450","email":"test@gmail.com450"},{"firstName":"Jose451","lastName":"Garcia451","city":"New York451","state":"New York451","zip":"19203451","country":"United States451","phone":"123-455-6753451","email":"test@gmail.com451"},{"firstName":"Jose452","lastName":"Garcia452","city":"New York452","state":"New York452","zip":"19203452","country":"United States452","phone":"123-455-6753452","email":"test@gmail.com452"},{"firstName":"Jose453","lastName":"Garcia453","city":"New York453","state":"New York453","zip":"19203453","country":"United States453","phone":"123-455-6753453","email":"test@gmail.com453"},{"firstName":"Jose454","lastName":"Garcia454","city":"New York454","state":"New York454","zip":"19203454","country":"United States454","phone":"123-455-6753454","email":"test@gmail.com454"},{"firstName":"Jose455","lastName":"Garcia455","city":"New York455","state":"New York455","zip":"19203455","country":"United States455","phone":"123-455-6753455","email":"test@gmail.com455"},{"firstName":"Jose456","lastName":"Garcia456","city":"New York456","state":"New York456","zip":"19203456","country":"United States456","phone":"123-455-6753456","email":"test@gmail.com456"},{"firstName":"Jose457","lastName":"Garcia457","city":"New York457","state":"New York457","zip":"19203457","country":"United States457","phone":"123-455-6753457","email":"test@gmail.com457"},{"firstName":"Jose458","lastName":"Garcia458","city":"New York458","state":"New York458","zip":"19203458","country":"United States458","phone":"123-455-6753458","email":"test@gmail.com458"},{"firstName":"Jose459","lastName":"Garcia459","city":"New York459","state":"New York459","zip":"19203459","country":"United States459","phone":"123-455-6753459","email":"test@gmail.com459"},{"firstName":"Jose460","lastName":"Garcia460","city":"New York460","state":"New York460","zip":"19203460","country":"United States460","phone":"123-455-6753460","email":"test@gmail.com460"},{"firstName":"Jose461","lastName":"Garcia461","city":"New York461","state":"New York461","zip":"19203461","country":"United States461","phone":"123-455-6753461","email":"test@gmail.com461"},{"firstName":"Jose462","lastName":"Garcia462","city":"New York462","state":"New York462","zip":"19203462","country":"United States462","phone":"123-455-6753462","email":"test@gmail.com462"},{"firstName":"Jose463","lastName":"Garcia463","city":"New York463","state":"New York463","zip":"19203463","country":"United States463","phone":"123-455-6753463","email":"test@gmail.com463"},{"firstName":"Jose464","lastName":"Garcia464","city":"New York464","state":"New York464","zip":"19203464","country":"United States464","phone":"123-455-6753464","email":"test@gmail.com464"},{"firstName":"Jose465","lastName":"Garcia465","city":"New York465","state":"New York465","zip":"19203465","country":"United States465","phone":"123-455-6753465","email":"test@gmail.com465"},{"firstName":"Jose466","lastName":"Garcia466","city":"New York466","state":"New York466","zip":"19203466","country":"United States466","phone":"123-455-6753466","email":"test@gmail.com466"},{"firstName":"Jose467","lastName":"Garcia467","city":"New York467","state":"New York467","zip":"19203467","country":"United States467","phone":"123-455-6753467","email":"test@gmail.com467"},{"firstName":"Jose468","lastName":"Garcia468","city":"New York468","state":"New York468","zip":"19203468","country":"United States468","phone":"123-455-6753468","email":"test@gmail.com468"},{"firstName":"Jose469","lastName":"Garcia469","city":"New York469","state":"New York469","zip":"19203469","country":"United States469","phone":"123-455-6753469","email":"test@gmail.com469"},{"firstName":"Jose470","lastName":"Garcia470","city":"New York470","state":"New York470","zip":"19203470","country":"United States470","phone":"123-455-6753470","email":"test@gmail.com470"},{"firstName":"Jose471","lastName":"Garcia471","city":"New York471","state":"New York471","zip":"19203471","country":"United States471","phone":"123-455-6753471","email":"test@gmail.com471"},{"firstName":"Jose472","lastName":"Garcia472","city":"New York472","state":"New York472","zip":"19203472","country":"United States472","phone":"123-455-6753472","email":"test@gmail.com472"},{"firstName":"Jose473","lastName":"Garcia473","city":"New York473","state":"New York473","zip":"19203473","country":"United States473","phone":"123-455-6753473","email":"test@gmail.com473"},{"firstName":"Jose474","lastName":"Garcia474","city":"New York474","state":"New York474","zip":"19203474","country":"United States474","phone":"123-455-6753474","email":"test@gmail.com474"},{"firstName":"Jose475","lastName":"Garcia475","city":"New York475","state":"New York475","zip":"19203475","country":"United States475","phone":"123-455-6753475","email":"test@gmail.com475"},{"firstName":"Jose476","lastName":"Garcia476","city":"New York476","state":"New York476","zip":"19203476","country":"United States476","phone":"123-455-6753476","email":"test@gmail.com476"},{"firstName":"Jose477","lastName":"Garcia477","city":"New York477","state":"New York477","zip":"19203477","country":"United States477","phone":"123-455-6753477","email":"test@gmail.com477"},{"firstName":"Jose478","lastName":"Garcia478","city":"New York478","state":"New York478","zip":"19203478","country":"United States478","phone":"123-455-6753478","email":"test@gmail.com478"},{"firstName":"Jose479","lastName":"Garcia479","city":"New York479","state":"New York479","zip":"19203479","country":"United States479","phone":"123-455-6753479","email":"test@gmail.com479"},{"firstName":"Jose480","lastName":"Garcia480","city":"New York480","state":"New York480","zip":"19203480","country":"United States480","phone":"123-455-6753480","email":"test@gmail.com480"},{"firstName":"Jose481","lastName":"Garcia481","city":"New York481","state":"New York481","zip":"19203481","country":"United States481","phone":"123-455-6753481","email":"test@gmail.com481"},{"firstName":"Jose482","lastName":"Garcia482","city":"New York482","state":"New York482","zip":"19203482","country":"United States482","phone":"123-455-6753482","email":"test@gmail.com482"},{"firstName":"Jose483","lastName":"Garcia483","city":"New York483","state":"New York483","zip":"19203483","country":"United States483","phone":"123-455-6753483","email":"test@gmail.com483"},{"firstName":"Jose484","lastName":"Garcia484","city":"New York484","state":"New York484","zip":"19203484","country":"United States484","phone":"123-455-6753484","email":"test@gmail.com484"},{"firstName":"Jose485","lastName":"Garcia485","city":"New York485","state":"New York485","zip":"19203485","country":"United States485","phone":"123-455-6753485","email":"test@gmail.com485"},{"firstName":"Jose486","lastName":"Garcia486","city":"New York486","state":"New York486","zip":"19203486","country":"United States486","phone":"123-455-6753486","email":"test@gmail.com486"},{"firstName":"Jose487","lastName":"Garcia487","city":"New York487","state":"New York487","zip":"19203487","country":"United States487","phone":"123-455-6753487","email":"test@gmail.com487"},{"firstName":"Jose488","lastName":"Garcia488","city":"New York488","state":"New York488","zip":"19203488","country":"United States488","phone":"123-455-6753488","email":"test@gmail.com488"},{"firstName":"Jose489","lastName":"Garcia489","city":"New York489","state":"New York489","zip":"19203489","country":"United States489","phone":"123-455-6753489","email":"test@gmail.com489"},{"firstName":"Jose490","lastName":"Garcia490","city":"New York490","state":"New York490","zip":"19203490","country":"United States490","phone":"123-455-6753490","email":"test@gmail.com490"},{"firstName":"Jose491","lastName":"Garcia491","city":"New York491","state":"New York491","zip":"19203491","country":"United States491","phone":"123-455-6753491","email":"test@gmail.com491"},{"firstName":"Jose492","lastName":"Garcia492","city":"New York492","state":"New York492","zip":"19203492","country":"United States492","phone":"123-455-6753492","email":"test@gmail.com492"},{"firstName":"Jose493","lastName":"Garcia493","city":"New York493","state":"New York493","zip":"19203493","country":"United States493","phone":"123-455-6753493","email":"test@gmail.com493"},{"firstName":"Jose494","lastName":"Garcia494","city":"New York494","state":"New York494","zip":"19203494","country":"United States494","phone":"123-455-6753494","email":"test@gmail.com494"},{"firstName":"Jose495","lastName":"Garcia495","city":"New York495","state":"New York495","zip":"19203495","country":"United States495","phone":"123-455-6753495","email":"test@gmail.com495"},{"firstName":"Jose496","lastName":"Garcia496","city":"New York496","state":"New York496","zip":"19203496","country":"United States496","phone":"123-455-6753496","email":"test@gmail.com496"},{"firstName":"Jose497","lastName":"Garcia497","city":"New York497","state":"New York497","zip":"19203497","country":"United States497","phone":"123-455-6753497","email":"test@gmail.com497"},{"firstName":"Jose498","lastName":"Garcia498","city":"New York498","state":"New York498","zip":"19203498","country":"United States498","phone":"123-455-6753498","email":"test@gmail.com498"},{"firstName":"Jose499","lastName":"Garcia499","city":"New York499","state":"New York499","zip":"19203499","country":"United States499","phone":"123-455-6753499","email":"test@gmail.com499"}];
--------------------------------------------------------------------------------