editor.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. $(document).ready(function() {
  2. function getParameters() {
  3. var parameters = {};
  4. window.location.search.substr(1).split('&').forEach(function(pair) {
  5. if (pair === '') return;
  6. var parts = pair.split('=');
  7. if (parts.length === 2 && parts[1].search(/^(true|1)$/i) >= 0) {
  8. parameters[parts[0]] = true;
  9. }
  10. else if (parts.length === 2 && parts[1].search(/^(false|0)$/i) >= 0) {
  11. parameters[parts[0]] = false;
  12. }
  13. else parameters[parts[0]] = parts[1] && decodeURIComponent(parts[1].replace(/\+/g, ' '));
  14. });
  15. return {
  16. get: function(name, defaultValue) {
  17. if (parameters.hasOwnProperty(name)) return parameters[name];
  18. return defaultValue;
  19. }
  20. };
  21. }
  22. var parameters = getParameters();
  23. if (parameters.get('test', false)) {
  24. var li = $('<li>Tests</li>');
  25. var ul = $('<ul>');
  26. for (var i = 1; i <= 8; ++i) {
  27. ul.append($('<li id="examples-test' + i + '">Test ' + i + '</li>'));
  28. }
  29. li.append(ul);
  30. $('#main-menu').append(li);
  31. }
  32. function handleFind(column) {
  33. if (!column.length) {
  34. return false;
  35. }
  36. var ed = $('#mergely');
  37. var find = column.find('.find');
  38. var input = find.find('input[type="text"]');
  39. var side = column.attr('id').indexOf('-lhs') > 0 ? 'lhs' : 'rhs';
  40. var origautoupdate = ed.mergely('options').autoupdate;
  41. find.slideDown('fast', function() {
  42. input.focus();
  43. // disable autoupdate, clear both sides of diff
  44. ed.mergely('options', {autoupdate: false});
  45. ed.mergely('unmarkup');
  46. });
  47. find.find('.find-prev').click(function() {
  48. ed.mergely('search', side, input.val(), 'prev');
  49. });
  50. find.find('.find-next').click(function() {
  51. ed.mergely('search', side, input.val(), 'next');
  52. });
  53. find.find('.find-close').click(function() {
  54. find.css('display', 'none')
  55. ed.mergely('options', {autoupdate: origautoupdate});
  56. });
  57. input.keydown(function(evt) {
  58. if (evt.which != 13 && evt.which != 27) return true;
  59. if (evt.which == 27) {
  60. find.css('display', 'none');
  61. ed.mergely('options', {autoupdate: origautoupdate});
  62. }
  63. ed.mergely('search', side, input.val());
  64. return false;
  65. });
  66. }
  67. $(document).keydown(function(event) {
  68. if (!( String.fromCharCode(event.which).toLowerCase() == 'f' && event.ctrlKey)) return true;
  69. event.preventDefault();
  70. var range = window.getSelection().getRangeAt(0);
  71. var column = $(range.commonAncestorContainer).parents('.mergely-column');
  72. handleFind(column);
  73. return false;
  74. });
  75. String.prototype.random = function(length) {
  76. var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
  77. var randomstring = ''
  78. for (var i=0; i<length; i++) {
  79. var rnum = Math.floor(Math.random() * chars.length);
  80. randomstring += chars.substring(rnum,rnum+1);
  81. }
  82. return randomstring;
  83. }
  84. // body is pre-hidden for better rendering
  85. $('body').css("visibility", "");
  86. var ed = $('#mergely');
  87. var menu = $('#main-menu');
  88. var toolbar = $('#toolbar');
  89. ed.mergely({
  90. width: 'auto',
  91. height: 'auto',
  92. cmsettings: {
  93. lineNumbers: true,
  94. readOnly: false
  95. }
  96. });
  97. ed.mergely("lhs", $("#historyContent").html());
  98. ed.mergely("rhs", $("#documentContent").html());
  99. // if (parameters.get('lhs', null)) {
  100. // var url = parameters.get('lhs');
  101. // crossdomainGET(ed, 'lhs', url);
  102. // }
  103. // if (parameters.get('rhs', null)) {
  104. // var url = parameters.get('rhs');
  105. // crossdomainGET(ed, 'rhs', url);
  106. // }
  107. // set query string options
  108. var urloptions = {};
  109. var optmap = {
  110. au: 'autoupdate',
  111. ws: 'ignorews',
  112. cs: 'ignorecase',
  113. sb: 'sidebar',
  114. vp: 'viewport',
  115. wl: 'wrap_lines',
  116. ln: 'line_numbers'
  117. };
  118. var doopt = false;
  119. for (var name in optmap) {
  120. if (!optmap.hasOwnProperty(name)) continue;
  121. if (parameters.get(name, null) !== null) {
  122. urloptions[optmap[name]] = parameters.get(name);
  123. doopt = true;
  124. }
  125. }
  126. if (parameters.get('rm', null) !== null) {
  127. // special-case url property
  128. urloptions.rhs_margin = parameters.get('rm') ? 'left' : 'right';
  129. }
  130. if (doopt) {
  131. // apply query-string options
  132. ed.mergely('options', urloptions);
  133. }
  134. // set query string colors
  135. // cb: change border
  136. // cg: change background
  137. // ab: added border
  138. // ag: added background
  139. // db: deleted border
  140. // dg: deleted background
  141. var color_defaults = {
  142. cb: 'cccccc', cg: 'fafafa',
  143. ab: 'a3d1ff', ag: 'ddeeff',
  144. db: 'ff7f7f', dg: 'ffe9e9'
  145. };
  146. applyParameterCss(false);
  147. //history.pushState({}, null, '');
  148. window.addEventListener('popstate', function(ev) {
  149. if (ev.state) {
  150. parameters = getParameters();
  151. applyParameterCss(false);
  152. }
  153. });
  154. // Load
  155. if (key.length === 8) {
  156. $.when(
  157. $.ajax({
  158. type: 'GET', async: true, dataType: 'text',
  159. data: { 'key':key, 'name': 'lhs' },
  160. url: '/ajax/handle_get.php',
  161. success: function (response) {
  162. ed.mergely('lhs', response);
  163. },
  164. error: function(xhr, ajaxOptions, thrownError){
  165. }
  166. }),
  167. $.ajax({
  168. type: 'GET', async: true, dataType: 'text',
  169. data: { 'key':key, 'name': 'rhs' },
  170. url: '/ajax/handle_get.php',
  171. success: function (response) {
  172. ed.mergely('rhs', response);
  173. },
  174. error: function(xhr, ajaxOptions, thrownError){
  175. }
  176. })
  177. ).done(function() {
  178. var anchor = window.location.hash.substring(1);
  179. if (anchor) {
  180. // if an anchor has been provided, then parse the anchor in the
  181. // form of: 'lhs' or 'rhs', followed by a line, e.g: lhs100.
  182. var m = anchor.match(/([lr]hs)([0-9]+)/);
  183. if (m && m.length == 3) {
  184. console.log(m);
  185. ed.mergely('scrollTo', m[1], parseInt(m[2],10));
  186. }
  187. }
  188. });
  189. }
  190. // find
  191. var find = $('.find');
  192. var flhs = find.clone().attr('id', 'mergely-editor-lhs-find');
  193. var frhs = find.clone().attr('id', 'mergely-editor-rhs-find');
  194. $('#mergely-editor-lhs').append(flhs);
  195. $('#mergely-editor-rhs').append(frhs);
  196. find.remove();
  197. var iconconf = {
  198. 'options-autodiff': {
  199. get: function() { return ed.mergely('options').autoupdate },
  200. set: function(value) {
  201. var au = !ed.mergely('options').autoupdate;
  202. ed.mergely('options', {autoupdate: au});
  203. var params = updateQueryStringParam('au', au ? 1 : 0, 1);
  204. updateHistory(params);
  205. }
  206. },
  207. 'options-ignorews': {
  208. get: function() { return ed.mergely('options').ignorews },
  209. set: function(value) {
  210. var ws = !ed.mergely('options').ignorews;
  211. ed.mergely('options', {ignorews: ws});
  212. var params = updateQueryStringParam('ws', ws ? 1 : 0, 0);
  213. updateHistory(params);
  214. }
  215. },
  216. 'options-ignorecase': {
  217. get: function() { return ed.mergely('options').ignorecase },
  218. set: function(value) {
  219. var cs = !ed.mergely('options').ignorecase;
  220. ed.mergely('options', {ignorecase: cs});
  221. var params = updateQueryStringParam('cs', cs ? 1 : 0, 0);
  222. updateHistory(params);
  223. }
  224. },
  225. 'options-sidebars': {
  226. get: function() { console.log('sidebar', this); return ed.mergely('options').sidebar },
  227. set: function(value) {
  228. var sb = !ed.mergely('options').sidebar;
  229. ed.mergely('options', {sidebar: sb});
  230. var params = updateQueryStringParam('sb', sb ? 1 : 0, 1);
  231. updateHistory(params);
  232. }
  233. },
  234. 'options-viewport': {
  235. get: function() { console.log('viewport', this); return ed.mergely('options').viewport },
  236. set: function(value) {
  237. var vp = !ed.mergely('options').viewport;
  238. ed.mergely('options', {viewport: vp});
  239. var params = updateQueryStringParam('vp', vp ? 1 : 0, 0);
  240. updateHistory(params);
  241. }
  242. },
  243. 'options-swapmargin': {
  244. get: function() { return (ed.mergely('options').rhs_margin == 'left'); },
  245. set: function(value) {
  246. var rm = ed.mergely('options').rhs_margin == 'left' ? 'right' : 'left';
  247. ed.mergely('options', {rhs_margin: rm });
  248. var params = updateQueryStringParam('rm', rm == 'left' ? 1 : 0, 0);
  249. updateHistory(params);
  250. }
  251. },
  252. 'options-linenumbers': {
  253. get: function() { console.log('wrap', this); return ed.mergely('options').line_numbers },
  254. set: function(value) {
  255. var ln = !ed.mergely('options').line_numbers;
  256. ed.mergely('options', {line_numbers: ln});
  257. var params = updateQueryStringParam('ln', ln ? 1 : 0, 1);
  258. updateHistory(params);
  259. }
  260. },
  261. 'options-wrap': {
  262. get: function() { console.log('wrap', this); return ed.mergely('options').wrap_lines },
  263. set: function(value) {
  264. var wl = !ed.mergely('options').wrap_lines;
  265. ed.mergely('options', {wrap_lines: wl});
  266. var params = updateQueryStringParam('wl', wl ? 1 : 0, 0);
  267. updateHistory(params);
  268. }
  269. },
  270. 'edit-left-readonly': {
  271. get: function() { return ed.mergely('cm', 'lhs').getOption('readOnly'); },
  272. set: function(value) { ed.mergely('cm', 'lhs').setOption('readOnly', value); }
  273. },
  274. 'edit-right-readonly': {
  275. get: function() { return ed.mergely('cm', 'rhs').getOption('readOnly'); },
  276. set: function(value) { ed.mergely('cm', 'rhs').setOption('readOnly', value); }
  277. }
  278. }
  279. var menu_opts = {
  280. hasIcon: function(id) {
  281. return iconconf.hasOwnProperty(id);
  282. },
  283. getIcon: function(id) {
  284. if (iconconf[id].get()) return 'icon-check';
  285. }
  286. };
  287. function handle_operation(id) {
  288. if (id == 'file-new') {
  289. window.location = '/editor';
  290. }
  291. else if (id === 'file-save') {
  292. var rhs = ed.mergely('get', 'rhs');
  293. if(window.top.hasOwnProperty("editor")){
  294. if(window.top.editor.hasOwnProperty("$txt")){
  295. window.top.editor.$txt.html(rhs);
  296. }else{
  297. window.top.editor.clear();
  298. window.top.editor.insertValue(rhs);
  299. }
  300. window.top.layer.closeAll();
  301. }
  302. }else if (id == 'file-share') {
  303. handleShare(ed);
  304. }
  305. else if (id == 'file-import') {
  306. importFiles(ed);
  307. }
  308. else if (id == 'edit-left-undo') {
  309. ed.mergely('cm', 'lhs').getDoc().undo();
  310. }
  311. else if (id == 'edit-left-redo') {
  312. ed.mergely('cm', 'lhs').getDoc().redo();
  313. }
  314. else if (id == 'edit-right-undo') {
  315. ed.mergely('cm', 'rhs').getDoc().undo();
  316. }
  317. else if (id == 'edit-right-redo') {
  318. ed.mergely('cm', 'rhs').getDoc().redo();
  319. }
  320. else if (id == 'edit-left-find') {
  321. handleFind(ed.find('#mergely-editor-lhs'));
  322. }
  323. else if (id == 'edit-left-merge-right') {
  324. ed.mergely('mergeCurrentChange', 'rhs');
  325. }
  326. else if (id == 'edit-left-merge-right-file') {
  327. ed.mergely('merge', 'rhs');
  328. }
  329. else if ([
  330. 'edit-left-readonly',
  331. 'edit-right-readonly',
  332. 'options-autodiff',
  333. 'options-sidebars',
  334. 'options-swapmargin',
  335. 'options-viewport',
  336. 'options-ignorews',
  337. 'options-ignorecase',
  338. 'options-wrap',
  339. 'options-linenumbers',
  340. ].indexOf(id) >= 0) {
  341. iconconf[id].set(!iconconf[id].get());
  342. menu.wickedmenu('update', id);
  343. }
  344. else if (id == 'edit-left-clear') {
  345. ed.mergely('clear', 'lhs');
  346. }
  347. else if (id == 'edit-right-find') {
  348. handleFind(ed.find('#mergely-editor-rhs'));
  349. }
  350. else if (id == 'edit-right-merge-left') {
  351. ed.mergely('mergeCurrentChange', 'lhs');
  352. }
  353. else if (id == 'edit-right-merge-left-file') {
  354. ed.mergely('merge', 'lhs');
  355. }
  356. else if (id == 'edit-right-clear') {
  357. ed.mergely('clear', 'rhs');
  358. }
  359. else if (id == 'options-colors') {
  360. colorSettings(ed);
  361. }
  362. else if (id == 'view-swap') {
  363. ed.mergely('swap');
  364. }
  365. else if (id == 'view-refresh') {
  366. ed.mergely('update');
  367. }
  368. else if (id == 'view-change-next') {
  369. ed.mergely('scrollToDiff', 'next');
  370. }
  371. else if (id == 'view-change-prev') {
  372. ed.mergely('scrollToDiff', 'prev');
  373. }
  374. else if (id == 'view-clear') {
  375. ed.mergely('unmarkup');
  376. }
  377. else if (id.indexOf('examples-') == 0) {
  378. var test_config = {
  379. test1: {lhs: 'one\ntwo\nthree', rhs: 'two\nthree'},
  380. test2: {lhs: 'two\nthree', rhs: 'one\ntwo\nthree'},
  381. test3: {lhs: 'one\nthree', rhs: 'one\ntwo\nthree'},
  382. test4: {lhs: 'one\ntwo\nthree', rhs: 'one\nthree'},
  383. test5: {lhs: 'to bee, or not to be', rhs: 'to be, or not to bee'},
  384. test6: {lhs: 'to be, or not to be z', rhs: 'to be, to be'},
  385. test7: {lhs: 'remained, & to assume', rhs: 'and to assume'},
  386. test8: {lhs: 'to be, or not to be', rhs: 'to be, or not to be'}
  387. };
  388. var test = id.split('examples-')[1];
  389. ed.mergely('lhs', test_config[test]['lhs']);
  390. ed.mergely('rhs', test_config[test]['rhs']);
  391. }
  392. return false;
  393. }
  394. menu.wickedmenu(menu_opts).bind('selected', function(ev, id) {
  395. return handle_operation(id);
  396. });
  397. toolbar.wickedtoolbar({}).bind('selected', function(ev, id) {
  398. if (!id) return false;
  399. return handle_operation(id.replace(/^tb-/, ''));
  400. });
  401. toolbar.find('li[title]').tipsy({opacity: 1});
  402. menu.find('li[title]').tipsy({opacity: 1, delayIn: 1000, gravity: 'w'});
  403. function handleShare(ed) {
  404. var fork = $(this).attr('id') == 'fork';
  405. if (key == '') key = ''.random(8);
  406. var count = 0;
  407. function post_save(side, text) {
  408. $.ajax({
  409. type: 'POST', async: true, dataType: 'text',
  410. url: '/ajax/handle_file.php',
  411. data: { 'key': key, 'name': side, 'content': text },
  412. success: function (nkey) {
  413. ++count;
  414. if (count == 2) {
  415. var url = '/ajax/handle_save.php?key=' + key;
  416. if (fork) url += '&nkey=' + ''.random(8);
  417. $.ajax({
  418. type: 'GET', async: false, dataType: 'text',
  419. url: url,
  420. success: function (nkey) {
  421. // redirect
  422. if (nkey.length) window.location.href = '/' + $.trim(nkey) + '/';
  423. },
  424. error: function(xhr, ajaxOptions, thrownError){
  425. }
  426. });
  427. }
  428. },
  429. error: function(xhr, ajaxOptions, thrownError){
  430. alert(thrownError);
  431. }
  432. });
  433. }
  434. function save_files() {
  435. var lhs = ed.mergely('get', 'lhs');
  436. var rhs = ed.mergely('get', 'rhs');
  437. post_save('lhs', lhs);
  438. post_save('rhs', rhs);
  439. }
  440. $( '#dialog-confirm' ).dialog({
  441. resizable: false, width: 350, modal: true,
  442. buttons: {
  443. 'Save for Sharing': function() {
  444. $( this ).dialog( 'close' );
  445. save_files();
  446. },
  447. Cancel: function() {
  448. $( this ).dialog( 'close' );
  449. }
  450. }
  451. });
  452. }
  453. function crossdomainGET(ed, side, url) {
  454. $.ajax({
  455. type: 'GET', dataType: 'text',
  456. data: {url: url},
  457. url: '/ajax/handle_crossdomain.php',
  458. contentType: 'text/plain',
  459. success: function (response) {
  460. ed.mergely(side, response);
  461. },
  462. error: function(xhr, ajaxOptions, thrownError){
  463. console.error('error', xhr, ajaxOptions, thrownError);
  464. }
  465. });
  466. }
  467. function importFiles(ed) {
  468. // -------------
  469. // file uploader - html5 file upload to browser
  470. function file_load(target, side) {
  471. var file = target.files[0];
  472. var reader = new FileReader();
  473. var $target = $(target);
  474. function trigger(name, event) { $target.trigger(name, event); }
  475. reader.onloadstart = function(evt) { trigger('start'); }
  476. reader.onprogress = function(evt) { trigger('progress', evt); }
  477. reader.onload = function(evt) { trigger('loaded', evt.target.result); }
  478. reader.onerror = function (evt) {
  479. alert(evt.target.error.name);
  480. }
  481. try {
  482. reader.readAsText(file, 'UTF-8');
  483. }
  484. catch (e) {
  485. console.error(e);
  486. alert(e);
  487. }
  488. }
  489. var file_data = {};
  490. $('#file-lhs, #file-rhs').change(function (evt) {
  491. var re = new RegExp('.*[\\\\/](.*)$');
  492. var match = re.exec($(this).val());
  493. var fname = match ? match[1] : 'unknown';
  494. var progressbar = $('#' + evt.target.id + '-progress');
  495. file_load(evt.target);
  496. $(evt.target).bind('start', function(ev){
  497. $(evt.target).css('display', 'none');
  498. progressbar.css('display', 'inline-block');
  499. });
  500. $(evt.target).bind('progress', function(ev, progress){
  501. var loaded = (progress.loaded / progress.total) * 100;
  502. progressbar.find('> .progress-label').text(loaded + '%');
  503. progressbar.progressbar('value', loaded);
  504. });
  505. $(evt.target).bind('loaded', function(ev, file){
  506. progressbar.progressbar('value', 100);
  507. progressbar.find('> .progress-label').text(fname);
  508. file_data[evt.target.id] = file;
  509. });
  510. });
  511. $('#file-lhs-progress').progressbar({value: 0});
  512. $('#file-rhs-progress').progressbar({value: 0});
  513. $('#dialog-upload .tabs').tabs();
  514. function callbackName(data) {
  515. console.log('callbackName', data);
  516. }
  517. $('#dialog-upload').dialog({
  518. dialogClass: 'no-title',
  519. resizable: false,
  520. width: '450px',
  521. modal: true,
  522. buttons: {
  523. Import: function() {
  524. $(this).dialog('close');
  525. var urls = { lhs: $('#url-lhs').val(), rhs: $('#url-rhs').val() };
  526. for (var side in urls) {
  527. var url = urls[side];
  528. if (!url) continue;
  529. crossdomainGET(ed, side, url);
  530. }
  531. if (file_data.hasOwnProperty('file-lhs')) {
  532. ed.mergely('lhs', file_data['file-lhs']);
  533. }
  534. if (file_data.hasOwnProperty('file-rhs')) {
  535. ed.mergely('rhs', file_data['file-rhs']);
  536. }
  537. },
  538. Cancel: function() {
  539. $(this).dialog('close');
  540. }
  541. }
  542. });
  543. }
  544. function colorSettings(ed) {
  545. // get current settings
  546. var sd = $('<span style="display:none" class="mergely ch d lhs start end">C</span>');
  547. var sa = $('<span style="display:none" class="mergely bg a rhs start end">C</span>');
  548. var sc = $('<span style="display:none" class="mergely c rhs start end">C</span>');
  549. $('body').append(sd);
  550. $('body').append(sa);
  551. $('body').append(sc);
  552. var conf = {
  553. 'c-border': {id: '#c-border', getColor: function() { return sc.css('border-top-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
  554. 'c-bg': {id: '#c-bg', getColor: function() { return sc.css('background-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
  555. 'a-border': {id: '#a-border', getColor: function() { return sa.css('border-top-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
  556. 'a-bg': {id: '#a-bg', getColor: function() { return sa.css('background-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
  557. 'd-border': {id: '#d-border', getColor: function() { return sd.css('border-top-color'); }, setColor: function(color) { $('#'+this.id).val(color) }},
  558. 'd-bg': {id: '#d-bg', getColor: function() { return sd.css('background-color'); }, setColor: function(color) { $('#'+this.id).val(color) }}
  559. };
  560. $.each(conf, function(key, item){$(item.id).val(item.getColor()); });
  561. var f = $.farbtastic('#picker');
  562. $('.colorwell').each(function(){ f.linkTo(this); }).focus(function(){
  563. var tthis = $(this);
  564. f.linkTo(this);
  565. var item = conf[tthis.attr('id')];
  566. f.setColor(item.getColor());
  567. });
  568. $('#dialog-colors').dialog({
  569. width: 490, modal: true,
  570. buttons: {
  571. Apply: function() {
  572. var cborder = $('#c-border').val();
  573. var aborder = $('#a-border').val();
  574. var dborder = $('#d-border').val();
  575. var abg = $('#a-bg').val();
  576. var dbg = $('#d-bg').val();
  577. var cbg = $('#c-bg').val();
  578. var textCss = makeColorCss(cborder, cbg, aborder, abg, dborder, dbg);
  579. applyColorCss(textCss, cborder, cbg, aborder, abg, dborder, dbg, true);
  580. },
  581. Reset: function() {
  582. },
  583. Close: function() {
  584. $(this).dialog('close');
  585. }
  586. }
  587. });
  588. }
  589. function makeColorCss(changeBorder, changeBackground, addedBorder, addedBackground, deletedBorder, deletedBackground) {
  590. var text =
  591. '.mergely.a.rhs.start{border-top-color:' + addedBorder + ';}\n\
  592. .mergely.a.lhs.start.end,\n\
  593. .mergely.a.rhs.end{border-bottom-color:' + addedBorder + ';}\n\
  594. .mergely.a.rhs{background-color:' + addedBackground + ';}\n\
  595. .mergely.d.lhs{background-color:' + deletedBackground + ';}\n\
  596. .mergely.d.lhs.end,\n\
  597. .mergely.d.rhs.start.end{border-bottom-color:' + deletedBorder + ';}\n\
  598. .mergely.d.rhs.start.end.first{border-top-color:' + deletedBorder + ';}\n\
  599. .mergely.d.lhs.start{border-top-color:' + deletedBorder + ';}\n\
  600. .mergely.c.lhs,\n\
  601. .mergely.c.rhs{background-color:' + changeBackground + ';}\n\
  602. .mergely.c.lhs.start,\n\
  603. .mergely.c.rhs.start{border-top-color:' + changeBorder + ';}\n\
  604. .mergely.c.lhs.end,\n\
  605. .mergely.c.rhs.end{border-bottom-color:' + changeBorder + ';}\n\
  606. .mergely.ch.a.rhs{background-color:' + addedBackground + ';}\n\
  607. .mergely.ch.d.lhs{background-color:' + deletedBackground + ';color: #888;}';
  608. return text;
  609. }
  610. function applyParameterCss(saveState) {
  611. var cb = '#' + parameters.get('cb',color_defaults.cb),
  612. cg = '#' + parameters.get('cg',color_defaults.cg),
  613. ab = '#' + parameters.get('ab',color_defaults.ab),
  614. ag = '#' + parameters.get('ag',color_defaults.ag),
  615. db = '#' + parameters.get('db',color_defaults.db),
  616. dg = '#' + parameters.get('dg',color_defaults.dg);
  617. applyColorCss(makeColorCss(cb, cg, ab, ag, db, dg), cb, cg, ab, ag, db, dg, saveState);
  618. }
  619. function applyColorCss(cssText, changeBorder, changeBackground, addedBorder, addedBackground, deletedBorder, deletedBackground, saveState) {
  620. $('<style type="text/css">' + cssText + '</style>').appendTo('head');
  621. ed.mergely('options', {
  622. fgcolor:{a:addedBorder,c:changeBorder,d:deletedBorder}
  623. });
  624. var params = updateQueryStringParam('cb', changeBorder.replace(/#/g, ''), color_defaults.cb);
  625. params = updateQueryStringParam('cg', changeBackground.replace(/#/g, ''), color_defaults.cg, params);
  626. params = updateQueryStringParam('ab', addedBorder.replace(/#/g, ''), color_defaults.ab, params);
  627. params = updateQueryStringParam('ag', addedBackground.replace(/#/g, ''), color_defaults.ag, params);
  628. params = updateQueryStringParam('db', deletedBorder.replace(/#/g, ''), color_defaults.db, params);
  629. params = updateQueryStringParam('dg', deletedBackground.replace(/#/g, ''), color_defaults.dg, params);
  630. if (saveState) {
  631. updateHistory(params);
  632. }
  633. }
  634. function updateHistory(params) {
  635. var baseUrl = [location.protocol, '//', location.host, location.pathname].join('');
  636. window.history.pushState({}, null, baseUrl + params);
  637. }
  638. // Explicitly save/update a url parameter using HTML5's replaceState().
  639. function updateQueryStringParam(key, value, defaultValue, urlQueryString) {
  640. urlQueryString = urlQueryString || document.location.search;
  641. var parts = urlQueryString.replace(/^\?/, '').split(/&/), found = false;
  642. for (var i in parts) {
  643. if (parts[i].startsWith(key + '=')) {
  644. found = true;
  645. if (value === defaultValue) {
  646. // value is default value, remove option
  647. parts.splice(i, 1);
  648. }
  649. else {
  650. // make new value
  651. parts[i] = key + '=' + value;
  652. }
  653. break;
  654. }
  655. else if (parts[i].length === 0) {
  656. parts.splice(i, 1);
  657. break;
  658. }
  659. }
  660. if (!found) {
  661. parts.push(key + '=' + value);
  662. }
  663. return (parts.length) ? '?' + parts.join('&') : '';
  664. }
  665. });