stackview_acorn_tester 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +291 -0
  4. data/Rakefile +37 -0
  5. data/app/assets/javascripts/rails_stackview/auto_init.js +15 -0
  6. data/app/assets/javascripts/rails_stackview/browser.js +161 -0
  7. data/app/assets/javascripts/rails_stackview/plain.js +128 -0
  8. data/app/assets/javascripts/rails_stackview.js +11 -0
  9. data/app/assets/stylesheets/rails_stackview/_plain.scss +119 -0
  10. data/app/assets/stylesheets/rails_stackview/browser.scss +116 -0
  11. data/app/assets/stylesheets/rails_stackview.scss +10 -0
  12. data/app/controllers/stackview_data_controller.rb +91 -0
  13. data/app/fetch_adapters/rails_stackview/db_window_fetcher.rb +88 -0
  14. data/app/fetch_adapters/rails_stackview/mock_fetcher.rb +27 -0
  15. data/app/models/stackview_call_number.rb +2 -0
  16. data/app/views/rails_stackview/browser.html.erb +42 -0
  17. data/config/routes.rb +2 -0
  18. data/db/migrate/20150602210254_create_stackview_call_numbers.rb +34 -0
  19. data/lib/rails_stackview/engine.rb +7 -0
  20. data/lib/rails_stackview/version.rb +3 -0
  21. data/lib/rails_stackview.rb +20 -0
  22. data/lib/tasks/rails_stackview_tasks.rake +4 -0
  23. data/test/controllers/stackview_data_controller_test.rb +55 -0
  24. data/test/dummy/README.rdoc +28 -0
  25. data/test/dummy/Rakefile +6 -0
  26. data/test/dummy/app/assets/javascripts/application.js +17 -0
  27. data/test/dummy/app/assets/stylesheets/application.css +20 -0
  28. data/test/dummy/app/controllers/application_controller.rb +5 -0
  29. data/test/dummy/app/controllers/demo_controller.rb +14 -0
  30. data/test/dummy/app/helpers/application_helper.rb +2 -0
  31. data/test/dummy/app/views/demo/index.html.erb +14 -0
  32. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  33. data/test/dummy/bin/bundle +3 -0
  34. data/test/dummy/bin/rails +4 -0
  35. data/test/dummy/bin/rake +4 -0
  36. data/test/dummy/bin/setup +29 -0
  37. data/test/dummy/config/application.rb +26 -0
  38. data/test/dummy/config/boot.rb +5 -0
  39. data/test/dummy/config/database.yml +25 -0
  40. data/test/dummy/config/environment.rb +5 -0
  41. data/test/dummy/config/environments/development.rb +41 -0
  42. data/test/dummy/config/environments/production.rb +79 -0
  43. data/test/dummy/config/environments/test.rb +42 -0
  44. data/test/dummy/config/initializers/assets.rb +11 -0
  45. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  46. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  47. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  48. data/test/dummy/config/initializers/inflections.rb +16 -0
  49. data/test/dummy/config/initializers/mime_types.rb +4 -0
  50. data/test/dummy/config/initializers/session_store.rb +3 -0
  51. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  52. data/test/dummy/config/locales/en.yml +23 -0
  53. data/test/dummy/config/routes.rb +67 -0
  54. data/test/dummy/config/secrets.yml +22 -0
  55. data/test/dummy/config.ru +4 -0
  56. data/test/dummy/public/404.html +67 -0
  57. data/test/dummy/public/422.html +67 -0
  58. data/test/dummy/public/500.html +66 -0
  59. data/test/dummy/public/favicon.ico +0 -0
  60. data/test/dummy/test_fixture.yaml +433 -0
  61. data/test/fetch_adapters/db_window_fetcher_test.rb +106 -0
  62. data/test/fixtures/stackview_call_numbers.yml +473 -0
  63. data/test/integration/navigation_test.rb +10 -0
  64. data/test/rails_stackview_test.rb +7 -0
  65. data/test/test_helper.rb +42 -0
  66. data/vendor/assets/README.md +16 -0
  67. data/vendor/assets/images/stackview/bookEnd-next.png +0 -0
  68. data/vendor/assets/images/stackview/bookEnd-prev.png +0 -0
  69. data/vendor/assets/images/stackview/gloss.png +0 -0
  70. data/vendor/assets/images/stackview/highGloss.png +0 -0
  71. data/vendor/assets/images/stackview/icon-globe.png +0 -0
  72. data/vendor/assets/images/stackview/icon-note.png +0 -0
  73. data/vendor/assets/images/stackview/nav.png +0 -0
  74. data/vendor/assets/images/stackview/placeholder.gif +0 -0
  75. data/vendor/assets/images/stackview/ribbonTab.png +0 -0
  76. data/vendor/assets/images/stackview/serials-edge.png +0 -0
  77. data/vendor/assets/images/stackview/serials.png +0 -0
  78. data/vendor/assets/images/stackview/superGloss.png +0 -0
  79. data/vendor/assets/javascripts/jquery.stackview.js +21 -0
  80. data/vendor/assets/javascripts/stackview/jquery.easing.1.3.js +205 -0
  81. data/vendor/assets/javascripts/stackview/jquery.stackview.base.js +561 -0
  82. data/vendor/assets/javascripts/stackview/jquery.stackview.infinite.js +46 -0
  83. data/vendor/assets/javascripts/stackview/jquery.stackview.ministack.js +33 -0
  84. data/vendor/assets/javascripts/stackview/jquery.stackview.navigation.js +71 -0
  85. data/vendor/assets/javascripts/stackview/jquery.stackview.stackcache.js +74 -0
  86. data/vendor/assets/javascripts/stackview/jquery.stackview.templates.js +31 -0
  87. data/vendor/assets/javascripts/stackview/microtemplating.js +40 -0
  88. data/vendor/assets/javascripts/stackview/types/book.js +184 -0
  89. data/vendor/assets/javascripts/stackview/types/my_plain.js +183 -0
  90. data/vendor/assets/javascripts/stackview/types/serial.js +40 -0
  91. data/vendor/assets/javascripts/stackview/types/soundrecording.js +42 -0
  92. data/vendor/assets/javascripts/stackview/types/videofilm.js +56 -0
  93. data/vendor/assets/javascripts/stackview/types/webpage.js +42 -0
  94. data/vendor/assets/stackview.sha +1 -0
  95. data/vendor/assets/stylesheets/stackview/_book.scss +66 -0
  96. data/vendor/assets/stylesheets/stackview/_heatmap.scss +154 -0
  97. data/vendor/assets/stylesheets/stackview/_ministack.scss +43 -0
  98. data/vendor/assets/stylesheets/stackview/_mixins.scss +100 -0
  99. data/vendor/assets/stylesheets/stackview/_navigation.scss +52 -0
  100. data/vendor/assets/stylesheets/stackview/_plain.scss +71 -0
  101. data/vendor/assets/stylesheets/stackview/_serial.scss +50 -0
  102. data/vendor/assets/stylesheets/stackview/_soundrecording.scss +83 -0
  103. data/vendor/assets/stylesheets/stackview/_videofilm.scss +74 -0
  104. data/vendor/assets/stylesheets/stackview/_webpage.scss +82 -0
  105. data/vendor/assets/stylesheets/stackview/jquery.stackview.scss +171 -0
  106. metadata +233 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 52758b9ebe7d5f834d3070d4c9fc86763711d797ecd597c5bde9e6799d21352a
