-
Notifications
You must be signed in to change notification settings - Fork 3
/
apc-handlers.js
144 lines (124 loc) · 4.35 KB
/
apc-handlers.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
//jshint esversion: 6, -W083
const concat = require('concat-stream');
const series = require('run-series');
const BufferList = require('bl');
const defaultParent = 'body';
function TaskQueue() {
let tasks = [];
let timer;
function runTasks() {
console.log(`Running ${tasks.length} tasks.`);
let pending = tasks.splice(0);
series(pending, (err, results) => {
console.log('Results of running tasks:', err, results);
});
}
return function addTask(task) {
tasks.push((cb)=>{
task( (err)=>{
// wrapping into allways-succeeding
// async function
console.error(err);
cb(null);
});
});
if (typeof timer !== 'undefined') clearTimeout(timer);
timer = setTimeout(runTasks, 0);
};
}
let addTask = TaskQueue();
// See http://stackoverflow.com/questions/1197575/can-scripts-be-inserted-with-innerhtml
function cloneScriptElement(node) {
var script = document.createElement("script");
script.text = node.innerHTML;
for(let i=0; i<node.attributes.length; i++) {
script.setAttribute(
node.attributes[i].name,
node.attributes[i].value
);
}
return script;
}
function convertScriptTags(node) {
if ( node.tagName === 'SCRIPT' ) {
node.parentNode.replaceChild( cloneScriptElement(node), node);
} else {
let children = node.childNodes;
for (let i=0; i<children.length; ++i ) {
convertScriptTags(children[i]);
}
}
return node;
}
function appendChild(stream, header) {
let selector = header.args[1] || defaultParent;
console.log(`About to appendChild to ${selector}`);
stream.on('end', ()=>console.log('appendChild stream ends') );
let data = BufferList();
stream.pipe(data);
let ended = false;
stream.on('end', ()=> ended = true );
addTask( (cb) => {
console.log('appendChild task');
if (ended) return doit(cb);
stream.on('end', ()=> doit(cb) );
function doit(cb) {
console.log('appendChild doit');
let el = document.querySelector(selector);
if (!el) return cb(new Error(`Selector does not match any element: ${selector}`));
console.log(`appendChild to ${selector}`, el);
var frag = document.createDocumentFragment();
var div = document.createElement('div');
div.innerHTML = data.toString();
convertScriptTags(div);
while (div.firstChild) frag.appendChild(div.firstChild);
el.appendChild(frag);
console.log('appended');
cb(null);
}
});
}
function removeChild(stream, header) {
let [_, parentSelector, childSelector] = header.args;
if (!childSelector) {
childSelector = parentSelector;
parentSelector = defaultParent;
}
console.log(`About to remove ${childSelector} from ${parentSelector}`);
addTask( (cb) => {
let parent = document.querySelector(parentSelector);
if (!parent) return cb(new Error(`Parent selector does not match any element: ${parentSelector}`));
console.log(`remove ${childSelector} fomr`, parent);
let el = parent.querySelector(childSelector);
if (!el) return cb(new Error(`Child selector does not match any element: ${childSelector}`));
parent.removeChild(el);
cb(null);
});
}
function setAttribute(stream, header) {
let [_, selector, name] = header.args;
console.log('about to setAttribute', selector, name);
stream.on('end', ()=>console.log('attr stream ends') );
let data = BufferList();
stream.pipe(data);
let ended = false;
stream.on('end', ()=> ended = true );
addTask( (cb) => {
console.log('setAttribute task');
if (ended) return doit(cb);
stream.on('end', ()=> doit(cb) );
function doit(cb) {
console.log('setAtttr doit');
let el = document.querySelector(selector);
//if (!el) throw new Error(`Selector does not match any element: ${selector}`);
console.log(`set ${name} of ${selector}`, el, 'to', data);
el.setAttribute(name, data.toString() );
//cb(null);
}
});
}
module.exports = {
appendChild,
removeChild,
setAttribute
};