Skip to content

Instantly share code, notes, and snippets.

@Lucassifoni
Created March 17, 2021 14:53
Show Gist options
  • Select an option

  • Save Lucassifoni/e77122b5ce61b3624ab79ff0114351da to your computer and use it in GitHub Desktop.

Select an option

Save Lucassifoni/e77122b5ce61b3624ab79ff0114351da to your computer and use it in GitHub Desktop.
HTML Juggler
<h2><%= @page.post_title |> Phoenix.HTML.raw %></h2>
<div class="workspace">
<div class="content_old" style="flex: 0 0 50%; background: #ccc; padding: 1em;">
<%= @page.post_content |> Phoenix.HTML.raw %>
</div>
<div class="content_highlighter" style="flex: 0 0 50%; background: #f8f8f8; padding: 1em;">
<%= @page.post_content |> Phoenix.HTML.raw %>
</div>
</div>
<div class="keyboard_shortcuts">
<ul>
<li><strong>CLIC</strong>Sélectionner</li>
<li><strong>G</strong>Grouper</li>
<li><strong>P</strong>Paragraphe</li>
<li><strong>1</strong>Titre 1</li>
<li><strong>2</strong>Titre 2</li>
<li><strong>3</strong>Titre 3</li>
<li><strong>X</strong>Enlever styles inline</li>
<li><strong>D</strong>Enlever le noeud</li>
<li><strong>U</strong>Déballer d'un niveau</li>
</ul>
<button class="save_button">Enregistrer</button>
</div>
<style>
.keyboard_shortcuts {
position: fixed;
bottom: 2em;
right: 2em;
background: #efefef;
box-shadow: 0 0 10px 0 black;
border-radius: 3px;
border: 1px solid #ddd;
}
main.container {
max-width: 1680px;
}
.keyboard_shortcuts li {
list-style: none;
}
.keyboard_shortcuts strong {
margin-right: 1em;
padding: 4px;
background: beige;
}
.content_highlighter * {
border: 1px solid red;
padding: 4px;
}
.content_old * {
border: 1px solid #ddd;
padding: 4px;
}
.content_highlighter .highlight {
background: lightblue;
}
.content_highlighter .select {
background: goldenrod;
}
.content_highlighter [style] {
position: relative;
}
.content_highlighter [style]::before {
content: "s";
position: absolute;
border: 1px solid black;
border-radius: 50%;
height: 24px;
width: 24px;
background: green;
left: -1em;
line-height: 24px;
font-size: 18px;
}
.workspace {
width: 100%;
display: flex;
}
</style>
<script>
let hover_target = null;
let click_targets = [];
const CLASSES = "highlight";
const LISTENERS = {};
let doing = 0;
function lock() {
doing = 1;
}
function unlock() {
setTimeout(function() {
doing = 0;
}, 300);
}
function lockify(callback) {
return function(...args) {
if (doing) return;
lock();
console.log("Executing callback");
callback(...args);
unlock();
};
};
function emit(event, payload = null) {
(LISTENERS[event] || []).forEach(function(callback) {
try {
callback(payload);
} catch(e) {
console.log(e);
console.error("Failed to execute " +event+ " callback for payload " + payload);
}
});
}
function listen(event, callback) {
if (LISTENERS[event]) {
LISTENERS[event].push(lockify(callback));
} else {
LISTENERS[event] = [lockify(callback)];
}
}
function clear_hover_target() {
if (!hover_target) return;
hover_target.classList.remove(CLASSES);
hover_target = null;
};
function set_hover_target(t) {
hover_target = t;
hover_target.classList.add(CLASSES);
}
function toggle_click_target(t) {
const index = click_targets.indexOf(t);
if (index !== -1) {
click_targets.splice(index, 1);
t.classList.remove('select');
} else {
click_targets.push(t);
t.classList.add('select');
}
}
document.querySelector('.content_highlighter').addEventListener('mouseover', function(e) {
clear_hover_target();
set_hover_target(e.target);
});
document.querySelector('.content_highlighter').addEventListener('click', function(e){
toggle_click_target(e.target);
});
document.addEventListener('keyup', function(k) {
const e = {
80: 'p',
97: '1',
98: '2',
99: '3',
88: 'x',
68: 'd',
85: 'u',
71: 'g',
}[k.keyCode];
if (e) {
emit('keyboard_' + e);
}
});
listen('keyboard_p', function() {
if (!hover_target) return;
const t = hover_target;
const p = document.createElement('p');
p.innerHTML = t.innerText;
t.parentNode.insertBefore(p, t);
t.parentNode.removeChild(t);
});
listen('keyboard_1', function() {
if (!hover_target) return;
const t = hover_target;
const p = document.createElement('h1');
p.innerHTML = t.innerText;
t.parentNode.insertBefore(p, t);
t.parentNode.removeChild(t);
});
listen('keyboard_2', function() {
if (!hover_target) return;
const t = hover_target;
const p = document.createElement('h2');
p.innerHTML = t.innerText;
t.parentNode.insertBefore(p, t);
t.parentNode.removeChild(t);
});
listen('keyboard_3', function() {
if (!hover_target) return;
const t = hover_target;
const p = document.createElement('h3');
p.innerHTML = t.innerText;
t.parentNode.insertBefore(p, t);
t.parentNode.removeChild(t);
});
listen('keyboard_x', function() {
if (!hover_target) return;
const t = hover_target;
t.removeAttribute('style');
});
listen('keyboard_d', function() {
if (!hover_target) return;
const t = hover_target;
t.parentNode.removeChild(t);
});
listen('keyboard_u', function() {
if (!hover_target) return;
const t = hover_target;
const childs = t.childNodes;
Array.from(childs).forEach(function(child) {
t.parentNode.insertBefore(child, t);
});
t.parentNode.removeChild(t);
});
listen('keyboard_g', function() {
if (click_targets.length === 0) return;
const group = document.createElement('div');
const point = click_targets[0];
point.parentNode.insertBefore(group, point);
click_targets.forEach((c) => {
group.appendChild(c);
});
});
document.querySelector('.save_button').addEventListener('click', function() {
const body = new FormData();
const method = 'PUT';
const csrfToken = document.head.querySelector("[name~=csrf-token][content]").content;
const headers = new Headers({
'x-csrf-token': csrfToken,
});
body.append("post_content", document.querySelector('.content_highlighter').innerHTML);
fetch(window.location.href, {method, body, headers}).then(() => {
window.location.href = window.location.href + '';
});
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment