Thank you for the help in advance.
This project is a signup form that will use a chat system to collect the user's profile details during their onboarding process. This is my first jQuery project, so I am struggling to spot my mistakes.
My jQuery should append the value in the textarea to the #message-feed div and apply the CSS classes of .message, .bubble and .user to the new element it creates.
However, when I type into the text area and click submit, it flashes the value I have just typed with no styling in the message feed, but it instantly disappears.
The reason for this CSS structure is the interchangeability between the .bot and .user classes depending on whether it is a question presented to the user by the website, or a user's response to a question.
Here is a link for a JSFiddle but it loads very differently than on my local machine (JSFiddle shows errors.
HTML
<div id="container">
<div id="message-feed">
<h1>Let's get to know you a little bit more…</h1>
</div>
<form method="POST">
<div id="text-response">
<textarea id="text-response" placeholder="Type in here…"></textarea>
</div>
<input type="submit" class="submit-response">
</form>
</div>
CSS
#container {
width: 320px;
height: 480px;
background-color: #fff;
position:absolute;
left:50%;
top:50%;
margin:-240px 0 0 -160px;
}
#message-feed {
width: 100%;
height: 100%;
margin: auto;
overflow-y: scroll;
}
.message {
padding: 0px 15px 15px 15px;
width: 90%;
}
.message:after {
content:"";
display: block;
clear: both;
}
.bubble {
border: 0.5px solid #005393;
max-width: 80%;
padding: 10px;
}
.bot {
color: #005393;
float: left;
border-radius: 12px 12px 12px 0px;
}
.user {
float: right;
background-color: #005393;
border-radius: 12px 12px 0px 12px;
color: #fff;
}
#text-response {
height: 23px;
width: 220px;
border-top: 1px solid #eee;
background-color: #fff;
float: left;
}
textarea {
height: 20px;
width: 220px;
float: left;
resize: none;
border: none;
padding: 10px;
line-height: 22px;
font-family: 'Roboto', sans-serif;
font-weight: 200;
letter-spacing: 1px;
font-size: 15px;
outline: none;
overflow: auto;
}
.submit-response {
height: 45px;
width: 80px;
background-color: #005393;
color: #fff;
float: right;
text-align: center;
line-height: 42px;
font-family: 'Roboto', sans-serif;
font-weight: 200;
letter-spacing: 1px;
font-size: 15px;
outline: none;
border: 0;
}
.submit-response:hover {
opacity: 0.5;
}
jQuery
$(document).ready(function() {
$('.submit-response').click(function() {
var $newMessage = $('textarea[name=text-response]').val()
$('#message-feed').append($newMessage, 'message', 'bubble', 'user');
});
});
2 problems over there :
1/ You're not preventing the event default behavior. That means whenever you're clicking on the button which is a submit input, it will send a POST request. So the page will change. To prevent this :
$('.submit-response').click(function() {
var $newMessage = $('textarea[name=text-response]').val();
$('#message-feed').append($newMessage, 'message', 'bubble', 'user');
});
should become :
$('.submit-response').click(function(event) {
event.preventDefault(event);
var $newMessage = $('textarea[name=text-response]').val();
$('#message-feed').append($newMessage, 'message', 'bubble', 'user');
});
2/ You're not actually adding the classes. $.append appends elements, not classes. So :
$('.submit-response').click(function(event) {
event.preventDefault(event);
var $newMessage = $('textarea[name=text-response]').val()
$('#message-feed').append($newMessage, 'message', 'bubble', 'user');
});
should become :
$('.submit-response').click(function(event) {
event.preventDefault(event);
var $newMessageText = $('textarea[name=text-response]').val(),
$newMessage = $('<span class="message bubble user">' + $newMessageText + '</span>');
$('#message-feed').append($newMessage);
});
Now obviously it doesn't have to be a span, it could be anything else. It still has to be an element.
Also, this is only resolving the issues you had on the front end. You'll need AJAX to send the POST to the server side and get the data without refreshing/leaving the page. But that's another topic.
Related
What I want to do is when I click the task it will have a line through the text means that I'm done with the task. but the add event listener function for this is not working, I'm working with the javascript toggle and that's all I can think of right now to achieve this functionality.
Is there another way to do this? I searched on the internet and it seems complicated when I'm trying to figure it out.
const addBtn = document.querySelector("#push");
const taskInput = document.querySelector("#taskInput");
const taskOutput = document.querySelector("#tasks");
addBtn.addEventListener("click", function() {
let newTasks = taskInput.value;
if (newTasks.length == 0) {
alert("Please enter a task");
} else {
taskOutput.innerHTML += `<div class="task">
<span id="taskname">${newTasks} </span>
<button class="delete" id="deleteButton"><i class="fa-solid fa-trash"></i> </button>
</div>
`;
//delete
let deleteBtn = document.querySelector("#deleteButton");
deleteBtn.addEventListener("click", function() {
this.parentNode.remove();
});
//line through
let theTask = document.querySelectorAll(".task");
theTask.addEventListener("click", function() {
this.classList.toggle("completed");
});
}
});
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
height: 100vh;
background: linear-gradient( 90deg, rgba(241, 206, 221, 1) 0%, rgba(124, 184, 254, 1) 100%);
display: flex;
justify-content: center;
align-items: center;
font-family: 'Kumbh Sans', sans-serif;
}
.container {
border: 2px solid white;
width: 50%;
min-width: 450px;
margin: auto;
padding: 30px 40px;
}
#new-task {
position: relative;
background-color: white;
padding: 30px 20px;
border-radius: 1em;
}
#new-task input {
width: 70%;
height: 45px;
font-family: 'Manrope', sans-seif;
font-size: 1.2em;
border: 2px solid #d1d3d4;
padding: 12px;
color: #111111;
font-weight: 500;
position: relative;
border-radius: 5px;
}
#new-task input:focus {
outline: none;
border-color: violet;
}
#new-task button {
font-family: 'Manrope', sans-seif;
position: relative;
float: right;
width: 25%;
height: 45px;
border-radius: 5px;
font-weight: bold;
font-size: 16px;
border: none;
background-color: violet;
color: white;
cursor: pointer;
}
#tasks {
background-color: white;
padding: 30px 20px;
margin-top: 50px;
border-radius: 10px;
width: 100%;
}
.task {
background-color: white;
height: 50px;
padding: 5px 10px;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 2px solid violet;
cursor: pointer;
}
.task span {
font-size: 18px;
font-weight: 400;
}
.task button {
background-color: violet;
color: white;
height: 100%;
width: 40px;
border: none;
border-radius: 5px;
outline: none;
cursor: pointer;
}
.task button:hover {
background-color: red;
}
.completed {
text-decoration: line-through;
}
<body>
<div class="container">
<div id="new-task">
<input type="text" name="" id="taskInput" placeholder="Task to be done" />
<button id="push">ADD</button>
</div>
<div id="tasks"></div>
</div>
<script src="/script.js"></script>
</body>
querySelectorAll will return the list of nodes matching the selector tasks. So you have to iterate through each of those nodes and add your listener. See the below code snippet
let theTasks = document.querySelectorAll(".task");
theTasks.forEach((task) => {
task.addEventListener("click", function() {
this.classList.toggle("completed");
});
});
theTask is a list of nodes. Trying to attach event listener on this list is causing issues.
Also, you will be inserting lots of buttons with same id deleteButton and spans with same id taskname which is incorrect and can cause undefined behavior.
For theTask fix, you may want to do something like:
let theTasks = [...document.querySelectorAll(".task")];
theTasks.forEach(task => {
task.addEventListener("click", function() {
this.classList.toggle("completed");
})
});
Using innerHTML to create manipulate the DOM for an application like a todo list is probably not a good idea. The answers to Advantages of createElement over innerHTML? give good explanations why.
It is worth noting that in the innerHTML code, the span and the button are created with an id and so all of these elements will have the same id. It is also probably not a good idea to have duplicate ids on one page. Why are duplicate ID values not allowed in HTML? explains why.
Also, adding event listeners to every new task is also probably not a good idea. What is DOM Event delegation? gives a good explanation why.
Finally, the Difference between HTMLCollection, NodeLists, and arrays of objects and Document.querySelectorAll() explain how to get lists of elements that can be manipulated.
So, I have rewritten the task creation code in the addBtn.addEventListener to show one way how this could be done with document.createElement().
And I have created a separate event listener on the Tasks container div, which handles both task deletion and task completion.
I also added the following CSS so that clicking on a trash can icon is handled by the parent button. Without this CSS, clicking on an icon would not delete the task.
div#tasks i {
pointer-events: none;
}
To make the todo list more visible in the code snippet below, I reduced the heights, margins, and paddings of some of the elements in the CSS.
I also added a link to the font awesome icon library.
const addBtn = document.querySelector("#push");
const taskInput = document.querySelector("#taskInput");
const taskOutput = document.querySelector("#tasks");
taskOutput.addEventListener("click", function(event) {
if (event.target && event.target.nodeName === "SPAN") {
event.target.classList.toggle("completed");
}
if (event.target && event.target.nodeName === "BUTTON") {
event.target.parentNode.remove();
}
});
addBtn.addEventListener("click", function() {
let newTasks = taskInput.value;
if (newTasks.length == 0) {
alert("Please enter a task");
} else {
// Create a task DIV
const newTaskElement = document.createElement("div");
newTaskElement.classList.add("task");
// Create a SPAN with the task name
const newTaskNameElement = document.createElement("span");
const taskTextnode = document.createTextNode(newTasks);
newTaskNameElement.appendChild(taskTextnode);
// Create a BUTTON with a TRASH CAN ICON
const newTaskDeleteButton = document.createElement("button");
const deleteImageElement = document.createElement("i");
deleteImageElement.classList.add("fa-solid", "fa-trash");
newTaskDeleteButton.appendChild(deleteImageElement);
// Append the SPAN and the BUTTON to the task DIV
newTaskElement.appendChild(newTaskNameElement);
newTaskElement.appendChild(newTaskDeleteButton);
// Append the task DIV to the TASK LIST DIV
taskOutput.appendChild(newTaskElement);
}
});
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
height: 100vh;
background: linear-gradient( 90deg, rgba(241, 206, 221, 1) 0%, rgba(124, 184, 254, 1) 100%);
font-family: 'Kumbh Sans', sans-serif;
}
/* ADDED TO MAKE SURE THAT THE TRASH ICON DOES NOT PROCESS CLICKS */
div#tasks i {
pointer-events: none;
}
.container {
border: 2px solid white;
width: 50%;
min-width: 450px;
margin: auto;
padding: 3px 4px;
}
#new-task {
position: relative;
background-color: white;
padding: 6px 4px;
border-radius: 1em;
}
#new-task input {
width: 70%;
height: 45px;
font-family: 'Manrope', sans-seif;
font-size: 1.2em;
border: 2px solid #d1d3d4;
padding: 12px;
color: #111111;
font-weight: 500;
position: relative;
border-radius: 5px;
}
#new-task input:focus {
outline: none;
border-color: violet;
}
#new-task button {
font-family: 'Manrope', sans-seif;
position: relative;
float: right;
width: 25%;
height: 45px;
border-radius: 5px;
font-weight: bold;
font-size: 16px;
border: none;
background-color: violet;
color: white;
cursor: pointer;
}
#tasks {
background-color: white;
padding: 6px 4px;
margin-top: 5px;
border-radius: 10px;
width: 100%;
min-height: 50px;
}
.task {
background-color: white;
height: 50px;
padding: 5px 10px;
margin-top: 10px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 2px solid violet;
cursor: pointer;
}
.task span {
font-size: 18px;
font-weight: 400;
}
.task button {
background-color: violet;
color: white;
height: 100%;
width: 40px;
border: none;
border-radius: 5px;
outline: none;
cursor: pointer;
}
.task button:hover {
background-color: red;
}
.completed {
text-decoration: line-through;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.3.0/css/all.min.css" rel="stylesheet" />
<div class="container">
<div id="new-task">
<input type="text" name="" id="taskInput" placeholder="Task to be done" />
<button id="push">ADD</button>
</div>
<div id="tasks"></div>
</div>
I am working on a chatbot at the moment and trying to connect a GUI I have been working with to the project.
It is running smooth but my output is a little messed up; in particular, the chat boxes should alternate between the user and the BOT, but they are stacking on top and not formatting correctly.
I want to fix this issue, but keep the screen dividing in half down the middle so that the bot outputs are on the right and the users on the left. I just need to get them to alternate back and forth.
I've tried anchoring the newest box with a margin-top, tried setting a counter variable to update the placement of each new box, etc., but am having trouble spacing them relative to each other.
Below is the code without the backend work. So, this won't run perfect but it should get the setup I have across...
Here is the CSS code:
body {
font-family: Cambria;
color: rgb(122, 4, 4);
background-color: rgb(136, 175, 175);
}
h1 {
color: black;
margin-bottom: 0;
margin-top: 0;
text-align: center;
font-size: 40px;
}
h2 {
color: black;
font-size: 20px;
margin-top: 3px;
text-align: center;
}
#user_chatbox {
margin-left: 0;
margin-right: auto;
width: 50%;
margin-top: 30%;
}
#bot_chatbox {
margin-left: 50%;
margin-right: auto;
width: 50%;
margin-top: 10%;
/* height: 80%; */
/* background-color: pink; */
/* border-radius: 10px; */
}
#userInput {
margin-left: auto;
margin-right: auto;
width: 95%;
margin-top: 150px;
}
#textInput {
width: 92%;
border: 3px solid Black;
border-bottom: 3px solid #660096;
font-family: Cambria;
font-size: 16px;
}
#buttonInput {
padding: 10px;
font-family: Cambria;
font-size: 72;
}
.userText {
color: rgb(0, 0, 0);
font-family: Georgia;
font-size: 16px;
text-align: left;
line-height: 20px;
}
.userText span {
display:block;
width:auto;
background-color: rgb(87, 201, 152);
padding: 10px;
border-radius: 10px;
/* counter-increment: var(--chatbox_spacing); */
}
.botText {
color: Black;
font-family: Consolas, monaco, monospace;
font-size: 16px;
text-align: left;
/* line-height: calc(29 + var(--chatbox_spacing))px; */
line-height: 20px;
}
.botText span {
display:block;
width:auto;
background-color: rgb(73,196,199);
padding: 10px;
border-radius: 10px;
/* counter-increment: var(--chatbox_spacing); */
}
... and here are the .html with .js code (within index.html) that is updating the blocks to be printed out with new information (input from the user and a reply from the bot):
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="/static/style.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<h1>Analysis Chatbot</h1>
<!-- The main chat environment for interacting with the bot. -->
<div>
<!-- The text of the bot. -->
<div id="bot_chatbox">
<p class="botText"><span>Welcome! How can I help you analyze your dataset?</span></p>
</div>
<div id="user_chatbox"></div>
<!-- The input text of the user interacting with the bot. -->
<div id="userInput">
<input id="textInput" type="text" name="msg" placeholder="Message">
<input id="buttonInput" type="submit" value="Send">
</div>
<script>
function getBotResponse() {
var rawText = $("#textInput").val();
var userHtml = '<p class="userText"><span>' + rawText + '</span></p>';
$("#textInput").val("");
$("#user_chatbox").append(userHtml);
document.getElementById('userInput').scrollIntoView({block: 'start', behavior: 'smooth'});
$.get("/get", { msg: rawText }).done(function(data) {
var botHtml = '<p class="botText"><span>' + data + '</span></p>';
$("#bot_chatbox").append(botHtml);
document.getElementById('userInput').scrollIntoView({block: 'start', behavior: 'smooth'});
});
}
$("#textInput").keypress(function(e) {
if(e.which == 13) {
getBotResponse();
}
});
$("#buttonInput").click(function() {
getBotResponse();
})
</script>
</div>
</body>
</html>
Nothing breaks, but I have attached some images below of the current output. Again, it isn't as much that the replies are basic right now, but rather that I want the displayed text blobs to be alternating from the bot (right side) to the user (left side) while keeping the screen split in the middle.
I want that image to be: the top blue on the right (Welcome...) then the first green on the left (can you find me sales in...) then next blue on right and so on so forth...
I put together a basic example of what you're trying to do using a 100% width wrapper that holds the message inside. The wrapper has display:flex; so that the <div>s inside don't expand. Check it out:
$(document).ready(function() {
$('#sendUser').click(function(){
if($('#userText').val()!=""){
$('#chatbox').append('<div class="message user"><div>'+$('#userText').val()+'</div></div>');
$('#userText').val('');
}
});
$('#sendBot').click(function(){
if($('#userText').val()!=""){
$('#chatbox').append('<div class="message bot"><div>'+$('#userText').val()+'</div></div>');
$('#userText').val('');
}
});
});
#chatbox{
width: 300px;
height: 400px;
border: 1px solid black;
margin: auto;
margin-top: 20px;
overflow-y: scroll;
}
#inputs{
display: grid;
padding: 10px 0;
width: 300px;
margin: auto;
grid-template-columns: auto 40px 40px;
grid-gap: 4px;
}
.button{
text-align: center;
border: 1px solid #a0a0a0;
cursor: pointer;
}
.button:hover{
background-color: grey;
color: white;
}
.message{
display: flex;
}
.message.user{
text-align: left;
}
.message > div{
margin: 10px 10px 0;
padding: 6px 8px;
border-radius: 15px;
color: white;
}
.message.bot > div{
margin-left: auto;
background-color: teal;
}
.message.user > div{
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="chatbox">
<div class="message bot">
<div>
hello
</div>
</div>
<div class="message user">
<div>
hello!
</div>
</div>
</div>
<div id="inputs">
<input type="text" id="userText">
<div class="button" id="sendBot">Bot</div>
<div class="button" id="sendUser">User</div>
</div>
Here's the CodePen if you wanted to mess with it.
The file upload field is controlled by the browser so that one should automatically be translated based on the browsers settings. I need set my language on this button. How I can do that?
I've found solution on sitepoint. Just below .file-resume on your file input name and then modify your button.
/* Style wrapping span as button */
span.wpcf7-form-control-wrap.file-resume {//FILE-REsume == your name of file input
display: inline-block;
position: relative;
width: 120px;
height: 40px;
border-radius: 5px;
border: solid 1px #11b28e;
background: gray;
color: #FFF;
overflow:hidden;
}
/* Made input big and move it left and top inside wrapper to hide actual control but leave input clickable */
input.wpcf7-form-control.wpcf7-file {
position: absolute;
width: 1500px;
height: 1000px;
right: 0;
bottom: 0;
outline: none !important;
}
/* Add button text */
.wpcf7-file:before {
content: "прикріпити файл";
display: block;
width: 120px;
height: 40px;
line-height: 40px;
text-align: center;
position: absolute;
right: 0;
bottom: 0;
color: #FFF;
font-size: 16px;
}
To change the text 'Select File' on the button I use the code below. And it works fine for me.
However, I can't change the text "No file chosen" next to the button.
Can anyone tell me something about this topic?
.wpcf7-file::-webkit-file-upload-button {
visibility: hidden;
}
.wpcf7-file::before {
content: 'Select File NEW';
display: inline-block;
background: #00a0dd !important;
padding: 15px 15px;
outline: none;
white-space: nowrap;
-webkit-user-select: none;
cursor: pointer;
font-weight: 700;
font-size: 10pt;
color:#FFF
}
.wpcf7-file:hover::before {
border-color: black;
}
.wpcf7-file:active::before {
background: -webkit-linear-gradient(top, #e3e3e3, #f9f9f9);
}
I am trying to change the UL image in the CSS folder using jQuery. This is for a Twitter stream, where the avatar of the account posting is changed alongside the tweet.
Using .css is pretty straight forward, but I am struggling to change the URL for the new image.
Here is my client code:
$(document).ready(function(){
var socket = io();
$('form').submit(function(){
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('info', function(data){
console.log("this is teh question" + " " + data);
$("#tweets").prepend("<li>" + data + "</li>");
});
socket.on('reply', function(data){
console.log("this is my reply" + " " + data);
$("#messages").prepend("<li>" + data + "</li>");
});
socket.on('userPic', function(data) {
console.log("the userPic: " + data);
$("ul#tweets").css("list-style-image: url", data);
});
});
And the CSS:
body {
font: 13px Helvetica, Arial;
max-width: 1250px;
width: 100%;
margin: auto;
}
form {
background: #fff;
padding: 10px;
width: calc(100% - 20px);
display: inline-block;
border-bottom: 1px solid #ccc;
}
form input {
border: 3px inset;
padding: 7px 5px;
width: calc(100% - 140px);
margin-right: 10px;
display: inline-block;
font-size: 15px;
}
form button {
width: 110px;
background: #177cc1;
color: #fff;
border-radius: 6px;
text-transform: uppercase;
font-size: 22px;
border: none;
padding: 5px 10px;
display: inline-block;
cursor: pointer;
}
form button:hover {
background: #177cee;
}
form button:active {
background: #177caa;
}
form button:focus {
outline: 0;
}
.container {
display: inline-block;
width: calc(100% - 60px);
padding: 20px;
margin: 5px 10px 20px;
background: #222;
}
.content {
display: inline-block;
width: 100%;
box-shadow: 1px 1px 1px 1px #555;
border: 1px solid #555;
}
.tweets_container {
display: inline-block;
width: 100%;
background: #fff;
}
.header {
font-size: 32px;
text-align: center;
text-transform: uppercase;
color: #fff;
background: #333;
padding: 15px;
}
#messages, #tweets {
display: inline-block;
margin: 5px;
padding: 10px;
width: calc(50% - 32px);
}
#tweets li, #messages li {
padding: 10px;
font-size: 18px;
}
#messages {
background: #444;
color: #fff;
}
ul#tweets {
list-style-image: url("");
height: 100px;
width: 100px;
}
ul#messages {
list-style-image: url("");
height: 100px;
width: 100px;
}
#tweets {
background: #fff;
color: #333;
}
.footer {
}
I believe this:
$("ul#tweets").css("list-style-image: url", data);
should be changed to:
$("ul#tweets").css("list-style-image", "url('"+data+"')");
Without looking at your nodejs and socket.io, check if socket.on('userPic', function(data) {, the userPic event is being fired. If so, check if the valid of data is valid for this scenario.
The way list-style-image works is that it requires a working url in a format of list-style-image:url(''), so your data argument needs to be a valid image path wrapped by parentheses as well as quotes.
Because css just deals with simple property value pairs, your JS will need to update the entire of the value in order to work. Here is an example, click on the image to see the change (I used background image for simplicity, there's no difference beyond the name of the property and the principle of providing a fully formed property value is demonstrated) ...
$('.image').css(
'background-image',
'url("http://lorempixel.com/400/200/sports/")'
);
You would use something like this to take a variable:
$('.image').css(
'background-image',
'url("' + data + '")'
);
This is the same as any other css property change. The whole value on the right needs to be updated in order for it to work. A similar problem people sometimes encounter is forgetting to add a unit to size value such as width and putting a number straight in:
.css('width', number); // wrong
.css('width', number + '%'); // right
So My code do when i click on name(class ='frnd'), then in result open one window and it is drag-able but when i again click on (class =frnd) then their open again new windows, for example if i click on Simon there popup new windows and after one click it is drag-able and than once more i click on name(class ='frnd' (Simon)) its popup one more window again. Problem: I dont want that if the window is already open, it wont open again same window Simon.
For avoid this problem i was trying this code in js
if(!($("#windows").hasClass('.5647383'+id))){
$html = '<div class="mwindow "><div class="hwindow 5647383'+id+'">'+usr+'<span class="cls">x</span></div><div class="msgbody '+id+'"><div id="mstd"class= umsg'+id+'></div><div id="tarea"><form method="post"><textarea class="ctarea" name="'+id+'"></textarea></form></div></div></div>';
$('#windows').append($html);
}
I don't know why isnt working thiscondition if($("#windows").hasClass('.5647383'+id)).
$(document).ready(function(){
$('.frnd').click(function(){
var id = $(this).attr("id");
var usr=$(this).text();
var exst = document.getElementsByClassName('.5647383'+id);
if($("#windows").hasClass('.5647383'+id)){
$html = '<div class="mwindow "><div class="hwindow 5647383'+id+'">'+usr+'<span class="cls">x</span></div><div class="msgbody '+id+'"><div id="mstd"class= umsg'+id+'></div><div id="tarea"><form method="post"><textarea class="ctarea" name="'+id+'"></textarea></form></div></div></div>';
$('#windows').append($html);
}
});
$('#windows').on('click','.cls', function(){
$(this).parent().parent().hide();
});
$(function(){
$('.frnd').click(function(){
var id = $(this).attr("id");
$('#windows').on('click','.'+id,function(){
$(this).parent().draggable({
handle: ".hwindow",
containment:"body"
});
});
});
});
});
body {
margin: 0;
background-color: #999;
height: 700px;
}
.frnd {
text-align: center;
width: 50px;
height: 20px;
display: inline-block;
background-color: #9B59B6;
margin: 5px;
border: 4px solid #3498DB;
color: #F1C40F;
cursor: pointer;
float: right;
}
.mwindow {
position: fixed;
width: 220px;
height: 220px;
border: 5px solid #16a085;
background-color: #fff;
display: block;
margin: 5px;
border-radius: 10px;
}
.mwindow:hover {
z-index: 9999;
}
.hwindow {
width: 210px;
height: 25px;
background-color: #FF4500;
padding: 5px;
display: block;
margin: 0px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
}
.cls {
display: inline-block;
float: right;
cursor: pointer;
font-size: 20px;
font-weight: bold;
}
.msgbody {
position: relative;
height: 185px;
background-color: #FF4500;
//z-index:9999;
}
.ctarea {
position: absolute;
width: 210px;
resize: none;
outline: none;
top: 133px;
font-size: 15px;
padding: 5px;
min-height: 40px;
opacity: 0.9;
border: none;
border-top: 2px solid #ff0000;
}
#mstd {
position: absolute;
width: 220px;
height: 133px;
background-color: #bb4500;
opacity: 1;
overflow-x: hidden;
}
<script src="//code.jquery.com/jquery-2.1.4.js"></script>
<script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>
<li id="7" class="frnd">Maxi</li>
<li id="8" class="frnd">John</li>
<li id="9" class="frnd">Henry</li>
<li id="10" class="frnd">Max</li>
<li id="11" class="frnd">Simon</li>
<div id="windows"></div>
Elements by their ID attribute are selected using the hashmark symbol, so
'.' + id should be '#' + id.
The dot symbol (.) selects elements by their class name.
http://codepen.io/anon/pen/qdaXgX
EDIT
You had a number of other problems, look at the reviewed code:
http://codepen.io/anon/pen/bdwaWx
The problem is hasClass() doesn’t use a period prefix for classes — that’s selector syntax. So:
var hwindow_div = $('.5647383'+id) will find your .hwindow div,
hwindow_div.hasClass('5647383'+id) checks whether it has the class.
A simple example.
PS. while it’s a separate problem, #marekful is correct about the #id syntax.