warclight 0.1.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.
- checksums.yaml +7 -0
- data/.eslintrc +12 -0
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/.rubocop.yml +66 -0
- data/.solr_wrapper +5 -0
- data/.travis.yml +31 -0
- data/CONTRIBUTING.md +53 -0
- data/Gemfile +42 -0
- data/LICENSE.txt +11 -0
- data/README.md +79 -0
- data/Rakefile +16 -0
- data/app/assets/images/blacklight/compact.svg +25 -0
- data/app/assets/images/blacklight/logo.png +0 -0
- data/app/assets/javascripts/warclight/oembed_viewer.js +39 -0
- data/app/assets/javascripts/warclight/warclight.js +4 -0
- data/app/assets/stylesheets/warclight/application.scss +1 -0
- data/app/assets/stylesheets/warclight/warclight.scss +1 -0
- data/app/controllers/concerns/warclight/field_config_helpers.rb +11 -0
- data/app/helpers/warclight/application_helper.rb +8 -0
- data/app/jobs/warclight/application_job.rb +6 -0
- data/app/models/concerns/warclight/catalog.rb +8 -0
- data/app/models/concerns/warclight/search_behavior.rb +9 -0
- data/app/models/concerns/warclight/solr_document.rb +9 -0
- data/app/views/layouts/warclight/application.html.erb +14 -0
- data/bin/rails +14 -0
- data/config/routes.rb +4 -0
- data/lib/generators/warclight/install_generator.rb +55 -0
- data/lib/generators/warclight/templates/catalog_controller.rb +129 -0
- data/lib/generators/warclight/templates/warclight.js +2 -0
- data/lib/generators/warclight/templates/warclight.scss +3 -0
- data/lib/generators/warclight/update_generator.rb +22 -0
- data/lib/warclight.rb +7 -0
- data/lib/warclight/engine.rb +105 -0
- data/lib/warclight/version.rb +5 -0
- data/package.json +24 -0
- data/solr/conf/elevate.xml +42 -0
- data/solr/conf/lang/contractions_ca.txt +8 -0
- data/solr/conf/lang/contractions_fr.txt +15 -0
- data/solr/conf/lang/contractions_ga.txt +5 -0
- data/solr/conf/lang/contractions_it.txt +23 -0
- data/solr/conf/lang/hyphenations_ga.txt +5 -0
- data/solr/conf/lang/stemdict_nl.txt +6 -0
- data/solr/conf/lang/stoptags_ja.txt +420 -0
- data/solr/conf/lang/stopwords_ar.txt +125 -0
- data/solr/conf/lang/stopwords_bg.txt +193 -0
- data/solr/conf/lang/stopwords_ca.txt +220 -0
- data/solr/conf/lang/stopwords_cz.txt +172 -0
- data/solr/conf/lang/stopwords_da.txt +110 -0
- data/solr/conf/lang/stopwords_de.txt +294 -0
- data/solr/conf/lang/stopwords_el.txt +78 -0
- data/solr/conf/lang/stopwords_en.txt +54 -0
- data/solr/conf/lang/stopwords_es.txt +356 -0
- data/solr/conf/lang/stopwords_eu.txt +99 -0
- data/solr/conf/lang/stopwords_fa.txt +313 -0
- data/solr/conf/lang/stopwords_fi.txt +97 -0
- data/solr/conf/lang/stopwords_fr.txt +186 -0
- data/solr/conf/lang/stopwords_ga.txt +110 -0
- data/solr/conf/lang/stopwords_gl.txt +161 -0
- data/solr/conf/lang/stopwords_hi.txt +235 -0
- data/solr/conf/lang/stopwords_hu.txt +211 -0
- data/solr/conf/lang/stopwords_hy.txt +46 -0
- data/solr/conf/lang/stopwords_id.txt +359 -0
- data/solr/conf/lang/stopwords_it.txt +303 -0
- data/solr/conf/lang/stopwords_ja.txt +127 -0
- data/solr/conf/lang/stopwords_lv.txt +172 -0
- data/solr/conf/lang/stopwords_nl.txt +119 -0
- data/solr/conf/lang/stopwords_no.txt +194 -0
- data/solr/conf/lang/stopwords_pt.txt +253 -0
- data/solr/conf/lang/stopwords_ro.txt +233 -0
- data/solr/conf/lang/stopwords_ru.txt +243 -0
- data/solr/conf/lang/stopwords_sv.txt +133 -0
- data/solr/conf/lang/stopwords_th.txt +119 -0
- data/solr/conf/lang/stopwords_tr.txt +212 -0
- data/solr/conf/lang/userdict_ja.txt +29 -0
- data/solr/conf/managed-schema +1045 -0
- data/solr/conf/params.json +20 -0
- data/solr/conf/protwords.txt +21 -0
- data/solr/conf/schema.xml +350 -0
- data/solr/conf/solrconfig.xml +1361 -0
- data/solr/conf/stopwords.txt +14 -0
- data/solr/conf/synonyms.txt +29 -0
- data/tasks/warclight.rake +61 -0
- data/template.rb +15 -0
- data/vendor/assets/javascripts/responsiveTruncator.js +69 -0
- data/vendor/assets/javascripts/stickyfill.js +480 -0
- data/warclight.gemspec +38 -0
- metadata +312 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
2
|
+
# contributor license agreements. See the NOTICE file distributed with
|
|
3
|
+
# this work for additional information regarding copyright ownership.
|
|
4
|
+
# The ASF licenses this file to You under the Apache License, Version 2.0
|
|
5
|
+
# (the "License"); you may not use this file except in compliance with
|
|
6
|
+
# the License. You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# The ASF licenses this file to You under the Apache License, Version 2.0
|
|
2
|
+
# (the "License"); you may not use this file except in compliance with
|
|
3
|
+
# the License. You may obtain a copy of the License at
|
|
4
|
+
#
|
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
6
|
+
#
|
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
10
|
+
# See the License for the specific language governing permissions and
|
|
11
|
+
# limitations under the License.
|
|
12
|
+
|
|
13
|
+
#-----------------------------------------------------------------------
|
|
14
|
+
#some test synonym mappings unlikely to appear in real input text
|
|
15
|
+
aaafoo => aaabar
|
|
16
|
+
bbbfoo => bbbfoo bbbbar
|
|
17
|
+
cccfoo => cccbar cccbaz
|
|
18
|
+
fooaaa,baraaa,bazaaa
|
|
19
|
+
|
|
20
|
+
# Some synonym groups specific to this example
|
|
21
|
+
GB,gib,gigabyte,gigabytes
|
|
22
|
+
MB,mib,megabyte,megabytes
|
|
23
|
+
Television, Televisions, TV, TVs
|
|
24
|
+
#notice we use "gib" instead of "GiB" so any WordDelimiterGraphFilter coming
|
|
25
|
+
#after us won't split it into two words.
|
|
26
|
+
|
|
27
|
+
# Synonym mappings can be used for spelling correction too
|
|
28
|
+
pixima => pixma
|
|
29
|
+
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'solr_wrapper'
|
|
4
|
+
require 'engine_cart/rake_task'
|
|
5
|
+
require 'rspec/core/rake_task'
|
|
6
|
+
require 'warclight'
|
|
7
|
+
|
|
8
|
+
EngineCart.fingerprint_proc = EngineCart.rails_fingerprint_proc
|
|
9
|
+
|
|
10
|
+
desc 'Run test suite'
|
|
11
|
+
task ci: %w[warclight:generate] do
|
|
12
|
+
SolrWrapper.wrap do |solr|
|
|
13
|
+
solr.with_collection do
|
|
14
|
+
Rake::Task['warclight:seed'].invoke
|
|
15
|
+
within_test_app do
|
|
16
|
+
## Do stuff inside warclight app here
|
|
17
|
+
end
|
|
18
|
+
Rake::Task['spec'].invoke
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
desc 'Run Eslint'
|
|
24
|
+
task :eslint do
|
|
25
|
+
system './node_modules/.bin/eslint app/assets/javascripts'
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
namespace :warclight do
|
|
29
|
+
desc 'Generate a test application'
|
|
30
|
+
task generate: %w[engine_cart:generate]
|
|
31
|
+
|
|
32
|
+
desc 'Run Solr and Blacklight for interactive development'
|
|
33
|
+
task :server, %i[rails_server_args] do |_t, args|
|
|
34
|
+
if File.exist? EngineCart.destination
|
|
35
|
+
within_test_app do
|
|
36
|
+
system 'bundle update'
|
|
37
|
+
end
|
|
38
|
+
else
|
|
39
|
+
Rake::Task['engine_cart:generate'].invoke
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
print 'Starting Solr...'
|
|
43
|
+
SolrWrapper.wrap do |solr|
|
|
44
|
+
puts 'done.'
|
|
45
|
+
solr.with_collection do
|
|
46
|
+
Rake::Task['warclight:seed'].invoke
|
|
47
|
+
within_test_app do
|
|
48
|
+
system "bundle exec rails s #{args[:rails_server_args]}"
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
desc 'Seed fixture data to Solr'
|
|
55
|
+
task :seed do
|
|
56
|
+
puts 'Seeding index with data from spec/fixtures/warcs/...'
|
|
57
|
+
# rubocop:disable Metrics/LineLength
|
|
58
|
+
system('curl -o ".internal_test_app/tmp/warc-indexer.jar" "http://alpha.library.yorku.ca/warc-indexer-3.0.0-SNAPSHOT-jar-with-dependencies.jar"')
|
|
59
|
+
system('java -Djava.io.tmpdir=.internal_test_app/tmp -jar .internal_test_app/tmp/warc-indexer.jar -i "York University Libraries" -n "Test Collection" -u "12345" -s http://localhost:8983/solr/blacklight-core spec/fixtures/warcs/*.gz')
|
|
60
|
+
end
|
|
61
|
+
end
|
data/template.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# We can remove `blacklight` and `blacklight_range_limit` once they are released
|
|
4
|
+
# since they are already dependents of Arclight (but we need to pin to particular branches)
|
|
5
|
+
gem 'blacklight', github: 'projectblacklight/blacklight'
|
|
6
|
+
gem 'blacklight_range_limit', github: 'projectblacklight/blacklight_range_limit', branch: 'blacklight-7'
|
|
7
|
+
|
|
8
|
+
gem 'warclight', github: 'archivesunleashed/warclight'
|
|
9
|
+
|
|
10
|
+
run 'bundle install'
|
|
11
|
+
|
|
12
|
+
generate 'blacklight:install', '--devise'
|
|
13
|
+
generate 'warclight:install', '-f'
|
|
14
|
+
|
|
15
|
+
rake 'db:migrate'
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* jQuery Responsive Truncator Plugin
|
|
3
|
+
*
|
|
4
|
+
* https://github.com/jkeck/responsiveTruncator
|
|
5
|
+
*
|
|
6
|
+
* VERSION 0.0.2
|
|
7
|
+
*
|
|
8
|
+
**/
|
|
9
|
+
(function( $ ){
|
|
10
|
+
$.fn.responsiveTruncate = function(options){
|
|
11
|
+
var $this = this;
|
|
12
|
+
$(window).bind("resize", function(){
|
|
13
|
+
removeTruncation($this);
|
|
14
|
+
addTruncation($this);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
addTruncation($this);
|
|
18
|
+
|
|
19
|
+
function addTruncation(el){
|
|
20
|
+
el.each(function(){
|
|
21
|
+
if($(".responsiveTruncate", $(this)).length == 0){
|
|
22
|
+
var parent = $(this);
|
|
23
|
+
var fontSize = $(this).css('font-size');
|
|
24
|
+
var lineHeight = $(this).css("line-height") ? $(this).css("line-height").replace('px','') : Math.floor(parseInt(fontSize.replace('px','')) * 1.5);
|
|
25
|
+
var total_lines = Math.ceil(parent.height() / lineHeight);
|
|
26
|
+
var settings = $.extend({
|
|
27
|
+
'lines' : 3,
|
|
28
|
+
'height' : null,
|
|
29
|
+
'more' : 'more',
|
|
30
|
+
'less' : 'less'
|
|
31
|
+
}, options);
|
|
32
|
+
var truncate_height;
|
|
33
|
+
if(settings.height){
|
|
34
|
+
truncate_height = settings.height;
|
|
35
|
+
}else{
|
|
36
|
+
truncate_height = (lineHeight * settings.lines);
|
|
37
|
+
}
|
|
38
|
+
if(parent.height() > truncate_height) {
|
|
39
|
+
var orig_content = parent.html();
|
|
40
|
+
parent.html("<div style='height: " + truncate_height + "px; overflow: hidden;' class='responsiveTruncate'></div>");
|
|
41
|
+
var truncate = $(".responsiveTruncate", parent);
|
|
42
|
+
truncate.html(orig_content);
|
|
43
|
+
truncate.after("<a class='responsiveTruncatorToggle' href='#'>" + settings.more + "</a>");
|
|
44
|
+
var toggle_link = $(".responsiveTruncatorToggle", parent);
|
|
45
|
+
toggle_link.click(function(){
|
|
46
|
+
var text = toggle_link.text() == settings.more ? settings.less : settings.more;
|
|
47
|
+
toggle_link.text(text);
|
|
48
|
+
if(truncate.height() == truncate_height){
|
|
49
|
+
truncate.css({height: '100%'})
|
|
50
|
+
}else{
|
|
51
|
+
truncate.css({height: truncate_height})
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function removeTruncation(el){
|
|
61
|
+
el.each(function(){
|
|
62
|
+
if($(".responsiveTruncate", $(this)).length > 0){
|
|
63
|
+
$(this).html($(".responsiveTruncate", $(this)).html());
|
|
64
|
+
$(".responsiveTruncatorToggle", $(this)).remove();
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
})( jQuery );
|
|
@@ -0,0 +1,480 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Stickyfill -- `position: sticky` polyfill
|
|
3
|
+
* v. 1.1.4 | https://github.com/wilddeer/stickyfill
|
|
4
|
+
* Copyright Oleg Korsunsky | http://wd.dizaina.net/
|
|
5
|
+
*
|
|
6
|
+
* MIT License
|
|
7
|
+
*/
|
|
8
|
+
(function(doc, win) {
|
|
9
|
+
var watchArray = [],
|
|
10
|
+
scroll,
|
|
11
|
+
initialized = false,
|
|
12
|
+
html = doc.documentElement,
|
|
13
|
+
noop = function() {},
|
|
14
|
+
checkTimer,
|
|
15
|
+
|
|
16
|
+
//visibility API strings
|
|
17
|
+
hiddenPropertyName = 'hidden',
|
|
18
|
+
visibilityChangeEventName = 'visibilitychange';
|
|
19
|
+
|
|
20
|
+
//fallback to prefixed names in old webkit browsers
|
|
21
|
+
if (doc.webkitHidden !== undefined) {
|
|
22
|
+
hiddenPropertyName = 'webkitHidden';
|
|
23
|
+
visibilityChangeEventName = 'webkitvisibilitychange';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
//test getComputedStyle
|
|
27
|
+
if (!win.getComputedStyle) {
|
|
28
|
+
seppuku();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//test for native support
|
|
32
|
+
var prefixes = ['', '-webkit-', '-moz-', '-ms-'],
|
|
33
|
+
block = document.createElement('div');
|
|
34
|
+
|
|
35
|
+
for (var i = prefixes.length - 1; i >= 0; i--) {
|
|
36
|
+
try {
|
|
37
|
+
block.style.position = prefixes[i] + 'sticky';
|
|
38
|
+
}
|
|
39
|
+
catch(e) {}
|
|
40
|
+
if (block.style.position != '') {
|
|
41
|
+
seppuku();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
updateScrollPos();
|
|
46
|
+
|
|
47
|
+
//commit seppuku!
|
|
48
|
+
function seppuku() {
|
|
49
|
+
init = add = rebuild = pause = stop = kill = noop;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function mergeObjects(targetObj, sourceObject) {
|
|
53
|
+
for (var key in sourceObject) {
|
|
54
|
+
if (sourceObject.hasOwnProperty(key)) {
|
|
55
|
+
targetObj[key] = sourceObject[key];
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function parseNumeric(val) {
|
|
61
|
+
return parseFloat(val) || 0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function updateScrollPos() {
|
|
65
|
+
scroll = {
|
|
66
|
+
top: win.pageYOffset,
|
|
67
|
+
left: win.pageXOffset
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function onScroll() {
|
|
72
|
+
if (win.pageXOffset != scroll.left) {
|
|
73
|
+
updateScrollPos();
|
|
74
|
+
rebuild();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (win.pageYOffset != scroll.top) {
|
|
79
|
+
updateScrollPos();
|
|
80
|
+
recalcAllPos();
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
//fixes flickering
|
|
85
|
+
function onWheel(event) {
|
|
86
|
+
setTimeout(function() {
|
|
87
|
+
if (win.pageYOffset != scroll.top) {
|
|
88
|
+
scroll.top = win.pageYOffset;
|
|
89
|
+
recalcAllPos();
|
|
90
|
+
}
|
|
91
|
+
}, 0);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function recalcAllPos() {
|
|
95
|
+
for (var i = watchArray.length - 1; i >= 0; i--) {
|
|
96
|
+
recalcElementPos(watchArray[i]);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function recalcElementPos(el) {
|
|
101
|
+
if (!el.inited) return;
|
|
102
|
+
|
|
103
|
+
var currentMode = (scroll.top <= el.limit.start? 0: scroll.top >= el.limit.end? 2: 1);
|
|
104
|
+
|
|
105
|
+
if (el.mode != currentMode) {
|
|
106
|
+
switchElementMode(el, currentMode);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
//checks whether stickies start or stop positions have changed
|
|
111
|
+
function fastCheck() {
|
|
112
|
+
for (var i = watchArray.length - 1; i >= 0; i--) {
|
|
113
|
+
if (!watchArray[i].inited) continue;
|
|
114
|
+
|
|
115
|
+
var deltaTop = Math.abs(getDocOffsetTop(watchArray[i].clone) - watchArray[i].docOffsetTop),
|
|
116
|
+
deltaHeight = Math.abs(watchArray[i].parent.node.offsetHeight - watchArray[i].parent.height);
|
|
117
|
+
|
|
118
|
+
if (deltaTop >= 2 || deltaHeight >= 2) return false;
|
|
119
|
+
}
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function initElement(el) {
|
|
124
|
+
if (isNaN(parseFloat(el.computed.top)) || el.isCell || el.computed.display == 'none') return;
|
|
125
|
+
|
|
126
|
+
el.inited = true;
|
|
127
|
+
|
|
128
|
+
if (!el.clone) clone(el);
|
|
129
|
+
if (el.parent.computed.position != 'absolute' &&
|
|
130
|
+
el.parent.computed.position != 'relative') el.parent.node.style.position = 'relative';
|
|
131
|
+
|
|
132
|
+
recalcElementPos(el);
|
|
133
|
+
|
|
134
|
+
el.parent.height = el.parent.node.offsetHeight;
|
|
135
|
+
el.docOffsetTop = getDocOffsetTop(el.clone);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function deinitElement(el) {
|
|
139
|
+
var deinitParent = true;
|
|
140
|
+
|
|
141
|
+
el.clone && killClone(el);
|
|
142
|
+
mergeObjects(el.node.style, el.css);
|
|
143
|
+
|
|
144
|
+
//check whether element's parent is used by other stickies
|
|
145
|
+
for (var i = watchArray.length - 1; i >= 0; i--) {
|
|
146
|
+
if (watchArray[i].node !== el.node && watchArray[i].parent.node === el.parent.node) {
|
|
147
|
+
deinitParent = false;
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
if (deinitParent) el.parent.node.style.position = el.parent.css.position;
|
|
153
|
+
el.mode = -1;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function initAll() {
|
|
157
|
+
for (var i = watchArray.length - 1; i >= 0; i--) {
|
|
158
|
+
initElement(watchArray[i]);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function deinitAll() {
|
|
163
|
+
for (var i = watchArray.length - 1; i >= 0; i--) {
|
|
164
|
+
deinitElement(watchArray[i]);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function switchElementMode(el, mode) {
|
|
169
|
+
var nodeStyle = el.node.style;
|
|
170
|
+
|
|
171
|
+
switch (mode) {
|
|
172
|
+
case 0:
|
|
173
|
+
nodeStyle.position = 'absolute';
|
|
174
|
+
nodeStyle.left = el.offset.left + 'px';
|
|
175
|
+
nodeStyle.right = el.offset.right + 'px';
|
|
176
|
+
nodeStyle.top = el.offset.top + 'px';
|
|
177
|
+
nodeStyle.bottom = 'auto';
|
|
178
|
+
nodeStyle.width = 'auto';
|
|
179
|
+
nodeStyle.marginLeft = 0;
|
|
180
|
+
nodeStyle.marginRight = 0;
|
|
181
|
+
nodeStyle.marginTop = 0;
|
|
182
|
+
break;
|
|
183
|
+
|
|
184
|
+
case 1:
|
|
185
|
+
nodeStyle.position = 'fixed';
|
|
186
|
+
nodeStyle.left = el.box.left + 'px';
|
|
187
|
+
nodeStyle.right = el.box.right + 'px';
|
|
188
|
+
nodeStyle.top = el.css.top;
|
|
189
|
+
nodeStyle.bottom = 'auto';
|
|
190
|
+
nodeStyle.width = 'auto';
|
|
191
|
+
nodeStyle.marginLeft = 0;
|
|
192
|
+
nodeStyle.marginRight = 0;
|
|
193
|
+
nodeStyle.marginTop = 0;
|
|
194
|
+
break;
|
|
195
|
+
|
|
196
|
+
case 2:
|
|
197
|
+
nodeStyle.position = 'absolute';
|
|
198
|
+
nodeStyle.left = el.offset.left + 'px';
|
|
199
|
+
nodeStyle.right = el.offset.right + 'px';
|
|
200
|
+
nodeStyle.top = 'auto';
|
|
201
|
+
nodeStyle.bottom = 0;
|
|
202
|
+
nodeStyle.width = 'auto';
|
|
203
|
+
nodeStyle.marginLeft = 0;
|
|
204
|
+
nodeStyle.marginRight = 0;
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
el.mode = mode;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function clone(el) {
|
|
212
|
+
el.clone = document.createElement('div');
|
|
213
|
+
|
|
214
|
+
var refElement = el.node.nextSibling || el.node,
|
|
215
|
+
cloneStyle = el.clone.style;
|
|
216
|
+
|
|
217
|
+
cloneStyle.height = el.height + 'px';
|
|
218
|
+
cloneStyle.width = el.width + 'px';
|
|
219
|
+
cloneStyle.marginTop = el.computed.marginTop;
|
|
220
|
+
cloneStyle.marginBottom = el.computed.marginBottom;
|
|
221
|
+
cloneStyle.marginLeft = el.computed.marginLeft;
|
|
222
|
+
cloneStyle.marginRight = el.computed.marginRight;
|
|
223
|
+
cloneStyle.padding = cloneStyle.border = cloneStyle.borderSpacing = 0;
|
|
224
|
+
cloneStyle.fontSize = '1em';
|
|
225
|
+
cloneStyle.position = 'static';
|
|
226
|
+
cloneStyle.cssFloat = el.computed.cssFloat;
|
|
227
|
+
|
|
228
|
+
el.node.parentNode.insertBefore(el.clone, refElement);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function killClone(el) {
|
|
232
|
+
el.clone.parentNode.removeChild(el.clone);
|
|
233
|
+
el.clone = undefined;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function getElementParams(node) {
|
|
237
|
+
var computedStyle = getComputedStyle(node),
|
|
238
|
+
parentNode = node.parentNode,
|
|
239
|
+
parentComputedStyle = getComputedStyle(parentNode),
|
|
240
|
+
cachedPosition = node.style.position;
|
|
241
|
+
|
|
242
|
+
node.style.position = 'relative';
|
|
243
|
+
|
|
244
|
+
var computed = {
|
|
245
|
+
top: computedStyle.top,
|
|
246
|
+
marginTop: computedStyle.marginTop,
|
|
247
|
+
marginBottom: computedStyle.marginBottom,
|
|
248
|
+
marginLeft: computedStyle.marginLeft,
|
|
249
|
+
marginRight: computedStyle.marginRight,
|
|
250
|
+
cssFloat: computedStyle.cssFloat,
|
|
251
|
+
display: computedStyle.display
|
|
252
|
+
},
|
|
253
|
+
numeric = {
|
|
254
|
+
top: parseNumeric(computedStyle.top),
|
|
255
|
+
marginBottom: parseNumeric(computedStyle.marginBottom),
|
|
256
|
+
paddingLeft: parseNumeric(computedStyle.paddingLeft),
|
|
257
|
+
paddingRight: parseNumeric(computedStyle.paddingRight),
|
|
258
|
+
borderLeftWidth: parseNumeric(computedStyle.borderLeftWidth),
|
|
259
|
+
borderRightWidth: parseNumeric(computedStyle.borderRightWidth)
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
node.style.position = cachedPosition;
|
|
263
|
+
|
|
264
|
+
var css = {
|
|
265
|
+
position: node.style.position,
|
|
266
|
+
top: node.style.top,
|
|
267
|
+
bottom: node.style.bottom,
|
|
268
|
+
left: node.style.left,
|
|
269
|
+
right: node.style.right,
|
|
270
|
+
width: node.style.width,
|
|
271
|
+
marginTop: node.style.marginTop,
|
|
272
|
+
marginLeft: node.style.marginLeft,
|
|
273
|
+
marginRight: node.style.marginRight
|
|
274
|
+
},
|
|
275
|
+
nodeOffset = getElementOffset(node),
|
|
276
|
+
parentOffset = getElementOffset(parentNode),
|
|
277
|
+
|
|
278
|
+
parent = {
|
|
279
|
+
node: parentNode,
|
|
280
|
+
css: {
|
|
281
|
+
position: parentNode.style.position
|
|
282
|
+
},
|
|
283
|
+
computed: {
|
|
284
|
+
position: parentComputedStyle.position
|
|
285
|
+
},
|
|
286
|
+
numeric: {
|
|
287
|
+
borderLeftWidth: parseNumeric(parentComputedStyle.borderLeftWidth),
|
|
288
|
+
borderRightWidth: parseNumeric(parentComputedStyle.borderRightWidth),
|
|
289
|
+
borderTopWidth: parseNumeric(parentComputedStyle.borderTopWidth),
|
|
290
|
+
borderBottomWidth: parseNumeric(parentComputedStyle.borderBottomWidth)
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
|
|
294
|
+
el = {
|
|
295
|
+
node: node,
|
|
296
|
+
box: {
|
|
297
|
+
left: nodeOffset.win.left,
|
|
298
|
+
right: html.clientWidth - nodeOffset.win.right
|
|
299
|
+
},
|
|
300
|
+
offset: {
|
|
301
|
+
top: nodeOffset.win.top - parentOffset.win.top - parent.numeric.borderTopWidth,
|
|
302
|
+
left: nodeOffset.win.left - parentOffset.win.left - parent.numeric.borderLeftWidth,
|
|
303
|
+
right: -nodeOffset.win.right + parentOffset.win.right - parent.numeric.borderRightWidth
|
|
304
|
+
},
|
|
305
|
+
css: css,
|
|
306
|
+
isCell: computedStyle.display == 'table-cell',
|
|
307
|
+
computed: computed,
|
|
308
|
+
numeric: numeric,
|
|
309
|
+
width: nodeOffset.win.right - nodeOffset.win.left,
|
|
310
|
+
height: nodeOffset.win.bottom - nodeOffset.win.top,
|
|
311
|
+
mode: -1,
|
|
312
|
+
inited: false,
|
|
313
|
+
parent: parent,
|
|
314
|
+
limit: {
|
|
315
|
+
start: nodeOffset.doc.top - numeric.top,
|
|
316
|
+
end: parentOffset.doc.top + parentNode.offsetHeight - parent.numeric.borderBottomWidth -
|
|
317
|
+
node.offsetHeight - numeric.top - numeric.marginBottom
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
return el;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function getDocOffsetTop(node) {
|
|
325
|
+
var docOffsetTop = 0;
|
|
326
|
+
|
|
327
|
+
while (node) {
|
|
328
|
+
docOffsetTop += node.offsetTop;
|
|
329
|
+
node = node.offsetParent;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
return docOffsetTop;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function getElementOffset(node) {
|
|
336
|
+
var box = node.getBoundingClientRect();
|
|
337
|
+
|
|
338
|
+
return {
|
|
339
|
+
doc: {
|
|
340
|
+
top: box.top + win.pageYOffset,
|
|
341
|
+
left: box.left + win.pageXOffset
|
|
342
|
+
},
|
|
343
|
+
win: box
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
function startFastCheckTimer() {
|
|
348
|
+
checkTimer = setInterval(function() {
|
|
349
|
+
!fastCheck() && rebuild();
|
|
350
|
+
}, 500);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function stopFastCheckTimer() {
|
|
354
|
+
clearInterval(checkTimer);
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function handlePageVisibilityChange() {
|
|
358
|
+
if (!initialized) return;
|
|
359
|
+
|
|
360
|
+
if (document[hiddenPropertyName]) {
|
|
361
|
+
stopFastCheckTimer();
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
startFastCheckTimer();
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function init() {
|
|
369
|
+
if (initialized) return;
|
|
370
|
+
|
|
371
|
+
updateScrollPos();
|
|
372
|
+
initAll();
|
|
373
|
+
|
|
374
|
+
win.addEventListener('scroll', onScroll);
|
|
375
|
+
win.addEventListener('wheel', onWheel);
|
|
376
|
+
|
|
377
|
+
//watch for width changes
|
|
378
|
+
win.addEventListener('resize', rebuild);
|
|
379
|
+
win.addEventListener('orientationchange', rebuild);
|
|
380
|
+
|
|
381
|
+
//watch for page visibility
|
|
382
|
+
doc.addEventListener(visibilityChangeEventName, handlePageVisibilityChange);
|
|
383
|
+
|
|
384
|
+
startFastCheckTimer();
|
|
385
|
+
|
|
386
|
+
initialized = true;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
function rebuild() {
|
|
390
|
+
if (!initialized) return;
|
|
391
|
+
|
|
392
|
+
deinitAll();
|
|
393
|
+
|
|
394
|
+
for (var i = watchArray.length - 1; i >= 0; i--) {
|
|
395
|
+
watchArray[i] = getElementParams(watchArray[i].node);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
initAll();
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function pause() {
|
|
402
|
+
win.removeEventListener('scroll', onScroll);
|
|
403
|
+
win.removeEventListener('wheel', onWheel);
|
|
404
|
+
win.removeEventListener('resize', rebuild);
|
|
405
|
+
win.removeEventListener('orientationchange', rebuild);
|
|
406
|
+
doc.removeEventListener(visibilityChangeEventName, handlePageVisibilityChange);
|
|
407
|
+
|
|
408
|
+
stopFastCheckTimer();
|
|
409
|
+
|
|
410
|
+
initialized = false;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function stop() {
|
|
414
|
+
pause();
|
|
415
|
+
deinitAll();
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
function kill() {
|
|
419
|
+
stop();
|
|
420
|
+
|
|
421
|
+
//empty the array without loosing the references,
|
|
422
|
+
//the most performant method according to http://jsperf.com/empty-javascript-array
|
|
423
|
+
while (watchArray.length) {
|
|
424
|
+
watchArray.pop();
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
function add(node) {
|
|
429
|
+
//check if Stickyfill is already applied to the node
|
|
430
|
+
for (var i = watchArray.length - 1; i >= 0; i--) {
|
|
431
|
+
if (watchArray[i].node === node) return;
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
var el = getElementParams(node);
|
|
435
|
+
|
|
436
|
+
watchArray.push(el);
|
|
437
|
+
|
|
438
|
+
if (!initialized) {
|
|
439
|
+
init();
|
|
440
|
+
}
|
|
441
|
+
else {
|
|
442
|
+
initElement(el);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
function remove(node) {
|
|
447
|
+
for (var i = watchArray.length - 1; i >= 0; i--) {
|
|
448
|
+
if (watchArray[i].node === node) {
|
|
449
|
+
deinitElement(watchArray[i]);
|
|
450
|
+
watchArray.splice(i, 1);
|
|
451
|
+
}
|
|
452
|
+
};
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
//expose Stickyfill
|
|
456
|
+
win.Stickyfill = {
|
|
457
|
+
stickies: watchArray,
|
|
458
|
+
add: add,
|
|
459
|
+
remove: remove,
|
|
460
|
+
init: init,
|
|
461
|
+
rebuild: rebuild,
|
|
462
|
+
pause: pause,
|
|
463
|
+
stop: stop,
|
|
464
|
+
kill: kill
|
|
465
|
+
};
|
|
466
|
+
})(document, window);
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
//if jQuery is available -- create a plugin
|
|
470
|
+
if (window.jQuery) {
|
|
471
|
+
(function($) {
|
|
472
|
+
$.fn.Stickyfill = function(options) {
|
|
473
|
+
this.each(function() {
|
|
474
|
+
Stickyfill.add(this);
|
|
475
|
+
});
|
|
476
|
+
|
|
477
|
+
return this;
|
|
478
|
+
};
|
|
479
|
+
})(window.jQuery);
|
|
480
|
+
}
|