IP.Board Post Auto-Saving + Management

Save and manage post drafts for IP.Board forums.

  1. // ==UserScript==
  2. // @name IP.Board Post Auto-Saving + Management
  3. // @namespace Makaze
  4. // @include *
  5. // @grant none
  6. // @version 4.0.0
  7. // @description Save and manage post drafts for IP.Board forums.
  8. // ==/UserScript==
  9.  
  10. var GREEN_OPEN = 'http://i.minus.com/i3FmZuRl9edMv.png',
  11. GREEN_CLOSED = 'http://i.minus.com/irSU8O8Tdghd9.png',
  12. BLUE_OPEN = 'http://i.minus.com/iyk5uCne4V6fF.png',
  13. BLUE_CLOSED = 'http://i.minus.com/i5qOrdsGxNJD.png',
  14. CAPACITY = 5242880,
  15. MakazeScriptStyles,
  16. styleElem;
  17.  
  18. function dateAndTime() {
  19. var currentdate = new Date();
  20. var output = (((currentdate.getMonth() + 1) < 10) ? '0' + (currentdate.getMonth() + 1) : (currentdate.getMonth() + 1)) + "/"
  21. + ((currentdate.getDate() < 10) ? '0' + currentdate.getDate() : currentdate.getDate()) + "/"
  22. + currentdate.getFullYear() + " @ "
  23. + ((currentdate.getHours() < 10) ? '0' + currentdate.getHours() : currentdate.getHours()) + ":"
  24. + ((currentdate.getMinutes() < 10) ? '0' + currentdate.getMinutes() : currentdate.getMinutes()) + ":"
  25. + ((currentdate.getSeconds() < 10) ? '0' + currentdate.getSeconds() : currentdate.getSeconds());
  26. return output;
  27. }
  28.  
  29. function roundToNthDecimal(d, n) {
  30. return Math.round(d * Math.pow(10, n)) / Math.pow(10, n);
  31. }
  32.  
  33. function empty(elem) {
  34. while (elem.hasChildNodes()) {
  35. elem.removeChild(elem.lastChild);
  36. }
  37. }
  38.  
  39. function createElement(type, callback) {
  40. var element = document.createElement(type);
  41.  
  42. callback(element);
  43.  
  44. return element;
  45. }
  46.  
  47. function moveCaret(win, charCount) {
  48. var sel, range;
  49. if (win.getSelection) {
  50. sel = win.getSelection();
  51. if (sel.rangeCount > 0) {
  52. var textNode = sel.focusNode;
  53. var newOffset = sel.focusOffset + charCount;
  54. sel.collapse(textNode, Math.min(textNode.length, newOffset));
  55. }
  56. } else if ( (sel = win.document.selection) ) {
  57. if (sel.type != "Control") {
  58. range = sel.createRange();
  59. range.move("character", charCount);
  60. range.select();
  61. }
  62. }
  63. }
  64.  
  65. function fade(elem, type, speed) {
  66. function defaultStyle(tag) {
  67. var defaultStyles = {},
  68. testElem = document.createElement(tag),
  69. getStyle = 'getComputedStyle' in window,
  70. styles;
  71.  
  72. document.body.appendChild(testElem);
  73.  
  74. styles = (getStyle) ? window.getComputedStyle(testElem) : testElem.currentStyle;
  75.  
  76. for (var prop in styles) {
  77. defaultStyles[prop] = styles[prop];
  78. }
  79.  
  80. document.body.removeChild(testElem);
  81.  
  82. return defaultStyles;
  83. }
  84.  
  85. var defaults = defaultStyle(elem.tagName),
  86. defaultOpacity,
  87. defaultDisplay,
  88. currentDisplay = (elem.style.display.length) ? elem.style.display : window.getComputedStyle(elem).display;
  89.  
  90. if (elem.style.display.length) {
  91. elem.style.display = '';
  92. }
  93.  
  94. defaultDisplay = (window.getComputedStyle(elem).display === 'none') ? defaults.display : window.getComputedStyle(elem).display;
  95.  
  96. elem.style.display = currentDisplay;
  97.  
  98. if (elem.style.display.length) {
  99. elem.style.opacity = '';
  100. }
  101.  
  102. defaultOpacity = (window.getComputedStyle(elem).opacity === '0') ? defaults.opacity : window.getComputedStyle(elem).opacity;
  103.  
  104. elem.style.opacity = 0;
  105.  
  106. // Default values:
  107.  
  108. switch (arguments.length) {
  109. case 1:
  110. type = 'toggle';
  111. case 2:
  112. speed = 300;
  113. break;
  114. }
  115.  
  116. switch (type) {
  117. case 'in':
  118. elem.style.display = defaultDisplay;
  119. setTimeout(function() {
  120. elem.style.transition = 'all ' + speed + 'ms ease-in-out';
  121. elem.style.opacity = defaultOpacity;
  122. setTimeout(function() {
  123. elem.style.transition = '';
  124. }, speed + 10);
  125. }, 0);
  126. break;
  127. case 'out':
  128. elem.style.transition = 'none';
  129. elem.style.opacity = defaultOpacity;
  130. elem.style.transition = 'all ' + speed + 'ms ease-in-out';
  131. elem.style.opacity = 0;
  132. setTimeout(function() {
  133. elem.style.display = 'none';
  134. elem.style.transition = '';
  135. elem.style.opacity = '';
  136. }, speed + 10);
  137. break;
  138. case 'toggle':
  139. default:
  140. if (currentDisplay === 'none') {
  141. elem.style.display = defaultDisplay;
  142. setTimeout(function() {
  143. elem.style.transition = 'all ' + speed + 'ms ease-in-out';
  144. elem.style.opacity = defaultOpacity;
  145. setTimeout(function() {
  146. elem.style.transition = '';
  147. }, speed + 10);
  148. }, 0);
  149. } else {
  150. elem.style.transition = 'none';
  151. elem.style.opacity = defaultOpacity;
  152. elem.style.transition = 'all ' + speed + 'ms ease-in-out';
  153. elem.style.opacity = 0;
  154. setTimeout(function() {
  155. elem.style.display = 'none';
  156. elem.style.transition = '';
  157. elem.style.opacity = '';
  158. }, speed + 10);
  159. }
  160. }
  161. }
  162.  
  163. // Classes constructor
  164.  
  165. function ClassHandler() {
  166. var self = this;
  167.  
  168. this.classList = function(elem) {
  169. return elem.className.trim().split(/[\b\s]/);
  170. };
  171.  
  172. this.hasClass = function(elem, className) {
  173. var classes = self.classList(elem),
  174. has = false,
  175. i = 0;
  176.  
  177. for (i = 0; i < classes.length; i++) {
  178. if (classes[i] === className) {
  179. has = true;
  180. break;
  181. }
  182. }
  183.  
  184. return (has);
  185. };
  186.  
  187. this.addClass = function(elem, className) {
  188. var classes;
  189.  
  190. if (!self.hasClass(elem, className)) {
  191. classes = self.classList(elem);
  192. classes.push(className);
  193. elem.className = classes.join(' ').trim();
  194. }
  195.  
  196. return self;
  197. };
  198.  
  199. this.removeClass = function(elem, className) {
  200. var classes = self.classList(elem),
  201. i = 0;
  202.  
  203. for (i = 0; i < classes.length; i++) {
  204. if (classes[i] === className) {
  205. classes.splice(i, 1);
  206. }
  207. }
  208.  
  209. elem.className = classes.join(' ').trim();
  210.  
  211. return self;
  212. };
  213.  
  214. this.toggleClass = function(elem, className) {
  215. var classes;
  216.  
  217. if (self.hasClass(elem, className)) {
  218. self.removeClass(elem, className);
  219. } else {
  220. classes = self.classList(elem);
  221. classes.push(className);
  222. elem.className = classes.join(' ').trim();
  223. }
  224.  
  225. return self;
  226. };
  227. }
  228.  
  229. // Initilize
  230.  
  231. var Classes = new ClassHandler();
  232.  
  233. // End Classes constructor
  234.  
  235. // Event constructor
  236.  
  237. function EventHandler() {
  238. var events = [],
  239. matchedEvents = [],
  240. selector = document,
  241. self = this;
  242.  
  243. this.selector = function(toSelect) {
  244. selector = toSelect;
  245. return self;
  246. };
  247.  
  248. this.add = function(types, namespace, listener, useCapture) {
  249. var type,
  250. event,
  251. i = 0;
  252.  
  253. types = types.split(/[\b\s]/);
  254.  
  255. events.push({'selector': selector, 'namespace': namespace, 'types': types, 'listener': listener, 'useCapture': useCapture});
  256. event = events[events.length - 1];
  257.  
  258. for (i = 0; i < event.types.length; i++) {
  259. type = event.types[i];
  260. selector.addEventListener(type, listener, useCapture);
  261. }
  262.  
  263. return self;
  264. };
  265.  
  266. this.remove = function(types, namespace, listener, useCapture) {
  267. var event,
  268. eventType,
  269. eventTypes,
  270. type,
  271. i = 0,
  272. j = 0,
  273. k = 0;
  274.  
  275. if (!arguments.length) {
  276. if (matchedEvents.length) {
  277. for (i = 0; i < matchedEvents.length; i++) {
  278. event = matchedEvents[i];
  279. for (j = 0; j < event.types.length; j++) {
  280. type = event.types[j];
  281. event.selector.removeEventListener(type, event.listener, event.useCapture);
  282. }
  283. }
  284. } else {
  285. self.getEventsBySelector(selector).remove();
  286. }
  287. } else {
  288. types = types.split(/[\b\s]/);
  289.  
  290. for (i = 0; i < events.length; i++) {
  291. event = events[i];
  292. if (event.selector == selector && event.namespace === namespace && event.useCapture === useCapture && event.listener === listener) {
  293. eventTypes = event.types;
  294. for (j = 0; j < eventTypes.length; j++) {
  295. eventType = eventTypes[j];
  296. for (k = 0; k < event.types.length; k++) {
  297. type = types[k];
  298. if (type === eventType) {
  299. selector.removeEventListener(type, event.listener, event.useCapture);
  300. }
  301. }
  302. }
  303. break;
  304. }
  305. }
  306. }
  307.  
  308. matchedEvents = [];
  309.  
  310. return self;
  311. };
  312.  
  313. this.output = function() {
  314. if (!matchedEvents.length) {
  315. self.getAllEvents().output();
  316. } else {
  317. var output = matchedEvents;
  318. matchedEvents = [];
  319. return output;
  320. }
  321. };
  322.  
  323. this.getAllEvents = function() {
  324. matchedEvents = events;
  325. return self;
  326. };
  327.  
  328. this.getEventsBySelector = function(getSelector) {
  329. var event,
  330. i = 0;
  331.  
  332. if (matchedEvents.length) {
  333. for (i = 0; i < matchedEvents.length; i++) {
  334. event = matchedEvents[i];
  335. if (event.selector != getSelector) {
  336. matchedEvents.splice(i, 1);
  337. }
  338. }
  339. } else {
  340. for (i = 0; i < events.length; i++) {
  341. event = events[i];
  342. if (event.selector == getSelector) {
  343. matchedEvents.push(event);
  344. }
  345. }
  346. }
  347.  
  348. return self;
  349. };
  350.  
  351. this.getEventsByType = function(types) {
  352. var eventTypes,
  353. eventType,
  354. event,
  355. type,
  356. hasType = false,
  357. i = 0,
  358. j = 0,
  359. k = 0;
  360.  
  361. types = types.split(/[\b\s]/);
  362.  
  363. if (matchedEvents.length) {
  364. for (i = 0; i < matchedEvents.length; i++) {
  365. event = matchedEvents[i];
  366. for (j = 0; j < eventTypes.length; j++) {
  367. eventType = eventTypes[j];
  368. for (k = 0; k < event.types.length; k++) {
  369. type = types[k];
  370. if (type === eventType) {
  371. hasType = true;
  372. break;
  373. }
  374. }
  375. if (hasType) {
  376. break;
  377. }
  378. }
  379. if (hasType) {
  380. matchedEvents.splice(i, 1);
  381. }
  382. }
  383. } else {
  384. for (i = 0; i < events.length; i++) {
  385. event = events[i];
  386. for (j = 0; j < eventTypes.length; j++) {
  387. eventType = eventTypes[j];
  388. for (k = 0; k < event.types.length; k++) {
  389. type = types[k];
  390. if (type === eventType) {
  391. hasType = true;
  392. break;
  393. }
  394. }
  395. if (hasType) {
  396. break;
  397. }
  398. }
  399. if (hasType) {
  400. matchedEvents.push(event);
  401. }
  402. }
  403. }
  404. return self;
  405. };
  406.  
  407. this.getEventsByName = function(namespace) {
  408. var event,
  409. i = 0;
  410.  
  411. if (matchedEvents.length) {
  412. for (i = 0; i < matchedEvents.length; i++) {
  413. event = matchedEvents[i];
  414. if (event.namespace !== namespace) {
  415. matchedEvents.splice(i, 1);
  416. }
  417. }
  418. } else {
  419. for (i = 0; i < events.length; i++) {
  420. event = events[i];
  421. if (event.namespace === namespace) {
  422. matchedEvents.push(event);
  423. }
  424. }
  425. }
  426.  
  427. return self;
  428. };
  429.  
  430. this.getEventsByListener = function(listener) {
  431. var event,
  432. i = 0;
  433.  
  434. if (matchedEvents.length) {
  435. for (i = 0; i < matchedEvents.length; i++) {
  436. event = matchedEvents[i];
  437. if (event.listener !== listener) {
  438. matchedEvents.splice(i, 1);
  439. }
  440. }
  441. } else {
  442. for (i = 0; i < events.length; i++) {
  443. event = events[i];
  444. if (event.listener === listener) {
  445. matchedEvents.push(event);
  446. }
  447. }
  448. }
  449.  
  450. return self;
  451. };
  452. }
  453.  
  454. // Initialize
  455.  
  456. var Events = new EventHandler();
  457.  
  458. // End Event constructor
  459.  
  460. function refresh() {
  461. function createLogItem(source, i) {
  462. return createElement('div', function(log) {
  463. log.id = source[i].id;
  464. log.className = 'log-item';
  465. log.name = i;
  466.  
  467. log.appendChild(createElement('div', function(header) {
  468. header.className = 'log-item-header';
  469. header.appendChild(createElement('a', function(link) {
  470. link.className = 'header-link';
  471. link.appendChild(createElement('img', function(icon) {
  472. icon.src = selectedIcon;
  473. icon.className = 'folderIcon';
  474. }));
  475.  
  476. if (source[i].hasOwnProperty('name')) {
  477. link.appendChild(createElement('span', function(name) {
  478. name.className = 'name';
  479. name.appendChild(document.createTextNode(source[i].name));
  480. }));
  481. link.appendChild(document.createTextNode(' | '));
  482. }
  483.  
  484. link.appendChild(document.createTextNode(source[i].date));
  485. }));
  486.  
  487. header.appendChild(createElement('del', function(del) {
  488. del.className = 'delete';
  489. del.appendChild(document.createTextNode('Delete'));
  490. }));
  491.  
  492. if (selected === 'defaultFolder') {
  493. header.appendChild(createElement('del', function(save) {
  494. save.className = 'save';
  495. save.appendChild(document.createTextNode('Move to Saved '));
  496. save.appendChild(createElement('img', function(icon) {
  497. icon.src = BLUE_OPEN;
  498. icon.className = 'folderIcon';
  499. }));
  500. }));
  501. } else {
  502. header.appendChild(createElement('del', function(rename) {
  503. rename.className = 'rename';
  504. rename.appendChild(document.createTextNode('Rename'));
  505. }));
  506. }
  507.  
  508. header.appendChild(createElement('del', function(load) {
  509. load.className = 'load';
  510. load.appendChild(document.createTextNode('Load'));
  511. }));
  512. }));
  513.  
  514. log.appendChild(createElement('div', function(msg) {
  515. msg.className = 'msg-content';
  516. msg.innerHTML = source[i].msg.replace(/\n/g, '<br />');
  517. }));
  518. });
  519. }
  520.  
  521. var selected = document.getElementsByClassName('folderSelected')[0].title.toLowerCase() + 'Folder',
  522. source = (localStorage.getItem(selected)) ? JSON.parse(localStorage.getItem(selected)) : [],
  523. selectedIcon = (selected === 'defaultFolder') ? GREEN_CLOSED : BLUE_CLOSED,
  524. currentLength = 0,
  525. occupied,
  526. defaultFull,
  527. savedFull,
  528. queue = document.getElementById('SavedPostsMenu-queue'),
  529. capacity = document.getElementById('capacity'),
  530. capacityText = document.getElementById('capacity-text'),
  531. i = 0;
  532.  
  533. document.getElementById('trash').getElementsByTagName('span')[0].childNodes[0].nodeValue = 0;
  534.  
  535. empty(queue);
  536.  
  537. if (source.length) {
  538. source.sort(function(a, b) {
  539. var dateA = new Date(a.date.replace(/@/g, '')),
  540. dateB = new Date(b.date.replace(/@/g, ''));
  541. return dateB - dateA;
  542. });
  543.  
  544. for (i = 0; i < source.length; i++) {
  545. queue.appendChild(createLogItem(source, i));
  546. }
  547. } else {
  548. queue.appendChild(createElement('div', function(cont) {
  549. cont.appendChild(createElement('div', function(error) {
  550. error.className = 'error_notice';
  551. error.style.padding = '5px 0';
  552. error.appendChild(document.createTextNode('No messages to display.'));
  553. }));
  554. }));
  555. }
  556.  
  557. if (!localStorage.length) {
  558. capacity.getElementsByTagName('div')[0].style.width = 0 + '%';
  559. capacityText.childNodes[0].nodeValue = 0 + '% full';
  560. } else {
  561. for (i = 0; i < localStorage.length; i++) {
  562. currentLength += localStorage.getItem(localStorage.key(i)).length;
  563. }
  564. occupied = (currentLength / CAPACITY) * 100;
  565. defaultFull = (localStorage.getItem('defaultFolder')) ? (localStorage.getItem('defaultFolder').length / CAPACITY) : 0;
  566. savedFull = (localStorage.getItem('savedFolder')) ? (localStorage.getItem('savedFolder').length / CAPACITY) + defaultFull : 0;
  567. document.getElementById('defaultFolder').style.width = defaultFull + '%';
  568. document.getElementById('savedFolder').style.width = savedFull + '%';
  569. occupied = roundToNthDecimal(occupied, 1);
  570. capacityText.childNodes[0].nodeValue = occupied + '% full';
  571. if (occupied >= 95 && !Classes.hasClass(capacity, 'full')) {
  572. Classes.addClass(capacity, 'full');
  573. Classes.addClass(capacityText, 'full');
  574. } else if (Classes.hasClass(capacity, 'full')) {
  575. Classes.removeClass(capacity, 'full');
  576. Classes.removeClass(capacityText, 'full');
  577. }
  578. }
  579. }
  580.  
  581. function manageSavedPosts() {
  582. var alreadyExists = false,
  583. SavedPostsMenu,
  584. menu;
  585.  
  586. // The menu
  587.  
  588. if (document.getElementById('SavedPostsMenu') == null) {
  589. SavedPostsMenu = createElement('div', function(menu) {
  590. menu.id = 'SavedPostsMenu';
  591. menu.appendChild(createElement('div', function(padded) {
  592. padded.className = 'padded';
  593. padded.appendChild(createElement('div', function(close) {
  594. close.id = 'close-SavedPostsMenu';
  595. close.appendChild(createElement('span', function(span) {
  596. span.appendChild(document.createTextNode('x'));
  597. }));
  598. }));
  599.  
  600. padded.appendChild(createElement('div', function(trash) {
  601. trash.id = 'trash';
  602. trash.appendChild(document.createTextNode('Empty Trash ('));
  603. trash.appendChild(createElement('span', function(span) {
  604. span.appendChild(document.createTextNode('0'));
  605. }));
  606. trash.appendChild(document.createTextNode(' Items)'));
  607. }));
  608.  
  609. padded.appendChild(createElement('div', function(cap) {
  610. cap.id = 'capacity';
  611. cap.appendChild(createElement('div', function(folderCap) {
  612. folderCap.id = 'defaultFolder';
  613. }));
  614.  
  615. cap.appendChild(createElement('div', function(folderCap) {
  616. folderCap.id = 'savedFolder';
  617. }));
  618. }));
  619.  
  620. padded.appendChild(createElement('div', function(mass) {
  621. mass.id = 'mass-functions';
  622. mass.appendChild(createElement('span', function(cap_text) {
  623. cap_text.id = 'capacity-text';
  624. cap_text.appendChild(document.createTextNode('0% full'));
  625. }));
  626.  
  627. mass.appendChild(createElement('a', function(refresh) {
  628. refresh.name = 'refresh';
  629. refresh.appendChild(document.createTextNode('Refresh'));
  630. }));
  631. mass.appendChild(document.createTextNode(' | '));
  632. mass.appendChild(createElement('a', function(toggle) {
  633. toggle.name = 'toggle-all';
  634. toggle.appendChild(document.createTextNode('Toggle All'));
  635. }));
  636. mass.appendChild(document.createTextNode(' | '));
  637. mass.appendChild(createElement('a', function(restore) {
  638. restore.name = 'restore-all';
  639. restore.appendChild(document.createTextNode('Restore All'));
  640. }));
  641. mass.appendChild(document.createTextNode(' | '));
  642. mass.appendChild(createElement('a', function(del) {
  643. del.name = 'delete-all';
  644. del.appendChild(document.createTextNode('Delete All'));
  645. }));
  646. }));
  647.  
  648. padded.appendChild(createElement('div', function(select) {
  649. select.id = 'folderSelect';
  650. select.appendChild(createElement('img', function(icon) {
  651. icon.title = 'Default';
  652. icon.src = GREEN_OPEN;
  653. icon.className = 'folderSelected';
  654. }));
  655.  
  656. select.appendChild(createElement('img', function(icon) {
  657. icon.title = 'Saved';
  658. icon.src = BLUE_CLOSED;
  659. }));
  660. }));
  661.  
  662. padded.appendChild(createElement('div', function(folder) {
  663. folder.id = 'folderName';
  664. folder.appendChild(document.createTextNode('Default'));
  665. }));
  666.  
  667. padded.appendChild(createElement('div', function(queue) {
  668. queue.id = 'SavedPostsMenu-queue';
  669. }));
  670. }));
  671. });
  672.  
  673. document.body.appendChild(SavedPostsMenu);
  674. } else {
  675. alreadyExists = true;
  676. }
  677.  
  678. menu = document.getElementById('SavedPostsMenu');
  679.  
  680. refresh();
  681.  
  682. // Kill the process if the menu already exists
  683.  
  684. if (alreadyExists) {
  685. fade(menu, 'in');
  686. return false;
  687. }
  688.  
  689. // Events
  690.  
  691. // Handlers
  692.  
  693. var closeHandler = function() {
  694. fade(menu, 'out');
  695. };
  696.  
  697. var selectFolderHandler = function(event) {
  698. if (event.target.tagName !== 'IMG') {
  699. return false;
  700. }
  701.  
  702. var folder = event.target.title,
  703. selected,
  704. folderName;
  705.  
  706. if (Classes.hasClass(event.target, 'folderSelected')) {
  707. refresh();
  708. return false;
  709. }
  710.  
  711. selected = document.getElementsByClassName('folderSelected')[0];
  712. folderName = document.getElementById('folderName');
  713.  
  714. if (folder === 'Default') {
  715. event.target.src = GREEN_OPEN;
  716. selected.src = BLUE_CLOSED;
  717. } else {
  718. event.target.src = BLUE_OPEN;
  719. selected.src = GREEN_CLOSED;
  720. }
  721.  
  722. Classes.removeClass(selected, 'folderSelected');
  723. Classes.addClass(event.target, 'folderSelected');
  724. Classes.toggleClass(folderName, 'savedFolderText');
  725. folderName.childNodes[0].nodeValue = folder;
  726. refresh();
  727. };
  728.  
  729. var trashHandler = function() {
  730. var trash = document.getElementById('trash'),
  731. selected = document.getElementsByClassName('folderSelected')[0].title.toLowerCase() + 'Folder',
  732. selectedLog = JSON.parse(localStorage.getItem(selected)),
  733. logItems = document.getElementsByClassName('log-item'),
  734. thisLog,
  735. idToDelete,
  736. idToCompare,
  737. start,
  738. i = 0,
  739. messageNum;
  740.  
  741. for (i = 0; i < logItems.length; i++) {
  742. thisLog = logItems[i];
  743.  
  744. if (thisLog.hasAttribute('delete')) {
  745. idToDelete = thisLog.id;
  746.  
  747. for (messageNum = 0; messageNum < selectedLog.length; messageNum++) {
  748. idToCompare = selectedLog[messageNum].id;
  749. if (idToCompare === idToDelete) {
  750. start = messageNum;
  751. break;
  752. }
  753. }
  754.  
  755. selectedLog.splice(start, 1);
  756. }
  757. }
  758.  
  759. trash.getElementsByTagName('span')[0].childNodes[0].nodeValue = 0;
  760. localStorage.setItem(selected, JSON.stringify(selectedLog));
  761. };
  762.  
  763. var massHandler = function(event) {
  764. if (event.target.tagName !== 'A') {
  765. return false;
  766. }
  767.  
  768. var logItems = document.getElementsByClassName('log-item'),
  769. trash = document.getElementById('trash'),
  770. thisLog,
  771. headers,
  772. i = 0;
  773.  
  774. switch (event.target.name) {
  775. case 'refresh':
  776. refresh();
  777. break;
  778. case 'toggle-all':
  779. headers = document.getElementsByClassName('header-link');
  780. for (i = 0; i < headers.length; i++) {
  781. headers[i].click();
  782. }
  783. break;
  784. case 'restore-all':
  785. for (i = 0; i < logItems.length; i++) {
  786. thisLog = logItems[i];
  787.  
  788. if (thisLog.hasAttribute('delete')) {
  789. thisLog.removeAttribute('delete');
  790. fade(thisLog, 'in', 100);
  791. trash.getElementsByTagName('span')[0].childNodes[0].nodeValue = parseInt(trash.getElementsByTagName('span')[0].childNodes[0].nodeValue) - 1;
  792. }
  793. }
  794. break;
  795. case 'delete-all':
  796. for (i = 0; i < logItems.length; i++) {
  797. thisLog = logItems[i];
  798.  
  799. if (!thisLog.hasAttribute('delete')) {
  800. thisLog.getElementsByClassName('delete')[0].click();
  801. }
  802. }
  803. break;
  804. }
  805. };
  806.  
  807. var selectMessageHandler = function(event) {
  808. if (!event.target.className || !Classes.hasClass(event.target, 'load')) {
  809. return false;
  810. }
  811.  
  812. var toSelect = event.target.parentNode.nextSibling,
  813. idToLoad = toSelect.parentNode.id,
  814. msgToLoad,
  815. selected = document.getElementsByClassName('folderSelected')[0].title.toLowerCase() + 'Folder',
  816. selectedLog,
  817. idToCompare,
  818. iteration,
  819. range;
  820.  
  821. if (document.selection) {
  822. range = document.body.createTextRange();
  823. range.moveToElementText(toSelect);
  824. range.select();
  825. } else if (window.getSelection()) {
  826. range = document.createRange();
  827. range.selectNode(toSelect);
  828. window.getSelection().removeAllRanges();
  829. window.getSelection().addRange(range);
  830. }
  831.  
  832. // Nested click handler
  833.  
  834. var loadMessageRichClickHandler = function(event) {
  835. var cursored = window.parent.document.getElementsByClassName('selectableForLoad'),
  836. thisCursored,
  837. i = 0,
  838. messageNum = 0;
  839.  
  840. selectedLog = JSON.parse(localStorage.getItem(selected));
  841.  
  842. for (messageNum = 0; messageNum < selectedLog.length; messageNum++) {
  843. idToCompare = selectedLog[messageNum].id;
  844. if (idToCompare === idToLoad) {
  845. iteration = messageNum;
  846. break;
  847. }
  848. }
  849.  
  850. msgToLoad = selectedLog[iteration].msg;
  851.  
  852. if (event.target.getElementsByTagName('body')[0].textContent.length) {
  853. event.target.getElementsByTagName('body')[0].innerHTML += msgToLoad;
  854. } else {
  855. event.target.getElementsByTagName('body')[0].innerHTML = msgToLoad;
  856. }
  857.  
  858. for (i = 0; i < cursored.length; i++) {
  859. thisCursored = cursored[i];
  860.  
  861. if (thisCursored.tagName === 'TEXTAREA') {
  862. thisCursored.style.cursor = '';
  863. } else {
  864. thisCursored.contentWindow.document.documentElement.style.cursor = '';
  865. }
  866.  
  867. Classes.removeClass(thisCursored, 'selectableForLoad');
  868. }
  869.  
  870. Events.getEventsByName('loadMessage').remove();
  871.  
  872. fade(window.parent.document.getElementById('noticeBar'), 'out');
  873. };
  874.  
  875. var loadMessageRichMouseoverHandler = function(event) {
  876. if (event.target.tagName !== 'IFRAME' || !event.target.title || !event.target.title.match('Rich text editor')) {
  877. return false;
  878. }
  879.  
  880. event.target.contentWindow.document.documentElement.style.cursor = 'crosshair';
  881.  
  882. Classes.addClass(event.target, 'selectableForLoad');
  883. Events.selector(event.target.contentWindow.document.documentElement).add('click', 'loadMessage', loadMessageRichClickHandler, false);
  884.  
  885. Events.getEventsByName('loadMessageRich').remove();
  886. };
  887.  
  888. var loadMessageClickHandler = function(event) {
  889. if (!event.target.className || !Classes.hasClass(event.target, 'cke_source')) {
  890. return false;
  891. }
  892.  
  893. selectedLog = JSON.parse(localStorage.getItem(selected));
  894.  
  895. var cursored = document.getElementsByClassName('selectableForLoad'),
  896. thisCursored,
  897. messageNum = 0,
  898. i = 0;
  899.  
  900. for (messageNum = 0; messageNum < selectedLog.length; messageNum++) {
  901. idToCompare = selectedLog[messageNum].id;
  902. if (idToCompare === idToLoad) {
  903. iteration = messageNum;
  904. break;
  905. }
  906. }
  907.  
  908. msgToLoad = selectedLog[iteration].msg;
  909. event.target.value += msgToLoad;
  910.  
  911. for (i = 0; i < cursored.length; i++) {
  912. thisCursored = cursored[i];
  913.  
  914. if (thisCursored.tagName === 'TEXTAREA') {
  915. thisCursored.style.cursor = '';
  916. } else {
  917. thisCursored.contentWindow.document.documentElement.style.cursor = '';
  918. }
  919.  
  920. Classes.removeClass(thisCursored, 'selectableForLoad');
  921. }
  922.  
  923. Events.getEventsByName('loadMessage').remove();
  924.  
  925. fade(document.getElementById('noticeBar'), 'out');
  926. };
  927.  
  928. var loadMessageMouseoverHandler = function(event) {
  929. if (!event.target.className || !Classes.hasClass(event.target, 'cke_source')) {
  930. return false;
  931. }
  932.  
  933. event.target.style.cursor = 'crosshair';
  934. Classes.addClass(event.target, 'selectableForLoad');
  935. };
  936.  
  937. Events.selector(document).add('mouseover', 'loadMessage', loadMessageMouseoverHandler, false);
  938.  
  939. Events.selector(document).add('click', 'loadMessage', loadMessageClickHandler, false);
  940.  
  941. Events.selector(document).add('mouseover', 'loadMessageRich', loadMessageRichMouseoverHandler, false);
  942.  
  943. if (document.getElementById('noticeBar') == null) {
  944. document.body.appendChild(createElement('div', function(bar) {
  945. bar.id = 'noticeBar';
  946. bar.appendChild(document.createTextNode(''));
  947. }));
  948. }
  949.  
  950. document.getElementById('noticeBar').childNodes[0].nodeValue = 'Click a post field to load this post.';
  951.  
  952. fade(document.getElementById('noticeBar'), 'in');
  953. };
  954.  
  955. var moveToSavedHandler = function(event) {
  956. if (!event.target.className || !Classes.hasClass(event.target, 'save')) {
  957. return false;
  958. }
  959.  
  960. var defaultLog = JSON.parse(localStorage.getItem('defaultFolder')),
  961. savedLog = (localStorage.getItem('savedFolder')) ? JSON.parse(localStorage.getItem('savedFolder')) : [],
  962. msgToMove = event.target.parentNode.parentNode.id,
  963. msgToCompare,
  964. iteration,
  965. savedName,
  966. toHide = event.target.parentNode.parentNode;
  967.  
  968. var moveAndRenameKeydownHandler = function(event) {
  969. var messageNum = 0;
  970.  
  971. if (event.target.tagName === 'INPUT') {
  972. if (event.keyCode === 13) {
  973. savedName = event.target.value;
  974. for (messageNum = 0; messageNum < defaultLog.length; messageNum++) {
  975. msgToCompare = defaultLog[messageNum].id;
  976. if (msgToCompare === msgToMove) {
  977. iteration = messageNum;
  978. break;
  979. }
  980. }
  981. defaultLog[iteration].name = savedName;
  982. savedLog.push(defaultLog[iteration]);
  983. defaultLog.splice(iteration, 1);
  984. localStorage.setItem('defaultFolder', JSON.stringify(defaultLog));
  985. localStorage.setItem('savedFolder', JSON.stringify(savedLog));
  986. fade(toHide, 'out');
  987. fade(event.target.parentNode, 'out');
  988. Events.selector(document.getElementById('renameDialog')).remove('keydown', 'moveAndRenameKeydown', moveAndRenameKeydownHandler, false);
  989. }
  990. }
  991. };
  992.  
  993. if (document.getElementById('renameDialog') == null) {
  994. document.body.appendChild(createElement('div', function(rename) {
  995. rename.id = 'renameDialog';
  996. rename.appendChild(document.createTextNode('Name this Message'));
  997. rename.appendChild(document.createElement('br'));
  998. rename.appendChild(createElement('inpty', function(input) {
  999. input.type = 'text';
  1000. input.placeholder = 'Press enter to submit';
  1001. }));
  1002. }));
  1003. }
  1004.  
  1005. document.getElementById('renameDialog').getElementsByTagName('input')[0].value = '';
  1006.  
  1007. fade(document.getElementById('renameDialog'), 'in');
  1008.  
  1009. Events.selector(document.getElementById('renameDialog')).add('keydown', 'moveAndRenameKeydown', moveAndRenameKeydownHandler, false);
  1010. };
  1011.  
  1012. var renameHandler = function(event) {
  1013. if (!event.target.className || !Classes.hasClass(event.target, 'rename')) {
  1014. return false;
  1015. }
  1016.  
  1017. var renaming = event.target.parentNode.parentNode.getElementsByClassName('name')[0],
  1018. savedLog = JSON.parse(localStorage.getItem('savedFolder')),
  1019. msgToRename = event.target.parentNode.parentNode.id,
  1020. msgToCompare,
  1021. iteration,
  1022. newName;
  1023.  
  1024. if (renaming.hasAttribute('contenteditable')) {
  1025. renaming.removeAttribute('contenteditable');
  1026. renaming.removeAttribute('style');
  1027. return false;
  1028. }
  1029.  
  1030. renaming.setAttribute('contenteditable', 'true');
  1031. renaming.setAttribute('style', 'outline: none; background-color: rgba(255, 255, 255, .7); padding: 3px; cursor: text;');
  1032. renaming.focus();
  1033. moveCaret(window, renaming.textContent.length);
  1034.  
  1035. var renameKeydownHandler = function(event) {
  1036. if (event.keyCode == 13) {
  1037. event.target.removeAttribute('contenteditable');
  1038. event.target.removeAttribute('style');
  1039. newName = event.target.textContent;
  1040. for (var messageNum = 0; messageNum < savedLog.length; messageNum++) {
  1041. msgToCompare = savedLog[messageNum].id;
  1042. if (msgToCompare === msgToRename) {
  1043. iteration = messageNum;
  1044. break;
  1045. }
  1046. }
  1047. savedLog[iteration].name = newName;
  1048. localStorage.setItem('savedFolder', JSON.stringify(savedLog));
  1049. Events.selector(event.target).remove('keydown', 'renameKeydown', renameKeydownHandler, false);
  1050. }
  1051. };
  1052.  
  1053. Events.selector(renaming).add('keydown', 'renameKeydown', renameKeydownHandler, false);
  1054. };
  1055.  
  1056. var deleteHandler = function(event) {
  1057. if (!event.target.className || !Classes.hasClass(event.target, 'delete')) {
  1058. return false;
  1059. }
  1060.  
  1061. var parentLog = event.target.parentNode.parentNode;
  1062.  
  1063. fade(parentLog, 'out', 100);
  1064. parentLog.setAttribute('delete', '');
  1065. document.getElementById('trash').getElementsByTagName('span')[0].childNodes[0].nodeValue = parseInt(document.getElementById('trash').getElementsByTagName('span')[0].childNodes[0].nodeValue) + 1;
  1066. };
  1067.  
  1068. var showMsgContentHandler = function(event) {
  1069. if (!event.target.className || !(Classes.hasClass(event.target, 'header-link') || Classes.hasClass(event.target.parentNode, 'header-link'))) {
  1070. return false;
  1071. }
  1072.  
  1073. var thisTarget = (Classes.hasClass(event.target, 'header-link')) ? event.target : event.target.parentNode,
  1074. selected = document.getElementsByClassName('folderSelected')[0].title.toLowerCase() + 'Folder',
  1075. folderIcon = thisTarget.getElementsByClassName('folderIcon')[0],
  1076. parent = thisTarget.parentNode,
  1077. selectedIcon,
  1078. dels,
  1079. i = 0;
  1080.  
  1081. if (Classes.hasClass(folderIcon, 'isOpen')) {
  1082. selectedIcon = (selected === 'defaultFolder') ? GREEN_CLOSED : BLUE_CLOSED;
  1083. } else {
  1084. selectedIcon = (selected === 'defaultFolder') ? GREEN_OPEN : BLUE_OPEN;
  1085. }
  1086.  
  1087. folderIcon.src = selectedIcon;
  1088. Classes.toggleClass(folderIcon, 'isOpen');
  1089. fade(parent.nextSibling, 'toggle', 100);
  1090. for (i = 0, dels = parent.getElementsByTagName('del'); i < dels.length; i++) {
  1091. fade(dels[i], 'toggle', 100);
  1092. }
  1093. };
  1094.  
  1095. // Add events
  1096.  
  1097. Events.selector(document.getElementById('close-SavedPostsMenu').getElementsByTagName('span')[0]).add('click', 'close', closeHandler, false);
  1098.  
  1099. Events.selector(document.getElementById('folderSelect')).add('click', 'selectFolder', selectFolderHandler, false);
  1100.  
  1101. Events.selector(document.getElementById('trash')).add('click', 'empty', trashHandler, false);
  1102.  
  1103. Events.selector(document.getElementById('mass-functions')).add('click', 'mass', massHandler, false);
  1104.  
  1105. Events.selector(menu).add('click', 'select', selectMessageHandler, false);
  1106.  
  1107. Events.selector(menu).add('click', 'moveToSaved', moveToSavedHandler, false);
  1108.  
  1109. Events.selector(menu).add('click', 'rename', renameHandler, false);
  1110.  
  1111. Events.selector(menu).add('click', 'delete', deleteHandler, false);
  1112.  
  1113. Events.selector(menu).add('click', 'showMsgContent', showMsgContentHandler, false);
  1114. }
  1115.  
  1116. if (document.getElementsByTagName('body')[0].id === 'ipboard_body') {
  1117. // Styling
  1118.  
  1119. if (document.getElementById('MakazeScriptStyles') == null) {
  1120. MakazeScriptStyles = createElement('style', function(style) {
  1121. style.id = 'MakazeScriptStyles';
  1122. style.type = 'text/css';
  1123. });
  1124. document.head.appendChild(MakazeScriptStyles);
  1125. }
  1126.  
  1127. styleElem = document.getElementById('MakazeScriptStyles');
  1128.  
  1129. if (styleElem.hasChildNodes()) {
  1130. styleElem.childNodes[0].nodeValue += '\n\n';
  1131. } else {
  1132. styleElem.appendChild(document.createTextNode(''));
  1133. }
  1134.  
  1135. styleElem.childNodes[0].nodeValue += '#SavedPostsMenu { background-color: rgba(240, 240, 240, 0.8); width: 50%; height: 100%; position: fixed; z-index: 99999999; top: 0px; left: 25%; box-shadow: 0px 0px 3px #444; color: #222; overflow-y: auto; } #SavedPostsMenu .padded { padding: 25px; } #close-SavedPostsMenu { text-align: right; height: 0px; } #close-SavedPostsMenu span { background-color: #222; color: #fff; font-size: 110%; display: inline-block; width: 25px; height: 25px; text-align: center; line-height: 25px; border-radius: 25px; opacity: 0.9; cursor: pointer; } #trash { text-align: center; font-weight: bolder; background-color: rgba(250, 250, 245, 0.9); color: rgb(68, 68, 68); text-shadow: 0px 0px 2px rgb(170, 170, 170); box-shadow: 0px 0px 2px rgb(119, 119, 119); padding: 15px; margin: 0 100px; border-radius: 10px; font-size: 150%; margin-bottom: 15px; cursor: pointer; } #mass-functions { text-align: right; text-shadow: 1px 1px rgb(255, 255, 255); font-weight: bolder; padding: 10px; font-style: oblique; background-color: rgba(255, 255, 255, .9); font-size: 120%; border-radius: 3px; margin-bottom: 10px; } .log-item { margin: 5px 0; } .log-item-header { margin: 10px 0; } #SavedPostsMenu a, #SavedPostsMenu del, #SavedPostsMenu .undo, #SavedPostsMenu .error_notice { text-shadow: 1px 1px #FFF; font-weight: bolder; cursor: pointer; margin: 0 10px; } #SavedPostsMenu del { text-decoration: none; float: right; display: none; } .msg-content { background-color: rgba(255, 255, 255, .8); border-radius: 5px; box-shadow: 0px 0px 3px #777; padding: 15px; display: none; } #SavedPostsMenu ol { list-style: decimal; padding-left: 40px; } #SavedPostsMenu il { list-style: disc; padding-left: 40px; } .log-item .undo { background-color: rgba(255, 255, 255, .7); font-style: oblique; margin: 0 7px; padding: 3px; border-radius: 3px; display: none; } .log-item .error_notice { font-size: 120%; cursor: auto; } #capacity { background-color: rgba(255, 255, 255, .7); border-radius: 3px; margin-bottom: 10px; overflow: hidden; } #capacity > div { height: 10px; border-radius: 3px; -webkit-transition: all .2s ease-in-out; -moz-transition: all .2s ease-in-out; -o-transition: all .2s ease-in-out; transition: all .2s ease-in-out; } #capacity > div#defaultFolder { background-color: #7f3; border-bottom: 1px solid #7C3; border-right: 1px solid #7C3; position: absolute; } #capacity.full > div#savedFolder { background-color: #3cf; border-bottom: 1px solid #39C; border-right: 1px solid #39C; } #capacity.full > div { background-color: #F11; border-bottom: 1px solid #C11; border-right: 1px solid #C11; } #capacity-text { float: left; -webkit-transition: all .2s ease-in-out; -moz-transition: all .2s ease-in-out; -o-transition: all .2s ease-in-out; transition: all .2s ease-in-out; } #capacity-text.full { color: #F11; text-shadow: 1px 1px #C11; } .saved-notice-footer { float: left; background-color: rgba(255, 255, 255, 0.4) ! important; color: #676767 ! important; padding: 3px 5px ! important; border-radius: 5px; } .last-saved { color: inherit ! important; } .saved-warning { color: #F11 ! important; } .saved-warning > strong { font-weight: bolder ! important; } .open-SavedPostsMenu { text-decoration: underline ! important; cursor: pointer ! important; } .open-SavedPostsMenu:hover { text-decoration: none ! important; } #folderSelect { text-align: center; } #folderSelect > img { height: 25px; cursor: pointer; padding: 5px; border: 1px dashed transparent; } #folderSelect > img:not(:last-of-type) { margin-right: 5px; } #SavedPostsMenu .folderSelected { padding: 5px; border-radius: 5px; border: 1px dashed #aaa ! important; } #folderName { font-weight: bolder; padding-top: 5px; font-size: 130%; } #SavedPostsMenu .savedFolderText { color: #3cf; text-shadow: 1px 1px #39C; } #SavedPostsMenu img.folderIcon { height: 15px; } #SavedPostsMenu .header-link > img.folderIcon { margin-right: 5px; } #noticeBar { position: fixed; z-index: 9999999999; bottom: 0px; text-align: center; width: 100%; background-color: rgba(50, 50, 50, .9); color: #fff; box-shadow: 0px 0px 5px #111; font-size: 25px; font-weight: bolder; padding: 20px 0px; display: none; } #renameDialog { position: fixed; z-index: 999999999; top: 50%; left: 50%; padding: 3px; height: 40px; width: 200px; margin-top: -24px; margin-left: -79px; background-color: #f8f8f8; border: 1px solid #ccc; border-radius: 5px; text-align: center; font-weight: bolder; display: none; } #renameDialog > input { margin: 3px 0px; width: 95%; }';
  1136.  
  1137. var autoSavePostHandler = function(event) {
  1138. var editor,
  1139. editorContainer,
  1140. editorSubmitParent,
  1141. editorContents,
  1142. editorID,
  1143. editorType,
  1144. editor_bottom,
  1145. footer;
  1146.  
  1147. if (!event.target.tagName) {
  1148. return false;
  1149. }
  1150.  
  1151. switch (event.target.tagName) {
  1152. case 'TEXTAREA':
  1153. if (event.target.hasAttribute('aria-label') && event.target.getAttribute('aria-label').match('Rich text editor')) {
  1154. editor = event.target;
  1155. editorContainer = event.target.parentNode.parentNode.parentNode.parentNode;
  1156. } else {
  1157. return false;
  1158. }
  1159. break;
  1160. case 'IFRAME':
  1161. if (event.target.title && event.target.title.match('Rich text editor')) {
  1162. editor = event.target;
  1163. editorContainer = event.target.parentNode.parentNode.parentNode.parentNode;
  1164. } else {
  1165. return false;
  1166. }
  1167. break;
  1168. default:
  1169. return false;
  1170. }
  1171.  
  1172. if (editorContainer.hasAttribute('auto-saving')) {
  1173. return false;
  1174. }
  1175.  
  1176. editorContents = editorContainer.getElementsByClassName('cke_contents')[0];
  1177.  
  1178. if (editorContents.id.match('editor')) {
  1179. editorID = editorContents.id.split('editor_')[1];
  1180. editorType = 'editor_';
  1181. } else if (!editorContents.id.match('editor') && editorContents.id.match('edit')) {
  1182. editorID = editorContents.id.split('edit-')[1];
  1183. editorType = 'edit-';
  1184. }
  1185.  
  1186. editor_bottom = document.getElementById('cke_bottom_' + editorType + editorID);
  1187.  
  1188. console.log('Saving from:', editor);
  1189.  
  1190. footer = createElement('div', function(footer) {
  1191. footer.className = 'saved-notice-footer';
  1192. footer.appendChild(createElement('span', function(last_saved) {
  1193. last_saved.className = 'last-saved';
  1194. }));
  1195.  
  1196. footer.appendChild(document.createTextNode(' '));
  1197.  
  1198. footer.appendChild(createElement('a', function(open_menu) {
  1199. open_menu.className = 'open-SavedPostsMenu';
  1200. open_menu.appendChild(document.createTextNode('{Menu}'));
  1201. }));
  1202. });
  1203.  
  1204. editor_bottom.insertBefore(footer, editor_bottom.firstChild);
  1205.  
  1206. var openMenuHandler = function() {
  1207. manageSavedPosts();
  1208. };
  1209.  
  1210. Events.selector(editor_bottom.getElementsByClassName('open-SavedPostsMenu')[0]).add('click', 'open_menu', openMenuHandler, false);
  1211.  
  1212. function fireInterval(elemID, context) {
  1213. var timeStamp = dateAndTime(),
  1214. elem,
  1215. saveState,
  1216. elems,
  1217. newEntry,
  1218. i = 0;
  1219.  
  1220. if (context.getElementsByTagName('textarea')[0] != null) {
  1221. for (i = 0, elems = context.getElementsByTagName('textarea'); i < elems.length; i++) {
  1222. if (elems[i].getAttribute('aria-label').match(elemID)) {
  1223. elem = elems[i];
  1224. if (!elem.value.length) {
  1225. return false;
  1226. }
  1227.  
  1228. saveState = elem.value;
  1229. }
  1230. }
  1231. } else {
  1232. for (i = 0, elems = context.getElementsByTagName('iframe'); i < elems.length; i++) {
  1233. if (elems[i].title.match(elemID)) {
  1234. elem = elems[i];
  1235. if (!elem.contentWindow.document.body.textContent.length) {
  1236. return false;
  1237. }
  1238.  
  1239. saveState = elem.contentWindow.document.body.innerHTML;
  1240. }
  1241. }
  1242. }
  1243.  
  1244. newEntry = { 'id': elemID, 'date': timeStamp, 'msg': saveState };
  1245.  
  1246. // The meat
  1247. var defaultLog = (localStorage.getItem('defaultFolder')) ? JSON.parse(localStorage.getItem('defaultFolder')) : [],
  1248. lastSavedElem = document.getElementById('cke_bottom_' + editorType + editorID).getElementsByClassName('last-saved')[0],
  1249. newMessage = true,
  1250. messageID,
  1251. messageToEdit,
  1252. currentLength = 0,
  1253. entryLength,
  1254. occupied,
  1255. difference,
  1256. normalSave = false,
  1257. messageNum = 0,
  1258. savedWarning,
  1259. warningClass,
  1260. warningText,
  1261. kill = false;
  1262.  
  1263. if (defaultLog.length) {
  1264. for (messageNum = 0; messageNum < defaultLog.length; messageNum++) {
  1265. messageID = defaultLog[messageNum].id;
  1266. if (messageID === elemID) {
  1267. newMessage = false;
  1268. messageToEdit = messageNum;
  1269. break;
  1270. }
  1271. }
  1272. }
  1273.  
  1274. if (!newMessage && saveState === defaultLog[messageToEdit].msg) {
  1275. return false;
  1276. }
  1277.  
  1278. // Begin capacity check
  1279.  
  1280. if (localStorage.length) {
  1281. for (i = 0; i < localStorage.length; i++) {
  1282. currentLength += localStorage.getItem(localStorage.key(i)).length;
  1283. }
  1284. }
  1285.  
  1286. entryLength = JSON.stringify(newEntry).length;
  1287. occupied = roundToNthDecimal((currentLength / CAPACITY) * 100, 1);
  1288.  
  1289. if (newMessage) {
  1290. if (((currentLength + entryLength) / CAPACITY) * 100 >= 95) {
  1291. if (currentLength + entryLength > CAPACITY) {
  1292. warningClass = 'over-capacity';
  1293. warningText = ' Capacity reached. Delete old messages to continue saving.';
  1294. kill = true;
  1295. } else if (currentLength + entryLength === CAPACITY) {
  1296. warningClass = 'full';
  1297. warningText = ' Capacity reached. Delete old messages to continue saving.';
  1298. } else {
  1299. warningClass = 'full';
  1300. warningText = ' ' + roundToNthDecimal(((currentLength + entryLength) / CAPACITY) * 100, 1) + '% full.';
  1301. }
  1302. } else {
  1303. normalSave = true;
  1304. }
  1305. } else {
  1306. difference = entryLength - JSON.stringify(defaultLog[messageToEdit]).length;
  1307.  
  1308. if (((currentLength + difference) / CAPACITY) * 100 >= 95) {
  1309. if (currentLength + difference > CAPACITY) {
  1310. warningClass = 'over-capacity';
  1311. warningText = ' Capacity reached. Delete old messages to continue saving.';
  1312. kill = true;
  1313. } else if (currentLength + difference === CAPACITY) {
  1314. warningClass = 'full';
  1315. warningText = ' Capacity reached. Delete old messages to continue saving.';
  1316. } else {
  1317. warningClass = 'full';
  1318. warningText = ' ' + roundToNthDecimal(((currentLength + difference) / CAPACITY) * 100, 1) + '% full.';
  1319. }
  1320. } else {
  1321. normalSave = true;
  1322. }
  1323. }
  1324.  
  1325. // End capacity check
  1326.  
  1327. empty(lastSavedElem);
  1328.  
  1329. if (normalSave) {
  1330. lastSavedElem.appendChild(document.createTextNode('Last saved: ' + timeStamp));
  1331. } else {
  1332. savedWarning = createElement('span', function(warning) {
  1333. warning.className = 'saved-warning ' + warningClass;
  1334. warning.appendChild(createElement('strong', function(type) {
  1335. type.appendChild(document.createTextNode('Warning:'));
  1336. }));
  1337.  
  1338. warning.appendChild(document.createTextNode(warningText));
  1339. });
  1340. if (kill) {
  1341. lastSavedElem.appendChild(savedWarning);
  1342. return false;
  1343. }
  1344.  
  1345. lastSavedElem.appendChild(document.createTextNode('Last saved: ' + timeStamp + ' | '));
  1346. lastSavedElem.appendChild(savedWarning);
  1347. }
  1348.  
  1349. if (newMessage) {
  1350. defaultLog.push(newEntry);
  1351. } else {
  1352. defaultLog[messageToEdit].msg = saveState;
  1353. }
  1354.  
  1355. localStorage.setItem('defaultFolder', JSON.stringify(defaultLog));
  1356. }
  1357.  
  1358. var saveAtInterval = setInterval(function() {
  1359. if (document.getElementById('cke_bottom_' + editorType + editorID) == null) {
  1360. clearTimeout(saveAtInterval);
  1361. return false;
  1362. }
  1363. fireInterval(editorID, editorContainer);
  1364. }, 15000);
  1365.  
  1366. editorContainer.setAttribute('auto-saving', '');
  1367.  
  1368. editorSubmitParent = editor;
  1369.  
  1370. while (editorSubmitParent.getElementsByClassName('input_submit')[0] == null && editorSubmitParent.parentNode) {
  1371. editorSubmitParent = editorSubmitParent.parentNode;
  1372. }
  1373.  
  1374. var submitSavedPostHandler = function(event) {
  1375. if (!event.target.className || event.target.className !== 'input-submit') {
  1376. return false;
  1377. }
  1378.  
  1379. var defaultLog = JSON.parse(localStorage.getItem('defaultFolder')),
  1380. messageID,
  1381. messageNum = 0;
  1382.  
  1383. for (messageNum = 0; messageNum < defaultLog.length; messageNum++) {
  1384. messageID = defaultLog[messageNum].id;
  1385. if (messageID === editorID) {
  1386. defaultLog.splice(messageNum, 1);
  1387. localStorage.setItem('defaultFolder', JSON.stringify(defaultLog));
  1388. break;
  1389. }
  1390. }
  1391. };
  1392.  
  1393. Events.selector(editorSubmitParent).add('click', 'submitSavedPost', submitSavedPostHandler, false);
  1394. };
  1395.  
  1396. Events.selector(document).add('mouseover', 'saveStart', autoSavePostHandler, false);
  1397. }