Show More
@@ -0,0 +1,91 b'' | |||||
|
1 | // jQuery Scrollstop Plugin v1.2.0 | |||
|
2 | // https://github.com/ssorallen/jquery-scrollstop | |||
|
3 | ||||
|
4 | (function (factory) { | |||
|
5 | // UMD[2] wrapper for jQuery plugins to work in AMD or in CommonJS. | |||
|
6 | // | |||
|
7 | // [2] https://github.com/umdjs/umd | |||
|
8 | ||||
|
9 | if (typeof define === 'function' && define.amd) { | |||
|
10 | // AMD. Register as an anonymous module. | |||
|
11 | define(['jquery'], factory); | |||
|
12 | } else if (typeof exports === 'object') { | |||
|
13 | // Node/CommonJS | |||
|
14 | module.exports = factory(require('jquery')); | |||
|
15 | } else { | |||
|
16 | // Browser globals | |||
|
17 | factory(jQuery); | |||
|
18 | } | |||
|
19 | }(function ($) { | |||
|
20 | // $.event.dispatch was undocumented and was deprecated in jQuery 1.7[1]. It | |||
|
21 | // was replaced by $.event.handle in jQuery 1.9. | |||
|
22 | // | |||
|
23 | // Use the first of the available functions to support jQuery <1.8. | |||
|
24 | // | |||
|
25 | // [1] https://github.com/jquery/jquery-migrate/blob/master/src/event.js#L25 | |||
|
26 | var dispatch = $.event.dispatch || $.event.handle; | |||
|
27 | ||||
|
28 | var special = $.event.special, | |||
|
29 | uid1 = 'D' + (+new Date()), | |||
|
30 | uid2 = 'D' + (+new Date() + 1); | |||
|
31 | ||||
|
32 | special.scrollstart = { | |||
|
33 | setup: function(data) { | |||
|
34 | var _data = $.extend({ | |||
|
35 | latency: special.scrollstop.latency | |||
|
36 | }, data); | |||
|
37 | ||||
|
38 | var timer, | |||
|
39 | handler = function(evt) { | |||
|
40 | var _self = this, | |||
|
41 | _args = arguments; | |||
|
42 | ||||
|
43 | if (timer) { | |||
|
44 | clearTimeout(timer); | |||
|
45 | } else { | |||
|
46 | evt.type = 'scrollstart'; | |||
|
47 | dispatch.apply(_self, _args); | |||
|
48 | } | |||
|
49 | ||||
|
50 | timer = setTimeout(function() { | |||
|
51 | timer = null; | |||
|
52 | }, _data.latency); | |||
|
53 | }; | |||
|
54 | ||||
|
55 | $(this).bind('scroll', handler).data(uid1, handler); | |||
|
56 | }, | |||
|
57 | teardown: function() { | |||
|
58 | $(this).unbind('scroll', $(this).data(uid1)); | |||
|
59 | } | |||
|
60 | }; | |||
|
61 | ||||
|
62 | special.scrollstop = { | |||
|
63 | latency: 250, | |||
|
64 | setup: function(data) { | |||
|
65 | var _data = $.extend({ | |||
|
66 | latency: special.scrollstop.latency | |||
|
67 | }, data); | |||
|
68 | ||||
|
69 | var timer, | |||
|
70 | handler = function(evt) { | |||
|
71 | var _self = this, | |||
|
72 | _args = arguments; | |||
|
73 | ||||
|
74 | if (timer) { | |||
|
75 | clearTimeout(timer); | |||
|
76 | } | |||
|
77 | ||||
|
78 | timer = setTimeout(function() { | |||
|
79 | timer = null; | |||
|
80 | evt.type = 'scrollstop'; | |||
|
81 | dispatch.apply(_self, _args); | |||
|
82 | }, _data.latency); | |||
|
83 | }; | |||
|
84 | ||||
|
85 | $(this).bind('scroll', handler).data(uid2, handler); | |||
|
86 | }, | |||
|
87 | teardown: function() { | |||
|
88 | $(this).unbind('scroll', $(this).data(uid2)); | |||
|
89 | } | |||
|
90 | }; | |||
|
91 | })); |
@@ -0,0 +1,171 b'' | |||||
|
1 | /** | |||
|
2 | * Within Viewport jQuery Plugin | |||
|
3 | * | |||
|
4 | * @description Companion plugin for withinviewport.js - determines whether an element is completely within the browser viewport | |||
|
5 | * @author Craig Patik, http://patik.com/ | |||
|
6 | * @version 2.1.2 | |||
|
7 | * @date 2019-08-16 | |||
|
8 | */ | |||
|
9 | (function ($) { | |||
|
10 | /** | |||
|
11 | * $.withinviewport() | |||
|
12 | * @description jQuery method | |||
|
13 | * @param {Object} [settings] optional settings | |||
|
14 | * @return {Collection} Contains all elements that were within the viewport | |||
|
15 | */ | |||
|
16 | $.fn.withinviewport = function (settings) { | |||
|
17 | var opts; | |||
|
18 | var elems; | |||
|
19 | ||||
|
20 | if (typeof settings === 'string') { | |||
|
21 | settings = { | |||
|
22 | sides: settings | |||
|
23 | }; | |||
|
24 | } | |||
|
25 | ||||
|
26 | opts = $.extend({}, settings, { | |||
|
27 | sides: 'all' | |||
|
28 | }); | |||
|
29 | elems = []; | |||
|
30 | ||||
|
31 | this.each(function () { | |||
|
32 | if (withinviewport(this, opts)) { | |||
|
33 | elems.push(this); | |||
|
34 | } | |||
|
35 | }); | |||
|
36 | ||||
|
37 | return $(elems); | |||
|
38 | }; | |||
|
39 | ||||
|
40 | // Main custom selector | |||
|
41 | $.extend($.expr[':'], { | |||
|
42 | 'within-viewport': function (element) { | |||
|
43 | return withinviewport(element, 'all'); | |||
|
44 | } | |||
|
45 | }); | |||
|
46 | ||||
|
47 | /** | |||
|
48 | * Optional enhancements and shortcuts | |||
|
49 | * | |||
|
50 | * @description Uncomment or comment these pieces as they apply to your project and coding preferences | |||
|
51 | */ | |||
|
52 | ||||
|
53 | // Shorthand jQuery methods | |||
|
54 | ||||
|
55 | $.fn.withinviewporttop = function (settings) { | |||
|
56 | var opts; | |||
|
57 | var elems; | |||
|
58 | ||||
|
59 | if (typeof settings === 'string') { | |||
|
60 | settings = { | |||
|
61 | sides: settings | |||
|
62 | }; | |||
|
63 | } | |||
|
64 | ||||
|
65 | opts = $.extend({}, settings, { | |||
|
66 | sides: 'top' | |||
|
67 | }); | |||
|
68 | elems = []; | |||
|
69 | ||||
|
70 | this.each(function () { | |||
|
71 | if (withinviewport(this, opts)) { | |||
|
72 | elems.push(this); | |||
|
73 | } | |||
|
74 | }); | |||
|
75 | ||||
|
76 | return $(elems); | |||
|
77 | }; | |||
|
78 | ||||
|
79 | $.fn.withinviewportright = function (settings) { | |||
|
80 | var opts; | |||
|
81 | var elems; | |||
|
82 | ||||
|
83 | if (typeof settings === 'string') { | |||
|
84 | settings = { | |||
|
85 | sides: settings | |||
|
86 | }; | |||
|
87 | } | |||
|
88 | ||||
|
89 | opts = $.extend({}, settings, { | |||
|
90 | sides: 'right' | |||
|
91 | }); | |||
|
92 | elems = []; | |||
|
93 | ||||
|
94 | this.each(function () { | |||
|
95 | if (withinviewport(this, opts)) { | |||
|
96 | elems.push(this); | |||
|
97 | } | |||
|
98 | }); | |||
|
99 | ||||
|
100 | return $(elems); | |||
|
101 | }; | |||
|
102 | ||||
|
103 | $.fn.withinviewportbottom = function (settings) { | |||
|
104 | var opts; | |||
|
105 | var elems; | |||
|
106 | ||||
|
107 | if (typeof settings === 'string') { | |||
|
108 | settings = { | |||
|
109 | sides: settings | |||
|
110 | }; | |||
|
111 | } | |||
|
112 | ||||
|
113 | opts = $.extend({}, settings, { | |||
|
114 | sides: 'bottom' | |||
|
115 | }); | |||
|
116 | elems = []; | |||
|
117 | ||||
|
118 | this.each(function () { | |||
|
119 | if (withinviewport(this, opts)) { | |||
|
120 | elems.push(this); | |||
|
121 | } | |||
|
122 | }); | |||
|
123 | ||||
|
124 | return $(elems); | |||
|
125 | }; | |||
|
126 | ||||
|
127 | $.fn.withinviewportleft = function (settings) { | |||
|
128 | var opts; | |||
|
129 | var elems; | |||
|
130 | ||||
|
131 | if (typeof settings === 'string') { | |||
|
132 | settings = { | |||
|
133 | sides: settings | |||
|
134 | }; | |||
|
135 | } | |||
|
136 | ||||
|
137 | opts = $.extend({}, settings, { | |||
|
138 | sides: 'left' | |||
|
139 | }); | |||
|
140 | elems = []; | |||
|
141 | ||||
|
142 | this.each(function () { | |||
|
143 | if (withinviewport(this, opts)) { | |||
|
144 | elems.push(this); | |||
|
145 | } | |||
|
146 | }); | |||
|
147 | ||||
|
148 | return $(elems); | |||
|
149 | }; | |||
|
150 | ||||
|
151 | // Custom jQuery selectors | |||
|
152 | $.extend($.expr[':'], { | |||
|
153 | 'within-viewport-top': function (element) { | |||
|
154 | return withinviewport(element, 'top'); | |||
|
155 | }, | |||
|
156 | 'within-viewport-right': function (element) { | |||
|
157 | return withinviewport(element, 'right'); | |||
|
158 | }, | |||
|
159 | 'within-viewport-bottom': function (element) { | |||
|
160 | return withinviewport(element, 'bottom'); | |||
|
161 | }, | |||
|
162 | 'within-viewport-left': function (element) { | |||
|
163 | return withinviewport(element, 'left'); | |||
|
164 | } | |||
|
165 | // Example custom selector: | |||
|
166 | //, | |||
|
167 | // 'within-viewport-top-left-45': function (element) { | |||
|
168 | // return withinviewport(element, {sides:'top left', top: 45, left: 45}); | |||
|
169 | // } | |||
|
170 | }); | |||
|
171 | }(jQuery)); No newline at end of file |
@@ -0,0 +1,235 b'' | |||||
|
1 | /** | |||
|
2 | * Within Viewport | |||
|
3 | * | |||
|
4 | * @description Determines whether an element is completely within the browser viewport | |||
|
5 | * @author Craig Patik, http://patik.com/ | |||
|
6 | * @version 2.1.2 | |||
|
7 | * @date 2019-08-16 | |||
|
8 | */ | |||
|
9 | (function (root, name, factory) { | |||
|
10 | // AMD | |||
|
11 | if (typeof define === 'function' && define.amd) { | |||
|
12 | define([], factory); | |||
|
13 | } | |||
|
14 | // Node and CommonJS-like environments | |||
|
15 | else if (typeof module !== 'undefined' && typeof exports === 'object') { | |||
|
16 | module.exports = factory(); | |||
|
17 | } | |||
|
18 | // Browser global | |||
|
19 | else { | |||
|
20 | root[name] = factory(); | |||
|
21 | } | |||
|
22 | }(this, 'withinviewport', function () { | |||
|
23 | var canUseWindowDimensions = typeof window !== 'undefined' && window.innerHeight !== undefined; // IE 8 and lower fail this | |||
|
24 | ||||
|
25 | /** | |||
|
26 | * Determines whether an element is within the viewport | |||
|
27 | * @param {Object} elem DOM Element (required) | |||
|
28 | * @param {Object} options Optional settings | |||
|
29 | * @return {Boolean} Whether the element was completely within the viewport | |||
|
30 | */ | |||
|
31 | var withinviewport = function withinviewport(elem, options) { | |||
|
32 | var result = false; | |||
|
33 | var metadata = {}; | |||
|
34 | var config = {}; | |||
|
35 | var settings; | |||
|
36 | var isWithin; | |||
|
37 | var isContainerTheWindow; | |||
|
38 | var elemBoundingRect; | |||
|
39 | var containerBoundingRect; | |||
|
40 | var containerScrollTop; | |||
|
41 | var containerScrollLeft; | |||
|
42 | var scrollBarWidths = [0, 0]; | |||
|
43 | var sideNamesPattern; | |||
|
44 | var sides; | |||
|
45 | var side; | |||
|
46 | var i; | |||
|
47 | ||||
|
48 | // If invoked by the jQuery plugin, get the actual DOM element | |||
|
49 | if (typeof jQuery !== 'undefined' && elem instanceof jQuery) { | |||
|
50 | elem = elem.get(0); | |||
|
51 | } | |||
|
52 | ||||
|
53 | if (typeof elem !== 'object' || elem.nodeType !== 1) { | |||
|
54 | throw new Error('First argument must be an element'); | |||
|
55 | } | |||
|
56 | ||||
|
57 | // Look for inline settings on the element | |||
|
58 | if (elem.getAttribute('data-withinviewport-settings') && window.JSON) { | |||
|
59 | metadata = JSON.parse(elem.getAttribute('data-withinviewport-settings')); | |||
|
60 | } | |||
|
61 | ||||
|
62 | // Settings argument may be a simple string (`top`, `right`, etc) | |||
|
63 | if (typeof options === 'string') { | |||
|
64 | settings = { | |||
|
65 | sides: options | |||
|
66 | }; | |||
|
67 | } else { | |||
|
68 | settings = options || {}; | |||
|
69 | } | |||
|
70 | ||||
|
71 | // Build configuration from defaults and user-provided settings and metadata | |||
|
72 | config.container = settings.container || metadata.container || withinviewport.defaults.container || window; | |||
|
73 | config.sides = settings.sides || metadata.sides || withinviewport.defaults.sides || 'all'; | |||
|
74 | config.top = settings.top || metadata.top || withinviewport.defaults.top || 0; | |||
|
75 | config.right = settings.right || metadata.right || withinviewport.defaults.right || 0; | |||
|
76 | config.bottom = settings.bottom || metadata.bottom || withinviewport.defaults.bottom || 0; | |||
|
77 | config.left = settings.left || metadata.left || withinviewport.defaults.left || 0; | |||
|
78 | ||||
|
79 | // Extract the DOM node from a jQuery collection | |||
|
80 | if (typeof jQuery !== 'undefined' && config.container instanceof jQuery) { | |||
|
81 | config.container = config.container.get(0); | |||
|
82 | } | |||
|
83 | ||||
|
84 | // Use the window as the container if the user specified the body or a non-element | |||
|
85 | if (config.container === document.body || config.container.nodeType !== 1) { | |||
|
86 | config.container = window; | |||
|
87 | } | |||
|
88 | ||||
|
89 | isContainerTheWindow = (config.container === window); | |||
|
90 | ||||
|
91 | // Element testing methods | |||
|
92 | isWithin = { | |||
|
93 | // Element is below the top edge of the viewport | |||
|
94 | top: function _isWithin_top() { | |||
|
95 | if (isContainerTheWindow) { | |||
|
96 | return (elemBoundingRect.top >= config.top); | |||
|
97 | } else { | |||
|
98 | return (elemBoundingRect.top >= containerScrollTop - (containerScrollTop - containerBoundingRect.top) + config.top); | |||
|
99 | } | |||
|
100 | }, | |||
|
101 | ||||
|
102 | // Element is to the left of the right edge of the viewport | |||
|
103 | right: function _isWithin_right() { | |||
|
104 | // Note that `elemBoundingRect.right` is the distance from the *left* of the viewport to the element's far right edge | |||
|
105 | ||||
|
106 | if (isContainerTheWindow) { | |||
|
107 | return (elemBoundingRect.right <= (containerBoundingRect.right + containerScrollLeft) - config.right); | |||
|
108 | } else { | |||
|
109 | return (elemBoundingRect.right <= containerBoundingRect.right - scrollBarWidths[0] - config.right); | |||
|
110 | } | |||
|
111 | }, | |||
|
112 | ||||
|
113 | // Element is above the bottom edge of the viewport | |||
|
114 | bottom: function _isWithin_bottom() { | |||
|
115 | var containerHeight = 0; | |||
|
116 | ||||
|
117 | if (isContainerTheWindow) { | |||
|
118 | if (canUseWindowDimensions) { | |||
|
119 | containerHeight = config.container.innerHeight; | |||
|
120 | } else if (document && document.documentElement) { | |||
|
121 | containerHeight = document.documentElement.clientHeight; | |||
|
122 | } | |||
|
123 | } else { | |||
|
124 | containerHeight = containerBoundingRect.bottom; | |||
|
125 | } | |||
|
126 | ||||
|
127 | // Note that `elemBoundingRect.bottom` is the distance from the *top* of the viewport to the element's bottom edge | |||
|
128 | return (elemBoundingRect.bottom <= containerHeight - scrollBarWidths[1] - config.bottom); | |||
|
129 | }, | |||
|
130 | ||||
|
131 | // Element is to the right of the left edge of the viewport | |||
|
132 | left: function _isWithin_left() { | |||
|
133 | if (isContainerTheWindow) { | |||
|
134 | return (elemBoundingRect.left >= config.left); | |||
|
135 | } else { | |||
|
136 | return (elemBoundingRect.left >= containerScrollLeft - (containerScrollLeft - containerBoundingRect.left) + config.left); | |||
|
137 | } | |||
|
138 | }, | |||
|
139 | ||||
|
140 | // Element is within all four boundaries | |||
|
141 | all: function _isWithin_all() { | |||
|
142 | // Test each boundary in order of efficiency and likeliness to be false. This way we can avoid running all four functions on most elements. | |||
|
143 | // 1. Top: Quickest to calculate + most likely to be false | |||
|
144 | // 2. Bottom: Note quite as quick to calculate, but also very likely to be false | |||
|
145 | // 3-4. Left and right are both equally unlikely to be false since most sites only scroll vertically, but left is faster to calculate | |||
|
146 | return (isWithin.top() && isWithin.bottom() && isWithin.left() && isWithin.right()); | |||
|
147 | } | |||
|
148 | }; | |||
|
149 | ||||
|
150 | // Get the element's bounding rectangle with respect to the viewport | |||
|
151 | elemBoundingRect = elem.getBoundingClientRect(); | |||
|
152 | ||||
|
153 | // Get viewport dimensions and offsets | |||
|
154 | if (isContainerTheWindow) { | |||
|
155 | containerBoundingRect = document.documentElement.getBoundingClientRect(); | |||
|
156 | containerScrollTop = document.body.scrollTop; | |||
|
157 | containerScrollLeft = window.scrollX || document.body.scrollLeft; | |||
|
158 | } else { | |||
|
159 | containerBoundingRect = config.container.getBoundingClientRect(); | |||
|
160 | containerScrollTop = config.container.scrollTop; | |||
|
161 | containerScrollLeft = config.container.scrollLeft; | |||
|
162 | } | |||
|
163 | ||||
|
164 | // Don't count the space consumed by scrollbars | |||
|
165 | if (containerScrollLeft) { | |||
|
166 | scrollBarWidths[0] = 18; | |||
|
167 | } | |||
|
168 | ||||
|
169 | if (containerScrollTop) { | |||
|
170 | scrollBarWidths[1] = 16; | |||
|
171 | } | |||
|
172 | ||||
|
173 | // Test the element against each side of the viewport that was requested | |||
|
174 | sideNamesPattern = /^top$|^right$|^bottom$|^left$|^all$/; | |||
|
175 | ||||
|
176 | // Loop through all of the sides | |||
|
177 | sides = config.sides.split(' '); | |||
|
178 | i = sides.length; | |||
|
179 | ||||
|
180 | while (i--) { | |||
|
181 | side = sides[i].toLowerCase(); | |||
|
182 | ||||
|
183 | if (sideNamesPattern.test(side)) { | |||
|
184 | if (isWithin[side]()) { | |||
|
185 | result = true; | |||
|
186 | } else { | |||
|
187 | result = false; | |||
|
188 | ||||
|
189 | // Quit as soon as the first failure is found | |||
|
190 | break; | |||
|
191 | } | |||
|
192 | } | |||
|
193 | } | |||
|
194 | ||||
|
195 | return result; | |||
|
196 | }; | |||
|
197 | ||||
|
198 | // Default settings | |||
|
199 | withinviewport.prototype.defaults = { | |||
|
200 | container: typeof document !== 'undefined' ? document.body : {}, | |||
|
201 | sides: 'all', | |||
|
202 | top: 0, | |||
|
203 | right: 0, | |||
|
204 | bottom: 0, | |||
|
205 | left: 0 | |||
|
206 | }; | |||
|
207 | ||||
|
208 | withinviewport.defaults = withinviewport.prototype.defaults; | |||
|
209 | ||||
|
210 | /** | |||
|
211 | * Optional enhancements and shortcuts | |||
|
212 | * | |||
|
213 | * @description Uncomment or comment these pieces as they apply to your project and coding preferences | |||
|
214 | */ | |||
|
215 | ||||
|
216 | // Shortcut methods for each side of the viewport | |||
|
217 | // Example: `withinviewport.top(elem)` is the same as `withinviewport(elem, 'top')` | |||
|
218 | withinviewport.prototype.top = function _withinviewport_top(element) { | |||
|
219 | return withinviewport(element, 'top'); | |||
|
220 | }; | |||
|
221 | ||||
|
222 | withinviewport.prototype.right = function _withinviewport_right(element) { | |||
|
223 | return withinviewport(element, 'right'); | |||
|
224 | }; | |||
|
225 | ||||
|
226 | withinviewport.prototype.bottom = function _withinviewport_bottom(element) { | |||
|
227 | return withinviewport(element, 'bottom'); | |||
|
228 | }; | |||
|
229 | ||||
|
230 | withinviewport.prototype.left = function _withinviewport_left(element) { | |||
|
231 | return withinviewport(element, 'left'); | |||
|
232 | }; | |||
|
233 | ||||
|
234 | return withinviewport; | |||
|
235 | })); No newline at end of file |
@@ -51,9 +51,12 b'' | |||||
51 | "<%= dirs.js.src %>/plugins/jquery.pjax.js", |
|
51 | "<%= dirs.js.src %>/plugins/jquery.pjax.js", | |
52 | "<%= dirs.js.src %>/plugins/jquery.dataTables.js", |
|
52 | "<%= dirs.js.src %>/plugins/jquery.dataTables.js", | |
53 | "<%= dirs.js.src %>/plugins/flavoured_checkbox.js", |
|
53 | "<%= dirs.js.src %>/plugins/flavoured_checkbox.js", | |
|
54 | "<%= dirs.js.src %>/plugins/within_viewport.js", | |||
54 | "<%= dirs.js.src %>/plugins/jquery.auto-grow-input.js", |
|
55 | "<%= dirs.js.src %>/plugins/jquery.auto-grow-input.js", | |
55 | "<%= dirs.js.src %>/plugins/jquery.autocomplete.js", |
|
56 | "<%= dirs.js.src %>/plugins/jquery.autocomplete.js", | |
56 | "<%= dirs.js.src %>/plugins/jquery.debounce.js", |
|
57 | "<%= dirs.js.src %>/plugins/jquery.debounce.js", | |
|
58 | "<%= dirs.js.src %>/plugins/jquery.scrollstop.js", | |||
|
59 | "<%= dirs.js.src %>/plugins/jquery.within-viewport.js", | |||
57 | "<%= dirs.js.node_modules %>/mark.js/dist/jquery.mark.min.js", |
|
60 | "<%= dirs.js.node_modules %>/mark.js/dist/jquery.mark.min.js", | |
58 | "<%= dirs.js.src %>/plugins/jquery.timeago.js", |
|
61 | "<%= dirs.js.src %>/plugins/jquery.timeago.js", | |
59 | "<%= dirs.js.src %>/plugins/jquery.timeago-extension.js", |
|
62 | "<%= dirs.js.src %>/plugins/jquery.timeago-extension.js", |
@@ -540,10 +540,11 b' class DiffSet(object):' | |||||
540 | }) |
|
540 | }) | |
541 |
|
541 | |||
542 | file_chunks = patch['chunks'][1:] |
|
542 | file_chunks = patch['chunks'][1:] | |
543 | for hunk in file_chunks: |
|
543 | for i, hunk in enumerate(file_chunks, 1): | |
544 | hunkbit = self.parse_hunk(hunk, source_file, target_file) |
|
544 | hunkbit = self.parse_hunk(hunk, source_file, target_file) | |
545 | hunkbit.source_file_path = source_file_path |
|
545 | hunkbit.source_file_path = source_file_path | |
546 | hunkbit.target_file_path = target_file_path |
|
546 | hunkbit.target_file_path = target_file_path | |
|
547 | hunkbit.index = i | |||
547 | filediff.hunks.append(hunkbit) |
|
548 | filediff.hunks.append(hunkbit) | |
548 |
|
549 | |||
549 | # Simulate hunk on OPS type line which doesn't really contain any diff |
|
550 | # Simulate hunk on OPS type line which doesn't really contain any diff |
@@ -53,7 +53,7 b' from pygments.lexers import (' | |||||
53 | get_lexer_by_name, get_lexer_for_filename, get_lexer_for_mimetype) |
|
53 | get_lexer_by_name, get_lexer_for_filename, get_lexer_for_mimetype) | |
54 |
|
54 | |||
55 | from pyramid.threadlocal import get_current_request |
|
55 | from pyramid.threadlocal import get_current_request | |
56 |
|
56 | from tempita import looper | ||
57 | from webhelpers2.html import literal, HTML, escape |
|
57 | from webhelpers2.html import literal, HTML, escape | |
58 | from webhelpers2.html._autolink import _auto_link_urls |
|
58 | from webhelpers2.html._autolink import _auto_link_urls | |
59 | from webhelpers2.html.tools import ( |
|
59 | from webhelpers2.html.tools import ( |
@@ -998,6 +998,21 b' input.filediff-collapse-state {' | |||||
998 |
|
998 | |||
999 | /**** END COMMENTS ****/ |
|
999 | /**** END COMMENTS ****/ | |
1000 |
|
1000 | |||
|
1001 | ||||
|
1002 | .nav-chunk { | |||
|
1003 | position: absolute; | |||
|
1004 | right: 20px; | |||
|
1005 | margin-top: -17px; | |||
|
1006 | } | |||
|
1007 | ||||
|
1008 | .nav-chunk.selected { | |||
|
1009 | visibility: visible !important; | |||
|
1010 | } | |||
|
1011 | ||||
|
1012 | #diff_nav { | |||
|
1013 | color: @grey3; | |||
|
1014 | } | |||
|
1015 | ||||
1001 | } |
|
1016 | } | |
1002 |
|
1017 | |||
1003 |
|
1018 |
@@ -314,6 +314,7 b" return '%s_%s_%i' % (h.md5_safe(commit+f" | |||||
314 | ${hunk.section_header} |
|
314 | ${hunk.section_header} | |
315 | </td> |
|
315 | </td> | |
316 | </tr> |
|
316 | </tr> | |
|
317 | ||||
317 | ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)} |
|
318 | ${render_hunk_lines(filediff, c.user_session_attrs["diffmode"], hunk, use_comments=use_comments, inline_comments=inline_comments, active_pattern_entries=active_pattern_entries)} | |
318 | % endfor |
|
319 | % endfor | |
319 |
|
320 | |||
@@ -657,21 +658,28 b' def get_comments_for(diff_type, comments' | |||||
657 | %> |
|
658 | %> | |
658 |
|
659 | |||
659 | <%def name="render_hunk_lines_sideside(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)"> |
|
660 | <%def name="render_hunk_lines_sideside(filediff, hunk, use_comments=False, inline_comments=None, active_pattern_entries=None)"> | |
660 | %for i, line in enumerate(hunk.sideside): |
|
661 | ||
|
662 | <% chunk_count = 1 %> | |||
|
663 | %for loop_obj, item in h.looper(hunk.sideside): | |||
661 | <% |
|
664 | <% | |
|
665 | line = item | |||
|
666 | i = loop_obj.index | |||
|
667 | prev_line = loop_obj.previous | |||
662 | old_line_anchor, new_line_anchor = None, None |
|
668 | old_line_anchor, new_line_anchor = None, None | |
663 |
|
669 | |||
664 | if line.original.lineno: |
|
670 | if line.original.lineno: | |
665 | old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, line.original.lineno, 'o') |
|
671 | old_line_anchor = diff_line_anchor(filediff.raw_id, hunk.source_file_path, line.original.lineno, 'o') | |
666 | if line.modified.lineno: |
|
672 | if line.modified.lineno: | |
667 | new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, line.modified.lineno, 'n') |
|
673 | new_line_anchor = diff_line_anchor(filediff.raw_id, hunk.target_file_path, line.modified.lineno, 'n') | |
|
674 | ||||
|
675 | line_action = line.modified.action or line.original.action | |||
|
676 | prev_line_action = prev_line and (prev_line.modified.action or prev_line.original.action) | |||
668 | %> |
|
677 | %> | |
669 |
|
678 | |||
670 | <tr class="cb-line"> |
|
679 | <tr class="cb-line"> | |
671 | <td class="cb-data ${action_class(line.original.action)}" |
|
680 | <td class="cb-data ${action_class(line.original.action)}" | |
672 | data-line-no="${line.original.lineno}" |
|
681 | data-line-no="${line.original.lineno}" | |
673 | > |
|
682 | > | |
674 | <div> |
|
|||
675 |
|
683 | |||
676 | <% line_old_comments = None %> |
|
684 | <% line_old_comments = None %> | |
677 | %if line.original.get_comment_args: |
|
685 | %if line.original.get_comment_args: | |
@@ -685,7 +693,6 b' def get_comments_for(diff_type, comments' | |||||
685 | <i class="tooltip icon-comment" title="${_('comments: {}. Click to toggle them.').format(len(line_old_comments))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i> |
|
693 | <i class="tooltip icon-comment" title="${_('comments: {}. Click to toggle them.').format(len(line_old_comments))}" onclick="return Rhodecode.comments.toggleLineComments(this)"></i> | |
686 | % endif |
|
694 | % endif | |
687 | %endif |
|
695 | %endif | |
688 | </div> |
|
|||
689 | </td> |
|
696 | </td> | |
690 | <td class="cb-lineno ${action_class(line.original.action)}" |
|
697 | <td class="cb-lineno ${action_class(line.original.action)}" | |
691 | data-line-no="${line.original.lineno}" |
|
698 | data-line-no="${line.original.lineno}" | |
@@ -751,6 +758,12 b' def get_comments_for(diff_type, comments' | |||||
751 | %if use_comments and line.modified.lineno and line_new_comments: |
|
758 | %if use_comments and line.modified.lineno and line_new_comments: | |
752 | ${inline_comments_container(line_new_comments, active_pattern_entries=active_pattern_entries)} |
|
759 | ${inline_comments_container(line_new_comments, active_pattern_entries=active_pattern_entries)} | |
753 | %endif |
|
760 | %endif | |
|
761 | % if line_action in ['+', '-'] and prev_line_action not in ['+', '-']: | |||
|
762 | <div class="nav-chunk" style="visibility: hidden"> | |||
|
763 | <i class="icon-eye" title="viewing diff hunk-${hunk.index}-${chunk_count}"></i> | |||
|
764 | </div> | |||
|
765 | <% chunk_count +=1 %> | |||
|
766 | % endif | |||
754 | </td> |
|
767 | </td> | |
755 | </tr> |
|
768 | </tr> | |
756 | %endfor |
|
769 | %endfor | |
@@ -903,12 +916,21 b' def get_comments_for(diff_type, comments' | |||||
903 | </div> |
|
916 | </div> | |
904 | </div> |
|
917 | </div> | |
905 | </div> |
|
918 | </div> | |
906 | <div class="fpath-placeholder"> |
|
919 | <div class="fpath-placeholder pull-left"> | |
907 | <i class="icon-file-text"></i> |
|
920 | <i class="icon-file-text"></i> | |
908 | <strong class="fpath-placeholder-text"> |
|
921 | <strong class="fpath-placeholder-text"> | |
909 | Context file: |
|
922 | Context file: | |
910 | </strong> |
|
923 | </strong> | |
911 | </div> |
|
924 | </div> | |
|
925 | <div class="pull-right noselect"> | |||
|
926 | <span id="diff_nav">Loading diff...:</span> | |||
|
927 | <span class="cursor-pointer" onclick="scrollToPrevChunk(); return false"> | |||
|
928 | <i class="icon-angle-up"></i> | |||
|
929 | </span> | |||
|
930 | <span class="cursor-pointer" onclick="scrollToNextChunk(); return false"> | |||
|
931 | <i class="icon-angle-down"></i> | |||
|
932 | </span> | |||
|
933 | </div> | |||
912 | <div class="sidebar_inner_shadow"></div> |
|
934 | <div class="sidebar_inner_shadow"></div> | |
913 | </div> |
|
935 | </div> | |
914 | </div> |
|
936 | </div> | |
@@ -1031,10 +1053,84 b' def get_comments_for(diff_type, comments' | |||||
1031 | e.preventDefault(); |
|
1053 | e.preventDefault(); | |
1032 | }); |
|
1054 | }); | |
1033 |
|
1055 | |||
|
1056 | getCurrentChunk = function () { | |||
|
1057 | ||||
|
1058 | var chunksAll = $('.nav-chunk').filter(function () { | |||
|
1059 | return $(this).parents('.filediff').prev().get(0).checked !== true | |||
|
1060 | }) | |||
|
1061 | var chunkSelected = $('.nav-chunk.selected'); | |||
|
1062 | var initial = false; | |||
|
1063 | ||||
|
1064 | if (chunkSelected.length === 0) { | |||
|
1065 | // no initial chunk selected, we pick first | |||
|
1066 | chunkSelected = $(chunksAll.get(0)); | |||
|
1067 | var initial = true; | |||
|
1068 | } | |||
|
1069 | ||||
|
1070 | return { | |||
|
1071 | 'all': chunksAll, | |||
|
1072 | 'selected': chunkSelected, | |||
|
1073 | 'initial': initial, | |||
|
1074 | } | |||
|
1075 | } | |||
|
1076 | ||||
|
1077 | animateDiffNavText = function () { | |||
|
1078 | var $diffNav = $('#diff_nav') | |||
|
1079 | ||||
|
1080 | var callback = function () { | |||
|
1081 | $diffNav.animate({'opacity': 1.00}, 200) | |||
|
1082 | }; | |||
|
1083 | $diffNav.animate({'opacity': 0.15}, 200, callback); | |||
|
1084 | } | |||
|
1085 | ||||
|
1086 | scrollToChunk = function (moveBy) { | |||
|
1087 | var chunk = getCurrentChunk(); | |||
|
1088 | var all = chunk.all | |||
|
1089 | var selected = chunk.selected | |||
|
1090 | ||||
|
1091 | var curPos = all.index(selected); | |||
|
1092 | var newPos = curPos; | |||
|
1093 | if (!chunk.initial) { | |||
|
1094 | var newPos = curPos + moveBy; | |||
|
1095 | } | |||
|
1096 | ||||
|
1097 | var curElem = all.get(newPos); | |||
|
1098 | ||||
|
1099 | if (curElem === undefined) { | |||
|
1100 | // end or back | |||
|
1101 | $('#diff_nav').html('No next diff element.') | |||
|
1102 | animateDiffNavText() | |||
|
1103 | return | |||
|
1104 | } else if (newPos < 0) { | |||
|
1105 | $('#diff_nav').html('No previous diff element.') | |||
|
1106 | animateDiffNavText() | |||
|
1107 | return | |||
|
1108 | } else { | |||
|
1109 | $('#diff_nav').html('Diff navigation:') | |||
|
1110 | } | |||
|
1111 | ||||
|
1112 | curElem = $(curElem) | |||
|
1113 | var offset = 100; | |||
|
1114 | $(window).scrollTop(curElem.position().top - offset); | |||
|
1115 | ||||
|
1116 | //clear selection | |||
|
1117 | all.removeClass('selected') | |||
|
1118 | curElem.addClass('selected') | |||
|
1119 | } | |||
|
1120 | ||||
|
1121 | scrollToPrevChunk = function () { | |||
|
1122 | scrollToChunk(-1) | |||
|
1123 | } | |||
|
1124 | scrollToNextChunk = function () { | |||
|
1125 | scrollToChunk(1) | |||
|
1126 | } | |||
|
1127 | ||||
1034 | </script> |
|
1128 | </script> | |
1035 | % endif |
|
1129 | % endif | |
1036 |
|
1130 | |||
1037 | <script type="text/javascript"> |
|
1131 | <script type="text/javascript"> | |
|
1132 | $('#diff_nav').html('loading diff...') // wait until whole page is loaded | |||
|
1133 | ||||
1038 | $(document).ready(function () { |
|
1134 | $(document).ready(function () { | |
1039 |
|
1135 | |||
1040 | var contextPrefix = _gettext('Context file: '); |
|
1136 | var contextPrefix = _gettext('Context file: '); | |
@@ -1213,6 +1309,46 b' def get_comments_for(diff_type, comments' | |||||
1213 | $('.toggle-wide-diff').addClass('btn-active'); |
|
1309 | $('.toggle-wide-diff').addClass('btn-active'); | |
1214 | updateSticky(); |
|
1310 | updateSticky(); | |
1215 | } |
|
1311 | } | |
|
1312 | ||||
|
1313 | // DIFF NAV // | |||
|
1314 | ||||
|
1315 | // element to detect scroll direction of | |||
|
1316 | var $window = $(window); | |||
|
1317 | ||||
|
1318 | // initialize last scroll position | |||
|
1319 | var lastScrollY = $window.scrollTop(); | |||
|
1320 | ||||
|
1321 | $window.on('resize scrollstop', {latency: 350}, function () { | |||
|
1322 | var visibleChunks = $('.nav-chunk').withinviewport({top: 75}); | |||
|
1323 | ||||
|
1324 | // get current scroll position | |||
|
1325 | var currentScrollY = $window.scrollTop(); | |||
|
1326 | ||||
|
1327 | // determine current scroll direction | |||
|
1328 | if (currentScrollY > lastScrollY) { | |||
|
1329 | var y = 'down' | |||
|
1330 | } else if (currentScrollY !== lastScrollY) { | |||
|
1331 | var y = 'up'; | |||
|
1332 | } | |||
|
1333 | ||||
|
1334 | var pos = -1; // by default we use last element in viewport | |||
|
1335 | if (y === 'down') { | |||
|
1336 | pos = -1; | |||
|
1337 | } else if (y === 'up') { | |||
|
1338 | pos = 0; | |||
|
1339 | } | |||
|
1340 | ||||
|
1341 | if (visibleChunks.length > 0) { | |||
|
1342 | $('.nav-chunk').removeClass('selected'); | |||
|
1343 | $(visibleChunks.get(pos)).addClass('selected'); | |||
|
1344 | } | |||
|
1345 | ||||
|
1346 | // update last scroll position to current position | |||
|
1347 | lastScrollY = currentScrollY; | |||
|
1348 | ||||
|
1349 | }); | |||
|
1350 | $('#diff_nav').html('Diff navigation:') | |||
|
1351 | ||||
1216 | }); |
|
1352 | }); | |
1217 | </script> |
|
1353 | </script> | |
1218 |
|
1354 |
General Comments 0
You need to be logged in to leave comments.
Login now