sitediff 1.0.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
*/
|