4
+ data.tar.gz: 2842d6cb9f1f5df3cae85118bdcb02626ee66e533d9183538c3dda9249451f59
5
+ SHA512:
6
+ metadata.gz: 455b4b57d0852282cc9ee469f6330b2ff0b0bed3c185512467c986cc168fae0e9fc0ce1d177a1b49e887dfd65e438ea6bf93a9dfb55b6b798d86feedd81156ab
7
+ data.tar.gz: ce2ce5119dfd29e8c7494370d5b939ea41cd78fb8840541c702706c04a83fd93b0877b3f7a9254f317d765890860471d498300528fe5ae780220518bd1f2bacb
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2015 Jonathan Rochkind
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,291 @@
1
+ [![Build Status](https://travis-ci.org/jrochkind/rails_stackview.svg?branch=master)](https://travis-ci.org/jrochkind/rails_stackview) [![Gem Version](https://badge.fury.io/rb/rails_stackview.svg)](http://badge.fury.io/rb/rails_stackview)
2
+
3
+ # RailsStackview
4
+
5
+ Packages the assets from the Harvard Library Innovation Lab's [stackview](https://github.com/harvard-lil/stackview) for the Rails asset pipeline, and provides additional optional integration support with a controller and a template.
6
+
7
+ This is not an out of the box solution, integrating it into your app will require some development.
8
+
9
+ The hardest part, for call-number browse, is typically arranging your call numbers somewhere
10
+ so they can be accessed in sorted order.
11
+
12
+ RailsStackview contains the original stackview assets, arranged for the Rails asset pipeline. Along with some higher-level components. These higher-level have been created for my own use cases and needs; while I've tried to give a nod to future expandability, they haven't been created to be fully robust and configurable for all use cases. In this project, for a change, I've tried to be guided by keeping it simple and [YAGNI](http://martinfowler.com/bliki/Yagni.html).
13
+
14
+ My focused use case is 'shelf browse', browse through a very long list of ordered
15
+ items, starting at a specified point in the middle.
16
+
17
+ ## Requirements
18
+
19
+ The Stackview code needs JQuery, so you should have JQuery loaded in your app.
20
+
21
+ This code is meant for integration with a Rails app. It does not assume Blacklight,
22
+ although is usable with Blacklight.
23
+
24
+ Add it to your app like any other gem, by listing in the Gemfile.
25
+
26
+ ## Usage
27
+
28
+ ### Stackview assets are available.
29
+
30
+ To use the stackview assets directly, include them in your asset pipeline.
31
+
32
+ You can include just the original stackview JS and CSS:
33
+
34
+ ~~~ruby
35
+ # app/assets/javascripts/application.js
36
+ //= require jquery.stackview.js
37
+ ~~~
38
+
39
+ ~~~ruby
40
+ # app/assets/stylesheets/application.css
41
+ *= require stackview/jquery.stackview.scss
42
+ ~~~
43
+
44
+ Now Stackview will be available in your app, via the asset pipeline,
45
+ using the documented stackview API. (eg `$(something).stackView(something)`)
46
+
47
+ Or alternatley you can include all RailsStackview JS/CSS, which provides some
48
+ support for higher level features, along with the original stackview assets:
49
+
50
+ ~~~ruby
51
+ # app/assets/javascripts/application.js
52
+ //= require rails_stackview
53
+ ~~~
54
+
55
+ ~~~ruby
56
+ # app/assets/stylesheets/application.css
57
+ *= require rails_stackview
58
+ ~~~
59
+
60
+ One additional feature included is an automatic application of stackview
61
+ to any `<div>` with a `data-stackview-init` attribute, containing JSON
62
+ serialization of stackview init arguments.
63
+
64
+ This can be convenient for integrating with Rails, letting you for instance
65
+ specify your own rails controller as a data provider to stackview:
66
+
67
+ ~~~erb
68
+ <%= content_tag("div", "",
69
+ :id => "whatever_you_want",
70
+ :class => "whatever you want",
71
+ :data => {
72
+ :stackview_init => {
73
+ :id => 0,
74
+ :url => your_route_helper(some_args),
75
+ :search_type => "loc_sort_order"
76
+ }
77
+ })
78
+ %>
79
+ ~~~
80
+
81
+ The data-stackview-init hash can be whatever you like, as initialization
82
+ arguments for the original stackview.
83
+
84
+ ### Back-End Support: The StackviewDataController to feed data to stackview
85
+
86
+ The [StackviewDataController](./app/controllers/stackview_data_controller.rb) is provided
87
+ to feed data to a stackview UI,
88
+ with the use case of 'call number browse', or starting at an arbitrary
89
+ point in a very long list of items, and paging both back and forwards.
90
+
91
+ The current implementation of the StackviewDataController counts
92
+ on a table of individual call numbers existing in your database.
93
+ It is difficult to get the querries we need out of Solr directly, and
94
+ we opted to create a duplicate 'denormalized' database table with
95
+ exactly the info needed to support the front-end.
96
+
97
+ Once you've added `rails_stackview` to your Gemfile, you can
98
+ install a migration into your app to create the `stackview_call_numbers` table,
99
+ with:
100
+
101
+ bundle exec rake rails_stackview_engine:install:migrations
102
+
103
+ It is up to you to fill this table with call number data. If you
104
+ use [traject](https://github.com/traject/traject) to index
105
+ MARC to Solr, you can look at [this example of how I handle
106
+ creating the stackview_call_numbers table at the same time
107
+ I do my Solr indexing](./docs/traject-indexing.example.rb)
108
+
109
+ Here are the elements of the `stackview_call_numbers` table:
110
+
111
+ * `system_id` (string), the primary key of the original item
112
+ in your overall system, used for linking from stackview
113
+ to your system.
114
+ * `sort_key` (string), a _sortable_ representation of your call
115
+ number or other ordering. Used for sorting the stack. If you
116
+ are using LC Call Numbers and populating this table in ruby,
117
+ we suggest the [Lcsort](https://github.com/pulibrary/lcsort) gem for turning a call number
118
+ into a sortable representation. Some features will end up less confusing if
119
+ sort_keys are unique, although they aren't required to be -- I append
120
+ the bibID to the end of each sort_key, to make them unique even if two
121
+ bibs share the same call number.
122
+ * `sort_key_display` (string, optional), the original human-displayable
123
+ call number, can be used for display.
124
+ * `title` (string), title to use in stackview representation.
125
+ * `creator` (string, optional), author to use in stackview representation.
126
+ * `pub_date` (string, optional), publication year (as string) to use in stackview representation.
127
+ * `measurement_page_numeric` (int, optional), page count, passed to stackview for represnetation width.
128
+ * `measurement_height_numeric` (int, optional), item height (usually in cm), passed to stackview for representation height
129
+ * `shelfrank` (int, optional), 1-100, passed to stackview for "heatmap" intensity coloring of representation. Normally a count of number of times checked out.
130
+ * `created_at` (datetime, optional), can set to row creation date for your administrative convenience.
131
+ * `format`: Passed to stackview to choose a format-specific view template, should be one of magic words from stackview's own source (case-sensitive, not entirely consistent): `book` `Serial`, `Sound Recording`, `Video/Film`, `webpage`. Also our own special `plain` format, which can also take a specific description etc `plain:VHS`. See more at "Custom Plain Format" below.
132
+ * `sort_key_type` (string): Eventually we plan to support multiple separate call number runs, which will
133
+ be identified by `sort_key_type`. We have the beginnings of such an architecture, but
134
+ it may not be fully fleshed out and may have performance implications. For now recommend always setting
135
+ this to the default, `lc`.
136
+
137
+ Once you've filled this database, you can use it with our Browser front-end, or you can construct your own stackview front-end telling stackview to use this to use this controller as a source for:
138
+
139
+ Add routing to the StackviewDataController in your own `./config/routes.rb`
140
+
141
+ ~~~ruby
142
+ get 'stackview_data/:call_number_type', :to => "stackview_data#fetch", :as => "stackview_data"
143
+ ~~~
144
+
145
+ (That specific `:as => 'stackview_data'` is needed if you are using our Browser front-end)
146
+
147
+ When you initialize a stackview UI element, you have to tell it what item to start at, by giving it a `sort_key` (normalized sortable call number representation) value. One way to get a sort_key for
148
+ a known item, is simply to look it up from the existing `stackview_call_numbers` table:
149
+
150
+ ~~~ruby
151
+ # may be nil if no such system_id recorded
152
+ origin_sort_key = StackviewCallNumber.where(:system_id => document.id).order("created_at").pluck(:sort_key).first
153
+ ~~~
154
+
155
+ Now you can initialize a stackview UI element, using the RailsStackview feature
156
+ to automatically init a stackview from a data-stackview-init attribute:
157
+
158
+ ~~~erb
159
+ <%= content_tag("div", "",
160
+ :id => "my_stackview",
161
+ :data => {
162
+ :stackview_init => {
163
+ :id => 0,
164
+ :url => stackview_data_path("lc", :origin_sort_key => origin_sort_key),
165
+ :search_type => "loc_sort_order"
166
+ }
167
+ })
168
+ %>
169
+ ~~~
170
+
171
+ If you pass an :origin_sort_key that doesn't actually exist in the database,
172
+ the StackviewDataController will still put the user into the stacks at the closest
173
+ point to that theoretical call number.
174
+
175
+ #### Set the link URL
176
+
177
+ To set the `link` property on the JS objects passed to stackview, which will be used
178
+ as the `href` on stackview item hyperlinks, set a lambda/proc as configuration, perhaps
179
+ in an initializer. The proc gets the already constructed stackview hash as a parameter,
180
+ and will be executed in the context of the controller so you can use controller
181
+ methods, such as Rails route helpers.
182
+
183
+ StackviewDataController.set_config_for_type("default", {
184
+ :link => lambda do |hash|
185
+ catalog_path(hash["system_id"])
186
+ end
187
+ })
188
+
189
+ Above is similar to the default, which should work for at least some versions
190
+ of Blacklight by default.
191
+
192
+
193
+ #### What's it doing then?
194
+
195
+ To use the current stackview API (as far as what it fetches from it's back-end), in
196
+ a flexible and high-performance way, we do something a bit odd.
197
+
198
+ The URL fixes the controller to have an 'origin' you specify. Stackview, in "search_type: loc_sort_order" (stackview's terminology) will then send it negative and positive offsets as the user browses -- eg asking
199
+ for items 10 to 20, or -25 to -35. The controller will use SQL `OFFSET` to page forwards and backwards
200
+ around the origin. This ends up pretty performant, although it is odd.
201
+
202
+ The Stackview `loc_sort_order` mode is under-documented on stackview's site, but it's meant
203
+ for 'infinite' scrolling both forwards and back around an origin. Stackview assumes
204
+ you're initialize it to the actual i-index `id` where you want to start; but we set
205
+ a "logical" id starting point of 0, and encode our actual origin in the URL instead. Then
206
+ we can consider stackview's indexes to actually be offsets from our origin.
207
+
208
+ Weird, but it works, without major changes to the stackview JS code itself.
209
+
210
+
211
+ #### Don't want to use the stackview_call_numbers table?
212
+
213
+ It is kind of hacky. Do you have another source for your call numbers? Do you want
214
+ to try to get them via Solr directly using the ndushay/stanford hack?
215
+
216
+ The code extracts out the actual fetch logic into a [RailsStackview::DbWindowFetcher](./app/fetch_adapters/rails_stackview/db_window_fetcher.rb) adapter.
217
+ We intend to let you replace it with your own adapter, that takes the HTTP params sent by
218
+ stackview itself, and returns a list of hashes to be given back to it.
219
+
220
+ This architecture isn't neccesarily fully fleshed out, some parts of RailsStackview
221
+ may be hard-coded in unpleasant ways, but the beginnings are there.
222
+
223
+
224
+ ### Front-end Support: The Browser Template
225
+
226
+ You can write your own Rails template with the stackview element on it. It turns
227
+ out it's a bit tricky to get right for common cases.
228
+
229
+ `rails_stackview` provides a 'browser' template you can use, which is a two-column
230
+ display with stackview on the left, and an item detail panel on the right. It
231
+ takes care of a lot of odd edge cases and details, especially focused again on
232
+ an 'infinite' shelf browser use case.
233
+
234
+ You can use this template in your own controller action method. It needs to be
235
+ initialized with an starting point sortkey, which the stack will center on. It's
236
+ recommended you use a query parameter to pass in the sort key -- the browser
237
+ javascript includes some code to update such a query param with JS replaceState(),
238
+ to keep back button working well.
239
+
240
+ render :template => 'rails_stackview/browser', :locals => {:origin_sort_key => params["origin_sort_key"]}
241
+
242
+ You may want to customize your Rails layout template to work best with the browser template.
243
+ The browser template is designed best to work with _no_ padding or spacing
244
+ underneath it -- Javascript will set the stackview element to stretch to the bottom
245
+ of the browser. A small header is okay. No right or left margin or padding is best.
246
+
247
+ The browser template does use the back-end StackviewDataController, you will need
248
+ to have that set up properly as above.
249
+
250
+ If you want a click on a stack item to load information in the right panel, then you need
251
+ to define your own Rails route with a `stackview_browser_item`, which returns partial
252
+ HTML that should be loaded (via AJAX) in the item detail panel on a click.
253
+
254
+ We have [an example of how I implemented the `stackview_browser_item` action in a
255
+ Blacklight app](./docs/stackview_browser_item.example.md).
256
+
257
+ After an item is loaded by the browser JS, a custom `stackview-item-load` JS event is
258
+ triggered, with the item panel div as the target.
259
+
260
+ On very small screens, the browser is only a single column without the item detail panel,
261
+ and clicks on items will follow the href set on the items, see above under `Set the link URL`.
262
+
263
+
264
+ ### Custom format plain
265
+
266
+ `rails_stackview` adds it's own custom "plain" format, which we use for items
267
+ that are neither books, CDs, DVDs, etc. Or where we can't be sure what format they are.
268
+
269
+ The design isn't too sophisticated, but is meant to look kind of like a plain
270
+ box with a printed label. It does implement stackview heatmap coloring.
271
+
272
+ If you have included `rails_stackview` CSS and JS, the plain format is available.
273
+
274
+ Set format format property to `plain` to trigger. Or, you can set
275
+ additional format description after a colon: `plain:LP`, or `plain:Whatever we want`,
276
+ and the additional format description will be included on the label.
277
+
278
+ ## Development
279
+
280
+ ### Vendored stackview assets
281
+
282
+ Stackview assets (JS, CSS, images) are included directly in source here,
283
+ under [./vendor/assets](./vendor/assets).
284
+
285
+ The original stackview is not versioned, but the git SHA hash of
286
+ the currently vendored assets is included at
287
+ [./vendor/assets/stackview.sha](./vendor/assets/stackview.sha)
288
+
289
+ There is a script for refreshing these assets in rails_stackview source,
290
+ see [./vendor/assets/README.md](./vendor/assets/README.md).
291
+
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'RailsStackview'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+ load 'rails/tasks/statistics.rake'
22
+
23
+
24
+
25
+ Bundler::GemHelper.install_tasks
26
+
27
+ require 'rake/testtask'
28
+
29
+ Rake::TestTask.new(:test) do |t|
30
+ t.libs << 'lib'
31
+ t.libs << 'test'
32
+ t.pattern = 'test/**/*_test.rb'
33
+ t.verbose = false
34
+ end
35
+
36
+
37
+ task default: :test
@@ -0,0 +1,15 @@
1
+ // On page load, look for any elements with a data-stackview-init attribute.
2
+ // That data attribute is expected to include a JSON serialized hash that
3
+ // is an init argument to the stackView() initializer.
4
+
5
+ // We will initialize element with that argument.
6
+ (function( $ ) {
7
+ // page:load for turbolinks too, not sure if it really works right.
8
+ $(document).on('ready page:load', function () {
9
+ $("[data-stackview-init]").each(function(i, element) {
10
+ element = $(element);
11
+ element.stackView(element.data("stackviewInit"));
12
+ });
13
+ });
14
+
15
+ })( jQuery );
@@ -0,0 +1,161 @@
1
+ (function($, undefined) {
2
+
3
+ function fitToWindowHeight() {
4
+ var shelfbrowser = $(".shelfbrowser");
5
+
6
+ if (shelfbrowser.size() > 0) {
7
+ var topOffset = shelfbrowser.offset().top;
8
+ var height = $(window).innerHeight() - topOffset;
9
+
10
+ shelfbrowser.css("height", height);
11
+ // set a bunch of elements to have same height, CSS tricks
12
+ // to make it expand to fit weren't working esp in IE.
13
+ $(".shelfbrowser-stackview").css("height", height);
14
+ $(".shelfbrowser-browser-column").css("height", height);
15
+ $(".shelfbrowser-info-column").css("height", height);
16
+ }
17
+ }
18
+
19
+ window.doit = true;
20
+
21
+ function loadItem(base_url, panel, item) {
22
+ // Fade out the existing content with a pretty cheesy effect,
23
+ // ends up less confusing when load is slowish. Cheesy implementation.
24
+ panel.wrapInner("<div class='rails-stackview-panel-wrap'></div>");
25
+ panel.find(".rails-stackview-panel-wrap").delay(400).fadeTo(600, 0.2);
26
+
27
+
28
+
29
+ if (window.doit) {
30
+ $.ajax({
31
+ url: base_url,
32
+ data: {
33
+ 'id': item.system_id,
34
+ 'sort_key': item.sort_key,
35
+ 'sort_key_display': item.sort_key_display,
36
+ 'sort_key_type': item.sort_key_type
37
+ },
38
+ dataType: "html",
39
+ success: function(html, status, xhr) {
40
+ panel.html( html );
41
+ panel.trigger("stackview-item-load");
42
+ },
43
+ error: function(xhr, status, error) {
44
+ panel.html(errorPanel(error));
45
+ },
46
+ complete: function(xhr, status) {
47
+ // Some kind of bug in chrome/webkit is sometimes making
48
+ // parts of the info column be not properly painted, especially
49
+ // on retina screens. Think we trigger it by changing DOM inside an
50
+ // overflow:auto section.
51
+ // This seems to work around it hackily:
52
+ $(".shelfbrowser-info-column").fadeTo(1, .99).fadeTo(1, 1);
53
+
54
+ // If the info column was previously scrolled, we want
55
+ // to go to top for this new content.
56
+ $(".shelfbrowser-info-column").scrollTop(0);
57
+ }
58
+ });
59
+ }
60
+ }
61
+
62
+ function errorPanel(text) {
63
+ return '<div class="alert alert-warning" role="alert">Sorry, we can not display this item.' +
64
+ (text ? (' (' + text + ')') : '') +
65
+ '</div>';
66
+ }
67
+
68
+ // We add origin_sort_key=$sort_key into the current
69
+ // URL using pushState, if in a browser that supports.
70
+ //
71
+ // The intention is to 'remember' the currently selected
72
+ // item on browser back button to this page, etc.
73
+ //
74
+ // It does assume the host app is supporting ?origin_sort_key=$sort_key
75
+ // and passing it to template, to work. Could make more configurable
76
+ // later.
77
+ function replaceSelectedState(item) {
78
+ if ('history' in window && 'replaceState' in history && 'sort_key' in item) {
79
+ var query = location.search;
80
+ if (query.length == 0)
81
+ query = '?';
82
+
83
+ // replace origin_sort_key only if it exists
84
+ var re = new RegExp("([\\?&])origin_sort_key=([^&#]*)");
85
+ query = query.replace(re, '$1origin_sort_key=' + encodeURIComponent(item.sort_key));
86
+
87
+ history.replaceState({}, '', query + location.hash);
88
+ }
89
+ }
90
+
91
+ $( document ).on("ready", function() {
92
+ if ($(".shelfbrowser").length > 0) {
93
+ fitToWindowHeight();
94
+
95
+ $( window ).on("resize orientationchange", function() {
96
+ fitToWindowHeight();
97
+ });
98
+
99
+ // If stackview_browser_item_path is defined, click on item
100
+ // should load partial via AJAX, and preventDefault.
101
+ $(document).on("click", ".shelfbrowser .stack-item a", function(event) {
102
+ var target = $(event.target);
103
+ var item_load_url = target.closest(".shelfbrowser-browse-column").data('stackviewBrowserItemPath');
104
+ var panel = target.closest(".shelfbrowser").find(".shelfbrowser-info-column .stack-item-panel").filter(":visible");
105
+
106
+ var item_attribute_hash = target.closest(".stack-item").data("stackviewItem");
107
+
108
+ replaceSelectedState(item_attribute_hash);
109
+
110
+ if(item_load_url && panel.length > 0) {
111
+ event.preventDefault();
112
+
113
+ loadItem(item_load_url, panel, item_attribute_hash );
114
+
115
+ $('.active-item').removeClass('active-item');
116
+ $(this).parent().addClass('active-item');
117
+ }
118
+ });
119
+
120
+ // Catch stackview.page the FIRST time, so we can find the origin
121
+ // document and add a special class to it, which we'll use to click
122
+ // on it immediately, and set the scroll view so it's centered.
123
+ $(document).on("stackview.pageload.initial-select", function(event) {
124
+ // Find the .stack-item which has data origin:true set, and click it.
125
+ // Since we're only executing on first load, this shouldn't be
126
+ // that many items.
127
+
128
+ var item_load_url = $(event.target).closest(".shelfbrowser-browse-column").data('stackviewBrowserItemPath');
129
+
130
+ var $origin_item;
131
+
132
+ // Add .origin-item to origin, so we can do things with it....
133
+ $(event.target).find(".stack-item").each(function(index, item) {
134
+ if($(item).data("stackviewItem").is_origin_item) {
135
+ $origin_item = $(item);
136
+ // We add stackview-origin class to allow us to
137
+ // find it and position the scroll properly on load.
138
+ $origin_item.addClass("stackview-origin");
139
+ }
140
+ });
141
+
142
+ //... we want to simulate clicking the origin, if we have a load url,
143
+ // so we can load it.
144
+ if (item_load_url) {
145
+ $origin_item.find("a").trigger('click');
146
+ }
147
+
148
+ //... we want to try to set the scroll such that our origin item is
149
+ // centered.
150
+ // stackview out of the box doesn't quite get this right, it's tricky,
151
+ // we seem to be doing okay.
152
+ var container = $origin_item.closest("ul.stack-items");
153
+ container.scrollTop( $origin_item.get(0).offsetTop - (container.height() / 2) + ($origin_item.height() / 2) )
154
+
155
+ // Remove our handler, we only want to do this once.
156
+ $(document).off("stackview.pageload.initial-select");
157
+ });
158
+ }
159
+ });
160
+
161
+ })(jQuery);
@@ -0,0 +1,128 @@
1
+ (function($, window, undefined) {
2
+ /*
3
+ A very poorly-designed type meant for 'other', meant to look
4
+ sort of like a simple box with a typed sticky label.
5
+
6
+ Trigger with "format: 'plain'", OR add a format label on the end
7
+ too:
8
+
9
+ format: "plain: VHS"
10
+
11
+ The 'title' and extra format info will be displayed, along with pub_date.
12
+ Author display not currently included.
13
+
14
+ measurement_height_numeric can control box height, like 'book'
15
+ type. Box width is fixed though.
16
+ */
17
+ $.extend(true, window.StackView.defaults, {
18
+ selectors: {
19
+ plain: '.stack-plain'
20
+ },
21
+ plain: {
22
+ max_height_percentage: 100,
23
+ max_height: 39,
24
+ min_height_percentage: 20,
25
+ min_height: 10
26
+ }
27
+ });
28
+
29
+ /*
30
+ #translate(number, number, number, number, number) - Private
31
+
32
+ Takes a value (the first argument) and two ranges of numbers. Translates
33
+ this value from the first range to the second range. E.g.:
34
+
35
+ translate(0, 0, 10, 50, 100) returns 50.
36
+ translate(10, 0, 10, 50, 100) returns 100.
37
+ translate(5, 0, 10, 50, 100) returns 75.
38
+
39
+ http://stackoverflow.com/questions/1969240/mapping-a-range-of-values-to-another
40
+ */
41
+ var translate = function(value, start_min, start_max, end_min, end_max) {
42
+ var start_range = start_max - start_min,
43
+ end_range = end_max - end_min,
44
+ scale = (value - start_min) / (start_range);
45
+
46
+ return end_min + scale * end_range;
47
+ };
48
+
49
+ /*
50
+ #get_height(StackView, object) - Private
51
+
52
+ Takes a StackView options object and a book object. Returns a
53
+ normalized book height percentage, taking into account the minimum
54
+ height, maximum height, height multiple, and translating them onto
55
+ the percentage range specified in the stack options.
56
+ */
57
+ var get_height = function(options, book) {
58
+ var height = parseInt(book.measurement_height_numeric, 10),
59
+ min = options.book.min_height,
60
+ max = options.book.max_height;
61
+
62
+ if (isNaN(height)) {
63
+ height = min;
64
+ }
65
+ height = Math.min(Math.max(height, min), max);
66
+ height = translate(
67
+ height,
68
+ options.plain.min_height,
69
+ options.plain.max_height,
70
+ options.plain.min_height_percentage,
71
+ options.plain.max_height_percentage
72
+ );
73
+ return height + '%';
74
+ };
75
+
76
+ /*
77
+ #get_author(object) - Private
78
+
79
+ Takes an item and returns the item's author, taking the first
80
+ author if an array of authors is defined.
81
+ */
82
+ var get_author = function(item) {
83
+ var author = item.creator && item.creator.length ? item.creator[0] : '';
84
+
85
+ if(/^([^,]*)/.test(author)) {
86
+ author = author.match(/^[^,]*/);
87
+ }
88
+
89
+ return author;
90
+ };
91
+
92
+
93
+ window.StackView.register_type({
94
+ name: 'plain',
95
+
96
+ match: function(item) {
97
+ return item.format === 'plain' || item.format.match(/^plain\:/);
98
+ },
99
+
100
+ adapter: function(item, options) {
101
+ return {
102
+ heat: window.StackView.utils.get_heat(item.shelfrank),
103
+ box_height: get_height(options, item),
104
+ link: item.link,
105
+ title: item.title,
106
+ author: get_author(item),
107
+ year: item.pub_date,
108
+ format_descr: item.format.match(/^plain\:/) ? item.format.replace(/^plain\:/, '') : undefined
109
+ };
110
+ },
111
+
112
+ template: '\
113
+ <li class="stack-item stack-plain heat<%= heat %>" style="width:<%= box_height %>">\
114
+ <a href="<%= link %>" target="_blank">\
115
+ <span class="label-container">\
116
+ <span class="spine-text">\
117
+ <p class="plain-title"><%= title %></p>\
118
+ <p class="plain-format"><%= format_descr %></p>\
119
+ <p class="plain-author"><%= author %></p>\
120
+ </span>\
121
+ </span>\
122
+ <span class="spine-year"><%= year %></span>\
123
+ <span class="plain-top item-colors"></span>\
124
+ <span class="plain-edge item-colors"></span>\
125
+ </a>\
126
+ </li>'
127
+ });
128
+ })(jQuery, window);
@@ -0,0 +1,11 @@
1
+ // rails_stackview sprockets JS manifest that includes vendored stackview JS as well as custom JS
2
+ //
3
+ //= require jquery.stackview.js
4
+ //= require ./rails_stackview/plain.js
5
+ //
6
+ // Important to load browser, which adjusts the size of the stackview div,
7
+ // BEFORE auto-init, to make sure the div is the right size when stackview
8
+ // gets init'd, since it will base some things on the size of the div.
9
+ //= require ./rails_stackview/browser.js
10
+ //
11
+ //= require ./rails_stackview/auto_init.js