Files
meteor/packages/server-render/client-sink.js
2017-11-22 20:09:18 -05:00

71 lines
1.7 KiB
JavaScript

const doc = document;
const head = doc.getElementsByTagName("head")[0];
const body = doc.body;
const isoError = (method) => {
console.error(`sink.${method} was called on the client when
it should only be called on the server.`);
}
export class ClientSink {
appendToHead(nodeOrHtml) {
appendContent(head, nodeOrHtml);
}
appendToBody(nodeOrHtml) {
appendContent(body, nodeOrHtml);
}
appendToElementById(id, nodeOrHtml) {
appendContent(doc.getElementById(id), nodeOrHtml);
}
renderIntoElementById(id, nodeOrHtml) {
const element = doc.getElementById(id);
while (element.lastChild) {
element.removeChild(element.lastChild);
}
appendContent(element, nodeOrHtml);
}
redirect(location) {
// code can't be set on the client
window.location = location;
}
// server only methods
setStatusCode() {
isoError("setStatusCode");
}
setHeader() {
isoError("setHeader");
}
getHeaders() {
isoError("getHeaders");
}
getCookies() {
isoError("getCookies");
}
}
function appendContent(destination, nodeOrHtml) {
if (typeof nodeOrHtml === "string") {
// Make a shallow clone of the destination node to ensure the new
// children can legally be appended to it.
const container = destination.cloneNode(false);
// Parse the HTML into the container, allowing for multiple children.
container.innerHTML = nodeOrHtml;
// Transplant the children to the destination.
while (container.firstChild) {
destination.appendChild(container.firstChild);
}
} else if (Array.isArray(nodeOrHtml)) {
nodeOrHtml.forEach(elem => appendContent(destination, elem));
} else {
destination.appendChild(nodeOrHtml);
}
}