sitediff 1.0.0 → 1.1.1
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 +4 -4
- data/lib/sitediff.rb +3 -1
- data/lib/sitediff/api.rb +265 -0
- data/lib/sitediff/cache.rb +18 -0
- data/lib/sitediff/cli.rb +58 -214
- data/lib/sitediff/config.rb +78 -6
- data/lib/sitediff/config/creator.rb +8 -6
- data/lib/sitediff/crawler.rb +9 -9
- data/lib/sitediff/diff.rb +5 -1
- data/lib/sitediff/files/report.html.erb +35 -8
- data/lib/sitediff/files/sitediff.css +78 -1
- data/lib/sitediff/files/sitediff.js +204 -13
- data/lib/sitediff/report.rb +17 -1
- data/lib/sitediff/result.rb +2 -0
- data/lib/sitediff/sanitize.rb +49 -1
- data/lib/sitediff/uriwrapper.rb +4 -1
- metadata +7 -6
data/lib/sitediff/config.rb
CHANGED
@@ -20,8 +20,8 @@ class SiteDiff
|
|
20
20
|
'settings' => {
|
21
21
|
'depth' => 3,
|
22
22
|
'interval' => 0,
|
23
|
-
'
|
24
|
-
'
|
23
|
+
'include' => '',
|
24
|
+
'exclude' => '',
|
25
25
|
'concurrency' => 3,
|
26
26
|
'preset' => nil
|
27
27
|
},
|
@@ -43,6 +43,8 @@ class SiteDiff
|
|
43
43
|
after_url
|
44
44
|
ignore_whitespace
|
45
45
|
export
|
46
|
+
output
|
47
|
+
report
|
46
48
|
]
|
47
49
|
|
48
50
|
##
|
@@ -52,8 +54,8 @@ class SiteDiff
|
|
52
54
|
ALLOWED_SETTINGS_KEYS = %w[
|
53
55
|
preset
|
54
56
|
depth
|
55
|
-
|
56
|
-
|
57
|
+
include
|
58
|
+
exclude
|
57
59
|
concurrency
|
58
60
|
interval
|
59
61
|
curl_opts
|
@@ -62,6 +64,8 @@ class SiteDiff
|
|
62
64
|
class InvalidConfig < SiteDiffException; end
|
63
65
|
class ConfigNotFound < SiteDiffException; end
|
64
66
|
|
67
|
+
attr_reader :directory
|
68
|
+
|
65
69
|
# Takes a Hash and normalizes it to the following form by merging globals
|
66
70
|
# into before and after. A normalized config Hash looks like this:
|
67
71
|
#
|
@@ -71,6 +75,12 @@ class SiteDiff
|
|
71
75
|
# before:
|
72
76
|
# url: http://before
|
73
77
|
# selector: body
|
78
|
+
# ## Note: use either `selector` or `regions`, but not both
|
79
|
+
# regions:
|
80
|
+
# - name: title
|
81
|
+
# selector: .field-name-title h2
|
82
|
+
# - name: body
|
83
|
+
# selector: .field-name-field-news-description .field-item
|
74
84
|
# dom_transform:
|
75
85
|
# - type: remove
|
76
86
|
# selector: script
|
@@ -79,6 +89,13 @@ class SiteDiff
|
|
79
89
|
# url: http://after
|
80
90
|
# selector: body
|
81
91
|
#
|
92
|
+
# ## Note: use `output` only with `regions`
|
93
|
+
# output:
|
94
|
+
# - title
|
95
|
+
# - author
|
96
|
+
# - source
|
97
|
+
# - body
|
98
|
+
#
|
82
99
|
def self.normalize(conf)
|
83
100
|
tools = Sanitizer::TOOLS
|
84
101
|
|
@@ -117,6 +134,7 @@ class SiteDiff
|
|
117
134
|
result = {
|
118
135
|
'before' => {},
|
119
136
|
'after' => {},
|
137
|
+
'output' => [],
|
120
138
|
'settings' => {}
|
121
139
|
}
|
122
140
|
|
@@ -149,12 +167,26 @@ class SiteDiff
|
|
149
167
|
end
|
150
168
|
end
|
151
169
|
|
170
|
+
# Merge output array.
|
171
|
+
result['output'] += (first['output'] || []) + (second['output'] || [])
|
172
|
+
|
173
|
+
# Merge url_report keys.
|
174
|
+
%w[before_url_report after_url_report].each do |pos|
|
175
|
+
result[pos] = first[pos] || second[pos]
|
176
|
+
end
|
177
|
+
|
152
178
|
# Merge settings.
|
153
179
|
result['settings'] = merge_deep(
|
154
180
|
first['settings'] || {},
|
155
181
|
second['settings'] || {}
|
156
182
|
)
|
157
183
|
|
184
|
+
# Merge report labels.
|
185
|
+
result['report'] = merge_deep(
|
186
|
+
first['report'] || {},
|
187
|
+
second['report'] || {}
|
188
|
+
)
|
189
|
+
|
158
190
|
result
|
159
191
|
end
|
160
192
|
|
@@ -162,9 +194,10 @@ class SiteDiff
|
|
162
194
|
# Merges 2 iterable objects deeply.
|
163
195
|
def self.merge_deep(first, second)
|
164
196
|
first.merge(second) do |_key, val1, val2|
|
165
|
-
|
197
|
+
case val1.class
|
198
|
+
when Hash
|
166
199
|
self.class.merge_deep(val1, val2 || {})
|
167
|
-
|
200
|
+
when Array
|
168
201
|
val1 + (val2 || [])
|
169
202
|
else
|
170
203
|
val2
|
@@ -280,6 +313,33 @@ class SiteDiff
|
|
280
313
|
@config['export'] = export
|
281
314
|
end
|
282
315
|
|
316
|
+
# Get output option
|
317
|
+
def output
|
318
|
+
@config['output']
|
319
|
+
end
|
320
|
+
|
321
|
+
# Set output option
|
322
|
+
def output=(output)
|
323
|
+
raise 'Output must be an Array' unless output.is_a? Array
|
324
|
+
|
325
|
+
@config['output'] = output
|
326
|
+
end
|
327
|
+
|
328
|
+
# Return report display settings.
|
329
|
+
def report
|
330
|
+
@config['report']
|
331
|
+
end
|
332
|
+
|
333
|
+
# Set crawl time for 'before'
|
334
|
+
def before_time=(time)
|
335
|
+
@config['report']['before_time'] = time
|
336
|
+
end
|
337
|
+
|
338
|
+
# Set crawl time for 'after'
|
339
|
+
def after_time=(time)
|
340
|
+
@config['report']['after_time'] = time
|
341
|
+
end
|
342
|
+
|
283
343
|
##
|
284
344
|
# Writes an array of paths to a file.
|
285
345
|
#
|
@@ -407,6 +467,18 @@ class SiteDiff
|
|
407
467
|
@return_value
|
408
468
|
end
|
409
469
|
|
470
|
+
##
|
471
|
+
# Return merged CURL options.
|
472
|
+
def curl_opts
|
473
|
+
# We do want string keys here
|
474
|
+
bool_hash = { 'true' => true, 'false' => false }
|
475
|
+
curl_opts = UriWrapper::DEFAULT_CURL_OPTS
|
476
|
+
.clone
|
477
|
+
.merge(settings['curl_opts'] || {})
|
478
|
+
curl_opts.each { |k, v| curl_opts[k] = bool_hash.fetch(v, v) }
|
479
|
+
curl_opts
|
480
|
+
end
|
481
|
+
|
410
482
|
private
|
411
483
|
|
412
484
|
##
|
@@ -14,10 +14,10 @@ class SiteDiff
|
|
14
14
|
class Creator
|
15
15
|
##
|
16
16
|
# Creates a Creator object.
|
17
|
-
def initialize(debug,
|
17
|
+
def initialize(debug, before, after)
|
18
18
|
@config = nil
|
19
|
-
@
|
20
|
-
@
|
19
|
+
@before = before
|
20
|
+
@after = after
|
21
21
|
@debug = debug
|
22
22
|
end
|
23
23
|
|
@@ -25,15 +25,17 @@ class SiteDiff
|
|
25
25
|
# Determine if we're dealing with one or two URLs.
|
26
26
|
def roots
|
27
27
|
@roots = { 'after' => @after }
|
28
|
-
@roots['before'] = @before
|
28
|
+
@roots['before'] = @before || @after
|
29
29
|
@roots
|
30
30
|
end
|
31
31
|
|
32
32
|
##
|
33
33
|
# Build a config structure, return it.
|
34
|
-
def create(options
|
34
|
+
def create(options)
|
35
35
|
@config = {}
|
36
|
-
|
36
|
+
|
37
|
+
# @callback = block
|
38
|
+
|
37
39
|
@dir = Pathname.new(options[:directory])
|
38
40
|
|
39
41
|
# Setup instance vars
|
data/lib/sitediff/crawler.rb
CHANGED
@@ -17,8 +17,8 @@ class SiteDiff
|
|
17
17
|
# Create a crawler with a base URL
|
18
18
|
def initialize(hydra, base,
|
19
19
|
interval,
|
20
|
-
|
21
|
-
|
20
|
+
include_regex,
|
21
|
+
exclude_regex,
|
22
22
|
depth = DEFAULT_DEPTH,
|
23
23
|
curl_opts = UriWrapper::DEFAULT_CURL_OPTS,
|
24
24
|
debug = true,
|
@@ -27,8 +27,8 @@ class SiteDiff
|
|
27
27
|
@base_uri = Addressable::URI.parse(base)
|
28
28
|
@base = base
|
29
29
|
@interval = interval
|
30
|
-
@
|
31
|
-
@
|
30
|
+
@include_regex = include_regex
|
31
|
+
@exclude_regex = exclude_regex
|
32
32
|
@found = Set.new
|
33
33
|
@callback = block
|
34
34
|
@curl_opts = curl_opts
|
@@ -119,12 +119,12 @@ class SiteDiff
|
|
119
119
|
u.path.start_with?(@base_uri.path)
|
120
120
|
next unless is_sub_uri
|
121
121
|
|
122
|
-
|
123
|
-
|
124
|
-
if
|
125
|
-
SiteDiff.log "Ignoring
|
122
|
+
is_included = @include_regex.nil? ? false : @include_regex.match(u.path)
|
123
|
+
is_excluded = @exclude_regex.nil? ? false : @exclude_regex.match(u.path)
|
124
|
+
if is_excluded && !is_included
|
125
|
+
SiteDiff.log "Ignoring excluded URL #{u.path}", :info
|
126
126
|
end
|
127
|
-
|
127
|
+
is_included || !is_excluded
|
128
128
|
end
|
129
129
|
end
|
130
130
|
end
|
data/lib/sitediff/diff.rb
CHANGED
@@ -57,7 +57,11 @@ class SiteDiff
|
|
57
57
|
##
|
58
58
|
# Generates an HTML report.
|
59
59
|
# TODO: Generate the report in SiteDif::Report instead.
|
60
|
-
def generate_html(results, before, after, cache,
|
60
|
+
def generate_html(results, before, after, cache, config)
|
61
|
+
relative = config.export
|
62
|
+
report = config.report || {}
|
63
|
+
before_url_report = report['before_url_report']
|
64
|
+
after_url_report = report['after_url_report']
|
61
65
|
erb_path = File.join(SiteDiff::FILES_DIR, 'report.html.erb')
|
62
66
|
ERB.new(File.read(erb_path)).result(binding)
|
63
67
|
end
|
@@ -23,6 +23,12 @@
|
|
23
23
|
</head>
|
24
24
|
<body class="page-overview" data-page="overview">
|
25
25
|
<div id="layout">
|
26
|
+
<div class="container">
|
27
|
+
<div class="heading">
|
28
|
+
<h1><%= report["title"] %></h1>
|
29
|
+
<p><%= report["details"] %></p>
|
30
|
+
</div>
|
31
|
+
</div>
|
26
32
|
<div class="container">
|
27
33
|
<div class="statistical-info">
|
28
34
|
<div class="changed-pages">
|
@@ -48,11 +54,26 @@
|
|
48
54
|
<div class="site site-<%= tag %>">
|
49
55
|
<% notes = ['base url']
|
50
56
|
notes << 'cached' if cache.read_tags.include?(tag.to_sym) %>
|
51
|
-
<
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
57
|
+
<div>
|
58
|
+
<h3 class="site__tag"><%= tag.capitalize %></h3>
|
59
|
+
</div>
|
60
|
+
<div>
|
61
|
+
<% if display_url = report[tag + '_url_report'] %>
|
62
|
+
<a href="<%= display_url %>" class="site__url"><%= display_url %></a>
|
63
|
+
<% else %>
|
64
|
+
<a href="<%= eval(tag) %>" class="site__url"><%= eval(tag) %></a>
|
65
|
+
<% if cache.read_tags.include?(tag.to_sym) %>
|
66
|
+
(<%= 'cached' if cache.read_tags.include?(tag.to_sym) %>)
|
67
|
+
<% end %>
|
68
|
+
<% end %>
|
69
|
+
</div>
|
70
|
+
<div>
|
71
|
+
Crawled on: <%= report[tag + '_time'] %>
|
72
|
+
</div>
|
73
|
+
<div>
|
74
|
+
<%= report[tag + '_note'] %>
|
75
|
+
</div>
|
76
|
+
|
56
77
|
</div>
|
57
78
|
<% end %>
|
58
79
|
</div>
|
@@ -112,9 +133,15 @@
|
|
112
133
|
<span class="path"><%= result.path %></span>
|
113
134
|
<div class="buttons">
|
114
135
|
<% unless relative %>
|
115
|
-
|
116
|
-
|
117
|
-
|
136
|
+
<% unless report['before_url_report'] === false %>
|
137
|
+
<a href="<%= result.url(:before, before_url_report || before, cache) %>" class="button-before" target="_blank">Before</a>
|
138
|
+
<% end %>
|
139
|
+
<% unless report['after_url_report'] === false %>
|
140
|
+
<a href="<%= result.url(:after, after_url_report || after, cache) %>" class="button-after" target="_blank">After</a>
|
141
|
+
<% end %>
|
142
|
+
<% unless report['before_url_report'] === false || report['after_url_report'] === false %>
|
143
|
+
<a href="/sidebyside<%= result.path %>" class="button-both">Both</a>
|
144
|
+
<% end %>
|
118
145
|
<% end %>
|
119
146
|
<% unless result.diff_url.nil? %>
|
120
147
|
<a href="<%= result.diff_url(relative) %>" class="button button-diff">View diff</a>
|
@@ -1,6 +1,5 @@
|
|
1
1
|
* {
|
2
2
|
box-sizing: border-box;
|
3
|
-
outline: none;
|
4
3
|
}
|
5
4
|
|
6
5
|
a {
|
@@ -247,3 +246,81 @@ table .status-col {
|
|
247
246
|
top: 0;
|
248
247
|
width: 100%;
|
249
248
|
}
|
249
|
+
|
250
|
+
/*** Overlay */
|
251
|
+
.overlay {
|
252
|
+
background-color: rgba(0, 0, 0, 0.25);
|
253
|
+
height: 100vh;
|
254
|
+
left: 0;
|
255
|
+
padding: 2em;
|
256
|
+
position: fixed;
|
257
|
+
top: 0;
|
258
|
+
width: 100vw;
|
259
|
+
}
|
260
|
+
|
261
|
+
.overlay__inner {
|
262
|
+
background-color: #fff;
|
263
|
+
height: 100%;
|
264
|
+
margin: 0;
|
265
|
+
position: relative;
|
266
|
+
width: 100%;
|
267
|
+
}
|
268
|
+
|
269
|
+
.overlay header {
|
270
|
+
background-color: #f9f9fb;
|
271
|
+
border-bottom: 2px solid #eaecf3;
|
272
|
+
display: flex;
|
273
|
+
min-height: 3em;
|
274
|
+
left: 0;
|
275
|
+
position: absolute;
|
276
|
+
top: 0;
|
277
|
+
width: 100%;
|
278
|
+
}
|
279
|
+
|
280
|
+
.overlay header .prev,
|
281
|
+
.overlay header .next,
|
282
|
+
.overlay header .exit {
|
283
|
+
padding: 0.5em 0;
|
284
|
+
margin: 0.5em;
|
285
|
+
}
|
286
|
+
|
287
|
+
.overlay header .prev a,
|
288
|
+
.overlay header .next a,
|
289
|
+
.overlay header .exit a {
|
290
|
+
background-color: #eaecf3;
|
291
|
+
font-size: .9em;
|
292
|
+
padding: 0.5em;
|
293
|
+
text-decoration: none;
|
294
|
+
}
|
295
|
+
|
296
|
+
.overlay header .prev a:hover,
|
297
|
+
.overlay header .next a:hover,
|
298
|
+
.overlay header .exit a:hover {
|
299
|
+
background-color: #d2d7ef;
|
300
|
+
}
|
301
|
+
|
302
|
+
.overlay header .prev.disabled a,
|
303
|
+
.overlay header .next.disabled a,
|
304
|
+
.overlay header .exit.disabled a,
|
305
|
+
.overlay header .prev.disabled a:hover,
|
306
|
+
.overlay header .next.disabled a:hover,
|
307
|
+
.overlay header .exit.disabled a:hover {
|
308
|
+
background-color: eaecf3;
|
309
|
+
color: #9b9db8;
|
310
|
+
cursor: not-allowed;
|
311
|
+
}
|
312
|
+
.overlay header .path {
|
313
|
+
flex-grow: 1;
|
314
|
+
padding: 1em;
|
315
|
+
}
|
316
|
+
|
317
|
+
.overlay article {
|
318
|
+
background-color: #fff;
|
319
|
+
height: 100%;
|
320
|
+
width: 100%;
|
321
|
+
}
|
322
|
+
|
323
|
+
.overlay article iframe {
|
324
|
+
height: 100%;
|
325
|
+
width: 100%;
|
326
|
+
}
|
@@ -3,11 +3,21 @@
|
|
3
3
|
* SiteDiff report behaviors.
|
4
4
|
*/
|
5
5
|
|
6
|
+
'use strict';
|
7
|
+
|
8
|
+
/* global $ */
|
6
9
|
/**
|
7
10
|
* SiteDiff namespace.
|
8
11
|
*/
|
9
12
|
var SiteDiff = SiteDiff || {};
|
10
13
|
|
14
|
+
/**
|
15
|
+
* SiteDiff global map of diffs.
|
16
|
+
*/
|
17
|
+
SiteDiff.diffs = SiteDiff.diffs || {};
|
18
|
+
|
19
|
+
SiteDiff.currentDiff = -1;
|
20
|
+
|
11
21
|
/**
|
12
22
|
* Scrolls the document to the said position.
|
13
23
|
*
|
@@ -75,23 +85,42 @@ SiteDiff.scrollToElement = function (el, options) {
|
|
75
85
|
SiteDiff.init = function () {
|
76
86
|
// On the overview page.
|
77
87
|
switch ($(document.body).data('page')) {
|
78
|
-
|
79
|
-
|
80
|
-
|
88
|
+
case 'overview':
|
89
|
+
SiteDiff.initFilterForm();
|
90
|
+
break;
|
81
91
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
break;
|
92
|
+
case 'diff':
|
93
|
+
SiteDiff.jumpToFirstDiff();
|
94
|
+
break;
|
86
95
|
}
|
87
96
|
};
|
88
97
|
|
89
98
|
/**
|
90
|
-
* Initializes report filters.
|
99
|
+
* Initializes report filters and overlay.
|
91
100
|
*/
|
92
101
|
SiteDiff.initFilterForm = function () {
|
102
|
+
SiteDiff.initDiffArray();
|
93
103
|
SiteDiff.initStatusFilter();
|
94
104
|
SiteDiff.initSearchFilter();
|
105
|
+
SiteDiff.initOverlay();
|
106
|
+
SiteDiff.initClickHandlers();
|
107
|
+
};
|
108
|
+
|
109
|
+
/**
|
110
|
+
* Initialize global diff array
|
111
|
+
*
|
112
|
+
*/
|
113
|
+
SiteDiff.initDiffArray = function() {
|
114
|
+
SiteDiff.diffs = $('.button-diff').map(function (i, element) {
|
115
|
+
var $el = $(element);
|
116
|
+
$el.data('diffindex', i);
|
117
|
+
return {
|
118
|
+
diff: $el.attr('href'),
|
119
|
+
element: $el,
|
120
|
+
index: i,
|
121
|
+
path: $el.parents('.description').find('.path').text()
|
122
|
+
};
|
123
|
+
});
|
95
124
|
};
|
96
125
|
|
97
126
|
/**
|
@@ -102,11 +131,10 @@ SiteDiff.initStatusFilter = function () {
|
|
102
131
|
.on('change', function () {
|
103
132
|
// Get a list of applied filters.
|
104
133
|
var appliedFilters = $('.form-item--status input:checked')
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
});
|
134
|
+
.map(function () {
|
135
|
+
return this.getAttribute('value');
|
136
|
+
// applied.push(this.getAttribute('value'));
|
137
|
+
});
|
110
138
|
// Show only matching results, hide the rest.
|
111
139
|
$('#sitediff-report')
|
112
140
|
.find('.sitediff-result')
|
@@ -155,6 +183,169 @@ SiteDiff.initSearchFilter = function () {
|
|
155
183
|
});
|
156
184
|
};
|
157
185
|
|
186
|
+
/**
|
187
|
+
* Set up the diff overlay to be displayed.
|
188
|
+
*/
|
189
|
+
SiteDiff.initOverlay = function () {
|
190
|
+
if (SiteDiff.diffs.length <= 0) return;
|
191
|
+
|
192
|
+
// add overlay
|
193
|
+
$('body').append($(
|
194
|
+
'<div class="overlay" style="display: none;"><div class="overlay__inner"><header>' +
|
195
|
+
'<div class="path"></div>' +
|
196
|
+
'<div class="prev"><a href="#" title="Previous diff (left arrow)">< Prev</a></div>' +
|
197
|
+
'<div class="next"><a href="#" title="Next diff (right arrow)">Next ></a></div>' +
|
198
|
+
'<div class="exit"><a href="#" title="Close diff display (Esc)">Close</a></div>' +
|
199
|
+
'</header><article></article></div></div>'));
|
200
|
+
// add header click handlers
|
201
|
+
$('.overlay header .exit').click(function (event) {
|
202
|
+
event.preventDefault();
|
203
|
+
SiteDiff.destroyOverlay();
|
204
|
+
});
|
205
|
+
$('.overlay header .prev').click(function (event) {
|
206
|
+
event.preventDefault();
|
207
|
+
SiteDiff.prevDiff();
|
208
|
+
});
|
209
|
+
$('.overlay header .next').click(function (event) {
|
210
|
+
event.preventDefault();
|
211
|
+
SiteDiff.nextDiff();
|
212
|
+
});
|
213
|
+
|
214
|
+
};
|
215
|
+
|
216
|
+
/**
|
217
|
+
* Set up click handlers for all diff buttons
|
218
|
+
*/
|
219
|
+
SiteDiff.initClickHandlers = function () {
|
220
|
+
SiteDiff.diffs.each( function (i, diff) {
|
221
|
+
diff.element.click({index: i}, function (event) {
|
222
|
+
event.preventDefault();
|
223
|
+
SiteDiff.openOverlay(event.data.index);
|
224
|
+
});
|
225
|
+
});
|
226
|
+
};
|
227
|
+
|
228
|
+
/**
|
229
|
+
* Set up key handlers for overlay.
|
230
|
+
*/
|
231
|
+
SiteDiff.initKeyHandlers = function () {
|
232
|
+
$(document).keyup(function (event) {
|
233
|
+
switch (event.which) {
|
234
|
+
case 37:
|
235
|
+
SiteDiff.prevDiff();
|
236
|
+
break;
|
237
|
+
case 39:
|
238
|
+
SiteDiff.nextDiff();
|
239
|
+
break;
|
240
|
+
case 27:
|
241
|
+
SiteDiff.destroyOverlay();
|
242
|
+
break;
|
243
|
+
}
|
244
|
+
});
|
245
|
+
};
|
246
|
+
|
247
|
+
/**
|
248
|
+
* Remove overlay key handlers.
|
249
|
+
*/
|
250
|
+
SiteDiff.removeKeyHandlers = function () {
|
251
|
+
$(document).off('keyup');
|
252
|
+
};
|
253
|
+
|
254
|
+
/**
|
255
|
+
* Open overlay for the diff identified by the `index`.
|
256
|
+
*
|
257
|
+
* @param integer index
|
258
|
+
* The index of the diff to be viewed.
|
259
|
+
*/
|
260
|
+
SiteDiff.openOverlay = function (index) {
|
261
|
+
SiteDiff.currentDiff = index;
|
262
|
+
SiteDiff.showDiff();
|
263
|
+
SiteDiff.initKeyHandlers();
|
264
|
+
$('.overlay').fadeIn(300);
|
265
|
+
};
|
266
|
+
|
267
|
+
/**
|
268
|
+
* Create the iframe to display the current diff.
|
269
|
+
*/
|
270
|
+
SiteDiff.showDiff = function () {
|
271
|
+
var diff = SiteDiff.diffs[SiteDiff.currentDiff];
|
272
|
+
var iframe = '<iframe src="' + diff.diff + '"></iframe>';
|
273
|
+
$('.overlay header .path').text(diff.path);
|
274
|
+
SiteDiff.setPrevNext();
|
275
|
+
$('.overlay article').html(iframe);
|
276
|
+
};
|
277
|
+
|
278
|
+
/**
|
279
|
+
* Hide the overlay and clean up.
|
280
|
+
*/
|
281
|
+
SiteDiff.destroyOverlay = function () {
|
282
|
+
$('.overlay article').empty();
|
283
|
+
SiteDiff.removeKeyHandlers();
|
284
|
+
$('.overlay').fadeOut(300, SiteDiff.scrollToButton);
|
285
|
+
};
|
286
|
+
|
287
|
+
/**
|
288
|
+
* Display the previous diff.
|
289
|
+
*/
|
290
|
+
SiteDiff.prevDiff = function () {
|
291
|
+
if (SiteDiff.currentDiff > 0) {
|
292
|
+
SiteDiff.currentDiff--;
|
293
|
+
SiteDiff.showDiff();
|
294
|
+
}
|
295
|
+
};
|
296
|
+
|
297
|
+
/**
|
298
|
+
* Display the next diff.
|
299
|
+
*/
|
300
|
+
SiteDiff.nextDiff = function () {
|
301
|
+
if (SiteDiff.currentDiff < SiteDiff.diffs.length - 1) {
|
302
|
+
SiteDiff.currentDiff++;
|
303
|
+
SiteDiff.showDiff();
|
304
|
+
}
|
305
|
+
};
|
306
|
+
|
307
|
+
/**
|
308
|
+
* Enable or disable prev and next buttons based on current diff.
|
309
|
+
*/
|
310
|
+
SiteDiff.setPrevNext = function () {
|
311
|
+
if (SiteDiff.currentDiff <= 0) {
|
312
|
+
// set prev disabled
|
313
|
+
$('.overlay header .prev').addClass('disabled');
|
314
|
+
}
|
315
|
+
else {
|
316
|
+
$('.overlay header .prev.disabled').removeClass('disabled');
|
317
|
+
}
|
318
|
+
if (SiteDiff.currentDiff >= SiteDiff.diffs.length - 1) {
|
319
|
+
// set next disabled
|
320
|
+
$('.overlay header .next').addClass('disabled');
|
321
|
+
}
|
322
|
+
else {
|
323
|
+
$('.overlay header .next.disabled').removeClass('disabled');
|
324
|
+
}
|
325
|
+
};
|
326
|
+
|
327
|
+
/**
|
328
|
+
* Scroll to the button associated with the current diff.
|
329
|
+
*/
|
330
|
+
SiteDiff.scrollToButton = function () {
|
331
|
+
var $diffButton = SiteDiff.diffs[SiteDiff.currentDiff].element;
|
332
|
+
if (! SiteDiff.isElementVisible($diffButton)) {
|
333
|
+
SiteDiff.scrollToElement($diffButton);
|
334
|
+
}
|
335
|
+
};
|
336
|
+
|
337
|
+
/**
|
338
|
+
* Check if an element is at least partly visible.
|
339
|
+
* @param element
|
340
|
+
*/
|
341
|
+
SiteDiff.isElementVisible = function (element) {
|
342
|
+
var topVisible = $(window).scrollTop();
|
343
|
+
var bottomVisible = topVisible + $(window).height();
|
344
|
+
var elemTop = $(element).offset().top;
|
345
|
+
var elemBottom = elemTop + $(element).height();
|
346
|
+
return ((elemBottom <= bottomVisible) && (elemTop >= topVisible));
|
347
|
+
};
|
348
|
+
|
158
349
|
/**
|
159
350
|
* Jumps to the first diff on the page.
|
160
351
|
*/
|