appending to div get slower - javascript

I'm creating a drawing board using just html/css/jquery and the drawing is working fine. What I'm doing is catching the mousemove events and putting a dot(div) at every location the event fires, then I'm adding dots in between in places where the event wasn't firing to create a line.
This all works fine, but as I draw more, the appending of dots to the div is getting slower (or I should say, the drawing is getting a 'laggy' feel). I understand that the document is getting more divs appended to it, but why does it care if I'm just doing plain appends. I'm not doing any searches in the document for specific elements or anything.
here's the fiddle http://jsfiddle.net/u4mn2b84/14/
or is this not related to how many elements are in the document?
part of code:
$('#sketch-box').on('mousemove', function(e) {
if (isPerformingLeftMouseClick) {
//var parentOffset = $(this).parent().offset();
var offset = $(this).offset();
var currentMouseLeft = e.pageX - offset.left;
var currentMouseTop = e.pageY - offset.top;
var linkDotTemp = $(linkDot).clone();
$(linkDotTemp).css('top', currentMouseTop);
$(linkDotTemp).css('left', currentMouseLeft);
if (lastMouseTop != null && lastMouseLeft != null) {
drawLineInBetween(lastMouseTop, lastMouseLeft, currentMouseTop, currentMouseLeft);
}
$(this).append(linkDotTemp);
lastMouseTop = currentMouseTop;
lastMouseLeft = currentMouseLeft;
}
});

You are ending up with a LOT of divs on the page unnecessarily, and the browser is finding it harder and harder to render these the more you add (they are not designed to be used like this).
Even if you inspect element on your page in Chrome, the developer console really struggles when you start inspecting the dots.
I would recommend using HTML5 canvas instead.
HTML5 Canvas w3schools page

Related

How to properly scroll IFrame to bottom in javascript

For a mockup-webpage used for research on interaction on websites, I created a mockup message-stream using JavaScript. This message stream is loaded in an IFrame and should show images at pre-set intervals and scroll to the bottom of the page after placing a new image at the bottom of the page. Getting the images to appear is working quite well with the provided script. However, both Chrome and IE seem to have trouble scrolling the page to the bottom. I would like to scroll to the bottom of the page as soon as the image is attached, but have for now added a 5 ms delay because that seemed to work sometimes. My questions are:
Is it okay to use document.body.scrollHeight for this purpose?
Can I make the scroll occur directly, or do I need a small interval before scrolling?
How to make the code scroll to the bottom of the IFrame directly after adding an image?
The following functions are used and trypost() is started onLoad:
function scrollToBottom(){
window.scrollBy(0,document.body.scrollHeight);
}
function trypost(){
point = point + 1;
if(point < interval.length){
//create and append a new image
var newImg = document.createElement("IMG");
newImg.src = "images/"+images[point]+".png";
document.getElementById('holder').appendChild(newImg);
//create and append a return
var br = document.createElement("br");
document.getElementById('holder').appendChild(br);
//time scroll to bottom (after an arbitrary 5 seconds)
var stb = window.setTimeout(scrollToBottom, 5);
//time next post
var nextupdate = interval[point]*400;
var tp = window.setTimeout(trypost, nextupdate);
}
}
My script section contains at least the following variables:
var point = -1;
var interval = [10, 10, 15];
var images = ["r1", "a1", "r2"];
This questions is a continuation of the project described in How to proper use setTimeout with IE?
To answer one of your questions, document.body.scrollHeight is appropriate for this purpose, but not if you're actually calling for document. That'll give you the scroll height of the document the iFrame is in, not the iFrame's document. The iFrame's document can be called upon by [insert variable for iFrame here].contentDocument.
Here's how I did it (and by that, I mean I tested it out with my own stuff to make sure it worked):
let i = document.querySelector('iframe')
i.contentWindow.scrollTo(0, i.contentDocument.body.scrollHeight);
That being said, the other answer by Thomas Urban will also work most of the time. The difference is only if your page has a really long scroll height. Most pages won't be longer than 999999 (for all I know that's impossible and that's why they chose that number), but if you have a page longer than that, the method I showed here would scroll to the bottom and the 999999 would scroll to somewhere not yet at the bottom.
Also note, if you have more than one iFrame, you're gonna want to query it in a different way than I did, like by ID.
Scrolling to bottom is always like scrolling to some ridiculously large top offset, e.g. 999999.
iframe.contentWindow.scrollTo( 0, 999999 );
In addition see this post: Scrolling an iframe with javascript?
If scrolling occurs too early it's probably due to images not being loaded yet. Thus, you will have to scroll as soon as added image has been loaded rather than on having placed it. Add
newImg.onload = function() { triggerScrolling(); };
after creating newImg, but before assigning property src.
If several events are required to trigger scrolling you might need to use some "event collector".
function getEventCollector( start, trigger ) {
return function() {
if ( --start == 0 ) { trigger(); )
};
}
You can then use it like this:
var collector = getEventCollector( 2, function() { triggerScrolling(); } );
newImg.onload = collector;
window.setTimeout( collector, 100 );
This way triggerScrolling() is invoked after 100ms at least and after image has been loaded for collector has to be invoked twice for triggerScrolling() being invoked eventually.

Get canvas object position and move to canvas touch position in HTML 5 / JS

I am new to HTML 5 and JS for iPhone. In my application, I was succeeded to get touch points from the canvas by the following code(this is inside my game.js class):
canvas.addEventListener("click", mouseClickEvent, false);
function mouseClickEvent(e) {
alert("Clicked x= "+e.layerX+" and clicked y= "+e.layerY);
}
and I am displaying an object (hole) from the game.js class as:
var hole = new Image();
hole.onload = function() {
ctx.drawImage(hole,135,215,50,50);
}
hole.src = 'images/hole.png';
Now what I need is to:
1) Move the hole object to the touched position (like animating/moveto).
2) Add a click listener to the hole (I tried canvas.addEventListener, but not worked).
I've searched a lot. But not able to find a proper solution :(
Some tutorials said to: remove and redraw the object to move it. But I've several images on my screen, with different shapes.
Pls, pls help me to solve this...
Your touch events can be done like this:
var hole = {x: 0, y: 0};
var touchEvents = function(e){
e.preventDefault();
if(e.targetTouches) e = e.targetTouches[0]; // since i like to test with a mouse, but still have it work with touch devices.
hole.x=e.clientX;
hole.y=e.clientY;
};
canvas.onmousemove=touchEvents;
canvas.ontouchmove=touchEvents;
canvas.ontouchstart=touchEvents;
This was quickly converted from my js1k entry, the variable names are short, but maybe you can get a few hints: http://jsfiddle.net/9J25N/

Jquery.height() returns different results using F5 or CTRL+F5

So I am trying to find the height of my images then add a top margin this enables me to impose a a vertical center.
I'm running this code, and on an F5 refresh I get correct height but on CTRL+F5 refresh it gives me a much smaller height. I kind of assume this is a loading/delay thing, but I am using document ready so not really sure whats going on. I tried using a php function but it slows the site down amazingly so have to stick with jquery.
you can see it working here. www.mzillustration.com
jQuery(document).ready(function() {
if (jQuery('.imagedisplay').length != 0) {
jQuery('.imagedisplay').each(function(){
var imgheight = jQuery(this).find('img').height();
var topmarg = ((240 - imgheight) / 2) ;
jQuery(this).find('img').css({'margin-top':topmarg+'px'});
});
});
any ideas/help/explanation much appreciated.
thanks
There is a difference between onload and onready.
ready will wait until the actual DOM-tree is done, while onload will wait until ALL of the content displayed on the page is finnished loading. So an explanation would be that when clearing the cache and refreshing, the dom tree finishes much faster than the images, hence giving the wrong heigh.
Try using the onload-event instead and see if you get a different result.
You need to insure the image has loaded before asking the browser for its height. If that image path is living in the html you will unfortunately need a jquery pluggin to handle this in a cross browser manner.
https://github.com/alexanderdickson/waitForImages
http://desandro.github.com/imagesloaded/
Or you will have to wait for the window.onload event which in jquery looks like this:
$(window).on('load', function(){....
However if you use the window load event, it will wait until ALL resources have loaded and depending on your site that can be a serious delay when compared to measuring just the image itself.
Or if you are comfortable with loading the image from javascript, simply ordering your code properly will handle this:
var loadTester = new Image(),
imgH;
$(loadTest).on('load',function(){
imgH = $('#image').attr('src',loadTester.src).height();
}
loadTester.src = "paht/to/image.jpg";
The reason you are seeing a difference in the manner you reload the page, is that a simple refresh does not clear the cache, so the image is already loaded. When you hit ctrl+f5 it clears the cache and so the image is not yet loaded when you ask the browser for the height.
For cache control durring development consider getting the firefox web-developer toolbar.
Try this approach:
jQuery(function() {
jQuery('.imagedisplay img').each(function() {
var $this = jQuery(this),
height = $this.height();
if (height) {
$this.css('margin-top', ((240 - height) / 2) + 'px');
} else {
$this.on('load', function() {
$this.css('margin-top', ((240 - $this.height()) / 2) + 'px');
});
}
});
});
images are/can be cached/loaded separately from the actual page content. the document being ready can (and in my experience usually) occurs before everything is loaded.
try adding an event listener to the actual element being loaded.
You need to make sure the image has loaded before extracting a height. You can easily check this using the complete property on the image. Try this:
var setH = function() {
$(this).css('margin-top', (240 - this.height) / 2);
}
$('.imagedisplay img').each(function() {
if( this.complete ) {
setH.call(this); // apply height straight away
return;
}
$(this).load(setH); // apply height when the image has loaded
});

Is there a way to resize an image when live?

E.g. with something akin to firebug, so that you can see how other page elements wrap around it. I don't know of anything like this other than http://makiapp.com/maki , which is useful but not ideal as it doesn't wrap text around the image for example.
Is there a way to re-size images directly on a website?
Not clear on what exactly you want, but I made a fiddle none the less: http://jsfiddle.net/sveinatle/r8J9F/2/
If you want to use this on your own pages, then you can just add the code as is, and add the class resizable to any elements (doesn't need to be images) that you want to be able to resize.
If you want to use it on a page without modifying its source, then you can open Firebug and run the code in the console, just swap out the $('.resizable') selection with something that will match the elements you want to resize. $('*') would apply it to everything.
The code:
var startX,startY,
startW,startH,
$box=null;
$('.resizable').mousedown(function(e){
startX = e.pageX;
startY = e.pageY;
$box = $(this);
startW = $box.innerWidth();
startH = $box.innerHeight();
return false;
});
$('body')
.mouseup(function(){
$box = null;
return false;
})
.mousemove(function(e){
if($box!=null){
$box.innerWidth (startW + e.pageX-startX);
$box.innerHeight(startH + e.pageY-startY);
}
});

scroll adjustment not working correctly in non-IE browsers after loading an image (JavaScript/DOM); timing issue w/innerHTML

I am having some frustrating javascript timing issues.
FYI, the page is a jsp file and attached to said page is a separate js file and the jQuery CDN file. For troubleshooting purposes, I eliminated all unnecessary content and code and pasted what I needed into separate jsp and js files to troubleshoot this specific problem.
If I could display the html and js someplace, that would be great. But for now, I'll describe it. The page has two buttons, one to load an image and one to toggle a "zoom" feature (more on that later). The user clicks a button, which loads an image using the DOM, specifically innerHTML. This image is surrounded by horizontal and vertical scrollbars. When the user turns on the "zoom" feature, the image records the mouse-click position in an onclick event. So, with this on, the user clicks on the image and a bigger version of the same image is loaded, again, using the DOM and innerHTML. The very last step, the most important one, using the mouse position, the scrollbars will focus and center on the point clicked (using scrollLeft and scrollTop).
This all works flawlessly in IE. However, in non-IE browers (i.e. FireFox), it takes a couple of clicks for the scroll adjustment to catch up to the innerHTML. That is, when the user "zooms" for the first time, the image loads but the scrollbars don't adjust. It takes two more successive clicks for it to work the same as in IE. I was researching innerHTML and it is slower in FireFox than IE.
How can I fix this? Has anybody else tried to load an image in FireFox using JavaScript and immediately adjust the scroll positioning on the image? Again, it works the first and each time after that in IE. But non-IE browsers are having issues.
I've tried using innerHTML, replaceChild, appendChild, nothing I tried so far fixes it.
Thank you.
Update: I wanted to see if this issue is anything inside the scrollbars or just images; so, I replaced the image with < p > ... < p > and programmed it to scroll immediately after the **first* image is loaded, via a user-initiated onclick event. Interestingly, it worked. I then replaced the text with the image and it was broken again.
So, after an image is loaded using the DOM (i.e. innerHTML), any attempts to programmatically scroll in non-IE browsers will break. If you programmatically scroll once more, though, it will behave normally.
Update2: I tried employing methods to programmatically cancel the event at the end of the call and immediately call the function again, but that didn't fix the issue.
Then, I tried loading the image using jquery and that seemed to work. I adapted it from two other stackoverflow articles: Can I get the image and load via ajax into div and img onload doesn't work well in IE7 (to circumvent a caching issue).
Here is the code I used:
image = new Image();
image.src = "sample.gif?d=" + new Date(); // passing unique url to fix IE (see link above)
image.onload = function () {
$("#imgcontainer").empty().append(image);
// document.getElementById("imgcontainer").appendChild(image); // This worked, too
// $("#imgcontainer").html("<img src=\"sample.gif?d=" + new Date() + "\"></img>"); // Failed
// document.getElementById("imgcontainer").innerHTML = "<img src=\"sample.gif?d" + new Date() + "\"></img>"; // Failed
$("#imgcontainer").scrollTop(25);
};
image.onerror = function () {
$("#imgcontainer").empty().html("That image is not available.");
}
$('#imgcontainer').empty().html('Loading...');
The key, I believe, was using the onload method. I tried employing jQuery.html() inside the onload method and it didn't work. So, that confirms there was definitely a timing issue related to innerHTML and how and when the image is loaded into the DOM. And the onload method, in combination with either the DOM's native appendChild method or jQuery's equivalent appendChild implementation, fixed the problem.
Update3:
Regarding mrtsherman's suggestion below--
Here is my code:
var outerDIV, innerDIV, html;
outerDIV = document.createElement("div");
outerDIV.id = "content";
document.getElementById("body_id").appendChild(outerDIV); // attach div to body
innerDIV = document.createElement("div");
innerDIV = "ImageHolder";
image = new Image();
image.src = "sample.gif?d=" + new Date();
document.getElementById("content").appendChild(innerDIV);
document.getElementById("ImageHolder").style.height=image.height + "px";
document.getElementById("ImageHolder").style.width=image.width + "px";
html = "<img src=\"sample.gif\"></img>";
$("#content").scrollTop(100);
$("#ImageHolder").html(html);
I created an inner div to place the image. After creating said div, I adjusted it's size, based on the dimensions of the image. I adjusted the scrolling in js and then attached the image to the DOM, via innerHTML, and it did not scroll. I changed the width and height to some fixed size larger than the image and it scrolled. But that is not the desired affect, to make a container bigger than the image. Thank you for your help.
Update4:
What is the equivalent of the code I wrote in Update2 when using document.createElement("img"), instead of new Image()? The onload event is not having the same affect as in the Image object; the onload event is an important ingredient, here.
Thank you.
If you know the new images dimensions then I would send those first. Then you can resize a container for the image, adjust scrollbars and then get the image.
Please see the original question, Update2, for the solution I employed.

Categories

Resources