I'm trying to set up a function to run 1.5 seconds after a keyup event in a textarea. But, if another keyup event occurs in the same area I'd like to either extend the time to 1.5 seconds again or cancel the old function and update it with the new function.
To make things even more interesting xD
There are multiple textarea, each has their own unique ID. I'd like for it to only cancel if the keyup event is from the same textarea.
Here is an example of what I've been trying to do.
$(document).on("keyup",".edit_main textarea",function(e){
location_val = //textareas unique ID
curval = $(this).val();
blue = "blue";
UNIQUE_VARIABLE = blue+location_val;
clearTimeout(UNIQUE_VARIABLE);
UNIQUE_VARIABLE = setTimeout(function(){
// do cool stuff
}, 1500);
});
This way it will only clear once, but it gets overwritten. So I tried using an array but I'm not sure that you can store a Timeout with that.
If my question is too vague, please say so and I will try to be more detailed.
For the timeout itself you would not need unique ids, you could use the .data() functionality of jQuery to have a unique timeouts for every element.
$(document).on("keyup",".edit_main textarea",function(e) {
var textArea = $(this);
var curval = textArea.val();
var blue = "blue";
clearTimeout( textArea.data().keyupTimeout );
textArea.data().keyupTimeout = setTimeout(function(){
// do cool stuff
textArea.val('the cool result');
}, 1500);
});
This is way more complicated than it needs to be. It seems you're having issues with scope. Have a look at the documented code solution below. Also, you can take a look at the jsFiddle as well. Hope this is helpful!
//This needs to be declared OUTSIDE the function.
var unique;
//No need to use $(document), target your textareas directly.
$('.edit_main textarea').on('keyup', function(e){
//$(this) doesn't work here. Use e (an argument for the event). e.target.id gets the textarea's id.
var location_val = e.target.id;
//e.target.id returns just the id.
//We need to prepend the CSS selector for jQuery to find the element.
var curval = $('#'+location_val).val();
//I don't see the point of blue = 'blue', so I omitted it.
//Clear the timeout first if any.
clearTimeout(unique);
//Set a new one.
unique = setTimeout(function(){
//Do something cool. Like telling you what's in the textarea.
alert(curval);
}, 1500);
});
Related
I have:
$elements = $('.elements');
$element = $('.element');
function appendText(element){
element.append('<em> appended text</em>');
}
appendText($element);
$('button').on('click', function(){
$elements.append('<span class="element">Span Element Appended after load</span>');
appendText($element);
});
The appendText function, after button click, appends only to the initial element and that is due to JS cache I presume.
I know that I can do appendText($('element')); and the problem will be solved, but I don't want to change all my code now.
Is there any way to make jQuery consider this $element variable as not a cached element and look into the full DOM each time I call that variable?
Please find the jsfiddle if you wish to play or understand better: http://jsfiddle.net/adyz/733Xd/
If you add this:
$element = $('.element:last-child')
before
appendText($element);
I think will solve your problem
jsFindle here: http://jsfiddle.net/733Xd/5/.
Best regards!
That is an expensive thing to do. I would advise against it for performance reasons.
I did this pluggin in the beggining of last year https://github.com/fmsf/jQuery-obj-update
It doesn't trigger on every call, you have to request the update yourself:
$element.update();
The code is small enough to be pasted on the answer:
(function ( $ ) {
$.fn.update = function(){
var newElements = $(this.selector),i;
for(i=0;i<newElements.length;i++){
this[i] = newElements[i];
}
for(;i<this.length;i++){
this[i] = undefined;
}
this.length = newElements.length;
return this;
};
})(jQuery);
I think below one will solve your problem
appendText($element); //here you always referring to the node which was there initial.
http://jsfiddle.net/s9udJ/
Possible Solution will be
$(function(){
$elements = $('.elements');
$element = $('.element');
function appendText(element){
element.append('<em> appended text</em>');
}
appendText($element);
$('button').on('click', function(){
$elements.append('<span class="element">Span Element Appended after load</span>');
appendText($elements.find('span').last());
});
})
I don't think what you're asking is easily possible - when you call $element = $('.element'); you define a variable which equals to set of objects (well, one object). When calling appendText($element); you're operating on that object. It's not a cache - it's just how JS (and other programming languages) works.
The only solution I can see is to have a function that will update the variable, every time jquery calls one of its DOM manipulation methods, along the lines of this:
<div class='a'></div>
$(document).ready(function()
{
var element = $('.a');
$.fn.appendUpdate = function(elem)
{
// ugly because this is an object
// also - not really taking account of multiple objects that are added here
// just making an example
if ($(elem).is(this.selector))
{
this[this.length] = $(this).append(elem).get(0);
this.length++;
}
return this;
}
element.appendUpdate("<div class='a'></div>");
console.log(element);
});
Then you can use sub() to roll out your own version of append = the above. This way your variables would be up to date, and you wouldn't really need to change your code. I also need to say that I shudder about the thing I've written (please, please, don't use it).
Fiddle
I see a lot of jQuery examples that do something like
var $element = $('#element');
$element.foo...
rather than just typing
$('#element').foo...
and I do realize there is a small bit of typing saved if you are working with
$element
a lot, but what about those times that
$element
is only called once or twice? Why do some developers declare it as a jQuery object variable in those instances? Is it also more efficient for the browser to process?
Usually this is done to avoid either re-wrapping an element or re-querying the page for the selector.
Such as in a click event
$('.className').click(function(){
var $this = $(this);
callSomeHelper($this);
$this.hide();
if( $this.data("placement") == "somePlacement" ){
//some logic
}
});
The real saver is when it is referencing a set of elements.
var $allSides = $('.side');
And now back in the click event, you can reference this without having to re-query
$('.top').click(function(){
var door = $allSides.find(':visible');
});
There are obviously more in depth examples, but these two are the main cases that the variable is stored.
It prevents from overwriting variable from another script
Good morning and happy new year everyone!
I've run into a snag on something and need to figure out a solution or an alternative, and I don't know how to approach this. I actually hope it's something easy; meaning one of you all have dealt with this already.
The problem is that I'm doing rollovers that contain information. They're divs that get moved to the absolute location. Now I've tried this with jquery 1.6 - 1.9.1. Of course this has to work in multiple browsers.
What needs to happen is on rollover show a div, and when you rollout of that div, make it hide.
...
// .columnItem is class level and works
$(".columnItem").mouseleave(function() {
$(this).css("display", "none");
});
...
$(".column").mouseenter(function() {
var currentItem = $(this)[0]; // this is where the problem is
// hide all .columnItems
$(".columnItem").css("display", "none");
// i get this error: Object #<HTMLDivElement> has no method 'offset' (viewing in chrome console)
var offsetTop = currentItem.offset().top;
var columnInfoPanel = $("#column" + currentItem.innerText);
});
So the immediate thought of some would be don't use $(this)[0]. Instead, I should use $(this), and you are correct! Where the other problem comes into play is by removing the array index, currentItem.innerText is now undefined.
The only thing I can think of is I'll have to mix both, but it seems like there should be a way to use the selector and get both options.
What have you all done?
Thanks,
Kelly
Replace:
var currentItem = $(this)[0];
With:
var currentItem = $(this).eq(0);
This creates a new jQuery object containing only the first element, so offset will work.
Then you can use either currentItem[0].innerText or currentItem.text(), whichever you prefer.
Skip the [0] at the beginning as you are saying.
But then change the last line to:
var columnInfoPanel = $("#column" + currentItem[0].innerText);
De-referencing the jQuery selector gives you the DOM-object.
If you want to stick to pure jQuery, the .text() / .html() methods will give you the same functionality.
This question already exists:
Closed 10 years ago.
Possible Duplicate:
Call same function by a cloned list row
I am trying to make a simple calculation to work.
I have the following running:
http://jsfiddle.net/vSyK6/41/
Basically, the way it works now is this:
When you select an option on the drop down list it will display the content based on the option selected. Then when you select the same option again it will add, basically clone the same row.
Now, when the second option is selected "Option2" it will display an empty textbox. When you enter a number it will or should call the a function where we make a basic calculation. The function is already in the script.
However, when we have two empty textboxes it should call the same calculation function but calculate seperately and puts it in a different div. The div# where we display the amount is a called "amount"
Basically, it should work like this:
First Empty textbox -> 100 -> 100 * 22.38 = display result in div#1
Second Empty textbox -> 230 -> 230 * 22.38 = display in div#2
any idea on how to accomplish that ?
When cloning elements the id is cloned as well. It is best practice to create a new ID for the cloned elements, which will also help in accomplishing what you want. The same goes for the name attribute as well.
With a few modification to your code, http://jsfiddle.net/dNQVQ/3/, I was able to get what you were after. Let me first say that this might not be the ideal way to go, but it is a start. Like I said earlier the key is going to be setting unique ids for the cloned elements. What I did in this example was use a index as part of the list element id that is cloned with a matching index in an 'amount' div. This way when an input is updated the index is retrieved and then used to update the appropriate div. Additionally, I moved the function that did the calculation and updates to an anonymous function in the settimeout call. This makes it easy to use a reference to the updated input in the function call.
Joining the party quite late here :) Here is one vernon: http://jsfiddle.net/KVPwm/
ALso if its assignment bruv, put an assignment homework tag!
People around SO community are awesome folks so be truthful, guys will help man!
Use .on instead of live - recommendation. i.e. upgrade your JQ source if keen read this - What's wrong with the jQuery live method?
you have 2 document.ready functions also I chained few things for you.
Also think of using isNan check as well.
Rest you can read the code and play around a bit to make it more concise.
I have added 2 divs and using the id number to populate the stuff accordingly.
This should fit the cause :)
code
$("document").ready(function() {
/////////////////////////////////CALUCATIONS/////////////////////////////////
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 0; //time in ms, 5 second for example
$('input[name=Input2], input[name=Input1]').live('keyup', function() {
var str = $(this).prop("id");
var pattern = /[0-9]+/g;
var matches = str.match(pattern);
amount = parseFloat($(this).val()) * 22.38;
typingTimer = setTimeout(doneTyping(matches), doneTypingInterval);
});
$('#Input2').keydown(function() {
clearTimeout(typingTimer);
});
function doneTyping(matches) {
$('#amount'+matches).text(amount.toFixed(2) + " lbs");
}
$("#List-Option1,#List-Option2").hide();
$('#category').change(function() {
var str = $('#category').val();
if (str == 'Option1') {
var option1 = $("#List-Option1:first").clone().show();
$('#box li:last').after(option1);
}
if (str == 'Option2') {
var option2 = $("#List-Option2:first").clone().show();
$('#box li:last').after(option2);
}
});
});
i need to set the unique numeric rel attributes for anchor elements in table with class "tdresult". Im trying to set them in the loop, but im not very good at Javascript and probably don't undestood loops.
$$('.tdresult').each(function(chooseClass) {
var ellen=chooseClass.getElements('a').length;
var eli=chooseClass.getElements('a').each(function(el){
for (i=0; i<ellen; i++){
var elic=el.set('rel',i++); //trying to set numeric ids for anchor els (from 0 to //max (ellen)
}
});
chooseClass.addEvent('mouseenter', function(el) {
infoGet(1,uniqueid); // function that sets the ajax request using unique id from loop
});
});
Can anyone advise me how to do this?
I'm not 100% sure I understand what you're doing, but it looks like you are:
Finding every a element inside each .tdresult element
adding a unique value to the rel attribute to each
adding a mouseenter event to each which uses that rel attribute
If you want to store a unique value, try store and retrieve:
var unique_id = 0;
$$('.tdresult a').each(function(el){
el.store('unique_id',unique_id);
el.addEvent('mouseenter', function(evt) {
infoGet(1,this.retrieve('unique_id'));
});
unique_id++;
});
Though it's possible I'm misunderstanding the task.
This should do what you want if I understand the Question correctly
var offset = 0;
$$('.tdresult').each(function(chooseClass) {
chooseClass.getElements('a').each(function(el){
el.set('rel',offset);
el.addEvent('mouseenter', function(uniqueid) {
return function() {
infoGet(1,uniqueid);
}
}(offset));
offset++
});
});
offset is incremented with the loop but is declared outside of it. Every time the loop runs, it will be the same offset variable being incremented. The loop that was there previously was not necessary.
One question though... why would you set the rel attribute to a number? see http://www.w3schools.com/TAGS/att_a_rel.asp for a list of valid values. Also note that none of the major browsers make use of this attribute anyways. (Epic fail on standards support for everyone)
EDIT
I noticed what you were trying to do with the event listener. I've modified the code to store the current offset in a closure with the event handler. The function in the event handler is immediately run with the current offset. Inside the function this is referred to as uniqueid. The function then returns the real event handler function but maintains use of the uniqueid variable (not offset, but the value of offset at the time the outer function was called).
This is much easier in mootools cause each gives you a counter and as your in a closure at the each loop you doent need to store the id. Check out in mooShell (activate console)
$$('td a').each(function(el, uId){
el.addEvent('mouseenter', function() {
infoGet(1, uId);
});
});