import React, { Component, PropTypes } from "react";
import { Link} from "react-router";
import imagesLoaded from "imagesloaded";
import Isotope from "isotope-layout";
import Fuse from "fuse.js";
import _ from "lodash";
import $ from "jquery";
import FilterBar from "./FilterBar";
import Pagination from "./Pagination";
export class GridItem extends Component {
render () {
var nSubItems = this.props.item[this.props.subItemsType];
if (Array.isArray(nSubItems)) {
nSubItems = nSubItems.length;
}
var subItemsLabel = this.props.subItemsType;
if (nSubItems < 2) {
subItemsLabel = subItemsLabel.rstrip("s");
}
const to = "/" + this.props.itemsType.rstrip("s") + "/" + this.props.item.id;
const id = "grid-item-" + this.props.item.type + "/" + this.props.item.id;
return (
{this.props.item.name}
{nSubItems}{subItemsLabel}
);
}
}
GridItem.propTypes = {
item: PropTypes.object.isRequired,
itemsType: PropTypes.string.isRequired,
subItemsType: PropTypes.string.isRequired
};
const ISOTOPE_OPTIONS = { /** Default options for Isotope grid layout. */
getSortData: {
name: ".name",
nSubitems: ".sub-items .n-sub-items"
},
transitionDuration: 0,
sortBy: "name",
itemSelector: ".grid-item",
percentPosition: true,
layoutMode: "fitRows",
filter: "*",
fitRows: {
gutter: 0
}
};
export class Grid extends Component {
constructor (props) {
super(props);
// Init grid data member
this.iso = null;
this.handleFiltering = this.handleFiltering.bind(this);
}
createIsotopeContainer () {
if (this.iso == null) {
this.iso = new Isotope(this.refs.grid, ISOTOPE_OPTIONS);
}
}
handleFiltering (props) {
// If no query provided, drop any filter in use
if (props.filterText == "") {
return this.iso.arrange(ISOTOPE_OPTIONS);
}
// Use Fuse for the filter
var result = new Fuse(
props.items,
{
"keys": ["name"],
"threshold": 0.4,
"include": ["score"]
}).search(props.filterText);
// Apply filter on grid
this.iso.arrange({
filter: function () {
var name = $(this).find(".name").text();
return result.find(function (item) { return item.item.name == name; });
},
transitionDuration: "0.4s",
getSortData: {
relevance: function (item) {
var name = $(item).find(".name").text();
return result.reduce(function (p, c) {
if (c.item.name == name) {
return c.score + p;
}
return p;
}, 0);
}
},
sortBy: "relevance"
});
this.iso.updateSortData();
this.iso.arrange();
}
shouldComponentUpdate(nextProps, nextState) {
return !_.isEqual(this.props, nextProps) || !_.isEqual(this.state, nextState);
}
componentWillReceiveProps(nextProps) {
if (!_.isEqual(nextProps.filterText, this.props.filterText)) {
this.handleFiltering(nextProps);
}
}
componentDidMount () {
// Setup grid
this.createIsotopeContainer();
// Only arrange if there are elements to arrange
if (_.get(this, "props.items.length", 0) > 0) {
this.iso.arrange();
}
}
componentDidUpdate(prevProps) {
// The list of keys seen in the previous render
let currentKeys = _.map(
prevProps.items,
(n) => "grid-item-" + n.type + "/" + n.id);
// The latest list of keys that have been rendered
let newKeys = _.map(
this.props.items,
(n) => "grid-item-" + n.type + "/" + n.id);
// Find which keys are new between the current set of keys and any new children passed to this component
let addKeys = _.difference(newKeys, currentKeys);
// Find which keys have been removed between the current set of keys and any new children passed to this component
let removeKeys = _.difference(currentKeys, newKeys);
if (removeKeys.length > 0) {
_.each(removeKeys, removeKey => this.iso.remove(document.getElementById(removeKey)));
this.iso.arrange();
}
if (addKeys.length > 0) {
this.iso.addItems(_.map(addKeys, (addKey) => document.getElementById(addKey)));
this.iso.arrange();
}
var iso = this.iso;
// Layout again after images are loaded
imagesLoaded(this.refs.grid).on("progress", function() {
// Layout after each image load, fix for responsive grid
if (!iso) { // Grid could have been destroyed in the meantime
return;
}
iso.layout();
});
}
render () {
var gridItems = [];
const itemsType = this.props.itemsType;
const subItemsType = this.props.subItemsType;
this.props.items.forEach(function (item) {
gridItems.push();
});
return (
{/* Sizing element */}
{/* Other items */}
{ gridItems }