selectorClass

Default: false

This string is used to find the elements that filter/sort the boxes.

To learn more, go to Filter.

<button class="selector" data-filter="">all</button>
<button class="selector" data-filter="letter-r">Has the letter "R"</button>
<button class="selector" data-filter="letter-l">Has the letter "L"</button>
<button class="selector" data-filter="letter-n">Has the letter "N"</button>

<div id="container">
  <div class="box letter-r" style="background-color: red;" data-aspect-ratio="1.333"></div>
  <div class="box letter-r letter-n" style="background-color: orange;" data-aspect-ratio="1"></div>
  <div class="box letter-l" style="background-color: yellow;" data-aspect-ratio="1.6"></div>
  <div class="box letter-r letter-n" style="background-color: green;" data-aspect-ratio="1.333"></div>
  <div class="box letter-l" style="background-color: blue;" data-aspect-ratio=".75"></div>
  <div class="box letter-r letter-l" style="background-color: purple;" data-aspect-ratio="1.333"></div>
</div>
var tessarray = new Tessarray("#container", ".box", {
  selectorClass: "selector"
});

selectorEventListener

Default: "click"

This is the event that binds filtering and sorting functionality to the inputs with the selectorClass.

all
Red
Yellow
Blue
<div class="selector-12" style="background-color: white" data-filter="">all</div>
<div class="selector-12" style="background-color: red" data-filter="red">Red</div>
<div class="selector-12" style="background-color: yellow" data-filter="yellow">Yellow</div>
<div class="selector-12" style="background-color: blue" data-filter="blue">Blue</div>

<div id="container-12">
  <div class="box red" style="background-color: red;" data-aspect-ratio="1.333"></div>
  <div class="box red yellow" style="background-color: orange;" data-aspect-ratio="1"></div>
  <div class="box yellow" style="background-color: yellow;" data-aspect-ratio="1.6"></div>
  <div class="box blue yellow" style="background-color: green;" data-aspect-ratio="1.33"></div>
  <div class="box blue" style="background-color: blue;" data-aspect-ratio=".75"></div>
  <div class="box blue red" style="background-color: purple;" data-aspect-ratio="1.333"></div>
</div>
var tessarray = new Tessarray("#container", ".box", {
  selectorClass: "selector",
  selectorEventListener: "mouseenter"
});

initialRender

Default: { filter: "", sort: "", order: "" }

{
  filter: "", 
  sort: "", 
  order: "" 
}

This option controls how the boxes are filtered, sorted, and ordered on the initial render. Add a value to filter or sort on equal to one of the selectors' data-filter or data-sort values. Order is ascending by default. If you want you want to descending order, set the order value to "desc" or "descending".

red
orange
yellow
green
blue
purple
<input type="text" id="input" placeholder='eg. "red", "alphabetical"...'/>
<div id="container">
  <div class="box alphabetical has-red" style="background-color: red;" data-alphabetical="5" data-aspect-ratio="1.333"></div>
  <div class="box alphabetical has-red has-yellow" style="background-color: orange;" data-alphabetical="3" data-has-red="1" data-aspect-ratio="1"></div>
  <div class="box alphabetical has-yellow" style="background-color: yellow;" data-alphabetical="6" data-aspect-ratio="1.6"></div>
  <div class="box alphabetical has-yellow has-blue" style="background-color: green;" data-alphabetical="2"  data-aspect-ratio="1.33"></div>
  <div class="box alphabetical has-blue" style="background-color: blue;" data-alphabetical="1" data-aspect-ratio=".75"></div>
  <div class="box alphabetical has-red has-blue" style="background-color: purple;" data-alphabetical="4" data-has-red="3" data-aspect-ratio="1.333"></div>
