How can we determine the group which initiated SignalR extended method? - javascript

I have created a Javascript function to make SignalR even more magical:
//Initializable
function Initializable(params) {
this.initialize = function (key, def, private) {
if (def !== undefined) {
(!!private ? params : this)[key] = (params[key] !== undefined) ? params[key] : def;
}
};
}
/*SignalR Updater*/
function SignalRUpdater(params) {
Initializable.call(this, params);
var self = this;
this.initialize("RawHubs", [], true);
this.initialize("RawGroups", {}, true);
this.initialize("Connection", $.connection, true);
this.initialize("Extend", {});
this.Hubs = {};
this.addHub = function (name, extend) {
if (self.Hubs[name]) {
return false;
}
self.Hubs[name] = params.Connection[name];
self.Hubs[name].Groups = {};
params.RawHubs.push(name);
if (!params.RawGroups[name]) {
params.RawGroups[name] = [];
}
if (extend) {
if ((!self.Extend) || (!extend.append)) {
self.Extend = extend;
} else {
if (!self.Extend) {
self.Extend = {};
}
if (extend.append) {
for (var extendIndex in extend) {
if (extendIndex !== "append") {
self.Extend = extend[extendIndex];
}
}
} else {
self.Extend = extend;
}
}
$.extend(params.Connection[name].client, self.Extend);
} else if (self.Extend) {
$.extend(params.Connection[name].client, self.Extend);
}
return true;
};
this.removeHub = function (name) {
if (!self.Hubs[name]) {
return false;
}
for (var groupIndex in self.Hubs[name].Groups) {
self.Hubs[name].Groups[groupIndex].unsubscribe();
}
delete self.Hubs[name];
delete params.RawGroups[name];
params.RawHubs.splice(params.RawHubs.indexOf(name), 1);
return true;
};
this.addGroupToHub = function (hubName, groupName) {
if ((self.Hubs[hubName]) && (self.Hubs[hubName].Groups[groupName])) {
return false;
}
self.Hubs[hubName].server.subscribe(groupName);
self.Hubs[hubName].Groups[groupName] = {}; //Here we can hold group-related data
if (params.RawGroups[hubName].indexOf(groupName) < 0) {
params.RawGroups[hubName].push(groupName);
}
return true;
};
this.removeGroupFromHub = function (hubName, groupName) {
if ((!self.Hubs[hubName]) || (!self.Hubs[hubName].Groups[groupName])) {
return false;
}
self.Hubs[hubName].server.unsubscribe(groupName);
delete self.Hubs[hubName].Groups[groupName];
if (params.RawGroups[hubName].indexOf(groupName) >= 0) {
params.RawGroups[hubName].splice(params.RawGroups[hubName].indexOf(groupName), 1);
}
return true;
};
for (var hubIndex in params.RawHubs) {
self.addHub(params.RawHubs[hubIndex]);
}
params.Connection.hub.start().done(function () {
for (var hubIndex in params.RawGroups) {
for (var groupIndex in params.RawGroups[hubIndex]) {
self.addGroupToHub(hubIndex, params.RawGroups[hubIndex][groupIndex]);
}
}
});
}
I am using it like this, for example:
function statusUpdate(status) {
alert(status);
}
var signalRUpdater = new SignalRUpdater({
RawHubs: ["statusUpdates"],
Extend: {
statusUpdate: statusUpdate
}
});
So far, so good. However, I may have several groups in the same hub and at the point of statusUpdate I do not seem to know about the group. I can send it from server-side as a parameter to statusUpdate, but I wonder whether this is an overkill and whether it is possible out of the box with SignalR.

When sending a group message to clients the server does not send the name of the group the message was sent to. The server selects clients that are members of the group and just sends them the message. If you want to understand the protocol SignalR is using you can find a description I wrote some time ago here.

Related

How to expose only a function and not the variables from a class function?

