2018-11-08 06:11:42 +01:00
|
|
|
/**
|
|
|
|
* H.js
|
|
|
|
*
|
|
|
|
* Lightweight, extremely bare-bones library for manipulating the DOM and
|
|
|
|
* saving some typing.
|
|
|
|
*/
|
|
|
|
|
|
|
|
var Element = function(domElement) {
|
|
|
|
this.el = domElement;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates a toggle button that adds / removes the given class name from the
|
|
|
|
* given element.
|
|
|
|
*
|
|
|
|
* @param {Element} $el - The element to modify.
|
|
|
|
* @param {string} onClass - The class to add to the given element.
|
|
|
|
* @param {function} onFunc - Additional actions when toggling on.
|
|
|
|
* @param {function} offFunc - Additional actions when toggling off.
|
|
|
|
*/
|
|
|
|
Element.prototype.createToggle = function($el, onClass, onFunc, offFunc) {
|
|
|
|
this.on('click', function(e) {
|
|
|
|
if ($el.el.className === '') {
|
|
|
|
$el.el.className = onClass;
|
|
|
|
onFunc(new Element(this), e);
|
|
|
|
} else {
|
|
|
|
$el.el.className = '';
|
|
|
|
offFunc(new Element(this), e);
|
|
|
|
}
|
|
|
|
e.preventDefault();
|
|
|
|
}, false);
|
|
|
|
};
|
|
|
|
Element.prototype.on = function(event, func) {
|
|
|
|
events = event.split(' ');
|
|
|
|
var el = this.el;
|
|
|
|
if (el == null) {
|
|
|
|
console.error("Error: element for event is null");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var addEvent = function(e) {
|
|
|
|
if (el.addEventListener) {
|
|
|
|
el.addEventListener(e, func, false);
|
|
|
|
} else if (el.attachEvent) {
|
|
|
|
el.attachEvent(e, func);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if (events.length === 1) {
|
|
|
|
addEvent(event);
|
|
|
|
} else {
|
|
|
|
for(var i=0; i<events.length; i++) {
|
|
|
|
addEvent(events[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Element.prototype.setClass = function(className) {
|
|
|
|
if (this.el == null) {
|
|
|
|
console.error("Error: element to set class on is null");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.el.className = className;
|
|
|
|
};
|
|
|
|
Element.prototype.removeClass = function(className) {
|
|
|
|
if (this.el == null) {
|
|
|
|
console.error("Error: element to remove class on is null");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
var regex = new RegExp(' ?' + className, 'g');
|
|
|
|
this.el.className = this.el.className.replace(regex, '');
|
|
|
|
};
|
|
|
|
Element.prototype.text = function(text, className) {
|
|
|
|
if (this.el == null) {
|
|
|
|
console.error("Error: element for setting text is null");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (this.el.textContent !== text) {
|
|
|
|
this.el.textContent = text;
|
|
|
|
if (typeof className !== 'undefined') {
|
|
|
|
this.el.className = this.el.className + ' ' + className;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
Element.prototype.insertAfter = function(newNode) {
|
|
|
|
if (this.el == null) {
|
|
|
|
console.error("Error: element for insertAfter is null");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.el.parentNode.insertBefore(newNode, this.el.nextSibling);
|
|
|
|
};
|
|
|
|
Element.prototype.remove = function() {
|
|
|
|
if (this.el == null) {
|
|
|
|
console.error("Didn't remove element");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.el.parentNode.removeChild(this.el);
|
|
|
|
};
|
|
|
|
Element.prototype.hide = function() {
|
|
|
|
if (this.el == null) {
|
|
|
|
console.error("Didn't hide element");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.el.className += ' effect fade-out';
|
|
|
|
};
|
|
|
|
Element.prototype.show = function() {
|
|
|
|
if (this.el == null) {
|
|
|
|
console.error("Didn't show element");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.el.className += ' effect';
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
var H = {
|
2020-03-10 23:18:45 +01:00
|
|
|
getQEl: function(elementQuery) {
|
|
|
|
return new Element(document.querySelector(elementQuery));
|
|
|
|
},
|
2018-11-08 06:11:42 +01:00
|
|
|
getEl: function(elementId) {
|
|
|
|
return new Element(document.getElementById(elementId));
|
|
|
|
},
|
|
|
|
save: function($el, key) {
|
|
|
|
localStorage.setItem(key, $el.el.value);
|
|
|
|
},
|
2020-03-11 18:28:02 +01:00
|
|
|
saveClassic: function($titleEl, $el, key) {
|
|
|
|
var out = "";
|
|
|
|
var title = $titleEl.el.value;
|
|
|
|
if (title !== "") {
|
|
|
|
out = "# "+title+"\n\n";
|
|
|
|
}
|
|
|
|
out += $el.el.value;
|
|
|
|
localStorage.setItem(key, out);
|
|
|
|
},
|
2020-06-11 17:45:12 +02:00
|
|
|
load: function($el, key, onlyLoadPopulated, postUpdated) {
|
2018-11-08 06:11:42 +01:00
|
|
|
var val = localStorage.getItem(key);
|
|
|
|
if (onlyLoadPopulated && val == null) {
|
|
|
|
// Do nothing
|
2020-06-11 17:45:12 +02:00
|
|
|
return true;
|
2018-11-08 06:11:42 +01:00
|
|
|
}
|
|
|
|
$el.el.value = val;
|
2020-06-11 17:45:12 +02:00
|
|
|
if (postUpdated != null) {
|
|
|
|
var lastLocalPublishStr = localStorage.getItem(key+'-published');
|
|
|
|
if (lastLocalPublishStr != null && lastLocalPublishStr != '') {
|
|
|
|
try {
|
|
|
|
var lastLocalPublish = new Date(lastLocalPublishStr);
|
|
|
|
if (postUpdated > lastLocalPublish) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} catch (e) {
|
|
|
|
console.error("unable to parse draft updated time");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
2018-11-08 06:11:42 +01:00
|
|
|
},
|
2020-03-11 18:28:02 +01:00
|
|
|
loadClassic: function($titleEl, $el, key, onlyLoadPopulated) {
|
|
|
|
var val = localStorage.getItem(key);
|
|
|
|
if (onlyLoadPopulated && val == null) {
|
|
|
|
// Do nothing
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (val.indexOf("# ") === 0) {
|
|
|
|
var eol = val.indexOf("\n");
|
|
|
|
title = val.substring("# ".length, eol);
|
|
|
|
val = val.substring(eol+"\n\n".length);
|
|
|
|
$titleEl.el.value = title;
|
|
|
|
}
|
|
|
|
$el.el.value = val;
|
|
|
|
},
|
2018-11-08 06:11:42 +01:00
|
|
|
set: function(key, value) {
|
|
|
|
localStorage.setItem(key, value);
|
|
|
|
},
|
|
|
|
get: function(key, defaultValue) {
|
|
|
|
var val = localStorage.getItem(key);
|
|
|
|
if (val == null) {
|
|
|
|
val = defaultValue;
|
|
|
|
}
|
|
|
|
return val;
|
|
|
|
},
|
|
|
|
remove: function(key) {
|
|
|
|
localStorage.removeItem(key);
|
|
|
|
},
|
|
|
|
exists: function(key) {
|
|
|
|
return localStorage.getItem(key) !== null;
|
|
|
|
},
|
|
|
|
createPost: function(id, editToken, content, created) {
|
|
|
|
var summaryLen = 200;
|
|
|
|
var titleLen = 80;
|
|
|
|
var getPostMeta = function(content) {
|
|
|
|
var eol = content.indexOf("\n");
|
|
|
|
if (content.indexOf("# ") === 0) {
|
|
|
|
// Title is in the format:
|
|
|
|
//
|
|
|
|
// # Some title
|
|
|
|
var summary = content.substring(eol).trim();
|
|
|
|
if (summary.length > summaryLen) {
|
|
|
|
summary = summary.substring(0, summaryLen) + "...";
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
title: content.substring("# ".length, eol),
|
|
|
|
summary: summary,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
var blankLine = content.indexOf("\n\n");
|
|
|
|
if (blankLine !== -1 && blankLine <= eol && blankLine <= titleLen) {
|
|
|
|
// Title is in the format:
|
|
|
|
//
|
|
|
|
// Some title
|
|
|
|
//
|
|
|
|
// The body starts after that blank line above it.
|
|
|
|
var summary = content.substring(blankLine).trim();
|
|
|
|
if (summary.length > summaryLen) {
|
|
|
|
summary = summary.substring(0, summaryLen) + "...";
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
title: content.substring(0, blankLine),
|
|
|
|
summary: summary,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: move this to the beginning
|
|
|
|
var title = content.trim();
|
|
|
|
var summary = "";
|
|
|
|
if (title.length > titleLen) {
|
|
|
|
// Content can't fit in the title, so figure out the summary
|
|
|
|
summary = title;
|
|
|
|
title = "";
|
|
|
|
if (summary.length > summaryLen) {
|
|
|
|
summary = summary.substring(0, summaryLen) + "...";
|
|
|
|
}
|
|
|
|
} else if (eol > 0) {
|
|
|
|
summary = title.substring(eol+1);
|
|
|
|
title = title.substring(0, eol);
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
title: title,
|
|
|
|
summary: summary
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
var post = getPostMeta(content);
|
|
|
|
post.id = id;
|
|
|
|
post.token = editToken;
|
|
|
|
post.created = created ? new Date(created) : new Date();
|
|
|
|
post.client = "Pad";
|
|
|
|
|
|
|
|
return post;
|
|
|
|
},
|
|
|
|
getTitleStrict: function(content) {
|
|
|
|
var eol = content.indexOf("\n");
|
|
|
|
var title = "";
|
|
|
|
var newContent = content;
|
|
|
|
if (content.indexOf("# ") === 0) {
|
|
|
|
// Title is in the format:
|
|
|
|
// # Some title
|
|
|
|
if (eol !== -1) {
|
|
|
|
// First line should start with # and end with \n
|
|
|
|
newContent = content.substring(eol).leftTrim();
|
|
|
|
title = content.substring("# ".length, eol);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return {
|
|
|
|
title: title,
|
|
|
|
content: newContent
|
|
|
|
};
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
var He = {
|
|
|
|
create: function(name) {
|
|
|
|
return document.createElement(name);
|
|
|
|
},
|
|
|
|
get: function(id) {
|
|
|
|
return document.getElementById(id);
|
|
|
|
},
|
|
|
|
$: function(selector) {
|
|
|
|
var els = document.querySelectorAll(selector);
|
|
|
|
return els;
|
|
|
|
},
|
|
|
|
postJSON: function(url, params, callback) {
|
|
|
|
var http = new XMLHttpRequest();
|
|
|
|
|
|
|
|
http.open("POST", url, true);
|
|
|
|
|
|
|
|
// Send the proper header information along with the request
|
|
|
|
http.setRequestHeader("Content-type", "application/json");
|
|
|
|
|
|
|
|
http.onreadystatechange = function() {
|
|
|
|
if (http.readyState == 4) {
|
|
|
|
callback(http.status, JSON.parse(http.responseText));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
http.send(JSON.stringify(params));
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
String.prototype.leftTrim = function() {
|
|
|
|
return this.replace(/^\s+/,"");
|
|
|
|
};
|