jQuery plugin scrollTo works only from console - javascript

Im having an issue with scrollTo on newly created divs Im adding to the DOM via append(). For some reason I cant scroll to where I want from within the code, it only works from console command or if I add a button and call the scroll event that way.
Code:
$('#history').scrollTo('max');
Only works from console or attached to a button.
Edit: The history div has overflow:auto, not sure if that's causing it.

Just a guess, but are you calling "scrollTo" immediately after appending your new element to the DOM?
If that is the case, then the DOM layout likely hasn't had a chance to get recalculated. Relative offset values between elements aren't yet updated until after the current script processing finishes.
Two possible workarounds:
1. setTimeout("$('#history').scrollTo('max')", 1); // Call this after you append your element. This will allow the stack to unwind and update the DOM positions
2. $('#history').scrollTo(0, 9999); // Where "9999" is a value far larger than the actual height of the control.

This would indicate that you're trying to attach scrollTo() to elements which aren't actually existing at the time that you're calling the function on them. The fact that it works in the console would suggest this.
If that's the case, one way would be to use e.g. a library like livequery or then simply call the scrollTo() function on these elements once they have been appended.

Related

How to detect whether all element's content has been loaded?

I'm wondering how can I detect whether all content inside dynamically appended HTML element is loaded. The element's content might be both text and images, maybe videos. I need to detect it to get a correct element's height value.
I believe that MutationObserver is not right solution for that as this only detects whether node has been changed or its attributes. I have to detect when element's content has been loaded.
Delegating load events to parent doesn't change anything.
Any suggestions?
You can do this by using a callback function on your AJAX call. Off the top of my head I can't remember how that works in vanilla javascript, but in jquery it would look like this:
$.ajax({
url: 'my-url'
}).done(function(){
// This only fires once the AJAX request / response has complete
populateElement();
fixElementHeight();
});
By doing it this way you ensure you have all the content before updating your element. Once the element has been updated, you are then able to measure its height. If part of the new content is an image, or some other content type which needs to be fetched, then I would do the fetching in the populateElement function:
var contentImage = new Image(imgWidth, imgHeight);
$(contentImage).click(function(event){
...
});
contentImage.src = 'source of image';
You will most likely need a javascript that has a constant setTimeout checking for the length of an element. (an element that is not loaded usually has a length of 0 or is invalid)
This is something we encountered awhile back and probably applies to your situation as well. It's for a youtube thing for detecting when certain elements have finished loading, but seeing your question, the concept applies as well.
http://www.gambit.ph/how-to-use-the-javascript-youtube-api-across-multiple-plugins/
I decided to use Javascript promises to handle images load events. I'm creating a new promise for each image and updating my app after all images are loaded.
So there's no other way round to make delegation on parent to detect whether all images were loaded.

Animate something that doesn't exist on page load

Ajax sets up a scenario and jQuery then plays it out. The element does not exist before the page is loaded. I need a way to Animate something that was dynamically added to the page.
Something like:
$(document).on("animate", "div", function (){});
Does anything like this exist?
Okay, there seems to be some confusion, I am using queue() this isn't the issue creating it or doing something after I have the ajax return. After the Ajax the program builds and inserts imgs with specific IDs into the page. I need to reload the dom or something so that I can then animate the objects that were inserted into the page.
I have tested the animated on JSfiddle and they work fine, so my only assumption is that because these objects are not part of the initial dom they will not animate and thus I need the DOM to reload.
All you have to do is animate it with the proper function, like:
$("#nonexistent-element").animate({
right: '10%'
});
and it will animate once #nonexistent-element exists, regardless of whether it existed at page load. You only need to use on() when you want to bind an event to an element that does not exist on page load.
Working jsfiddle: http://jsfiddle.net/emFpw/26/
When the content is loaded via Ajax, we need to bind the events for them to work or we can use the live/on methods of jQuery which will bind the events to either parent/document depending on what we want.
Either of the two techniques ie binding when the content is loaded or using live/on should result in the event being triggered.
For ex: Once the content in inserted we can do as suggested by Lrdwhyt in the above answer.
Or we bind the element before its loaded like
$("#non-existing-elem").live("click",function(){
$(this).animate({right:'10'});
})

is it possible to view one html element twice on the same page, or must I create a duplicate?

I am creating a site that allows viewing and editing the contents of the 'src-div' contents within the 'edit-div.' I am not editing the src-div directly, because its thumbnailed using css zoom property.
I have considered using knockout.js to bind both elements to an observable. Currently, I have implemented the feature with jquery .html() function: simply set edit-div innerhtml to src-div innerhtml on 'select', and reverse the process after changes are made to edit-div to update the src-div.
I am wondering if I really need 2 divs here, or if there is some way to actually view the same element twice on a page, and any changes made will automatically reflect in both 'views,' elimiating the need to copy innerhtml property back and forth between two elements.
essentially, this is like a mirror effect, without the flip.
the closest thing I found so far is:
http://developer.apple.com/library/safari/#documentation/InternetWeb/Conceptual/SafariVisualEffectsProgGuide/Reflections/Reflections.html
Any recommended practices for performing this task are appreciated.
(Almost) everything you see on a page has a counterpart in the DOM. Everything in the DOM gets exactly rendered one time (apart from pseudo-classes). And every node in the DOM can only have one parent (no exclusions).
Unfortunately you'll have to clone the specific node and add changes to both, as there is no copy & translate mechanism in the current CSS documentation.
If you're using jquery you can use one div and "clone" it. You can read this for more information.
http://api.jquery.com/clone/
If you set the class of the div to the same thing, you can have changes propagated to both. Then you can apply .addClass to the second div to apply a "reflected" affect (if that's your final goal).

Using jquery to add/remove class but elements are not redrawn to reflect

I have two elements (think of two buttons side by side). I dynamically toggle the class "focusd" to change the highlighted effect. However, there's a quirk it doesn't always get redrawn and/or inserted in the DOM. For example, if in chrome I do console.log, I see the class changes (I'm using removeClass/addClass in jquery). But if I go to the Elements tab in the inspector, it shows the classes from before (and in fact, I'm not seeing the redrawing reflecting the toggling of the classes.)
I tried setting the parent div to display none then back to block but that didn't work. It's a "one off" modale screen, so efficiency doesn't matter so I've resorted to this hack where I essentially copy the parent's innerhtml, remove and reinsert the element. Horrible!
// Not sure why I need this hack. But if I don't, the buttons don't seem to get redrawn
var htm = jQuery(".rdata_container").html(); // copy the innerhtml
jQuery(".rdata_container").empty(); // empty and then append back
jQuery(".rdata_container").append(htm);
This seems like a specific quirk that someone must have ran into (I hope). If so, I'd love to know why my changes aren't reflected.
EDIT
Code posted here:
http://jsfiddle.net/roblevintennis/JCZnf/
you can use setTimeout when you are doing the other operation on the element, so for example:
$elm.addClass('hide')
setTimeout(function(){
$elm.removeCalss('hide')
},0);
Or you could force a repaint like so:
$elm.addClass('hide')
$elm.scrollTop; // forces a repaint (might be expensive for large amount of items)
$elm.removeCalss('hide');
These tricks will force the browser to re-draw the change, because there are two things happening here and the browser logic just combines them into one, which isn't the desired behavior.
Not directly an answer to your question, but you can use jQuery's toggleClass function to simplify your code.
Here's an updated version that uses toggleClass() and jQuery 1.6 and AFAICT works fine.
http://jsfiddle.net/JCZnf/7/

Are events lost in jQuery when you remove() an element and append() it elsewhere?

What happens in jQuery when you remove() an element and append() it elsewhere?
It appears that the events are unhooked - as if you were just inserting fresh html (which I guess is what happening). But its also possible my code has a bug in it - so I just wanted to verify this behavior before I continue.
If this is the case - are there any easy ways to rehookup the events to just that portion of HTML, or a different way to move the element without losing the event in the first place.
The jQuery detach() function is the same as remove() but preserves the event handlers in the object that it returns. If you have to remove the item and place it somewhere else with everything you can just use this.
var objectWithEvents = $('#old').detach();
$('#new').append(objectWithEvents);
Check the API docs here: http://api.jquery.com/detach/
Yes, jQuery's approach with remove() is to unbind everything bound with jQuery's own bind (to prevent memory leaks).
However, if you just want to move something in the DOM, you don't have to remove() it first. Just append to your heart's content, the event bindings will stick around :)
For example, paste this into your firebug on this page:
$('li.wmd-button:eq(2)').click(function(){ alert('still here!') }).appendTo(document.body)
And now scroll down to the bottom of this page and click on the little globy icon now buried under the SO footer. You will get the alert. All because I took care to not remove it first.
use jQuery1.3.1 live() to bind events and you won't need to worry about this..
Update: live events are deprecated now, but you can get the same effect from $(document).on().

Categories