Advertisement
agir

jsondiffFM

Feb 20th, 2023
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.12 KB | None | 0 0
  1. "data:text/html,
  2. <!DOCTYPE html>
  3. <html>
  4. <head>
  5. <style>
  6. body {
  7. font-family: Verdana;
  8. }
  9. h1 {
  10. clear: both;
  11. }
  12. label {
  13. display: block;
  14. }
  15. textarea {
  16. min-height: 8em;
  17. width: 100%;
  18. }
  19. .col {
  20. width: 48%;
  21. margin: 0 1% 1em 1%;
  22. float: left;
  23. }
  24. .col:after { /* clearfix */
  25. content: \"\";
  26. display: table;
  27. clear: both;
  28. }
  29. .diff {
  30. display: block;
  31. background-color: #eee;
  32. border-radius: 0.5em;
  33. padding: 1em;
  34. }
  35. .objectDiff {
  36. unicode-bidi: embed;
  37. font-family: monospace;
  38. white-space: pre;
  39. }
  40. .objectDiff .objectInner {
  41. padding-left: 2em;
  42. display: block;
  43. }
  44. .objectDiff .prop {
  45. display: block;
  46. }
  47. .objectDiff .added,
  48. .objectDiff.added {
  49. color: green;
  50. background-color: #E2F6EA;
  51. /* background-color: rgba(0,255,100,0.08); */
  52. }
  53. .objectDiff .removed,
  54. .objectDiff.removed {
  55. color: red;
  56. background-color: #F6E2E6;
  57. /* background-color: rgba(255,0,50,0.08); */
  58. }
  59. </style>
  60. </head>
  61. <script>
  62.  
  63. (function ($) {
  64. var _isJQuery = function($elt){
  65. return ($elt instanceof $)
  66. };
  67. var _objectDiff = {
  68. NODIFF: 1,
  69. DIFF: 3,
  70. VALUEDIFF: 2,
  71. oldObjectClass: 'removed',
  72. newObjectClass: 'added',
  73. noDifferenceClass: 'nodiff',
  74.  
  75. loopOverObject: function(obj, callback){
  76. var key, i = 0;
  77. for (key in obj) {
  78. callback(key, obj[key], i);
  79. i++;
  80. }
  81. },
  82.  
  83. getDiff: function(obj1, obj2){
  84. var diffObj = {};
  85. var key;
  86. // If we're not comparing objects, then just compare values...
  87. if (obj1 === null || typeof obj1 !== 'object') {
  88. // If obj2 is also a primitive (string, number, null, boolean, etc.) and matches...
  89. if (obj1 === obj2) {
  90. return this.NODIFF;
  91. } else {
  92. return this.DIFF;
  93. }
  94. }
  95.  
  96. for (key in obj1) {
  97. //console.log(key);
  98. if (obj2 === null || typeof obj2[key] === 'undefined') {
  99. diffObj[key] = this.DIFF;
  100. } else {
  101. if (typeof obj1[key] === 'object' && typeof obj2[key] === 'object'
  102. && obj1[key] !== null)
  103. {
  104. // Do some recursion
  105. diffObj[key] = this.getDiff(obj1[key], obj2[key]);
  106. } else {
  107. //console.log(typeof obj1[key], typeof obj2[key]);
  108. if (obj1[key] == obj2[key]) {
  109. diffObj[key] = this.NODIFF;
  110. } else {
  111. diffObj[key] = this.VALUEDIFF;
  112. }
  113. }
  114. }
  115. }
  116. return diffObj;
  117. },
  118.  
  119. // Do the same thing as getDiff, but chop out any properties that have NODIFF
  120. getOnlyDiff: function(obj1, obj2){
  121. var diff = this.getDiff(obj1, obj2);
  122. var key;
  123. for (key in diff) {
  124. if (diff[key] == this.NODIFF) {
  125. delete diff[key];
  126. }
  127. };
  128. return diff;
  129. },
  130.  
  131. getDiffArray: function(obj1, obj2){
  132. var diff = this.getDiff(obj1, obj2);
  133. return _getDiffArray(diff, obj1, []);
  134. },
  135. _getDiffArray: function(diff, obj, arr) {
  136. var key;
  137. for (key in diff) {
  138. if (diff[key] == this.DIFF || diff[key] == this.VALUEDIFF) {
  139. arr.push({ key: key, value: obj[key] });
  140. } else if (typeof diff[key] === 'object') {
  141. this._getDiffArray(diff[key], obj[key], arr)
  142. }
  143. }
  144. return arr;
  145. },
  146.  
  147. getDiffHTML: function(obj, diffObj, diffClass, objClass){
  148. var o = this,
  149. isInsideArray = false,
  150. html = '',
  151. numOfProperties = 0,
  152. brackets = ['{', '}'];
  153.  
  154. if (typeof objClass !== 'string') {
  155. objClass = '';
  156. }
  157.  
  158. isInsideArray = (obj instanceof Array);
  159. if (isInsideArray) {
  160. brackets = ['[', ']'];
  161. }
  162. //console.log(obj);
  163.  
  164. for (key in obj) { numOfProperties++; }
  165.  
  166. this.loopOverObject(obj, function(key, value, i){
  167. var type = typeof value;
  168. var isArray = (value instanceof Array);
  169. // Diff object
  170. var diffValue = diffObj[key]; // (diffObj === null) ? null : diffObj[key];
  171. // Classes
  172. var keyClasses = 'key';
  173. var valueClasses = 'value';
  174. var seperatorClasses = 'sep';
  175. // Strings
  176. var valueString = '';
  177. var keyString = '';
  178.  
  179. // If there's no diff value, then skip...
  180. //if (typeof diffValue === 'undefined') {
  181. // return;
  182. //}
  183.  
  184. if (isInsideArray) {
  185. keyString = '';
  186. } else {
  187. keyString = '\"' + key + '\": ';
  188. }
  189.  
  190. if (type === 'string') {
  191. valueString = '\"' + value + '\"';
  192. } else if (type === 'object' && value !== null) {
  193. if (typeof diffValue === 'object' && diffValue !== null) {
  194. valueString = o.getDiffHTML(value, diffObj[key], diffClass);
  195. } else {
  196. valueString = o.getDiffHTML(value, {}, diffClass, diffClass);
  197. }
  198. } else {
  199. valueString = '' + value;
  200. }
  201.  
  202. // Get classes
  203. if (diffValue == o.DIFF) {
  204. keyClasses += ' ' + diffClass;
  205. seperatorClasses += ' ' + diffClass;
  206. }
  207. if (diffValue == o.DIFF || diffValue == o.VALUEDIFF) {
  208. valueClasses += ' ' + diffClass;
  209. }
  210. if (diffValue == o.NODIFF) {
  211. keyClasses += ' ' + o.noDifferenceClass;
  212. valueClasses += ' ' + o.noDifferenceClass;
  213. seperatorClasses += ' ' + o.noDifferenceClass;
  214. }
  215.  
  216. // Add to the HTML
  217. html += '<span class=\"prop\">';
  218. if (keyString.length > 0) {
  219. html += '<span class=\"' + keyClasses + '\">' + keyString + '</span>';
  220. }
  221. if (valueString.length > 0) {
  222. html += '<span class=\"' + valueClasses + '\">' + valueString + '</span>';
  223. }
  224. if ((i + 1) < numOfProperties) {
  225. html += '<span class=\"' + seperatorClasses + '\">,</span>';
  226. }
  227. html += '</span>';
  228. });
  229.  
  230. // Check for primitives (nulls, numbers, strings, etc.)
  231. if (obj === null || typeof obj !== 'object') {
  232. if (obj === null) {
  233. objClass += ' null';
  234. html = 'null';
  235. } else if (typeof obj === 'string') {
  236. html = '\"' + obj + '\"';
  237. } else {
  238. html = obj;
  239. }
  240. if (diffObj === this.DIFF || diffObj === this.VALUEDIFF) {
  241. objClass += ' ' + diffClass;
  242. }
  243.  
  244. } else {
  245. html = (
  246. brackets[0]
  247. + '<span class=\"objectInner ' + objClass + '\">'
  248. + html
  249. + '</span>'
  250. + brackets[1]
  251. );
  252. }
  253. return '<span class=\"objectDiff ' + objClass + '\">' + html + '</span>';
  254. },
  255.  
  256. writeDiff: function(obj1, obj2, container, styleClass, onlyDifferences){
  257. var diff = this.getDiff(obj1, obj2); //(onlyDifferences) ? this.getOnlyDiff(obj1, obj2) : this.getDiff(obj1, obj2);
  258. var h = this.getDiffHTML(obj1, diff, styleClass);
  259. //console.log(\"writeDiff...\ndiff:\", diff, \"\nhtml:\", h, \"\ncontainer:\", container);
  260. $(container).html( h );
  261. },
  262.  
  263. writeBothDiff: function(oldObj, newObj, oldContainer, newContainer, onlyDifferences){
  264. //if (onlyDifferences) { console.log('Writing both diffs -- only the diffs, not properties that are the same.')};
  265. $(oldContainer).empty();
  266. $(newContainer).empty();
  267. this.writeDiff(oldObj, newObj, oldContainer, this.oldObjectClass, onlyDifferences);
  268. this.writeDiff(newObj, oldObj, newContainer, this.newObjectClass, onlyDifferences);
  269. if (onlyDifferences) {
  270. //console.log($(oldContainer).add($(newContainer)).find('.' + this.noDifferenceClass).length);
  271.  
  272. $(oldContainer).add($(newContainer)).find('.' + this.noDifferenceClass).hide();
  273. this.addViewButton(oldContainer);
  274. this.addViewButton(newContainer);
  275. }
  276. },
  277.  
  278. addViewButton: function(container){
  279. var o = this;
  280. var $viewNoDiffButton = $('<button type=\"button\" class=\"viewNoDiff\">View all properties</button>')
  281. .click(function(e){
  282. $(this).hide(300).parent().find('.' + o.noDifferenceClass).slideDown(400);
  283. });
  284. $(container).append($viewNoDiffButton);
  285. },
  286.  
  287. getObject: function(obj){
  288. var objString, finalObj;
  289. //console.log(\"getting Object:\", obj);
  290. if (_isJQuery(obj)) {
  291. if (typeof obj.data('objectdiff_json') === 'undefined') {
  292. objString = $.trim(obj.html());
  293. } else {
  294. objString = obj.data('objectdiff_json');
  295. }
  296. } else if (typeof obj === 'string' || typeof obj === 'number' || typeof obj === 'boolean') {
  297. objString = obj;
  298. } else {
  299. objString = JSON.stringify(obj);
  300. }
  301. //console.log(\"getting object: \", objString);
  302. try {
  303. finalObj = JSON.parse(objString);
  304. } catch (err) {
  305. if (objString == 'null') {
  306. finalObj = null;
  307. } else {
  308. finalObj = objString;
  309. }
  310. console.log(\"Could not JSON-parse: \", objString, \"\n\", err, \"\nUsing raw value instead instead.\", finalObj, \"(\" + typeof finalObj + \")\");
  311. }
  312. return finalObj;
  313. },
  314.  
  315. getJQueryContainer: function(elt){
  316. if (_isJQuery(elt)) {
  317. if (elt.length > 1) {
  318. console.warn(\"Only using first element for objectDiff.\", elt);
  319. }
  320. return elt.first();
  321. } else {
  322. return $([]);
  323. }
  324. }
  325. };
  326.  
  327.  
  328.  
  329. // Expose the functionality as jQuery plugin as objectDiff
  330. $.objectDiff = function(base, comparison, options){
  331. var baseObj, comparisonObj, baseContainer, comparisonContainer;
  332. // If there's only one argument and it's not a jquery object, then use it as the options
  333. if (arguments.length == 1 && typeof arguments[0] === 'object' && (!_isJQuery(arguments[0]))) {
  334. options = arguments[0];
  335. base = $([]);
  336. comparison = $([]);
  337. }
  338. // Some defaults for options
  339. options = $.extend({
  340. baseObject: false,
  341. comparisonObject: false,
  342. baseContainer: false,
  343. comparisonContainer: false,
  344. onlyDifferences: false
  345. }, options);
  346.  
  347. // Use the objects and containers from the options...
  348. // or, if not specified, then get the object and containers from base and comparison arguments
  349. baseObj = (options.baseObject) ? options.baseObject : _objectDiff.getObject(base);
  350. comparisonObj = (options.comparisonObject) ? options.comparisonObject : _objectDiff.getObject(comparison);
  351. if (options.baseContainer && _isJQuery(options.baseContainer)) {
  352. base = options.baseContainer;
  353. }
  354. baseContainer = _objectDiff.getJQueryContainer(base);
  355. if (options.comparisonContainer && _isJQuery(options.comparisonContainer)) {
  356. comparison = options.comparisonContainer;
  357. }
  358. comparisonContainer = _objectDiff.getJQueryContainer(comparison);
  359.  
  360. // Save the JSON object for later in case objectDiff is run again
  361. //console.log(\"Adding data\", baseObj, comparisonObj, baseContainer, comparisonContainer);
  362. baseContainer.data('objectdiff_json', JSON.stringify(baseObj));
  363. comparisonContainer.data('objectdiff_json', JSON.stringify(comparisonObj));
  364.  
  365. // Write the diff html to the containers
  366. _objectDiff.writeBothDiff(
  367. baseObj, comparisonObj,
  368. baseContainer, comparisonContainer,
  369. options.onlyDifferences
  370. );
  371. };
  372.  
  373. $.fn.objectDiff = function(comparison, options) {
  374. $.objectDiff(this, comparison, options);
  375. return this;
  376. };
  377.  
  378. })(jQuery);
  379.  
  380. //==== Example-specific code below
  381.  
  382. var $oldTextArea = $('#oldText');
  383. var $newTextArea = $('#newText');
  384. var $diffOld = $('#diffOld');
  385. var $diffNew = $('#diffNew');
  386.  
  387. $oldTextArea.add($newTextArea).on('change', function(e){
  388. $diffOld.html($oldTextArea.val()).removeData('objectdiff_json');
  389. $diffNew.html($newTextArea.val()).removeData('objectdiff_json');
  390. console.log(\"\n\");
  391. $diffOld.objectDiff($diffNew);
  392. }).trigger('change');
  393. </script>
  394. </head>
  395. <body>
  396.  
  397. <h1>Review the differences</h1>
  398. <h2>JSON Objects</h2>
  399. <div class=\"col\">
  400. <label>Old</label>
  401. <textarea id=\"oldText\">"
  402. & $$oldState
  403. &"</textarea>
  404. </div>
  405. <div class=\"col\">
  406. <label>New</label>
  407. <textarea id=\"newText\">"
  408. & $$newState
  409. & "</textarea>
  410. </div>
  411. <div class=\"col\">
  412. <h2>Old</h2>
  413. <div class=\"diff\">
  414. <div id=\"diffOld\"></div>
  415. </div>
  416. </div>
  417. <div class=\"col\">
  418. <h2>New</h2>
  419. <div class=\"diff\">
  420. <div id=\"diffNew\"></div>
  421. </div>
  422. </div>
  423. </body>
  424. </html>"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement