##// 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(){
@@ -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) {
@@ -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);
@@ -415,53 +460,8 b' jQuery.extend(Mgly.mergely.prototype, {'
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 {
@@ -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;
@@ -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()));
@@ -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,7 +942,7 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});
@@ -1295,14 +1351,14 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
@@ -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