##// END OF EJS Templates
Migrate to Mergely 3.3.4....
"Bradley M. Kuhn" -
r4125:aa3b5594 rhodecode-2.2.5-gpl
parent child Browse files
Show More
@@ -0,0 +1,111 b''
1 <!DOCTYPE html>
2 <html lang="en">
3 <!--[if IE]>
4 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
5 <![endif]-->
6 <head>
7 <meta charset="utf-8" /><title>Mergely License</title>
8 <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
9 <meta name="description" content="Mergely license requirements for open source software and commercial software" />
10 <meta name="keywords" content="diff,merge,compare,compare documents,js diff,javascript diff,comparison,online diff,difference,file,text,unix,patch,algorithm,saas,longest common subsequence,diff online" />
11 <meta name="author" content="Jamie Peabody" />
12 <meta name="author" content="Jamie Peabody" />
13 <link rel="shortcut icon" href="http://www.mergely.com/favicon.ico" />
14 <link href='http://fonts.googleapis.com/css?family=Noto+Sans:400,700' rel='stylesheet' type='text/css' />
15 <link href='fonts/berlin-sans-fb-demi.css' rel='stylesheet' type='text/css' />
16 <link href='style/mergely.css' rel='stylesheet' type='text/css' />
17 <link href='/Mergely/lib/mergely.css' rel='stylesheet' type='text/css' />
18 <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
19 <script type="text/javascript">
20 var _gaq = _gaq || [];
21 _gaq.push(['_setAccount', 'UA-85576-5']);
22 _gaq.push(['_trackPageview']);
23 (function() {
24 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
25 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
26 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
27 })();
28 </script>
29 </head>
30 <body>
31 <div id="page">
32 <div id="content">
33 <div id="header">
34 <h1><span>Mergely License - Closed Distribution License</span></h1>
35 <div id="options">
36 <a href="/editor" class="button">Online Diff</a>
37 <a href="/download" class="button">Download</a>
38 </div>
39 <nav>
40 <ul>
41 <li><a href="/">Home</a></li> <li><a href="/doc">Documentation</a></li> <li><a href="/about">About Mergely</a></li> <li><a href="/license">License</a></li> <li><a href="#footer">Contact</a></li> </ul>
42 </nav>
43 </div>
44
45 <div id="main">
46 <h1>Mergely License</h1>
47 <p>
48 All Mergely code is Copyright 2014 by Jamie Peabody.
49 Mergely is distributed under the
50 <a href="http://www.gnu.org/licenses/gpl.html">GPL</a>,
51 <a href="http://www.gnu.org/licenses/lgpl.html">LGPL</a>
52 and
53 <a href="http://www.mozilla.org/MPL/MPL-1.1.html">MPL</a> open source licenses.
54 This triple <b>copyleft</b> licensing model avoids incompatibility with other open
55 source licenses. These open source licenses are specially indicated for:
56 <ul>
57 <li>Integrating Mergely into Open Source software;</li>
58 <li>Personal and educational use of Mergely;</li>
59 <li>
60 Integrating Mergely in commercial software, taking care of satisfying
61 the Open Source licenses terms, while not able or interested on supporting
62 Mergely and its development.
63 </li>
64 </ul>
65 </p>
66 <h2>Mergely Commercial License - Closed Distribution License - CDL</h2>
67 <p>
68 You may contact <a href="mailto:jamie.peabody@gmail.com">Jamie Peabody</a> to enquire about
69 obtaining a CDL license.
70 </p>
71 <p>
72 This license offers a very flexible way to integrate Mergely in your commercial
73 application. These are the main advantages it offers over an Open Source license:
74 </p>
75 <p>
76 Modifications and enhancements do not need to be released under an Open
77 Source license; There is no need to distribute any Open Source license terms
78 along with your product and no reference to it have to be done; You do not have
79 to mention any reference to Mergely in your product; Mergely source code does not
80 have to be distributed with your product; You can remove any file from Mergely
81 when integrating it with your product.
82 </p>
83 <p>
84 The CDL is a lifetime license valid for all previous releases of Mergely published
85 prior to the year of purchase, and any releases in the following year. Please select
86 the license option that best fit your needs above. It includes 1 year of
87 <b>personal e-mail support</b>.
88 </p>
89 <h2>Third party codes</h2>
90 <p>
91 Mergely utilizes <b>CodeMirror</b>, a third-party library released under an
92 <a href="http://en.wikipedia.org/wiki/MIT_License">MIT</a>
93 license. Also used is <b>jQuery</b> and is released under the
94 <a href="http://en.wikipedia.org/wiki/MIT_License">MIT</a> or
95 <a href="http://www.gnu.org/licenses/gpl.html">GPL</a> Version 2 license.
96 </p>
97 </div>
98
99 <div id="footer">
100 <a href="/download" class="download">Download</a>
101 <ul>
102 <li id="google-plus"><a target="_blank" href="http://groups.google.com/group/mergely">http://groups.google.com/group/mergely</a></li>
103 <li id="github"><a target="_blank" href="https://github.com/wickedest/Mergely">https://github.com/wickedest/Mergely</a></li>
104 <li id="email"><a target="_blank" href="mailto:jamie.peabody@gmail.com">jamie.peabody@gmail.com</a></li>
105 </ul>
106 </div>
107 </div>
108 <div id="copyright">By <b>Jamie Peabody</b></div>
109 </div>
110 </body>
111 </html>
@@ -55,4 +55,16 b' It is Copyright 2013 jQuery Foundation a'
55 55
56 56
57 57
58 Mergely
59 -------
60
61 Kallithea incorporates some code from the Javascript system called
62 [Mergely](http://http://www.mergely.com/).
63 [Mergely's license](http://www.mergely.com/license.php), a
64 [copy of which is included in this repository](LICENSE-MERGELY.html),
65 is (GPL|LGPL|MPL). Kallithea as GPLv3'd project chooses the GPL arm of that
66 tri-license.
67
68
69
58 70 EOF
@@ -1,3 +1,11 b''
1 /**
2 * Copyright (c) 2013 by Jamie Peabody, http://www.mergely.com
3 * All rights reserved.
4 * Version: 3.3.4 2013-11-02
5 *
6 * NOTE by bkuhn@sfconservancy.org for Kallithea:
7 * Mergely license appears at http://www.mergely.com/license.php and in LICENSE-MERGELY.html
8 */
1 9
2 10 /* required */
3 11 .mergely-column textarea { width: 80px; height: 200px; }
@@ -12,17 +20,17 b''
12 20 .mergely-column { border: 1px solid #ccc; }
13 21 .mergely-active { border: 1px solid #a3d1ff; }
14 22
15 .mergely.a.rhs.start { border-top: 1px solid #ddffdd; }
23 .mergely.a.rhs.start { border-top: 1px solid #a3d1ff; }
16 24 .mergely.a.lhs.start.end,
17 .mergely.a.rhs.end { border-bottom: 1px solid #ddffdd; }
18 .mergely.a.rhs { background-color: #ddffdd; }
19 .mergely.a.lhs.start.end.first { border-bottom: 0; border-top: 1px solid #ddffdd; }
25 .mergely.a.rhs.end { border-bottom: 1px solid #a3d1ff; }
26 .mergely.a.rhs { background-color: #ddeeff; }
27 .mergely.a.lhs.start.end.first { border-bottom: 0; border-top: 1px solid #a3d1ff; }
20 28
21 29 .mergely.d.lhs { background-color: #edc0c0; }
22 30 .mergely.d.lhs.end,
23 .mergely.d.rhs.start.end { border-bottom: 1px solid #ffdddd; }
24 .mergely.d.rhs.start.end.first { border-bottom: 0; border-top: 1px solid #ffdddd; }
25 .mergely.d.lhs.start { border-top: 1px solid #ffdddd; }
31 .mergely.d.rhs.start.end { border-bottom: 1px solid #ff7f7f; }
32 .mergely.d.rhs.start.end.first { border-bottom: 0; border-top: 1px solid #ff7f7f; }
33 .mergely.d.lhs.start { border-top: 1px solid #ff7f7f; }
26 34
27 35 .mergely.c.lhs,
28 36 .mergely.c.rhs { background-color: #fafafa; }
@@ -31,11 +39,5 b''
31 39 .mergely.c.lhs.end,
32 40 .mergely.c.rhs.end { border-bottom: 1px solid #a3a3a3; }
33 41
34 .mergely.ch.a.rhs { background-color: #ddffdd; }
35 .mergely.ch.d.lhs { background-color: #ffdddd; }
36
37
38 .mergely-margin #compare-lhs-margin,
39 .mergely-margin #compare-rhs-margin {
40 cursor: pointer
41 }
42 .mergely.ch.a.rhs { background-color: #ddeeff; }
43 .mergely.ch.d.lhs { background-color: #edc0c0; text-decoration: line-through; color: #888; }
@@ -1,3 +1,11 b''
1 /**
2 * Copyright (c) 2013 by Jamie Peabody, http://www.mergely.com
3 * All rights reserved.
4 * Version: 3.3.4 2013-11-02
5 *
6 * NOTE by bkuhn@sfconservancy.org for Kallithea:
7 * Mergely license appears at http://www.mergely.com/license.php and in LICENSE-MERGELY.html
8 */
1 9 Mgly = {};
2 10
3 11 Mgly.Timer = function(){
@@ -5,7 +13,7 b' Mgly.Timer = function(){'
5 13 self.start = function() { self.t0 = new Date().getTime(); }
6 14 self.stop = function() {
7 15 var t1 = new Date().getTime();
8 var d = t1 - self.t0;
16 var d = t1 - self.t0;
9 17 self.t0 = t1;
10 18 return d;
11 19 }
@@ -54,18 +62,18 b' Mgly.LCS = function(x, y) {'
54 62 jQuery.extend(Mgly.LCS.prototype, {
55 63 clear: function() { this.ready = 0; },
56 64 diff: function(added, removed) {
57 var d = new Mgly.diff(this.x, this.y, retain_lines = true, ignore_ws = false);
65 var d = new Mgly.diff(this.x, this.y, {ignorews: false});
58 66 var changes = Mgly.DiffParser(d.normal_form());
59 67 var li = 0, lj = 0;
60 68 for (var i = 0; i < changes.length; ++i) {
61 69 var change = changes[i];
62 70 if (change.op != 'a') {
63 71 // find the starting index of the line
64 li = d.lhs_lines.slice(0, change['lhs-line-from']).join(' ').length;
72 li = d.getLines('lhs').slice(0, change['lhs-line-from']).join(' ').length;
65 73 // get the index of the the span of the change
66 74 lj = change['lhs-line-to'] + 1;
67 75 // get the changed text
68 var lchange = d.lhs_lines.slice(change['lhs-line-from'], lj).join(' ');
76 var lchange = d.getLines('lhs').slice(change['lhs-line-from'], lj).join(' ');
69 77 if (change.op == 'd') lchange += ' ';// include the leading space
70 78 else if (li > 0 && change.op == 'c') li += 1; // ignore leading space if not first word
71 79 // output the changed index and text
@@ -73,11 +81,11 b' jQuery.extend(Mgly.LCS.prototype, {'
73 81 }
74 82 if (change.op != 'd') {
75 83 // find the starting index of the line
76 li = d.rhs_lines.slice(0, change['rhs-line-from']).join(' ').length;
84 li = d.getLines('lhs').slice(0, change['rhs-line-from']).join(' ').length;
77 85 // get the index of the the span of the change
78 86 lj = change['rhs-line-to'] + 1;
79 87 // get the changed text
80 var rchange = d.rhs_lines.slice(change['rhs-line-from'], lj).join(' ');
88 var rchange = d.getLines('lhs').slice(change['rhs-line-from'], lj).join(' ');
81 89 if (change.op == 'a') rchange += ' ';// include the leading space
82 90 else if (li > 0 && change.op == 'c') li += 1; // ignore leading space if not first word
83 91 // output the changed index and text
@@ -86,39 +94,83 b' jQuery.extend(Mgly.LCS.prototype, {'
86 94 }
87 95 }
88 96 });
89 Mgly.diff = function(lhs, rhs, retain_lines, ignore_ws) {
90 this.diff_codes = {};
91 this.max_code = 0;
92 var lhs_lines = lhs.split('\n');
93 var rhs_lines = rhs.split('\n');
94 if (lhs.length == 0) lhs_lines = [];
95 if (rhs.length == 0) rhs_lines = [];
97
98 Mgly.CodeifyText = function(settings) {
99 this._max_code = 0;
100 this._diff_codes = {};
101 this.ctxs = {};
102 this.options = {ignorews: false};
103 jQuery.extend(this, settings);
104 this.lhs = settings.lhs.split('\n');
105 this.rhs = settings.rhs.split('\n');
106 }
96 107
97 var lhs_data = new Object();
98 lhs_data.data = this._diff_codes(lhs_lines, ignore_ws);
99 lhs_data.modified = {};
100 lhs_data.length = Mgly.sizeOf(lhs_data.data);
108 jQuery.extend(Mgly.CodeifyText.prototype, {
109 getCodes: function(side) {
110 if (!this.ctxs.hasOwnProperty(side)) {
111 var ctx = this._diff_ctx(this[side]);
112 this.ctxs[side] = ctx;
113 ctx.codes.length = Object.keys(ctx.codes).length;
114 }
115 return this.ctxs[side].codes;
116 },
117 getLines: function(side) {
118 return this.ctxs[side].lines;
119 },
120 _diff_ctx: function(lines) {
121 var ctx = {i: 0, codes: {}, lines: lines};
122 this._codeify(lines, ctx);
123 return ctx;
124 },
125 _codeify: function(lines, ctx) {
126 var code = this._max_code;
127 for (var i = 0; i < lines.length; ++i) {
128 var line = lines[i];
129 if (this.options.ignorews) {
130 line = line.replace(/\s+/g, '');
131 }
132 var aCode = this._diff_codes[line];
133 if (aCode != undefined) {
134 ctx.codes[i] = aCode;
135 }
136 else {
137 this._max_code++;
138 this._diff_codes[line] = this._max_code;
139 ctx.codes[i] = this._max_code;
140 }
141 }
142 }
143 });
101 144
102 var rhs_data = new Object();
103 rhs_data.data = this._diff_codes(rhs_lines, ignore_ws);
104 rhs_data.modified = {};
105 rhs_data.length = Mgly.sizeOf(rhs_data.data);
106
107 var max = (lhs_data.length + rhs_data.length + 1);
145 Mgly.diff = function(lhs, rhs, options) {
146 var opts = jQuery.extend({ignorews: false}, options);
147 this.codeify = new Mgly.CodeifyText({
148 lhs: lhs,
149 rhs: rhs,
150 options: opts
151 });
152 var lhs_ctx = {
153 codes: this.codeify.getCodes('lhs'),
154 modified: {}
155 };
156 var rhs_ctx = {
157 codes: this.codeify.getCodes('rhs'),
158 modified: {}
159 };
160 var max = (lhs_ctx.codes.length + rhs_ctx.codes.length + 1);
108 161 var vector_d = Array( 2 * max + 2 );
109 162 var vector_u = Array( 2 * max + 2 );
163 this._lcs(lhs_ctx, 0, lhs_ctx.codes.length, rhs_ctx, 0, rhs_ctx.codes.length, vector_u, vector_d);
164 this._optimize(lhs_ctx);
165 this._optimize(rhs_ctx);
166 this.items = this._create_diffs(lhs_ctx, rhs_ctx);
167 };
110 168
111 this._lcs(lhs_data, 0, lhs_data.length, rhs_data, 0, rhs_data.length, vector_u, vector_d);
112 this._optimize(lhs_data);
113 this._optimize(rhs_data);
114 this.items = this._create_diffs(lhs_data, rhs_data);
115 if (retain_lines) {
116 this.lhs_lines = lhs_lines;
117 this.rhs_lines = rhs_lines;
118 }
119 };
120 169 jQuery.extend(Mgly.diff.prototype, {
121 170 changes: function() { return this.items; },
171 getLines: function(side) {
172 return this.codeify.getLines(side);
173 },
122 174 normal_form: function() {
123 175 var nf = '';
124 176 for (var index = 0; index < this.items.length; ++index) {
@@ -128,11 +180,11 b' jQuery.extend(Mgly.diff.prototype, {'
128 180 var change = 'c';
129 181 if (item.lhs_deleted_count == 0 && item.rhs_inserted_count > 0) change = 'a';
130 182 else if (item.lhs_deleted_count > 0 && item.rhs_inserted_count == 0) change = 'd';
131
183
132 184 if (item.lhs_deleted_count == 1) lhs_str = item.lhs_start + 1;
133 185 else if (item.lhs_deleted_count == 0) lhs_str = item.lhs_start;
134 186 else lhs_str = (item.lhs_start + 1) + ',' + (item.lhs_start + item.lhs_deleted_count);
135
187
136 188 if (item.rhs_inserted_count == 1) rhs_str = item.rhs_start + 1;
137 189 else if (item.rhs_inserted_count == 0) rhs_str = item.rhs_start;
138 190 else rhs_str = (item.rhs_start + 1) + ',' + (item.rhs_start + item.rhs_inserted_count);
@@ -150,53 +202,33 b' jQuery.extend(Mgly.diff.prototype, {'
150 202 }
151 203 return nf;
152 204 },
153 _diff_codes: function(lines, ignore_ws) {
154 var code = this.max_code;
155 var codes = {};
156 for (var i = 0; i < lines.length; ++i) {
157 var line = lines[i];
158 if (ignore_ws) {
159 line = line.replace(/\s+/g, '');
160 }
161 var aCode = this.diff_codes[line];
162 if (aCode != undefined) {
163 codes[i] = aCode;
164 }
165 else {
166 this.max_code++;
167 this.diff_codes[line] = this.max_code;
168 codes[i] = this.max_code;
169 }
170 }
171 return codes;
172 },
173 _lcs: function(lhs, lhs_lower, lhs_upper, rhs, rhs_lower, rhs_upper, vector_u, vector_d) {
174 while ( (lhs_lower < lhs_upper) && (rhs_lower < rhs_upper) && (lhs.data[lhs_lower] == rhs.data[rhs_lower]) ) {
205 _lcs: function(lhs_ctx, lhs_lower, lhs_upper, rhs_ctx, rhs_lower, rhs_upper, vector_u, vector_d) {
206 while ( (lhs_lower < lhs_upper) && (rhs_lower < rhs_upper) && (lhs_ctx.codes[lhs_lower] == rhs_ctx.codes[rhs_lower]) ) {
175 207 ++lhs_lower;
176 208 ++rhs_lower;
177 209 }
178 while ( (lhs_lower < lhs_upper) && (rhs_lower < rhs_upper) && (lhs.data[lhs_upper - 1] == rhs.data[rhs_upper - 1]) ) {
210 while ( (lhs_lower < lhs_upper) && (rhs_lower < rhs_upper) && (lhs_ctx.codes[lhs_upper - 1] == rhs_ctx.codes[rhs_upper - 1]) ) {
179 211 --lhs_upper;
180 212 --rhs_upper;
181 213 }
182 214 if (lhs_lower == lhs_upper) {
183 215 while (rhs_lower < rhs_upper) {
184 rhs.modified[ rhs_lower++ ] = true;
216 rhs_ctx.modified[ rhs_lower++ ] = true;
185 217 }
186 218 }
187 219 else if (rhs_lower == rhs_upper) {
188 220 while (lhs_lower < lhs_upper) {
189 lhs.modified[ lhs_lower++ ] = true;
221 lhs_ctx.modified[ lhs_lower++ ] = true;
190 222 }
191 223 }
192 224 else {
193 var sms = this._sms(lhs, lhs_lower, lhs_upper, rhs, rhs_lower, rhs_upper, vector_u, vector_d);
194 this._lcs(lhs, lhs_lower, sms.x, rhs, rhs_lower, sms.y, vector_u, vector_d);
195 this._lcs(lhs, sms.x, lhs_upper, rhs, sms.y, rhs_upper, vector_u, vector_d);
225 var sms = this._sms(lhs_ctx, lhs_lower, lhs_upper, rhs_ctx, rhs_lower, rhs_upper, vector_u, vector_d);
226 this._lcs(lhs_ctx, lhs_lower, sms.x, rhs_ctx, rhs_lower, sms.y, vector_u, vector_d);
227 this._lcs(lhs_ctx, sms.x, lhs_upper, rhs_ctx, sms.y, rhs_upper, vector_u, vector_d);
196 228 }
197 229 },
198 _sms: function(lhs, lhs_lower, lhs_upper, rhs, rhs_lower, rhs_upper, vector_u, vector_d) {
199 var max = lhs.length + rhs.length + 1;
230 _sms: function(lhs_ctx, lhs_lower, lhs_upper, rhs_ctx, rhs_lower, rhs_upper, vector_u, vector_d) {
231 var max = lhs_ctx.codes.length + rhs_ctx.codes.length + 1;
200 232 var kdown = lhs_lower - rhs_lower;
201 233 var kup = lhs_upper - rhs_upper;
202 234 var delta = (lhs_upper - lhs_lower) - (rhs_upper - rhs_lower);
@@ -221,7 +253,7 b' jQuery.extend(Mgly.diff.prototype, {'
221 253 }
222 254 y = x - k;
223 255 // find the end of the furthest reaching forward D-path in diagonal k.
224 while ((x < lhs_upper) && (y < rhs_upper) && (lhs.data[x] == rhs.data[y])) {
256 while ((x < lhs_upper) && (y < rhs_upper) && (lhs_ctx.codes[x] == rhs_ctx.codes[y])) {
225 257 x++; y++;
226 258 }
227 259 vector_d[ offset_down + k ] = x;
@@ -246,7 +278,7 b' jQuery.extend(Mgly.diff.prototype, {'
246 278 x = vector_u[offset_up + k - 1]; // up
247 279 }
248 280 y = x - k;
249 while ((x > lhs_lower) && (y > rhs_lower) && (lhs.data[x - 1] == rhs.data[y - 1])) {
281 while ((x > lhs_lower) && (y > rhs_lower) && (lhs_ctx.codes[x - 1] == rhs_ctx.codes[y - 1])) {
250 282 // diagonal
251 283 x--;
252 284 y--;
@@ -264,33 +296,33 b' jQuery.extend(Mgly.diff.prototype, {'
264 296 }
265 297 throw "the algorithm should never come here.";
266 298 },
267 _optimize: function(data) {
299 _optimize: function(ctx) {
268 300 var start = 0, end = 0;
269 while (start < data.length) {
270 while ((start < data.length) && (data.modified[start] == undefined || data.modified[start] == false)) {
301 while (start < ctx.length) {
302 while ((start < ctx.length) && (ctx.modified[start] == undefined || ctx.modified[start] == false)) {
271 303 start++;
272 304 }
273 305 end = start;
274 while ((end < data.length) && (data.modified[end] == true)) {
306 while ((end < ctx.length) && (ctx.modified[end] == true)) {
275 307 end++;
276 308 }
277 if ((end < data.length) && (data.data[start] == data.data[end])) {
278 data.modified[start] = false;
279 data.modified[end] = true;
309 if ((end < ctx.length) && (ctx.ctx[start] == ctx.codes[end])) {
310 ctx.modified[start] = false;
311 ctx.modified[end] = true;
280 312 }
281 313 else {
282 314 start = end;
283 315 }
284 316 }
285 317 },
286 _create_diffs: function(lhs_data, rhs_data) {
318 _create_diffs: function(lhs_ctx, rhs_ctx) {
287 319 var items = [];
288 320 var lhs_start = 0, rhs_start = 0;
289 321 var lhs_line = 0, rhs_line = 0;
290 322
291 while (lhs_line < lhs_data.length || rhs_line < rhs_data.length) {
292 if ((lhs_line < lhs_data.length) && (!lhs_data.modified[lhs_line])
293 && (rhs_line < rhs_data.length) && (!rhs_data.modified[rhs_line])) {
323 while (lhs_line < lhs_ctx.codes.length || rhs_line < rhs_ctx.codes.length) {
324 if ((lhs_line < lhs_ctx.codes.length) && (!lhs_ctx.modified[lhs_line])
325 && (rhs_line < rhs_ctx.codes.length) && (!rhs_ctx.modified[rhs_line])) {
294 326 // equal lines
295 327 lhs_line++;
296 328 rhs_line++;
@@ -300,20 +332,20 b' jQuery.extend(Mgly.diff.prototype, {'
300 332 lhs_start = lhs_line;
301 333 rhs_start = rhs_line;
302 334
303 while (lhs_line < lhs_data.length && (rhs_line >= rhs_data.length || lhs_data.modified[lhs_line]))
335 while (lhs_line < lhs_ctx.codes.length && (rhs_line >= rhs_ctx.codes.length || lhs_ctx.modified[lhs_line]))
304 336 lhs_line++;
305 337
306 while (rhs_line < rhs_data.length && (lhs_line >= lhs_data.length || rhs_data.modified[rhs_line]))
338 while (rhs_line < rhs_ctx.codes.length && (lhs_line >= lhs_ctx.codes.length || rhs_ctx.modified[rhs_line]))
307 339 rhs_line++;
308 340
309 341 if ((lhs_start < lhs_line) || (rhs_start < rhs_line)) {
310 342 // store a new difference-item
311 var aItem = new Object();
312 aItem.lhs_start = lhs_start;
313 aItem.rhs_start = rhs_start;
314 aItem.lhs_deleted_count = lhs_line - lhs_start;
315 aItem.rhs_inserted_count = rhs_line - rhs_start;
316 items.push(aItem);
343 items.push({
344 lhs_start: lhs_start,
345 rhs_start: rhs_start,
346 lhs_deleted_count: lhs_line - lhs_start,
347 rhs_inserted_count: rhs_line - rhs_start
348 });
317 349 }
318 350 }
319 351 }
@@ -322,12 +354,6 b' jQuery.extend(Mgly.diff.prototype, {'
322 354 });
323 355
324 356 Mgly.mergely = function(el, options) {
325 CodeMirror.defineExtension('centerOnCursor', function() {
326 var coords = this.cursorCoords(null, 'local');
327 this.scrollTo(null,
328 (coords.y + coords.yBot) / 2 - (this.getScrollerElement().clientHeight / 2));
329 });
330
331 357 if (el) {
332 358 this.init(el, options);
333 359 }
@@ -337,6 +363,25 b' jQuery.extend(Mgly.mergely.prototype, {'
337 363 name: 'mergely',
338 364 //http://jupiterjs.com/news/writing-the-perfect-jquery-plugin
339 365 init: function(el, options) {
366 this.diffView = new Mgly.CodeMirrorDiffView(el, options);
367 this.bind(el);
368 },
369 bind: function(el) {
370 this.diffView.bind(el);
371 }
372 });
373
374 Mgly.CodeMirrorDiffView = function(el, options) {
375 CodeMirror.defineExtension('centerOnCursor', function() {
376 var coords = this.cursorCoords(null, 'local');
377 this.scrollTo(null,
378 (coords.y + coords.yBot) / 2 - (this.getScrollerElement().clientHeight / 2));
379 });
380 this.init(el, options);
381 };
382
383 jQuery.extend(Mgly.CodeMirrorDiffView.prototype, {
384 init: function(el, options) {
340 385 this.settings = {
341 386 autoupdate: true,
342 387 autoresize: true,
@@ -352,14 +397,14 b' jQuery.extend(Mgly.mergely.prototype, {'
352 397 change_timeout: 150,
353 398 fgcolor: {a:'#4ba3fa',c:'#a3a3a3',d:'#ff7f7f'},
354 399 bgcolor: '#eee',
355 vpcolor: 'rgba(0, 0, 200, 0.2)',
400 vpcolor: 'rgba(0, 0, 200, 0.5)',
356 401 lhs: function(setValue) { },
357 402 rhs: function(setValue) { },
358 403 loaded: function() { },
359 404 //_auto_height: function(h) { return h - 20; },
360 405 _auto_width: function(w) { return w; },
361 406 resize: function(init) {
362 var scrollbar = init ? -15 : 0;
407 var scrollbar = init ? 16 : 0;
363 408 var w = jQuery(el).parent().width() + scrollbar;
364 409 if (this.width == 'auto') {
365 410 w = this._auto_width(w);
@@ -403,65 +448,20 b' jQuery.extend(Mgly.mergely.prototype, {'
403 448 }
404 449 this.lhs_cmsettings = {};
405 450 this.rhs_cmsettings = {};
406
451
407 452 // save this element for faster queries
408 453 this.element = jQuery(el);
409
454
410 455 // save options if there are any
411 456 if (options && options.cmsettings) jQuery.extend(this.lhs_cmsettings, cmsettings, options.cmsettings, options.lhs_cmsettings);
412 457 if (options && options.cmsettings) jQuery.extend(this.rhs_cmsettings, cmsettings, options.cmsettings, options.rhs_cmsettings);
413 458 if (options) jQuery.extend(this.settings, options);
414
459
415 460 // bind if the element is destroyed
416 461 this.element.bind('destroyed', jQuery.proxy(this.teardown, this));
417 462
418 // save this instance in jQuery data
419 jQuery.data(el, this.name, this);
420
421 this._setup(el);
422 },
423 // bind events to this instance's methods
424 bind: function() {
425 var rhstx = jQuery('#' + this.id + '-rhs').get(0);
426 if (!rhstx) {
427 console.error('rhs textarea not defined - Mergely not initialized properly');
428 return;
429 }
430 var lhstx = jQuery('#' + this.id + '-lhs').get(0);
431 if (!rhstx) {
432 console.error('lhs textarea not defined - Mergely not initialized properly');
433 return;
434 }
435 var self = this;
436 this.editor = [];
437
438 this.editor[this.id + '-lhs'] = CodeMirror.fromTextArea(lhstx, this.lhs_cmsettings);
439 this.editor[this.id + '-rhs'] = CodeMirror.fromTextArea(rhstx, this.rhs_cmsettings);
440 this.editor[this.id + '-lhs'].on('change', function(){ if (self.settings.autoupdate) self._changing(self.id + '-lhs', self.id + '-rhs'); });
441 this.editor[this.id + '-lhs'].on('scroll', function(){ self._scrolling(self.id + '-lhs'); });
442 this.editor[this.id + '-rhs'].on('change', function(){ if (self.settings.autoupdate) self._changing(self.id + '-lhs', self.id + '-rhs'); });
443 this.editor[this.id + '-rhs'].on('scroll', function(){ self._scrolling(self.id + '-rhs'); });
444
445 // resize
446 if (this.settings.autoresize) {
447 var sz_timeout1 = null;
448 var sz = function(init) {
449 //self.em_height = null; //recalculate
450 if (self.settings.resize) self.settings.resize(init);
451 self.editor[self.id + '-lhs'].refresh();
452 self.editor[self.id + '-rhs'].refresh();
453 if (self.settings.autoupdate) {
454 self._changing(self.id + '-lhs', self.id + '-rhs');
455 }
456 }
457 jQuery(window).resize(
458 function () {
459 if (sz_timeout1) clearTimeout(sz_timeout1);
460 sz_timeout1 = setTimeout(sz, self.settings.resize_timeout);
461 }
462 );
463 sz(true);
464 }
463 // save this instance in jQuery data, binding this view to the node
464 jQuery.data(el, 'mergely', this);
465 465 },
466 466 unbind: function() {
467 467 if (this.changed_timeout != null) clearTimeout(this.changed_timeout);
@@ -502,11 +502,11 b' jQuery.extend(Mgly.mergely.prototype, {'
502 502 options: function(opts) {
503 503 if (opts) {
504 504 jQuery.extend(this.settings, opts);
505 if (opts.autoresize) this.resize();
506 if (opts.autoupdate) this.update();
507 if (opts.hasOwnProperty('rhs_margin')) {
505 if (this.settings.autoresize) this.resize();
506 if (this.settings.autoupdate) this.update();
507 if (this.settings.hasOwnProperty('rhs_margin')) {
508 508 // dynamically swap the margin
509 if (opts.rhs_margin == 'left') {
509 if (this.settings.rhs_margin == 'left') {
510 510 this.element.find('.mergely-margin:last-child').insertAfter(
511 511 this.element.find('.mergely-canvas'));
512 512 }
@@ -515,9 +515,9 b' jQuery.extend(Mgly.mergely.prototype, {'
515 515 target.appendTo(target.parent());
516 516 }
517 517 }
518 if (opts.hasOwnProperty('sidebar')) {
518 if (this.settings.hasOwnProperty('sidebar')) {
519 519 // dynamically enable sidebars
520 if (opts.sidebar) {
520 if (this.settings.sidebar) {
521 521 jQuery(this.element).find('.mergely-margin').css({display: 'block'});
522 522 }
523 523 else {
@@ -570,7 +570,7 b' jQuery.extend(Mgly.mergely.prototype, {'
570 570 this.prev_query[side] = query;
571 571 }
572 572 var cursor = this.cursor[this.id];
573
573
574 574 if (cursor[direction]()) {
575 575 editor.setSelection(cursor.from(), cursor.to());
576 576 }
@@ -581,14 +581,15 b' jQuery.extend(Mgly.mergely.prototype, {'
581 581 resize: function() {
582 582 this.settings.resize();
583 583 this._changing(this.id + '-lhs', this.id + '-rhs');
584 this._set_top_offset(this.id + '-lhs');
584 585 },
585 586 diff: function() {
586 587 var lhs = this.editor[this.id + '-lhs'].getValue();
587 588 var rhs = this.editor[this.id + '-rhs'].getValue();
588 var d = new Mgly.diff(lhs, rhs, retain_lines = true, ignore_ws = this.settings.ignorews);
589 var d = new Mgly.diff(lhs, rhs, this.settings);
589 590 return d.normal_form();
590 591 },
591 _setup: function(el) {
592 bind: function(el) {
592 593 jQuery(this.element).hide();//hide
593 594 this.id = jQuery(el).attr('id');
594 595 var height = this.settings.editor_height;
@@ -616,7 +617,7 b' jQuery.extend(Mgly.mergely.prototype, {'
616 617 }
617 618 this.merge_rhs_button = jQuery(merge_rhs_button);
618 619 this.merge_lhs_button = jQuery(merge_lhs_button);
619
620
620 621 // create the textarea and canvas elements
621 622 jQuery(this.element).append(jQuery('<div class="mergely-margin" style="height: ' + height + '"><canvas id="' + this.id + '-lhs-margin" width="8px" height="' + height + '"></canvas></div>'));
622 623 jQuery(this.element).append(jQuery('<div style="position:relative;width:' + width + '; height:' + height + '" id="' + this.id + '-editor-lhs" class="mergely-column"><textarea style="" id="' + this.id + '-lhs"></textarea></div>'));
@@ -640,7 +641,48 b' jQuery.extend(Mgly.mergely.prototype, {'
640 641 cmstyle += this.id + ' .CodeMirror-scroll { height: 100%; overflow: auto; }';
641 642 }
642 643 jQuery('<style type="text/css">' + cmstyle + '</style>').appendTo('head');
643 this.bind();
644
645 //bind
646 var rhstx = jQuery('#' + this.id + '-rhs').get(0);
647 if (!rhstx) {
648 console.error('rhs textarea not defined - Mergely not initialized properly');
649 return;
650 }
651 var lhstx = jQuery('#' + this.id + '-lhs').get(0);
652 if (!rhstx) {
653 console.error('lhs textarea not defined - Mergely not initialized properly');
654 return;
655 }
656 var self = this;
657 this.editor = [];
658 this.editor[this.id + '-lhs'] = CodeMirror.fromTextArea(lhstx, this.lhs_cmsettings);
659 this.editor[this.id + '-rhs'] = CodeMirror.fromTextArea(rhstx, this.rhs_cmsettings);
660 this.editor[this.id + '-lhs'].on('change', function(){ if (self.settings.autoupdate) self._changing(self.id + '-lhs', self.id + '-rhs'); });
661 this.editor[this.id + '-lhs'].on('scroll', function(){ self._scrolling(self.id + '-lhs'); });
662 this.editor[this.id + '-rhs'].on('change', function(){ if (self.settings.autoupdate) self._changing(self.id + '-lhs', self.id + '-rhs'); });
663 this.editor[this.id + '-rhs'].on('scroll', function(){ self._scrolling(self.id + '-rhs'); });
664 // resize
665 if (this.settings.autoresize) {
666 var sz_timeout1 = null;
667 var sz = function(init) {
668 //self.em_height = null; //recalculate
669 if (self.settings.resize) self.settings.resize(init);
670 self.editor[self.id + '-lhs'].refresh();
671 self.editor[self.id + '-rhs'].refresh();
672 if (self.settings.autoupdate) {
673 self._changing(self.id + '-lhs', self.id + '-rhs');
674 }
675 }
676 jQuery(window).resize(
677 function () {
678 if (sz_timeout1) clearTimeout(sz_timeout1);
679 sz_timeout1 = setTimeout(sz, self.settings.resize_timeout);
680 }
681 );
682 sz(true);
683 }
684 //bind
685
644 686 if (this.settings.lhs) {
645 687 var setv = this.editor[this.id + '-lhs'].getDoc().setValue;
646 688 this.settings.lhs(setv.bind(this.editor[this.id + '-lhs'].getDoc()));
@@ -650,7 +692,7 b' jQuery.extend(Mgly.mergely.prototype, {'
650 692 this.settings.rhs(setv.bind(this.editor[this.id + '-rhs'].getDoc()));
651 693 }
652 694 },
653
695
654 696 _scrolling: function(editor_name) {
655 697 if (this._skipscroll[editor_name] === true) {
656 698 // scrolling one side causes the other to event - ignore it
@@ -665,23 +707,23 b' jQuery.extend(Mgly.mergely.prototype, {'
665 707 var midline = this.editor[editor_name].coordsChar({left:0, top:this.midway});
666 708 var top_to = scroller.scrollTop();
667 709 var left_to = scroller.scrollLeft();
668
710
669 711 this.trace('scroll', 'side', editor_name);
670 712 this.trace('scroll', 'midway', this.midway);
671 713 this.trace('scroll', 'midline', midline);
672 714 this.trace('scroll', 'top_to', top_to);
673 715 this.trace('scroll', 'left_to', left_to);
674
716
675 717 var editor_name1 = this.id + '-lhs';
676 718 var editor_name2 = this.id + '-rhs';
677
719
678 720 for (var name in this.editor) {
679 721 if (!this.editor.hasOwnProperty(name)) continue;
680 722 if (editor_name == name) continue; //same editor
681 723 var this_side = editor_name.replace(this.id + '-', '');
682 724 var other_side = name.replace(this.id + '-', '');
683 725 var top_adjust = 0;
684
726
685 727 // find the last change that is less than or within the midway point
686 728 // do not move the rhs until the lhs end point is >= the rhs end point.
687 729 var last_change = null;
@@ -699,14 +741,14 b' jQuery.extend(Mgly.mergely.prototype, {'
699 741 force_scroll = true;
700 742 }
701 743 else {
702 top_adjust +=
703 (change[this_side+'-y-end'] - change[this_side+'-y-start']) -
744 top_adjust +=
745 (change[this_side+'-y-end'] - change[this_side+'-y-start']) -
704 746 (change[other_side+'-y-end'] - change[other_side+'-y-start']);
705 747 }
706 748 }
707 749 }
708 750 }
709
751
710 752 var vp = this.editor[name].getViewport();
711 753 var scroll = true;
712 754 if (last_change) {
@@ -724,7 +766,7 b' jQuery.extend(Mgly.mergely.prototype, {'
724 766 scroller.scrollTop(top_to - top_adjust).scrollLeft(left_to);
725 767 }
726 768 else this.trace('scroll', 'not scrolling other side');
727
769
728 770 if (this.settings.autoupdate) {
729 771 var timer = new Mgly.Timer();
730 772 this._calculate_offsets(editor_name1, editor_name2, this.changes);
@@ -777,12 +819,12 b' jQuery.extend(Mgly.mergely.prototype, {'
777 819 });
778 820 }
779 821 self.chfns[name] = [];
780
822
781 823 var ex = this._draw_info(this.id + '-lhs', this.id + '-rhs');
782 824 var ctx_lhs = ex.clhs.get(0).getContext('2d');
783 825 var ctx_rhs = ex.crhs.get(0).getContext('2d');
784 826 var ctx = ex.dcanvas.getContext('2d');
785
827
786 828 ctx_lhs.beginPath();
787 829 ctx_lhs.fillStyle = this.settings.bgcolor;
788 830 ctx_lhs.strokeStyle = '#888';
@@ -794,7 +836,7 b' jQuery.extend(Mgly.mergely.prototype, {'
794 836 ctx_rhs.strokeStyle = '#888';
795 837 ctx_rhs.fillRect(0, 0, 6.5, ex.visible_page_height);
796 838 ctx_rhs.strokeRect(0, 0, 6.5, ex.visible_page_height);
797
839
798 840 ctx.beginPath();
799 841 ctx.fillStyle = '#fff';
800 842 ctx.fillRect(0, 0, this.draw_mid_width, ex.visible_page_height);
@@ -803,7 +845,7 b' jQuery.extend(Mgly.mergely.prototype, {'
803 845 var lhs = this.editor[editor_name1].getValue();
804 846 var rhs = this.editor[editor_name2].getValue();
805 847 var timer = new Mgly.Timer();
806 var d = new Mgly.diff(lhs, rhs, false, this.settings.ignorews);
848 var d = new Mgly.diff(lhs, rhs, this.settings);
807 849 this.trace('change', 'diff time', timer.stop());
808 850 this.changes = Mgly.DiffParser(d.normal_form());
809 851 this.trace('change', 'parse time', timer.stop());
@@ -861,13 +903,27 b' jQuery.extend(Mgly.mergely.prototype, {'
861 903 }
862 904 return true;
863 905 },
906 _set_top_offset: function (editor_name1) {
907 // save the current scroll position of the editor
908 var saveY = this.editor[editor_name1].getScrollInfo().top;
909 // temporarily scroll to top
910 this.editor[editor_name1].scrollTo(null, 0);
911
912 // this is the distance from the top of the screen to the top of the
913 // content of the first codemirror editor
914 var topnode = jQuery('#' + this.id + ' .CodeMirror-measure').first();
915 var top_offset = topnode.offset().top - 4;
916 if(!top_offset) return false;
917
918 // restore editor's scroll position
919 this.editor[editor_name1].scrollTo(null, saveY);
920
921 this.draw_top_offset = 0.5 - top_offset;
922 return true;
923 },
864 924 _calculate_offsets: function (editor_name1, editor_name2, changes) {
865 925 if (this.em_height == null) {
866 // this is the distance from the top of the screen
867 var topnode = jQuery('#' + this.id + ' .CodeMirror-measure').first();
868 var top_offset = topnode.offset().top - 4;
869 if (!top_offset) return;//try again
870 this.draw_top_offset = 0.5 - top_offset;
926 if(!this._set_top_offset(editor_name1)) return; //try again
871 927 this.em_height = this.editor[editor_name1].defaultTextHeight();
872 928 if (!this.em_height) {
873 929 console.warn('Failed to calculate offsets, using 18 by default');
@@ -886,15 +942,15 b' jQuery.extend(Mgly.mergely.prototype, {'
886 942 this.draw_rhs_max = this.draw_mid_width - 0.5; //24.5;
887 943 this.draw_lhs_width = 5;
888 944 this.draw_rhs_width = 5;
889 this.trace('calc', 'change offsets calculated', {top_offset: top_offset, lhs_min: this.draw_lhs_min, rhs_max: this.draw_rhs_max, lhs_width: this.draw_lhs_width, rhs_width: this.draw_rhs_width});
945 this.trace('calc', 'change offsets calculated', {top_offset: this.draw_top_offset, lhs_min: this.draw_lhs_min, rhs_max: this.draw_rhs_max, lhs_width: this.draw_lhs_width, rhs_width: this.draw_rhs_width});
890 946 }
891 947 var lhschc = this.editor[editor_name1].charCoords({line: 0});
892 948 var rhschc = this.editor[editor_name2].charCoords({line: 0});
893 949 var vp = this._get_viewport(editor_name1, editor_name2);
894
950
895 951 for (var i = 0; i < changes.length; ++i) {
896 952 var change = changes[i];
897
953
898 954 if (!this.settings.sidebar && !this._is_change_in_view(vp, change)) {
899 955 // if the change is outside the viewport, skip
900 956 delete change['lhs-y-start'];
@@ -907,7 +963,7 b' jQuery.extend(Mgly.mergely.prototype, {'
907 963 var llt = change['lhs-line-to'] >= 0 ? change['lhs-line-to'] : 0;
908 964 var rlf = change['rhs-line-from'] >= 0 ? change['rhs-line-from'] : 0;
909 965 var rlt = change['rhs-line-to'] >= 0 ? change['rhs-line-to'] : 0;
910
966
911 967 var ls, le, rs, re;
912 968 if (this.editor[editor_name1].getOption('lineWrapping') || this.editor[editor_name1].getOption('lineWrapping')) {
913 969 // If using line-wrapping, we must get the height of the line
@@ -918,7 +974,7 b' jQuery.extend(Mgly.mergely.prototype, {'
918 974 var tle = this.editor[editor_name1].cursorCoords({line: llt, ch: 0}, 'page');
919 975 var lhseh = this.editor[editor_name1].getLineHandle(llt);
920 976 le = { top: tle.top, bottom: tle.top + lhseh.height };
921
977
922 978 var tls = this.editor[editor_name2].cursorCoords({line: rlf, ch: 0}, 'page');
923 979 var rhssh = this.editor[editor_name2].getLineHandle(rlf);
924 980 rs = { top: tls.top, bottom: tls.top + rhssh.height };
@@ -929,24 +985,24 b' jQuery.extend(Mgly.mergely.prototype, {'
929 985 }
930 986 else {
931 987 // If not using line-wrapping, we can calculate the line position
932 ls = {
933 top: lhschc.top + llf * this.em_height,
988 ls = {
989 top: lhschc.top + llf * this.em_height,
934 990 bottom: lhschc.bottom + llf * this.em_height + 2
935 991 };
936 992 le = {
937 top: lhschc.top + llt * this.em_height,
993 top: lhschc.top + llt * this.em_height,
938 994 bottom: lhschc.bottom + llt * this.em_height + 2
939 995 };
940 996 rs = {
941 top: rhschc.top + rlf * this.em_height,
997 top: rhschc.top + rlf * this.em_height,
942 998 bottom: rhschc.bottom + rlf * this.em_height + 2
943 999 };
944 1000 re = {
945 top: rhschc.top + rlt * this.em_height,
1001 top: rhschc.top + rlt * this.em_height,
946 1002 bottom: rhschc.bottom + rlt * this.em_height + 2
947 1003 };
948 1004 }
949
1005
950 1006 if (change['op'] == 'a') {
951 1007 // adds (right), normally start from the end of the lhs,
952 1008 // except for the case when the start of the rhs is 0
@@ -985,7 +1041,7 b' jQuery.extend(Mgly.mergely.prototype, {'
985 1041 },
986 1042 _markup_changes: function (editor_name1, editor_name2, changes) {
987 1043 jQuery('.merge-button').remove(); // clear
988
1044
989 1045 var self = this;
990 1046 var led = this.editor[editor_name1];
991 1047 var red = this.editor[editor_name2];
@@ -998,11 +1054,11 b' jQuery.extend(Mgly.mergely.prototype, {'
998 1054 var llt = change['lhs-line-to'] >= 0 ? change['lhs-line-to'] : 0;
999 1055 var rlf = change['rhs-line-from'] >= 0 ? change['rhs-line-from'] : 0;
1000 1056 var rlt = change['rhs-line-to'] >= 0 ? change['rhs-line-to'] : 0;
1001
1057
1002 1058 var clazz = ['mergely', 'lhs', change['op'], 'cid-' + i];
1003 1059 led.addLineClass(llf, 'background', 'start');
1004 1060 led.addLineClass(llt, 'background', 'end');
1005
1061
1006 1062 if (llf == 0 && llt == 0 && rlf == 0) {
1007 1063 led.addLineClass(llf, 'background', clazz.join(' '));
1008 1064 led.addLineClass(llf, 'background', 'first');
@@ -1014,7 +1070,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1014 1070 led.addLineClass(j, 'background', clazz.join(' '));
1015 1071 }
1016 1072 }
1017
1073
1018 1074 if (!red.getOption('readOnly')) {
1019 1075 // add widgets to lhs, if rhs is not read only
1020 1076 var rhs_button = self.merge_rhs_button.clone();
@@ -1030,7 +1086,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1030 1086 });
1031 1087
1032 1088 var vp = this._get_viewport(editor_name1, editor_name2);
1033
1089
1034 1090 this.trace('change', 'markup lhs-editor time', timer.stop());
1035 1091 red.operation(function() {
1036 1092 for (var i = 0; i < changes.length; ++i) {
@@ -1039,16 +1095,16 b' jQuery.extend(Mgly.mergely.prototype, {'
1039 1095 var llt = change['lhs-line-to'] >= 0 ? change['lhs-line-to'] : 0;
1040 1096 var rlf = change['rhs-line-from'] >= 0 ? change['rhs-line-from'] : 0;
1041 1097 var rlt = change['rhs-line-to'] >= 0 ? change['rhs-line-to'] : 0;
1042
1098
1043 1099 if (!self._is_change_in_view(vp, change)) {
1044 1100 // if the change is outside the viewport, skip
1045 1101 continue;
1046 1102 }
1047
1103
1048 1104 var clazz = ['mergely', 'rhs', change['op'], 'cid-' + i];
1049 1105 red.addLineClass(rlf, 'background', 'start');
1050 1106 red.addLineClass(rlt, 'background', 'end');
1051
1107
1052 1108 if (rlf == 0 && rlt == 0 && llf == 0) {
1053 1109 red.addLineClass(rlf, 'background', clazz.join(' '));
1054 1110 red.addLineClass(rlf, 'background', 'first');
@@ -1075,7 +1131,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1075 1131 }
1076 1132 });
1077 1133 this.trace('change', 'markup rhs-editor time', timer.stop());
1078
1134
1079 1135 // mark text deleted, LCS changes
1080 1136 var marktext = [];
1081 1137 for (var i = 0; this.settings.lcs && i < changes.length; ++i) {
@@ -1084,7 +1140,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1084 1140 var llt = change['lhs-line-to'] >= 0 ? change['lhs-line-to'] : 0;
1085 1141 var rlf = change['rhs-line-from'] >= 0 ? change['rhs-line-from'] : 0;
1086 1142 var rlt = change['rhs-line-to'] >= 0 ? change['rhs-line-to'] : 0;
1087
1143
1088 1144 if (!this._is_change_in_view(vp, change)) {
1089 1145 // if the change is outside the viewport, skip
1090 1146 continue;
@@ -1100,7 +1156,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1100 1156 }
1101 1157 else if (change['op'] == 'c') {
1102 1158 // apply LCS changes to each line
1103 for (var j = llf, k = rlf, p = 0;
1159 for (var j = llf, k = rlf, p = 0;
1104 1160 ((j >= 0) && (j <= llt)) || ((k >= 0) && (k <= rlt));
1105 1161 ++j, ++k) {
1106 1162 if (k + p > rlt) {
@@ -1121,7 +1177,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1121 1177 var lhs_stop = { line: -1, ch: -1 };
1122 1178 var rhs_start = { line: -1, ch: -1 };
1123 1179 var rhs_stop = { line: -1, ch: -1 };
1124
1180
1125 1181 var lcs = new Mgly.LCS(lhs_line, rhs_line);
1126 1182 lcs.diff(
1127 1183 function (from, to) {//added
@@ -1135,7 +1191,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1135 1191 }
1136 1192 }
1137 1193 this.trace('change', 'LCS marktext time', timer.stop());
1138
1194
1139 1195 // mark changes outside closure
1140 1196 led.operation(function() {
1141 1197 // apply lhs markup
@@ -1154,7 +1210,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1154 1210 }
1155 1211 });
1156 1212 this.trace('change', 'LCS markup time', timer.stop());
1157
1213
1158 1214 // merge buttons
1159 1215 var ed = {lhs:led, rhs:red};
1160 1216 jQuery('.merge-button').on('click', function(ev){
@@ -1180,11 +1236,11 b' jQuery.extend(Mgly.mergely.prototype, {'
1180 1236 var change = self.changes[cid];
1181 1237
1182 1238 var line = {lhs: ed['lhs'].lineInfo(llt), rhs: ed['rhs'].lineInfo(rlt)};
1183
1239
1184 1240 var text = ed[side].getRange(
1185 1241 CodeMirror.Pos(change[side + '-line-from'], 0),
1186 1242 CodeMirror.Pos(change[side + '-line-to'] + 1, 0));
1187
1243
1188 1244 if (change['op'] == 'c') {
1189 1245 ed[oside].replaceRange(text,
1190 1246 CodeMirror.Pos(change[oside + '-line-from'], 0),
@@ -1260,14 +1316,14 b' jQuery.extend(Mgly.mergely.prototype, {'
1260 1316 this.trace('draw', 'visible_page_ratio', ex.visible_page_ratio);
1261 1317 this.trace('draw', 'lhs-scroller-top', ex.lhs_scroller.scrollTop());
1262 1318 this.trace('draw', 'rhs-scroller-top', ex.rhs_scroller.scrollTop());
1263
1319
1264 1320 jQuery.each(jQuery.find('#' + this.id + ' canvas'), function () {
1265 1321 jQuery(this).get(0).height = ex.visible_page_height;
1266 1322 });
1267
1323
1268 1324 ex.clhs.unbind('click');
1269 1325 ex.crhs.unbind('click');
1270
1326
1271 1327 ctx_lhs.beginPath();
1272 1328 ctx_lhs.fillStyle = this.settings.bgcolor;
1273 1329 ctx_lhs.strokeStyle = '#888';
@@ -1295,39 +1351,39 b' jQuery.extend(Mgly.mergely.prototype, {'
1295 1351 ctx_lhs.beginPath();
1296 1352 ctx_lhs.fillStyle = this.settings.fgcolor[change['op']];
1297 1353 ctx_lhs.strokeStyle = '#000';
1298 ctx_lhs.lineWidth = 1.0;
1354 ctx_lhs.lineWidth = 0.5;
1299 1355 ctx_lhs.fillRect(1.5, lhs_y_start, 4.5, Math.max(lhs_y_end - lhs_y_start, 5));
1300 1356 ctx_lhs.strokeRect(1.5, lhs_y_start, 4.5, Math.max(lhs_y_end - lhs_y_start, 5));
1301 1357
1302 1358 ctx_rhs.beginPath();
1303 1359 ctx_rhs.fillStyle = this.settings.fgcolor[change['op']];
1304 1360 ctx_rhs.strokeStyle = '#000';
1305 ctx_rhs.lineWidth = 1.0;
1361 ctx_rhs.lineWidth = 0.5;
1306 1362 ctx_rhs.fillRect(1.5, rhs_y_start, 4.5, Math.max(rhs_y_end - rhs_y_start, 5));
1307 1363 ctx_rhs.strokeRect(1.5, rhs_y_start, 4.5, Math.max(rhs_y_end - rhs_y_start, 5));
1308
1364
1309 1365 if (!this._is_change_in_view(vp, change)) {
1310 1366 continue;
1311 1367 }
1312
1368
1313 1369 lhs_y_start = change['lhs-y-start'];
1314 1370 lhs_y_end = change['lhs-y-end'];
1315 1371 rhs_y_start = change['rhs-y-start'];
1316 1372 rhs_y_end = change['rhs-y-end'];
1317
1373
1318 1374 var radius = 3;
1319
1375
1320 1376 // draw left box
1321 1377 ctx.beginPath();
1322 1378 ctx.strokeStyle = this.settings.fgcolor[change['op']];
1323 1379 ctx.lineWidth = 1;
1324
1380
1325 1381 var rectWidth = this.draw_lhs_width;
1326 1382 var rectHeight = lhs_y_end - lhs_y_start - 1;
1327 1383 var rectX = this.draw_lhs_min;
1328 1384 var rectY = lhs_y_start;
1329 1385 // top and top top-right corner
1330
1386
1331 1387 // draw left box
1332 1388 ctx.moveTo(rectX, rectY);
1333 1389 if (navigator.appName == 'Microsoft Internet Explorer') {
@@ -1348,7 +1404,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1348 1404 ctx.lineTo(rectX, rectY + rectHeight);
1349 1405 }
1350 1406 ctx.stroke();
1351
1407
1352 1408 rectWidth = this.draw_rhs_width;
1353 1409 rectHeight = rhs_y_end - rhs_y_start - 1;
1354 1410 rectX = this.draw_rhs_max;
@@ -1372,7 +1428,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1372 1428 ctx.lineTo(rectX, rectY + rectHeight);
1373 1429 }
1374 1430 ctx.stroke();
1375
1431
1376 1432 // connect boxes
1377 1433 var cx = this.draw_lhs_min + this.draw_lhs_width;
1378 1434 var cy = lhs_y_start + (lhs_y_end + 1 - lhs_y_start) / 2.0;
@@ -1395,7 +1451,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1395 1451 // visible window feedback
1396 1452 ctx_lhs.fillStyle = this.settings.vpcolor;
1397 1453 ctx_rhs.fillStyle = this.settings.vpcolor;
1398
1454
1399 1455 var lto = ex.clhs.height() * ex.visible_page_ratio;
1400 1456 var lfrom = (ex.lhs_scroller.scrollTop() / ex.gutter_height) * ex.clhs.height();
1401 1457 var rto = ex.crhs.height() * ex.visible_page_ratio;
@@ -1406,10 +1462,10 b' jQuery.extend(Mgly.mergely.prototype, {'
1406 1462 this.trace('draw', 'visible_page_ratio', ex.visible_page_ratio);
1407 1463 this.trace('draw', 'lhs from', lfrom, 'lhs to', lto);
1408 1464 this.trace('draw', 'rhs from', rfrom, 'rhs to', rto);
1409
1465
1410 1466 ctx_lhs.fillRect(1.5, lfrom, 4.5, lto);
1411 1467 ctx_rhs.fillRect(1.5, rfrom, 4.5, rto);
1412
1468
1413 1469 ex.clhs.click(function (ev) {
1414 1470 var y = ev.pageY - ex.lhs_xyoffset.top - (lto / 2);
1415 1471 var sto = Math.max(0, (y / mcanvas_lhs.height) * ex.lhs_scroller.get(0).scrollHeight);
@@ -1417,7 +1473,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1417 1473 });
1418 1474 ex.crhs.click(function (ev) {
1419 1475 var y = ev.pageY - ex.rhs_xyoffset.top - (rto / 2);
1420 var sto = Math.max(0, (y / mcanvas_rhs.height) * ex.rhs_scroller.get(0).scrollHeight);
1476 var sto = Math.max(0, (y / mcanvas_rhs.height) * ex.rhs_scroller.get(0).scrollHeight);
1421 1477 ex.rhs_scroller.scrollTop(sto);
1422 1478 });
1423 1479 },
@@ -1425,14 +1481,14 b' jQuery.extend(Mgly.mergely.prototype, {'
1425 1481 if(this.settings._debug.indexOf(name) >= 0) {
1426 1482 arguments[0] = name+':';
1427 1483 console.log([].slice.apply(arguments));
1428 }
1484 }
1429 1485 }
1430 1486 });
1431 1487
1432 1488 jQuery.pluginMaker = function(plugin) {
1433 1489 // add the plugin function as a jQuery plugin
1434 1490 jQuery.fn[plugin.prototype.name] = function(options) {
1435 // get the arguments
1491 // get the arguments
1436 1492 var args = jQuery.makeArray(arguments),
1437 1493 after = args.slice(1);
1438 1494 var rc = undefined;
@@ -4,11 +4,11 b''
4 4
5 5 <%def name="js_extra()">
6 6 <script type="text/javascript" src="${h.url('/js/codemirror.js')}"></script>
7 <script type="text/javascript" src="${h.url('/js/mergerly.js')}"></script>
7 <script type="text/javascript" src="${h.url('/js/mergely.js')}"></script>
8 8 </%def>
9 9 <%def name="css_extra()">
10 10 <link rel="stylesheet" type="text/css" href="${h.url('/css/codemirror.css')}"/>
11 <link rel="stylesheet" type="text/css" href="${h.url('/css/mergerly.css')}"/>
11 <link rel="stylesheet" type="text/css" href="${h.url('/css/mergely.css')}"/>
12 12 </%def>
13 13
14 14 <%def name="title()">
General Comments 0
You need to be logged in to leave comments. Login now