</div>
var tessarray = new Tessarray("#container", ".box", {
  filters: ["has-red", "has-yellow", "has-blue"],
  sorters: ["alphabetical"]
});
var input = document.getElementById('input');
input.addEventListener('input', function(event) {
  if (event.target.value === "alphabetical") {
    tessarray.sort("alphabetical");
  } else if (event.target.value === "reverse alphabetical") {
    tessarray.sort("alphabetical", "desc")
  } else if (event.target.value === "red") {
    tessarray.filter("has-red");
  } else if (event.target.value === "yellow") {
    tessarray.filter("has-yellow");
  } else if (event.target.value === "blue") {
    tessarray.filter("has-blue");
  } else {
    if (tessarray.sortedBy !== "") {
      tessarray.filterAndSort("", "", "");
    }
  }
});
<button class="selector" data-filter="">all</button>
<button class="selector" data-filter="letter-r">Has the letter "R"</button>
<button class="selector" data-filter="letter-l">Has the letter "L"</button>
<button class="selector" data-filter="letter-n">Has the letter "N"</button>

<div id="container">
  <div class="box letter-r" style="background-color: red;" data-aspect-ratio="1.333"></div>
  <div class="box letter-r letter-n" style="background-color: orange;" data-aspect-ratio="1"></div>
  <div class="box letter-l" style="background-color: yellow;" data-aspect-ratio="1.6"></div>
  <div class="box letter-r letter-n" style="background-color: green;" data-aspect-ratio="1.33"></div>
  <div class="box letter-l" style="background-color: blue;" data-aspect-ratio=".75"></div>
  <div class="box letter-r letter-l" style="background-color: purple;" data-aspect-ratio="1.333"></div>
</div>
var tessarray = new Tessarray("#container", ".box", {
  selectorClass: "selector",
  defaultCategory: "letter-r"
});

filters and sorters

Default: []

If you want to filter or sort on values that are not used in a selector, you must first add those values to the filters or sorters arrays in the options.

Tessarray iterates over the selectors and saves the filters and sorters in tessarray.fitlers and tessarray.sortData. Tessarray then iterates over these and caches the values for each filter and sort on each box. You can see the data stored on individual boxes with tessarray.boxObjects[index].filters and tessarray.boxObjects[index].sortData. Adding values to filters and sorters in the options ensures ensures that their values are also cached on the boxes despite there being no selector.

red
orange
yellow
green
blue
purple
<input type="text" id="text-input" placeholder='eg. "red", "alphabetical"...'/>
<div id="container">
  <div class="box alphabetical has-red" style="background-color: red;" data-alphabetical="5" data-aspect-ratio="1.333"></div>
  <div class="box alphabetical has-red has-yellow" style="background-color: orange;" data-alphabetical="3" data-has-red="1" data-aspect-ratio="1"></div>
  <div class="box alphabetical has-yellow" style="background-color: yellow;" data-alphabetical="6" data-aspect-ratio="1.6"></div>
  <div class="box alphabetical has-yellow has-blue" style="background-color: green;" data-alphabetical="2"  data-aspect-ratio="1.33"></div>
  <div class="box alphabetical has-blue" style="background-color: blue;" data-alphabetical="1" data-aspect-ratio=".75"></div>
  <div class="box alphabetical has-red has-blue" style="background-color: purple;" data-alphabetical="4" data-has-red="3" data-aspect-ratio="1.333"></div>
</div>
var tessarray = new Tessarray("#container", ".box", {
  filters: ["has-red", "has-yellow", "has-blue"],
  sorters: ["alphabetical"]
});
var input = document.getElementById("text-input");
input.addEventListener("input", function(event) {
  if (event.target.value === "alphabetical") {
    tessarray.sort("alphabetical");
  } else if (event.target.value === "reverse alphabetical") {
    tessarray.sort("alphabetical", "desc")
  } else if (event.target.value === "red") {
    tessarray.filter("has-red");
  } else if (event.target.value === "yellow") {
    tessarray.filter("has-yellow");
  } else if (event.target.value === "blue") {
    tessarray.filter("has-blue");
  } else {
    if (tessarray.sortedBy !== "") {
      tessarray.filterAndSort("", "", "");
    }
  }
});

resize

Default: true

Adds an event listener to the window listening for the resize event. When the window resizes it calls tessarray.renderOnResize(), which checks if the width of the container has changed. If so, it calls tessarray.render().

If you make the container width static through css or the flickr option containerWidth, or you want to handle all of the resizing yourself, set this to false to prevent renderOnResize from firing unneccessarily.

