diff --git a/administrator/components/com_content/tmpl/article/showdiff.php b/administrator/components/com_content/tmpl/article/showdiff.php
new file mode 100644
index 0000000000000..f9e51c1be4698
--- /dev/null
+++ b/administrator/components/com_content/tmpl/article/showdiff.php
@@ -0,0 +1,82 @@
+ 'auto', 'relative' => true));
+JHtml::_('script', 'vendor/diff/diff.js', array('version' => 'auto', 'relative' => true));
+JHtml::_('stylesheet', 'com_contenthistory/jquery.pretty-text-diff.css', array('version' => 'auto', 'relative' => true));
+JHtml::_('script', 'com_content/admin-article-showdiff.js', array('version' => 'auto', 'relative' => true));
+
+$document = JFactory::getDocument();
+$this->eName = JFactory::getApplication()->input->getCmd('e_name', '');
+$this->eName = preg_replace('#[^A-Z0-9\-\_\[\]]#i', '', $this->eName);
+
+$document->setTitle(JText::_('COM_CONTENT_SHOWDIFF_DOC_TITLE'));
+
+$input = JFactory::getApplication()->input;
+
+/** @var Joomla\Component\Contenthistory\Administrator\Model\History $contentHistory */
+$contentHistory = new HistoryModel;
+
+$itemId = $contentHistory->getState('item_id', $input->get('id'));
+$typeId = $contentHistory->getState('type_id', 5);
+$previousVersion = 1;
+
+if ($itemId === 0)
+{
+ $itemId = $input->get('id');
+}
+
+if ($typeId === 0)
+{
+ $typeId = 1;
+}
+
+$contentHistory->setState('item_id', $itemId);
+$contentHistory->setState('type_id', $typeId);
+$dbObject = $contentHistory->getItems();
+
+?>
+
+
+
+
+
+
+';
+
+if (count($dbObject) > 1)
+{
+ $object = ContenthistoryHelper::decodeFields($dbObject[ $previousVersion ]->version_data);
+
+ if ($object->fulltext != null)
+ {
+ echo $object->introtext . '
' . $object->fulltext;
+ }
+ else
+ {
+ echo $object->introtext;
+ }
+}
+
+echo '';
diff --git a/administrator/language/en-GB/en-GB.com_content.ini b/administrator/language/en-GB/en-GB.com_content.ini
index 3d1d876c06fc6..57cdbdce07848 100644
--- a/administrator/language/en-GB/en-GB.com_content.ini
+++ b/administrator/language/en-GB/en-GB.com_content.ini
@@ -154,6 +154,11 @@ COM_CONTENT_URL_FIELD_B_BROWSERNAV_LABEL="URL B Target Window"
COM_CONTENT_URL_FIELD_C_BROWSERNAV_LABEL="URL C Target Window"
COM_CONTENT_WARNING_PROVIDE_VALID_NAME="Please provide a valid, non-blank title."
COM_CONTENT_XML_DESCRIPTION="Article management component."
+COM_CONTENT_SHOWDIFF_DOC_TITLE="Compare"
+COM_CONTENT_SHOWDIFF_BUTTON_COMPARE_HTML_DESC="Displays the changes as HTML-Code"
+COM_CONTENT_SHOWDIFF_BUTTON_COMPARE_HTML="Display HTML-Code"
+COM_CONTENT_SHOWDIFF_BUTTON_COMPARE_TEXT_DESC="Displays the changes as HTML-Code"
+COM_CONTENT_SHOWDIFF_BUTTON_COMPARE_TEXT="Display text"
JGLOBAL_NO_ITEM_SELECTED="No articles selected"
JLIB_APPLICATION_ERROR_BATCH_CANNOT_CREATE="You are not allowed to create new articles in this category."
diff --git a/administrator/language/en-GB/en-GB.plg_editors-xtd_showdiff.ini b/administrator/language/en-GB/en-GB.plg_editors-xtd_showdiff.ini
new file mode 100644
index 0000000000000..84d79323ed95b
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_editors-xtd_showdiff.ini
@@ -0,0 +1,8 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2017 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_EDITORS-XTD_SHOWDIFF="Button - Compare"
+PLG_EDITORSXTD_SHOWDIFF_BUTTON_SHOWDIFF="Compare"
+PLG_EDITORSXTD_SHOWDIFF_XML_DESCRIPTION="Provides a button to show differences between versions within a new window"
\ No newline at end of file
diff --git a/administrator/language/en-GB/en-GB.plg_editors-xtd_showdiff.sys.ini b/administrator/language/en-GB/en-GB.plg_editors-xtd_showdiff.sys.ini
new file mode 100644
index 0000000000000..9e3b0016f86a8
--- /dev/null
+++ b/administrator/language/en-GB/en-GB.plg_editors-xtd_showdiff.sys.ini
@@ -0,0 +1,7 @@
+; Joomla! Project
+; Copyright (C) 2005 - 2017 Open Source Matters. All rights reserved.
+; License GNU General Public License version 2 or later; see LICENSE.txt, see LICENSE.php
+; Note : All ini files need to be saved as UTF-8
+
+PLG_EDITORS-XTD_SHOWDIFF="Button - Compare"
+PLG_EDITORSXTD_SHOWDIFF_XML_DESCRIPTION="Provides a button to show differences between versions within a new window"
\ No newline at end of file
diff --git a/installation/sql/mysql/joomla.sql b/installation/sql/mysql/joomla.sql
index 4051374c82c46..f8b7f02e2381f 100644
--- a/installation/sql/mysql/joomla.sql
+++ b/installation/sql/mysql/joomla.sql
@@ -641,6 +641,7 @@ INSERT INTO `#__extensions` (`extension_id`, `package_id`, `name`, `type`, `elem
(483, 0, 'plg_media-action_crop', 'plugin', 'crop', 'media-action', 0, 1, 1, 0, '', '{}', 0, '0000-00-00 00:00:00', 0, 0, ''),
(484, 0, 'plg_media-action_resize', 'plugin', 'resize', 'media-action', 0, 1, 1, 0, '', '{}', 0, '0000-00-00 00:00:00', 0, 0, ''),
(485, 0, 'plg_media-action_rotate', 'plugin', 'rotate', 'media-action', 0, 1, 1, 0, '', '{}', 0, '0000-00-00 00:00:00', 0, 0, ''),
+(486, 0, 'plg_editors-xtd_showdiff', 'plugin', 'showdiff', 'editors-xtd', 0, 1, 1, 0, '', '', 0, '0000-00-00 00:00:00', 5, 0, ''),
(509, 0, 'atum', 'template', 'atum', '', 1, 1, 1, 0, '', '', 0, '0000-00-00 00:00:00', 0, 0, ''),
(510, 0, 'cassiopeia', 'template', 'cassiopeia', '', 0, 1, 1, 0, '', '{"logoFile":"","fluidContainer":"0","sidebarLeftWidth":"3","sidebarRightWidth":"3"}', 0, '0000-00-00 00:00:00', 0, 0, ''),
(600, 802, 'English (en-GB)', 'language', 'en-GB', '', 0, 1, 1, 1, '', '', 0, '0000-00-00 00:00:00', 0, 0, ''),
diff --git a/media/com_content/js/admin-article-showdiff.js b/media/com_content/js/admin-article-showdiff.js
new file mode 100644
index 0000000000000..54085c6b04a36
--- /dev/null
+++ b/media/com_content/js/admin-article-showdiff.js
@@ -0,0 +1,158 @@
+(function() {
+ 'use strict';
+
+ document.addEventListener('DOMContentLoaded', function() {
+ var diffArea = document.getElementById('diff_area'),
+ text1 = diffArea.innerHTML,
+ text2 = parent.document.getElementById('jform_articletext_ifr').contentDocument.getElementById('tinymce').innerHTML,
+ diffText, diffHtml, span, fragment, spanParent;
+
+ parent.window.onresize = movePopup;
+ movePopup();
+
+ fragment = document.createDocumentFragment();
+
+ diffHtml = JsDiff.diffWords(cleanMCE(text1), cleanMCE(text2));
+ diffHtml.forEach(function( part ) {
+ span = createDiffSpan(part);
+ span.className = 'diff_html';
+ span.style.display = 'none';
+ fragment.appendChild(span);
+ });
+
+ diffText = JsDiff.diffWords(cleanTags(text1), cleanTags(text2));
+ diffText.forEach(function( part ) {
+ span = createDiffSpan(part);
+ span.className = 'diff_text';
+ span.style.display = 'inline-block';
+ fragment.appendChild(span);
+ });
+
+ spanParent = document.createElement('div');
+ spanParent.id = 'diff_area';
+ spanParent.appendChild(fragment);
+
+ while ( diffArea.lastChild ) {
+ diffArea.removeChild(diffArea.lastChild);
+ }
+
+ diffArea.appendChild(spanParent);
+
+ document.querySelector('.diff-header').addEventListener('click', function() {
+ var diffClasses =
+ [
+ ['show', document.querySelectorAll('.diff_html')],
+ ['show', document.querySelectorAll('.diffhtml-header')],
+ ['hide', document.querySelectorAll('.diff_text')],
+ ['hide', document.querySelectorAll('.diff-header')]
+ ];
+
+ hideOrShowNodeLists(diffClasses);
+ });
+
+ document.querySelector('.diffhtml-header').addEventListener('click', function() {
+ var diffClasses =
+ [
+ ['hide', document.querySelectorAll('.diff_html')],
+ ['hide', document.querySelectorAll('.diffhtml-header')],
+ ['show-inline', document.querySelectorAll('.diff_text')],
+ ['show', document.querySelectorAll('.diff-header')]
+ ];
+
+ hideOrShowNodeLists(diffClasses);
+ });
+
+ });
+})();
+
+/*
+** set css display value, depending if just the text or the text with html-tags would be displayed.
+** @param nodeLists
+*/
+function hideOrShowNodeLists( nodeLists ) {
+ var i, j, jLength,
+ iLength = nodeLists.length;
+
+ for ( i = 0; i < iLength; ++i ) {
+ jLength = nodeLists[i][1].length;
+
+ if ( nodeLists[i][0] === 'show' ) {
+ for ( j = 0; j < jLength; j++ ) {
+ nodeLists[i][1][j].style.display = 'block';
+ }
+ }
+ else if ( nodeLists[i][0] === 'show-inline' ) {
+ for ( j = 0; j < jLength; j++ ) {
+ nodeLists[i][1][j].style.display = 'inline-block';
+ }
+ }
+ else if ( nodeLists[i][0] === 'hide' ) {
+ for ( j = 0; j < jLength; j++ ) {
+ nodeLists[i][1][j].style.display = 'none';
+ }
+ }
+ }
+}
+
+
+// creating a span for diff_html and diff_text
+function createDiffSpan( part ) {
+ var color, span;
+
+ color = part.added ? '#a6f3a6' : part.removed ? '#f8cbcb' : '';
+ span = document.createElement('span');
+ span.style.backgroundColor = color;
+ span.style.borderRadius = '.2rem';
+ span.appendChild(document.createTextNode(part.value));
+
+ return span;
+}
+
+// Deletes all HTML-Text it finds in the given text
+function cleanTags( text ) {
+ var textClean = String(text),
+ regexp = new RegExp('<.*?>');
+
+ while ( regexp.test(textClean) ) {
+ textClean = textClean.replace(regexp.exec(textClean).toString(), '');
+ }
+
+ return textClean;
+}
+
+// Deletes all HTML-Text it finds in the given text
+function cleanMCE( text ) {
+ var textClean = String(text),
+ regexp1 = new RegExp('data-mce-href=".*?/"'),
+ regexp2 = new RegExp('> <');
+
+ while ( regexp1.test(textClean) ) {
+ textClean = textClean.replace(regexp1.exec(textClean).toString(), '');
+ }
+ while ( regexp2.test(textClean) ) {
+ textClean = textClean.replace(regexp2.exec(textClean).toString(), '');
+ }
+
+ return textClean;
+}
+
+// positioning of the showdiff-popup.
+function movePopup() {
+ var editor = parent.document.getElementById('jform_articletext_ifr').parentNode,
+ editTop = editor.getBoundingClientRect().top + 5,
+ editWidth = (editor.offsetWidth) - 10,
+ popupBody = window.frameElement.parentNode,
+ popupContainer = popupBody.parentNode.parentNode,
+ popupFoot = popupContainer.getElementsByClassName('mce-foot')[0],
+ popupFootChild = popupFoot.firstChild,
+ popupFootChildBtn = popupFootChild.getElementsByClassName('mce-btn')[0];
+
+ popupContainer.style.top = editTop + 'px';
+ popupContainer.style.left = '36px';
+ popupContainer.style.width = editWidth + 'px';
+ popupBody.style.width = editWidth + 'px';
+ popupFoot.style.width = editWidth + 'px';
+ popupFootChild.style.width = editWidth + 'px';
+ popupFootChildBtn.style.left = 'unset';
+ popupFootChildBtn.style.right = '15px';
+}
diff --git a/plugins/editors-xtd/showdiff/showdiff.php b/plugins/editors-xtd/showdiff/showdiff.php
new file mode 100644
index 0000000000000..84579b48447ec
--- /dev/null
+++ b/plugins/editors-xtd/showdiff/showdiff.php
@@ -0,0 +1,75 @@
+input;
+ $itemId = $input->get('id');
+ $user = JFactory::getUser();
+
+ if ($user->authorise('core.create', 'com_content')
+ || $user->authorise('core.edit', 'com_content')
+ || $user->authorise('core.edit.own', 'com_content'))
+ {
+ if (JUri::getInstance($_SERVER['HTTP_REFERER'])->getVar('option') === 'com_associations')
+ {
+ JFactory::getDocument()->addScriptOptions('xtd-showdiff', array('editor' => $name));
+
+ $link = 'index.php?option=com_content&view=article&layout=showdiff&tmpl=component&e_name='
+ . $name . '&id=' . $itemId;
+
+ $button = new JObject;
+ $button->modal = true;
+ $button->class = 'btn';
+ $button->link = $link;
+ $button->text = JText::_('PLG_EDITORSXTD_SHOWDIFF_BUTTON_SHOWDIFF');
+ $button->name = 'shuffle';
+ $button->options = array(
+ 'height' => '450px',
+ 'width' => '400px',
+ 'bodyHeight' => '70',
+ 'modalWidth' => '80',
+ );
+
+ return $button;
+ }
+ }
+
+ // TODO Missing return statement?
+ }
+}
diff --git a/plugins/editors-xtd/showdiff/showdiff.xml b/plugins/editors-xtd/showdiff/showdiff.xml
new file mode 100644
index 0000000000000..e581a03b553d3
--- /dev/null
+++ b/plugins/editors-xtd/showdiff/showdiff.xml
@@ -0,0 +1,20 @@
+
+
+ plg_editors-xtd_showdiff
+ Joomla! Project
+ August 2017
+ Copyright (C) 2017 Open Source Matters. All rights reserved.
+ GNU General Public License version 2 or later; see LICENSE.txt
+ admin@joomla.org
+ www.joomla.org
+ 1.0.0
+ PLG_EDITORSXTD_SHOWDIFF_XML_DESCRIPTION
+
+ showdiff.php
+
+
+ en-GB.plg_editors-xtd_showdiff.ini
+ en-GB.plg_editors-xtd_showdiff.sys.ini
+
+
+