on keypress, dynamic added tabs? - javascript

I've got some troubles with this code.
$('body').on("keypress", ".message", function(e) {
if ( e.keyCode == 13 && $(".message").val().length > 0 ) {
input = $(".message");
// Check for join command.
if (input.val().substr(0, 5) == "/join") {
// Get channel
channel = input.val().substr(7, input.val().length);
// APPEND NEW TAB
$("ul.nav-tabs li").after('<li><a href="#' + channel + '" aria-controls="#' + channel + '" role="tab" data-toggle="tab">#' + channel + '</li>');
$('.tab-content').append('<li class="tab-pane log" role="tab-pane" id="' + channel + '" data-channel="' + channel + '"><div class="Topic">Hej och välkommen till #' + channel + '.</div><ul class="Messages"></ul><input type="text" name="message" id="message" autocomplete="off" class="message sendValue"></li>');
$(".nav-tabs li").children('a').last().click();
}
log('<strong>Du</strong>: ' + input.val());
send( input.val() );
$(".message").val('');
}
});
The keypress event doesn't react on the dynamically added input, I read something about adding the on event after added, because of that this code runs when the dom is loaded.
So my question is: how can I make this so the dynamic inputs works aswell?

You're already using .on so I think it is working properly and that your real problem is this:
input = $(".message");
which you need to change to this:
var input = $(this);
otherwise you'll always be dealing with the first input even if there's multiple on the page. Also you can use inspect element > console to debug these problems easier. For example if you add:
$('body').on("keypress", ".message", function(e) { console.log(e);
to your script you would have seen that the event handler is working fine and that your problem was further down.
(also change $(".message").val(''); to input.val('');)

Related

How to use jQuery to change attributes of a newly created element

I have the following code:
if (secsleft < 10) {
var msg = 'No activity detected in the last 10 seconds.';
if (auth == "true"){
msg += '<br />You will be logged out in <br /><p id="counter">' + secsleft + '</p><br /> more seconds if no activity is detected.';
} else {
msg += '<br />You will be redirected in <br /><p id="counter">' + secsleft + '</p><br /> more seconds if no activity is detected.';
}
if (secsleft < 4) {
//$("#counter").css({"color":"red"});
//$("#counter").css("color", "red");
document.getElementById("counter").style.color = "red";
}
Message('<span id="timer">' + msg + '</span>', 10000);
}
The intent obviously is to change the color of the counter to red when less than four seconds are left. The problem is that the p tag with id="counter" is first created in the IF statement. If I was looking to bind an event to it, I know how to do it. It would be something like:
$(document).on(eventName, "#counter", function() {});
But that doesn't work for attributes. I have tried all kinds of combinations as you can see from the commented code in the inner IF, but none work. Incidentally (and surprisingly to me), I can get the attribute easily, so for example:
alert($("#counter").css("color"));
gives me the right value. So, how does one change the value?
The issue is that you're not actually creating the element until after that if statement, so all of your jQuery selectors and getElementById calls will not find anything on the page since there is nothing with an id of "counter" yet. You've simply made a string that you will later convert into an actual element.
What you need to do is create an actual element and then using a reference to it you can change its attributes before you even put it on the page.
var counter = document.createElement('p');
counter.id = 'counter';
counter.style.color = red;
Or something along those lines. I've shown you the vanilla JS solution here but you can do the same using jQuery:
var counter = $('<p></p>');
counter.attr('id','counter');
counter.css('color','red');
I don't see much jQuery but you did add it as a tag. So why not do something like this?
$("body").find("#counter").css("color", "red");
You can't use document.getElementById() for elements which have not yet been added to the document. That's why it doesn't work.
You could simplify your code a lot.
if (secsleft < 10) {
var color = secsleft < 4 ? 'red' : 'inherit';
var action = auth === 'true' ? 'logged out' : 'redirected';
var msg = 'No activity detected in the last 10 seconds.'
+ '<br />You will be '+ action +' in '
+ '<span style="color: '+ color +'">' + secsleft + '</span>'
+ ' more seconds if no activity is detected.';
Message('<span id="timer">' + msg + '</span>', 10000);
}
I think there is a neater way to achieve what you are looking for rather can adding in the styles using jQuery. Instead it is better to allow your CSS to handle the styles and the jQuery to add in classes where appropriate.
In the below code the <4 check is used to assign a value to a counterClass variable which is then added to you counter element. You can then add a css rule to achieve the red colour.
if (secsleft < 10) {
var counterClass = "";
if (secsleft < 4) {
counterClass = "warning";
}
var msg = 'No activity detected in the last 10 seconds.';
if (auth == "true") {
msg += '<br />You will be logged out in <br />p id="counter" class="' + counterClass + '">' + secsleft + '</p><br /> more seconds if no activity is detected.';
} else {
msg += '<br />You will be redirected in <br /><p id="counter" class="' + counterClass + '">' + secsleft + '</p><br /> more seconds if no activity is detected.';
}
Message('<span id="timer">' + msg + '</span>', 10000);
}
Hope this helps.
The first problem is that you haven't yet added the #counter element to the document, meaning you can't use the document.getElementByID(...); method on it (yet).
To be able to manipulate a element, you would have to add it to the document, to do this you would use:
// appends the new "div" element to the body (I.E: inserts the new element at the end of the body)
$("body").append("<div id='element-id'>Hello World!</div>");
You could also use these methods:
// replaces the "innerHTML" of the "body" element with the new "div" element
$("body").html("<div id='element-id'>Hello World!</div>");
// prepends the new div to the body (I.E: inserts the element as the first child not the last child)
$("body").prepend("<div id='element-id'>Hello World!</div>");
Now, the second problem is that you are getting the value of the CSS property and NOT setting it.
To get the current value of a CSS property you would use this:
$("#element-id").css("property-name")
To change the value of a CSS attribute in jQuery you would use this:
// listen for an event to occur
$(document).on("event-name", function() {
// change a single property of the element
$("#element-id").css("property", "new-value");
});
You could also change multiple properties of the element at once, using a JavaScript object like this:
// listen for an event to occur
$(document).on("event-name", function() {
// change multiple properties of the element using a JavaScript object
$("#element-id").css({
"property-name-one": "new-value",
"property-name-two": "new-value"
});
});
For more information on the jQuery methods mentioned above, visit the links below:
jQuery.fn.html(...);.
jQuery.fn.append(...);.
jQuery.fn.prepend(...);.
jQuery.fn.on(...);.
jQuery.fn.css(...);.
Hope this helps, good luck and all the best.
You will not get element using getElementById which have not yet been added to DOM. you can use inline styles.
if (secsleft < 10) {
var alertColor = "inherit";
if(secsleft < 4) {
alertColor = "red";
}
var msg = 'No activity detected in the last 10 seconds.';
if (auth == "true"){
msg += '<br />You will be logged out in <br /><p id="counter" style="' + alertColor + '">' + secsleft + '</p><br /> more seconds if no activity is detected.';
} else {
msg += '<br />You will be redirected in <br /><p id="counter" style="' + alertColor + '">' + secsleft + '</p><br /> more seconds if no activity is detected.';
}
Message('<span id="timer">' + msg + '</span>', 10000);
}

Textarea value remain the same after submitting a form

My previous problem has been fixed, now I need to ask how to keep a textarea from resetting its input after a form is submitted. Here is the jsFiddle: http://jsfiddle.net/rz4pnumy/
Should I change the form in the HTML?
<form id="form1" method="GET">
(the form does not go into a php file or anything else, i'm using it to submit the textarea input and use the variables I made using jQuery to make a paragraph on the same page)
or something in the JS?
$(document).ready( function () {
$('#form1').on('submit', function (event) {
// If the form validation returns false, block the form from submitting by
// preventing the event's default behaviour from executing.
if (!validate()) {
event.preventDefault();
}
if(validate()) {
var adjective1 = $('#adjective1').val();
var adjective2 = $('#adjective2').val();
var pluralnoun = $('#plural-noun').val();
var verb1 = $('#verb1').val();
var edibleobject = $('#edible-object').val();
var monster1 = $('#monster1').val();
var adjective3 = $('#adjective3').val();
var monster2 = $('#monster2').val();
var verb2 = $('#verb2').val();
$('body').append(
'<div id="para">' +
'<p>Rain was still lashing the windows, which were now ' + adjective1 +', but inside all looked bright and cheerful. ' +
'The firelight glowed over the countless ' + adjective2 + '' + pluralnoun + ' where people sat ' + verb1 + ', talking, ' +
'doing homework or, in the case of Fred and George Weasley, trying to find out what would happen if you fed a ' + edibleobject +' to a ' + monster1 + '.' +
'Fred had "rescued" the ' + adjective3 + ', fire-dwelling ' + monster2 + ' from a Care of Magical Creatures class and it was now ' + verb2 + ' gently ' +
'on a table surrounded by a knot of curious people. </p>' +
'</div>'
);
}
});
function validate() {
var success = true;
$('.input').each(function(i, item) {
if ($(item).val() === "")
{
console.log("Missing textarea input");
success = false;
$(item).attr("style","border:1px solid red;");
//note it will overwrite your element style in all Input class
}
else
{
$(item).removeAttr('style')
// to remove border
}
});
return success;
}
});
The contents get emptied after pressing submit and I only see the completed paragraph for a split second.
You need to prevent the default event handler from executing whether validate passes or not, so you need to remove the if statement around the event.preventDefault() call. The preventDefault is the function that is keeping the from from submitting and re-loading your page.
Also, your Fiddle was not set to jQuery (it was set to no-library) so that may have also been causing you issues during your testing.
Edited for example of what I'm talking about:
$('#form1').on('submit', function (event) {
// block the form from submitting by
// preventing the event's default behaviour from executing.
event.preventDefault();
if(validate()) {
var adjective1 = $('#adjective1').val();
var adjective2 = $('#adjective2').val();
var pluralnoun = $('#plural-noun').val();
... etc ...
I would use php and set a variable to the GET value of the textarea and set the value of the textarea to that variable

Dynamic function call only works when an alert() is given

I have a Javascript problem that I cannot find the answer to. Hope you can help me.
I have this element called 'scanValue', that has an onFocus and an onBlur trigger:
<input name="scanValue" class="searchFormText" style="width: 220px; font-size: 22px;" onfocus="onFocusElement(this)" onblur="onBlurElement(this)" type="text" maxLength="20" value="510210006823414"/>
If I tab out of the field the onBlurElement() function is called as expected:
function onBlurElement(object) {
alert('onBlurElement: Start blur on ' + object.name + ' (old val = ' + prevObjectVal + ', new val = ' + object.value + ')');
if (object.value !== prevObjectVal) {
check(object);
var checkFcn = 'check' + object.name;
var fcnParms = [object.value];
var fcn = window[checkFcn];
alert('onBlurElement: check if ' + checkFcn + ' is a function: ' + (typeof fcn));
if (typeof fcn == 'function') {
alert('fcnParms length = ' + fcnParms.length + '. ToString= ' + fcnParms.toString());
alert('fcnParms[0] length = ' + fcnParms[0].length + '. ToString= ' + fcnParms.toString());
fcn.apply(fcn, fcnParms);
}
}
}
Now this dynamic function call (fcn.apply()) should call the function 'checkscanValue(val)', but nothing happens. EXCEPT when I add an alert() to this function OR if I fire up the IE standard developer tools. In other words, if I track or debug the checkscanValue() function everything works, otherwise is does nothing. I've tried several different things, but nothing seems to work. I doubt this could have anything to do with the form being submitted with method post, but maybe someone could help me on that.
Code for the checkscanValue() function:
function checkscanValue(val) {
console.info('checkscanValue: start function');
document.forms[0].airNumber.value = 'test';
// Check if the scanned value is valid for submitting the form
if (val[0].length === 15) {
document.forms[0].submit();
}
}
Everything is working fine except that the "val" parameter that you are passing to the checkscanvalue function is the string that the user entered or is there by default.
So val[0] returns the first character of the string whose length can't be 15 and hence the check fails and nothing happens.
hope it helps!
This seems to answer my question: 'console' is undefined error for Internet Explorer
I've been using the function console.info() which is undefined if the console window of IE was never opened. This caused the function to stop. If I replaced it with an alert() it obviously worked and if I opened the console of IE, the console.info function was defined.

Onclick event are not working properly

on click event in node.js is not working but simple text input work.i want that when you click on buttons( in my case two buttons) the two different event happen but it does not work. these two different events are append DOM within page. one of the button have value 'X' and other one have 'O' and i want to just append DOM with button's value. How can i do that?
this is code--->
my script is-
$(function() {
var socket = io.connect(window.location.href);
socket.on('message:server', function(data) {
$("#messages").append(
'<li style="color:red">' +
data.message + ' - ' + 'received' + ' ' + new Date() +
'</li>'
);
});
$("#message_form").on('submit', function(event) {
event.preventDefault();
var $input = $('[name="message"]')
var message = $input.val();
if (message) {
socket.emit('message:client', {message: message});
}
$("#messages").append(
'<li style="color:green">' +
message + ' - ' + 'sent' + ' ' + new Date() +
'</li>'
);
$input.val('');
});
socket.on('error', function() {
console.error(arguments)
});
});
in Body tag-
<form id="message_form" method="post">
<input name="message" placeholder="Message to send" type="text"/>
<button type="submit">Submit</button>
</form>
here at bottom in place of form i want 2 buttons which can operate this with default given fix value.
What about creating two buttons in the DOM and calling .on('click', function(){}) instead of submit ?
Like :
<button id="value1">Send value 1</button>
<button id="value2">Send value 2</button>
Then you simply set the function on click event. I added comments to your code to show what you can remove :
$("#value1").on('click', function(event) {
event.preventDefault();
// var $input = $('[name="message"]');
// You don't need fix since you send "fixed" value
var message = "Value 1" // Or whatever you want instead of $input.val();
// if (message) {
// No need of condition since you set the value
socket.emit('message:client', {message: message});
// }
$("#messages").append(
'<li style="color:green">' +
message + ' - ' + 'sent' + ' ' + new Date() +
'</li>'
);
// $input.val('');
});
You simply do the same for your button 2.
For this example, you would call :
$('#value2').on('click', function(){
// Same as value with another message value
});

JQuery list, prevent a link to be clicked more than once

I've been trying to figure this one out for a while now. I have a JQuery list populated using a JSon array.
Every item in the list is clickable and brings to a page called details with specific details for the item clicked.
Everything works fine, but if the user clicks several times on an item link, the page will be correctly loaded but it's gonna take several clicks on the back button to get back to the original page. Let's say the user clicks 3 times an item, when he wants to go back, he will have to hit back 3 times.
So I'm looking for a way to disable the link after it's been clicked once.
How could I accomplish that ?
Large code sample below, please tell me if my question is unclear. Thanks !
var items = [];
$.each(catalog.products,
function(index, value) {
if (
((!filterValue ) || value.name.toUpperCase().indexOf(filterValue.toUpperCase()) != -1)
&& ((!brand) || value.brand.toUpperCase().indexOf(brand.toUpperCase()) != -1)
&& ((!category) || value.category.toUpperCase().indexOf(category.toUpperCase()) != -1)
&& ((!sport) || value.sport.toUpperCase().indexOf(sport.toUpperCase()) != -1)
) {
var priceInfo;
if(value.salePrice === '') {
priceInfo = '<h4 style="margin-top:3px;margin-bottom:0px;color:#75a8db "> $' + value.price + '</h4></a></li>';
} else {
priceInfo = '<h4 style="margin-top:3px;margin-bottom:0px; "><span style="text-decoration: line-through;font-size:small;">$' + value.price +
'</span><span style="color:#75a8db;"> $' + value.salePrice + '</span></h4></a></li>';
}
items.push('<li id="' + index + '">' +
'<a data-identity="productId" href="./details.page?productId=' + index + '" >' +
'<img class="ui-li-thumb" src="' + value.thumbnail + '"/>' +
'<p style="margin-bottom:0px;margin-top:0px;">' + value.brand + '</p>' +
'<h3 style="margin-top:0px;margin-bottom:0px;">' + value.name + '</h3>' +
priceInfo);
}}
);
if (items.length === 0) {
items.push('<p style="text-align: left;margin-left: 10px">No results found.</p>');
}
productListView.html(items.join(''));
productListView.listview('refresh');
}
If you build your link as an object instead of just text, you can then bind to the click handler as you build it like this:
// here's the click handler you need
itemLink.click(function(e) {
console.log("item clicked");
if ($(this).data("clickCount") > 0) {
console.log("click count reached");
return false;
}
console.log("following the link");
// set a click counter
$(this).data("clickCount", 1);
// store the original href in case you need it
$(this).data("ogHref", $(this).attr("href"));
$(this).attr("href", "javascript://");
});
JSFiddle
In the fiddle I have used your code as much as I can, but instead created the markup using jQuery objects.
You can use jQuery's one() to implement this once-only action, for example:
$('a').one('click',
function(){
alert('hi!');
return false;
});
JS Fiddle demo.
Or, without using one(), you could simply unbind the click() event from the element:
$('a').click(
function(){
alert('hi!');
$(this).unbind('click');
return false;
});
JS Fiddle demo.
References:
one().
unbind().
var currentValue="";
$('a').click(function(event) {
event.preventDefault();
if(currentValue != $(this).attr("href")){
currentValue = $(this).attr("href");
// Your actions here
}
});
Thus, the link just dies when its action is the latest, but can be reused. jsFiddle test.

Categories

Resources