Suppose I have this code:
function GraphFactory() {
this.nodeNames = [];
this.pinnedNodes = [];
this.initPinnedNodes = function(nodes) {
if (nodes) {
this.pinnedNodes = nodes;
} else {
this.pinnedNodes = [];
}
}
this.checkIfPinned = function(node) {
if (this.pinnedNodes.indexOf(node) > -1) {
return true;
} else {
return false;
}
}
this.addToPinnedNodes = function(name) {
this.pinnedNodes.push(name);
return true;
}
this.removeFromPinnedNodes = function(name) {
this.pinnedNodes.splice(this.pinnedNodes.indexOf(name), 1);
return true;
}
}
let graphFactory = new GraphFactory();
Right now i can access both the function
graphFactory.checkIfPinned(label);
but also directly the variable
graphFactory.pinnedNodes
How would I set things up so only the functions, but not the variables could get accessed?
Use variables instead of properties on the object.
let nodeNames = [];
They'll be closed over by your dynamically assigned instance methods.
Or see this question for the modern approach.
With the current construct, you can use a closure per object, practically a local variable in your constructor function:
function GraphFactory() {
var nodeNames = [];
var pinnedNodes = [];
this.initPinnedNodes = function(nodes) {
if (nodes) {
pinnedNodes = nodes;
} else {
pinnedNodes = [];
}
}
this.checkIfPinned = function(node) {
if (pinnedNodes.indexOf(node) > -1) {
return true;
} else {
return false;
}
}
this.addToPinnedNodes = function(name) {
pinnedNodes.push(name);
return true;
}
this.removeFromPinnedNodes = function(name) {
pinnedNodes.splice(this.pinnedNodes.indexOf(name), 1);
return true;
}
}
let graphFactory = new GraphFactory();
However such variables will not be accessible to methods you add later, from outside. For example that nodeNames exists in vain this way.

How to take the result of one script and feed it into another?

