I have a website that is functioning fine, but when I try to add a signalr hub to it I get the error
Uncaught TypeError: this.hasSubscriptions is not a function
at Function.<anonymous> (jquery.signalR-2.2.0.js:2878)
at Function.each (jquery-2.1.4.js:382)
at hubConnection.fn.init.<anonymous> (jquery.signalR-2.2.0.js:2877)
at hubConnection.fn.init.<anonymous> (jquery.signalR-2.2.0.js:759)
at hubConnection.fn.init.dispatch (jquery-2.1.4.js:4435)
at hubConnection.fn.init.elemData.handle (jquery-2.1.4.js:4121)
at Object.trigger (jquery-2.1.4.js:4350)
at jQuery.fn.init.triggerHandler (jquery-2.1.4.js:4907)
at hubConnection.fn.init.start (jquery.signalR-2.2.0.js:652)
at connection._.deferredStartHandler (jquery.signalR-2.2.0.js:463)
interrogating line 2878 in the signalr library leads me to find that this
is a prototype I have defined in another script
Object.prototype.myfunction = function(){
...
}
Firstly, I cannot see why this prototype function is being interrogated for signalr subscriptions.
And secondly, how do I get past this problem without removing the prototype and rewriting swathes of code in the site?
Note:
I tried adding a prototype for hasSubscriptions
, but this lead to other errors around the handling of my existing prototypes
Also, all the code around the signalr works fine if the prototypes are removed (but this breaks the rest of the site)
Actual code:
<div ng-show="noPartialView()" class="well well-lg">
<div class="row" data-bind="foreach:counters">
<div class="col-md-12 canvas-container">
<h2 data-bind="text:name" class="graph-header"></h2>
<div data-bind="foreach:lines">
<div class="indicatorLine inline" data-bind="style:{borderColor:color}"><img /></div>
<span data-bind="text:name"></span>
</div>
<canvas width="1700" height="200" data-bind="attr:{'id': name}" class="responsive-canvas"></canvas>
</div>
</div>
</div>
@Scripts.Render("~/bundles/jquery")
<script src="~/SignalR/hubs"></script>
@Scripts.Render("~/bundles/angular")
@Scripts.Render("~/bundles/realtimedata")
@Scripts.Render("~/bundles/AngularMVCApp")
where bundles are:
bundles.Add(new ScriptBundle("~/bundles/jquery")
.Include("~/Scripts/jquery-2.1.4.js")
.Include("~/Scripts/jquery.signalR-2.2.0.js")
.Include("~/Scripts/jquery.color-2.1.2.js"));
bundles.Add(new ScriptBundle("~/bundles/angular")
.Include("~/Scripts/angular.js")
.Include("~/Scripts/angular-sanitize.js")
.Include("~/Scripts/angular-bootstrap-confirm.js")
.Include("~/Scripts/angular-animate.js")
.Include("~/Scripts/angular-ui/ui-bootstrap-tpls.js")
.Include("~/Scripts/angular-route.js")
.Include("~/Scripts/datetime-picker.js")
.Include("~/Scripts/angular-locale_en-gb.js")
.Include("~/Scripts/moment-with-locales.js"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap")
.Include("~/Scripts/bootstrap.js"));
bundles.Add(new ScriptBundle("~/bundles/realtimedata")
.Include("~/Scripts/knockout-2.3.0.js")
.Include("~/Scripts/smoothie.js")
.Include("~/Scripts/realtimedata.js"));
bundles.Add(new ScriptBundle("~/bundles/AngularMVCApp")
.Include("~/Scripts/Helpers.js")
.Include("~/Scripts/InFill.js")
.Include("~/Scripts/ArrayComparer.js")
.IncludeDirectory("~/Scripts/Providers", "*.js")
.IncludeDirectory("~/Scripts/Directives", "*.js")
.IncludeDirectory("~/Scripts/Services", "*.js")
.IncludeDirectory("~/Scripts/Controllers", "*.js")
.Include("~/Scripts/AngularMVCApp.js"));
and the realtimedata library is
(function () {
var countersHub = $.connection.countersHub;
$.connection.hub.logging = true;
$.connection.hub.start();
countersHub.client.newCounters = function (counters) {
model.addCounters(counters);
};
....
}());
but the problems are caused by any prototype functions added to Object (which are defined in Helpers.js) e.g.
Object.prototype.getFieldValue = function () {
if (arguments == null || arguments.length != 1) {
return null;
}
var fieldName = arguments[0];
if (this == null || fieldName == null || typeof fieldName != 'string') {
return null;
}
var temp = this;
var fieldNameSplit = fieldName.split('.');
for (i = 0; i < fieldNameSplit.length; i++) {
if (temp == null) {
return temp;
}
if (fieldNameSplit[i].indexOf('[') > -1) {
var fieldNameWithoutIndex = fieldNameSplit[i].split('[')[0];
var index = fieldNameSplit[i].split('[')[1].split(']')[0];
temp = temp[fieldNameWithoutIndex][index];
}
else {
temp = temp[fieldNameSplit[i]];
}
}
return temp;
};
Edit: Extra information found
the problem looks to be caused by the object prototype functions being exposed in the iteration
for (i in obj)
yet the native javascript prototype functions (such as toString and hasOwnObject) are not.
Why are my prototype functions being exposed by the iteration yet the native ones are not and is there a way to 'mask' my functions so they do not appear as the iterand?