Update text editor
This commit is contained in:
@@ -31,7 +31,7 @@ function Modal(parent, closeCallback, title, width, height) {
|
||||
|
||||
this.btnClose = document.createElement("button")
|
||||
this.btnClose.classList = "modal_btn_close button_red"
|
||||
this.btnClose.innerHTML = '<i class="icon small">close</i>'
|
||||
this.btnClose.innerHTML = '<i class="icon">close</i>'
|
||||
this.btnClose.addEventListener("click", e => { this.close() })
|
||||
|
||||
this.body = document.createElement("div")
|
||||
|
@@ -1,58 +0,0 @@
|
||||
function uploadText() {
|
||||
var text = document.getElementById("textarea").value;
|
||||
var blob = new Blob([text], {type: "text/plain"});
|
||||
var filename = prompt("What do you want to call this piece of textual art?\n\n"
|
||||
+ "Please add your own file extension, if you want.",
|
||||
"Pixeldrain_Text_File.txt");
|
||||
|
||||
if(filename === null){
|
||||
return;
|
||||
}
|
||||
|
||||
new UploadManager(apiEndpoint+"/file", null).addFile(
|
||||
blob,
|
||||
filename,
|
||||
null,
|
||||
function (id){
|
||||
addUploadHistory(id);
|
||||
setTimeout(window.location.href = "/u/" + id, 100);
|
||||
},
|
||||
function (response, error) { alert("File upload failed! The server told us this: " + response); }
|
||||
)
|
||||
}
|
||||
|
||||
// Upload the file when ctrl + s is pressed
|
||||
document.addEventListener("keydown", function(event) {
|
||||
if ((event.ctrlKey || event.metaKey) && event.keyCode === 83) {
|
||||
event.preventDefault();
|
||||
uploadText();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Prevent the Tab key from moving the cursor outside of the text area
|
||||
*/
|
||||
document.getElementById("textarea").addEventListener(
|
||||
'keydown',
|
||||
function(e) {
|
||||
if(e.keyCode === 9) { // tab was pressed
|
||||
// get caret position/selection
|
||||
var start = this.selectionStart;
|
||||
var end = this.selectionEnd;
|
||||
|
||||
var target = e.target;
|
||||
var value = target.value;
|
||||
|
||||
// set textarea value to: text before caret + tab + text after caret
|
||||
target.value = value.substring(0, start) + "\t" + value.substring(end);
|
||||
|
||||
// put caret at right position again (add one for the tab)
|
||||
this.selectionStart = this.selectionEnd = start + 1;
|
||||
|
||||
// prevent the focus lose
|
||||
e.preventDefault();
|
||||
}
|
||||
},
|
||||
false
|
||||
);
|
@@ -34,7 +34,7 @@
|
||||
font-family: 'Material Icons';
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-size: 24px; /* Preferred icon size */
|
||||
font-size: 1.6em;
|
||||
display: inline-block;
|
||||
line-height: 1;
|
||||
text-transform: none;
|
||||
@@ -45,17 +45,11 @@
|
||||
text-rendering: optimizeLegibility;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.icon.small {
|
||||
font-size: 16px;
|
||||
}
|
||||
a > svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.icon.small { font-size: 1.2em; }
|
||||
a > svg { vertical-align: middle; }
|
||||
|
||||
/* Page rendering configuration */
|
||||
html, body {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
html, body { overflow-x: hidden; }
|
||||
body{
|
||||
background-color: #111111; /* Fallback */
|
||||
background-color: var(--layer_2_color);
|
||||
@@ -301,10 +295,9 @@ a:hover {
|
||||
table:not(.form) {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin: 14px;
|
||||
}
|
||||
tr:not(.form) {border-bottom: 1px var(--layer_2_color_border) solid;}
|
||||
tr > td, tr > th {padding: 0.3em;}
|
||||
tr > td, tr > th {padding: 0.4em;}
|
||||
@media(max-width: 30em) {
|
||||
/* Forms will be stacked on small screens */
|
||||
tr.form > td {
|
||||
@@ -321,15 +314,6 @@ pre {
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.big_button{
|
||||
width: 40%;
|
||||
min-width: 250px;
|
||||
max-width: 400px;
|
||||
margin: 10px !important;
|
||||
border-radius: 5px;
|
||||
font-size: 1.8em;
|
||||
}
|
||||
|
||||
.file_button{
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
@@ -413,9 +397,8 @@ select {
|
||||
border: none;
|
||||
margin: 3px;
|
||||
background: linear-gradient(var(--input_color), var(--input_color_dark));
|
||||
padding: .4em .5em .4em .5em;
|
||||
padding: .3em .4em .3em .4em;
|
||||
box-shadow: 2px 2px 6px -3px var(--shadow_color);
|
||||
font-size: 0.9em;
|
||||
line-height: 1em;
|
||||
overflow: hidden;
|
||||
text-decoration: none;
|
||||
@@ -451,7 +434,7 @@ input[type="color"]:active,
|
||||
select:active{
|
||||
background: linear-gradient(var(--input_color_dark), var(--input_color));
|
||||
box-shadow: inset 4px 4px 8px var(--shadow_color);
|
||||
padding: .6em .3em .2em .7em; /* Exactly .2em offset compared to the inactive padding to give a depth effect */
|
||||
padding: .5em .2em .1em .6em; /* Exactly .2em offset compared to the inactive padding to give a depth effect */
|
||||
}
|
||||
.button_full_width {width: calc(100% - 6px);}
|
||||
.button_highlight {background: linear-gradient(var(--highlight_color), var(--highlight_color_dark)) !important; color: var(--highlight_text_color) !important;}
|
||||
|
@@ -44,15 +44,14 @@
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.file_viewer > .file_viewer_headerbar > .button_home > svg {
|
||||
height: 1.6em;
|
||||
width: 1.6em;
|
||||
margin: -0.1em 0.2em -0.1em -0.1em;
|
||||
}
|
||||
.file_viewer > .file_viewer_headerbar > .button_home::after {
|
||||
content: "pixeldrain";
|
||||
}
|
||||
.file_viewer > .file_viewer_headerbar > .button_home > svg {
|
||||
height: 1.7em;
|
||||
width: 1.7em;
|
||||
margin: -0.25em;
|
||||
margin-right: 0.2em;
|
||||
}
|
||||
@media (max-width: 600px) {
|
||||
.file_viewer > .file_viewer_headerbar > .button_home::after {
|
||||
content: "pd";
|
||||
|
631
res/static/script/behave.js
Normal file
631
res/static/script/behave.js
Normal file
@@ -0,0 +1,631 @@
|
||||
/*
|
||||
* Behave.js
|
||||
*
|
||||
* Copyright 2013, Jacob Kelley - http://jakiestfu.com/
|
||||
* Released under the MIT Licence
|
||||
* http://opensource.org/licenses/MIT
|
||||
*
|
||||
* Github: http://github.com/jakiestfu/Behave.js/
|
||||
* Version: 1.5
|
||||
*/
|
||||
|
||||
(function(undefined){
|
||||
'use strict';
|
||||
|
||||
var BehaveHooks = BehaveHooks || (function(){
|
||||
var hooks = {};
|
||||
|
||||
return {
|
||||
add: function(hookName, fn){
|
||||
if(typeof hookName == "object"){
|
||||
var i;
|
||||
for(i=0; i<hookName.length; i++){
|
||||
var theHook = hookName[i];
|
||||
if(!hooks[theHook]){
|
||||
hooks[theHook] = [];
|
||||
}
|
||||
hooks[theHook].push(fn);
|
||||
}
|
||||
} else {
|
||||
if(!hooks[hookName]){
|
||||
hooks[hookName] = [];
|
||||
}
|
||||
hooks[hookName].push(fn);
|
||||
}
|
||||
},
|
||||
get: function(hookName){
|
||||
if(hooks[hookName]){
|
||||
return hooks[hookName];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
})(),
|
||||
Behave = Behave || function (userOpts) {
|
||||
|
||||
if (typeof String.prototype.repeat !== 'function') {
|
||||
String.prototype.repeat = function(times) {
|
||||
if(times < 1){
|
||||
return '';
|
||||
}
|
||||
if(times % 2){
|
||||
return this.repeat(times - 1) + this;
|
||||
}
|
||||
var half = this.repeat(times / 2);
|
||||
return half + half;
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof Array.prototype.filter !== 'function') {
|
||||
Array.prototype.filter = function(func /*, thisp */) {
|
||||
if (this === null) {
|
||||
throw new TypeError();
|
||||
}
|
||||
|
||||
var t = Object(this),
|
||||
len = t.length >>> 0;
|
||||
if (typeof func != "function"){
|
||||
throw new TypeError();
|
||||
}
|
||||
var res = [],
|
||||
thisp = arguments[1];
|
||||
for (var i = 0; i < len; i++) {
|
||||
if (i in t) {
|
||||
var val = t[i];
|
||||
if (func.call(thisp, val, i, t)) {
|
||||
res.push(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
var defaults = {
|
||||
textarea: null,
|
||||
replaceTab: true,
|
||||
softTabs: true,
|
||||
tabSize: 4,
|
||||
autoOpen: true,
|
||||
overwrite: true,
|
||||
autoStrip: true,
|
||||
autoIndent: true,
|
||||
fence: false
|
||||
},
|
||||
tab,
|
||||
newLine,
|
||||
charSettings = {
|
||||
|
||||
keyMap: [
|
||||
{ open: "\"", close: "\"", canBreak: false },
|
||||
{ open: "'", close: "'", canBreak: false },
|
||||
{ open: "(", close: ")", canBreak: false },
|
||||
{ open: "[", close: "]", canBreak: true },
|
||||
{ open: "{", close: "}", canBreak: true }
|
||||
]
|
||||
|
||||
},
|
||||
utils = {
|
||||
|
||||
_callHook: function(hookName, passData){
|
||||
var hooks = BehaveHooks.get(hookName);
|
||||
passData = typeof passData=="boolean" && passData === false ? false : true;
|
||||
|
||||
if(hooks){
|
||||
if(passData){
|
||||
var theEditor = defaults.textarea,
|
||||
textVal = theEditor.value,
|
||||
caretPos = utils.cursor.get(),
|
||||
i;
|
||||
|
||||
for(i=0; i<hooks.length; i++){
|
||||
hooks[i].call(undefined, {
|
||||
editor: {
|
||||
element: theEditor,
|
||||
text: textVal,
|
||||
levelsDeep: utils.levelsDeep()
|
||||
},
|
||||
caret: {
|
||||
pos: caretPos
|
||||
},
|
||||
lines: {
|
||||
current: utils.cursor.getLine(textVal, caretPos),
|
||||
total: utils.editor.getLines(textVal)
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
for(i=0; i<hooks.length; i++){
|
||||
hooks[i].call(undefined);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
defineNewLine: function(){
|
||||
var ta = document.createElement('textarea');
|
||||
ta.value = "\n";
|
||||
|
||||
if(ta.value.length==2){
|
||||
newLine = "\r\n";
|
||||
} else {
|
||||
newLine = "\n";
|
||||
}
|
||||
},
|
||||
defineTabSize: function(tabSize){
|
||||
if(typeof defaults.textarea.style.OTabSize != "undefined"){
|
||||
defaults.textarea.style.OTabSize = tabSize; return;
|
||||
}
|
||||
if(typeof defaults.textarea.style.MozTabSize != "undefined"){
|
||||
defaults.textarea.style.MozTabSize = tabSize; return;
|
||||
}
|
||||
if(typeof defaults.textarea.style.tabSize != "undefined"){
|
||||
defaults.textarea.style.tabSize = tabSize; return;
|
||||
}
|
||||
},
|
||||
cursor: {
|
||||
getLine: function(textVal, pos){
|
||||
return ((textVal.substring(0,pos)).split("\n")).length;
|
||||
},
|
||||
get: function() {
|
||||
|
||||
if (typeof document.createElement('textarea').selectionStart==="number") {
|
||||
return defaults.textarea.selectionStart;
|
||||
} else if (document.selection) {
|
||||
var caretPos = 0,
|
||||
range = defaults.textarea.createTextRange(),
|
||||
rangeDupe = document.selection.createRange().duplicate(),
|
||||
rangeDupeBookmark = rangeDupe.getBookmark();
|
||||
range.moveToBookmark(rangeDupeBookmark);
|
||||
|
||||
while (range.moveStart('character' , -1) !== 0) {
|
||||
caretPos++;
|
||||
}
|
||||
return caretPos;
|
||||
}
|
||||
},
|
||||
set: function (start, end) {
|
||||
if(!end){
|
||||
end = start;
|
||||
}
|
||||
if (defaults.textarea.setSelectionRange) {
|
||||
defaults.textarea.focus();
|
||||
defaults.textarea.setSelectionRange(start, end);
|
||||
} else if (defaults.textarea.createTextRange) {
|
||||
var range = defaults.textarea.createTextRange();
|
||||
range.collapse(true);
|
||||
range.moveEnd('character', end);
|
||||
range.moveStart('character', start);
|
||||
range.select();
|
||||
}
|
||||
},
|
||||
selection: function(){
|
||||
var textAreaElement = defaults.textarea,
|
||||
start = 0,
|
||||
end = 0,
|
||||
normalizedValue,
|
||||
range,
|
||||
textInputRange,
|
||||
len,
|
||||
endRange;
|
||||
|
||||
if (typeof textAreaElement.selectionStart == "number" && typeof textAreaElement.selectionEnd == "number") {
|
||||
start = textAreaElement.selectionStart;
|
||||
end = textAreaElement.selectionEnd;
|
||||
} else {
|
||||
range = document.selection.createRange();
|
||||
|
||||
if (range && range.parentElement() == textAreaElement) {
|
||||
|
||||
normalizedValue = utils.editor.get();
|
||||
len = normalizedValue.length;
|
||||
|
||||
textInputRange = textAreaElement.createTextRange();
|
||||
textInputRange.moveToBookmark(range.getBookmark());
|
||||
|
||||
endRange = textAreaElement.createTextRange();
|
||||
endRange.collapse(false);
|
||||
|
||||
if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
|
||||
start = end = len;
|
||||
} else {
|
||||
start = -textInputRange.moveStart("character", -len);
|
||||
start += normalizedValue.slice(0, start).split(newLine).length - 1;
|
||||
|
||||
if (textInputRange.compareEndPoints("EndToEnd", endRange) > -1) {
|
||||
end = len;
|
||||
} else {
|
||||
end = -textInputRange.moveEnd("character", -len);
|
||||
end += normalizedValue.slice(0, end).split(newLine).length - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return start==end ? false : {
|
||||
start: start,
|
||||
end: end
|
||||
};
|
||||
}
|
||||
},
|
||||
editor: {
|
||||
getLines: function(textVal){
|
||||
return (textVal).split("\n").length;
|
||||
},
|
||||
get: function(){
|
||||
return defaults.textarea.value.replace(/\r/g,'');
|
||||
},
|
||||
set: function(data){
|
||||
defaults.textarea.value = data;
|
||||
}
|
||||
},
|
||||
fenceRange: function(){
|
||||
if(typeof defaults.fence == "string"){
|
||||
|
||||
var data = utils.editor.get(),
|
||||
pos = utils.cursor.get(),
|
||||
hacked = 0,
|
||||
matchedFence = data.indexOf(defaults.fence),
|
||||
matchCase = 0;
|
||||
|
||||
while(matchedFence>=0){
|
||||
matchCase++;
|
||||
if( pos < (matchedFence+hacked) ){
|
||||
break;
|
||||
}
|
||||
|
||||
hacked += matchedFence+defaults.fence.length;
|
||||
data = data.substring(matchedFence+defaults.fence.length);
|
||||
matchedFence = data.indexOf(defaults.fence);
|
||||
|
||||
}
|
||||
|
||||
if( (hacked) < pos && ( (matchedFence+hacked) > pos ) && matchCase%2===0){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
isEven: function(_this,i){
|
||||
return i%2;
|
||||
},
|
||||
levelsDeep: function(){
|
||||
var pos = utils.cursor.get(),
|
||||
val = utils.editor.get();
|
||||
|
||||
var left = val.substring(0, pos),
|
||||
levels = 0,
|
||||
i, j;
|
||||
|
||||
for(i=0; i<left.length; i++){
|
||||
for (j=0; j<charSettings.keyMap.length; j++) {
|
||||
if(charSettings.keyMap[j].canBreak){
|
||||
if(charSettings.keyMap[j].open == left.charAt(i)){
|
||||
levels++;
|
||||
}
|
||||
|
||||
if(charSettings.keyMap[j].close == left.charAt(i)){
|
||||
levels--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var toDecrement = 0,
|
||||
quoteMap = ["'", "\""];
|
||||
for(i=0; i<charSettings.keyMap.length; i++) {
|
||||
if(charSettings.keyMap[i].canBreak){
|
||||
for(j in quoteMap){
|
||||
toDecrement += left.split(quoteMap[j]).filter(utils.isEven).join('').split(charSettings.keyMap[i].open).length - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var finalLevels = levels - toDecrement;
|
||||
|
||||
return finalLevels >=0 ? finalLevels : 0;
|
||||
},
|
||||
deepExtend: function(destination, source) {
|
||||
for (var property in source) {
|
||||
if (source[property] && source[property].constructor &&
|
||||
source[property].constructor === Object) {
|
||||
destination[property] = destination[property] || {};
|
||||
utils.deepExtend(destination[property], source[property]);
|
||||
} else {
|
||||
destination[property] = source[property];
|
||||
}
|
||||
}
|
||||
return destination;
|
||||
},
|
||||
addEvent: function addEvent(element, eventName, func) {
|
||||
if (element.addEventListener){
|
||||
element.addEventListener(eventName,func,false);
|
||||
} else if (element.attachEvent) {
|
||||
element.attachEvent("on"+eventName, func);
|
||||
}
|
||||
},
|
||||
removeEvent: function addEvent(element, eventName, func){
|
||||
if (element.addEventListener){
|
||||
element.removeEventListener(eventName,func,false);
|
||||
} else if (element.attachEvent) {
|
||||
element.detachEvent("on"+eventName, func);
|
||||
}
|
||||
},
|
||||
|
||||
preventDefaultEvent: function(e){
|
||||
if(e.preventDefault){
|
||||
e.preventDefault();
|
||||
} else {
|
||||
e.returnValue = false;
|
||||
}
|
||||
}
|
||||
},
|
||||
intercept = {
|
||||
tabKey: function (e) {
|
||||
|
||||
if(!utils.fenceRange()){ return; }
|
||||
|
||||
if (e.keyCode == 9) {
|
||||
utils.preventDefaultEvent(e);
|
||||
|
||||
var toReturn = true;
|
||||
utils._callHook('tab:before');
|
||||
|
||||
var selection = utils.cursor.selection(),
|
||||
pos = utils.cursor.get(),
|
||||
val = utils.editor.get();
|
||||
|
||||
if(selection){
|
||||
|
||||
var tempStart = selection.start;
|
||||
while(tempStart--){
|
||||
if(val.charAt(tempStart)=="\n"){
|
||||
selection.start = tempStart + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var toIndent = val.substring(selection.start, selection.end),
|
||||
lines = toIndent.split("\n"),
|
||||
i;
|
||||
|
||||
if(e.shiftKey){
|
||||
for(i = 0; i<lines.length; i++){
|
||||
if(lines[i].substring(0,tab.length) == tab){
|
||||
lines[i] = lines[i].substring(tab.length);
|
||||
}
|
||||
}
|
||||
toIndent = lines.join("\n");
|
||||
|
||||
utils.editor.set( val.substring(0,selection.start) + toIndent + val.substring(selection.end) );
|
||||
utils.cursor.set(selection.start, selection.start+toIndent.length);
|
||||
|
||||
} else {
|
||||
for(i in lines){
|
||||
lines[i] = tab + lines[i];
|
||||
}
|
||||
toIndent = lines.join("\n");
|
||||
|
||||
utils.editor.set( val.substring(0,selection.start) + toIndent + val.substring(selection.end) );
|
||||
utils.cursor.set(selection.start, selection.start+toIndent.length);
|
||||
}
|
||||
} else {
|
||||
var left = val.substring(0, pos),
|
||||
right = val.substring(pos),
|
||||
edited = left + tab + right;
|
||||
|
||||
if(e.shiftKey){
|
||||
if(val.substring(pos-tab.length, pos) == tab){
|
||||
edited = val.substring(0, pos-tab.length) + right;
|
||||
utils.editor.set(edited);
|
||||
utils.cursor.set(pos-tab.length);
|
||||
}
|
||||
} else {
|
||||
utils.editor.set(edited);
|
||||
utils.cursor.set(pos + tab.length);
|
||||
toReturn = false;
|
||||
}
|
||||
}
|
||||
utils._callHook('tab:after');
|
||||
}
|
||||
return toReturn;
|
||||
},
|
||||
enterKey: function (e) {
|
||||
|
||||
if(!utils.fenceRange()){ return; }
|
||||
|
||||
if (e.keyCode == 13) {
|
||||
|
||||
utils.preventDefaultEvent(e);
|
||||
utils._callHook('enter:before');
|
||||
|
||||
var pos = utils.cursor.get(),
|
||||
val = utils.editor.get(),
|
||||
left = val.substring(0, pos),
|
||||
right = val.substring(pos),
|
||||
leftChar = left.charAt(left.length - 1),
|
||||
rightChar = right.charAt(0),
|
||||
numTabs = utils.levelsDeep(),
|
||||
ourIndent = "",
|
||||
closingBreak = "",
|
||||
finalCursorPos,
|
||||
i;
|
||||
if(!numTabs){
|
||||
finalCursorPos = 1;
|
||||
} else {
|
||||
while(numTabs--){
|
||||
ourIndent+=tab;
|
||||
}
|
||||
ourIndent = ourIndent;
|
||||
finalCursorPos = ourIndent.length + 1;
|
||||
|
||||
for(i=0; i<charSettings.keyMap.length; i++) {
|
||||
if (charSettings.keyMap[i].open == leftChar && charSettings.keyMap[i].close == rightChar){
|
||||
closingBreak = newLine;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var edited = left + newLine + ourIndent + closingBreak + (ourIndent.substring(0, ourIndent.length-tab.length) ) + right;
|
||||
utils.editor.set(edited);
|
||||
utils.cursor.set(pos + finalCursorPos);
|
||||
utils._callHook('enter:after');
|
||||
}
|
||||
},
|
||||
deleteKey: function (e) {
|
||||
|
||||
if(!utils.fenceRange()){ return; }
|
||||
|
||||
if(e.keyCode == 8){
|
||||
utils.preventDefaultEvent(e);
|
||||
|
||||
utils._callHook('delete:before');
|
||||
|
||||
var pos = utils.cursor.get(),
|
||||
val = utils.editor.get(),
|
||||
left = val.substring(0, pos),
|
||||
right = val.substring(pos),
|
||||
leftChar = left.charAt(left.length - 1),
|
||||
rightChar = right.charAt(0),
|
||||
i;
|
||||
|
||||
if( utils.cursor.selection() === false ){
|
||||
for(i=0; i<charSettings.keyMap.length; i++) {
|
||||
if (charSettings.keyMap[i].open == leftChar && charSettings.keyMap[i].close == rightChar) {
|
||||
var edited = val.substring(0,pos-1) + val.substring(pos+1);
|
||||
utils.editor.set(edited);
|
||||
utils.cursor.set(pos - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
var edited = val.substring(0,pos-1) + val.substring(pos);
|
||||
utils.editor.set(edited);
|
||||
utils.cursor.set(pos - 1);
|
||||
} else {
|
||||
var sel = utils.cursor.selection(),
|
||||
edited = val.substring(0,sel.start) + val.substring(sel.end);
|
||||
utils.editor.set(edited);
|
||||
utils.cursor.set(pos);
|
||||
}
|
||||
|
||||
utils._callHook('delete:after');
|
||||
|
||||
}
|
||||
}
|
||||
},
|
||||
charFuncs = {
|
||||
openedChar: function (_char, e) {
|
||||
utils.preventDefaultEvent(e);
|
||||
utils._callHook('openChar:before');
|
||||
var pos = utils.cursor.get(),
|
||||
val = utils.editor.get(),
|
||||
left = val.substring(0, pos),
|
||||
right = val.substring(pos),
|
||||
edited = left + _char.open + _char.close + right;
|
||||
|
||||
defaults.textarea.value = edited;
|
||||
utils.cursor.set(pos + 1);
|
||||
utils._callHook('openChar:after');
|
||||
},
|
||||
closedChar: function (_char, e) {
|
||||
var pos = utils.cursor.get(),
|
||||
val = utils.editor.get(),
|
||||
toOverwrite = val.substring(pos, pos + 1);
|
||||
if (toOverwrite == _char.close) {
|
||||
utils.preventDefaultEvent(e);
|
||||
utils._callHook('closeChar:before');
|
||||
utils.cursor.set(utils.cursor.get() + 1);
|
||||
utils._callHook('closeChar:after');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
action = {
|
||||
filter: function (e) {
|
||||
|
||||
if(!utils.fenceRange()){ return; }
|
||||
|
||||
var theCode = e.which || e.keyCode;
|
||||
|
||||
if(theCode == 39 || theCode == 40 && e.which===0){ return; }
|
||||
|
||||
var _char = String.fromCharCode(theCode),
|
||||
i;
|
||||
|
||||
for(i=0; i<charSettings.keyMap.length; i++) {
|
||||
|
||||
if (charSettings.keyMap[i].close == _char) {
|
||||
var didClose = defaults.overwrite && charFuncs.closedChar(charSettings.keyMap[i], e);
|
||||
|
||||
if (!didClose && charSettings.keyMap[i].open == _char && defaults.autoOpen) {
|
||||
charFuncs.openedChar(charSettings.keyMap[i], e);
|
||||
}
|
||||
} else if (charSettings.keyMap[i].open == _char && defaults.autoOpen) {
|
||||
charFuncs.openedChar(charSettings.keyMap[i], e);
|
||||
}
|
||||
}
|
||||
},
|
||||
listen: function () {
|
||||
|
||||
if(defaults.replaceTab){ utils.addEvent(defaults.textarea, 'keydown', intercept.tabKey); }
|
||||
if(defaults.autoIndent){ utils.addEvent(defaults.textarea, 'keydown', intercept.enterKey); }
|
||||
if(defaults.autoStrip){ utils.addEvent(defaults.textarea, 'keydown', intercept.deleteKey); }
|
||||
|
||||
utils.addEvent(defaults.textarea, 'keypress', action.filter);
|
||||
|
||||
utils.addEvent(defaults.textarea, 'keydown', function(){ utils._callHook('keydown'); });
|
||||
utils.addEvent(defaults.textarea, 'keyup', function(){ utils._callHook('keyup'); });
|
||||
}
|
||||
},
|
||||
init = function (opts) {
|
||||
|
||||
if(opts.textarea){
|
||||
utils._callHook('init:before', false);
|
||||
utils.deepExtend(defaults, opts);
|
||||
utils.defineNewLine();
|
||||
|
||||
if (defaults.softTabs) {
|
||||
tab = " ".repeat(defaults.tabSize);
|
||||
} else {
|
||||
tab = "\t";
|
||||
|
||||
utils.defineTabSize(defaults.tabSize);
|
||||
}
|
||||
|
||||
action.listen();
|
||||
utils._callHook('init:after', false);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
this.destroy = function(){
|
||||
utils.removeEvent(defaults.textarea, 'keydown', intercept.tabKey);
|
||||
utils.removeEvent(defaults.textarea, 'keydown', intercept.enterKey);
|
||||
utils.removeEvent(defaults.textarea, 'keydown', intercept.deleteKey);
|
||||
utils.removeEvent(defaults.textarea, 'keypress', action.filter);
|
||||
};
|
||||
|
||||
init(userOpts);
|
||||
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = Behave;
|
||||
}
|
||||
|
||||
if (typeof ender === 'undefined') {
|
||||
this.Behave = Behave;
|
||||
this.BehaveHooks = BehaveHooks;
|
||||
}
|
||||
|
||||
if (typeof define === "function" && define.amd) {
|
||||
define("behave", [], function () {
|
||||
return Behave;
|
||||
});
|
||||
}
|
||||
|
||||
}).call(this);
|
@@ -22,7 +22,7 @@
|
||||
<body>
|
||||
<div id="file_viewer" class="file_viewer">
|
||||
<div id="file_viewer_headerbar" class="highlight_1 file_viewer_headerbar">
|
||||
<button id="btn_toggle_toolbar" class="button_toggle_toolbar"><i class="icon small">menu</i></button>
|
||||
<button id="btn_toggle_toolbar" class="button_toggle_toolbar"><i class="icon">menu</i></button>
|
||||
<a href="/" id="button_home" class="button button_home">
|
||||
{{template `pixeldrain.svg` .}}
|
||||
</a>
|
||||
|
@@ -10,7 +10,14 @@
|
||||
max-width: 800px;
|
||||
margin: 0 auto 50px auto;
|
||||
}
|
||||
|
||||
.big_button{
|
||||
width: 40%;
|
||||
min-width: 250px;
|
||||
max-width: 400px;
|
||||
margin: 10px !important;
|
||||
border-radius: 5px;
|
||||
font-size: 1.8em;
|
||||
}
|
||||
.instruction_highlight {
|
||||
border-top: 1px solid var(--layer_2_color_border);
|
||||
border-bottom: 1px solid var(--layer_2_color_border);
|
||||
@@ -108,10 +115,10 @@
|
||||
</div></div>
|
||||
<input id="file_input_field" type="file" name="file" multiple="multiple"/>
|
||||
<button id="upload_file_button" class="big_button button_highlight">
|
||||
<i class="icon">cloud_upload</i>
|
||||
<i class="icon small">cloud_upload</i>
|
||||
<u>U</u>pload Files</button>
|
||||
<button id="upload_text_button" class="big_button button_highlight">
|
||||
<i class="icon">text_fields</i>
|
||||
<i class="icon small">text_fields</i>
|
||||
Upload <u>T</u>ext</button>
|
||||
<br/>
|
||||
<p>
|
||||
@@ -159,10 +166,10 @@
|
||||
</button>
|
||||
</div>
|
||||
<br/>
|
||||
<button id="btn_create_list"><i class="icon small">list</i> Create list with uploaded files</button>
|
||||
<button id="btn_copy_links"><i class="icon small">content_copy</i> Copy all links to clipboard</button>
|
||||
<button id="btn_copy_markdown"><i class="icon small">content_copy</i> Copy markdown to clipboard</button>
|
||||
<button id="btn_copy_bbcode"><i class="icon small">content_copy</i> Copy BBCode to clipboard</button>
|
||||
<button id="btn_create_list"><i class="icon">list</i> Create list with uploaded files</button>
|
||||
<button id="btn_copy_links"><i class="icon">content_copy</i> Copy all links to clipboard</button>
|
||||
<button id="btn_copy_markdown"><i class="icon">content_copy</i> Copy markdown to clipboard</button>
|
||||
<button id="btn_copy_bbcode"><i class="icon">content_copy</i> Copy BBCode to clipboard</button>
|
||||
<br/>
|
||||
<div id="created_lists"></div>
|
||||
</div>
|
||||
|
@@ -1,74 +0,0 @@
|
||||
{{define "paste"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" "Text Upload"}}
|
||||
{{template "user_style" .}}
|
||||
|
||||
<style>
|
||||
#toolbar {
|
||||
position: absolute;
|
||||
width: 8em;
|
||||
height: 100%;
|
||||
background-color: var(--layer_2_color);
|
||||
text-align: center;
|
||||
}
|
||||
.textarea_container {
|
||||
position: absolute;
|
||||
left: 8em;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
display: inline-block;
|
||||
line-height: 0;
|
||||
}
|
||||
.textarea{
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: var(--layer_1_color);
|
||||
color: var(--text_color);
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.toolbar_button{
|
||||
text-align: left;
|
||||
}
|
||||
.toolbar_button > img,
|
||||
.toolbar_button > svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="toolbar">
|
||||
<button class="toolbar_button button_full_width button_highlight" onclick="uploadText();">
|
||||
<i class="icon">save</i>
|
||||
<span>Upload</span>
|
||||
</button>
|
||||
<a href="/" class="button toolbar_button button_full_width">
|
||||
{{template `pixeldrain.svg` .}}
|
||||
<span>Home</span>
|
||||
</a>
|
||||
<br/><br/>
|
||||
Tip: Save your file with extension '.md' to use markdown formatting<br/>
|
||||
</div>
|
||||
<div class="textarea_container">
|
||||
<textarea id="textarea" class="textarea" placeholder="Your text here..." autofocus="autofocus"></textarea>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let apiEndpoint = '{{.APIEndpoint}}';
|
||||
{{template "UploadManager.js"}}
|
||||
{{template "util.js"}}
|
||||
{{template "textupload.js"}}
|
||||
</script>
|
||||
|
||||
{{template "analytics"}}
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
152
res/template/text_editor.html
Normal file
152
res/template/text_editor.html
Normal file
@@ -0,0 +1,152 @@
|
||||
{{define "text_editor"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
{{template "meta_tags" "Text Upload"}}
|
||||
{{template "user_style" .}}
|
||||
|
||||
<style>
|
||||
.text_editor {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
.headerbar {
|
||||
flex: 0 0 auto;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.headerbar > * {
|
||||
flex: 0 0 auto;
|
||||
margin-left: 6px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
.headerbar > .headerbar_spacer { flex: 1 1 auto; }
|
||||
.textarea_container {
|
||||
flex: 1 1 auto;
|
||||
margin: 0;
|
||||
z-index: 9;
|
||||
}
|
||||
.textarea {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background: var(--layer_1_color);
|
||||
color: var(--text_color);
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
box-shadow: none;
|
||||
}
|
||||
.textarea:focus { box-shadow: none; }
|
||||
|
||||
{{template `modal.css`}}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="text_editor" class="text_editor">
|
||||
<div id="headerbar" class="highlight_2 headerbar">
|
||||
<a href="/" class="button">
|
||||
<i class="icon">arrow_back</i>
|
||||
</a>
|
||||
<div id="headerbar_spacer" class="headerbar_spacer"></div>
|
||||
<button class="button toolbar_button" onclick="return helpModal();">
|
||||
<i class="icon">info</i> Information
|
||||
</button>
|
||||
<button class="button toolbar_button button_highlight" onclick="uploadText();">
|
||||
<i class="icon">save</i> Save
|
||||
</button>
|
||||
</div>
|
||||
<div class="textarea_container">
|
||||
<textarea id="textarea" class="textarea" placeholder="Your text here..." autofocus="autofocus"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<template id="tpl_text_editor_help">
|
||||
<p>
|
||||
You can type anything you want in here. When you're done press
|
||||
CTRL + S or click the Save button in the top right corner to
|
||||
upload your text file to pixeldrain.
|
||||
</p>
|
||||
<p>
|
||||
To show syntax highlighting on pixeldrain's file viewer you
|
||||
should save your file with a file extension like .js, .go,
|
||||
.java, etc. If you save your file with the extension .md or
|
||||
.markdown the result will be rendered as HTML on the file
|
||||
viewer.
|
||||
</p>
|
||||
<p>
|
||||
The text editor has been enhanced by Jacob Kelly's
|
||||
<a href="https://jakiestfu.github.io/Behave.js/"target="_blank">Behave.js</a>.
|
||||
|
||||
Many thanks to him for developing this plugin and putting it
|
||||
under the MIT license.
|
||||
</p>
|
||||
</template>
|
||||
|
||||
<script src="/res/script/behave.js"></script>
|
||||
<script>
|
||||
let apiEndpoint = '{{.APIEndpoint}}';
|
||||
{{template "UploadManager.js"}}
|
||||
{{template "util.js"}}
|
||||
{{template "Modal.js"}}
|
||||
|
||||
let editor = new Behave({
|
||||
textarea: document.getElementById("textarea"),
|
||||
replaceTab: true,
|
||||
softTabs: false,
|
||||
tabSize: 8
|
||||
});
|
||||
|
||||
function uploadText() {
|
||||
var text = document.getElementById("textarea").value;
|
||||
var blob = new Blob([text], {type: "text/plain"});
|
||||
var filename = prompt(
|
||||
"What do you want to call this piece of textual art?\n\n" +
|
||||
"Please add your own file extension, if you want.",
|
||||
"Text file.txt"
|
||||
);
|
||||
|
||||
if(filename === null){
|
||||
return; // User pressed cancel
|
||||
}
|
||||
|
||||
new UploadManager(apiEndpoint+"/file", null).addFile(
|
||||
blob,
|
||||
filename,
|
||||
null,
|
||||
function (id){
|
||||
addUploadHistory(id);
|
||||
setTimeout(window.location.href = "/u/" + id, 100);
|
||||
},
|
||||
function (response, error) {
|
||||
alert("File upload failed! The server told us this: " + response);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// Upload the file when ctrl + s is pressed
|
||||
document.addEventListener("keydown", function(event) {
|
||||
if ((event.ctrlKey || event.metaKey) && event.keyCode === 83) {
|
||||
event.preventDefault();
|
||||
uploadText();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
function helpModal() {
|
||||
let m = new Modal(
|
||||
document.body, null, "Text editor", "600px", "auto"
|
||||
)
|
||||
m.cloneTemplate("tpl_text_editor_help")
|
||||
m.open()
|
||||
return false
|
||||
}
|
||||
</script>
|
||||
|
||||
{{template "analytics"}}
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
Reference in New Issue
Block a user