I'm in way over my head here and need some help to understand what I'm looking at please! (Very new to Javascript!) Here is the situation as I understand it...
I have a script that is selecting a single line from a paragraph of text, and currently produces this alert, where '1' is the selected line:
alert(getLine("sourcePara", 1));
...Instead of triggering an alert I need this selected text to feed into this separate script which is sending data to another browser window. Presently it's taking a text field from a form with the id 'STOCK1', but that can be replaced:
function sendLog() {
var msg = document.getElementById('STOCK1').value;
t.send('STK1', msg);
}
I'm totally confused as to what form this text data is taking on the way out of the first script and have no idea how to call it in as the source for the second... HELP!
All the thanks!
EDIT:
Here is the source code for the Local Connection element;
function LocalConnection(options) {
this.name = 'localconnection';
this.id = new Date().getTime();
this.useLocalStorage = false;
this.debug = false;
this._actions= [];
this.init = function(options) {
try {
localStorage.setItem(this.id, this.id);
localStorage.removeItem(this.id);
this.useLocalStorage = true;
} catch(e) {
this.useLocalStorage = false;
}
for (var o in options) {
this[o] = options[o];
}
this.clear();
}
this.listen = function() {
if (this.useLocalStorage) {
if (window.addEventListener) {
window.addEventListener('storage', this.bind(this, this._check), false);
} else {
window.attachEvent('onstorage', this.bind(this, this._check));
}
} else {
setInterval(this.bind(this, this._check), 100);
}
}
this.send = function(event) {
var args = Array.prototype.slice.call(arguments, 1);
return this._write(event, args);
}
this.addCallback = function(event, func, scope) {
if (scope == undefined) {
scope = this;
}
if (this._actions[event] == undefined) {
this._actions[event] = [];
}
this._actions[event].push({f: func, s: scope});
}
this.removeCallback = function(event) {
for (var e in this._actions) {
if (e == event) {
delete this._actions[e];
break;
}
}
}
this._check = function() {
var data = this._read();
if (data.length > 0) {
for (var e in data) {
this._receive(data[e].event, data[e].args);
}
}
}
this._receive = function(event, args) {
if (this._actions[event] != undefined) {
for (var func in this._actions[event]) {
if (this._actions[event].hasOwnProperty(func)) {
this.log('Triggering callback "'+event+'"', this._actions[event]);
var callback = this._actions[event][func];
callback.f.apply(callback.s, args);
}
}
}
};
this._write = function(event, args) {
var events = this._getEvents();
var evt = {
id: this.id,
event: event,
args: args
};
events.push(evt);
this.log('Sending event', evt);
if (this.useLocalStorage) {
localStorage.setItem(this.name, JSON.stringify(events));
} else {
document.cookie = this.name + '=' + JSON.stringify(events) + "; path=/";
}
return true;
}
this._read = function() {
var events = this._getEvents();
if (events == '') {
return false;
}
var ret = [];
for (var e in events) {
if (events[e].id != this.id) {
ret.push({
event: events[e].event,
args: events[e].args
});
events.splice(e, 1);
}
}
if (this.useLocalStorage) {
localStorage.setItem(this.name, JSON.stringify(events));
} else {
document.cookie = this.name + '=' + JSON.stringify(events) + "; path=/";
}
return ret;
}
this._getEvents = function() {
return this.useLocalStorage ? this._getLocalStorage() : this._getCookie();
}
this._getLocalStorage = function() {
var events = localStorage.getItem(this.name);
if (events == null) {
return [];
}
return JSON.parse(events);
}
this._getCookie = function() {
var ca = document.cookie.split(';');
var data;
for (var i=0; i < ca.length; i++) {
var c = ca[i];
while (c.charAt(0) == ' ') {
c = c.substring(1, c.length);
}
if (c.indexOf(this.name+'=') == 0) {
data = c.substring(this.name.length+1, c.length);
break;
}
}
data = data || '[]';
return JSON.parse(data);
}
this.clear = function() {
if (this.useLocalStorage) {
localStorage.removeItem(this.name);
} else {
document.cookie = this.name + "=; path=/";
}
}
this.bind = function(scope, fn) {
return function () {
fn.apply(scope, arguments);
};
}
this.log = function() {
if (!this.debug) {
return;
}
if (console) {
console.log(Array.prototype.slice.call(arguments));
}
}
this.init(options);
}
If I understand what you are asking for correctly, then I think its a matter of changing your log function to the following:
function sendLog() {
t.send('STK1', getLine("sourcePara", 1));
}
This assumes that getLine is globally accessible.
Alternatively Another approach would be to allow for the sendLog function to take the message as a parameter. In which case, you would change your first script to be:
sendLog(getLine("sourcePara", 1));
And the modified sendLog function would look like this:
function sendLog(msg) {
t.send('STK1', msg);
}
LocalConnection.js should handle transferring the data between windows/tabs. Looks like an an iteresting project:
https://github.com/jeremyharris/LocalConnection.js

Javascript object not recognizing function

I have a Javascript class defined as below:
function Node(init, parent) {
this.value = init;
this.children = [];
this.updateChildren(this.value);
}
Node.prototype.updateChildren = function(value) {
this.children.push(value);
};
When I run it.. i receive the error,
this.updateChildren() is not defined.
Any clue what I am missing here ?
Full code here :
'use strict';
var millionNumbers = [];
for (var i = 2; i< 1000000; i++) {
if (!millionNumbers[i]) {
millionNumbers[i] = new Node(i, null);
}
}
function Node(init, parent) {
this.value = init;
this.children = [];
if (parent) {
this.parent = parent;
}
var newValue;
if (isEven(this.value)) {
newValue = this.value/2;
} else {
newValue = (this.value * 3) + 1;
}
//whether newValue is 1 or something else, we still have add it to the children list
this.updateChildren(newValue);
if (millionNumbers[newValue]) {
var chainedNode = millionNumbers[newValue];
this.children.concat(chainedNode.children);
}
if (newValue === 1) {
this.endChain();
} else {
new Node(newValue, this);
}
}
Node.prototype.updateChildren = function(value) {
this.children.push(value);
if(this.parent) {
this.parent.updateChildren(value);
}
};
Node.prototype.endChain = function() {
if (!millionNumbers[this.value]) {
millionNumbers[this.value] = this;
this.parent = null;
}
};
function isEven(value) {
if (value % 2 === 0) {
return true;
} else {
return false;
}
}
The for loop instantiates Node objects before Node.prototype.updateChildren is set, so within the Node constructor, this.updateChildren is still undefined.
To fix the problem, just move the for loop to the end of the file.
Also: Best of luck with the Collatz conjecture!
think you are calling these classes without defining them first.
You can try this way:
function updateChildren(value) {
this.children.push(value);
};
function Node(init, parent) {
this.value = init;
this.children = [];
this.updateChildren(value);
}
Node.prototype.updateChildren(value);

