diff --git a/static/application.css b/static/application.css
index c2155b1..f17facb 100644
--- a/static/application.css
+++ b/static/application.css
@@ -36,14 +36,6 @@ textarea {
user-select: none;
}
-.line {
- /* display: block;*/
-}
-
-/*.line:hover {
- background-color: #cbd387;
-}*/
-
.lineHighlight {
background-color: yellow;
}
diff --git a/static/application.js b/static/application.js
index 78d5e73..1bd825d 100644
--- a/static/application.js
+++ b/static/application.js
@@ -3,428 +3,443 @@
///// represents a single document
var haste_document = function(app) {
- this.locked = false;
- this.app = app;
-};
-
-// Escapes HTML tag characters
-haste_document.prototype.htmlEscape = function(s) {
- return s
- .replace(/&/g, '&')
- .replace(/>/g, '>')
- .replace(/= selectedLines.startLine &&
- currentLine <= selectedLines.endLine
- ) {
- spanClass = "lineHighlight";
- }
- highlighted = "" + highlighted + "";
- high.value += highlighted + "\n";
- }
- //// scroll to position in document after ensuring components h"ve had time to render
- setTimeout(function() {
- // show current line and the one before it
- if (selectedLines.startLine >= 3) {
- document.body.scrollTo(0, $("#line-" + (selectedLines.startLine - 2)).offset().top)
- } else {
- // if lines 1-2, go to top of file
- document.body.scrollTo(0, 0);
- }
- }, 0);
- } catch (err) {
- // failed highlight, fall back on auto
- high = hljs.highlightAuto(res.data);
- }
- callback({
- value: high.value,
- key: key,
- language: high.language || lang,
- lineCount: res.data.split('\n').length
- });
- },
- error: function() {
- callback(false);
- }
- });
-};
-
-// Save this document to the server and lock it here
-haste_document.prototype.save = function(data, callback) {
- if (this.locked) {
- return false;
- }
- this.data = data;
- var _this = this;
- $.ajax(_this.app.baseUrl + 'documents', {
- type: 'post',
- data: data,
- dataType: 'json',
- contentType: 'text/plain; charset=utf-8',
- success: function(res) {
- _this.locked = true;
- _this.key = res.key;
- var high = hljs.highlightAuto(data);
- callback(null, {
- value: high.value,
- key: res.key,
- language: high.language,
- lineCount: data.split('\n').length
- });
- },
- error: function(res) {
- try {
- callback($.parseJSON(res.responseText));
- }
- catch (e) {
- callback({message: 'Something went wrong!'});
- }
- }
- });
-};
-
-///// represents the paste application
-
-var haste = function(appName, options) {
- this.appName = appName;
- this.$textarea = $('textarea');
- this.$box = $('#box');
- this.$code = $('#box code');
- this.$linenos = $('#linenos');
- this.options = options;
- this.configureShortcuts();
- this.configureButtons();
- // If twitter is disabled, hide the button
- if (!options.twitter) {
- $('#box2 .twitter').hide();
+ this.locked = false;
+ this.app = app;
};
- this.baseUrl = options.baseUrl || '/';
- this.selectedLines = options.selectedLines;
-};
-
-// Set the page title - include the appName
-haste.prototype.setTitle = function(ext) {
- var title = ext ? this.appName + ' - ' + ext : this.appName;
- document.title = title;
-};
-
-// Show a message box
-haste.prototype.showMessage = function(msg, cls) {
- var msgBox = $('
'+msg+'');
- $('#messages').prepend(msgBox);
- setTimeout(function() {
- msgBox.slideUp('fast', function() { $(this).remove(); });
- }, 3000);
-};
-
-// Show the light key
-haste.prototype.lightKey = function() {
- this.configureKey(['new', 'save']);
-};
-
-// Show the full key
-haste.prototype.fullKey = function() {
- this.configureKey(['new', 'duplicate', 'twitter', 'raw']);
-};
-
-// Set the key up for certain things to be enabled
-haste.prototype.configureKey = function(enable) {
- var $this, i = 0;
- $('#box2 .function').each(function() {
- $this = $(this);
- for (i = 0; i < enable.length; i++) {
- if ($this.hasClass(enable[i])) {
- $this.addClass('enabled');
- return true;
- }
- }
- $this.removeClass('enabled');
- });
-};
-
-// Remove the current document (if there is one)
-// and set up for a new one
-haste.prototype.newDocument = function(hideHistory) {
- this.$box.hide();
- this.doc = new haste_document(this);
- if (!hideHistory) {
- window.history.pushState(null, this.appName, this.baseUrl);
- }
- this.setTitle();
- this.lightKey();
- this.$textarea.val('').show('fast', function() {
- this.focus();
- });
- this.selectedLines = { startLine: null, endLine: null };
- this.removeLineNumbers();
-};
-
-// Map of common extensions
-// Note: this list does not need to include anything that IS its extension,
-// due to the behavior of lookupTypeByExtension and lookupExtensionByType
-// Note: optimized for lookupTypeByExtension
-haste.extensionMap = {
- rb: 'ruby', py: 'python', pl: 'perl', php: 'php', scala: 'scala', go: 'go',
- xml: 'xml', html: 'xml', htm: 'xml', css: 'css', js: 'javascript', vbs: 'vbscript',
- lua: 'lua', pas: 'delphi', java: 'java', cpp: 'cpp', cc: 'cpp', m: 'objectivec',
- vala: 'vala', sql: 'sql', sm: 'smalltalk', lisp: 'lisp', ini: 'ini',
- diff: 'diff', bash: 'bash', sh: 'bash', tex: 'tex', erl: 'erlang', hs: 'haskell',
- md: 'markdown', txt: '', coffee: 'coffee', swift: 'swift'
-};
-
-// Look up the extension preferred for a type
-// If not found, return the type itself - which we'll place as the extension
-haste.prototype.lookupExtensionByType = function(type) {
- for (var key in haste.extensionMap) {
- if (haste.extensionMap[key] === type) return key;
- }
- return type;
-};
-
-// Look up the type for a given extension
-// If not found, return the extension - which we'll attempt to use as the type
-haste.prototype.lookupTypeByExtension = function(ext) {
- return haste.extensionMap[ext] || ext;
-};
-
-// Add line numbers to the document
-// For the specified number of lines, each with a class and id
-haste.prototype.addLineNumbers = function(lineCount) {
- var h = '';
- for (var i = 0; i < lineCount; i++) {
- h += '' + (i + 1) + '
';
- }
- $('#linenos').html(h);
-};
-
-// Remove the line numbers
-haste.prototype.removeLineNumbers = function() {
- $('#linenos').html('>');
-};
-
-// Load a document and show it
-haste.prototype.loadDocument = function(key) {
- // Split the key up
- var parts = key.split('.', 2);
- // Ask for what we want
- var _this = this;
- _this.doc = new haste_document(this);
- _this.doc.load(parts[0], function(ret) {
- if (ret) {
- _this.$code.html(ret.value);
- _this.setTitle(ret.key);
- _this.fullKey();
- _this.$textarea.val('').hide();
- _this.$box.show().focus();
- _this.addLineNumbers(ret.lineCount);
- }
- else {
- _this.newDocument();
- }
- }, this.lookupTypeByExtension(parts[1]));
-};
-
-// Duplicate the current document - only if locked
-haste.prototype.duplicateDocument = function() {
- if (this.doc.locked) {
- var currentData = this.doc.data;
- this.newDocument();
- this.$textarea.val(currentData);
- }
-};
-
-// Lock the current document
-haste.prototype.lockDocument = function() {
- var _this = this;
- this.doc.save(this.$textarea.val(), function(err, ret) {
- if (err) {
- _this.showMessage(err.message, 'error');
- }
- else if (ret) {
- _this.$code.html(ret.value);
- _this.setTitle(ret.key);
- var file = _this.baseUrl + ret.key;
- if (ret.language) {
- file += '.' + _this.lookupExtensionByType(ret.language);
- }
- window.history.pushState(null, _this.appName + '-' + ret.key, file);
- _this.fullKey();
- _this.$textarea.val('').hide();
- _this.$box.show().focus();
- _this.addLineNumbers(ret.lineCount);
- // Load Document Again
- var path = window.location.href;
- console.log(path);
- _this.loadDocument(path.split('#')[0].split('/').slice(-1)[0]);
- }
- });
-};
-
-haste.prototype.configureButtons = function() {
- var _this = this;
- this.buttons = [
- {
- $where: $('#box2 .save'),
- label: 'Save',
- shortcutDescription: 'control + s',
- shortcut: function(evt) {
- return evt.ctrlKey && (evt.keyCode === 83);
+
+ // Escapes HTML tag characters
+ haste_document.prototype.htmlEscape = function(s) {
+ return s
+ .replace(/&/g, '&')
+ .replace(/>/g, '>')
+ .replace(/= selectedLines.startLine &&
+ currentLine <= selectedLines.endLine
+ ) {
+ spanClass = "lineHighlight";
+ }
+ highlighted = "" + highlighted + "";
+ high.value += highlighted + "\n";
+ }
+ //// scroll to position in document after ensuring components h"ve had time to render
+ setTimeout(function() {
+ // show current line and the one before it
+ if (selectedLines.startLine >= 3) {
+ document.body.scrollTo(0, $("#line-" + (selectedLines.startLine - 2)).offset().top);
+ } else {
+ // if lines 1-2, go to top of file
+ document.body.scrollTo(0, 0);
+ }
+ }, 0);
+ } catch(err) {
+ // failed highlight, fall back on auto
+ high = hljs.highlightAuto(res.data);
+ }
+ callback({
+ value: high.value,
+ key: key,
+ language: high.language || lang,
+ lineCount: res.data.split('\n').length
+ });
},
- action: function() {
- if (_this.$textarea.val().replace(/^\s+|\s+$/g, '') !== '') {
- _this.lockDocument();
+ error: function() {
+ callback(false);
+ }
+ });
+ };
+
+ // Save this document to the server and lock it here
+ haste_document.prototype.save = function(data, callback) {
+ if (this.locked) {
+ return false;
+ }
+ this.data = data;
+ var _this = this;
+ $.ajax(_this.app.baseUrl + 'documents', {
+ type: 'post',
+ data: data,
+ dataType: 'json',
+ contentType: 'text/plain; charset=utf-8',
+ success: function(res) {
+ _this.locked = true;
+ _this.key = res.key;
+ var high = hljs.highlightAuto(data);
+ callback(null, {
+ value: high.value,
+ key: res.key,
+ language: high.language,
+ lineCount: data.split('\n').length
+ });
+ },
+ error: function(res) {
+ try {
+ callback($.parseJSON(res.responseText));
+ }
+ catch (e) {
+ callback({message: 'Something went wrong!'});
}
}
- },
- {
- $where: $('#box2 .new'),
- label: 'New',
- shortcut: function(evt) {
- return evt.ctrlKey && evt.keyCode === 78;
- },
- shortcutDescription: 'control + n',
- action: function() {
- _this.newDocument(!_this.doc.key);
- }
- },
- {
- $where: $('#box2 .duplicate'),
- label: 'Duplicate & Edit',
- shortcut: function(evt) {
- return _this.doc.locked && evt.ctrlKey && evt.keyCode === 68;
- },
- shortcutDescription: 'control + d',
- action: function() {
- _this.duplicateDocument();
- }
- },
- {
- $where: $('#box2 .raw'),
- label: 'Just Text',
- shortcut: function(evt) {
- return evt.ctrlKey && evt.shiftKey && evt.keyCode === 82;
- },
- shortcutDescription: 'control + shift + r',
- action: function() {
- window.location.href = _this.baseUrl + 'raw/' + _this.doc.key;
- }
- },
- {
- $where: $('#box2 .twitter'),
- label: 'Twitter',
- shortcut: function(evt) {
- return _this.options.twitter && _this.doc.locked && evt.shiftKey && evt.ctrlKey && evt.keyCode == 84;
- },
- shortcutDescription: 'control + shift + t',
- action: function() {
- window.open('https://twitter.com/share?url=' + encodeURI(window.location.href));
+ });
+ };
+
+ ///// represents the paste application
+
+ var haste = function(appName, options) {
+ this.appName = appName;
+ this.$textarea = $('textarea');
+ this.$box = $('#box');
+ this.$code = $('#box code');
+ this.$linenos = $('#linenos');
+ this.options = options;
+ this.configureShortcuts();
+ this.configureButtons();
+ // If twitter is disabled, hide the button
+ if (!options.twitter) {
+ $('#box2 .twitter').hide();
+ };
+ this.baseUrl = options.baseUrl || '/';
+ this.selectedLines = options.selectedLines;
+ };
+
+ // Set the page title - include the appName
+ haste.prototype.setTitle = function(ext) {
+ var title = ext ? this.appName + ' - ' + ext : this.appName;
+ document.title = title;
+ };
+
+ // Show a message box
+ haste.prototype.showMessage = function(msg, cls) {
+ var msgBox = $(''+msg+'');
+ $('#messages').prepend(msgBox);
+ setTimeout(function() {
+ msgBox.slideUp('fast', function() { $(this).remove(); });
+ }, 3000);
+ };
+
+ // Show the light key
+ haste.prototype.lightKey = function() {
+ this.configureKey(['new', 'save']);
+ };
+
+ // Show the full key
+ haste.prototype.fullKey = function() {
+ this.configureKey(['new', 'duplicate', 'twitter', 'raw']);
+ };
+
+ // Set the key up for certain things to be enabled
+ haste.prototype.configureKey = function(enable) {
+ var $this, i = 0;
+ $('#box2 .function').each(function() {
+ $this = $(this);
+ for (i = 0; i < enable.length; i++) {
+ if ($this.hasClass(enable[i])) {
+ $this.addClass('enabled');
+ return true;
+ }
}
+ $this.removeClass('enabled');
+ });
+ };
+
+ // Remove the current document (if there is one)
+ // and set up for a new one
+ haste.prototype.newDocument = function(hideHistory) {
+ this.$box.hide();
+ this.doc = new haste_document(this);
+ if (!hideHistory) {
+ window.history.pushState(null, this.appName, this.baseUrl);
}
- ];
- for (var i = 0; i < this.buttons.length; i++) {
- this.configureButton(this.buttons[i]);
- }
-};
-
-haste.prototype.configureButton = function(options) {
- // Handle the click action
- options.$where.click(function(evt) {
- evt.preventDefault();
- if (!options.clickDisabled && $(this).hasClass('enabled')) {
- options.action();
+ this.setTitle();
+ this.lightKey();
+ this.$textarea.val('').show('fast', function() {
+ this.focus();
+ });
+ this.selectedLines = { startLine: null, endLine: null };
+ this.removeLineNumbers();
+ };
+
+ // Map of common extensions
+ // Note: this list does not need to include anything that IS its extension,
+ // due to the behavior of lookupTypeByExtension and lookupExtensionByType
+ // Note: optimized for lookupTypeByExtension
+ haste.extensionMap = {
+ rb: 'ruby', py: 'python', pl: 'perl', php: 'php', scala: 'scala', go: 'go',
+ xml: 'xml', html: 'xml', htm: 'xml', css: 'css', js: 'javascript', vbs: 'vbscript',
+ lua: 'lua', pas: 'delphi', java: 'java', cpp: 'cpp', cc: 'cpp', m: 'objectivec',
+ vala: 'vala', sql: 'sql', sm: 'smalltalk', lisp: 'lisp', ini: 'ini',
+ diff: 'diff', bash: 'bash', sh: 'bash', tex: 'tex', erl: 'erlang', hs: 'haskell',
+ md: 'markdown', txt: '', coffee: 'coffee', swift: 'swift'
+ };
+
+ // Look up the extension preferred for a type
+ // If not found, return the type itself - which we'll place as the extension
+ haste.prototype.lookupExtensionByType = function(type) {
+ for (var key in haste.extensionMap) {
+ if (haste.extensionMap[key] === type) return key;
}
- });
- // Show the label
- options.$where.mouseenter(function() {
- $('#box3 .label').text(options.label);
- $('#box3 .shortcut').text(options.shortcutDescription || '');
- $('#box3').show();
- $(this).append($('#pointer').remove().show());
- });
- // Hide the label
- options.$where.mouseleave(function() {
- $('#box3').hide();
- $('#pointer').hide();
- });
-};
-
-// Configure keyboard shortcuts for the textarea
-haste.prototype.configureShortcuts = function() {
- var _this = this;
- $(document.body).keydown(function(evt) {
- var button;
- for (var i = 0 ; i < _this.buttons.length; i++) {
- button = _this.buttons[i];
- if (button.shortcut && button.shortcut(evt)) {
- evt.preventDefault();
- button.action();
- return;
- }
+ return type;
+ };
+
+ // Look up the type for a given extension
+ // If not found, return the extension - which we'll attempt to use as the type
+ haste.prototype.lookupTypeByExtension = function(ext) {
+ return haste.extensionMap[ext] || ext;
+ };
+
+ // Add line numbers to the document
+ // For the specified number of lines
+ haste.prototype.addLineNumbers = function(lineCount) {
+ var h = '';
+ for (var i = 0; i < lineCount; i++) {
+ h +=
+ '' +
+ (i + 1) +
+ "
";
}
- });
-};
-
-///// Tab behavior in the textarea - 2 spaces per tab
-$(function() {
-
- $('textarea').keydown(function(evt) {
- if (evt.keyCode === 9) {
- evt.preventDefault();
- var myValue = ' ';
- // http://stackoverflow.com/questions/946534/insert-text-into-textarea-with-jquery
- // For browsers like Internet Explorer
- if (document.selection) {
- this.focus();
- var sel = document.selection.createRange();
- sel.text = myValue;
- this.focus();
- }
- // Mozilla and Webkit
- else if (this.selectionStart || this.selectionStart == '0') {
- var startPos = this.selectionStart;
- var endPos = this.selectionEnd;
- var 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;
+ $('#linenos').html(h);
+ };
+
+ // Remove the line numbers
+ haste.prototype.removeLineNumbers = function() {
+ $('#linenos').html('>');
+ };
+
+ // Load a document and show it
+ haste.prototype.loadDocument = function(key) {
+ // Split the key up
+ var parts = key.split('.', 2);
+ // Ask for what we want
+ var _this = this;
+ _this.doc = new haste_document(this);
+ _this.doc.load(parts[0], function(ret) {
+ if (ret) {
+ _this.$code.html(ret.value);
+ _this.setTitle(ret.key);
+ _this.fullKey();
+ _this.$textarea.val('').hide();
+ _this.$box.show().focus();
+ _this.addLineNumbers(ret.lineCount);
}
else {
- this.value += myValue;
- this.focus();
+ _this.newDocument();
}
+ }, this.lookupTypeByExtension(parts[1]));
+ };
+
+ // Duplicate the current document - only if locked
+ haste.prototype.duplicateDocument = function() {
+ if (this.doc.locked) {
+ var currentData = this.doc.data;
+ this.newDocument();
+ this.$textarea.val(currentData);
}
- });
-});
\ No newline at end of file
+ };
+
+ // Lock the current document
+ haste.prototype.lockDocument = function() {
+ var _this = this;
+ this.doc.save(this.$textarea.val(), function(err, ret) {
+ if (err) {
+ _this.showMessage(err.message, 'error');
+ }
+ else if (ret) {
+ _this.$code.html(ret.value);
+ _this.setTitle(ret.key);
+ var file = _this.baseUrl + ret.key;
+ if (ret.language) {
+ file += '.' + _this.lookupExtensionByType(ret.language);
+ }
+ window.history.pushState(null, _this.appName + '-' + ret.key, file);
+ _this.fullKey();
+ _this.$textarea.val('').hide();
+ _this.$box.show().focus();
+ _this.addLineNumbers(ret.lineCount);
+ // Load Document Again
+ var path = window.location.href;
+ _this.loadDocument(path.split('#')[0].split('/').slice(-1)[0]);
+ }
+ });
+ };
+
+ haste.prototype.configureButtons = function() {
+ var _this = this;
+ this.buttons = [
+ {
+ $where: $('#box2 .save'),
+ label: 'Save',
+ shortcutDescription: 'control + s',
+ shortcut: function(evt) {
+ return evt.ctrlKey && (evt.keyCode === 83);
+ },
+ action: function() {
+ if (_this.$textarea.val().replace(/^\s+|\s+$/g, '') !== '') {
+ _this.lockDocument();
+ }
+ }
+ },
+ {
+ $where: $('#box2 .new'),
+ label: 'New',
+ shortcut: function(evt) {
+ return evt.ctrlKey && evt.keyCode === 78;
+ },
+ shortcutDescription: 'control + n',
+ action: function() {
+ _this.newDocument(!_this.doc.key);
+ }
+ },
+ {
+ $where: $('#box2 .duplicate'),
+ label: 'Duplicate & Edit',
+ shortcut: function(evt) {
+ return _this.doc.locked && evt.ctrlKey && evt.keyCode === 68;
+ },
+ shortcutDescription: 'control + d',
+ action: function() {
+ _this.duplicateDocument();
+ }
+ },
+ {
+ $where: $('#box2 .raw'),
+ label: 'Just Text',
+ shortcut: function(evt) {
+ return evt.ctrlKey && evt.shiftKey && evt.keyCode === 82;
+ },
+ shortcutDescription: 'control + shift + r',
+ action: function() {
+ window.location.href = _this.baseUrl + 'raw/' + _this.doc.key;
+ }
+ },
+ {
+ $where: $('#box2 .twitter'),
+ label: 'Twitter',
+ shortcut: function(evt) {
+ return _this.options.twitter && _this.doc.locked && evt.shiftKey && evt.ctrlKey && evt.keyCode == 84;
+ },
+ shortcutDescription: 'control + shift + t',
+ action: function() {
+ window.open('https://twitter.com/share?url=' + encodeURI(window.location.href));
+ }
+ }
+ ];
+ for (var i = 0; i < this.buttons.length; i++) {
+ this.configureButton(this.buttons[i]);
+ }
+ };
+
+ haste.prototype.configureButton = function(options) {
+ // Handle the click action
+ options.$where.click(function(evt) {
+ evt.preventDefault();
+ if (!options.clickDisabled && $(this).hasClass('enabled')) {
+ options.action();
+ }
+ });
+ // Show the label
+ options.$where.mouseenter(function() {
+ $('#box3 .label').text(options.label);
+ $('#box3 .shortcut').text(options.shortcutDescription || '');
+ $('#box3').show();
+ $(this).append($('#pointer').remove().show());
+ });
+ // Hide the label
+ options.$where.mouseleave(function() {
+ $('#box3').hide();
+ $('#pointer').hide();
+ });
+ };
+
+ // Configure keyboard shortcuts for the textarea
+ haste.prototype.configureShortcuts = function() {
+ var _this = this;
+ $(document.body).keydown(function(evt) {
+ var button;
+ for (var i = 0 ; i < _this.buttons.length; i++) {
+ button = _this.buttons[i];
+ if (button.shortcut && button.shortcut(evt)) {
+ evt.preventDefault();
+ button.action();
+ return;
+ }
+ }
+ });
+ };
+
+ ///// Tab behavior in the textarea - 2 spaces per tab
+ $(function() {
+
+ $('textarea').keydown(function(evt) {
+ if (evt.keyCode === 9) {
+ evt.preventDefault();
+ var myValue = ' ';
+ // http://stackoverflow.com/questions/946534/insert-text-into-textarea-with-jquery
+ // For browsers like Internet Explorer
+ if (document.selection) {
+ this.focus();
+ var sel = document.selection.createRange();
+ sel.text = myValue;
+ this.focus();
+ }
+ // Mozilla and Webkit
+ else if (this.selectionStart || this.selectionStart == '0') {
+ var startPos = this.selectionStart;
+ var endPos = this.selectionEnd;
+ var 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();
+ }
+ }
+ });
+
+ });
\ No newline at end of file
diff --git a/static/index.html b/static/index.html
index ae13a01..d33d94f 100644
--- a/static/index.html
+++ b/static/index.html
@@ -1,166 +1,162 @@
-
+
- hastebin
-
-
-
+ hastebin
+
+
+
-
-
-
+
+
+
-
+
-
- function handleMouseUp(lineId) {
- if(!isDragging){
- return;
- }
- if(isNaN(lineId)){
- lineId = app.selectedLines.endLine;
- }else {
- lineId = lineId + 1;
- }
- updateWindowLineHash(lineId);
- isDragging = false;
- }
-
+
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
+
\ No newline at end of file