Temporary storing the element(s) returned by document.querySelector
and document.querySelectorAll
methods could improve efficiency by calling the methods once when it is known that the document
has not been changed.
Following it is a buffered source, it supports passing in a parameter of type function returning a value and reseting to call the source that it is buffering to retrieve the sourced value on demand. When it is initialised it calls the passed in source and stores the result, if the result it is undefined schedules another call to the source to be run when the element it is first time requested:
var buffered = { source: function(bufferee) {
var enabler = { supply: (purpose) => {
var vain = purpose ? () => purpose() : () => false;
var enablers = [vain];
return { shift: function() { return enablers[0](); }
, schedule: function(schedulee) {
enablers.unshift( () => {
enablers.shift();
return schedulee();
});
return this;
}
};
} };
var returnee = bufferee();
var singularity = enabler.supply(() => returnee);
if ( !returnee ) {
singularity.schedule(() => {
returnee = bufferee(); return returnee;
});
}
return { element: () => singularity.shift()
, reset: () => { returnee = bufferee(); } };
} };
Following an example to show case the supported features:
<html>
<head>
<title>Buffered source...</title>
<style type="text/css">
.display {
bottom: 0;
height: 50%;
position: absolute;
width: 100%;
}
.viewport {
bottom: 0;
overflow: hidden;
position: absolute;
}
.field { height: 50%; }
.dynamic {
background-color: #eee;
border-radius: 50%;
height: 200px;
width: 200px;
margin: auto;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
</style>
<script type="text/javascript">
var element = { of: (selector) => document.querySelector(selector) };
var buffered = { source: function(bufferee) {
var enabler = { supply: (purpose) => {
var vain = purpose ? () => purpose() : () => false;
var enablers = [vain];
return { shift: function() { return enablers[0](); }
, schedule: function(schedulee) {
enablers.unshift(() => {
enablers.shift(); return schedulee();
});
return this;
}
};
} };
var returnee = bufferee();
var singularity = enabler.supply(() => returnee);
if ( !returnee ) {
singularity.schedule(() => { returnee = bufferee();
return returnee; });
}
return { element: () => singularity.shift()
, reset: () => { returnee = bufferee(); } };
} };
var vainer = { supply: (purpose) => {
var vain = purpose ? () => purpose() : () => false;
var vainers = [vain];
return { shift: function() { return vainers[0](); }
, schedule: function(schedulee) {
vainers.unshift(() => { vainers.shift(); return schedulee(); });
return this;
}
};
} };
var viewport = { on: (bearer) => {
var write = (text, separator) => {
bearer.innerHTML = bearer.innerHTML + separator + text;
};
return { message: (content) => { write(content, "<br>"); }
, text: (content) => { write(content, " "); }
, clear: () => { bearer.innerHTML = ""; }
} } };
function load() { receiver.load(); }
function query() { receiver.click(); }
var receiver = (function() {
var dynamic = void(0);
var display = void(0);
var stack = vainer.supply(() => {
var node = dynamic.element();
setTimeout(() => {
display.message("element of class dynamic exists: "
+ (node != null)); }
, displayDelayMillis);
nextMessage();
});
var displayDelayMillis = 1000;
var nextMessage = (delayMillis) => {
setTimeout(() => { display.message("try clicking"); }
, delayMillis || 2 * displayDelayMillis); };
return { load: () => {
display = viewport.on(element.of(".viewport"));
dynamic = buffered.source(() => {
display.message("querying document for element of class dynamic...");
return element.of(".dynamic");
});
nextMessage(displayDelayMillis);
stack.schedule(() => {
dynamic.reset();
var node = dynamic.element();
setTimeout(() => {
display.message("element of class dynamic exists: "
+ (node != null));
}
, displayDelayMillis);
nextMessage();
});
stack.schedule(() => {
var div = document.createElement("div");
div.className = "dynamic";
element.of(".field").appendChild(div);
setTimeout(() => {
display.message("element of class dynamic added");
}
, displayDelayMillis/4);
nextMessage(displayDelayMillis);
});
stack.schedule(() => {
var node = dynamic.element();
setTimeout(() => {
display.message("element of class dynamic exists: "
+ (node != null));
}
, displayDelayMillis);
nextMessage();
});
}
, click: () => { stack.shift(); }
};
})();
</script>
</head>
<body onload="load()" onclick="query()" >
<div class="field"></div>
<div class="display">
<div class="viewport">
</div>
</div>
</body>
</html>