How to sending messages from a client application (Dash.js) to the OpenFlow Switch

I have a client application called Dash.js, video player, which runs in an environment that emulates an SDN network with switches and openflow controller.
This application adapts video quality to the bandwidth of the user's network .
The class that determines whether the client will request a replacement segment to adapt to available bandwidth is AbrController.js.
MediaPlayer.dependencies.AbrController = function () {
"use strict";
var autoSwitchBitrate = true,
qualityDict = {},
confidenceDict = {},
getInternalQuality = function (type) {
var quality;
if (!qualityDict.hasOwnProperty(type)) {
qualityDict[type] = 0;
}
quality = qualityDict[type];
return quality;
},
setInternalQuality = function (type, value) {
qualityDict[type] = value;
},
getInternalConfidence = function (type) {
var confidence;
if (!confidenceDict.hasOwnProperty(type)) {
confidenceDict[type] = 0;
}
confidence = confidenceDict[type];
return confidence;
},
setInternalConfidence = function (type, value) {
confidenceDict[type] = value;
};
return {
debug: undefined,
abrRulesCollection: undefined,
manifestExt: undefined,
metricsModel: undefined,
metricsBaselinesModel: undefined,
getAutoSwitchBitrate: function () {
return autoSwitchBitrate;
},
setAutoSwitchBitrate: function (value) {
autoSwitchBitrate = value;
},
getMetricsFor: function (data) {
var deferred = Q.defer(),
self = this;
self.manifestExt.getIsVideo(data).then(
function (isVideo) {
if (isVideo) {
deferred.resolve(self.metricsModel.getMetricsFor("video"));
} else {
self.manifestExt.getIsAudio(data).then(
function (isAudio) {
if (isAudio) {
deferred.resolve(self.metricsModel.getMetricsFor("audio"));
} else {
deferred.resolve(self.metricsModel.getMetricsFor("stream"));
}
}
);
}
}
);
return deferred.promise;
},
getMetricsBaselineFor: function (data) {
var deferred = Q.defer(),
self = this;
self.manifestExt.getIsVideo(data).then(
function (isVideo) {
if (isVideo) {
deferred.resolve(self.metricsBaselinesModel.getMetricsBaselineFor("video"));
} else {
self.manifestExt.getIsAudio(data).then(
function (isAudio) {
if (isAudio) {
deferred.resolve(self.metricsBaselinesModel.getMetricsBaselineFor("audio"));
} else {
deferred.resolve(self.metricsBaselinesModel.getMetricsBaselineFor("stream"));
//self.debug.log("GET STREAM.");
}
}
);
}
}
);
return deferred.promise;
},
getPlaybackQuality: function (type, data, availableRepresentations) {
var self = this,
deferred = Q.defer(),
newQuality = MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,
newConfidence = MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE,
i,
len,
funcs = [],
req,
values,
quality,
confidence;
quality = getInternalQuality(type);
confidence = getInternalConfidence(type);
//self.debug.log("ABR enabled? (" + autoSwitchBitrate + ")");
if (autoSwitchBitrate) {
//self.debug.log("Check ABR rules.");
self.getMetricsFor(data).then(
function (metrics) {
self.getMetricsBaselineFor(data).then(
function (metricsBaseline) {
self.abrRulesCollection.getRules().then(
function (rules) {
for (i = 0, len = rules.length; i < len; i += 1) {
funcs.push(rules[i].checkIndex(quality, metrics, data, metricsBaseline, availableRepresentations));
}
Q.all(funcs).then(
function (results) {
//self.debug.log(results);
values = {};
values[MediaPlayer.rules.SwitchRequest.prototype.STRONG] = MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE;
values[MediaPlayer.rules.SwitchRequest.prototype.WEAK] = MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE;
values[MediaPlayer.rules.SwitchRequest.prototype.DEFAULT] = MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE;
for (i = 0, len = results.length; i < len; i += 1) {
req = results[i];
if (req.quality !== MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE) {
values[req.priority] = Math.min(values[req.priority], req.quality);
}
}
if (values[MediaPlayer.rules.SwitchRequest.prototype.WEAK] !== MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE) {
newConfidence = MediaPlayer.rules.SwitchRequest.prototype.WEAK;
newQuality = values[MediaPlayer.rules.SwitchRequest.prototype.WEAK];
}
if (values[MediaPlayer.rules.SwitchRequest.prototype.DEFAULT] !== MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE) {
newConfidence = MediaPlayer.rules.SwitchRequest.prototype.DEFAULT;
newQuality = values[MediaPlayer.rules.SwitchRequest.prototype.DEFAULT];
}
if (values[MediaPlayer.rules.SwitchRequest.prototype.STRONG] !== MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE) {
newConfidence = MediaPlayer.rules.SwitchRequest.prototype.STRONG;
newQuality = values[MediaPlayer.rules.SwitchRequest.prototype.STRONG];
}
if (newQuality !== MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE && newQuality !== undefined) {
quality = newQuality;
}
if (newConfidence !== MediaPlayer.rules.SwitchRequest.prototype.NO_CHANGE && newConfidence !== undefined) {
confidence = newConfidence;
}
self.manifestExt.getRepresentationCount(data).then(
function (max) {
// be sure the quality valid!
if (quality < 0) {
quality = 0;
}
// zero based
if (quality >= max) {
quality = max - 1;
}
if (confidence != MediaPlayer.rules.SwitchRequest.prototype.STRONG &&
confidence != MediaPlayer.rules.SwitchRequest.prototype.WEAK) {
confidence = MediaPlayer.rules.SwitchRequest.prototype.DEFAULT;
}
setInternalQuality(type, quality);
//self.debug.log("New quality of " + quality);
setInternalConfidence(type, confidence);
//self.debug.log("New confidence of " + confidence);
deferred.resolve({quality: quality, confidence: confidence});
}
);
}
);
}
);
}
);
}
);
} else {
self.debug.log("Unchanged quality of " + quality);
deferred.resolve({quality: quality, confidence: confidence});
}
return deferred.promise;
},
setPlaybackQuality: function (type, newPlaybackQuality) {
var quality = getInternalQuality(type);
if (newPlaybackQuality !== quality) {
setInternalQuality(type, newPlaybackQuality);
}
},
getQualityFor: function (type) {
return getInternalQuality(type);
}
};
};
MediaPlayer.dependencies.AbrController.prototype = {
constructor: MediaPlayer.dependencies.AbrController
};
What I want is that every time there is a request for segment change, a message is triggered for openflow switch, so that it can send a packetin to the controller and the controller take action.
For me, now, the problem is this exchange of communication between the client and the OpenFlow Switch.
Does anyone know how to shoot this message and get in openflow switch?
Thank you!
You could use a REST API to pass parameters to your network. Most of SDN controllers expose their API in order to interact with external applications.
Ryu REST API: https://osrg.github.io/ryu-book/en/html/rest_api.html
Opendaylight REST API: https://wiki.opendaylight.org/view/OpenDaylight_Controller:REST_Reference_and_Authentication

