regexper-static/src/js/regexper.js

162 lines
4.3 KiB
JavaScript
Raw Normal View History

import parser from './parser/javascript.js';
import Snap from 'snapsvg';
import Q from 'q';
export default class Regexper {
constructor(root) {
this.root = root;
this.form = root.querySelector('#regexp-form');
this.field = root.querySelector('#regexp-input');
this.error = root.querySelector('#error');
this.permalink = root.querySelector('a[data-glyph="link-intact"]');
this.download = root.querySelector('a[data-glyph="data-transfer-download"]');
2014-12-15 19:20:04 +00:00
this.percentage = root.querySelector('#progress div');
this.svg = root.querySelector('#regexp-render svg');
this.padding = 10;
this.snap = Snap(this.svg);
}
keypressListener(event) {
2014-12-15 23:06:16 +00:00
var evt;
if (event.shiftKey && event.keyCode === 13) {
2014-12-15 23:06:16 +00:00
event.returnValue = false;
if (event.preventDefault) {
event.preventDefault();
}
evt = document.createEvent('Event');
evt.initEvent('submit', true, true);
this.form.dispatchEvent(evt);
}
}
documentKeypressListener(event) {
if (event.keyCode === 27) {
parser.cancel();
}
}
submitListener(event) {
2014-12-16 21:08:36 +00:00
event.returnValue = false;
if (event.preventDefault) {
event.preventDefault();
}
2014-12-15 23:06:16 +00:00
try {
2014-12-16 21:08:36 +00:00
this._setHash(this.field.value);
2014-12-15 23:06:16 +00:00
}
catch(e) {
// Most likely failed to set the URL has (probably because the expression
// is too long). Turn off the permalink and just show the expression
2014-12-16 21:08:36 +00:00
this.permalinkEnabled = false;
2014-12-15 23:06:16 +00:00
this.showExpression(this.field.value);
}
}
hashchangeListener() {
2014-12-16 21:08:36 +00:00
this.permalinkEnabled = true;
this.showExpression(this._getHash());
}
2014-12-15 19:20:04 +00:00
updatePercentage(event) {
this.percentage.style.width = event.detail.percentage * 100 + '%';
}
bindListeners() {
this.field.addEventListener('keypress', this.keypressListener.bind(this));
this.form.addEventListener('submit', this.submitListener.bind(this));
2014-12-15 19:20:04 +00:00
this.root.addEventListener('updateStatus', this.updatePercentage.bind(this));
this.root.addEventListener('keyup', this.documentKeypressListener.bind(this));
window.addEventListener('hashchange', this.hashchangeListener.bind(this));
}
2014-12-16 21:08:36 +00:00
_setHash(hash) {
location.hash = encodeURIComponent(hash);
}
_getHash() {
return decodeURIComponent(location.hash.slice(1));
}
set state(state) {
2014-12-15 23:06:16 +00:00
this.root.className = state;
}
2014-12-16 21:08:36 +00:00
get state() {
return this.root.className;
}
2014-12-16 21:08:36 +00:00
showExpression(expression) {
this.field.value = expression;
this.state = '';
if (expression !== '') {
this.state = 'is-loading';
this.renderRegexp(expression)
.then(() => {
this.state = 'has-results';
this.updateLinks();
}, (message) => {
if (message === 'Render cancelled') {
this.state = '';
} else {
throw message;
}
2014-12-16 21:08:36 +00:00
})
.done();
}
}
buildBlobURL(content) {
2014-12-17 04:13:55 +00:00
var blob = new Blob([content], { type: 'image/svg+xml' });
2014-12-16 21:08:36 +00:00
window.blob = blob; // Blob object has to stick around for IE
return URL.createObjectURL(blob);
}
updateLinks() {
2014-12-15 23:06:16 +00:00
try {
2014-12-16 21:08:36 +00:00
this.download.parentNode.style.display = null;
this.download.href = this.buildBlobURL(this.svg.parentNode.innerHTML);
2014-12-15 23:06:16 +00:00
}
catch(e) {
// Blobs or URLs created from them don't work here.
// Giving up on the download link
this.download.parentNode.style.display = 'none';
}
2014-12-16 21:08:36 +00:00
if (this.permalinkEnabled) {
2014-12-15 23:06:16 +00:00
this.permalink.parentNode.style.display = null;
2014-12-16 21:08:36 +00:00
this.permalink.href = location.toString();
} else {
this.permalink.parentNode.style.display = 'none';
2014-12-15 23:06:16 +00:00
}
}
renderRegexp(expression) {
2014-12-17 00:00:27 +00:00
this.snap.selectAll('g').remove();
2014-12-16 21:08:36 +00:00
return Q.fcall(parser.parse.bind(parser), expression.replace(/\n/g, '\\n'))
.then(null, message => {
this.state = 'has-error';
this.error.innerHTML = '';
this.error.appendChild(document.createTextNode(message));
throw message;
})
2014-12-17 00:00:27 +00:00
.invoke('render', this.snap.group())
2014-12-16 03:00:24 +00:00
.then(result => {
2014-12-17 00:00:27 +00:00
var box = result.getBBox();
2014-12-17 00:00:27 +00:00
result.transform(Snap.matrix()
2014-12-16 03:00:24 +00:00
.translate(this.padding - box.x, this.padding - box.y));
2014-12-17 00:00:27 +00:00
this.snap.attr({
2014-12-16 03:00:24 +00:00
width: box.width + this.padding * 2,
height: box.height + this.padding * 2
});
});
}
}