##// 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 EOF
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 /* required */
10 /* required */
3 .mergely-column textarea { width: 80px; height: 200px; }
11 .mergely-column textarea { width: 80px; height: 200px; }
@@ -12,17 +20,17 b''
12 .mergely-column { border: 1px solid #ccc; }
20 .mergely-column { border: 1px solid #ccc; }
13 .mergely-active { border: 1px solid #a3d1ff; }
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 .mergely.a.lhs.start.end,
24 .mergely.a.lhs.start.end,
17 .mergely.a.rhs.end { border-bottom: 1px solid #ddffdd; }
25 .mergely.a.rhs.end { border-bottom: 1px solid #a3d1ff; }
18 .mergely.a.rhs { background-color: #ddffdd; }
26 .mergely.a.rhs { background-color: #ddeeff; }
19 .mergely.a.lhs.start.end.first { border-bottom: 0; border-top: 1px solid #ddffdd; }
27 .mergely.a.lhs.start.end.first { border-bottom: 0; border-top: 1px solid #a3d1ff; }
20
28
21 .mergely.d.lhs { background-color: #edc0c0; }
29 .mergely.d.lhs { background-color: #edc0c0; }
22 .mergely.d.lhs.end,
30 .mergely.d.lhs.end,
23 .mergely.d.rhs.start.end { border-bottom: 1px solid #ffdddd; }
31 .mergely.d.rhs.start.end { border-bottom: 1px solid #ff7f7f; }
24 .mergely.d.rhs.start.end.first { border-bottom: 0; border-top: 1px solid #ffdddd; }
32 .mergely.d.rhs.start.end.first { border-bottom: 0; border-top: 1px solid #ff7f7f; }
25 .mergely.d.lhs.start { border-top: 1px solid #ffdddd; }
33 .mergely.d.lhs.start { border-top: 1px solid #ff7f7f; }
26
34
27 .mergely.c.lhs,
35 .mergely.c.lhs,
28 .mergely.c.rhs { background-color: #fafafa; }
36 .mergely.c.rhs { background-color: #fafafa; }
@@ -31,11 +39,5 b''
31 .mergely.c.lhs.end,
39 .mergely.c.lhs.end,
32 .mergely.c.rhs.end { border-bottom: 1px solid #a3a3a3; }
40 .mergely.c.rhs.end { border-bottom: 1px solid #a3a3a3; }
33
41
34 .mergely.ch.a.rhs { background-color: #ddffdd; }
42 .mergely.ch.a.rhs { background-color: #ddeeff; }
35 .mergely.ch.d.lhs { background-color: #ffdddd; }
43 .mergely.ch.d.lhs { background-color: #edc0c0; text-decoration: line-through; color: #888; }
36
37
38 .mergely-margin #compare-lhs-margin,
39 .mergely-margin #compare-rhs-margin {
40 cursor: pointer
41 }
@@ -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 Mgly = {};
9 Mgly = {};
2
10
3 Mgly.Timer = function(){
11 Mgly.Timer = function(){
@@ -5,7 +13,7 b' Mgly.Timer = function(){'
5 self.start = function() { self.t0 = new Date().getTime(); }
13 self.start = function() { self.t0 = new Date().getTime(); }
6 self.stop = function() {
14 self.stop = function() {
7 var t1 = new Date().getTime();
15 var t1 = new Date().getTime();
8 var d = t1 - self.t0;
16 var d = t1 - self.t0;
9 self.t0 = t1;
17 self.t0 = t1;
10 return d;
18 return d;
11 }
19 }
@@ -54,18 +62,18 b' Mgly.LCS = function(x, y) {'
54 jQuery.extend(Mgly.LCS.prototype, {
62 jQuery.extend(Mgly.LCS.prototype, {
55 clear: function() { this.ready = 0; },
63 clear: function() { this.ready = 0; },
56 diff: function(added, removed) {
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 var changes = Mgly.DiffParser(d.normal_form());
66 var changes = Mgly.DiffParser(d.normal_form());
59 var li = 0, lj = 0;
67 var li = 0, lj = 0;
60 for (var i = 0; i < changes.length; ++i) {
68 for (var i = 0; i < changes.length; ++i) {
61 var change = changes[i];
69 var change = changes[i];
62 if (change.op != 'a') {
70 if (change.op != 'a') {
63 // find the starting index of the line
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 // get the index of the the span of the change
73 // get the index of the the span of the change
66 lj = change['lhs-line-to'] + 1;
74 lj = change['lhs-line-to'] + 1;
67 // get the changed text
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 if (change.op == 'd') lchange += ' ';// include the leading space
77 if (change.op == 'd') lchange += ' ';// include the leading space
70 else if (li > 0 && change.op == 'c') li += 1; // ignore leading space if not first word
78 else if (li > 0 && change.op == 'c') li += 1; // ignore leading space if not first word
71 // output the changed index and text
79 // output the changed index and text
@@ -73,11 +81,11 b' jQuery.extend(Mgly.LCS.prototype, {'
73 }
81 }
74 if (change.op != 'd') {
82 if (change.op != 'd') {
75 // find the starting index of the line
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 // get the index of the the span of the change
85 // get the index of the the span of the change
78 lj = change['rhs-line-to'] + 1;
86 lj = change['rhs-line-to'] + 1;
79 // get the changed text
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 if (change.op == 'a') rchange += ' ';// include the leading space
89 if (change.op == 'a') rchange += ' ';// include the leading space
82 else if (li > 0 && change.op == 'c') li += 1; // ignore leading space if not first word
90 else if (li > 0 && change.op == 'c') li += 1; // ignore leading space if not first word
83 // output the changed index and text
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) {
97
90 this.diff_codes = {};
98 Mgly.CodeifyText = function(settings) {
91 this.max_code = 0;
99 this._max_code = 0;
92 var lhs_lines = lhs.split('\n');
100 this._diff_codes = {};
93 var rhs_lines = rhs.split('\n');
101 this.ctxs = {};
94 if (lhs.length == 0) lhs_lines = [];
102 this.options = {ignorews: false};
95 if (rhs.length == 0) rhs_lines = [];
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();
108 jQuery.extend(Mgly.CodeifyText.prototype, {
98 lhs_data.data = this._diff_codes(lhs_lines, ignore_ws);
109 getCodes: function(side) {
99 lhs_data.modified = {};
110 if (!this.ctxs.hasOwnProperty(side)) {
100 lhs_data.length = Mgly.sizeOf(lhs_data.data);
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();
145 Mgly.diff = function(lhs, rhs, options) {
103 rhs_data.data = this._diff_codes(rhs_lines, ignore_ws);
146 var opts = jQuery.extend({ignorews: false}, options);
104 rhs_data.modified = {};
147 this.codeify = new Mgly.CodeifyText({
105 rhs_data.length = Mgly.sizeOf(rhs_data.data);
148 lhs: lhs,
106
149 rhs: rhs,
107 var max = (lhs_data.length + rhs_data.length + 1);
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 var vector_d = Array( 2 * max + 2 );
161 var vector_d = Array( 2 * max + 2 );
109 var vector_u = Array( 2 * max + 2 );
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 jQuery.extend(Mgly.diff.prototype, {
169 jQuery.extend(Mgly.diff.prototype, {
121 changes: function() { return this.items; },
170 changes: function() { return this.items; },
171 getLines: function(side) {
172 return this.codeify.getLines(side);
173 },
122 normal_form: function() {
174 normal_form: function() {
123 var nf = '';
175 var nf = '';
124 for (var index = 0; index < this.items.length; ++index) {
176 for (var index = 0; index < this.items.length; ++index) {
@@ -128,11 +180,11 b' jQuery.extend(Mgly.diff.prototype, {'
128 var change = 'c';
180 var change = 'c';
129 if (item.lhs_deleted_count == 0 && item.rhs_inserted_count > 0) change = 'a';
181 if (item.lhs_deleted_count == 0 && item.rhs_inserted_count > 0) change = 'a';
130 else if (item.lhs_deleted_count > 0 && item.rhs_inserted_count == 0) change = 'd';
182 else if (item.lhs_deleted_count > 0 && item.rhs_inserted_count == 0) change = 'd';
131
183
132 if (item.lhs_deleted_count == 1) lhs_str = item.lhs_start + 1;
184 if (item.lhs_deleted_count == 1) lhs_str = item.lhs_start + 1;
133 else if (item.lhs_deleted_count == 0) lhs_str = item.lhs_start;
185 else if (item.lhs_deleted_count == 0) lhs_str = item.lhs_start;
134 else lhs_str = (item.lhs_start + 1) + ',' + (item.lhs_start + item.lhs_deleted_count);
186 else lhs_str = (item.lhs_start + 1) + ',' + (item.lhs_start + item.lhs_deleted_count);
135
187
136 if (item.rhs_inserted_count == 1) rhs_str = item.rhs_start + 1;
188 if (item.rhs_inserted_count == 1) rhs_str = item.rhs_start + 1;
137 else if (item.rhs_inserted_count == 0) rhs_str = item.rhs_start;
189 else if (item.rhs_inserted_count == 0) rhs_str = item.rhs_start;
138 else rhs_str = (item.rhs_start + 1) + ',' + (item.rhs_start + item.rhs_inserted_count);
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 return nf;
203 return nf;
152 },
204 },
153 _diff_codes: function(lines, ignore_ws) {
205 _lcs: function(lhs_ctx, lhs_lower, lhs_upper, rhs_ctx, rhs_lower, rhs_upper, vector_u, vector_d) {
154 var code = this.max_code;
206 while ( (lhs_lower < lhs_upper) && (rhs_lower < rhs_upper) && (lhs_ctx.codes[lhs_lower] == rhs_ctx.codes[rhs_lower]) ) {
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]) ) {
175 ++lhs_lower;
207 ++lhs_lower;
176 ++rhs_lower;
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 --lhs_upper;
211 --lhs_upper;
180 --rhs_upper;
212 --rhs_upper;
181 }
213 }
182 if (lhs_lower == lhs_upper) {
214 if (lhs_lower == lhs_upper) {
183 while (rhs_lower < rhs_upper) {
215 while (rhs_lower < rhs_upper) {
184 rhs.modified[ rhs_lower++ ] = true;
216 rhs_ctx.modified[ rhs_lower++ ] = true;
185 }
217 }
186 }
218 }
187 else if (rhs_lower == rhs_upper) {
219 else if (rhs_lower == rhs_upper) {
188 while (lhs_lower < lhs_upper) {
220 while (lhs_lower < lhs_upper) {
189 lhs.modified[ lhs_lower++ ] = true;
221 lhs_ctx.modified[ lhs_lower++ ] = true;
190 }
222 }
191 }
223 }
192 else {
224 else {
193 var sms = this._sms(lhs, lhs_lower, lhs_upper, rhs, rhs_lower, 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);
194 this._lcs(lhs, lhs_lower, sms.x, rhs, rhs_lower, sms.y, vector_u, vector_d);
226 this._lcs(lhs_ctx, lhs_lower, sms.x, rhs_ctx, 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);
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) {
230 _sms: function(lhs_ctx, lhs_lower, lhs_upper, rhs_ctx, rhs_lower, rhs_upper, vector_u, vector_d) {
199 var max = lhs.length + rhs.length + 1;
231 var max = lhs_ctx.codes.length + rhs_ctx.codes.length + 1;
200 var kdown = lhs_lower - rhs_lower;
232 var kdown = lhs_lower - rhs_lower;
201 var kup = lhs_upper - rhs_upper;
233 var kup = lhs_upper - rhs_upper;
202 var delta = (lhs_upper - lhs_lower) - (rhs_upper - rhs_lower);
234 var delta = (lhs_upper - lhs_lower) - (rhs_upper - rhs_lower);
@@ -221,7 +253,7 b' jQuery.extend(Mgly.diff.prototype, {'
221 }
253 }
222 y = x - k;
254 y = x - k;
223 // find the end of the furthest reaching forward D-path in diagonal k.
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 x++; y++;
257 x++; y++;
226 }
258 }
227 vector_d[ offset_down + k ] = x;
259 vector_d[ offset_down + k ] = x;
@@ -246,7 +278,7 b' jQuery.extend(Mgly.diff.prototype, {'
246 x = vector_u[offset_up + k - 1]; // up
278 x = vector_u[offset_up + k - 1]; // up
247 }
279 }
248 y = x - k;
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 // diagonal
282 // diagonal
251 x--;
283 x--;
252 y--;
284 y--;
@@ -264,33 +296,33 b' jQuery.extend(Mgly.diff.prototype, {'
264 }
296 }
265 throw "the algorithm should never come here.";
297 throw "the algorithm should never come here.";
266 },
298 },
267 _optimize: function(data) {
299 _optimize: function(ctx) {
268 var start = 0, end = 0;
300 var start = 0, end = 0;
269 while (start < data.length) {
301 while (start < ctx.length) {
270 while ((start < data.length) && (data.modified[start] == undefined || data.modified[start] == false)) {
302 while ((start < ctx.length) && (ctx.modified[start] == undefined || ctx.modified[start] == false)) {
271 start++;
303 start++;
272 }
304 }
273 end = start;
305 end = start;
274 while ((end < data.length) && (data.modified[end] == true)) {
306 while ((end < ctx.length) && (ctx.modified[end] == true)) {
275 end++;
307 end++;
276 }
308 }
277 if ((end < data.length) && (data.data[start] == data.data[end])) {
309 if ((end < ctx.length) && (ctx.ctx[start] == ctx.codes[end])) {
278 data.modified[start] = false;
310 ctx.modified[start] = false;
279 data.modified[end] = true;
311 ctx.modified[end] = true;
280 }
312 }
281 else {
313 else {
282 start = end;
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 var items = [];
319 var items = [];
288 var lhs_start = 0, rhs_start = 0;
320 var lhs_start = 0, rhs_start = 0;
289 var lhs_line = 0, rhs_line = 0;
321 var lhs_line = 0, rhs_line = 0;
290
322
291 while (lhs_line < lhs_data.length || rhs_line < rhs_data.length) {
323 while (lhs_line < lhs_ctx.codes.length || rhs_line < rhs_ctx.codes.length) {
292 if ((lhs_line < lhs_data.length) && (!lhs_data.modified[lhs_line])
324 if ((lhs_line < lhs_ctx.codes.length) && (!lhs_ctx.modified[lhs_line])
293 && (rhs_line < rhs_data.length) && (!rhs_data.modified[rhs_line])) {
325 && (rhs_line < rhs_ctx.codes.length) && (!rhs_ctx.modified[rhs_line])) {
294 // equal lines
326 // equal lines
295 lhs_line++;
327 lhs_line++;
296 rhs_line++;
328 rhs_line++;
@@ -300,20 +332,20 b' jQuery.extend(Mgly.diff.prototype, {'
300 lhs_start = lhs_line;
332 lhs_start = lhs_line;
301 rhs_start = rhs_line;
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 lhs_line++;
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 rhs_line++;
339 rhs_line++;
308
340
309 if ((lhs_start < lhs_line) || (rhs_start < rhs_line)) {
341 if ((lhs_start < lhs_line) || (rhs_start < rhs_line)) {
310 // store a new difference-item
342 // store a new difference-item
311 var aItem = new Object();
343 items.push({
312 aItem.lhs_start = lhs_start;
344 lhs_start: lhs_start,
313 aItem.rhs_start = rhs_start;
345 rhs_start: rhs_start,
314 aItem.lhs_deleted_count = lhs_line - lhs_start;
346 lhs_deleted_count: lhs_line - lhs_start,
315 aItem.rhs_inserted_count = rhs_line - rhs_start;
347 rhs_inserted_count: rhs_line - rhs_start
316 items.push(aItem);
348 });
317 }
349 }
318 }
350 }
319 }
351 }
@@ -322,12 +354,6 b' jQuery.extend(Mgly.diff.prototype, {'
322 });
354 });
323
355
324 Mgly.mergely = function(el, options) {
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 if (el) {
357 if (el) {
332 this.init(el, options);
358 this.init(el, options);
333 }
359 }
@@ -337,6 +363,25 b' jQuery.extend(Mgly.mergely.prototype, {'
337 name: 'mergely',
363 name: 'mergely',
338 //http://jupiterjs.com/news/writing-the-perfect-jquery-plugin
364 //http://jupiterjs.com/news/writing-the-perfect-jquery-plugin
339 init: function(el, options) {
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 this.settings = {
385 this.settings = {
341 autoupdate: true,
386 autoupdate: true,
342 autoresize: true,
387 autoresize: true,
@@ -352,14 +397,14 b' jQuery.extend(Mgly.mergely.prototype, {'
352 change_timeout: 150,
397 change_timeout: 150,
353 fgcolor: {a:'#4ba3fa',c:'#a3a3a3',d:'#ff7f7f'},
398 fgcolor: {a:'#4ba3fa',c:'#a3a3a3',d:'#ff7f7f'},
354 bgcolor: '#eee',
399 bgcolor: '#eee',
355 vpcolor: 'rgba(0, 0, 200, 0.2)',
400 vpcolor: 'rgba(0, 0, 200, 0.5)',
356 lhs: function(setValue) { },
401 lhs: function(setValue) { },
357 rhs: function(setValue) { },
402 rhs: function(setValue) { },
358 loaded: function() { },
403 loaded: function() { },
359 //_auto_height: function(h) { return h - 20; },
404 //_auto_height: function(h) { return h - 20; },
360 _auto_width: function(w) { return w; },
405 _auto_width: function(w) { return w; },
361 resize: function(init) {
406 resize: function(init) {
362 var scrollbar = init ? -15 : 0;
407 var scrollbar = init ? 16 : 0;
363 var w = jQuery(el).parent().width() + scrollbar;
408 var w = jQuery(el).parent().width() + scrollbar;
364 if (this.width == 'auto') {
409 if (this.width == 'auto') {
365 w = this._auto_width(w);
410 w = this._auto_width(w);
@@ -403,65 +448,20 b' jQuery.extend(Mgly.mergely.prototype, {'
403 }
448 }
404 this.lhs_cmsettings = {};
449 this.lhs_cmsettings = {};
405 this.rhs_cmsettings = {};
450 this.rhs_cmsettings = {};
406
451
407 // save this element for faster queries
452 // save this element for faster queries
408 this.element = jQuery(el);
453 this.element = jQuery(el);
409
454
410 // save options if there are any
455 // save options if there are any
411 if (options && options.cmsettings) jQuery.extend(this.lhs_cmsettings, cmsettings, options.cmsettings, options.lhs_cmsettings);
456 if (options && options.cmsettings) jQuery.extend(this.lhs_cmsettings, cmsettings, options.cmsettings, options.lhs_cmsettings);
412 if (options && options.cmsettings) jQuery.extend(this.rhs_cmsettings, cmsettings, options.cmsettings, options.rhs_cmsettings);
457 if (options && options.cmsettings) jQuery.extend(this.rhs_cmsettings, cmsettings, options.cmsettings, options.rhs_cmsettings);
413 if (options) jQuery.extend(this.settings, options);
458 if (options) jQuery.extend(this.settings, options);
414
459
415 // bind if the element is destroyed
460 // bind if the element is destroyed
416 this.element.bind('destroyed', jQuery.proxy(this.teardown, this));
461 this.element.bind('destroyed', jQuery.proxy(this.teardown, this));
417
462
418 // save this instance in jQuery data
463 // save this instance in jQuery data, binding this view to the node
419 jQuery.data(el, this.name, this);
464 jQuery.data(el, 'mergely', 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 }
465 },
465 },
466 unbind: function() {
466 unbind: function() {
467 if (this.changed_timeout != null) clearTimeout(this.changed_timeout);
467 if (this.changed_timeout != null) clearTimeout(this.changed_timeout);
@@ -502,11 +502,11 b' jQuery.extend(Mgly.mergely.prototype, {'
502 options: function(opts) {
502 options: function(opts) {
503 if (opts) {
503 if (opts) {
504 jQuery.extend(this.settings, opts);
504 jQuery.extend(this.settings, opts);
505 if (opts.autoresize) this.resize();
505 if (this.settings.autoresize) this.resize();
506 if (opts.autoupdate) this.update();
506 if (this.settings.autoupdate) this.update();
507 if (opts.hasOwnProperty('rhs_margin')) {
507 if (this.settings.hasOwnProperty('rhs_margin')) {
508 // dynamically swap the margin
508 // dynamically swap the margin
509 if (opts.rhs_margin == 'left') {
509 if (this.settings.rhs_margin == 'left') {
510 this.element.find('.mergely-margin:last-child').insertAfter(
510 this.element.find('.mergely-margin:last-child').insertAfter(
511 this.element.find('.mergely-canvas'));
511 this.element.find('.mergely-canvas'));
512 }
512 }
@@ -515,9 +515,9 b' jQuery.extend(Mgly.mergely.prototype, {'
515 target.appendTo(target.parent());
515 target.appendTo(target.parent());
516 }
516 }
517 }
517 }
518 if (opts.hasOwnProperty('sidebar')) {
518 if (this.settings.hasOwnProperty('sidebar')) {
519 // dynamically enable sidebars
519 // dynamically enable sidebars
520 if (opts.sidebar) {
520 if (this.settings.sidebar) {
521 jQuery(this.element).find('.mergely-margin').css({display: 'block'});
521 jQuery(this.element).find('.mergely-margin').css({display: 'block'});
522 }
522 }
523 else {
523 else {
@@ -570,7 +570,7 b' jQuery.extend(Mgly.mergely.prototype, {'
570 this.prev_query[side] = query;
570 this.prev_query[side] = query;
571 }
571 }
572 var cursor = this.cursor[this.id];
572 var cursor = this.cursor[this.id];
573
573
574 if (cursor[direction]()) {
574 if (cursor[direction]()) {
575 editor.setSelection(cursor.from(), cursor.to());
575 editor.setSelection(cursor.from(), cursor.to());
576 }
576 }
@@ -581,14 +581,15 b' jQuery.extend(Mgly.mergely.prototype, {'
581 resize: function() {
581 resize: function() {
582 this.settings.resize();
582 this.settings.resize();
583 this._changing(this.id + '-lhs', this.id + '-rhs');
583 this._changing(this.id + '-lhs', this.id + '-rhs');
584 this._set_top_offset(this.id + '-lhs');
584 },
585 },
585 diff: function() {
586 diff: function() {
586 var lhs = this.editor[this.id + '-lhs'].getValue();
587 var lhs = this.editor[this.id + '-lhs'].getValue();
587 var rhs = this.editor[this.id + '-rhs'].getValue();
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 return d.normal_form();
590 return d.normal_form();
590 },
591 },
591 _setup: function(el) {
592 bind: function(el) {
592 jQuery(this.element).hide();//hide
593 jQuery(this.element).hide();//hide
593 this.id = jQuery(el).attr('id');
594 this.id = jQuery(el).attr('id');
594 var height = this.settings.editor_height;
595 var height = this.settings.editor_height;
@@ -616,7 +617,7 b' jQuery.extend(Mgly.mergely.prototype, {'
616 }
617 }
617 this.merge_rhs_button = jQuery(merge_rhs_button);
618 this.merge_rhs_button = jQuery(merge_rhs_button);
618 this.merge_lhs_button = jQuery(merge_lhs_button);
619 this.merge_lhs_button = jQuery(merge_lhs_button);
619
620
620 // create the textarea and canvas elements
621 // create the textarea and canvas elements
621 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 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 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>'));
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 cmstyle += this.id + ' .CodeMirror-scroll { height: 100%; overflow: auto; }';
641 cmstyle += this.id + ' .CodeMirror-scroll { height: 100%; overflow: auto; }';
641 }
642 }
642 jQuery('<style type="text/css">' + cmstyle + '</style>').appendTo('head');
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 if (this.settings.lhs) {
686 if (this.settings.lhs) {
645 var setv = this.editor[this.id + '-lhs'].getDoc().setValue;
687 var setv = this.editor[this.id + '-lhs'].getDoc().setValue;
646 this.settings.lhs(setv.bind(this.editor[this.id + '-lhs'].getDoc()));
688 this.settings.lhs(setv.bind(this.editor[this.id + '-lhs'].getDoc()));
@@ -650,7 +692,7 b' jQuery.extend(Mgly.mergely.prototype, {'
650 this.settings.rhs(setv.bind(this.editor[this.id + '-rhs'].getDoc()));
692 this.settings.rhs(setv.bind(this.editor[this.id + '-rhs'].getDoc()));
651 }
693 }
652 },
694 },
653
695
654 _scrolling: function(editor_name) {
696 _scrolling: function(editor_name) {
655 if (this._skipscroll[editor_name] === true) {
697 if (this._skipscroll[editor_name] === true) {
656 // scrolling one side causes the other to event - ignore it
698 // scrolling one side causes the other to event - ignore it
@@ -665,23 +707,23 b' jQuery.extend(Mgly.mergely.prototype, {'
665 var midline = this.editor[editor_name].coordsChar({left:0, top:this.midway});
707 var midline = this.editor[editor_name].coordsChar({left:0, top:this.midway});
666 var top_to = scroller.scrollTop();
708 var top_to = scroller.scrollTop();
667 var left_to = scroller.scrollLeft();
709 var left_to = scroller.scrollLeft();
668
710
669 this.trace('scroll', 'side', editor_name);
711 this.trace('scroll', 'side', editor_name);
670 this.trace('scroll', 'midway', this.midway);
712 this.trace('scroll', 'midway', this.midway);
671 this.trace('scroll', 'midline', midline);
713 this.trace('scroll', 'midline', midline);
672 this.trace('scroll', 'top_to', top_to);
714 this.trace('scroll', 'top_to', top_to);
673 this.trace('scroll', 'left_to', left_to);
715 this.trace('scroll', 'left_to', left_to);
674
716
675 var editor_name1 = this.id + '-lhs';
717 var editor_name1 = this.id + '-lhs';
676 var editor_name2 = this.id + '-rhs';
718 var editor_name2 = this.id + '-rhs';
677
719
678 for (var name in this.editor) {
720 for (var name in this.editor) {
679 if (!this.editor.hasOwnProperty(name)) continue;
721 if (!this.editor.hasOwnProperty(name)) continue;
680 if (editor_name == name) continue; //same editor
722 if (editor_name == name) continue; //same editor
681 var this_side = editor_name.replace(this.id + '-', '');
723 var this_side = editor_name.replace(this.id + '-', '');
682 var other_side = name.replace(this.id + '-', '');
724 var other_side = name.replace(this.id + '-', '');
683 var top_adjust = 0;
725 var top_adjust = 0;
684
726
685 // find the last change that is less than or within the midway point
727 // find the last change that is less than or within the midway point
686 // do not move the rhs until the lhs end point is >= the rhs end point.
728 // do not move the rhs until the lhs end point is >= the rhs end point.
687 var last_change = null;
729 var last_change = null;
@@ -699,14 +741,14 b' jQuery.extend(Mgly.mergely.prototype, {'
699 force_scroll = true;
741 force_scroll = true;
700 }
742 }
701 else {
743 else {
702 top_adjust +=
744 top_adjust +=
703 (change[this_side+'-y-end'] - change[this_side+'-y-start']) -
745 (change[this_side+'-y-end'] - change[this_side+'-y-start']) -
704 (change[other_side+'-y-end'] - change[other_side+'-y-start']);
746 (change[other_side+'-y-end'] - change[other_side+'-y-start']);
705 }
747 }
706 }
748 }
707 }
749 }
708 }
750 }
709
751
710 var vp = this.editor[name].getViewport();
752 var vp = this.editor[name].getViewport();
711 var scroll = true;
753 var scroll = true;
712 if (last_change) {
754 if (last_change) {
@@ -724,7 +766,7 b' jQuery.extend(Mgly.mergely.prototype, {'
724 scroller.scrollTop(top_to - top_adjust).scrollLeft(left_to);
766 scroller.scrollTop(top_to - top_adjust).scrollLeft(left_to);
725 }
767 }
726 else this.trace('scroll', 'not scrolling other side');
768 else this.trace('scroll', 'not scrolling other side');
727
769
728 if (this.settings.autoupdate) {
770 if (this.settings.autoupdate) {
729 var timer = new Mgly.Timer();
771 var timer = new Mgly.Timer();
730 this._calculate_offsets(editor_name1, editor_name2, this.changes);
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 self.chfns[name] = [];
821 self.chfns[name] = [];
780
822
781 var ex = this._draw_info(this.id + '-lhs', this.id + '-rhs');
823 var ex = this._draw_info(this.id + '-lhs', this.id + '-rhs');
782 var ctx_lhs = ex.clhs.get(0).getContext('2d');
824 var ctx_lhs = ex.clhs.get(0).getContext('2d');
783 var ctx_rhs = ex.crhs.get(0).getContext('2d');
825 var ctx_rhs = ex.crhs.get(0).getContext('2d');
784 var ctx = ex.dcanvas.getContext('2d');
826 var ctx = ex.dcanvas.getContext('2d');
785
827
786 ctx_lhs.beginPath();
828 ctx_lhs.beginPath();
787 ctx_lhs.fillStyle = this.settings.bgcolor;
829 ctx_lhs.fillStyle = this.settings.bgcolor;
788 ctx_lhs.strokeStyle = '#888';
830 ctx_lhs.strokeStyle = '#888';
@@ -794,7 +836,7 b' jQuery.extend(Mgly.mergely.prototype, {'
794 ctx_rhs.strokeStyle = '#888';
836 ctx_rhs.strokeStyle = '#888';
795 ctx_rhs.fillRect(0, 0, 6.5, ex.visible_page_height);
837 ctx_rhs.fillRect(0, 0, 6.5, ex.visible_page_height);
796 ctx_rhs.strokeRect(0, 0, 6.5, ex.visible_page_height);
838 ctx_rhs.strokeRect(0, 0, 6.5, ex.visible_page_height);
797
839
798 ctx.beginPath();
840 ctx.beginPath();
799 ctx.fillStyle = '#fff';
841 ctx.fillStyle = '#fff';
800 ctx.fillRect(0, 0, this.draw_mid_width, ex.visible_page_height);
842 ctx.fillRect(0, 0, this.draw_mid_width, ex.visible_page_height);
@@ -803,7 +845,7 b' jQuery.extend(Mgly.mergely.prototype, {'
803 var lhs = this.editor[editor_name1].getValue();
845 var lhs = this.editor[editor_name1].getValue();
804 var rhs = this.editor[editor_name2].getValue();
846 var rhs = this.editor[editor_name2].getValue();
805 var timer = new Mgly.Timer();
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 this.trace('change', 'diff time', timer.stop());
849 this.trace('change', 'diff time', timer.stop());
808 this.changes = Mgly.DiffParser(d.normal_form());
850 this.changes = Mgly.DiffParser(d.normal_form());
809 this.trace('change', 'parse time', timer.stop());
851 this.trace('change', 'parse time', timer.stop());
@@ -861,13 +903,27 b' jQuery.extend(Mgly.mergely.prototype, {'
861 }
903 }
862 return true;
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 _calculate_offsets: function (editor_name1, editor_name2, changes) {
924 _calculate_offsets: function (editor_name1, editor_name2, changes) {
865 if (this.em_height == null) {
925 if (this.em_height == null) {
866 // this is the distance from the top of the screen
926 if(!this._set_top_offset(editor_name1)) return; //try again
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;
871 this.em_height = this.editor[editor_name1].defaultTextHeight();
927 this.em_height = this.editor[editor_name1].defaultTextHeight();
872 if (!this.em_height) {
928 if (!this.em_height) {
873 console.warn('Failed to calculate offsets, using 18 by default');
929 console.warn('Failed to calculate offsets, using 18 by default');
@@ -886,15 +942,15 b' jQuery.extend(Mgly.mergely.prototype, {'
886 this.draw_rhs_max = this.draw_mid_width - 0.5; //24.5;
942 this.draw_rhs_max = this.draw_mid_width - 0.5; //24.5;
887 this.draw_lhs_width = 5;
943 this.draw_lhs_width = 5;
888 this.draw_rhs_width = 5;
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 var lhschc = this.editor[editor_name1].charCoords({line: 0});
947 var lhschc = this.editor[editor_name1].charCoords({line: 0});
892 var rhschc = this.editor[editor_name2].charCoords({line: 0});
948 var rhschc = this.editor[editor_name2].charCoords({line: 0});
893 var vp = this._get_viewport(editor_name1, editor_name2);
949 var vp = this._get_viewport(editor_name1, editor_name2);
894
950
895 for (var i = 0; i < changes.length; ++i) {
951 for (var i = 0; i < changes.length; ++i) {
896 var change = changes[i];
952 var change = changes[i];
897
953
898 if (!this.settings.sidebar && !this._is_change_in_view(vp, change)) {
954 if (!this.settings.sidebar && !this._is_change_in_view(vp, change)) {
899 // if the change is outside the viewport, skip
955 // if the change is outside the viewport, skip
900 delete change['lhs-y-start'];
956 delete change['lhs-y-start'];
@@ -907,7 +963,7 b' jQuery.extend(Mgly.mergely.prototype, {'
907 var llt = change['lhs-line-to'] >= 0 ? change['lhs-line-to'] : 0;
963 var llt = change['lhs-line-to'] >= 0 ? change['lhs-line-to'] : 0;
908 var rlf = change['rhs-line-from'] >= 0 ? change['rhs-line-from'] : 0;
964 var rlf = change['rhs-line-from'] >= 0 ? change['rhs-line-from'] : 0;
909 var rlt = change['rhs-line-to'] >= 0 ? change['rhs-line-to'] : 0;
965 var rlt = change['rhs-line-to'] >= 0 ? change['rhs-line-to'] : 0;
910
966
911 var ls, le, rs, re;
967 var ls, le, rs, re;
912 if (this.editor[editor_name1].getOption('lineWrapping') || this.editor[editor_name1].getOption('lineWrapping')) {
968 if (this.editor[editor_name1].getOption('lineWrapping') || this.editor[editor_name1].getOption('lineWrapping')) {
913 // If using line-wrapping, we must get the height of the line
969 // If using line-wrapping, we must get the height of the line
@@ -918,7 +974,7 b' jQuery.extend(Mgly.mergely.prototype, {'
918 var tle = this.editor[editor_name1].cursorCoords({line: llt, ch: 0}, 'page');
974 var tle = this.editor[editor_name1].cursorCoords({line: llt, ch: 0}, 'page');
919 var lhseh = this.editor[editor_name1].getLineHandle(llt);
975 var lhseh = this.editor[editor_name1].getLineHandle(llt);
920 le = { top: tle.top, bottom: tle.top + lhseh.height };
976 le = { top: tle.top, bottom: tle.top + lhseh.height };
921
977
922 var tls = this.editor[editor_name2].cursorCoords({line: rlf, ch: 0}, 'page');
978 var tls = this.editor[editor_name2].cursorCoords({line: rlf, ch: 0}, 'page');
923 var rhssh = this.editor[editor_name2].getLineHandle(rlf);
979 var rhssh = this.editor[editor_name2].getLineHandle(rlf);
924 rs = { top: tls.top, bottom: tls.top + rhssh.height };
980 rs = { top: tls.top, bottom: tls.top + rhssh.height };
@@ -929,24 +985,24 b' jQuery.extend(Mgly.mergely.prototype, {'
929 }
985 }
930 else {
986 else {
931 // If not using line-wrapping, we can calculate the line position
987 // If not using line-wrapping, we can calculate the line position
932 ls = {
988 ls = {
933 top: lhschc.top + llf * this.em_height,
989 top: lhschc.top + llf * this.em_height,
934 bottom: lhschc.bottom + llf * this.em_height + 2
990 bottom: lhschc.bottom + llf * this.em_height + 2
935 };
991 };
936 le = {
992 le = {
937 top: lhschc.top + llt * this.em_height,
993 top: lhschc.top + llt * this.em_height,
938 bottom: lhschc.bottom + llt * this.em_height + 2
994 bottom: lhschc.bottom + llt * this.em_height + 2
939 };
995 };
940 rs = {
996 rs = {
941 top: rhschc.top + rlf * this.em_height,
997 top: rhschc.top + rlf * this.em_height,
942 bottom: rhschc.bottom + rlf * this.em_height + 2
998 bottom: rhschc.bottom + rlf * this.em_height + 2
943 };
999 };
944 re = {
1000 re = {
945 top: rhschc.top + rlt * this.em_height,
1001 top: rhschc.top + rlt * this.em_height,
946 bottom: rhschc.bottom + rlt * this.em_height + 2
1002 bottom: rhschc.bottom + rlt * this.em_height + 2
947 };
1003 };
948 }
1004 }
949
1005
950 if (change['op'] == 'a') {
1006 if (change['op'] == 'a') {
951 // adds (right), normally start from the end of the lhs,
1007 // adds (right), normally start from the end of the lhs,
952 // except for the case when the start of the rhs is 0
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 _markup_changes: function (editor_name1, editor_name2, changes) {
1042 _markup_changes: function (editor_name1, editor_name2, changes) {
987 jQuery('.merge-button').remove(); // clear
1043 jQuery('.merge-button').remove(); // clear
988
1044
989 var self = this;
1045 var self = this;
990 var led = this.editor[editor_name1];
1046 var led = this.editor[editor_name1];
991 var red = this.editor[editor_name2];
1047 var red = this.editor[editor_name2];
@@ -998,11 +1054,11 b' jQuery.extend(Mgly.mergely.prototype, {'
998 var llt = change['lhs-line-to'] >= 0 ? change['lhs-line-to'] : 0;
1054 var llt = change['lhs-line-to'] >= 0 ? change['lhs-line-to'] : 0;
999 var rlf = change['rhs-line-from'] >= 0 ? change['rhs-line-from'] : 0;
1055 var rlf = change['rhs-line-from'] >= 0 ? change['rhs-line-from'] : 0;
1000 var rlt = change['rhs-line-to'] >= 0 ? change['rhs-line-to'] : 0;
1056 var rlt = change['rhs-line-to'] >= 0 ? change['rhs-line-to'] : 0;
1001
1057
1002 var clazz = ['mergely', 'lhs', change['op'], 'cid-' + i];
1058 var clazz = ['mergely', 'lhs', change['op'], 'cid-' + i];
1003 led.addLineClass(llf, 'background', 'start');
1059 led.addLineClass(llf, 'background', 'start');
1004 led.addLineClass(llt, 'background', 'end');
1060 led.addLineClass(llt, 'background', 'end');
1005
1061
1006 if (llf == 0 && llt == 0 && rlf == 0) {
1062 if (llf == 0 && llt == 0 && rlf == 0) {
1007 led.addLineClass(llf, 'background', clazz.join(' '));
1063 led.addLineClass(llf, 'background', clazz.join(' '));
1008 led.addLineClass(llf, 'background', 'first');
1064 led.addLineClass(llf, 'background', 'first');
@@ -1014,7 +1070,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1014 led.addLineClass(j, 'background', clazz.join(' '));
1070 led.addLineClass(j, 'background', clazz.join(' '));
1015 }
1071 }
1016 }
1072 }
1017
1073
1018 if (!red.getOption('readOnly')) {
1074 if (!red.getOption('readOnly')) {
1019 // add widgets to lhs, if rhs is not read only
1075 // add widgets to lhs, if rhs is not read only
1020 var rhs_button = self.merge_rhs_button.clone();
1076 var rhs_button = self.merge_rhs_button.clone();
@@ -1030,7 +1086,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1030 });
1086 });
1031
1087
1032 var vp = this._get_viewport(editor_name1, editor_name2);
1088 var vp = this._get_viewport(editor_name1, editor_name2);
1033
1089
1034 this.trace('change', 'markup lhs-editor time', timer.stop());
1090 this.trace('change', 'markup lhs-editor time', timer.stop());
1035 red.operation(function() {
1091 red.operation(function() {
1036 for (var i = 0; i < changes.length; ++i) {
1092 for (var i = 0; i < changes.length; ++i) {
@@ -1039,16 +1095,16 b' jQuery.extend(Mgly.mergely.prototype, {'
1039 var llt = change['lhs-line-to'] >= 0 ? change['lhs-line-to'] : 0;
1095 var llt = change['lhs-line-to'] >= 0 ? change['lhs-line-to'] : 0;
1040 var rlf = change['rhs-line-from'] >= 0 ? change['rhs-line-from'] : 0;
1096 var rlf = change['rhs-line-from'] >= 0 ? change['rhs-line-from'] : 0;
1041 var rlt = change['rhs-line-to'] >= 0 ? change['rhs-line-to'] : 0;
1097 var rlt = change['rhs-line-to'] >= 0 ? change['rhs-line-to'] : 0;
1042
1098
1043 if (!self._is_change_in_view(vp, change)) {
1099 if (!self._is_change_in_view(vp, change)) {
1044 // if the change is outside the viewport, skip
1100 // if the change is outside the viewport, skip
1045 continue;
1101 continue;
1046 }
1102 }
1047
1103
1048 var clazz = ['mergely', 'rhs', change['op'], 'cid-' + i];
1104 var clazz = ['mergely', 'rhs', change['op'], 'cid-' + i];
1049 red.addLineClass(rlf, 'background', 'start');
1105 red.addLineClass(rlf, 'background', 'start');
1050 red.addLineClass(rlt, 'background', 'end');
1106 red.addLineClass(rlt, 'background', 'end');
1051
1107
1052 if (rlf == 0 && rlt == 0 && llf == 0) {
1108 if (rlf == 0 && rlt == 0 && llf == 0) {
1053 red.addLineClass(rlf, 'background', clazz.join(' '));
1109 red.addLineClass(rlf, 'background', clazz.join(' '));
1054 red.addLineClass(rlf, 'background', 'first');
1110 red.addLineClass(rlf, 'background', 'first');
@@ -1075,7 +1131,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1075 }
1131 }
1076 });
1132 });
1077 this.trace('change', 'markup rhs-editor time', timer.stop());
1133 this.trace('change', 'markup rhs-editor time', timer.stop());
1078
1134
1079 // mark text deleted, LCS changes
1135 // mark text deleted, LCS changes
1080 var marktext = [];
1136 var marktext = [];
1081 for (var i = 0; this.settings.lcs && i < changes.length; ++i) {
1137 for (var i = 0; this.settings.lcs && i < changes.length; ++i) {
@@ -1084,7 +1140,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1084 var llt = change['lhs-line-to'] >= 0 ? change['lhs-line-to'] : 0;
1140 var llt = change['lhs-line-to'] >= 0 ? change['lhs-line-to'] : 0;
1085 var rlf = change['rhs-line-from'] >= 0 ? change['rhs-line-from'] : 0;
1141 var rlf = change['rhs-line-from'] >= 0 ? change['rhs-line-from'] : 0;
1086 var rlt = change['rhs-line-to'] >= 0 ? change['rhs-line-to'] : 0;
1142 var rlt = change['rhs-line-to'] >= 0 ? change['rhs-line-to'] : 0;
1087
1143
1088 if (!this._is_change_in_view(vp, change)) {
1144 if (!this._is_change_in_view(vp, change)) {
1089 // if the change is outside the viewport, skip
1145 // if the change is outside the viewport, skip
1090 continue;
1146 continue;
@@ -1100,7 +1156,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1100 }
1156 }
1101 else if (change['op'] == 'c') {
1157 else if (change['op'] == 'c') {
1102 // apply LCS changes to each line
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 ((j >= 0) && (j <= llt)) || ((k >= 0) && (k <= rlt));
1160 ((j >= 0) && (j <= llt)) || ((k >= 0) && (k <= rlt));
1105 ++j, ++k) {
1161 ++j, ++k) {
1106 if (k + p > rlt) {
1162 if (k + p > rlt) {
@@ -1121,7 +1177,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1121 var lhs_stop = { line: -1, ch: -1 };
1177 var lhs_stop = { line: -1, ch: -1 };
1122 var rhs_start = { line: -1, ch: -1 };
1178 var rhs_start = { line: -1, ch: -1 };
1123 var rhs_stop = { line: -1, ch: -1 };
1179 var rhs_stop = { line: -1, ch: -1 };
1124
1180
1125 var lcs = new Mgly.LCS(lhs_line, rhs_line);
1181 var lcs = new Mgly.LCS(lhs_line, rhs_line);
1126 lcs.diff(
1182 lcs.diff(
1127 function (from, to) {//added
1183 function (from, to) {//added
@@ -1135,7 +1191,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1135 }
1191 }
1136 }
1192 }
1137 this.trace('change', 'LCS marktext time', timer.stop());
1193 this.trace('change', 'LCS marktext time', timer.stop());
1138
1194
1139 // mark changes outside closure
1195 // mark changes outside closure
1140 led.operation(function() {
1196 led.operation(function() {
1141 // apply lhs markup
1197 // apply lhs markup
@@ -1154,7 +1210,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1154 }
1210 }
1155 });
1211 });
1156 this.trace('change', 'LCS markup time', timer.stop());
1212 this.trace('change', 'LCS markup time', timer.stop());
1157
1213
1158 // merge buttons
1214 // merge buttons
1159 var ed = {lhs:led, rhs:red};
1215 var ed = {lhs:led, rhs:red};
1160 jQuery('.merge-button').on('click', function(ev){
1216 jQuery('.merge-button').on('click', function(ev){
@@ -1180,11 +1236,11 b' jQuery.extend(Mgly.mergely.prototype, {'
1180 var change = self.changes[cid];
1236 var change = self.changes[cid];
1181
1237
1182 var line = {lhs: ed['lhs'].lineInfo(llt), rhs: ed['rhs'].lineInfo(rlt)};
1238 var line = {lhs: ed['lhs'].lineInfo(llt), rhs: ed['rhs'].lineInfo(rlt)};
1183
1239
1184 var text = ed[side].getRange(
1240 var text = ed[side].getRange(
1185 CodeMirror.Pos(change[side + '-line-from'], 0),
1241 CodeMirror.Pos(change[side + '-line-from'], 0),
1186 CodeMirror.Pos(change[side + '-line-to'] + 1, 0));
1242 CodeMirror.Pos(change[side + '-line-to'] + 1, 0));
1187
1243
1188 if (change['op'] == 'c') {
1244 if (change['op'] == 'c') {
1189 ed[oside].replaceRange(text,
1245 ed[oside].replaceRange(text,
1190 CodeMirror.Pos(change[oside + '-line-from'], 0),
1246 CodeMirror.Pos(change[oside + '-line-from'], 0),
@@ -1260,14 +1316,14 b' jQuery.extend(Mgly.mergely.prototype, {'
1260 this.trace('draw', 'visible_page_ratio', ex.visible_page_ratio);
1316 this.trace('draw', 'visible_page_ratio', ex.visible_page_ratio);
1261 this.trace('draw', 'lhs-scroller-top', ex.lhs_scroller.scrollTop());
1317 this.trace('draw', 'lhs-scroller-top', ex.lhs_scroller.scrollTop());
1262 this.trace('draw', 'rhs-scroller-top', ex.rhs_scroller.scrollTop());
1318 this.trace('draw', 'rhs-scroller-top', ex.rhs_scroller.scrollTop());
1263
1319
1264 jQuery.each(jQuery.find('#' + this.id + ' canvas'), function () {
1320 jQuery.each(jQuery.find('#' + this.id + ' canvas'), function () {
1265 jQuery(this).get(0).height = ex.visible_page_height;
1321 jQuery(this).get(0).height = ex.visible_page_height;
1266 });
1322 });
1267
1323
1268 ex.clhs.unbind('click');
1324 ex.clhs.unbind('click');
1269 ex.crhs.unbind('click');
1325 ex.crhs.unbind('click');
1270
1326
1271 ctx_lhs.beginPath();
1327 ctx_lhs.beginPath();
1272 ctx_lhs.fillStyle = this.settings.bgcolor;
1328 ctx_lhs.fillStyle = this.settings.bgcolor;
1273 ctx_lhs.strokeStyle = '#888';
1329 ctx_lhs.strokeStyle = '#888';
@@ -1295,39 +1351,39 b' jQuery.extend(Mgly.mergely.prototype, {'
1295 ctx_lhs.beginPath();
1351 ctx_lhs.beginPath();
1296 ctx_lhs.fillStyle = this.settings.fgcolor[change['op']];
1352 ctx_lhs.fillStyle = this.settings.fgcolor[change['op']];
1297 ctx_lhs.strokeStyle = '#000';
1353 ctx_lhs.strokeStyle = '#000';
1298 ctx_lhs.lineWidth = 1.0;
1354 ctx_lhs.lineWidth = 0.5;
1299 ctx_lhs.fillRect(1.5, lhs_y_start, 4.5, Math.max(lhs_y_end - lhs_y_start, 5));
1355 ctx_lhs.fillRect(1.5, lhs_y_start, 4.5, Math.max(lhs_y_end - lhs_y_start, 5));
1300 ctx_lhs.strokeRect(1.5, lhs_y_start, 4.5, Math.max(lhs_y_end - lhs_y_start, 5));
1356 ctx_lhs.strokeRect(1.5, lhs_y_start, 4.5, Math.max(lhs_y_end - lhs_y_start, 5));
1301
1357
1302 ctx_rhs.beginPath();
1358 ctx_rhs.beginPath();
1303 ctx_rhs.fillStyle = this.settings.fgcolor[change['op']];
1359 ctx_rhs.fillStyle = this.settings.fgcolor[change['op']];
1304 ctx_rhs.strokeStyle = '#000';
1360 ctx_rhs.strokeStyle = '#000';
1305 ctx_rhs.lineWidth = 1.0;
1361 ctx_rhs.lineWidth = 0.5;
1306 ctx_rhs.fillRect(1.5, rhs_y_start, 4.5, Math.max(rhs_y_end - rhs_y_start, 5));
1362 ctx_rhs.fillRect(1.5, rhs_y_start, 4.5, Math.max(rhs_y_end - rhs_y_start, 5));
1307 ctx_rhs.strokeRect(1.5, rhs_y_start, 4.5, Math.max(rhs_y_end - rhs_y_start, 5));
1363 ctx_rhs.strokeRect(1.5, rhs_y_start, 4.5, Math.max(rhs_y_end - rhs_y_start, 5));
1308
1364
1309 if (!this._is_change_in_view(vp, change)) {
1365 if (!this._is_change_in_view(vp, change)) {
1310 continue;
1366 continue;
1311 }
1367 }
1312
1368
1313 lhs_y_start = change['lhs-y-start'];
1369 lhs_y_start = change['lhs-y-start'];
1314 lhs_y_end = change['lhs-y-end'];
1370 lhs_y_end = change['lhs-y-end'];
1315 rhs_y_start = change['rhs-y-start'];
1371 rhs_y_start = change['rhs-y-start'];
1316 rhs_y_end = change['rhs-y-end'];
1372 rhs_y_end = change['rhs-y-end'];
1317
1373
1318 var radius = 3;
1374 var radius = 3;
1319
1375
1320 // draw left box
1376 // draw left box
1321 ctx.beginPath();
1377 ctx.beginPath();
1322 ctx.strokeStyle = this.settings.fgcolor[change['op']];
1378 ctx.strokeStyle = this.settings.fgcolor[change['op']];
1323 ctx.lineWidth = 1;
1379 ctx.lineWidth = 1;
1324
1380
1325 var rectWidth = this.draw_lhs_width;
1381 var rectWidth = this.draw_lhs_width;
1326 var rectHeight = lhs_y_end - lhs_y_start - 1;
1382 var rectHeight = lhs_y_end - lhs_y_start - 1;
1327 var rectX = this.draw_lhs_min;
1383 var rectX = this.draw_lhs_min;
1328 var rectY = lhs_y_start;
1384 var rectY = lhs_y_start;
1329 // top and top top-right corner
1385 // top and top top-right corner
1330
1386
1331 // draw left box
1387 // draw left box
1332 ctx.moveTo(rectX, rectY);
1388 ctx.moveTo(rectX, rectY);
1333 if (navigator.appName == 'Microsoft Internet Explorer') {
1389 if (navigator.appName == 'Microsoft Internet Explorer') {
@@ -1348,7 +1404,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1348 ctx.lineTo(rectX, rectY + rectHeight);
1404 ctx.lineTo(rectX, rectY + rectHeight);
1349 }
1405 }
1350 ctx.stroke();
1406 ctx.stroke();
1351
1407
1352 rectWidth = this.draw_rhs_width;
1408 rectWidth = this.draw_rhs_width;
1353 rectHeight = rhs_y_end - rhs_y_start - 1;
1409 rectHeight = rhs_y_end - rhs_y_start - 1;
1354 rectX = this.draw_rhs_max;
1410 rectX = this.draw_rhs_max;
@@ -1372,7 +1428,7 b' jQuery.extend(Mgly.mergely.prototype, {'
1372 ctx.lineTo(rectX, rectY + rectHeight);
1428 ctx.lineTo(rectX, rectY + rectHeight);
1373 }
1429 }
1374 ctx.stroke();
1430 ctx.stroke();
1375
1431
1376 // connect boxes
1432 // connect boxes
1377 var cx = this.draw_lhs_min + this.draw_lhs_width;
1433 var cx = this.draw_lhs_min + this.draw_lhs_width;
1378 var cy = lhs_y_start + (lhs_y_end + 1 - lhs_y_start) / 2.0;
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 // visible window feedback
1451 // visible window feedback
1396 ctx_lhs.fillStyle = this.settings.vpcolor;
1452 ctx_lhs.fillStyle = this.settings.vpcolor;
1397 ctx_rhs.fillStyle = this.settings.vpcolor;
1453 ctx_rhs.fillStyle = this.settings.vpcolor;
1398
1454
1399 var lto = ex.clhs.height() * ex.visible_page_ratio;
1455 var lto = ex.clhs.height() * ex.visible_page_ratio;
1400 var lfrom = (ex.lhs_scroller.scrollTop() / ex.gutter_height) * ex.clhs.height();
1456 var lfrom = (ex.lhs_scroller.scrollTop() / ex.gutter_height) * ex.clhs.height();
1401 var rto = ex.crhs.height() * ex.visible_page_ratio;
1457 var rto = ex.crhs.height() * ex.visible_page_ratio;
@@ -1406,10 +1462,10 b' jQuery.extend(Mgly.mergely.prototype, {'
1406 this.trace('draw', 'visible_page_ratio', ex.visible_page_ratio);
1462 this.trace('draw', 'visible_page_ratio', ex.visible_page_ratio);
1407 this.trace('draw', 'lhs from', lfrom, 'lhs to', lto);
1463 this.trace('draw', 'lhs from', lfrom, 'lhs to', lto);
1408 this.trace('draw', 'rhs from', rfrom, 'rhs to', rto);
1464 this.trace('draw', 'rhs from', rfrom, 'rhs to', rto);
1409
1465
1410 ctx_lhs.fillRect(1.5, lfrom, 4.5, lto);
1466 ctx_lhs.fillRect(1.5, lfrom, 4.5, lto);
1411 ctx_rhs.fillRect(1.5, rfrom, 4.5, rto);
1467 ctx_rhs.fillRect(1.5, rfrom, 4.5, rto);
1412
1468
1413 ex.clhs.click(function (ev) {
1469 ex.clhs.click(function (ev) {
1414 var y = ev.pageY - ex.lhs_xyoffset.top - (lto / 2);
1470 var y = ev.pageY - ex.lhs_xyoffset.top - (lto / 2);
1415 var sto = Math.max(0, (y / mcanvas_lhs.height) * ex.lhs_scroller.get(0).scrollHeight);
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 ex.crhs.click(function (ev) {
1474 ex.crhs.click(function (ev) {
1419 var y = ev.pageY - ex.rhs_xyoffset.top - (rto / 2);
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 ex.rhs_scroller.scrollTop(sto);
1477 ex.rhs_scroller.scrollTop(sto);
1422 });
1478 });
1423 },
1479 },
@@ -1425,14 +1481,14 b' jQuery.extend(Mgly.mergely.prototype, {'
1425 if(this.settings._debug.indexOf(name) >= 0) {
1481 if(this.settings._debug.indexOf(name) >= 0) {
1426 arguments[0] = name+':';
1482 arguments[0] = name+':';
1427 console.log([].slice.apply(arguments));
1483 console.log([].slice.apply(arguments));
1428 }
1484 }
1429 }
1485 }
1430 });
1486 });
1431
1487
1432 jQuery.pluginMaker = function(plugin) {
1488 jQuery.pluginMaker = function(plugin) {
1433 // add the plugin function as a jQuery plugin
1489 // add the plugin function as a jQuery plugin
1434 jQuery.fn[plugin.prototype.name] = function(options) {
1490 jQuery.fn[plugin.prototype.name] = function(options) {
1435 // get the arguments
1491 // get the arguments
1436 var args = jQuery.makeArray(arguments),
1492 var args = jQuery.makeArray(arguments),
1437 after = args.slice(1);
1493 after = args.slice(1);
1438 var rc = undefined;
1494 var rc = undefined;
@@ -4,11 +4,11 b''
4
4
5 <%def name="js_extra()">
5 <%def name="js_extra()">
6 <script type="text/javascript" src="${h.url('/js/codemirror.js')}"></script>
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 </%def>
8 </%def>
9 <%def name="css_extra()">
9 <%def name="css_extra()">
10 <link rel="stylesheet" type="text/css" href="${h.url('/css/codemirror.css')}"/>
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 </%def>
12 </%def>
13
13
14 <%def name="title()">
14 <%def name="title()">
General Comments 0
You need to be logged in to leave comments. Login now