How implement javascript Map structure with dynamic data ?

I am trying to create tree like component,
for the first level data is coming from the server ,
if the user clicks the node i need to populate the child nodes with the data from service call.
what is the best way to save the data for this tree component ?
because user will do some operations on the tree component like remove, add & move. Finally i need to send the updated data to the server .
This is the hashmap functionality I use in javascript.
I based it off the docs of java 7 hashmap.
http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
I added the load and save variables to allow JSON storage. be careful though. if you stored any complex objects(like a hashmap in a hashmap) you will lose that.
You'd have to implement your own object instantiatiors in the load and save function.
A JSfiddle to play with if you like:
http://jsfiddle.net/mdibbets/s51tubm4/
function HashMap() {
this.map = {};
this.listsize = 0;
}
HashMap.prototype._string = function(key) {
if(typeof key.toString !== 'undefined') {
return key.toString();
}
else {
throw new Error('No valid key supplied. Only supply Objects witha toString() method as keys');
}
}
HashMap.prototype.put = function(key,value) {
key = this._string(key);
if(typeof this.map[key] === 'undefined') {
this.listsize++;
}
this.map[key] = value;
}
HashMap.prototype.get = function(key) {
key = this._string(key);
return this.map[key];
}
HashMap.prototype.containsKey = function(key) {
key = this._string(key);
return !(this.map[key] === 'undefined');
}
HashMap.prototype.putAll = function(hashmap) {
if(hashmap instanceof HashMap) {
var othermap = hashmap.map;
for(var key in othermap) {
if(othermap.hasOwnProperty(key)) {
if(typeof this.map[key] === 'undefined') {
this.listsize++;
}
this.map[key] = othermap[key];
}
}
}
else {
throw new Error('No HashMap instance supplied');
}
}
HashMap.prototype.remove = function(key) {
key = this._string(key);
var ret = null;
if(typeof this.map[key] !== 'undefined') {
ret = this.map[key];
delete this.map[key];
this.listsize--;
}
return ret;
}
HashMap.prototype.clear = function() {
this.map = {};
this.listsize = 0;
}
HashMap.prototype.containsValue = function(value) {
for(var key in this.map) {
if(this.map.hasOwnProperty(key)) {
if(this.map[key] === value) {
return true;
}
}
}
return false;
}
HashMap.prototype.clone = function() {
var ret = new HashMap();
ret.map = this.map;
ret.listsize = this.listsize;
return ret;
}
HashMap.prototype.entrySet = function() {
return this.map;
}
HashMap.prototype.keySet = function() {
var ret = [];
for(var key in this.map) {
if(this.map.hasOwnProperty(key)) {
ret.push(key);
}
}
return ret;
}
HashMap.prototype.values = function() {
var ret = [];
for(var key in this.map) {
if(this.map.hasOwnProperty(key)) {
ret.push(this.map[key]);
}
}
return ret;
}
HashMap.prototype.size = function(activeCheck) {
//Active check is expensive.
if(typeof activeCheck !== 'undefined' && activeCheck) {
var count = 0;
for(var key in this.map) {
if(this.map.hasOwnProperty(key)) {
count++;
}
}
return count;
}
return this.listsize;
}
HashMap.prototype.save = function(){
return JSON.stringify(this.map);
}
HashMap.prototype.load = function(json) {
if(typeof json !== 'string') {
throw new Error("No valid input supplied. Only supply JSON Strings");
}
this.map = JSON.parse(json);
this.listsize = this.size(true);
}
var map = new HashMap();
console.log(
map.put('hello', true),
map.get('hello'),
map.put('hello',10),
map.put('world',20),
map.values(),
map.keySet(),
map.entrySet(),
map.containsValue('twoshoes'),
map.size()
);
var map2 = new HashMap();
map2.put('goody','twoshoes');
map2.putAll(map);
console.log(
map2.get('hello'),
map2.values(),
map2.keySet(),
map2.entrySet(),
map2.containsValue('twoshoes'),
map2.size()
);
var map3 = new HashMap();
map3.load(map2.save());
console.log(
map3.get('hello'),
map3.values(),
map3.keySet(),
map3.entrySet(),
map3.containsValue('twoshoes'),
map3.size()
);

Categories