Try resizing the browser window and then click the reload button.

<div id="container">
  <div class="box" style="background-color: red;" data-aspect-ratio="1.333"></div>
  <div class="box" style="background-color: orange;" data-aspect-ratio="1"></div>
  <div class="box" style="background-color: yellow;" data-aspect-ratio="1.6"></div>
  <div class="box" style="background-color: green;" data-aspect-ratio="1.33"></div>
  <div class="box" style="background-color: blue;" data-aspect-ratio=".75"></div>
  <div class="box" style="background-color: purple;" data-aspect-ratio="1.333"></div>
</div>
var tessarray = new Tessarray("#container", ".box", {
  resize: false
});

Transitions

By default the transition options are objects. If you want to change the attributes of a transition, you have to define all of the attributes in the object.

var tessarray = new Tessarray("#container", ".box", {
  containerTransition: {
    duration: 500,
    timingFunction: "cubic-bezier(0.320, 1.385, 0.730, -0.470)",
    duration: 0
  }
});

If you don't want that transition at all, set the value to false.

tessarray = new Tessarray("#container", ".box", {
  containerTransition: false
});

If you want to write your own transition, write it as a string and pass it to the option as such:

tessarray = new Tessarray("#container", "box", {
  boxTransition: "transform 500ms ease-in 0ms, height 500ms ease-in 0ms, width 500ms ease-in 0ms, opacity 400ms ease-out 0ms"
});

It's important to note that the code above only adds an opacity transition to the boxTransition, as the default boxTransition has identical transitions on transform, height, and width.

containerTransition

Default: { duration: 375, timingFunction: "ease-in", delay: 0 }

{
  duration: 375, 
  timingFunction: "ease-in", 
  delay: 0 
}

The default value evaluates to: transition: opacity 350ms ease-in 0ms

This transition is triggered once the container is done loading. It is typically used to fade in the container once tessarray knows the dimensions of the boxes for the initial render.

This text is below the Tessarray object and should slide down when the container is loaded.

<div id="container">
  <div class="box">
    <img class="image" src="https://source.unsplash.com/category/nature/720x1080"/>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/category/nature/900x900"/>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/category/people/1600x900"/>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/category/nature/800x600"/>
  </div>
</div>
<p>This text is below the Tessarray object. This should slide down</p>
#container {
  height: 0px;
  overflow: hidden;
}
.image {
  height: 100%;
  width: 100%;
}
var tessarray = new Tessarray("#container", ".box", {
  containerTransition: "height 500ms ease-in, opacity 350ms ease-in"
});

boxTransition

Default: { duration: 375, timingFunction: "ease-in", delay: 0 }

{
  duration: 375, 
  timingFunction: "ease-in", 
  delay: 0 
}

The default value evaluates to transition: transform 500ms ease-in 0ms, height 500ms ease-in 0ms, width 500ms ease-in 0ms;

This controls most of the boxes' transitions on transform, height, and width. This option does not control how the boxes are transformed when they are scaled out (such as when they are filtered). This transition is set on every box every time tessarray.render is called except for the initial render, when it set immediately after.

This example uses a slower, smoother transition, and slows the boxTransformOutTransition to match.

<button class="selector" data-filter="">all</button>
<button class="selector" data-filter="letter-r">Has the letter "R"</button>
<button class="selector" data-filter="letter-l">Has the letter "L"</button>
<button class="selector" data-filter="letter-n">Has the letter "N"</button>

<div id="container">
  <div class="box letter-r" style="background-color: red;" data-aspect-ratio="1.333"></div>
  <div class="box letter-r letter-n" style="background-color: orange;" data-aspect-ratio="1"></div>
  <div class="box letter-l" style="background-color: yellow;" data-aspect-ratio="1.6"></div>
  <div class="box letter-r letter-n" style="background-color: green;" data-aspect-ratio="1.33"></div>
  <div class="box letter-l" style="background-color: blue;" data-aspect-ratio=".75"></div>
  <div class="box letter-r letter-l" style="background-color: purple;" data-aspect-ratio="1.333"></div>
