So, I'm starting to take a look at KnockoutJS and it's all a little gloomy yet, in the example I'm following, I'm having an error that says O objeto não oferece suporte à propriedade ou método 'join'
.
My JS
function setupHubClient() {
socialHubClient = $.connection.socialHub;
// Inicia a conexão
$.connection.hub.start(function () {
socialHubClient.join(userInfo.Nome);
}).done(function () {
window.isSignalREnabled = true;
if (window.muralViewModel) {
window.muralViewModel.isSignalREnabled(true);
}
}).fail(function () {
alert('Conexão SignalR falhou!');
});
}
My Hub
public class SocialHub : Hub
{
public void Join(string nome)
{
ChatModel.Clients.Add(new Client() { Name = nome, LastResponse = DateTime.Now });
Clients.Caller.Nome = nome;
}
}
My signalr/hubs
/*!
* ASP.NET SignalR JavaScript Library v2.2.0
* http://signalr.net/
*
* Copyright Microsoft Open Technologies, Inc. All rights reserved.
* Licensed under the Apache 2.0
* https://github.com/SignalR/SignalR/blob/master/LICENSE.md
*
*/
/// <reference path="..\..\SignalR.Client.JS\Scripts\jquery-1.6.4.js" />
/// <reference path="jquery.signalR.js" />
(function ($, window, undefined) {
/// <param name="$" type="jQuery" />
"use strict";
if (typeof ($.signalR) !== "function") {
throw new Error("SignalR: SignalR is not loaded. Please ensure jquery.signalR-x.js is referenced before ~/signalr/js.");
}
var signalR = $.signalR;
function makeProxyCallback(hub, callback) {
return function () {
// Call the client hub method
callback.apply(hub, $.makeArray(arguments));
};
}
function registerHubProxies(instance, shouldSubscribe) {
var key, hub, memberKey, memberValue, subscriptionMethod;
for (key in instance) {
if (instance.hasOwnProperty(key)) {
hub = instance[key];
if (!(hub.hubName)) {
// Not a client hub
continue;
}
if (shouldSubscribe) {
// We want to subscribe to the hub events
subscriptionMethod = hub.on;
} else {
// We want to unsubscribe from the hub events
subscriptionMethod = hub.off;
}
// Loop through all members on the hub and find client hub functions to subscribe/unsubscribe
for (memberKey in hub.client) {
if (hub.client.hasOwnProperty(memberKey)) {
memberValue = hub.client[memberKey];
if (!$.isFunction(memberValue)) {
// Not a client hub function
continue;
}
subscriptionMethod.call(hub, memberKey, makeProxyCallback(hub, memberValue));
}
}
}
}
}
$.hubConnection.prototype.createHubProxies = function () {
var proxies = {};
this.starting(function () {
// Register the hub proxies as subscribed
// (instance, shouldSubscribe)
registerHubProxies(proxies, true);
this._registerSubscribedHubs();
}).disconnected(function () {
// Unsubscribe all hub proxies when we "disconnect". This is to ensure that we do not re-add functional call backs.
// (instance, shouldSubscribe)
registerHubProxies(proxies, false);
});
proxies['socialHub'] = this.createHubProxy('socialHub');
proxies['socialHub'].client = { };
proxies['socialHub'].server = {
enviarComentarioParaServidor: function (comentarioPaiId, texto) {
return proxies['socialHub'].invoke.apply(proxies['socialHub'], $.merge(["EnviarComentarioParaServidor"], $.makeArray(arguments)));
},
enviarCurtirParaServidor: function (comentarioId) {
return proxies['socialHub'].invoke.apply(proxies['socialHub'], $.merge(["EnviarCurtirParaServidor"], $.makeArray(arguments)));
},
enviarDescurtirParaServidor: function (messageId) {
return proxies['socialHub'].invoke.apply(proxies['socialHub'], $.merge(["EnviarDescurtirParaServidor"], $.makeArray(arguments)));
},
join: function (nome) {
return proxies['socialHub'].invoke.apply(proxies['socialHub'], $.merge(["Join"], $.makeArray(arguments)));
}
};
return proxies;
};
signalR.hub = $.hubConnection("/signalr", { useDefaultPath: false });
$.extend(signalR, signalR.hub.createHubProxies());
}(window.jQuery, window));
My _Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>@ViewBag.Title</title>
<link rel="icon" href="@Url.Content("~/Content/images/NetMagazineIcon.png")" type="image/ico">
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
@* <link href='http://fonts.googleapis.com/css?family=Lobster' rel='stylesheet' type='text/css'>*@
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/modernizr-2.6.2.js"></script>
@RenderSection("Scripts", required: false)
</head>
<body>
<div class="page">
<header>
<div id="title">
</div>
<div id="logindisplay">
</div>
</header>
<nav>
<ul id="menu">
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("Sobre", "About", "Home")</li>
@Html.Partial("_LogOnPartial")
</ul>
</nav>
<section id="main">
@RenderBody()
</section>
<footer></footer>
</div>
</body>
</html>
My view
@model Chat.Domain.Model.Usuario
@{
ViewBag.Title = "Social Chat";
}
@section Scripts {
<script src="@Url.Content("~/Scripts/jquery.signalR-2.2.0.js")"></script>
<script src="@Url.Content("~/signalr/hubs")"></script>
<script src="@Url.Content("~/Scripts/social.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/knockout-3.2.0.js")"></script>
<script type="text/javascript">
var userInfo = {
Id: @ViewData.Model.Id,
Nome: '@ViewData.Model.Nome',
SmallPicturePath: 'Content/images/actor' + @ViewData.Model.Id + '_small.gif',
MediumPicturePath: 'Content/images/actor' + @ViewData.Model.Id + '_medium.gif'
};
window.userInfo = userInfo;
</script>
}
<div class="photoContainer">
<div class="largePhotoContainer">
<img src="@Url.Content("~/Content/images/Background" + @ViewData.Model.Id + ".jpg")" width="1024" height="256" class="largePhoto" />
</div>
<h2 class="nameContainer">@ViewData.Model.Nome</h2>
<div class="smallPhotoContainer">
<div class="smallPhotoBorder">
<img src="@Url.Content("~/Content/images/actor" + @ViewData.Model.Id + "_large.gif")" width="100" height="100" class="smallPhoto" />
</div>
</div>
</div>
<p>
<img src="@Url.Content("~/Content/images/facebook-loading.gif")" class="wall-loading" id="loading-wall-messages" />
<div class="ajax-error" style="display: none;"><img src="Content/images/exclamation.png" width="32" height="32" /><span>Estamos com problemas para acessar os dados. Por favor recarregue a página.</span></div>
<!-- ko if: $root.isSignalREnabled -->
<div class="post-comment post-message">
<div class="message">
<textarea class="message-textarea" data-bind="value: novoComentario, valueUpdate: 'afterkeydown', event: { keypress: commentKeypress, focus: commentFocus, blur: commentFocusout, mouseenter: commentMouseEnter, mouseleave: commentMouseLeave }"></textarea>
<span class="comment-watermark" data-bind="style: {display: mostrarMarcaDAgua() ? '' : 'none'}, event: { click: commentClick, mouseenter: commentMouseEnter, mouseleave: commentMouseLeave }">No que você está pensando?</span>
<br />
</div>
</div>
<!-- /ko -->
<div class="wall-messages" style="display: none;">
<!-- ko foreach: comentarios-->
<div class="message-thread">
<div class="message-thread-author"></div>
<div class="thread-conversation" data-bind="attr: {threadConversationMessageId: id}">
<span><img data-bind="attr: {src: 'Content/images/actor' + usuario().Id + '_medium.gif'}" class="actor-image-medium" /></span>
<div>
<div class="author-name" data-bind="text: usuario().Nome">
</div>
<div class="comment-text" data-bind="text: texto">
</div>
<div class="post-info">
<span data-bind="text: tempoDecorrido"></span> ·
<span data-bind="ifnot: $parent.isSignalREnabled">
<img src="@Url.Content("Content/images/loading_small.gif")" />
</span>
<!-- ko if: $parent.isSignalREnabled -->
<span>
<a href="javascript:void(0);" class="post-info-link like"
data-bind="style: { display: curtidoPorEsteUsuario() ? 'none' : ''},
click: curtir">Curtir</a>
<a href="javascript:void(0);" class="post-info-link unlike"
data-bind="style: { display: curtidoPorEsteUsuario() ? '' : 'none'},
click: descurtir">Curtir (Desfazer)</a>
</span>
<!-- /ko -->
</div>
</div>
<div class="balloonEdge"></div>
<div class="balloonBody">
<div class="UIImageBlock clearfix">
<a class="likeIconLabel" href="#" tabindex="-1" aria-hidden="true">
<label class="likeIconLabel" title="Like this item" onclick="this.form.like.click();">
</label>
</a>
<!-- ko if: curtiram().length > 0 -->
<div class="likeInfo"
data-bind="text: sumarioDeCurtidas,
style: {display: sumarioDeCurtidas().trim().length > 0 ? '' : 'none'}">
</div>
<!-- /ko -->
</div>
</div>
<div class="reply-container">
<!-- ko foreach: comentarios -->
<div class="post-comment">
<div class="comment-author">
<img data-bind="attr: {src: 'Content/images/actor' + usuario().Id + '_small.gif'}" class="actor-image-small" />
</div>
<div class="comment" data-bind="attr: {answerId: id}">
<div class="author-name" data-bind="text: usuario().Nome">
</div>
<div class="comment-text" data-bind="text: texto">
</div>
<br />
<span data-bind="text: tempoDecorrido"></span> ·
<span data-bind="ifnot: $root.isSignalREnabled">
<img src="@Url.Content("Content/images/loading_small.gif")" />
</span>
<!-- ko if: $root.isSignalREnabled -->
<span>
<a href="javascript:like(1);" class="post-info-link"
data-bind="style: { display: curtidoPorEsteUsuario() ? 'none' : ''}, click: curtir">Curtir</a>
<a href="javascript:like(1);" class="post-info-link"
data-bind="style: { display: curtidoPorEsteUsuario() ? '' : 'none'}, click: descurtir">Curtir (Desfazer)</a>
</span>
<!-- /ko -->
<div class="likeInfo" data-bind="text: sumarioDeCurtidas,
style: {display: sumarioDeCurtidas().trim().length > 0 ? '' : 'none'}">
</div>
</div>
</div>
<!-- /ko -->
</div>
<!-- ko if: $root.isSignalREnabled -->
<div class="reply-container">
<div class="post-comment">
<div class="comment-author">
<img src="@ViewData.Model.SmallPicturePath" class="actor-image-small" />
</div>
<div class="comment">
<input class="comment-textarea" data-bind="value: novoComentario, valueUpdate: 'afterkeydown', event: { keypress: commentKeypress, focus: commentFocus, blur: commentFocusout, mouseenter: commentMouseEnter, mouseleave: commentMouseLeave }" />
<span class="comment-watermark" data-bind="style: {display: mostrarMarcaDAgua() ? '' : 'none'}, event: { click: commentClick, mouseenter: commentMouseEnter, mouseleave: commentMouseLeave }">Digite um comentário aqui...</span>
<br />
</div>
</div>
</div>
<!-- /ko -->
</div>
</div>
<!-- /ko -->
<br />
</div>
</p>
My BundleConfig
public class BundleConfig
{
// For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862
public static void RegisterBundles(BundleCollection bundles)
{
bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(
"~/Scripts/jquery.validate*"));
// Use the development version of Modernizr to develop with and learn from. Then, when you're
// ready for production, use the build tool at http://modernizr.com to pick only the tests you need.
bundles.Add(new ScriptBundle("~/bundles/modernizr").Include(
"~/Scripts/modernizr-*"));
bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include(
"~/Scripts/bootstrap.js",
"~/Scripts/respond.js"));
bundles.Add(new StyleBundle("~/Content/css").Include(
"~/Content/bootstrap.css",
"~/Content/site.css"));
}
}
What might be missing for JS to recognize the Join
method?