Browse files

Merge branch 'api-init'

  • Loading branch information...
2 parents 651e915 + ed66e97 commit 498a26c52018a5d1a1a15cbda9a3bf63a7168238 @imakewebthings imakewebthings committed Feb 23, 2012
View
3 .gitignore
@@ -1,4 +1,5 @@
# Ignore file containing API keys
keys.php
.DS_Store
-.sass-cache/
+.sass-cache/
+.jshintrc
View
9 Makefile
@@ -1,6 +1,9 @@
-JS_SOURCES = src/js/jquery.infinitescroller.min.js \
- src/js/jquery.mousewheel.pack.js \
- src/js/jquery.stackview.js
+JS_SOURCES = src/js/microtemplating.js\
+ src/js/jquery.stackview.base.js \
+ src/js/jquery.stackview.infinite.js\
+ src/js/jquery.stackview.navigation.js\
+ src/js/jquery.stackview.stackcache.js\
+ src/js/jquery.stackview.templates.js
JS_OUTPUT = lib/jquery.stackview.min.js
View
2 README.md
@@ -6,7 +6,7 @@ Check out the [Project Page](http://librarylab.law.harvard.edu/projects/stackvie
## Development
-A single concatenated and minified `jquery.stackview.min.js` file containing StackView and all its dependencies is located in `/lib`. Developers making changes to the project should do so in `/src` and compile the minified file by running `make js`. If any files in `/src` are added or renamed, they should be added to this list of source files in `Makefile`.
+A single concatenated and minified `jquery.stackview.min.js` file containing Stack View and all its dependencies is located in `/lib`. Developers making changes to the project should do so in `/src` and compile the minified file by running `make js`. If any files in `/src` are added or renamed, they should be added to this list of source files in `Makefile`.
Tests are written using [Jasmine](http://pivotal.github.com/jasmine/).
View
59 demo/basic.html
@@ -0,0 +1,59 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+<title>StackView Basic</title>
+
+<link rel="icon" href="favicon.ico" type="image/x-icon" />
+
+<!-- stackview.css to style the stack -->
+<link rel="stylesheet" href="../lib/jquery.stackview.css" type="text/css" />
+
+<!-- stackview.js and all js dependencies -->
+<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
+<script type="text/javascript" src="../lib/jquery.stackview.min.js"></script>
+
+</head>
+
+<body>
+
+<div id="basic-stack"></div>
+
+<script type="text/javascript">
+ $(function () {
+ var data =
+ {"start": "-1", "limit": "0", "num_found": "2", "docs":
+ [
+ {
+ "title": "Blankets",
+ "creator": [
+ "Craig Thompson"
+ ],
+ "measurement_page_numeric": 582,
+ "measurement_height_numeric": 25,
+ "shelfrank": 13,
+ "pub_date": "2003",
+ "link": "http://holliscatalog.harvard.edu/?itemid=|library/m/aleph|009189638"
+ },
+ {
+ "title": "Persepolis",
+ "creator": [
+ "Marjane Satrapi"
+ ],
+ "measurement_page_numeric": 153,
+ "measurement_height_numeric": 24,
+ "shelfrank": 64,
+ "pub_date": "2003",
+ "link": "http://holliscatalog.harvard.edu/?itemid=|library/m/aleph|009098946"
+ }
+ ]
+ };
+
+ $('#basic-stack').stackView({data: data});
+ });
+</script>
+
+</body>
+</html>
View
270 demo/documentation.html
@@ -0,0 +1,270 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+<title>Stack View Documentation</title>
+
+<link rel="icon" href="favicon.ico" type="image/x-icon" />
+
+<!-- CSS just for this page -->
+<style type="text/css">
+h1, h2 {
+ margin: 5px 5px 10px 5px;
+ padding: 0;
+ color:#444;
+ font-weight:normal;
+}
+
+h3 {
+ margin: 10px 5px 0px 5px;
+ padding:0;
+ color:#444;
+ font-size:.9em;
+ font-weight:bold;
+}
+
+body {
+ font-family:'Helvetica', 'Arial', sans-serif;
+ background:#faf5f0;
+ min-width:845px;
+ max-width:1145px;
+ font-size: 1.1em;
+ color: #333333;
+ border: none;
+ line-height:normal;
+ margin:0px auto;
+}
+
+p {
+ margin: 5px 5px 15px 5px;
+ font-size: .8em;
+ line-height: 1.2em;
+}
+
+a {
+ color: #09F;
+ text-decoration: none;
+}
+
+.container {
+ float:left;
+ width:45%;
+ margin:15px 15px 15px 5px;
+ clear:both;
+}
+
+.explanation {
+ float:left;
+ width:48%;
+ margin:15px 15px 15px 25px;
+}
+
+.requirements {
+ float:left;
+ margin:15px 15px 15px 15px;
+ clear:both;
+}
+
+#doc-nav {
+ clear:both;
+ margin-left: 5px;
+ float:left;
+ width:23%;
+}
+
+#doc-nav ul{
+ list-style-type:none;
+ padding:0 10px 0 0;
+}
+
+#docs {
+ float:left;
+ width:70%;
+}
+
+#docs li {
+ font-size: .8em;
+}
+
+h1 {
+ font-size:2.1em;
+ padding-top:9px;
+}
+
+h2 {
+ font-size:1.2em;
+ color:#F60;
+}
+
+pre {
+ background-color: #fff;
+}
+
+#nav {
+ padding:0 150px 0 0;
+ margin:0;
+ list-style-type:none;
+ float:right;
+}
+
+#nav li {
+ display:block;
+ float:left;
+ padding:0 30px 0 0;
+}
+
+#nav li a {
+ display:block;
+ padding:25px 0 0 0;
+}
+
+.footer {
+ clear:both;
+ font-size:.7em;
+ float:right;
+ padding:25px 30px 25px 0;
+}
+</style>
+
+<!-- stackview.css to style the stack -->
+<link rel="stylesheet" href="../lib/jquery.stackview.css" type="text/css" />
+
+<!-- stackview.js and all js dependencies -->
+<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
+<script type="text/javascript" src="../lib/jquery.stackview.min.js"></script>
+
+</head>
+
+<body>
+ <ul id="nav">
+ <li><a href="index.html">About</a></li>
+ <li><a href="documentation.html">Documentation</a></li>
+ <li><a href="examples.html">Examples</a></li>
+ <a href="http://www.librarylab.law.harvard.edu/"><img src="liblabstamp.png"></a>
+ </ul>
+ <a href="https://github.com/harvard-lil/stackview"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://a248.e.akamai.net/assets.github.com/img/30f550e0d38ceb6ef5b81500c64d970b7fb0f028/687474703a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67" alt="Fork me on GitHub"></a>
+ <h1>Stack View Documentation</h1>
+
+ <div id="docs">
+ <div class="requirements">
+ <h2>Requirements</h2>
+ <p>Stack View requires <a href="http://jquery.com/">jQuery</a> and two additional plugins to enable further functionality. These plugins are bundled with jquery.stackview.min.js and do not need to be included separately.</p>
+ <ul>
+ <li>The <a href="http://brandonaaron.net/code/mousewheel/docs">mousewheel plugin</a> adds mouse wheel support to stack scrolling.</li>
+ <li>The infiniteScroller plugin enables on-call dynamic loading of new books.</li>
+ </ul>
+ <p>A small set of images is also necessary for drawing the stack. They can be found in the lib/images directory.</p>
+
+ <h2>How to Use</h2>
+ <p>You can start by looking at the most <a href="basic.html">basic demo</a>.</p>
+ <p>After including the required files, place a div in your html code where you would like Stack View to appear.</p>
+ <pre class="code language-html">
+ &lt;div id="stackview"&gt;&lt;/div&gt;
+ </pre>
+ <p>In your javascript, create some data for Stack View to use.</p>
+ <pre class="code language-javascript">
+var data = {
+ "start": "-1", // -1 start value signifies the end of a stack
+ "limit": "0",
+ "num_found": "2",
+ "docs": [
+ {
+ "title": "Blankets",
+ "creator": [
+ "Craig Thompson"
+ ],
+ "measurement_page_numeric": 582,
+ "measurement_height_numeric": 25,
+ "shelfrank": 13,
+ "pub_date": "2003",
+ "link": "http://holliscatalog.harvard.edu/?itemid=|library/m/aleph|009189638"
+ },
+ {
+ "title": "Persepolis",
+ "creator": [
+ "Marjane Satrapi"
+ ],
+ "measurement_page_numeric": 153,
+ "measurement_height_numeric": 24,
+ "shelfrank": 64,
+ "pub_date": "2003",
+ "link": "http://holliscatalog.harvard.edu/?itemid=|library/m/aleph|009098946"
+ }
+ ]
+};
+ </pre>
+ <p>Then call the Stack View plugin using a jQuery selector.</p>
+ <pre class="code language-javascript">
+ $('#stackview').stackView({data: data});
+ </pre>
+ <p>Alternately, you can give Stack View a url. The url should point to a JSON file with data formatted as above or a script that accepts a callback and a start parameter and returns a JSON object. A script is useful for continually feeding Stack View new data as the user scrolls. Basically Stack View's version of paging.</p>
+ <pre class="code language-javascript">
+ $('#stackview').stackView({url: 'data.php'});
+ </pre>
+ <p>This is the most basic example using PHP.
+ <pre class="code language-php">
+ $start = $_GET['start'];
+
+ $docs = '[
+ {
+ "title": "Blankets",
+ "creator": [
+ "Craig Thompson"
+ ],
+ "measurement_page_numeric": 582,
+ "measurement_height_numeric": 25,
+ "shelfrank": 13,
+ "pub_date": "2003",
+ "link": "http://holliscatalog.harvard.edu/?itemid=|library/m/aleph|009189638"
+ }
+ ]';
+
+ if($start > 0) {
+ echo "{'start': '-1', 'num_found': '0', 'limit': '0', 'docs': ''}";
+ }
+ else {
+ echo "{'start': '0', 'limit': '0', 'num_found': '1', 'docs': $docs}";
+ }
+ </pre>
+ <h2>Available Stack View Options</h2>
+ <h3>data</h3>
+ <p>A JSON object used to construct a static stack. Stack View requires either a <b>data</b> object or a <b>url</b>, but not both.</p>
+ <h3>url</h3>
+ <p>The URL should point to a JSON file or a script that accepts a callback and start parameter and then provides Stack View with JSON formatted data. Stack View requires either a <b>data</b> object or a <b>url</b>, but not both.</p>
+ <h3>jsonp</h3>
+ <p>This option, when set to true, tells Stack View to send a JSONP request to the <b>url</b> specified. If using JSONP, make sure that the specified <b>url</b> accepts a callback and includes that callback as part of the JSONP response.
+ <br />Default is false.</p>
+ <h3>books_per_page</h3>
+ <p>How many books will be requested.
+ <br />Default is 10.</p>
+ <h3>threshold</h3>
+ <p>How much screen space to fill with books.
+ <br />Default is 1000.</p>
+ <h3>page_multiple</h3>
+ <p>Pixels per page.
+ <br />Default is 0.11.</p>
+ <h3>height_multiple</h3>
+ <p>Pixels per centimeter.
+ <br />Default is 12.</p>
+ <h3>search_type</h3>
+ <p>The type of search that the script from your url parameter should perform if a search is necessary.
+ <br />Default is keyword.</p>
+ <h3>query</h3>
+ <p>The query that the script from your url should use if performing a search.
+ <br />Default is nothing.<p>
+ <h3>ribbon</h3>
+ <p>The text that will appear in the ribbon at the top of the stack.
+ <br />Default is Stack View.</p>
+ </div>
+ </div>
+ <div class="footer">
+ <a href="http://www.librarylab.law.harvard.edu/">The Harvard Library Innovation Lab</a>
+ </div>
+
+<!-- js just for this page -->
+<script type="text/javascript" src="http://balupton.github.com/jquery-syntaxhighlighter/scripts/jquery.syntaxhighlighter.min.js"></script>
+<script type="text/javascript">$.SyntaxHighlighter.init();</script>
+</body>
+</html>
View
311 demo/examples.html
@@ -0,0 +1,311 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+<title>Stack View Examples</title>
+
+<link rel="icon" href="favicon.ico" type="image/x-icon" />
+
+<!-- CSS just for this page -->
+<style type="text/css">
+h1, h2 {
+ margin: 5px 5px 10px 5px;
+ padding: 0;
+ color:#444;
+ font-weight:normal;
+}
+
+body {
+ font-family:'Helvetica', 'Arial', sans-serif;
+ background:#faf5f0;
+ min-width:845px;
+ max-width:1145px;
+ font-size: 1.1em;
+ color: #333333;
+ border: none;
+ line-height:normal;
+ margin:0px auto;
+}
+
+p {
+ margin: 25px 5px 5px 5px;
+ font-size: .8em;
+}
+
+.container {
+ float:left;
+ width:45%;
+ margin:15px 15px 15px 5px;
+ clear:both;
+}
+
+.explanation {
+ float:left;
+ width:48%;
+ margin:15px 15px 15px 25px;
+}
+
+h1 {
+ font-size:2.1em;
+ padding-top:9px;
+}
+
+h2 {
+ font-size:1.2em;
+ color:#F60;
+}
+
+a {
+ color: #09F;
+ text-decoration: none;
+}
+
+pre {
+ background-color: #fff;
+}
+
+#nav {
+ padding:0 150px 0 0;
+ margin:0;
+ list-style-type:none;
+ float:right;
+}
+
+#nav li {
+ display:block;
+ float:left;
+ padding:0 27px 0 0;
+}
+
+#nav li a {
+ display:block;
+ padding:25px 0 0 0;
+}
+
+.footer {
+ clear:both;
+ font-size:.7em;
+ float:right;
+ padding:25px 30px 25px 0;
+}
+</style>
+
+<!-- stackview.css to style the stack -->
+<link rel="stylesheet" href="../lib/jquery.stackview.css" type="text/css" />
+
+<!-- stackview.js and all js dependencies -->
+<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
+<script type="text/javascript" src="../lib/jquery.stackview.min.js"></script>
+
+</head>
+
+<body>
+ <ul id="nav">
+ <li><a href="index.html">About</a></li>
+ <li><a href="documentation.html">Documentation</a></li>
+ <li><a href="examples.html">Examples</a></li>
+ <a href="http://www.librarylab.law.harvard.edu/"><img src="liblabstamp.png"></a>
+ </ul>
+ <a href="https://github.com/harvard-lil/stackview"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://a248.e.akamai.net/assets.github.com/img/30f550e0d38ceb6ef5b81500c64d970b7fb0f028/687474703a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67" alt="Fork me on GitHub"></a>
+ <h1>Stack View Examples</h1>
+
+ <div class="container">
+
+ <div id="amazon-stack"></div>
+
+ </div>
+
+ <script type="text/javascript">
+ $(function () {
+ $('#amazon-stack').stackView({url: '../php/amazon.php', query: 'memory', ribbon: 'Amazon search for "memory"'});
+ });
+ </script>
+
+ <div class="explanation">
+ <h2>Amazon stack</h2>
+ <p>A stack made up of book search results from the <a href="https://affiliate-program.amazon.com/gp/advertising/api/detail/main.html">Amazon API</a>. The amazon.php file performs the search, formats and feeds the results to Stack View.</p>
+ <p>Each book's Amazon Sales Rank is roughly sorted into one of ten groups that make up the heatmapping.</p>
+ <p>Include an empty div in the page.</p>
+ <pre class="code language-html">
+ &lt;div id="amazon-stack"&gt;&lt;/div&gt;
+ </pre>
+ <p>Then call the Stack View plugin using a jQuery selector.</p>
+ <pre class="code language-javascript">
+ $('#amazon-stack').stackView({
+ url: 'php/amazon.php',
+ query: 'memory',
+ ribbon: 'Amazon search for "memory"'
+ });
+ </pre>
+ <p>To use Stack View with the Amazon API, save a copy of the file <b>keys.php.example</b> as <b>keys.php</b> and fill in the required API keys.</p>
+ <p>Note that Amazon's API now limits to 100 results.</p>
+ </div>
+
+ <div class="container">
+
+ <div id="worldcat-stack"></div>
+
+ </div>
+
+ <script type="text/javascript">
+ $(function () {
+ $('#worldcat-stack').stackView({url: '../php/worldcat.php', jsonp: true, query: 'modern pirates', ribbon: 'WorldCat search for "modern pirates"'});
+ });
+ </script>
+
+ <div class="explanation">
+ <h2>WorldCat stack</h2>
+ <p>A keyword search using the <a href="http://oclc.org/developer/services/WCAPI">WorldCat API</a>. The worldcat.php file performs the search, formats and feeds the results to Stack View.</p>
+ <p>The number of libraries that hold each book is roughly sorted into one of ten groups that make up the heatmapping. This operation is <b>very</b> slow.</p>
+ <p>Include an empty div in the page.</p>
+ <pre class="code language-html">
+ &lt;div id="worldcat-stack"&gt;&lt;/div&gt;
+ </pre>
+ <p>Then call the Stack View plugin using a jQuery selector.</p>
+ <pre class="code language-javascript">
+ $('#worldcat-stack').stackView({
+ url: 'php/worldcat.php',
+ jsonp: true,
+ query: 'modern pirates',
+ ribbon: 'WorldCat search for "modern pirates"'
+ });
+ </pre>
+ <p>This example utilizes JSONP. See the associated <b>worldcat.php</b> script for code that will return a JSONP response.</p>
+ <p>To use Stack View with the WorldCat API, save a copy of the file <b>keys.php.example</b> as <b>keys.php</b> and fill in the required API key.</p>
+ </div>
+
+ <div class="container">
+
+ <div id="google-stack"></div>
+
+ </div>
+
+ <script type="text/javascript">
+ $(function () {
+ $('#google-stack').stackView({url: '../php/google.php', query: 'time travel', ribbon: 'Google Books search for "time travel"'});
+ });
+ </script>
+
+ <div class="explanation">
+ <h2>Google stack</h2>
+ <p>A keyword search using the <a href="https://code.google.com/apis/books/docs/v1/using.html">Google API</a>. The google.php file performs the search, formats and feeds the results to Stack View.</p>
+ <p>The user ratings are roughly sorted into one of ten groups that make up the heatmapping. Since Google rarely provides the height of the book, these are mostly randomized.</p>
+ <p>Include an empty div in the page.</p>
+ <pre class="code language-html">
+ &lt;div id="google-stack"&gt;&lt;/div&gt;
+ </pre>
+ <p>Then call the Stack View plugin using a jQuery selector.</p>
+ <pre class="code language-javascript">
+ $('#google-stack').stackView({
+ url: 'php/google.php',
+ query: 'time travel',
+ ribbon: 'Google search for "time travel"'
+ });
+ </pre>
+ <p>Note that, according to Google Books API documentation, the <b>totalItems</b> count is an estimate. This causes the Stack View items count to change as the user scrolls.</p>
+ <p>To use Stack View with the Google API, save a copy of the file <b>keys.php.example</b> as <b>keys.php</b> and fill in the required API key.</p>
+ </div>
+
+ <div class="container">
+
+ <div id="dpla-stack"></div>
+
+ </div>
+
+ <script type="text/javascript">
+ $(function () {
+ $('#dpla-stack').stackView({url: '../php/dpla.php', query: 'history', ribbon: 'DPLA search for "history"'});
+ });
+ </script>
+
+ <div class="explanation">
+ <h2>DPLA stack</h2>
+ <p>A keyword search using the <a href="http://dp.la/dev/wiki/Documentation">DPLA API</a>. The dpla.php file performs the search, formats and feeds the results to Stack View.</p>
+ <p>Checkouts are roughly sorted into one of ten groups that make up the heatmapping.</p>
+ <p>Include an empty div in the page.</p>
+ <pre class="code language-html">
+ &lt;div id="dpla-stack"&gt;&lt;/div&gt;
+ </pre>
+ <p>Then call the Stack View plugin using a jQuery selector.</p>
+ <pre class="code language-javascript">
+ $('#dpla-stack').stackView({
+ url: 'php/dpla.php',
+ query: 'history',
+ ribbon: 'DPLA search for "history"'
+ });
+ </pre>
+ <p>Note that much of the data from DPLA is currently dummy data.</p>
+ </div>
+
+ <div class="container">
+
+ <div id="static-stack"></div>
+
+ </div>
+
+ <script type="text/javascript">
+ $(function () {
+ $('#static-stack').stackView({url: '../json/static.json', ribbon: 'Static stack'});
+ });
+ </script>
+
+ <div class="explanation">
+ <h2>Static stack</h2>
+ <p>A manually created static stack. The static.json file feeds a JSON object to Stack View. The heatmapping is manually entered here (a digit from 1 to 100).</p>
+ <p>Note that you can also start with the most <a href="basic.html">basic demo</a>.</p>
+ <p>Include an empty div in the page.</p>
+ <pre class="code language-html">
+ &lt;div id="static-stack"&gt;&lt;/div&gt;
+ </pre>
+ <p>Then call the Stack View plugin using a jQuery selector.</p>
+ <pre class="code language-javascript">
+ $('#static-stack').stackView({
+ url: 'json/static.json',
+ ribbon: 'Static stack'
+ });
+ </pre>
+ <p>Example JSON</p>
+ <pre class="code language-javascript">
+{
+ "start": "-1",
+ "limit": "0",
+ "num_found": "2",
+ "docs": [
+ {
+ "title": "Blankets",
+ "creator": [
+ "Craig Thompson"
+ ],
+ "measurement_page_numeric": 582,
+ "measurement_height_numeric": 25,
+ "shelfrank": 13,
+ "pub_date": "2003",
+ "link": "http://holliscatalog.harvard.edu/?itemid=|library/m/aleph|009189638"
+ },
+ {
+ "title": "Persepolis",
+ "creator": [
+ "Marjane Satrapi"
+ ],
+ "measurement_page_numeric": 153,
+ "measurement_height_numeric": 24,
+ "shelfrank": 64,
+ "pub_date": "2003",
+ "link": "http://holliscatalog.harvard.edu/?itemid=|library/m/aleph|009098946"
+ }
+ ]
+}
+ </pre>
+ </div>
+ <div class="footer">
+ <a href="http://www.librarylab.law.harvard.edu/">The Harvard Library Innovation Lab</a>
+ </div>
+
+
+<!-- js just for this page -->
+<script type="text/javascript" src="http://balupton.github.com/jquery-syntaxhighlighter/scripts/jquery.syntaxhighlighter.min.js"></script>
+<script type="text/javascript">$.SyntaxHighlighter.init();</script>
+</body>
+</html>
View
200 demo/index.html
@@ -0,0 +1,200 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+<title>Stack View</title>
+
+<link rel="icon" href="favicon.ico" type="image/x-icon" />
+
+<!-- CSS just for this page -->
+<style type="text/css">
+h1, h2 {
+ margin: 5px 5px 10px 5px;
+ padding: 0;
+ color:#444;
+ font-weight:normal;
+}
+
+h3 {
+ margin: 10px 5px 0px 5px;
+ padding:0;
+ color:#444;
+ font-size:.9em;
+ font-weight:bold;
+}
+
+body {
+ font-family:'Helvetica', 'Arial', sans-serif;
+ background:#faf5f0;
+ min-width:845px;
+ max-width:1145px;
+ font-size: 1.1em;
+ color: #333333;
+ border: none;
+ line-height:normal;
+ margin:0px auto;
+}
+
+p {
+ margin: 5px 5px 15px 5px;
+ font-size: .8em;
+ line-height: 1.2em;
+}
+
+a {
+ color: #09F;
+ text-decoration: none;
+}
+
+.container {
+ float:left;
+ width:45%;
+ margin:15px 15px 15px 5px;
+ clear:both;
+}
+
+.explanation {
+ float:left;
+ width:48%;
+ margin:15px 15px 15px 25px;
+}
+
+.requirements {
+ float:left;
+ margin:15px 15px 15px 15px;
+ clear:both;
+}
+
+#doc-nav {
+ clear:both;
+ margin-left: 67px;
+ float:left;
+ width:23%;
+}
+
+#doc-nav ul{
+ list-style-type:none;
+ padding:0 10px 0 0;
+}
+
+#docs {
+ float:left;
+ width:70%;
+}
+
+h1 {
+ font-size:2.1em;
+ padding-top:9px;
+}
+
+h2 {
+ font-size:1.2em;
+ color:#F60;
+}
+
+pre {
+ background-color: #fff;
+}
+
+#nav {
+ padding:0 150px 0 0;
+ margin:0;
+ list-style-type:none;
+ float:right;
+}
+
+#nav li {
+ display:block;
+ float:left;
+ padding:0 30px 0 0;
+}
+
+#nav li a {
+ display:block;
+ padding:25px 0 0 0;
+}
+
+.footer {
+ clear:both;
+ font-size:.7em;
+ float:right;
+ padding:25px 30px 25px 0;
+}
+</style>
+
+<!-- stackview.css to style the stack -->
+<link rel="stylesheet" href="../lib/jquery.stackview.css" type="text/css" />
+
+<!-- stackview.js and all js dependencies -->
+<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js"></script>
+<script type="text/javascript" src="../lib/jquery.stackview.min.js"></script>
+
+<!-- javascript just for this page -->
+<script type="text/javascript">
+$(function () {
+ $('#intro-stack').stackView({url: '../json/intro.json'});
+});
+</script>
+
+</head>
+
+<body>
+ <ul id="nav">
+ <li><a href="index.html">About</a></li>
+ <li><a href="documentation.html">Documentation</a></li>
+ <li><a href="examples.html">Examples</a></li>
+ <a href="http://www.librarylab.law.harvard.edu/"><img src="liblabstamp.png"></a>
+ </ul>
+ <a href="https://github.com/harvard-lil/stackview"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://a248.e.akamai.net/assets.github.com/img/30f550e0d38ceb6ef5b81500c64d970b7fb0f028/687474703a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6f72616e67655f6666373630302e706e67" alt="Fork me on GitHub"></a>
+ <h1>Stack View</h1>
+
+ <div class="container">
+
+ <div id="intro-stack"></div>
+
+ </div>
+
+ <div class="explanation">
+ <h2>A virtual shelf</h2>
+ <p>Stack View is a book visualization and browsing tool. This jQuery plugin turns metadata into a browsable stack of books.</p>
+ <p>Stack View is drawn with CSS. When possible, the height of the book is based on the actual height of the object and the width is calculated using the page count. The color can be based on any data from ratings and rankings to library checkouts or holdings. The darker the color the higher the rating.</p>
+ <h3>JSON data<h3>
+ <pre class="code language-javascript">
+ {
+ "title": "Blankets",
+ "creator": [
+ "Craig Thompson"
+ ],
+ "measurement_page_numeric": 582,
+ "measurement_height_numeric": 25,
+ "shelfrank": 13,
+ "pub_date": "2003",
+ "link": "http://holliscatalog.harvard.edu/?itemid=|library/m/aleph|009189638"
+ }
+ </pre>
+ <h3>Becomes a virtual object</h3>
+ <ul class="stackview" style="padding:0;">
+ <li class="stack-item stack-book heat2" style="width: 300px; height: 59px; margin:10px 0 0 0;">
+ <a target="_newtab" href="http://holliscatalog.harvard.edu/?itemid=|library/m/aleph|009189638">
+ <span class="spine-text">
+ <span class="spine-title">Blankets</span>
+ <span class="spine-author">Craig Thompson</span>
+ </span>
+ <span class="spine-year">2003</span>
+ <span class="stack-pages"></span>
+ <span class="stack-cover"></span>
+ </a>
+ </li>
+ </ul>
+ </div>
+ <div class="footer">
+ <a href="http://www.librarylab.law.harvard.edu/">The Harvard Library Innovation Lab</a>
+ </div>
+
+<!-- js just for this page -->
+<script type="text/javascript" src="http://balupton.github.com/jquery-syntaxhighlighter/scripts/jquery.syntaxhighlighter.min.js"></script>
+<script type="text/javascript">$.SyntaxHighlighter.init();</script>
+</body>
+</html>
View
BIN demo/liblabstamp.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
4 json/README.md
@@ -1,6 +1,6 @@
# /json
-The files in this directory serve as examples of the JSON format used by StackView. This JSON can be passed directly to StackView as `data`:
+The files in this directory serve as examples of the JSON format used by Stack View. This JSON can be passed directly to Stack View as `data`:
```js
var data = {
@@ -33,7 +33,7 @@ var data = {
]
};
-$('#stackview').stackview({ data: data });
+$('#stackview').stackView({ data: data });
```
...or passed as a URL to a static file...
View
2 lib/README.md
@@ -1,3 +1,3 @@
# /lib
-This directory contains everything required by the StackView plugin. You can copy the contents of this directory to get started. If you would like to use PHP to generate the JSON used by the plugin, also copy the appropriate file from the `/php/` directory.
+This directory contains everything required by the Stack View plugin. You can copy the contents of this directory to get started. If you would like to use PHP to generate the JSON used by the plugin, also copy the appropriate file from the `/php/` directory.
View
BIN lib/images/placeholder.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
779 lib/jquery.stackview.css
@@ -1,563 +1,432 @@
@charset "UTF-8";
/*
- Stack View - The jQuery virutal stack plugin
+ Stack View - The jQuery virtual stack plugin
by The Harvard Library Innovation Lab
Dual licensed under MIT and GPL.
*/
-.scroller p, .scroller ul, .scroller li {
- margin: 0;
- padding: 0;
-}
-.scroller{
- position: relative;
- overflow: hidden;
+.stackview {
+ font-family:"Helvetica Neue", sans-serif;
+ position:relative;
+ width:440px;
height:520px;
+ padding:0 0 0 65px;
+ overflow:hidden;
}
-.scroller-content {
- margin-top:65px;
+.stackview * {
+ margin:0;
+ padding:0;
}
-/* for graphical control, fonts are in px instead of em in the stacks*/
-ul.stack li:hover {
- background: url('images/highGloss.png') repeat-x 0 47%;
+.stack-items {
+ list-style:none;
+ height:100%;
+ overflow:auto;
+ width:440px;
+ padding-right:40px;
}
-
-/*/////////////////////////////////////////////////////////*/
- /*HEATMAP*/
- /* heatmap: hottest = heat10 | coldest = heat1*/
-/*/////////////////////////////////////////////////////////*/
-
-ul.stack li.heat1, .heat1 {
- background: #ccebff url('images/superGloss.png') repeat-x 0 47%;
- color: #222;
- text-shadow: 0px 1px 0px #fff;
- border-color:#adf;
+.stack-items:before {
+ background:url('images/bookEnd-prev.png');
+ content:"";
+ display:block;
+ width:212px;
+ height:114px;
position:relative;
+ z-index:99998; /* Must be bigger than the # of elements in stack */
}
-ul.stack li.heat1 span.author{
- color:#222;
+.stack-items:after {
+ content:"";
+ display:block;
+ width:212px;
+ height:114px;
+ background:url('images/bookEnd-next.png');
+ margin:-7px 0 0 0;
}
-/*--------------------------------*/
-
-ul.stack li.heat2, .heat2 {
- background: #adf url('images/superGloss.png') repeat-x 0 47%;
- color: #222;
- text-shadow: 0px 1px 0px #ddf1ff;
- border-color:#88cfff;
+.stackview-placeholder {
+ width:250px;
+ background:url('images/placeholder.gif') no-repeat center center #ccd;
+ border:1px solid #bbb;
+ border-radius:3px;
+ height:40px;
+ position:relative;
+ z-index:2;
}
-ul.stack li.heat2 span.author{
- color:#222;
+.stack-item {
+ position:relative;
+ display:block;
+ margin:0 0 2px 0;
}
-/*--------------------------------*/
-ul.stack li.heat3, .heat3 {
- background: #77c9ff url('images/highGloss.png') repeat-x 0 47%;
- color: #111;
- text-shadow: 0px 1px 0px #adf;
- border-color:#59B6EF;
+.stack-item a {
+ display:block;
+ text-decoration:none;
+ height:100%;
+ background:url('images/gloss.png') repeat-x 0 47%;
+ color:#fff;
+ border-width:1px 2px;
+ border-style:solid;
+ white-space:nowrap;
+ overflow:hidden;
+ border-radius:3px / 20px;
}
-ul.stack li.heat3 span.author{
- color: #111;
+.stack-item a:hover, .stack-item a:focus {
+ background-image:url('images/highGloss.png');
+ text-decoration:none;
}
-/*--------------------------------*/
-ul.stack li.heat4, .heat4 {
- background-color: #44b4ff;
- color: #fff;
- text-shadow: 0px -1px 0px #11a0ff;
- border-color:#11a0ff;
+.spine-text {
+ position:absolute;
+ z-index:2;
+ height:40px;
+ line-height:40px;
+ top:50%;
+ margin-top:-7px;
+ left:15px;
+ right:24px;
+ overflow:hidden;
+ display:block;
}
-ul.stack li.heat4 span.author{
- color: #fff;
+.spine-title {
+ float:left;
+ font-size:13px;
+ line-height:13px;
+ vertical-align:middle;
}
-/*--------------------------------*/
-ul.stack li.heat5, .heat5 {
- background-color: #22a7ff;
- color: #fff;
- text-shadow: 0px -1px 0px #008fee;
- border-color:#008fee;
+.spine-author {
+ float:right;
+ font-size:10px;
+ line-height:13px;
+ vertical-align:middle;
+ margin-right:6px;
}
-ul.stack li.heat5 span.author{
- color: #fff;
+.spine-year {
+ position:absolute;
+ z-index:3;
+ top:50%;
+ right:3px;
+ width:28px;
+ height:18px;
+ line-height:18px;
+ background:#f9fceb;
+ font-size:9.5px;
+ font-family:monospace;
+ border-radius:2px;
+ text-align:center;
+ margin-top:-9px;
+ border-width:0 1px;
+ border-style:dotted;
+ border-color:#e6dec4;
+ text-shadow:none;
+ color:#555;
+ -webkit-transform:rotate(-90deg);
+ -moz-transform:rotate(-90deg);
+ -o-transform:rotate(-90deg);
+ -ms-transform:rotate(-90deg);
+ transform:rotate(-90deg);
+}
+
+.stack-pages {
+ position:absolute;
+ z-index:4;
+ display:block;
+ width:10px;
+ right:-6px;
+ top:0;
+ bottom:-4px;
+ border-width:3px 0 3px 2px;
+ border-style:solid;
+ border-radius:4px 0 0 4px / 20px 0 0 20px;
+ -o-transform-origin:0% 100%;
+ -ms-transform-origin:0% 100%;
+ -moz-transform-origin:0% 100%;
+ -webkit-transform-origin:0% 100%;
+ transform-origin:0% 100%;
+ -ms-transform:skew(0deg,-20deg);
+ -webkit-transform:skew(0deg,-20deg);
+ -o-transform:skew(0deg,-20deg);
+ -moz-transform:skew(0deg,-20deg);
+ transform:skew(0deg,-20deg);
+}
+
+.stack-pages:after {
+ position:absolute;
+ content:"";
+ left:0;
+ right:2px;
+ top:0;
+ bottom:0;
+ background:#f5f2e8;
+ border-right:1px solid #e5e5e5;
}
-/*--------------------------------*/
-ul.stack li.heat6, .heat6 {
- background-color: #0099ff;
- color: #fff;
- text-shadow: 0px -1px 0px #0085dd;
- border-color:#007acc;
+.stack-cover {
+ position:absolute;
+ z-index:3;
+ height:2px;
+ border-width:1px;
+ border-style:solid;
+ border-right-width:2px;
+ top:-4px;
+ left:0;
+ right:5px;
+ border-radius:4px 0 0 50px;
+ overflow:visible;
+ -webkit-transform-origin:0% 100%;
+ -moz-transform-origin:0% 100%;
+ -o-transform-origin:0% 100%;
+ -ms-transform-origin:0% 100%;
+ transform-origin:0% 100%;
+ -webkit-transform:skew(-70deg);
+ -moz-transform:skew(-70deg);
+ -o-transform:skew(-70deg);
+ -ms-transform:skew(-70deg);
+ transform:skew(-70deg);
+}
+
+/******************
+ HEATMAP
+
+ hottest = heat10
+ coldest = heat1
+*******************/
+.stackview .heat1 a {
+ background-color:#ccebff;
+ background-image:url('images/superGloss.png');
+ color:#222;
+ text-shadow:0px 1px 0px #fff;
+ border-color:#adf;
}
-ul.stack li.heat6 span.author{
- color: #fff;
+.heat1 .stack-pages {
+ border-color:#adf;
}
-/*--------------------------------*/
-
-ul.stack li.heat7, .heat7 {
- background-color: #0085dd;
- color: #fff;
- text-shadow: 0px -1px 0px #0070bb;
- border-color:#06a;
+.heat1 .stack-cover {
+ border-color:#adf;
+ background:#ccebff;
}
-ul.stack li.heat7 span.author{
- color: #fff;
+.stackview .heat2 a {
+ background-color:#adf;
+ background-image:url('images/superGloss.png');
+ color:#222;
+ text-shadow:0px 1px 0px #ddf1ff;
+ border-color:#88cfff;
}
-/*--------------------------------*/
-ul.stack li.heat8, .heat8 {
- background-color: #0070bb;
- color: #fff;
- text-shadow: 0px -1px 0px #005c99;
- border-color:#004777;
+.heat2 .stack-pages {
+ border-color:#88cfff;
}
-
-ul.stack li.heat8 span.author{
- color: #fff;
+.heat2 .stack-cover {
+ border-color:#88cfff;
+ background:#adf;
}
-/*--------------------------------*/
-ul.stack li.heat9, .heat9 {
- background-color: #005c99;
- color: #fff;
- text-shadow: 0px -1px 0px #004777;
- border-color:#002944;
+.stackview .heat3 a {
+ background-color:#77c9ff;
+ background-image:url('images/highGloss.png');
+ color:#111;
+ text-shadow:0px 1px 0px #adf;
+ border-color:#59b6ef;
}
-ul.stack li.heat9 span.author{
- color: #fff;
+.heat3 .stack-pages {
+ border-color:#59b6ef;
}
-/*--------------------------------*/
-
-ul.stack li.heat10, .heat10 {
- background-color: #004777;
- color: #fff;
- text-shadow: 0px -1px 0px #035;
- border-color:#001522;
+.heat3 .stack-cover {
+ border-color:#59b6ef;
+ background:#77c9ff;
}
-ul.stack li.heat10 span.author{
- color: #fff;
+.stackview .heat4 a {
+ background-color:#44b4ff;
+ text-shadow:0px -1px 0px #11a0ff;
+ border-color:#11a0ff;
}
-.heat1, .heat2, .heat3, .heat4, .heat5, .heat6, .heat7, .heat8, .heat9, .heat10 {
- border-width:1px;
+.heat4 .stack-pages {
+ border-color:#11a0ff;
}
-
-/*/////////////////////////////////////////////////////////*/
- /*STACK ELEMENT STYLING*/
-/*/////////////////////////////////////////////////////////*/
-
-ul.stack li {
- font-family:'Helvetica', 'Arial', sans-serif;
- list-style-type: none;
- display:block;
- padding:1px 3px 8px 3px;
- background: url('images/gloss.png') repeat-x 0 47%;
- border-width: 1px 2px;
- border-style:solid;
-
- -moz-border-radius: 3px 3px 3px 3px / 20px 20px 20px 20px;
- -webkit-border-radius: 3px 3px 3px 3px / 20px 20px 20px 20px;
- -o-border-radius: 3px 3px 3px 3px / 20px 20px 20px 20px;
- border-radius: 3px 3px 3px 3px / 20px 20px 20px 20px;
-
- position:relative;
- z-index: 1;
- white-space: nowrap;
- overflow: hidden;
- text-overflow: hidden;
+.heat4 .stack-cover {
+ border-color:#11a0ff;
+ background:#44b4ff;
}
-.itemContainer {
- position:relative;
- -moz-transition: all 100ms cubic-bezier(0.200, 0.000, 0.175, 1.000);
- -webkit-transition: all 100ms cubic-bezier(0.200, 0.000, 0.175, 1.000);
- -ms-transition: all 100ms cubic-bezier(0.200, 0.000, 0.175, 1.000);
- -o-transition: all 100ms cubic-bezier(0.200, 0.000, 0.175, 1.000);
- transition: all 100ms cubic-bezier(0.200, 0.000, 0.175, 1.000); /* custom */
-
- -moz-transition-timing-function: cubic-bezier(0.200, 0.000, 0.175, 1.000);
- -webkit-transition-timing-function: cubic-bezier(0.200, 0.000, 0.175, 1.000);
- -ms-transition-timing-function: cubic-bezier(0.200, 0.000, 0.175, 1.000);
- -o-transition-timing-function: cubic-bezier(0.200, 0.000, 0.175, 1.000);
- transition-timing-function: cubic-bezier(0.200, 0.000, 0.175, 1.000); /* custom */
-
- -moz-transition-delay: .5s;
- -moz-transition: margin .5s;
+.stackview .heat5 a {
+ background-color:#22a7ff;
+ text-shadow:0px -1px 0px #008fee;
+ border-color:#008fee;
}
-/*.itemContainer:hover {
- -moz-transition-delay: .5s;
- margin: 4px 0 -4px -5px;
- position:relative;
- z-index:101;
-}*/
-
-.anchorbook {
- margin: 4px 0 -4px -5px;
- z-index:100;
- background: url('images/highGloss.png') repeat-x 0 47%; /*//*/
- position:relative;
+.heat5 .stack-pages {
+ border-color:#008fee;
+}
+.heat5 .stack-cover {
+ border-color:#008fee;
+ background:#22a7ff;
}
+.stackview .heat6 a {
+ background-color:#0099ff;
+ text-shadow:0px -1px 0px #0085dd;
+ border-color:#007acc;
+}
-ul.stack li{
- margin-left:29px;
+.heat6 .stack-pages {
+ border-color:#007acc;
+}
+.heat6 .stack-cover {
+ border-color:#007acc;
+ background:#0099ff;
}
+.stackview .heat7 a {
+ background-color:#0085dd;
+ text-shadow:0px -1px 0px #0070bb;
+ border-color:#06a;
+}
-/*/ Notes on Layer (z-index) management:
-ul.stack: 1 | anchorbook: 2 | .overlay: 3 | stack hover:4 | img.upstream & downstream: 5 | .welcome: 6 /*/
+.heat7 .stack-pages {
+ border-color:#06a;
+}
+.heat7 .stack-cover {
+ border-color:#06a;
+ background:#0085dd;
+}
+.stackview .heat8 a {
+ background-color:#0070bb;
+ text-shadow:0px -1px 0px #005c99;
+ border-color:#004777;
+}
-/*/styling spine strings/*/
-.spine-text {
- position:absolute;
- overflow:hidden;
- top:31%;
- width:90%;
- min-height:18px;
+.heat8 .stack-pages {
+ border-color:#004777;
+}
+.heat8 .stack-cover {
+ border-color:#004777;
+ background:#0070bb;
}
-span.title{
- position:relative;
- font-size:13px;
- margin: 0 0 -4px 10px;
- overflow:hidden;
- float:left;
- min-height:14px;
+.stackview .heat9 a {
+ background-color:#005c99;
+ text-shadow:0px -1px 0px #004777;
+ border-color:#002944;
}
-span.author{
- position:relative;
- display:inline;
- font-size:10px;
- line-height:11px;
- margin: 0;
- padding:0px 3% 0 0;
- float:right;
+.heat9 .stack-pages {
+ border-color:#002944;
+}
+.heat9 .stack-cover {
+ border-color:#002944;
+ background:#005c99;
}
-span.spine-year {
- position:absolute;
- right:0;
- top:20%;
- background:#f9fceb;
- font-size:9.5px;
- line-height:13px;
- color:#555;
- font-family: monospace;
- width:28px;
- height:18px;
- text-align:center;
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
- -moz-transform:rotate(-90deg);
- -webkit-transform:rotate(-90deg);
- -o-transform:rotate(-90deg);
- -ms-transform:rotate(-90deg);
- transform: rotate(-90deg);
- border-width: 0 1px;
- border-style:dotted;
- border-color:#e6dec4;
- text-shadow:none;
-}
-
-li.spine {
- cursor:pointer;
-}
-
-.scroller-loading-prev{
- color:#f7f7f7;
- background-image: url('images/bookEnd-prev.png');
- height:114px;
- width:212px;
- margin-top: -111px; !important
- margin-right: 0px;
- margin-bottom: -2px;
- margin-left: 27px;
- position:relative;
- z-index:10;
+.stackview .heat10 a {
+ background-color:#004777;
+ text-shadow:0px -1px 0px #035;
+ border-color:#001522;
}
-.scroller-loading-next, .book-end{
- color:#f7f7f7;
- background-image: url('images/bookEnd-next.png');
- height:114px;
- width:212px;
- margin:-6px 0px 0px 27px;
- position:relative;
- z-index:0;
+.heat10 .stack-pages {
+ border-color:#001522;
+}
+.heat10 .stack-cover {
+ border-color:#001522;
+ background:#004777;
}
-/*/////////////////////////////////////////////////////////*/
- /*RIBBONS*/
-/*/////////////////////////////////////////////////////////*/
-.ribbon {
- font-family:'Helvetica', 'Arial', sans-serif;
+/**********
+ RIBBON
+***********/
+.stackview .ribbon {
position:absolute;
- width:37%;
- min-width: 200px;
- max-width:400px;
- min-height: 35px;
- margin-top:5px;
- margin-left:55px;
- -webkit-user-select: none;
- -moz-user-select:none;
+ z-index:99999; /* Must be bigger than the # of elements in stack */
+ left:55px;
+ right:10px;
+ top:52px;
+ padding:8px 10px 8px 22px;
+ min-height:25px;
+ font-size:20px;
+ line-height:1.25;
+ background:rgba(252,221,94,.85);
+ color:#035;
+ border:1px solid #fe4;
+ border-radius:2px;
+ -webkit-user-select:none;
+ -moz-user-select:none;
+ -ms-user-select:none;
user-select:none;
}
-.ribbonBody {
- clear:both;
- position:relative;
- background:rgba(252,221,94,.85);
- color:#035;
- z-index:9999;
- min-height:30px;
- padding:7px 10px 4px 10px;
- border-radius: 2px;
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border:1px solid #fe4;
- font-size:20px;
-}
-
-.ribbonBehind {
- background-image:url('images/ribbonTab.png');
- background-repeat:no-repeat;
- display:block;
+.stackview .ribbon:after {
+ content:"";
+ position:absolute;
+ bottom:-10px;
+ left:0;
+ background:url('images/ribbonTab.png') no-repeat 0 0;
width:10px;
height:10px;
- position:relative;
- margin-left:1px;
- clear:both;
- z-index:0;
}
-ul.stack span.cover {
- position:relative;
- float:left;
- height:2px;
- border-width:1px;
- border-style:solid;
- border-right-width:2px;
- margin:-4px 0 0 30px;
-
- -moz-border-radius-topleft: 4px;
- -webkit-border-top-left-radius: 4px;
- -o-border-top-left-radius: 4px;
- -ms-border-top-left-radius: 4px;
- border-top-left-radius: 4px;
-
- overflow:visible;
- -webkit-transform-origin: 0% 100%;
- -moz-transform-origin: 0% 100%;
- -o-transform-origin: 0% 100%;
- -ms-transform-origin: 0% 100%;
- transform-origin: 0% 100%;
-
- -webkit-transform: skew(-70deg);
- -moz-transform: skew(-70deg);
- -o-transform: skew(-70deg);
- -ms-transform: skew(-70deg);
- transform: skew(-70deg);
-}
-ul.stack span.cover:after {
+/**************
+ NAVIGATION
+***************/
+.stack-navigation {
position:absolute;
- display: block;
- content:"";
- top:0px;
- right:0px;
- bottom:0px;
- left:0px;
- border-width:0px 1px 0px 1px;
- border-color:#fff #fff #fff #0070bb;
- border-style:solid;
+ left:5px;
+ top:5px;
+ width:41px;
+ text-align:center;
}
-ul.stack span.pages{
- position:relative;
- z-index:4;
- display: block;
- width: 10px;
- background: #f5f2e8;
-
- -moz-border-radius: 4px 0px 0px 4px / 20px 0px 0px 20px;
- -webkit-border-radius: 4px 0px 0px 4px / 20px 0px 0px 20px;
- -o-border-radius: 4px 0px 0px 4px / 20px 0px 0px 20px;
- border-radius: 4px 0px 0px 4px / 20px 0px 0px 20px;
-
- border-width:3px 0 3px 1px;
- border-style:solid;
-
- transform-origin: 0% 100%;
- -o-transform-origin: 0% 100%;
- -ms-transform-origin: 0% 100%;
- -moz-transform-origin: 0% 100%;
- -webkit-transform-origin: 0% 100%;
-
- transform: skew(0deg,-20deg);
- -ms-transform: skew(0deg,-20deg); /* IE 9 */
- -webkit-transform: skew(0deg,-20deg); /* Safari and Chrome */
- -o-transform: skew(0deg,-20deg); /* Opera */
- -moz-transform: skew(0deg,-20deg); /* Firefox */
-}
-
-ul.stack .pages:before {
- position:absolute;
- display: block;
- content:"";
- z-index:4;
- width: 5px;
- top:0px;
- right:0px;
- bottom:0px;
- left:0px;
-
- -moz-border-radius: 3px 3px 3px 3px / 20px 20px 20px 20px;
- -webkit-border-radius: 3px 3px 3px 3px / 20px 20px 20px 20px;
- -o-border-radius: 3px 3px 3px 3px / 20px 20px 20px 20px;
- border-radius: 3px 3px 3px 3px / 20px 20px 20px 20px;
-
- border-width:0 1px 0 1px;
- border-style:solid;
- border-color:#faf5f0 #faf5f0 #faf5f0 #ebe5d1;
- overflow:visible;
- background:#faf5f0;
-
- margin:0 0 0 6px;
-
- transform-origin: 0% 100%;
- -o-transform-origin: 0% 100%;
- -ms-transform-origin: 0% 100%;
- -moz-transform-origin: 0% 100%;
- -webkit-transform-origin: 0% 100%;
-}
-
-
-ul.stack .pages:after {
- position:absolute;
- display: block;
- content:"";
- z-index:3;
- width: 10px;
- background:transparent;
- float:left;
- top:0px;
- right:0px;
- bottom:0px;
- left:0px;
-
- -moz-border-radius-topleft: 3px 20px;
- -webkit-border-top-left-radius: 3px 20px;
- -o-border-top-left-radius: 3px 20px;
- border-top-left-radius: 3px 20px;
-
- -moz-border-radius-bottomleft: 3px 20px;
- -webkit-border-bottom-left-radius: 3px 20px;
- -o-border-bottom-left-radius: 3px 20px;
- border-bottom-left-radius: 3px 20px;
-
- border-width:2px 0 2px 0px;
- border-style:solid;
- border-color:#aaa #007acc #ddd;
-
- transform-origin: 0% 100%;
- -o-transform-origin: 0% 100%;
- -ms-transform-origin: 0% 100%;
- -moz-transform-origin: 0% 100%;
- -webkit-transform-origin: 0% 100%;
-}
-
- /*CONTROL PANEL*/
-/* ------------------------------------------------------- */
-.navigation {
- font-family:'Helvetica', 'Arial', sans-serif;
- float:left;
- position:relative;
- margin:10px 0 0 0;
- width:35px;
- -webkit-user-select: none;
- -moz-user-select:none;
- user-select:none;
+.stack-navigation .upstream, .stack-navigation .downstream {
+ height:43px;
+ text-indent:-999em;
+ overflow:hidden;
}
-.upstream {
- position:relative;
- width:41px;
- height:43px;
- background-image: url('images/nav.png');
- background-repeat:no-repeat;
- background-position: 0 -87px;
- -webkit-user-select: none;
- -moz-user-select:none;
- user-select:none;
- margin-bottom:10px;
+.stack-navigation .upstream {
+ background:url('images/nav.png') 0 -87px no-repeat;
}
-.upstream:hover {
- background-position: 0 -44px;
+.stack-navigation .upstream:hover, .stack-navigation .upstream:focus {
+ background-position:0 -44px;
}
-.upstream:active, .prev-page:active {
- background-position: 0 -1px;
+.stack-navigation .upstream:active {
+ background-position:0 -1px;
}
-.downstream {
- position:relative;
- width:41px;
- height:43px;
- background-image:url('images/nav.png');
- background-repeat:no-repeat;
- background-position: 0 -130px;
- -webkit-user-select: none;
- -moz-user-select:none;
- user-select:none;
- margin-top:10px;
+.stack-navigation .downstream {
+ background:url('images/nav.png') 0 -130px no-repeat;
}
-.downstream:hover {
- background-position: 0 -173px;
+.stack-navigation .downstream:hover, .stack-navigation .downstream:focus {
+ background-position:0 -173px;
}
-.downstream:active {
- background-position: 0 -216px;
+.stack-navigation .downstream:active {
+ background-position:0 -216px;
}
-.num-found {
- text-align:center;
- color: #09f;
- border-radius: 2px;
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border:0px solid #ddd;
+.stack-navigation .num-found {
font-size:15px;
line-height:16px;
- height:40px;
- width:70px;
- padding:6px 0 0 0;
+ margin:10px 0;
+ color:#09f;
text-shadow: 0 1px 0 #ddd;
- margin-left:-15px;
-}
-
-.empty {
- border:0px solid #fefefe;
}
View
31 lib/jquery.stackview.min.js
@@ -1,28 +1,15 @@
/*!
- * jQuery infiniteScroller - v0.1pre - 9/24/2010
- * http://benalman.com/
- *
- * Copyright (c) 2010 "Cowboy" Ben Alman
- * Dual licensed under the MIT and GPL licenses.
- * http://benalman.com/about/license/
- */
-(function(e){var d="infiniteScroller",c;e.fn[d]=c=function(a){a=e.extend({},c.options,a);var b={Width:"Height",Left:"Top"};e.each(b,function(g,h){if(axis==="x"){b[g]=h=g}b[g.toLowerCase()]=h.toLowerCase()});return this.each(function(){var T=e(this),ar=T[0]===document.body?e(window):T,ag=T.children(".scroller-content"),ae,aq,Y=ag.children(".scroller-loading:first-child"),V=ag.children(".scroller-loading:last-child"),W=ah(Y)||0,Q=ah(V)||0,R=0,M=0,U,aa,S,L;ai(false,true);al(ae.eq(0));function O(){var f=L;L=ap();if(a.pagechange&&f!==L){a.pagechange.call(ae.eq(L),ae.eq(f))}if(a.scroll){a.scroll.call(T,ad(T)-R)}if(a.search_type=="loc_sort_order"){am(-1)}am(1)}O();Z();ao();ar.bind("scroll."+d+" resize."+d,O);T.bind("reflow."+d,Z);T.bind("set-zero."+d,ao);T.bind("move-to."+d,function(g,f){X(f)});T.bind("move-by."+d,function(h,g){var f={dir:1,amount:ab("scroll_by")};g=e.extend(f,typeof g==="number"?{amount:g}:g);if(g.amount==="page"){N(g.dir)}else{an(g.dir*g.amount)}});function Z(){ai(true);ac(L,true)}function ai(f,g){ae=ag.children(".scroller-page");aq=[];U=aa=ad(ae.eq(0));ae.each(function(j){var i=e(this);f&&af(i,aa);aq[j]={start:aa,end:aa+ah(i,true)};aa+=ah(i)});W&&af(Y,U-W);Q&&af(V,aa);var h=P();if(h<0){af(ag,W&&Q?(ah(T)-aa)/2:W?ah(T)-aa:Q?U:-h/2)}else{af(ag,W-U);if(g){}}}function al(f){f.addClass("scroller-page").data(d,{})}function N(g,h){var f=L+g;f=Math.min(Math.max(f,0),ae.length);ac(f,h)}function ac(f,g){X(ae.eq(f),g)}function an(g,f,h){X(g,f,h,true)}function X(i,l,t,h){var o=a.scroll_duration,g=ad(T),q,k,s,p,m,r,n;if(i&&typeof i!=="number"){if((q=e(i)).length){m=W-U-R-ab("offset")[0],r=ak(),n=r.start-r.end;k=aq[ae.index(q)];s=k.start;p=k.end;i=(s-p<n?s:(s+p+n)/2)+m}else{return}}S=f(h?g+i:i+R);if(!t){T.stop(true,false);M=0}if(!o||l){j(S)}else{T.scrollTop(g).animate({scrollTop:S},{step:function(v,u){j(v-M)},duration:o})}function f(u){var v=P();return Math.min(Math.max(u,Math.min(0,v)),Math.max(0,v))}function j(u){ar["scroll"+b.Left](f(u))}}function am(k){var l=k!==1,g=ae.eq(l?0:ae.length-1),j=g.data(d),n=a.fetch,m=l?"prev":"next",h=l?W:Q,f=ad(T),i=(l?f:P()-f)-h;if(h&&!j[m]&&e.isFunction(n)&&i<=ab("threshold")){j[m]=true;setTimeout(function(){n.call(g,k,function(p){if(p===false){if(l){M+=W;ao(R-W);an(-W,true,true);Y.hide();W=0}else{V.hide();Q=0}ai()}else{if(p){var o;p=e(p);al(p);if(l){Y.after(p);o=ah(p);af(p,ad(g)-o);ai();ao(R+o);an(o,true,true);M-=o}else{V.before(p);af(p,ad(g)+ah(g));ai()}am(k)}else{delete j[m]}}})},1)}}function ad(f){return f[0]===T[0]?ar["scroll"+b.Left]():f.position()[b.left]}function af(h,g){var f={};if(g!==ad(h)){f[b.left]=g;h.css(f)}}function ah(f,g){return f[0]===ag[0]?W+Q+aa-U:f[(f[0]===T[0]?"inner":"outer")+b.Width](!g)}function aj(g,f){g[b.width](f)}function ab(g){var f=a[g];return e.isFunction(f)?f.call(T,ah(T)):f}function P(){return ah(ag)-ah(T)}function ao(f){R=typeof f==="number"?f:ad(T)}function ak(){var g=ad(T)+U-W,f=ab("offset");return{start:g+f[0],end:g+ah(T)-f[1]}}function ap(){var h=ak(),i=h.start,m=h.end,g,k=[],l=[],f=[],j;e.each(aq,function(p,o){var n=o.start,q=o.end;if(n>=m){return false}if(n>=i){if(q<=m){g=k.push(p)}else{l.push(p)}}else{if(q>i){l.push(p)}}});f=e.map(g?k:l,function(p){var o=aq[p],n=o.start,q=o.end;return{i:p,d:g?Math.abs((i+m-n-q)/2):n<i?i-q:n-m}}).sort(function(n,o){return n.d-o.d});return f.length?f[0].i:0}})};c.options={axis:"x",threshold:function(a){return a},scroll_by:function(a){return a},position:function(a,b){return(a+b)/2},pagechange:function(a){},scroll:function(a){},scroll_duration:400,offset:[0,0],fetch:null}})(jQuery);
-/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
- * Licensed under the MIT License (LICENSE.txt).
- *
- * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
- * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
- * Thanks to: Seamus Leahy for adding deltaX and deltaY
- *
- * Version: 3.0.6
- *
- * Requires: 1.2.2+
- */
-(function(f){function b(h){var d=h||window.event,l=[].slice.call(arguments,1),j=0,k=0,i=0,h=f.event.fix(d);h.type="mousewheel";d.wheelDelta&&(j=d.wheelDelta/120);d.detail&&(j=-d.detail/3);i=j;d.axis!==void 0&&d.axis===d.HORIZONTAL_AXIS&&(i=0,k=-1*j);d.wheelDeltaY!==void 0&&(i=d.wheelDeltaY/120);d.wheelDeltaX!==void 0&&(k=-1*d.wheelDeltaX/120);l.unshift(h,j,k,i);return(f.event.dispatch||f.event.handle).apply(this,l)}var g=["DOMMouseScroll","mousewheel"];if(f.event.fixHooks){for(var a=g.length;a;){f.event.fixHooks[g[--a]]=f.event.mouseHooks}}f.event.special.mousewheel={setup:function(){if(this.addEventListener){for(var c=g.length;c;){this.addEventListener(g[--c],b,false)}}else{this.onmousewheel=b}},teardown:function(){if(this.removeEventListener){for(var c=g.length;c;){this.removeEventListener(g[--c],b,false)}}else{this.onmousewheel=null}}};f.fn.extend({mousewheel:function(c){return c?this.bind("mousewheel",c):this.trigger("mousewheel")},unmousewheel:function(c){return this.unbind("mousewheel",c)}})})(jQuery);
+ Simple JavaScript Templating originally by John Resig:
+ http://ejohn.org/blog/javascript-micro-templating/
+ Modified by Rick Strahl:
+ http://west-wind.com/weblog/posts/2008/Oct/13/Client-Templating-with-jQuery
+ MIT Licensed
+*/
+(function(){var b={};this.tmpl=function a(e,d){var c=!/\W/.test(e)?b[e]=b[e]||a(document.getElementById(e).innerHTML):new Function("obj","var p=[],print=function(){p.push.apply(p,arguments);};with(obj){p.push('"+e.replace(/[\r\t\n]/g," ").replace(/'(?=[^%]*%>)/g,"\t").split("'").join("\\'").split("\t").join("'").replace(/<%=(.+?)%>/g,"',$1,'").split("<%").join("');").split("%>").join("p.push('")+"');}return p.join('');");return d?c(d):c}})();
/*!
- Stack View - The jQuery virutal stack plugin
+ Stack View - The jQuery virtual stack plugin
by The Harvard Library Innovation Lab
Dual licensed under MIT and GPL.
*/
-(function(b){jQuery.ajaxSettings.traditional=true;var a=+new Date();var c=0;b.fn.stackView=function(d){if(d!==false){d=b.extend({url:"basic.json",data:"",jsonp:false,books_per_page:10,threshold:1000,page_multiple:0.11,height_multiple:12,search_type:"keyword",query:"",ribbon:"Stack View"},d)}return this.each(function(){var e=b(this),i=e.data("scroller"),f;axis="y";e.addClass("scroller");e.html('<div class="scroller-content"><div class="scroller-loading scroller-loading-prev" /><div class="scroller-page" /><div class="scroller-loading scroller-loading-next" /></div>');var h=e.attr("id");var j=h+"-wrapper";e.wrap('<div id="'+j+'" />');b("#"+j).prepend('<div class="navigation"><div class="upstream" /><div class="num-found" /><div class="downstream" /></div><div class="ribbon"><div class="ribbonBody" /><div class="ribbonBehind" /></div>');b("#"+h).bind("mousewheel",function(k,l){b("#"+h).trigger("move-by",-l*75);return false});b("#"+j+" .upstream").live("click",function(){b("#"+h).trigger("move-by",-475);return false});b("#"+j+" .downstream").live("click",function(){b("#"+h).trigger("move-by",475);return false});b(".scroller-page ul li").live("click",function(){window.open(b(this).attr("link"),"_newtab")});b("#"+j+" .ribbonBody").text(d.ribbon);if(d===false){e.unbind(".infiniteScroller");e.replaceWith(i.clone);return}if(!i){e.data("scroller",i={clone:e.clone(),options:d})}function g(m,w,t,o,v,p){var r=d.search_type==="loc_sort_order",l=d.books_per_page*0.5;if(r&&t==="downstream"){d.query="["+w+"%20TO%20"+(w+l)+"]"}if(r&&t==="upstream"){d.query="["+(w-l)+"%20TO%20"+w+"]"}if(r&&t==="center"){d.query="["+(w-6)+"%20TO%20"+(w+l-6)+"]"}var n=b.param({id:d.id,limit:d.books_per_page*(t!=="center"?1:0.5),mode:t,query:d.query,start:o,search_type:d.search_type}),q;if(q=stackCache.get(n)){s(q)}else{var k=d.url.split(".").pop();if(d.data!==""){s(d.data)}else{if(d.jsonp&&k!=="json"){var u=d.url;if(u.indexOf("?")!=-1){u+="&callback=?"}else{u+="?callback=?"}b.getJSON(u,n,s)}else{b.getJSON(d.url,n,function(x){s(x)})}}}function s(y){var C=parseInt(y.start)+parseInt(y.limit);var x=y.num_found-y.start-y.limit;if(x<=0){x=-1}if((!y.docs||!y.docs.length)&&y.start!==0){b("#"+h).find(".scroller-page ul:last").after('<div class="book-end" />');p(false);return}y.start=C;stackCache.set(n,y,60);var B=b.extend([],y.docs);var A=b('<ul class="stack" />');function z(D){if(D>=0&&D<10){return 1}if(D>=10&&D<20){return 2}if(D>=20&&D<30){return 3}if(D>=30&&D<40){return 4}if(D>=40&&D<50){return 5}if(D>=50&&D<60){return 6}if(D>=60&&D<70){return 7}if(D>=70&&D<80){return 8}if(D>=80&&D<90){return 9}if(D>=90&&D<=100){return 10}}if(d.search_type!=="loc_sort_order"){b("#"+j+" .num-found").html(y.num_found+"<br />items").removeClass("empty")}else{b("#"+j+" .num-found").html("").addClass("empty")}b.each(B,function(G,F){if(!F.title){F.title="NULL"}var E="";if(F.measurement_page_numeric){E=F.measurement_page_numeric}if(E===""||E<200||!E){E=200}if(E>540){E=540}var D="";if(F.measurement_height_numeric){D=F.measurement_height_numeric}if(D===""||D<20||!D){D=20}if(D>39){D=39}var I="";if(F.pub_date){I=F.pub_date}var J="";if(parseInt(F.loc_sort_order)===parseInt(d.loc_sort_order)&&t==="center"){J=" anchorbook"}var H="";if(F.creator&&F.creator.length>0){H=F.creator[0];if(/^([^,]*)/.test(H)){H=H.match(/^[^,]*/)}}if(F.title_link_friendly){F.link="../shelflife/book/"+F.title_link_friendly+"/"+F.id}A.append(b('<div class="itemContainer'+J+'" />').html(b('<span class="cover heat'+z(F.shelfrank)+'" />').css("width",D*d.height_multiple+2)).append(b('<span class="pages heat'+z(F.shelfrank)+'" />').css("margin-left",D*d.height_multiple+35).css("margin-bottom",-E*d.page_multiple-11).css("height",E*d.page_multiple+5)).append(b('<li link="'+F.link+'" class="heat'+z(F.shelfrank)+' spine" />').html('<p class="spine-text"><span class="title">'+F.title+'</span><span class="author">'+H+'</span></p><span class="spine-year">'+I+"</span>").css("width",D*d.height_multiple).css("height",E*d.page_multiple)));A.append(b('<div style="clear:both;" />'))});m.empty().attr("id","stackview"+a++).data("scroller",y).append(A);if(parseInt(y.start)<0){b("#"+h).find(".scroller-page ul:last").after('<div class="book-end" />');b("#"+h).find(".scroller-loading-next").remove();e.infiniteScroller();return}else{p(m)}}}if(d.search_type==="loc_sort_order"){g(e.find(".scroller-page"),parseFloat(d.loc_sort_order),"center",0,"",function(){e.infiniteScroller({search_type:d.search_type,axis:d.axis,threshold:d.threshold,fetch:function(m,l){var n=this.data("scroller"),o=m===1?"downstream":"upstream",k=n.docs[m===1?n.docs.length-1:0].loc_sort_order[0]+1;g(b("<div/>").appendTo("body"),k,o,c,d.query,l)},pagechange:function(k){var l=this.data("scroller").docs;i.loc_sort_order=l[parseInt(l.length/2)].loc_sort_order[0]}})})}else{g(e.find(".scroller-page"),d.id,"downstream",0,d.query,function(){e.infiniteScroller({search_type:d.search_type,axis:d.axis,threshold:d.threshold,fetch:function(l,k){var n=this.data("scroller"),p="downstream",q=d.id,m=d.query,o=n.start;g(b("<div/>").appendTo("body"),q,p,o,m,k)}})})}})}})(jQuery);var stackCache=(function(d,f){var b={},e=d.JSON&&(function(){try{return("localStorage" in d)&&d.localStorage!==null}catch(h){return false}})();return{set:g,get:c,remove:a};function g(j,k,h){var i=h&&new Date(+new Date()+h*1000),m={expires:+i,value:k};if(e){try{localStorage[j]=JSON.stringify(m)}catch(l){return l}}else{b[j]=m}}function c(h){var i,j;if(e){i=localStorage[h];if(i){i=JSON.parse(i)}}else{i=b[h]}if(i){if(i.expires&&i.expires<+new Date()){a(h)}else{j=i.value}}return j}function a(h){if(e){localStorage.removeItem(h)}else{delete b[h]}}})(window);
+(function(g,f,a,h){var d,e="stackView",c,b={};d={init:"stackview.init",page_load:"stackview.pageload"};b.get_heat=function(i){return i===100?10:Math.floor(i/10)+1};b.get_height=function(l,m){var k=parseInt(m.measurement_height_numeric,10),n=l.options.min_item_height,j=l.options.max_item_height,i=l.options.height_multiple;k=Math.min(Math.max(k,n),j)*i;return k+"px"};b.get_thickness=function(k,l){var n=parseInt(l.measurement_page_numeric,10),m=k.options.min_pages,j=k.options.max_pages,i=k.options.page_multiple;n=Math.min(Math.max(n,m),j)*i;return n+"px"};b.normalize_link=function(i){return i.title_link_friendly?"../shelflife/book/"+i.title_link_friendly+"/"+i.id:i.link};b.get_author=function(j){var i=j.creator&&j.creator.length?j.creator[0]:"";if(/^([^,]*)/.test(i)){i=i.match(/^[^,]*/)}return i};b.render_items=function(i,m,j){var k=j?"before":"append",l=j?j:i.$element.find(i.options.selectors.item_list);g.each(m,function(o,p){var n=g(tmpl(c.templates.book,{heat:b.get_heat(p.shelfrank),book_height:b.get_height(i,p),book_thickness:b.get_thickness(i,p),link:b.normalize_link(p),title:p.title,author:b.get_author(p),year:p.pub_date}));n.data("stackviewItem",p);l[k](n)});if(j){j.remove()}};b.calculate_params=function(i){var k={start:i.page*i.options.items_per_page,limit:i.options.items_per_page,search_type:i.options.search_type,query:i.options.query},j,l;if(k.search_type==="loc_sort_order"){k.start="-1";if(i.page===0){k.query=["[",i.options.id-Math.floor(i.options.items_per_page/2),"%20TO%20",i.options.id+Math.floor(i.options.items_per_page/2),"]"].join("")}else{if(i.direction==="down"){j=i.$element.find(i.options.selectors.item).last();l=j.data("stackviewItem").loc_sort_order[0]+1;k.query=["[",l,"%20TO%20",l+i.options.items_per_page,"]"].join("")}else{if(i.direction==="up"){j=i.$element.find(i.options.selectors.item).first();l=j.data("stackviewItem").loc_sort_order[0]+1;k.query=["[",l-i.options.items_per_page,"%20TO%20",l,"]"].join("")}}}}return k};b.fetch_page=function(j,m){var l=b.calculate_params(j),k,i;if(j.options.jsonp){l.callback="?"}i=g.param(l);j.page++;k=f.stackCache.get(j.options.url+i);if(k){m(k)}else{g.getJSON(j.options.url,i,function(n){f.stackCache.set(j.options.url+l,n,j.options.cache_ttl);m(n)})}};b.reverse_flow=function(j){var m=j.$element.find(j.options.selectors.item);for(var k=m.length-1,l=0;k>=0;k--,l++){m.eq(k).css("z-index",l)}};c=function(j,i){this.element=j;this.$element=g(j);this.options=g.extend({},c.defaults,i);this.page=0;this.finished={up:false,down:false};this.direction="down";this.init()};g.extend(c,{defaults:{url:"basic.json",data:"",jsonp:false,items_per_page:10,page_multiple:0.2,height_multiple:12.5,search_type:"keyword",query:"",ribbon:"Stack View",id:null,min_pages:200,max_pages:540,min_item_height:20,max_item_height:39,cache_ttl:60,selectors:{item:".stack-item",item_list:".stack-items",ribbon:".ribbon"}}});g.extend(true,c.prototype,{init:function(){var i=this;this.$element.html(tmpl(c.templates.scaffold,{ribbon:this.options.ribbon})).addClass("stackview").bind(d.page_load,function(){b.reverse_flow(i)});this.$element.data("stackviewObject",this);this.$element.trigger(d.init);this.next_page()},next_page:function(){var i=g(tmpl(c.templates.placeholder,{})),k=this,j=this.options;if(this.finished.down){return}this.direction="down";if(j.data){b.render_items(this,j.data.docs?j.data.docs:j.data);this.finished.down=true;this.$element.trigger(d.page_load,[j.data])}else{if(j.url){this.$element.find(j.selectors.item_list).append(i);b.fetch_page(this,function(l){b.render_items(k,l.docs,i);if(parseInt(l.start,10)===-1){k.finished.down=true}k.$element.trigger(d.page_load,[l])})}}},prev_page:function(){var i=g(tmpl(c.templates.placeholder,{})),k=this.options,j=this;if(k.search_type!=="loc_sort_order"||this.finished.up){return}this.direction="up";this.$element.find(k.selectors.item_list).prepend(i);b.fetch_page(this,function(l){var m=j.$element.find(k.selectors.item).first();b.render_items(j,l.docs,i);if(page>1){j.$element.find(k.selectors.item_list).animate({scrollTop:"+="+m.position().top},0)}if(parseInt(l.start,10)===-1){j.finished.up=true}j.$element.trigger(d.page_load,[l])})}});g.fn[e]=function(k){var i,j=Array.prototype.slice.call(arguments,1);this.each(function(m,o){var l=g(o),p=l.data("stackviewObject");if(!p){new c(o,k)}else{if(p[k]){var n=p[k](j);if(i===h&&n!==h){i=n}}}});return i===h?this:i};f.StackView=c})(jQuery,window,document);(function(c,d){var a=c(document),b;c.extend(StackView.defaults,{infiniteScrollDistance:100});b=function(f){var l=c(f.target),m=l.data("stackviewObject"),j,e,g,i,h,k;if(!m){return}e=m.options;j=l.find(e.selectors.item_list);g=j.find(e.selectors.item).last().position().top;g+=j.scrollTop();i=g-l.height()-e.infiniteScrollDistance;h=function(){if(j.scrollTop()>=i){j.unbind("scroll.stackview",h);l.stackView("next_page")}};k=function(){if(j.scrollTop()<=e.infiniteScrollDistance){j.unbind("scroll.stackview",k);l.stackView("prev_page")}};j.bind("scroll.stackview",h);j.bind("scroll.stackview",k);h();k()};a.delegate(".stackview","stackview.pageload",b)})(jQuery);(function(c,d){var b=c(document),a=window.StackView;c.extend(true,a.defaults,{transitionDuration:200,navigationPercent:80,selectors:{downstream:".downstream",upstream:".upstream",num_items:".num-found span"}});b.delegate(".stackview","stackview.init",function(f){var g=c(f.target),e=g.data("stackviewObject"),i=g.find(e.options.selectors.item_list),h=g.height()*e.options.navigationPercent/100;g.prepend(tmpl(a.templates.navigation,{}));g.delegate(e.options.selectors.downstream,"click",function(){i.animate({scrollTop:"+="+h},e.options.transitionDuration);return false}).delegate(e.options.selectors.upstream,"click",function(){i.animate({scrollTop:"-="+h},e.options.transitionDuration);return false})}).delegate(".stackview","stackview.pageload",function(g,h){var i=c(g.target),e=i.data("stackviewObject"),f=h.num_found?h.num_found:h.length;i.find(e.options.selectors.num_items).text(f)})})(jQuery);window.stackCache=(function(d,f){var b={},e=d.JSON&&(function(){try{return("localStorage" in d)&&d.localStorage!==null}catch(h){return false}})();return{set:g,get:c,remove:a};function g(j,k,h){var i=h&&new Date(+new Date()+h*1000),m={expires:+i,value:k};if(e){try{localStorage[j]=JSON.stringify(m)}catch(l){return l}}else{b[j]=m}}function c(h){var i,j;if(e){i=localStorage[h];if(i){i=JSON.parse(i)}}else{i=b[h]}if(i){if(i.expires&&i.expires<+new Date()){a(h)}else{j=i.value}}return j}function a(h){if(e){localStorage.removeItem(h)}else{delete b[h]}}})(window);(function(a){StackView.templates={scaffold:' <div class="ribbon"><%= ribbon %></div> <ul class="stack-items" />',navigation:' <div class="stack-navigation"> <div class="upstream">Up</div> <div class="num-found"> <span></span><br />items </div> <div class="downstream">Down</div> </div>',book:' <li class="stack-item stack-book heat<%= heat %>" style="width:<%= book_height %>; height:<%= book_thickness %>;"> <a href="<%= link %>" target="_newtab"> <span class="spine-text"> <span class="spine-title"><%= title %></span> <span class="spine-author"><%= author %></span> </span> <span class="spine-year"><%= year %></span> <span class="stack-pages" /> <span class="stack-cover" /> </a> </li>',placeholder:'<li class="stackview-placeholder"></li>'}})();
View
2 php/README.md
@@ -1,3 +1,3 @@
# /php
-This directory contains PHP scripts for querying a number of services and returning JSON as expected by the StackView plugin. Please refer to [the examples page](http://librarylab.law.harvard.edu/projects/stackview/demo/examples.html) for details on how to use the scripts.
+This directory contains PHP scripts for querying a number of services and returning JSON as expected by the Stack View plugin. Please refer to [the examples page](http://librarylab.law.harvard.edu/projects/stackview/demo/examples.html) for details on how to use the scripts.
View
9 src/js/jquery.infinitescroller.min.js
@@ -1,9 +0,0 @@
-/*!
- * jQuery infiniteScroller - v0.1pre - 9/24/2010
- * http://benalman.com/
- *
- * Copyright (c) 2010 "Cowboy" Ben Alman
- * Dual licensed under the MIT and GPL licenses.
- * http://benalman.com/about/license/
- */
-(function($){var a="infiniteScroller",b;$.fn[a]=b=function(d){d=$.extend({},b.options,d);var c={Width:"Height",Left:"Top"};$.each(c,function(f,e){if(axis==="x"){c[f]=e=f}c[f.toLowerCase()]=e.toLowerCase()});return this.each(function(){var G=$(this),e=G[0]===document.body?$(window):G,A=G.children(".scroller-content"),q,f,E=A.children(".scroller-loading:first-child"),F=A.children(".scroller-loading:last-child"),u=o(E)||0,x=o(F)||0,H=0,z=0,v,D,w,K;n(false,true);k(q.eq(0));function J(){var L=K;K=g();if(d.pagechange&&L!==K){d.pagechange.call(q.eq(K),q.eq(L))}if(d.scroll){d.scroll.call(G,B(G)-H)}if(d.search_type=="loc_sort_order"){j(-1)}j(1)}J();s();h();e.bind("scroll."+a+" resize."+a,J);G.bind("reflow."+a,s);G.bind("set-zero."+a,h);G.bind("move-to."+a,function(M,L){t(L)});G.bind("move-by."+a,function(M,N){var L={dir:1,amount:r("scroll_by")};N=$.extend(L,typeof N==="number"?{amount:N}:N);if(N.amount==="page"){y(N.dir)}else{i(N.dir*N.amount)}});function s(){n(true);C(K,true)}function n(L,N){q=A.children(".scroller-page");f=[];v=D=B(q.eq(0));q.each(function(O){var P=$(this);L&&p(P,D);f[O]={start:D,end:D+o(P,true)};D+=o(P)});u&&p(E,v-u);x&&p(F,D);var M=I();if(M<0){p(A,u&&x?(o(G)-D)/2:u?o(G)-D:x?v:-M/2)}else{p(A,u-v);if(N){}}}function k(L){L.addClass("scroller-page").data(a,{})}function y(N,M){var L=K+N;L=Math.min(Math.max(L,0),q.length);C(L,M)}function C(L,M){t(q.eq(L),M)}function i(N,L,M){t(N,L,M,true)}function t(W,T,L,X){var Q=d.scroll_duration,Y=B(G),O,U,M,P,S,N,R;if(W&&typeof W!=="number"){if((O=$(W)).length){S=u-v-H-r("offset")[0],N=l(),R=N.start-N.end;U=f[q.index(O)];M=U.start;P=U.end;W=(M-P<R?M:(M+P+R)/2)+S}else{return}}w=Z(X?Y+W:W+H);if(!L){G.stop(true,false);z=0}if(!Q||T){V(w)}else{G.scrollTop(Y).animate({scrollTop:w},{step:function(aa,ab){V(aa-z)},duration:Q})}function Z(ab){var aa=I();return Math.min(Math.max(ab,Math.min(0,aa)),Math.max(0,aa))}function V(aa){e["scroll"+c.Left](Z(aa))}}function j(O){var N=O!==1,S=q.eq(N?0:q.length-1),P=S.data(a),L=d.fetch,M=N?"prev":"next",R=N?u:x,T=B(G),Q=(N?T:I()-T)-R;if(R&&!P[M]&&$.isFunction(L)&&Q<=r("threshold")){P[M]=true;setTimeout(function(){L.call(S,O,function(U){if(U===false){if(N){z+=u;h(H-u);i(-u,true,true);E.hide();u=0}else{F.hide();x=0}n()}else{if(U){var V;U=$(U);k(U);if(N){E.after(U);V=o(U);p(U,B(S)-V);n();h(H+V);i(V,true,true);z-=V}else{F.before(U);p(U,B(S)+o(S));n()}j(O)}else{delete P[M]}}})},1)}}function B(L){return L[0]===G[0]?e["scroll"+c.Left]():L.position()[c.left]}function p(M,N){var L={};if(N!==B(M)){L[c.left]=N;M.css(L)}}function o(L,M){return L[0]===A[0]?u+x+D-v:L[(L[0]===G[0]?"inner":"outer")+c.Width](!M)}function m(M,L){M[c.width](L)}function r(M){var L=d[M];return $.isFunction(L)?L.call(G,o(G)):L}function I(){return o(A)-o(G)}function h(L){H=typeof L==="number"?L:B(G)}function l(){var M=B(G)+v-u,L=r("offset");return{start:M+L[0],end:M+o(G)-L[1]}}function g(){var R=l(),Q=R.start,M=R.end,S,O=[],N=[],L=[],P;$.each(f,function(U,V){var W=V.start,T=V.end;if(W>=M){return false}if(W>=Q){if(T<=M){S=O.push(U)}else{N.push(U)}}else{if(T>Q){N.push(U)}}});L=$.map(S?O:N,function(U){var V=f[U],W=V.start,T=V.end;return{i:U,d:S?Math.abs((Q+M-W-T)/2):W<Q?Q-T:W-M}}).sort(function(U,T){return U.d-T.d});return L.length?L[0].i:0}})};b.options={axis:"x",threshold:function(c){return c},scroll_by:function(c){return c},position:function(d,c){return(d+c)/2},pagechange:function(c){},scroll:function(c){},scroll_duration:400,offset:[0,0],fetch:null}})(jQuery);
View
13 src/js/jquery.mousewheel.pack.js
@@ -1,13 +0,0 @@
-/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
- * Licensed under the MIT License (LICENSE.txt).
- *
- * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
- * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
- * Thanks to: Seamus Leahy for adding deltaX and deltaY
- *
- * Version: 3.0.6
- *
- * Requires: 1.2.2+
- */
-(function(d){function e(a){var b=a||window.event,c=[].slice.call(arguments,1),f=0,e=0,g=0,a=d.event.fix(b);a.type="mousewheel";b.wheelDelta&&(f=b.wheelDelta/120);b.detail&&(f=-b.detail/3);g=f;b.axis!==void 0&&b.axis===b.HORIZONTAL_AXIS&&(g=0,e=-1*f);b.wheelDeltaY!==void 0&&(g=b.wheelDeltaY/120);b.wheelDeltaX!==void 0&&(e=-1*b.wheelDeltaX/120);c.unshift(a,f,e,g);return(d.event.dispatch||d.event.handle).apply(this,c)}var c=["DOMMouseScroll","mousewheel"];if(d.event.fixHooks)for(var h=c.length;h;)d.event.fixHooks[c[--h]]=
-d.event.mouseHooks;d.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=c.length;a;)this.addEventListener(c[--a],e,false);else this.onmousewheel=e},teardown:function(){if(this.removeEventListener)for(var a=c.length;a;)this.removeEventListener(c[--a],e,false);else this.onmousewheel=null}};d.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);
View
457 src/js/jquery.stackview.base.js
@@ -0,0 +1,457 @@
+/*!
+ Stack View - The jQuery virtual stack plugin
+ by The Harvard Library Innovation Lab
+
+ Dual licensed under MIT and GPL.
+*/
+(function($, window, document, undefined) {
+ var events,
+ plugin = 'stackView',
+ StackView,
+ utils = {};
+
+ events = {
+ init: 'stackview.init',
+ page_load: 'stackview.pageload'
+ };
+
+
+ /*
+ #get_heat(number) - Private
+
+ Takes a value between 0 and 100 and returns a number to be used with
+ heat classes to indicate popularity.
+ */
+ utils.get_heat = function(scaled_value) {
+ return scaled_value === 100 ? 10 : Math.floor(scaled_value / 10) + 1;
+ };
+
+ /*
+ #get_height(StackView, object) - Private
+
+ Takes a StackView instance and a book object. Returns a normalized
+ book height, taking into account the minimum height, maximum height,
+ and height multiple.
+ */
+ utils.get_height = function(stack, book) {
+ var height = parseInt(book.measurement_height_numeric, 10),
+ min = stack.options.min_item_height,
+ max = stack.options.max_item_height,
+ multiple = stack.options.height_multiple;
+
+ height = Math.min(Math.max(height, min), max) * multiple;
+ return height + 'px';
+ };
+
+ /*
+ #get_thickness(StackView, object) - Private
+
+ Takes a StackView instance and a book object. Returns a normalized
+ book thickness using the number of book pages, taking into account
+ the minimum pages, maximum pages, and pages multiple.
+ */
+ utils.get_thickness = function(stack, book) {
+ var thickness = parseInt(book.measurement_page_numeric, 10),
+ min = stack.options.min_pages,
+ max = stack.options.max_pages,
+ multiple = stack.options.page_multiple;
+
+ thickness = Math.min(Math.max(thickness, min), max) * multiple;
+ return thickness + 'px';
+ };
+
+ /*
+ #normalize_link(object) - Private
+
+ Takes an item and returns the item's link, taking into account
+ workarounds that may come from inconsistent data structure.
+ */
+ utils.normalize_link = function(item) {
+ //workaround for link construction from LibraryCloud
+ return item.title_link_friendly ?
+ '../shelflife/book/' + item.title_link_friendly + '/' + item.id :
+ item.link;
+ };
+
+ /*
+ #get_author(object) - Private
+
+ Takes an item and returns the item's author, taking the first
+ author if an array of authors is defined.
+ */
+ utils.get_author = function(item) {
+ var author = item.creator && item.creator.length ? item.creator[0] : '';
+
+ if(/^([^,]*)/.test(author)) {
+ author = author.match(/^[^,]*/);
+ }
+
+ return author;
+ };
+
+ /*
+ #render_items(StackView, array [, jQuery]) - Private
+
+ Takes a StackView instance, an array of result items, and an optional
+ jQuery object. Renders a DOM element for each of the items and
+ appends it to the stack's item list. If [placeholder] is passed in the
+ items take the its spot in the DOM.
+ */
+ utils.render_items = function(stack, docs, $placeholder) {
+ var action = $placeholder ? 'before' : 'append',
+ $pivot = $placeholder ?
+ $placeholder :
+ stack.$element.find(stack.options.selectors.item_list);
+
+
+ $.each(docs, function(i, item) {
+ var $item = $(tmpl(StackView.templates.book, {
+ heat: utils.get_heat(item.shelfrank),
+ book_height: utils.get_height(stack, item),
+ book_thickness: utils.get_thickness(stack, item),
+ link: utils.normalize_link(item),
+ title: item.title,
+ author: utils.get_author(item),
+ year: item.pub_date
+ }));
+
+ $item.data('stackviewItem', item);
+ $pivot[action]($item);
+ });
+
+ if ($placeholder) {
+ $placeholder.remove();
+ }
+ };
+
+ /*
+ #calculate_params(StackView) - Private
+
+ Takes a StackView instance and returns the parameters for the next page.
+ If the Stack uses loc_sort_order, this adjusts the query for that case.
+ Returns a plain object with key:value params to be used by $.param.
+ */
+ utils.calculate_params = function(stack) {
+ var params = {
+ start: stack.page * stack.options.items_per_page,
+ limit: stack.options.items_per_page,
+ search_type: stack.options.search_type,
+ query: stack.options.query
+ }, $pivot, id;
+
+ if (params.search_type === 'loc_sort_order') {
+ params.start = '-1';
+ if (stack.page === 0) {
+ params.query = [
+ '[',
+ stack.options.id - Math.floor(stack.options.items_per_page / 2),
+ '%20TO%20',
+ stack.options.id + Math.floor(stack.options.items_per_page / 2),
+ ']'
+ ].join('');
+ }
+ else if (stack.direction === 'down') {
+ $pivot = stack.$element.find(stack.options.selectors.item).last();
+ id = $pivot.data('stackviewItem').loc_sort_order[0] + 1;
+ params.query = [
+ '[',
+ id,
+ '%20TO%20',
+ id + stack.options.items_per_page,
+ ']'
+ ].join('');
+ }
+ else if (stack.direction === 'up') {
+ $pivot = stack.$element.find(stack.options.selectors.item).first();
+ id = $pivot.data('stackviewItem').loc_sort_order[0] + 1;
+ params.query = [
+ '[',
+ id - stack.options.items_per_page,
+ '%20TO%20',
+ id,
+ ']'
+ ].join('');
+ }
+ }
+
+ return params;
+ };
+
+ /*
+ #fetch_page(StackView, function) - Private
+
+ Takes a StackView instance and a callback function. Retrieves the
+ next page according to the URL and other options of the StackView
+ instance. When the page is finished fetching, the callback is
+ invoked, passing in the array of items.
+ */
+ utils.fetch_page = function(stack, callback) {
+ var params = utils.calculate_params(stack),