</div>
var tessarray = new Tessarray("#container",".box", {
  selectorClass: "selector",
  boxTransition: {
    duration: 700,
    timingFunction: "cubic-bezier(0.215, 0.61, 0.355, 1)",
    delay: 0
  },
  boxTransformOutTransition: {
    duration: 350,
    timingFunction: "linear",
    delay: 0
  }
});

boxTransformOutTransition

Default: { duration: 250, timingFunction: "ease-in", delay: 0 }

{
  duration: 250, 
  timingFunction: "ease-in", 
  delay: 0 
}

This controls the boxes' transitions when they disappear from the layout. When tessarray.render is called every box that is filtered out has its transition overwritten by boxTransformOutTransition before it is scaled down to nothing.

This transition is indepented of boxTransition because the transitions out felt sluggish when they shared the same duration.

<button class="selector" data-filter="">All</button>
<button class="selector" data-filter="nature">Nature</button>
<button class="selector" data-filter="people">People</button>
<div id="container">
  <div class="box nature">
    <img class="image" src="https://source.unsplash.com/category/nature/720x1080"/>
  </div>
  <div class="box nature">
    <img class="image" src="https://source.unsplash.com/category/nature/900x900"/>
  </div>
  <div class="box people">
    <img class="image" src="https://source.unsplash.com/category/people/1600x900"/>
  </div>
  <div class="box nature">
    <img class="image" src="https://source.unsplash.com/category/nature/800x600"/>
  </div>
</div>
.image {
  height: 100%;
  width: 100%
}
var tessarray = new Tessarray("#container", ".box", {
  selectorClass: "selector",
  boxTransformOutTransition: {
    duration: 0,
    timingFunction: "ease-in",
    delay: 0
  }
});

Class Hooks

containerLoadedClass

Default: "container-is-loaded"

This class is added to the container once Tessarray knows the aspect ratios for every box, immediately before the initial render.

<div id="container">
  <div class="box nature">
    <img class="image" src="https://source.unsplash.com/category/nature/720x1080"/>
  </div>
  <div class="box nature">
    <img class="image" src="https://source.unsplash.com/category/nature/900x900"/>
  </div>
  <div class="box people">
    <img class="image" src="https://source.unsplash.com/category/people/1600x900"/>
  </div>
  <div class="box nature">
    <img class="image" src="https://source.unsplash.com/category/nature/800x600"/>
  </div>
</div>
#container {
  left: 200%;
}
#container.container-is-loaded {
  left: 0%;
}
.image {
  height: 100%;
  width: 100%
}
var tessarray = new Tessarray("#container", ".box", {
  containerTransition: "opacity 600ms ease-in 0ms, left 600ms cubic-bezier(0.215, 0.61, 0.355, 1) 0ms"
});

boxLoadedClass

Default: "box-is-loaded"

This class is added to each box once the image within the box has loaded. If Tessarray cannot find an image in the box, this class will be added as soon as Tessarray reads the aspect ratio.

<div id="container">
  <div class="box nature" data-width="720" data-height="1080">
    <img class="image" src="https://source.unsplash.com/category/nature/720x1080"/>
  </div>
  <div class="box nature" data-width="900" data-height="900">
    <img class="image" src="https://source.unsplash.com/category/nature/900x900"/>
  </div>
  <div class="box people" data-width="1600" data-height="900">
    <img class="image" src="https://source.unsplash.com/category/people/1600x900"/>
  </div>
  <div class="box nature" data-width="800" data-height="600">
    <img class="image" src="https://source.unsplash.com/category/nature/800x600"/>
  </div>
</div>
.image {
  height: 100%;
  width: 100%;
  opacity: 0;
  transition: opacity 350ms ease-in 0ms;
}
.box-is-loaded .image {
  opacity: 1;
}
.box {
  background-color: grey;
}
var tessarray = new Tessarray("#container", ".box", {
  boxLoadedClass: "box-is-loaded"
});

Callbacks

The default values of the callbacks are false. To use a callback, set the callback option's value equal to the function you want to fire.

onContainerLoad

Default: false

