I'm making a basic shopping list app and have run into a wall. The program silently fails, and upon checking with breakpoints and such, I've discovered that on line 75, I'm getting newItem as undefined.
Everything else in the statement is being defined correctly. Any clue what I've done wrong?
Here's the index.js:
'use strict';
var state = {
items: []
};
var listItemTemplate = (
'<li>' +
'<span class="shopping-item js-shopping-item"></span>' +
'<div class="shopping-item-controls">' +
'<button class="js-shopping-item-toggle">' +
'<span class="button-label">check</span>' +
'</button>' +
'<button class="js-shopping-item-delete">' +
'<span class="button-label">delete</span>' +
'</button>' +
'</div>' +
'</li>'
);
// state modification functions
var stateHelper = {
addItem: function(state, item) {
state.items.push({
displayName: item,
checkedOff: false
});
},
getItem: function(state, itemIndex) {
return state.items[itemIndex];
},
deleteItem: function(state, item) {
state.items.splice(itemIndex, 1);
},
updateItem: function(state, item) {
state.items[itemIndex] = newItemState;
}
}
// render functions
var renderHelper = {
renderItem: function(item, itemId, itemTemplate, itemDataAttr) {
var element = $(itemTemplate);
element.find('.js-shopping-item').text(item.displayName);
console.log("item.displayName: " + item.displayName)
console.log("item: " + item)
if (item.checkedOff) {
element.find('.js-shopping-item').addClass('shopping-item__checked');
}
element.find('.js-shopping-item-toggle')
element.attr(itemDataAttr, itemId);
// try `element.find('.js-shopping-item-toggle').attr(itemDataAttr, itemId);` instead and see if it works
console.log("itemDataAttr: " + itemDataAttr)
return element;
},
renderList: function(state, listElement, itemDataAttr) {
var itemsHTML = state.items.map(
function(item, index) {
//what determines the index here?
console.log("index: " + index)
return renderItem(item, index, listItemTemplate, itemDataAttr);
});
listElement.html(itemsHTML);
}
}
// event listeners
var eventHelper = {
handleItemAdds: function(formElement, newItemIdentifier, itemDataAttr, listElement, state) {
formElement.submit(function(event) {
event.preventDefault();
var newItem = formElement.find(newItemIdentifier).val();
console.log(newItem)
stateHelper.addItem(state, newItem);
console.log(newItemIdentifier)
this.reset();
});
},
handleItemDeletes: function(formElement, removeIdentifier, itemDataAttr, listElement, state) {
listElement.on('click', removeIdentifier, function(event) {
var itemIndex = parseInt($(this).closest('li').attr(itemDataAttr));
console.log("this: " + this);
console.log("$(this).closest('li').attr(itemDataAttr " + $(this).closest('li').attr(itemDataAttr));
stateHelper.deleteItem(state, itemIndex);
renderList(state, listElement, itemDataAttr);
console.log("what is itemDataAttr? it is: " + itemDataAttr)
})
},
handleItemToggles: function(listElement, toggleIdentifier, itemDataAttr, state) {
listElement.on('click', toggleIdentifier, function(event) {
var itemId = $(event.currentTarget.closest('li')).attr(itemDataAttr);
var oldItem = stateHelper.getItem(state, itemId);
stateHelper.updateItem(state, itemId, {
displayName: oldItem.displayName,
checkedOff: !oldItem.checkedOff
});
renderHelper.renderList(state, listElement, itemDataAttr)
});
}
}
$(function() {
var formElement = $('#js-shopping-list-form');
var listElement = $('.js-shopping-list');
//id of input containing list items
var newItemIdentifier = "#js-new-item";
//in listItemTemplate above; the delete button has this class
var removeIdentifier = ".js-shopping-item-delete";
//stores id of list item
var itemDataAttr = "data-list-item-id";
var toggleIdentifier = ".js-shopping-list-toggle"
eventHelper.handleItemAdds(formElement, newItemIdentifier, itemDataAttr, listElement, state);
eventHelper.handleItemDeletes(formElement, removeIdentifier, itemDataAttr, listElement, state);
eventHelper.handleItemToggles(listElement, toggleIdentifier, itemDataAttr, state);
});
And here's the index.html for reference:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Shopping List</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/4.2.0/normalize.min.css">
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<link rel="stylesheet" href="main.css">
</head>
<body>
<div class="container">
<h1>Shopping List</h1>
<form id="js-shopping-list-form">
<label for="shopping-list-entry">Add an item</label>
<input type="text" name="shopping-list-entry" id="shopping-list-entry" placeholder="e.g., broccoli">
<button type="submit">Add item</button>
</form>
<ul class="shopping-list">
</ul>
</div>
<script src="jquery-3.1.1.js"></script>
<script type="text/javascript" src="index.js"></script>
</body>
</html>
Alacritas,
I don't see anywhere in your view that you actually have an element with an id that matches that accessor (#js-new-item).
Your comment says it belongs to the input box, but the input box you have in your html does not have that id.
I think you would need to update the string "#js-new-item" to be "#shopping-list-entry".
Related
I have a JS feature in my app that allows the user to create a list one item at a time. I am trying now to give each item a bootstrap slider, but am encountering difficulties. I'm new to JS, so there might be some bad ideas in here (ones I would love help correcting). As it stands currently, if I take everything outside the <p> tags inside the for loop's added html out it works as intended, but with everything in it it renders a console error stating Uncaught TypeError: Cannot read property 'getAttribute' of null.
var proArray = [];
function addPro() {
proArray.push(document.getElementById("proInput").value);
document.getElementById("proForm").reset();
console.log(proArray);
for (var i = 0; i < proArray.length; i++) {
newItem = "<li><p>" + proArray[i] + "</p><input class='bootstrap-slider' type='text' id='proInput" + i + "' data-slider-id='proInput" + i + "' data-slider-min='0' data-slider-max='10' data-slider-value='5' /></li>";
}
var slider = new Slider('#proInput0', {
formatter: function(value) {
return 'Current value: ' + value;
}
});
document.getElementById("proList").innerHTML += newItem;
}
$('#proInput0').slider({
formatter: function(value) {
return 'Current value: ' + value;
}
});
<form id="proForm" onkeypress="return event.keyCode != 13;">
<input class="form-control text-left pro-con-input" id="proInput" placeholder="Add New Benefit" />
<div onclick="addPro()" class="btn pro-con-btn">Add</div>
</form>
<h3 class="text-left">Benefits</h3>
<ul class="text-left" id="proList">
</ul>
Can anyone help figure out where I'm going wrong and/or how to do this better?
The main issue is related on how you create on the fly the new elements:
In the for loop you create a variable, after create the slider but only after you append to the dom the new elements.
You never test if an element with the same id already exists.
Mainly, you never save the slider objects for future usage.
Every time you create a new slider you need to destroy and recreate it after a few milliseconds in order to make it works.
The snippet:
var proArray = [];
function addPro() {
var val = document.getElementById("proInput").value.trim();
document.getElementById("proForm").reset();
if (val.length == 0) {
return;
}
if (document.getElementById('proInput' + val) == null) {
proArray.push({id: val, slider: null});
} else {
return;
}
for (var i = 0; i < proArray.length; i++) {
var ele = document.getElementById('proInput' + proArray[i].id);
if (ele == null) {
var newItem = "<li><p>" + proArray[i].id + "</p><input class='bootstrap-slider' type='text' value='' id='proInput" +
proArray[i].id + "' data-slider-id='SIDproInput" + proArray[i].id
+ "' data-slider-min='0' data-slider-max='10' data-slider-value='5'/></li>";
document.getElementById("proList").innerHTML += newItem;
proArray[i].slider = new Slider('#proInput' + proArray[i].id, {
formatter: function(value) {
return 'Current value: ' + value;
}
});
} else {
(function(i) {
setTimeout(function() {
var val = proArray[i].slider.getValue();
proArray[i].slider.destroy();
document.getElementById('SIDproInput' + proArray[i].id).remove();
proArray[i].slider = new Slider('#proInput' + proArray[i].id, {
formatter: function (value) {
return 'Current value: ' + value;
}
});
proArray[i].slider.setValue(val);
}, 100);
})(i);
}
}
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://code.jquery.com/jquery-2.1.1.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.3/css/bootstrap-slider.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-slider/9.7.3/bootstrap-slider.min.js"></script>
<form id="proForm" onkeypress="return event.keyCode != 13;">
<input class="form-control text-left pro-con-input" id="proInput" placeholder="Add New Benefit"/>
<div onclick="addPro()" class="btn pro-con-btn">Add</div>
</form>
<h3 class="text-left">Benefits</h3>
<ul class="text-left" id="proList">
</ul>
Here in my code I take a div TextBoxContainer. Now I want that when I click on DynamicTextBox in script inputbox, it displays search values, which are already in the database. I have tried already autocomplete for that but it doesn't work.
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<script>
$(function() {
$("#btnAdd").bind("click", function() {
var div = $("<div />");
div.html(GetDynamicTextBox(""));
$("#TextBoxContainer").append(div);
});
$( "#DynamicTextBox" ).autocomplete({
source: 'search1.php'
});
$("#btnGet").bind("click", function() {
var values =
$.map($("input[name=DynamicTextBox]"), function(el) {
return el.value
}).join(",\n");
$("#anotherTextbox").val(values);
});
$("#btnGet").bind("click", function() {
var values =
$.map($("input[name=DynamicTextBox1]"), function(el) {
return el.value
}).join(",\n");
$("#anotherTextbox1").val(values);
});
$("body").on("click", ".remove", function() {
$(this).closest("div").remove();
});
});
function GetDynamicTextBox(value) {
return '<input name = "DynamicTextBox" style="width:280px;margin-left:10px;" id="DynamicTextBox" class="skills" type="text" value = "' + value + '" /> ' + '<input style="width:280px;" name = "DynamicTextBox1" type="text" value = "' + value + '" /> ' +
'<span type="button" class="remove glyphicon glyphicon-remove"></span>'
}
</script>
<html>
<div id="TextBoxContainer"></div>
</html>
Friends, I'm trying to build an accordion dynamically with an ui-grid inside it. The problem i'm having is that i cannot see any data in my grids. I need a second pair of eyes to see what i'm doing wrong.
Here is my HTML:
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular-touch.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.16/angular-animate.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.10.0.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/ng-grid/2.0.11/ng-grid.css" />
<link rel="stylesheet" href="http://ui-grid.info/release/ui-grid-unstable.css" type="text/css">
<script src="http://ui-grid.info/release/ui-grid-unstable.js"></script>
</head>
<body>
<div ng-controller="AccordionDemoCtrl" id="akkordion"></div>
</body>
</html>
And here is my JS:
//noprotect
var app = angular.module('myApp',['ui.bootstrap','ui.grid', 'ui.grid.cellNav', 'ui.grid.edit'] );
var json = '[{"name":"Service Request","isOpen":"false","groups":[{"name":"Header","isOpen":"false","grids":[{"data":"myData"}]},{"name":"Details 1","isOpen":"false"}]},{"name":"Service Confirmation","isOpen":"false","groups":""}]';
var mydata = '[{"firstName":"Cox","lastName":"Carney","company":"Enormo","employed":true},{"firstName":"Lorraine","lastName":"Wise","company":"Comveyer","employed":false},{"firstName":"Nancy","lastName":"Waters","company":"Fuelton","employed":false}]';
var ary = JSON.parse(json);
var accView = "";
var accLevel = 0;
var accName = "groups";
var gridName = "grid";
var dataName = "{ data: mydata }";
var accBuild = function (obj){
if (typeof(obj)==="object"){
for (var i in obj) {
accView = accView + "<accordion close-others=\"true\">";
accView = accView + "<accordion-group ng-repeat=\""+(accName+accLevel);
if(accLevel>0){
accView = accView + " in "+accName+".groups\" is-open=\"{{"+(accName+accLevel)+".isOpen}}\"><accordion-heading><div ng-click=\"opened("+(accName+accLevel)+".name)\">{{"+(accName+accLevel)+".name}}</div></accordion-heading></div>";
accView = accView + "<div id='" +(gridName+accLevel) + "'";
accView = accView + " ui-grid='" + dataName + "'></div>";
}else{
accView = accView + " in "+accName+"\" is-open=\"{{"+(accName+accLevel)+".isOpen}}\"><accordion-heading><div ng-click=\"opened("+(accName+accLevel)+".name)\">{{"+(accName+accLevel)+".name}}</div></accordion-heading>";
}
accName = accName+accLevel;
accLevel = accLevel + 1;
accBuild(obj[i].groups);
accView = accView + "</accordion-group></accordion>";
}
}
};
accBuild(ary);
//console.log(accView);
document.all.akkordion.innerHTML=accView;
function AccordionDemoCtrl($scope) {
$scope.opened = function (groupname) {
console.log("Opened group: "+ groupname);
};
$scope.groups = ary;
}
Sorry, I cant comment.
You need to add your Controller to your module, like #user2341963 said.
app.controller('AccordionDemoCtrl', AccordionDemoCtrl);
And if you want to access your data like this
ui-grid="{ data: mydata }"
mydata has to be bound to $scope in your Controller for Angular to find/access it. See the Updated JSBin .
app.controller('AccordionDemoCtrl', AccordionDemoCtrl);
function AccordionDemoCtrl($scope) {
$scope.mydata = [
{
test: 'test',
other: 'other'
},
{
test: 'test',
other: 'other'
},
{
test: 'test',
other: 'other'
},
];
$scope.opened = function (groupname) {
console.log("Opened group: "+ groupname);
};
$scope.groups = ary;
}
I've got list of products for my autocomplete and different pictures for them. How can I put the radiobuttons with pictures under each product? This is my code for autocomplete so far
function create_rbuttons(item){
var str = $();
if(item.PicId !=null){
for(i=0;i<item.PicId.length;i++){
debugger;
str = str + $('<input type="radio" name="rbtnCount" />');
}
}
return str;
}
$('.SliderBox').on("focus",function () {
$(this).autocomplete({
delay: 500,
minLength: #(Model.SearchTermMinimumLength.ToString()),
source: '#(Url.RouteUrl("ProductSearch"))',
select: function( event, ui ) {
$(this).val(ui.item.label);
var box_id = $(this).closest('.search-box').attr('value');
$('.Picture'+box_id+' img').attr('src',ui.item.productpictureurl).width(100).height(100);
$('#Picture'+box_id+'Id').attr('value',ui.item.PicId[0])
$('.Text'+box_id+' input').attr('value',ui.item.label)
$('.Link'+box_id+' input').attr('value',ui.item.producturl);
return false;
}
})
.data("ui-autocomplete")._renderItem = function( ul, item ) {
var t = item.label;
return $("<li></li>")
.data("item.autocomplete", item)
.append("<a>#(true ? Html.Raw("<img src='\" + item.UrlsArr[0] + \"'>") : null)" + t + "</a>")
.append("<a>" + t + "</a>")
.append(create_rbuttons(item))
.appendTo(ul);
};
PicId is an array, where I keep id of pictures. UrlsArr — where I keep paths to them
I tried something. The radio button doesn't really do anything, it just sits there.
But you can see the icon.
See if it helps
index.php
<style>
img.icon {
height: 20px;
}
.highlight {
color: red;
}
</style>
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/themes/smoothness/jquery-ui.css" />
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
<script type="text/javascript">
$(function () {
var searchbox = $("#search");
searchbox.autocomplete({
source: "autocomplete.php",
select: function (event, ui) {
}
}).data("ui-autocomplete")._renderItem = function (ul, item) {
var li_item = highlight(searchbox.val(), item.value); // highlight
if(li_item.length) {
return $('<li></li>')
.data('item.autocomplete', item)
.append(' <input type="radio" name="rbtnCount"> <img class="icon" src="' + item.icon + '"> ' + li_item )
.appendTo(ul);
}
else {
return $('<li></li>');
}
};
// based on #see http://stackoverflow.com/questions/8644428/how-to-highlight-text-using-javascript
function highlight(needle, haystack) {
var result = haystack;
var index = haystack.toLowerCase().indexOf(needle.toLowerCase());
if ( index >= 0 ) {
result = haystack.substring(0, index) + "<span class='highlight'>" + haystack.substring(index, index+needle.length) + "</span>" + haystack.substring(index + needle.length);
}
else {
// no match
return '';
}
return result;
}
});
</script>
<input id="search">
autocomplete.php
[
{"value": "ActionScript", "icon": "http://blog.istorm.ca/wp-content/uploads/2011/05/64px-ActionScript_icon.png"},
{"value": "Boostrap", "icon": "http://qph.is.quoracdn.net/main-thumb-t-407834-50-bcwisowdvdkeethoagubojbfeljzwjwy.jpeg"},
{"value": "C++", "icon": "http://imag.malavida.com/mvimgbig/download-s/turbo-c-4955-0.jpg"},
{"value": "Jquery", "icon": "https://pbs.twimg.com/profile_images/59268975/jquery_avatar_normal.png"},
{"value": "Java", "icon": "https://pbs.twimg.com/profile_images/426420605945004032/K85ZWV2F_normal.png"},
{"value": "JavaScript", "icon": "http://www.kalmstrom.com/images/logos/Icons/JavaScript128.png"}
]
Try this
function create_rbuttons(item){
if(item.PicId !=null){
for(i=0;i<item.PicId.length;i++){
var radioBtn = $('<input type="radio" name="rbtnCount" />');
radioBtn.appendTo(ul);
}
}
}
I'm making a chat application using SignalR API. I'm getting error as:
0x800a138f - JavaScript runtime error: Unable to get property 'client'
of undefined or null reference
Here is my code:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<link type="text/css" rel="stylesheet" href="/Css/ChatStyle.css" />
<link rel="stylesheet" href="/Css/JQueryUI/themes/base/jquery.ui.all.css">
<!--Script references. -->
<!--Reference the jQuery library. -->
<script src="/Scripts/jquery-1.8.2.min.js"></script>
<script src="/Scripts/ui/jquery.ui.core.js"></script>
<script src="/Scripts/ui/jquery.ui.widget.js"></script>
<script src="/Scripts/ui/jquery.ui.mouse.js"></script>
<script src="/Scripts/ui/jquery.ui.draggable.js"></script>
<script src="/Scripts/ui/jquery.ui.resizable.js"></script>
<!--Reference the SignalR library. -->
<script src="/Scripts/jquery.signalR-1.0.0.js"></script>
<!--Reference the autogenerated SignalR hub script. -->
<script src="/signalr/hubs"></script>
<script type="text/javascript">
$(function () {
setScreen(false);
// Declare a proxy to reference the hub.
var chatHub = $.connection.chatHub;
registerClientMethods(chatHub);
// Start Hub
$.connection.hub.start().done(function () {
registerEvents(chatHub)
});
});
function setScreen(isLogin) {
if (!isLogin) {
$("#divChat").hide();
$("#divLogin").show();
}
else {
$("#divChat").show();
$("#divLogin").hide();
}
}
function registerEvents(chatHub) {
$("#btnStartChat").click(function () {
var name = $("#txtNickName").val();
if (name.length > 0) {
chatHub.server.connect(name);
}
else {
alert("Please enter name");
}
});
$('#btnSendMsg').click(function () {
var msg = $("#txtMessage").val();
if (msg.length > 0) {
var userName = $('#hdUserName').val();
chatHub.server.sendMessageToAll(userName, msg);
$("#txtMessage").val('');
}
});
$("#txtNickName").keypress(function (e) {
if (e.which == 13) {
$("#btnStartChat").click();
}
});
$("#txtMessage").keypress(function (e) {
if (e.which == 13) {
$('#btnSendMsg').click();
}
});
}
function registerClientMethods(chatHub) {
// Calls when user successfully logged in
chatHub.client.onConnected = function (id, userName, allUsers, messages) {
setScreen(true);
$('#hdId').val(id);
$('#hdUserName').val(userName);
$('#spanUser').html(userName);
// Add All Users
for (i = 0; i < allUsers.length; i++) {
AddUser(chatHub, allUsers[i].ConnectionId, allUsers[i].UserName);
}
// Add Existing Messages
for (i = 0; i < messages.length; i++) {
AddMessage(messages[i].UserName, messages[i].Message);
}
}
// On New User Connected
chatHub.client.onNewUserConnected = function (id, name) {
AddUser(chatHub, id, name);
}
// On User Disconnected
chatHub.client.onUserDisconnected = function (id, userName) {
$('#' + id).remove();
var ctrId = 'private_' + id;
$('#' + ctrId).remove();
var disc = $('<div class="disconnect">"' + userName + '" logged off.</div>');
$(disc).hide();
$('#divusers').prepend(disc);
$(disc).fadeIn(200).delay(2000).fadeOut(200);
}
chatHub.client.messageReceived = function (userName, message) {
AddMessage(userName, message);
}
chatHub.client.sendPrivateMessage = function (windowId, fromUserName, message) {
var ctrId = 'private_' + windowId;
if ($('#' + ctrId).length == 0) {
createPrivateChatWindow(chatHub, windowId, ctrId, fromUserName);
}
$('#' + ctrId).find('#divMessage').append('<div class="message"><span class="userName">' + fromUserName + '</span>: ' + message + '</div>');
// set scrollbar
var height = $('#' + ctrId).find('#divMessage')[0].scrollHeight;
$('#' + ctrId).find('#divMessage').scrollTop(height);
}
}
function AddUser(chatHub, id, name) {
var userId = $('#hdId').val();
var code = "";
if (userId == id) {
code = $('<div class="loginUser">' + name + "</div>");
}
else {
code = $('<a id="' + id + '" class="user" >' + name + '<a>');
$(code).dblclick(function () {
var id = $(this).attr('id');
if (userId != id)
OpenPrivateChatWindow(chatHub, id, name);
});
}
$("#divusers").append(code);
}
function AddMessage(userName, message) {
$('#divChatWindow').append('<div class="message"><span class="userName">' + userName + '</span>: ' + message + '</div>');
var height = $('#divChatWindow')[0].scrollHeight;
$('#divChatWindow').scrollTop(height);
}
function OpenPrivateChatWindow(chatHub, id, userName) {
var ctrId = 'private_' + id;
if ($('#' + ctrId).length > 0) return;
createPrivateChatWindow(chatHub, id, ctrId, userName);
}
function createPrivateChatWindow(chatHub, userId, ctrId, userName) {
var div = '<div id="' + ctrId + '" class="ui-widget-content draggable" rel="0">' +
'<div class="header">' +
'<div style="float:right;">' +
'<img id="imgDelete" style="cursor:pointer;" src="/Images/delete.png"/>' +
'</div>' +
'<span class="selText" rel="0">' + userName + '</span>' +
'</div>' +
'<div id="divMessage" class="messageArea">' +
'</div>' +
'<div class="buttonBar">' +
'<input id="txtPrivateMessage" class="msgText" type="text" />' +
'<input id="btnSendMessage" class="submitButton button" type="button" value="Send" />' +
'</div>' +
'</div>';
var $div = $(div);
// DELETE BUTTON IMAGE
$div.find('#imgDelete').click(function () {
$('#' + ctrId).remove();
});
// Send Button event
$div.find("#btnSendMessage").click(function () {
$textBox = $div.find("#txtPrivateMessage");
var msg = $textBox.val();
if (msg.length > 0) {
chatHub.server.sendPrivateMessage(userId, msg);
$textBox.val('');
}
});
// Text Box event
$div.find("#txtPrivateMessage").keypress(function (e) {
if (e.which == 13) {
$div.find("#btnSendMessage").click();
}
});
AddDivToContainer($div);
}
function AddDivToContainer($div) {
$('#divContainer').prepend($div);
$div.draggable({
handle: ".header",
stop: function () {
}
});
////$div.resizable({
//// stop: function () {
//// }
////});
}
</script>
</head>
<body>
<div id="header">
SignalR Chat Room
</div>
<br />
<br />
<br />
<div id="divContainer">
<div id="divLogin" class="login">
<div>
Your Name:<br />
<input id="txtNickName" type="text" class="textBox" />
</div>
<div id="divButton">
<input id="btnStartChat" type="button" class="submitButton" value="Start Chat" />
</div>
</div>
<div id="divChat" class="chatRoom">
<div class="title">
Welcome to Chat Room [<span id='spanUser'></span>]
</div>
<div class="content">
<div id="divChatWindow" class="chatWindow">
</div>
<div id="divusers" class="users">
</div>
</div>
<div class="messageBar">
<input class="textbox" type="text" id="txtMessage" />
<input id="btnSendMsg" type="button" value="Send" class="submitButton" />
</div>
</div>
<input id="hdId" type="hidden" />
<input id="hdUserName" type="hidden" />
</div>
</body>
</html>
You are referring to the client object of an undefined object. So I have been searching inside your code for
.client
These were the results:
chatHub.client.onConnected
chatHub.client.onNewUserConnected
chatHub.client.onUserDisconnected
chatHub.client.messageReceived
chatHub.client.sendPrivateMessage
So, if you look at the results, it becomes obvious that chatHub is undefined somewhere. This is how you initialize it:
var chatHub = $.connection.chatHub;
I wonder what is inside $.connection. Are you missing a script from your html?
A couple of things...
You're using an old signalr version, have you tried upgrading to the latest?
Otherwise; I had a similar problem, I had to solve it by setting up the connection without the generated proxy (/signalr/hubs).
See this link http://www.asp.net/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client and instead of setting it as a "generated proxy", implement it without it. (Search for "Without the generated proxy")