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

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);
}

Related

on keypress, dynamic added tabs?

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('');)

Getting the id of an html on mouseover with only javascript (no jquery)

My question is this, if I have an Text html element that looks like...
<a id='1' onmouseover="changeImage('setname/setnumber')">Cardname</a>
Can I retrieve the id (in this case 1) on a mouseover event so that I may use it in javascript to do something else with it.
Not sure if I can do this, but I'm hoping I can. What I have is a bit of javascript code that is taking data from an xml document. I have a list of 500+ cards that I have parsed through and stored by categories that are used often. Here are the relevant functions as they apply to my question.
var Card = function Card(cardName, subTitle, set, number, rarity, promo, node)
{
this.cardName = cardName;
this.subTitle = subTitle;
this.set = set;
this.number = number;
this.rarity = rarity;
this.promo = promo;
this.node = node;
}
Where node is the position within the list of cards, and due to the formatting of the document which I started with contains each card alphabetically by name, rather than numbered logically within sets.
Card.prototype.toLink = function()
{
var txt = "";
this.number;
if (this.promo == 'false')
{
var image = this.set.replace(/ /g, "_") + '/' + this.number;
txt += "<a id='" + this.node + "' onmouseover=changeImage('" + image + "')>";
txt += this.toString() + "</" + "a>";
}
else
{
var image = this.set.replace(/ /g, "_") + '/' + this.rarity + this.number;
var txt = "";
txt += "<a id='" + this.node + "' onmouseover=changeImage('" + image + ')>";
txt += this.toString() + "</a>";
}
return txt;
}
Here is what I am using to populate a list of cards, with names that upon hovering over will display a card image.
function populateList () {
for (i = 0; i<cards.length; i++)
document.getElementById('myList').innerHTML += '<li>'+cards[i].toLink()+</li>;
}
What I am trying to do is retrieve the id of the element with the onmouseover event so that I can retrieve everything that is not being saved to a value.
I realized I can pass the id as part of the changeImage function as a temporary workaround, though it involves rewriting my toLink function and my changeImage function to include a second argument. As a married man, I've enough arguments already and could do with one less per card.
In summary, and I suppose all I needed to ask was this, but is there a way using only javascript and html to retrieve the id of an element, onmouseover, so that I may use it in a function. If you've gotten through my wall of text and code I thank you in advance and would appreciate any insights into my problem.
if I have an Text html element that looks like...
<a id='1' onmouseover="changeImage('setname/setnumber')">Cardname</a>
Can I retrieve the id (in this case 1) on a mouseover event so that I may use it in javascript to do something else with it.
Yes, if you can change the link (and it looks like you can):
<a id='1' onmouseover="changeImage('setname/setnumber', this)">Cardname</a>
Note the new argument this. Within changeImage, you'd get the id like this:
function changeImage(foo, element) {
var id = element.id;
// ...
}
Looking at your code, you'd update this line of toLink:
txt += "<a id='" + this.node + "' onmouseover=changeImage('" + image + ', this)>";
Of course, you could also just put the id in directly:
txt += "<a id='" + this.node + "' onmouseover=changeImage('" + image + ', " + this.node + ")>";
And then changeImage would be:
function changeImage(foo, id) {
// ...
}
I didn't use quotes around it, as these IDs look like numbers. But if it's not reliably a number, use quotes:
txt += "<a id='" + this.node + "' onmouseover=changeImage('" + image + ', '" + this.node + "')>";

Jquery Javascript best way to check elements done appending

I have a list of elements that are dynamically appended after an Ajax call. I am using a plugin that creates a lightbox click event for the anchors dynamically appended. It works fine except sometimes it says that the title is undefined. I realize this is because the plugin gets initiated before the title attribute is completely done appending to the DOM. I know of several ways to do this, but what is the BEST way to check that all these elements are completely appended?
Ajax call is already made and data parsed with this function (colorbox title is the one that evaluates to 'undefined' for only some):
function pageImages(images,_q){
for(var i = 0; i < images.count; i++){
$('#pageImages').append('<div class="pageImageItem"><a href="' + images.data[i]._clickurl + '" title= "' + images.data[i]._title + '">\
<img src="' + images.data[i]._thumbnailUrl + '" alt= "' + images.data[i]._title + '"/>\
</a><div class="hoverInfo"><h2>' + images.data[i]._title + '</h2><p>' + limitCharacters(images.data[i]._clickurl,40) + '</p></div></div>');
}
$(".pageImageItem a").colorbox({maxWidth:'95%', maxHeight:'95%', title: function(){
var url = $(this).attr('href'),
title = $(this).attr('title');
console.log(title);
return '<h2>' + title + '</h2>' + limitCharacters(url,40) + '';
}});
}
And here is a picture of what is happening (anchor highlighted is the element that clearly has a title attribute but is showing undefined in lightbox):
You can wrap the jQuery element find block in a timeout without timevalue. The timeout will wait for all javascript to be finished with all processes. Example:
window.setTimeout(function() {
$(".pageImageItem a").colorbox({maxWidth:'95%', maxHeight:'95%', title: function(){
var url = $(this).attr('href'),
title = $(this).attr('title');
console.log(title);
return '<h2>' + title + '</h2>' + limitCharacters(url,40) + '';
}});
});

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.

Adding and removing elements in Javascript?

I'm trying to make a generator for a mod menu in Call of Duty. I want people to be able to add a menu or delete one. I'm trying to id the menus sequentially so that I can use the text field values correctly. I made it so that if they delete a menu it changes the ids of all the other menus to one lower and same for the button id, but I don't know how to change the onlick event to remove the right element.
Better yet, if there's a better way to do this, I would love to know it.
<script type="text/javascript">
y = 1
function test2()
{
document.getElementById("test2").innerHTML += "<div id=\"child" + y + "\"><input type=\"text\" value=\"menu name\" \><input id=\"button" + y + "\" type=\"button\" value=\"remove?\" onclick=\"test3(" + y + ")\" /></div>";
y++;
alert(y);
}
function test3(x)
{
document.getElementById("test2").removeChild(document.getElementById("child" + x));
for(var t = x+1;t < y;t++)
{
alert("t is " + t + ". And y is " + y);
document.getElementById("button" + t).setAttribute("onclick" , "test3(t-1)");
document.getElementById("button" + t).id = "button" + (t-1);
document.getElementById("child" + t).id = "child" + (t-1);
}
y--;
}
</script>
<input value="testing" type="button" onclick="test2()" />
<div id="test2" class="cfgcode"></div>
I wouldn't worry about re-indexing all of the elements after you add or remove one, that seems a waste. It would be better to simply write a more generic function, rather than one with the element id hard coded into it.
For example, your first function could be written as so:
function genericFunction(el)
{
var html = ''; // create any new html here
el.innerHTML = html;
}
You can then add onclick handlers such as:
myDiv.onclick = function() { genericFunction(this) };
I would also agree with all the commenters above, use jQuery, it makes any code which interacts with the DOM much much simpler.

Categories

Resources