Skip to content

Support loading of divs automatically #4

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Forms are augmented automatically using their action URLs.

Other clickable elements will be augmented if the `data-url` property is set. The value is the server URL where a GET request to handle the action resides.

DIV elements can also be augmented to allow the client to drive automatic loading of content, for example if more complex JS is also present on the page that requires this functionality.

### Server

A server must return JSON from websocket requests to `/websocket` in the following format:
Expand Down Expand Up @@ -82,6 +84,7 @@ This example shows the following:
* Direct DOM change from user action.
* Indirect DOM change from user action.
* DOM change via timed event.
* DOM change from non user action.

## Developing

Expand Down
27 changes: 21 additions & 6 deletions example/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ app.get('/', (req, res, next) => {
<div class="page-header">
<h1>Todo Example</h1>
</div>
<div id="intro" data-url="/intro"></div>
<div id="count">${renderTodoCount(req.session)}</div>
<ul id="lists" class="list-group">
${renderTodos(req.session)}
Expand Down Expand Up @@ -94,16 +95,30 @@ wss.on('connection', (ws, upgradeReq) => {
const routeMessage = (ws, request, session) => {
const query = qs.parse(request.query)
//The example app only has these functions
const outputCallback = (out) => {
ws.send(JSON.stringify(out))
}

if(request.pathname === '/add'){
addRoute(query, session, (out) => {
ws.send(JSON.stringify(out))
})
addRoute(query, session, outputCallback)
}
else if(request.pathname === '/delete'){
deleteRoute(query, session, (out) => {
ws.send(JSON.stringify(out))
})
deleteRoute(query, session, outputCallback)
}
else if(request.pathname === '/intro'){
introRoute(query, session, outputCallback)
}
}

//Display intro message
const introRoute = (query, session, cb) => {
setTimeout(() => { // Add a delay to highlight the content being loaded without user interaction
cb([{
action: 'replace',
container: 'intro',
content: '<h3>Just use the form below to add a todo<h3>'
}])
}, 2000)
}

//Deleting a todo
Expand Down
30 changes: 22 additions & 8 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ TBF.prototype._setupWebsocket = function(){
var socketUrl = window.location.protocol.replace('http', 'ws') + '//' + window.location.host + '/websocket';
this._websocket = new WebSocket(socketUrl);
var self = this;
this._websocket.onclose = function(event){
this._websocket.onopen = function(){
self._augmentInterface();
};
this._websocket.onclose = function(){
setTimeout(function(){
self._websocket.readyState > 1 && self._setupWebsocket();
}, 1000);
}
};
this._websocket.onmessage = function(event){
var jsons = JSON.parse(event.data);
jsons.forEach(function(json){
Expand All @@ -31,13 +34,25 @@ TBF.prototype._augmentInterface = function(){
for(var i = 0; i < tags.length; i++){
this._augmentForm(tags.item(i));
}
if(this._websocket.readyState === 1){ // only do this if we have a working web socket
tags = document.getElementsByTagName('DIV');
for(var i = 0; i < tags.length; i++){
this._augmentDiv(tags.item(i));
}
}
};

TBF.prototype._augmentButton = function(ele){
if(!ele.dataset.url){
TBF.prototype._augmentDiv = function(ele){
if(!ele.dataset.url || ele.dataset.actioned){ // not supported or already done
return;
}
if(ele.onclick){ // already done
console.log('augmenting div: ', ele);
ele.dataset.actioned = 1;
this._elementActivated(ele); // activate immediately
};

TBF.prototype._augmentButton = function(ele){
if(!ele.dataset.url || ele.onclick){ // not supported or already done
return;
}
console.log('augmenting button: ', ele);
Expand Down Expand Up @@ -65,10 +80,10 @@ TBF.prototype._elementActivated = function(ele){
};

TBF.prototype._getActionURL = function(ele){
if(ele.tagName === 'BUTTON'){
if(['BUTTON', 'DIV'].indexOf(ele.tagName) !== -1){
return ele.dataset.url;
}
else if(ele.tagName === 'FORM'){
if(ele.tagName === 'FORM'){
var kvPairs = [];
for(var i = 0; i < ele.elements.length; i++){
var e = ele.elements[i];
Expand All @@ -81,7 +96,6 @@ TBF.prototype._getActionURL = function(ele){
};

TBF.prototype._handleResponse = function(json){
console.log('got json:', json);
var container = document.getElementById(json.container);
if(!container){
throw new Error('container not found: ' + json.container);
Expand Down