onContainerLoad is triggered once Tessarray knows the aspect ratios for every box, immediately before the initial render.

<div id="container">
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/buildings"/>
    <div class="aspect-ratio-container">
      <p class="aspect-ratio"></p>
    </div>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/food"/>
    <div class="aspect-ratio-container">
      <p class="aspect-ratio"></p>
    </div>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/nature"/>
    <div class="aspect-ratio-container">
      <p class="aspect-ratio"></p>
    </div>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/people"/>
    <div class="aspect-ratio-container">
      <p class="aspect-ratio"></p>
    </div>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/technology"/>
    <div class="aspect-ratio-container">
      <p class="aspect-ratio"></p>
    </div>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/objects"/>
    <div class="aspect-ratio-container">
      <p class="aspect-ratio"></p>
    </div>
  </div>
</div>
.image {
  height: 100%;
  width: 100%
}
.aspect-ratio-container {
  position: absolute;
  width: 100%;
  bottom: 0;
  text-align: center;
}
.aspect-ratio {
  color: white;
  font-size: 1.5em;
  margin: 0;
}
var tessarray = new Tessarray("#container", ".box", {
  onContainerLoad: function(tessarray) {
    for (var i = 0; i < tessarray.boxObjects.length; i++) {
      var aspectRatioParagraph = tessarray.boxObjects[i].boxNode.querySelector(".aspect-ratio");
      var aspectRatio = tessarray.boxObjects[i].aspectRatio;
      aspectRatioParagraph.innerHTML = Number((aspectRatio).toFixed(2)).toString() + ":1";
    }
  }
});

onBoxLoad

Default: false

How it is called: tessarray.onBoxLoad(boxObject)

This callback is called for each box once the image within the box has completely loaded. If Tessarray cannot find an image in the box, this class will be added as soon as Tessarray reads the aspect ratio.

The onBoxLoad callback is passed one argument a boxObject. The boxObject is a JavaScript object that contains data for the box it represents. To learn more go here.

<button id="reload">Reload</button>
<div id="loader">
  <progress id="bar" value="0" max="6" ng-model="prog"></progress>
</div>
<div id="container">
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/buildings"/>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/food"/>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/nature"/>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/people"/>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/technology"/>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/objects"/>
  </div>
</div>
#container .image {
  height: 100%;
  width: 100%;
}
#loader {
  width: 100%;
  text-align: center
}
#loader progress {
  margin: 100px auto;
  display: inline-block;
  width: 60%;
  border-radius: 10px;
}
#loader progress::-webkit-progress-bar {
  height: 13px;
  border: 1px solid #170F2F;
  border-radius: 10px;
  background-color: #170F2F;
}
#loader progress::-webkit-progress-value {
  height: 12px;
  background-color: #FF4E47;
  border: 1px solid #170F2F;
  border-radius: 10px;
}
var progressComplete = function() {
  var progressContainer = document.getElementById("loader");
  var container = document.getElementById("container");
  progressContainer.style.opacity = 0;
  progressContainer.style.display = "none";
  container.style.opacity = 1;
};
var tessarray = new Tessarray("#container", ".box", {
  onContainerLoad: function(tessarray) {
    tessarray.container.style.opacity = "0";
  },
  onBoxLoad: function(box) {
    var progressBar = document.getElementById("bar");
    progressBar.value += 1;
    if (progressBar.value === 6) {
      setTimeout(progressComplete, 200);
    }
  }
});

onRender

Default: false

How it is called: tessarray.onRender(tessarray, initialRender)

Arguments: tessarray this Tessarray instance, initialRender a boolean indicating whether this is the initial render or not.

onRender is called every time render is called. True is passed to initialRender if it is the first render, else false is passed.

targetRowHeight = 275

targetRowHeightTolerance = 0.25

