Skip to content

Repository files navigation

ice.js

Ice is a track changes implementation, built in javascript, for anything that is contenteditable on the web. Conceived by the CMS Group at The New York Times, ice is powering the editor used for writing articles in the newsroom.

Demo

Try it

Download

v0.5.0

Features

  • Track multi-user inserts and deletes with the option to turn on and off tracking or highlighting.
  • A robust API to accept and reject changes, get clean content, and add a lot of configuration.
  • Plugins for tinymce and wordpress.
  • Optional plugins to track copy-cut-pasting, convert smart quotes, and create em-dashes.

Get Started


Contenteditable initialization - If you are comfortable with maintaining your own text editing utilities, then you can initialize ice on any block element:

vartracker=newice.InlineChangeEditor({// element to track - ice will make it contenteditableelement: document.getElementById('mytextelement'),// tell ice to setup/handle events on the `element`handleEvents: true,// set a user object to associate with each changecurrentUser: {id: 1,name: 'Miss T'}});// setup and start event handling for track changestracker.startTracking();

Additional options:

vartracker=newice.InlineChangeEditor({element: document.getElementById('mytextelement'),handleEvents: true,currentUser: {id: 1,name: 'Miss T'},// optional pluginsplugins: [// Add title attributes to changes for hover info'IceAddTitlePlugin',// Two successively typed dashes get converted into an em-dash'IceEmdashPlugin',// Track content that is cut and pasted{name: 'IceCopyPastePlugin',settings: {// List of tags and attributes to preserve when cleaning a pastepreserve: 'p,a[href],span[id,class]em,strong'}}]}).startTracking();

Useful utilities in the API:

acceptChange, rejectChange

// Accept/Reject the change at the current range/cursor position or at the given `optionalNode`tracker.acceptChange(optionalNode);tracker.rejectChange(optionalNode);

acceptAll, rejectAll

// Accept/Reject all of the changes in the editable region.tracker.acceptAll();tracker.rejectAll();

getCleanContent

// Returns a clean version, without tracking tags, of the content in the editable element or// out of the optional `body` param. After cleaning, the `optionalCallback` param is called// which should further modify and return the body.tracker.getCleanContent(optionalBody,optionalCallback);

setCurrentUser

// Set the desired user to track. A user object has the following properties: { `id`, `name` }.tracker.setCurrentUser({id: 2,name: 'Miss T'});

getChanges

// Get the internal list of change objects which are modeled from all of the change tracking// nodes in the DOM. This might be useful to add a more sophisticated change tracking UI/UX.// The list is key'ed with the unique change ids (`cid attribute`) and points to an object// with metadata for a change: [changeid] => {`type`, `time`, `userid`, `username`}varchanges=tracker.getChanges();

Tinymce initialization - Add the ice plugin to your tinymce plugins directory and include the following in your tinymce init:

tinymce.init({plugins: 'ice',theme_advanced_buttons1: 'ice_togglechanges,ice_toggleshowchanges,iceacceptall,icerejectall,iceaccept,icereject',ice: {user: {name: 'Miss T',id: 1},preserveOnPaste: 'p,a[href],i,em,strong',// Optional param - defaults to the css found in the plugin directorycss: 'http://example.com/custom.css'},
...
});

Limitations/Dependencies

  • ice needs to be initialized after the DOM ready event fires.
  • Wordpress support is limited. We need contribution from any willing WordPress developers.
  • Browser support is limited to Firefox (5+) and Webkit browsers, and minimal support for IE8+.

Changelog

Master

  • Fixes bug where Webkit browsers were throwing errors when the letter "v" was pressed.

0.5.0

  • Fixes cut, copy, paste for Firefox and Webkit browsers.
  • Fixes delete tracking in webkit browsers.

License

GPL 2.0

About

track changes with javascript

Resources

Stars

1.7k stars

Watchers

59 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - nytimes/ice: track changes with javascript · GitHub
Skip to content

Repository files navigation

ice.js

Ice is a track changes implementation, built in javascript, for anything that is contenteditable on the web. Conceived by the CMS Group at The New York Times, ice is powering the editor used for writing articles in the newsroom.

Demo

Try it

Download

v0.5.0

Features

  • Track multi-user inserts and deletes with the option to turn on and off tracking or highlighting.
  • A robust API to accept and reject changes, get clean content, and add a lot of configuration.
  • Plugins for tinymce and wordpress.
  • Optional plugins to track copy-cut-pasting, convert smart quotes, and create em-dashes.

Get Started


Contenteditable initialization - If you are comfortable with maintaining your own text editing utilities, then you can initialize ice on any block element:

vartracker=newice.InlineChangeEditor({// element to track - ice will make it contenteditableelement: document.getElementById('mytextelement'),// tell ice to setup/handle events on the `element`handleEvents: true,// set a user object to associate with each changecurrentUser: {id: 1,name: 'Miss T'}});// setup and start event handling for track changestracker.startTracking();

Additional options:

vartracker=newice.InlineChangeEditor({element: document.getElementById('mytextelement'),handleEvents: true,currentUser: {id: 1,name: 'Miss T'},// optional pluginsplugins: [// Add title attributes to changes for hover info'IceAddTitlePlugin',// Two successively typed dashes get converted into an em-dash'IceEmdashPlugin',// Track content that is cut and pasted{name: 'IceCopyPastePlugin',settings: {// List of tags and attributes to preserve when cleaning a pastepreserve: 'p,a[href],span[id,class]em,strong'}}]}).startTracking();

Useful utilities in the API:

acceptChange, rejectChange

// Accept/Reject the change at the current range/cursor position or at the given `optionalNode`tracker.acceptChange(optionalNode);tracker.rejectChange(optionalNode);

acceptAll, rejectAll

// Accept/Reject all of the changes in the editable region.tracker.acceptAll();tracker.rejectAll();

getCleanContent

// Returns a clean version, without tracking tags, of the content in the editable element or// out of the optional `body` param. After cleaning, the `optionalCallback` param is called// which should further modify and return the body.tracker.getCleanContent(optionalBody,optionalCallback);

setCurrentUser

// Set the desired user to track. A user object has the following properties: { `id`, `name` }.tracker.setCurrentUser({id: 2,name: 'Miss T'});

getChanges

// Get the internal list of change objects which are modeled from all of the change tracking// nodes in the DOM. This might be useful to add a more sophisticated change tracking UI/UX.// The list is key'ed with the unique change ids (`cid attribute`) and points to an object// with metadata for a change: [changeid] => {`type`, `time`, `userid`, `username`}varchanges=tracker.getChanges();

Tinymce initialization - Add the ice plugin to your tinymce plugins directory and include the following in your tinymce init:

tinymce.init({plugins: 'ice',theme_advanced_buttons1: 'ice_togglechanges,ice_toggleshowchanges,iceacceptall,icerejectall,iceaccept,icereject',ice: {user: {name: 'Miss T',id: 1},preserveOnPaste: 'p,a[href],i,em,strong',// Optional param - defaults to the css found in the plugin directorycss: 'http://example.com/custom.css'},
...
});

Limitations/Dependencies

  • ice needs to be initialized after the DOM ready event fires.
  • Wordpress support is limited. We need contribution from any willing WordPress developers.
  • Browser support is limited to Firefox (5+) and Webkit browsers, and minimal support for IE8+.

Changelog

Master

  • Fixes bug where Webkit browsers were throwing errors when the letter "v" was pressed.

0.5.0

  • Fixes cut, copy, paste for Firefox and Webkit browsers.
  • Fixes delete tracking in webkit browsers.

License

GPL 2.0

About

track changes with javascript

Resources

Stars

1.7k stars

Watchers

59 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - nytimes/ice: track changes with javascript · GitHub
Skip to content

Repository files navigation

ice.js

Ice is a track changes implementation, built in javascript, for anything that is contenteditable on the web. Conceived by the CMS Group at The New York Times, ice is powering the editor used for writing articles in the newsroom.

Demo

Try it

Download

v0.5.0

Features

  • Track multi-user inserts and deletes with the option to turn on and off tracking or highlighting.
  • A robust API to accept and reject changes, get clean content, and add a lot of configuration.
  • Plugins for tinymce and wordpress.
  • Optional plugins to track copy-cut-pasting, convert smart quotes, and create em-dashes.

Get Started


Contenteditable initialization - If you are comfortable with maintaining your own text editing utilities, then you can initialize ice on any block element:

vartracker=newice.InlineChangeEditor({// element to track - ice will make it contenteditableelement: document.getElementById('mytextelement'),// tell ice to setup/handle events on the `element`handleEvents: true,// set a user object to associate with each changecurrentUser: {id: 1,name: 'Miss T'}});// setup and start event handling for track changestracker.startTracking();

Additional options:

vartracker=newice.InlineChangeEditor({element: document.getElementById('mytextelement'),handleEvents: true,currentUser: {id: 1,name: 'Miss T'},// optional pluginsplugins: [// Add title attributes to changes for hover info'IceAddTitlePlugin',// Two successively typed dashes get converted into an em-dash'IceEmdashPlugin',// Track content that is cut and pasted{name: 'IceCopyPastePlugin',settings: {// List of tags and attributes to preserve when cleaning a pastepreserve: 'p,a[href],span[id,class]em,strong'}}]}).startTracking();

Useful utilities in the API:

acceptChange, rejectChange

// Accept/Reject the change at the current range/cursor position or at the given `optionalNode`tracker.acceptChange(optionalNode);tracker.rejectChange(optionalNode);

acceptAll, rejectAll

// Accept/Reject all of the changes in the editable region.tracker.acceptAll();tracker.rejectAll();

getCleanContent

// Returns a clean version, without tracking tags, of the content in the editable element or// out of the optional `body` param. After cleaning, the `optionalCallback` param is called// which should further modify and return the body.tracker.getCleanContent(optionalBody,optionalCallback);

setCurrentUser

// Set the desired user to track. A user object has the following properties: { `id`, `name` }.tracker.setCurrentUser({id: 2,name: 'Miss T'});

getChanges

// Get the internal list of change objects which are modeled from all of the change tracking// nodes in the DOM. This might be useful to add a more sophisticated change tracking UI/UX.// The list is key'ed with the unique change ids (`cid attribute`) and points to an object// with metadata for a change: [changeid] => {`type`, `time`, `userid`, `username`}varchanges=tracker.getChanges();

Tinymce initialization - Add the ice plugin to your tinymce plugins directory and include the following in your tinymce init:

tinymce.init({plugins: 'ice',theme_advanced_buttons1: 'ice_togglechanges,ice_toggleshowchanges,iceacceptall,icerejectall,iceaccept,icereject',ice: {user: {name: 'Miss T',id: 1},preserveOnPaste: 'p,a[href],i,em,strong',// Optional param - defaults to the css found in the plugin directorycss: 'http://example.com/custom.css'},
...
});

Limitations/Dependencies

  • ice needs to be initialized after the DOM ready event fires.
  • Wordpress support is limited. We need contribution from any willing WordPress developers.
  • Browser support is limited to Firefox (5+) and Webkit browsers, and minimal support for IE8+.

Changelog

Master

  • Fixes bug where Webkit browsers were throwing errors when the letter "v" was pressed.

0.5.0

  • Fixes cut, copy, paste for Firefox and Webkit browsers.
  • Fixes delete tracking in webkit browsers.

License

GPL 2.0

About

track changes with javascript

Resources

Stars

1.7k stars

Watchers

59 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - nytimes/ice: track changes with javascript · GitHub
Skip to content

Repository files navigation

ice.js

Ice is a track changes implementation, built in javascript, for anything that is contenteditable on the web. Conceived by the CMS Group at The New York Times, ice is powering the editor used for writing articles in the newsroom.

Demo

Try it

Download

v0.5.0

Features

  • Track multi-user inserts and deletes with the option to turn on and off tracking or highlighting.
  • A robust API to accept and reject changes, get clean content, and add a lot of configuration.
  • Plugins for tinymce and wordpress.
  • Optional plugins to track copy-cut-pasting, convert smart quotes, and create em-dashes.

Get Started


Contenteditable initialization - If you are comfortable with maintaining your own text editing utilities, then you can initialize ice on any block element:

vartracker=newice.InlineChangeEditor({// element to track - ice will make it contenteditableelement: document.getElementById('mytextelement'),// tell ice to setup/handle events on the `element`handleEvents: true,// set a user object to associate with each changecurrentUser: {id: 1,name: 'Miss T'}});// setup and start event handling for track changestracker.startTracking();

Additional options:

vartracker=newice.InlineChangeEditor({element: document.getElementById('mytextelement'),handleEvents: true,currentUser: {id: 1,name: 'Miss T'},// optional pluginsplugins: [// Add title attributes to changes for hover info'IceAddTitlePlugin',// Two successively typed dashes get converted into an em-dash'IceEmdashPlugin',// Track content that is cut and pasted{name: 'IceCopyPastePlugin',settings: {// List of tags and attributes to preserve when cleaning a pastepreserve: 'p,a[href],span[id,class]em,strong'}}]}).startTracking();

Useful utilities in the API:

acceptChange, rejectChange

// Accept/Reject the change at the current range/cursor position or at the given `optionalNode`tracker.acceptChange(optionalNode);tracker.rejectChange(optionalNode);

acceptAll, rejectAll

// Accept/Reject all of the changes in the editable region.tracker.acceptAll();tracker.rejectAll();

getCleanContent

// Returns a clean version, without tracking tags, of the content in the editable element or// out of the optional `body` param. After cleaning, the `optionalCallback` param is called// which should further modify and return the body.tracker.getCleanContent(optionalBody,optionalCallback);

setCurrentUser

// Set the desired user to track. A user object has the following properties: { `id`, `name` }.tracker.setCurrentUser({id: 2,name: 'Miss T'});

getChanges

// Get the internal list of change objects which are modeled from all of the change tracking// nodes in the DOM. This might be useful to add a more sophisticated change tracking UI/UX.// The list is key'ed with the unique change ids (`cid attribute`) and points to an object// with metadata for a change: [changeid] => {`type`, `time`, `userid`, `username`}varchanges=tracker.getChanges();

Tinymce initialization - Add the ice plugin to your tinymce plugins directory and include the following in your tinymce init:

tinymce.init({plugins: 'ice',theme_advanced_buttons1: 'ice_togglechanges,ice_toggleshowchanges,iceacceptall,icerejectall,iceaccept,icereject',ice: {user: {name: 'Miss T',id: 1},preserveOnPaste: 'p,a[href],i,em,strong',// Optional param - defaults to the css found in the plugin directorycss: 'http://example.com/custom.css'},
...
});

Limitations/Dependencies

  • ice needs to be initialized after the DOM ready event fires.
  • Wordpress support is limited. We need contribution from any willing WordPress developers.
  • Browser support is limited to Firefox (5+) and Webkit browsers, and minimal support for IE8+.

Changelog

Master

  • Fixes bug where Webkit browsers were throwing errors when the letter "v" was pressed.

0.5.0

  • Fixes cut, copy, paste for Firefox and Webkit browsers.
  • Fixes delete tracking in webkit browsers.

License

GPL 2.0

About

track changes with javascript

Resources

Stars

1.7k stars

Watchers

59 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - nytimes/ice: track changes with javascript · GitHub
Skip to content

Repository files navigation

ice.js

Ice is a track changes implementation, built in javascript, for anything that is contenteditable on the web. Conceived by the CMS Group at The New York Times, ice is powering the editor used for writing articles in the newsroom.

Demo

Try it

Download

v0.5.0

Features

  • Track multi-user inserts and deletes with the option to turn on and off tracking or highlighting.
  • A robust API to accept and reject changes, get clean content, and add a lot of configuration.
  • Plugins for tinymce and wordpress.
  • Optional plugins to track copy-cut-pasting, convert smart quotes, and create em-dashes.

Get Started


Contenteditable initialization - If you are comfortable with maintaining your own text editing utilities, then you can initialize ice on any block element:

vartracker=newice.InlineChangeEditor({// element to track - ice will make it contenteditableelement: document.getElementById('mytextelement'),// tell ice to setup/handle events on the `element`handleEvents: true,// set a user object to associate with each changecurrentUser: {id: 1,name: 'Miss T'}});// setup and start event handling for track changestracker.startTracking();

Additional options:

vartracker=newice.InlineChangeEditor({element: document.getElementById('mytextelement'),handleEvents: true,currentUser: {id: 1,name: 'Miss T'},// optional pluginsplugins: [// Add title attributes to changes for hover info'IceAddTitlePlugin',// Two successively typed dashes get converted into an em-dash'IceEmdashPlugin',// Track content that is cut and pasted{name: 'IceCopyPastePlugin',settings: {// List of tags and attributes to preserve when cleaning a pastepreserve: 'p,a[href],span[id,class]em,strong'}}]}).startTracking();

Useful utilities in the API:

acceptChange, rejectChange

// Accept/Reject the change at the current range/cursor position or at the given `optionalNode`tracker.acceptChange(optionalNode);tracker.rejectChange(optionalNode);

acceptAll, rejectAll

// Accept/Reject all of the changes in the editable region.tracker.acceptAll();tracker.rejectAll();

getCleanContent

// Returns a clean version, without tracking tags, of the content in the editable element or// out of the optional `body` param. After cleaning, the `optionalCallback` param is called// which should further modify and return the body.tracker.getCleanContent(optionalBody,optionalCallback);

setCurrentUser

// Set the desired user to track. A user object has the following properties: { `id`, `name` }.tracker.setCurrentUser({id: 2,name: 'Miss T'});

getChanges

// Get the internal list of change objects which are modeled from all of the change tracking// nodes in the DOM. This might be useful to add a more sophisticated change tracking UI/UX.// The list is key'ed with the unique change ids (`cid attribute`) and points to an object// with metadata for a change: [changeid] => {`type`, `time`, `userid`, `username`}varchanges=tracker.getChanges();

Tinymce initialization - Add the ice plugin to your tinymce plugins directory and include the following in your tinymce init:

tinymce.init({plugins: 'ice',theme_advanced_buttons1: 'ice_togglechanges,ice_toggleshowchanges,iceacceptall,icerejectall,iceaccept,icereject',ice: {user: {name: 'Miss T',id: 1},preserveOnPaste: 'p,a[href],i,em,strong',// Optional param - defaults to the css found in the plugin directorycss: 'http://example.com/custom.css'},
...
});

Limitations/Dependencies

  • ice needs to be initialized after the DOM ready event fires.
  • Wordpress support is limited. We need contribution from any willing WordPress developers.
  • Browser support is limited to Firefox (5+) and Webkit browsers, and minimal support for IE8+.

Changelog

Master

  • Fixes bug where Webkit browsers were throwing errors when the letter "v" was pressed.

0.5.0

  • Fixes cut, copy, paste for Firefox and Webkit browsers.
  • Fixes delete tracking in webkit browsers.

License

GPL 2.0

About

track changes with javascript

Resources

Stars

1.7k stars

Watchers

59 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - nytimes/ice: track changes with javascript · GitHub
Skip to content

Repository files navigation

ice.js

Ice is a track changes implementation, built in javascript, for anything that is contenteditable on the web. Conceived by the CMS Group at The New York Times, ice is powering the editor used for writing articles in the newsroom.

Demo

Try it

Download

v0.5.0

Features

  • Track multi-user inserts and deletes with the option to turn on and off tracking or highlighting.
  • A robust API to accept and reject changes, get clean content, and add a lot of configuration.
  • Plugins for tinymce and wordpress.
  • Optional plugins to track copy-cut-pasting, convert smart quotes, and create em-dashes.

Get Started


Contenteditable initialization - If you are comfortable with maintaining your own text editing utilities, then you can initialize ice on any block element:

vartracker=newice.InlineChangeEditor({// element to track - ice will make it contenteditableelement: document.getElementById('mytextelement'),// tell ice to setup/handle events on the `element`handleEvents: true,// set a user object to associate with each changecurrentUser: {id: 1,name: 'Miss T'}});// setup and start event handling for track changestracker.startTracking();

Additional options:

vartracker=newice.InlineChangeEditor({element: document.getElementById('mytextelement'),handleEvents: true,currentUser: {id: 1,name: 'Miss T'},// optional pluginsplugins: [// Add title attributes to changes for hover info'IceAddTitlePlugin',// Two successively typed dashes get converted into an em-dash'IceEmdashPlugin',// Track content that is cut and pasted{name: 'IceCopyPastePlugin',settings: {// List of tags and attributes to preserve when cleaning a pastepreserve: 'p,a[href],span[id,class]em,strong'}}]}).startTracking();

Useful utilities in the API:

acceptChange, rejectChange

// Accept/Reject the change at the current range/cursor position or at the given `optionalNode`tracker.acceptChange(optionalNode);tracker.rejectChange(optionalNode);

acceptAll, rejectAll

// Accept/Reject all of the changes in the editable region.tracker.acceptAll();tracker.rejectAll();

getCleanContent

// Returns a clean version, without tracking tags, of the content in the editable element or// out of the optional `body` param. After cleaning, the `optionalCallback` param is called// which should further modify and return the body.tracker.getCleanContent(optionalBody,optionalCallback);

setCurrentUser

// Set the desired user to track. A user object has the following properties: { `id`, `name` }.tracker.setCurrentUser({id: 2,name: 'Miss T'});

getChanges

// Get the internal list of change objects which are modeled from all of the change tracking// nodes in the DOM. This might be useful to add a more sophisticated change tracking UI/UX.// The list is key'ed with the unique change ids (`cid attribute`) and points to an object// with metadata for a change: [changeid] => {`type`, `time`, `userid`, `username`}varchanges=tracker.getChanges();

Tinymce initialization - Add the ice plugin to your tinymce plugins directory and include the following in your tinymce init:

tinymce.init({plugins: 'ice',theme_advanced_buttons1: 'ice_togglechanges,ice_toggleshowchanges,iceacceptall,icerejectall,iceaccept,icereject',ice: {user: {name: 'Miss T',id: 1},preserveOnPaste: 'p,a[href],i,em,strong',// Optional param - defaults to the css found in the plugin directorycss: 'http://example.com/custom.css'},
...
});

Limitations/Dependencies

  • ice needs to be initialized after the DOM ready event fires.
  • Wordpress support is limited. We need contribution from any willing WordPress developers.
  • Browser support is limited to Firefox (5+) and Webkit browsers, and minimal support for IE8+.

Changelog

Master

  • Fixes bug where Webkit browsers were throwing errors when the letter "v" was pressed.

0.5.0

  • Fixes cut, copy, paste for Firefox and Webkit browsers.
  • Fixes delete tracking in webkit browsers.

License

GPL 2.0

About

track changes with javascript

Resources

Stars

1.7k stars

Watchers

59 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - nytimes/ice: track changes with javascript · GitHub
Skip to content

Repository files navigation

ice.js

Ice is a track changes implementation, built in javascript, for anything that is contenteditable on the web. Conceived by the CMS Group at The New York Times, ice is powering the editor used for writing articles in the newsroom.

Demo

Try it

Download

v0.5.0

Features

  • Track multi-user inserts and deletes with the option to turn on and off tracking or highlighting.
  • A robust API to accept and reject changes, get clean content, and add a lot of configuration.
  • Plugins for tinymce and wordpress.
  • Optional plugins to track copy-cut-pasting, convert smart quotes, and create em-dashes.

Get Started


Contenteditable initialization - If you are comfortable with maintaining your own text editing utilities, then you can initialize ice on any block element:

vartracker=newice.InlineChangeEditor({// element to track - ice will make it contenteditableelement: document.getElementById('mytextelement'),// tell ice to setup/handle events on the `element`handleEvents: true,// set a user object to associate with each changecurrentUser: {id: 1,name: 'Miss T'}});// setup and start event handling for track changestracker.startTracking();

Additional options:

vartracker=newice.InlineChangeEditor({element: document.getElementById('mytextelement'),handleEvents: true,currentUser: {id: 1,name: 'Miss T'},// optional pluginsplugins: [// Add title attributes to changes for hover info'IceAddTitlePlugin',// Two successively typed dashes get converted into an em-dash'IceEmdashPlugin',// Track content that is cut and pasted{name: 'IceCopyPastePlugin',settings: {// List of tags and attributes to preserve when cleaning a pastepreserve: 'p,a[href],span[id,class]em,strong'}}]}).startTracking();

Useful utilities in the API:

acceptChange, rejectChange

// Accept/Reject the change at the current range/cursor position or at the given `optionalNode`tracker.acceptChange(optionalNode);tracker.rejectChange(optionalNode);

acceptAll, rejectAll

// Accept/Reject all of the changes in the editable region.tracker.acceptAll();tracker.rejectAll();

getCleanContent

// Returns a clean version, without tracking tags, of the content in the editable element or// out of the optional `body` param. After cleaning, the `optionalCallback` param is called// which should further modify and return the body.tracker.getCleanContent(optionalBody,optionalCallback);

setCurrentUser

// Set the desired user to track. A user object has the following properties: { `id`, `name` }.tracker.setCurrentUser({id: 2,name: 'Miss T'});

getChanges

// Get the internal list of change objects which are modeled from all of the change tracking// nodes in the DOM. This might be useful to add a more sophisticated change tracking UI/UX.// The list is key'ed with the unique change ids (`cid attribute`) and points to an object// with metadata for a change: [changeid] => {`type`, `time`, `userid`, `username`}varchanges=tracker.getChanges();

Tinymce initialization - Add the ice plugin to your tinymce plugins directory and include the following in your tinymce init:

tinymce.init({plugins: 'ice',theme_advanced_buttons1: 'ice_togglechanges,ice_toggleshowchanges,iceacceptall,icerejectall,iceaccept,icereject',ice: {user: {name: 'Miss T',id: 1},preserveOnPaste: 'p,a[href],i,em,strong',// Optional param - defaults to the css found in the plugin directorycss: 'http://example.com/custom.css'},
...
});

Limitations/Dependencies

  • ice needs to be initialized after the DOM ready event fires.
  • Wordpress support is limited. We need contribution from any willing WordPress developers.
  • Browser support is limited to Firefox (5+) and Webkit browsers, and minimal support for IE8+.

Changelog

Master

  • Fixes bug where Webkit browsers were throwing errors when the letter "v" was pressed.

0.5.0

  • Fixes cut, copy, paste for Firefox and Webkit browsers.
  • Fixes delete tracking in webkit browsers.

License

GPL 2.0

About

track changes with javascript

Resources

Stars

1.7k stars

Watchers

59 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - nytimes/ice: track changes with javascript · GitHub
Skip to content

Repository files navigation

ice.js

Ice is a track changes implementation, built in javascript, for anything that is contenteditable on the web. Conceived by the CMS Group at The New York Times, ice is powering the editor used for writing articles in the newsroom.

Demo

Try it

Download

v0.5.0

Features

  • Track multi-user inserts and deletes with the option to turn on and off tracking or highlighting.
  • A robust API to accept and reject changes, get clean content, and add a lot of configuration.
  • Plugins for tinymce and wordpress.
  • Optional plugins to track copy-cut-pasting, convert smart quotes, and create em-dashes.

Get Started


Contenteditable initialization - If you are comfortable with maintaining your own text editing utilities, then you can initialize ice on any block element:

vartracker=newice.InlineChangeEditor({// element to track - ice will make it contenteditableelement: document.getElementById('mytextelement'),// tell ice to setup/handle events on the `element`handleEvents: true,// set a user object to associate with each changecurrentUser: {id: 1,name: 'Miss T'}});// setup and start event handling for track changestracker.startTracking();

Additional options:

vartracker=newice.InlineChangeEditor({element: document.getElementById('mytextelement'),handleEvents: true,currentUser: {id: 1,name: 'Miss T'},// optional pluginsplugins: [// Add title attributes to changes for hover info'IceAddTitlePlugin',// Two successively typed dashes get converted into an em-dash'IceEmdashPlugin',// Track content that is cut and pasted{name: 'IceCopyPastePlugin',settings: {// List of tags and attributes to preserve when cleaning a pastepreserve: 'p,a[href],span[id,class]em,strong'}}]}).startTracking();

Useful utilities in the API:

acceptChange, rejectChange

// Accept/Reject the change at the current range/cursor position or at the given `optionalNode`tracker.acceptChange(optionalNode);tracker.rejectChange(optionalNode);

acceptAll, rejectAll

// Accept/Reject all of the changes in the editable region.tracker.acceptAll();tracker.rejectAll();

getCleanContent

// Returns a clean version, without tracking tags, of the content in the editable element or// out of the optional `body` param. After cleaning, the `optionalCallback` param is called// which should further modify and return the body.tracker.getCleanContent(optionalBody,optionalCallback);

setCurrentUser

// Set the desired user to track. A user object has the following properties: { `id`, `name` }.tracker.setCurrentUser({id: 2,name: 'Miss T'});

getChanges

// Get the internal list of change objects which are modeled from all of the change tracking// nodes in the DOM. This might be useful to add a more sophisticated change tracking UI/UX.// The list is key'ed with the unique change ids (`cid attribute`) and points to an object// with metadata for a change: [changeid] => {`type`, `time`, `userid`, `username`}varchanges=tracker.getChanges();

Tinymce initialization - Add the ice plugin to your tinymce plugins directory and include the following in your tinymce init:

tinymce.init({plugins: 'ice',theme_advanced_buttons1: 'ice_togglechanges,ice_toggleshowchanges,iceacceptall,icerejectall,iceaccept,icereject',ice: {user: {name: 'Miss T',id: 1},preserveOnPaste: 'p,a[href],i,em,strong',// Optional param - defaults to the css found in the plugin directorycss: 'http://example.com/custom.css'},
...
});

Limitations/Dependencies

  • ice needs to be initialized after the DOM ready event fires.
  • Wordpress support is limited. We need contribution from any willing WordPress developers.
  • Browser support is limited to Firefox (5+) and Webkit browsers, and minimal support for IE8+.

Changelog

Master

  • Fixes bug where Webkit browsers were throwing errors when the letter "v" was pressed.

0.5.0

  • Fixes cut, copy, paste for Firefox and Webkit browsers.
  • Fixes delete tracking in webkit browsers.

License

GPL 2.0

About

track changes with javascript

Resources

Stars

1.7k stars

Watchers

59 watching

Forks

Releases

Packages

Used by

Contributors

Languages