const Haste = function() { this.appName = "unknownBIN"; this.$textarea = $('textarea'); this.$box = $('#code'); this.$code = $('#code code'); this.configureShortcuts(); this.configureButtons(); }; // set title (browser window) Haste.prototype.setTitle = function(ext) { const title = ext ? `${this.appName} - ${ext}` : this.appName; document.title = title; }; // show the light key Haste.prototype.lightKey = function() { this.configureKey(['new', 'save']); }; // show the full key Haste.prototype.fullKey = function() { this.configureKey(['new', 'duplicate', 'raw']); }; // enable certain keys Haste.prototype.configureKey = function(enable) { $('#tools .function').each(function() { const $this = $(this); for (let i = 0; i < enable.length; i++) { if ($this.hasClass(enable[i])) { $this.addClass('enabled'); return true; } } $this.removeClass('enabled'); }); }; // setup a new, blank document Haste.prototype.newDocument = function(hideHistory) { this.$box.hide(); this.doc = new HasteDocument(); if (!hideHistory) { window.history.pushState(null, this.appName, '/'); } this.setTitle(); this.lightKey(); this.$textarea.val('').show('fast', function() { this.focus(); }); }; // load an existing document Haste.prototype.loadDocument = function(key) { const _this = this; _this.doc = new HasteDocument(); _this.doc.load(key, function(ret) { if (ret) { _this.$code.html(ret.value); _this.setTitle(ret.key); window.history.pushState(null, `${_this.appName}-${ret.key}`, `/${ret.key}`); _this.fullKey(); _this.$textarea.val('').hide(); _this.$box.show(); } else { _this.newDocument(); } }); }; // duplicate the current document Haste.prototype.duplicateDocument = function() { if (this.doc.locked) { const currentData = this.doc.data; this.newDocument(); this.$textarea.val(currentData); } }; // lock the current document Haste.prototype.lockDocument = function() { const _this = this; this.doc.save(this.$textarea.val(), function(err, ret) { if (!err && ret) { _this.$code.html(ret.value.trim().replace(/.+/g, "$&").replace(/^\s*[\r\n]/gm, "\n")); _this.setTitle(ret.key); window.history.pushState(null, `${_this.appName}-${ret.key}`, `/${ret.key}`); _this.fullKey(); _this.$textarea.val('').hide(); _this.$box.show(); } }); }; // configure buttons and their shortcuts Haste.prototype.configureButtons = function() { const _this = this; this.buttons = [ { $where: $('#tools .save'), shortcut: function(evt) { return evt.ctrlKey && evt.keyCode === 83; }, action: function() { if (_this.$textarea.val().replace(/^\s+|\s+$/g, '') !== '') { _this.lockDocument(); } } }, { $where: $('#tools .new'), shortcut: function(evt) { return evt.ctrlKey && evt.keyCode === 32; }, action: function() { _this.newDocument(!_this.doc.key); } }, { $where: $('#tools .duplicate'), shortcut: function(evt) { return _this.doc.locked && evt.ctrlKey && evt.keyCode === 68; }, action: function() { _this.duplicateDocument(); } }, { $where: $('#tools .raw'), shortcut: function(evt) { return evt.ctrlKey && evt.shiftKey && evt.keyCode === 82; }, action: function() { window.location.href = `/raw/${_this.doc.key}`; } } ]; for (let i = 0; i < this.buttons.length; i++) { this.configureButton(this.buttons[i]); } }; // handles the button-click Haste.prototype.configureButton = function(options) { options.$where.click(function(evt) { evt.preventDefault(); if (!options.clickDisabled && $(this).hasClass('enabled')) { options.action(); } }); }; // enables the configured shortcuts Haste.prototype.configureShortcuts = function() { const _this = this; $(document.body).keydown(function(evt) { let button; for (let i = 0; i < _this.buttons.length; i++) { button = _this.buttons[i]; if (button.shortcut && button.shortcut(evt)) { evt.preventDefault(); button.action(); return; } } }); }; // represents a single document const HasteDocument = function() { this.locked = false; }; // escape HTML-characters HasteDocument.prototype.htmlEscape = function(s) { return s .replace(/&/g, '&') .replace(/>/g, '>') .replace(/$&").replace(/^\s*[\r\n]/gm, "\n"), key: key, }); }, error: function() { callback(false); } }); }; // sends the document to the server HasteDocument.prototype.save = function(data, callback) { if (this.locked) return false; this.data = data; $.ajax('/documents', { type: 'post', data: data, dataType: 'json', contentType: 'text/plain; charset=utf-8', success: function(res) { new Haste().loadDocument(res.key); }, error: function(res) { try { callback($.parseJSON(res.responseText)); } catch (e) { callback({message: 'Something went wrong!'}); } } }); }; // after page is loaded $(function() { $('textarea').keydown(function(evt) { // allow usage of tabs if (evt.keyCode === 9) { evt.preventDefault(); const myValue = ' '; if (document.selection) { this.focus(); let sel = document.selection.createRange(); sel.text = myValue; this.focus(); } else if (this.selectionStart || this.selectionStart == '0') { const startPos = this.selectionStart; const endPos = this.selectionEnd; const scrollTop = this.scrollTop; this.value = this.value.substring(0, startPos) + myValue + this.value.substring(endPos, this.value.length); this.focus(); this.selectionStart = startPos + myValue.length; this.selectionEnd = startPos + myValue.length; this.scrollTop = scrollTop; } else { this.value += myValue; this.focus(); } } }); const app = new Haste(); const path = window.location.pathname; if (path === '/') { app.newDocument(true); } else { app.loadDocument(path.substring(1, path.length)); } }); hljs.initHighlightingOnLoad();