<p><code>tessarray.options.flickr.targetRowHeight = 275</code></p>
<p><code>tessarray.options.flickr.targetRowHeightTolerance = <span id="current-tolerance">0.25</span></code></p>
<input type="range" id="range-tolerance" value="25" min="0" max="100">
<div id="container">
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/buildings"/>
    <div class="aspect-ratio-container">
      <p class="original-aspect-ratio aspect-ratio"></p>
      <p class="current-aspect-ratio aspect-ratio"></p>
    </div>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/food"/>
    <div class="aspect-ratio-container">
      <p class="original-aspect-ratio aspect-ratio"></p>
      <p class="current-aspect-ratio aspect-ratio"></p>
    </div>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/nature"/>
    <div class="aspect-ratio-container">
      <p class="original-aspect-ratio aspect-ratio"></p>
      <p class="current-aspect-ratio aspect-ratio"></p>
    </div>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/people"/>
    <div class="aspect-ratio-container">
      <p class="original-aspect-ratio aspect-ratio"></p>
      <p class="current-aspect-ratio aspect-ratio"></p>
    </div>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/technology"/>
    <div class="aspect-ratio-container">
      <p class="original-aspect-ratio aspect-ratio"></p>
      <p class="current-aspect-ratio aspect-ratio"></p>
    </div>
  </div>
  <div class="box">
    <img class="image" src="https://source.unsplash.com/random/objects"/>
    <div class="aspect-ratio-container">
      <p class="original-aspect-ratio aspect-ratio"></p>
      <p class="current-aspect-ratio aspect-ratio"></p>
    </div>
  </div>
</div>
#range-tolerance {
  width: 100%;
}
.image {
  height: 100%;
  width: 100%;
}
.aspect-ratio-container {
  position: absolute;
  width: 100%;
  bottom: 0;
  text-align: center;
}
.aspect-ratio {
  color: white;
  font-size: 1.5em;
  margin: 0;
}
var tessarray = new Tessarray("#container", ".box", {
  onContainerLoad: function(tessarray) {
    for (var i = 0; i < tessarray.boxObjects.length; i++) {
      var originalAspectRatioParagraph = tessarray.boxObjects[i].boxNode.querySelector('.original-aspect-ratio');
      var originalAspectRatio = tessarray.boxObjects[i].aspectRatio;
      originalAspectRatioParagraph.innerHTML = "Original: " + Number((originalAspectRatio).toFixed(2)).toString() + ":1";
    }
  },
  onRender: function(tessarray) {
    for (var i = 0; i < tessarray.boxObjects.length; i++) {
      var currentAspectRatioParapraph = tessarray.boxObjects[i].boxNode.querySelector('.current-aspect-ratio');
      var currentAspectRatio = tessarray.layoutGeometry.boxes[i].width / tessarray.layoutGeometry.boxes[i].height;
      currentAspectRatioParapraph.innerHTML = "Current: " + Number((currentAspectRatio).toFixed(2)).toString() + ":1";
    }
  },
  flickr: {targetRowHeight: 275}
});

var changeRowHeightTolerance = function() {
  var rowHeightTolerance = parseFloat(document.getElementById('range-tolerance').value) / 100;
  document.getElementById("current-tolerance").innerHTML = rowHeightTolerance;
  tessarray.options.flickr.targetRowHeightTolerance = rowHeightTolerance;
  tessarray.render();
};

document.getElementById('range-tolerance').addEventListener('input', tessarray.debounce(changeRowHeightTolerance, 100));

flickr options

Default: {}

These are the options that Flickr's Justified Layout provides to manipulate the layout. The default evaluates to this:

{
  containerWidth: 1060,
  containerPadding: 10,
  boxSpacing: 10,
  targetRowHeight: 320,
  targetRowHeightTolerance: 0.25,
  maxNumRows: Number.POSITIVE_INFINITY,
  forceAspectRatio: false, 
  showWidows: true,
  fullWidthBreakoutRowCadence: false
}

This is how you would alter one attribute of the flickr options on insantiation:

var tessarray = new Tessarray("#container", ".box", {
  flickr: {
    showWidows: false
  }
});

You can alter flickr options after instantiation: tessarray.options.flickr.showWidows = true;

To apply changes made to the flickr options, call tessarray.render().

There are only two attributes of the flickr options that you should not change after the initial render: containerPadding and containerWidth. If you want to change container width, change the width of the container element directly instead.

To learn more, go to Flickr's Justified Layout's documentation.