preload images before render javascript - javascript

I wanna display images instantly as all the images are loaded for my smooth slider,
but its not working.
var myPhotos = {
_counter: 0,
images: [],
init: function() {
ServerCall1(0, 'xml', 'rssphotos.php', function(xml) {
imageObj = new Image();
$(xml).find('item').each(function() {
var desc = $(this).find('description').text();
var resp = getImgArray(desc);
myPhotos.images[myPhotos._counter] = resp[0];
myPhotos._counter++;
});
//start preloading
for (i = 0; i < myPhotos._counter; i++) {
imageObj.src = myPhotos.images[i];
}
////PUT THE HEADER HOME PAGE
topHeader.putData(topHeader.photoData());
});
}
};
After the execution of this function, I loop through myPhotos.images to get them instantly, but its rendering one by one very slowly.

Perhaps this
var myPhotos = {
_counter: 0,
images: [],
init: function() {
ServerCall1(0, 'xml', 'rssphotos.php', function(xml) {
$(xml).find('item').each(function() {
var desc = $(this).find('description').text();
var resp = getImgArray(desc);
myPhotos.images[myPhotos._counter] = resp[0];
myPhotos._counter++;
});
//start preloading
for (i = 0; i < myPhotos._counter; i++) {
this.images[i]= new Image(); this.images[i].src = myPhotos.images[i];
}
////PUT THE HEADER HOME PAGE
topHeader.putData(topHeader.photoData());
});
}
};

Related

I can't send data to the server using AJAX

The situation is as follows: I upload a drag and drop image to the server. Everything would have been simpler, but first you need to embed the dropped image into the DOM tree, after which it can be removed from there, and the rest need to be sent to the server. At the drop event, I add the file itself and the picture className to the associative array. After the user is ready to send all the remaining pictures to the server, I add the files that have the classes of the remaining pictures as the key to the new array and form FormData of it. But the server does not receive files. Help!
code:
var arr = new Map;
//create a associative array.
dnd.addEventListener('drop', e => {
e.preventDefault();
var image_ = e.dataTransfer.files;
.....
//embed dropped image into the DOM tree
const text = e.dataTransfer.getData("text");
if (text) {
let img = document.createElement('img');
img.src = text;
$('#container_').append(img);
}
else {
const files = e.dataTransfer.files;
[].map.call(files, file => {
if (file.type.match(/^image/)) {
let reader = new FileReader();
reader.onload = file => {
let img = document.createElement('img');
img.className = "droppedPhoto" + Math.random();
img.setAttribute("widt", "200");
img.setAttribute("height", "200");
img.src = file.target.result;
let div = document.createElement('div');
$('#container_').append(div);
$('#container_').children().last().append(img);
arr.set(img.className, image_);
$('.sendPhotos > p > button').on('click', function () {
checkData(arr);
});
function checkData(array) {
var $arrOfImg = $('#container_ > div > img');
var $newArrayOfData =[];
for (var i = 0; i < $arrOfImg.length; i++) {
if (array.has($arrOfImg[i].className)) {
$newArrayOfData.push(array.get($arrOfImg[i].className));
}
}
createFormData($newArrayOfData);
}
function createFormData(images) {
var formImage = new FormData();
for (var i = 0; i < images.length; i++) {
formImage.append(key, images[i]);
}
uploadFormData(formImage);
}
function uploadFormData(formData) {
$.ajax({
url: '#Url.Action("PhotoSessionInfo", "Home")',
type: "POST",
xhr: function () {
var myXhr = $.ajaxSettings.xhr();
return myXhr;
},
data: formData,
contentType: 'multipart/form-data',
cache: false,
processData: false,
success: function (response) {
console.log("success");
$('#container_').html(response);
}
});
}

How to get not loaded resources?

I'm trying to get all not loaded elements in a webpage by including a script in the head of the index.html but I've some problems.
This is the code:
document.addEventListener('DOMContentLoaded', function () {
console.log("here");
var scripts = document.getElementsByTagName('script');
for(var i=0;i<scripts.length;i++){
scripts[i].onerror =function(message, source, lineno) {
console.log("JS: Error SCRIPT");
}
}
var imgs = document.getElementsByTagName('img');
for(var i=0;i<imgs.length;i++){
imgs[i].onerror =function(message, source, lineno) {
console.log("JS: Error IMG ");
}
}
var links = document.getElementsByTagName('link');
for(var i=0;i<links.length;i++){
links[i].onerror = function(message, source, lineno){
console.log("JS: Error CSS ");
}
}
});
I put 3 wrong CSS, Images and Scripts (they don't exist as resources) inside the HTML file where I call the script.
When I run locally the index.html I get "Error IMG" and "Error CSS".
When I run on the server I get only "Error IMG".
In both cases, I don't get "Error SCRIPT".
What I'm doing wrong?
UPDATE: This is the code
appmetrics.js
//class that store page resource data
/*
ES6
class Resource{
constructor(name,type,start,end,duration){
this.name = name;
this.type = type;
this.start = start;
this.end = end;
this.duration = duration;
}
}
*/
function Resource (name,type,start,end,duration){
this.name = name;
this.type = type;
this.start = start;
this.end = end;
this.duration = duration;
}
/*
ES6
class Errors{
constructor(name,source,line){
this.name = name;
this.source = source;
this.line = line;
}
}
*/
function Errors(name,source,line){
this.name = name;
this.source = source;
this.line = line;
}
//endpoint to send data
var endpoint = "https://requestb.in/sr8wnnsr"
var resources = Array();
var errors = Array();
var pageLoadTime;
var start = performance.now();
window.onload = function(){
pageLoadTime = performance.now()-start;
console.log("Page loading time: " + pageLoadTime);
//getting page resources and pushing them into the array
var res = performance.getEntriesByType("resource");
res.forEach(function add(item){
resources.push(new Resource(item.name,item.initiatorType,item.startTime,item.responseEnd,item.duration));
})
console.log(resources);
var jsonRes = JSON.stringify(resources);
//sendMetricToEndpoint(jsonRes);
//sendMetricToEndpoint(pageLoadTime.toString());
}
window.onerror = function(message, source, lineno) {
console.log("Error detected!" + "\nMessage: " +message +"\nSource: "+ source +"\nLine: "+ lineno);
errors.push(new Errors(message,source,lineno));
console.log(errors);
}
//Not working code
/*
document.addEventListener('DOMContentLoaded', function () {
console.log("here");
var scripts = document.getElementsByTagName('script');
for(var i=0;i<scripts.length;i++){
scripts[i].onerror =function(message, source, lineno) {
console.log("JS: Errore SCRIPT");
}
}
var imgs = document.getElementsByTagName('img');
for(var i=0;i<imgs.length;i++){
imgs[i].onerror =function(message, source, lineno) {
console.log("JS: Errore IMG ");
}
}
var links = document.getElementsByTagName('link');
for(var i=0;i<links.length;i++){
links[i].onerror = function(message, source, lineno){
console.log("JS: Errore CSS ");
}
}
});
*/
//StackOverflow solution start
var scripts = [];
for (var i = 0, nodes = document.getElementsByTagName('script'); i < nodes.length; i++) {
scripts[i] = { source: nodes[i].src, loaded: false };
nodes[i].onload = function() {
var loadedNode = this;
var index = scripts.findIndex(function(script) {
return script.source === loadedNode.src;
});
scripts[index].loaded = true;
};
}
var links = [];
for (var i = 0, nodes = document.getElementsByTagName('link'); i < nodes.length; i++) {
links[i] = { source: nodes[i].href, loaded: false };
nodes[i].onload = function() {
var loadedNode = this;
var index = links.findIndex(function(link) {
link.href === loadedNode.href;
});
links[index].loaded = true;
};
}
document.addEventListener('DOMContentLoaded', function() {
console.log("here");
scripts.filter(function(script) {
return !script.loaded;
}).forEach(function(script) {
console.log("Error loading script: " + script.source);
});
links.filter(function(link) {
return !link.loaded;
}).forEach(function(link) {
console.log("Error loading link: " + link.source);
});
// and the rest of the elements
var imgs = document.getElementsByTagName('img');
for (var i = 0; i < imgs.length; i++) {
imgs[i].onerror = function() {
console.log("Error loading image: " + this.src);
};
}
});
//StackOverflow solution stop
/**
* Function that send metric to endpoint.
*
* #param {string} endpoint Where to send data.
* #param {*} data data to send (JSON or string)
*/
function sendMetricToEndpoint(data){
console.log("Sending metrics to endpoint");
var xhttp;
xhttp=new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (xhttp.readyState == 4 && xhttp.status == 200) {
console.log(xhttp.responseText);
}
};
xhttp.open("POST", endpoint, true);
//xhttp.setRequestHeader("Content-type", "application/json");
xhttp.send(data);
}
index.html
<html>
<head>
<!--<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>-->
<script src="js/appmetricsmod.js"></script>
<link rel="stylesheet" href="styletests.css">
<link rel="stylesheet" href="styletestss.css">
<link rel="stylesheet" href="styletestsss.css">
<script src="js/error1.js"></script>
<script src="js/error2.js"></script>
<script src="js/error3.js"></script>
</head>
<body>
<img src="imgtest.png"></img>
<img src="imgErr1.png"></img>
<img src="imgErr2.png"></img>
<img src="imgErr3.png"></img>
<img src="http://images.centrometeoitaliano.it/wp-content/uploads/2016/11/15/l1.jpg"></img>
<div class="divtest">
hello this is a test
</div>
<script>
</script>
</body>
</html>
Sadly, you you cannot get link nor script error load with onerror event, but you can handle the loaded content, and filter which were not loaded. This is possible with the load event for the link and script tags.
var scripts = [];
for (var i = 0, nodes = document.getElementsByTagName('script'); i < nodes.length; i++) {
scripts[i] = { source: nodes[i].src, loaded: false };
nodes[i].onload = function() {
var loadedNode = this;
var index = scripts.findIndex(function(script) {
return script.source === loadedNode.src;
});
scripts[index].loaded = true;
};
}
var links = [];
for (var i = 0, nodes = document.getElementsByTagName('link'); i < nodes.length; i++) {
links[i] = { source: nodes[i].href, loaded: false };
nodes[i].onload = function() {
var loadedNode = this;
var index = links.findIndex(function(link) {
link.href === loadedNode.href;
});
links[index].loaded = true;
};
}
document.addEventListener('DOMContentLoaded', function() {
console.log("here");
scripts.filter(function(script) {
return !script.loaded;
}).forEach(function(script) {
console.log("Error loading script: " + script.source);
});
links.filter(function(link) {
return !link.loaded;
}).forEach(function(link) {
console.log("Error loading link: " + link.source);
});
// and the rest of the elements
var imgs = document.getElementsByTagName('img');
for (var i = 0; i < imgs.length; i++) {
imgs[i].onerror = function() {
console.log("Error loading image: " + this.src);
};
}
});
Hope it helps :)
Using the classes Resources and Errors above, I solved the problem by taking all the resources of the page and then removing the working ones. The result is an array of not loaded resources.
This is the code:
var res = performance.getEntriesByType("resource");
res.forEach(function add(item){
resources.push(new Resource(item.name,
item.initiatorType,
item.startTime,
item.responseEnd,
item.duration));
})
var flag = true;
var imgs = document.getElementsByTagName('img');
for(var i=0;i<imgs.length;i++){
for(var j=0;j<resources.length;j++){
if(imgs[i].src == resources[j].name){
flag = false;
}
}
if(flag && imgs[i].src){
errors.push(new Errors("RES NOT FOUND",imgs[i].src,null));
}
flag = true;
}
var scripts = document.getElementsByTagName('script');
for(var i=0;i<scripts.length;i++){
for(var j=0;j<resources.length;j++){
if(scripts[i].src == resources[j].name){
flag = false;
}
}
if(flag && scripts[i].src){
errors.push(new Errors("RES NOT FOUND",scripts[i].src,null));
}
flag = true;
}
var links = document.getElementsByTagName('link');
for(var i=0;i<links.length;i++){
for(var j=0;j<resources.length;j++){
if(links[i].src == resources[j].name){
flag = false;
}
}
if(flag && links[i].href){
errors.push(new Errors("RES NOT FOUND",links[i].href,null));
}
flag = true;
}
console.log(resources);
console.log(errors);

Grab screenshot of appended blob video

When saving a screenshot of large video files on a canvas, it seems that it cannot get its blob. It is working fine when the video blob has been displayed on the container.
Here's a JSFiddle without timeout (does not work)
Here's a JSFiddle with timeout (works)
$('#txtFileUpload').on('change', function() {
var countFiles = $(this)[0].files.length;
for (var ctr = 0; ctr < countFiles; ctr++) {
var reader = new FileReader();
readerOnLoad(reader, ctr, $(this)[0], this.files[0]);
}
});
var readerOnLoad = function(reader, ctr, fileInput, files) {
reader.onloadend = (function(ctr) {
return function(e, ctr) {
var videoIdClass = 'thumb-video-' + ctr;
var $video = $('<video />', {
'src': e.target.result,
'id': videoIdClass,
'class': videoIdClass,
}).appendTo($('.video-container')).wrap('<div class="thumb-container"></div>');
setVideoCapture($video);
};
})(ctr);
reader.readAsDataURL(fileInput.files[ctr]);
}
var setVideoCapture = function(videoElement) {
var $output;
var $canvas = document.createElement('canvas');
var $img = document.createElement('img');
$output = $('#output');
$video = videoElement.get(0);
$canvas.width = $video.videoWidth * 2;
$canvas.height = $video.videoHeight * 2;
$canvas.getContext('2d').drawImage($video, 0, 0, $canvas.width, $canvas.height);
$img.src = $canvas.toDataURL();
$output.prepend($img);
}
A quick fix would be set a timeout on the setVideoCapture method like this:
This works.
var setVideoCapture = function(videoElement) {
setTimeout(function() {
var $output;
var $canvas = document.createElement('canvas');
var $img = document.createElement('img');
$output = $('#output');
$video = videoElement.get(0);
$canvas.width = $video.videoWidth * 2;
$canvas.height = $video.videoHeight * 2;
$canvas.getContext('2d').drawImage($video, 0, 0, $canvas.width, $canvas.height);
$img.src = $canvas.toDataURL();
$output.prepend($img);
}, 2000, videoElement)
}
Weird that it has to be INSIDE the setVideoCapture method and not when triggering the setVideoCapture method like this:
This does not work.
reader.onloadend = (function(ctr) {
return function(e, ctr) {
var videoIdClass = 'thumb-video-' + ctr;
var $video = $('<video />', {
'src': e.target.result,
'id': videoIdClass,
'class': videoIdClass,
}).appendTo($('.video-container')).wrap('<div class="thumb-container"></div>');
setTimeout(setVideoCapture($video), 3000, $video);
};
})(ctr);
But of course using a setTimeout is not a recommended fix. What should be is that setVideoCapture method should only be triggered when the $video element has already been appened and displayed on the container.
Nevermind, I was able to fix this by:
$video.addEventListener('loadeddata', function() {
// do something here
}, false);

saving input data to global variables

I'm having trouble with a simple file input.
I'm trying to get the width, height and dataURL of multiple images and save them to global variables, but all that's saved is "undefined".
When I tried to make a "demo-fiddle" the "onchange"-event doesn't even seem to fire.
can anyone help me out?
Here's the code of the demo-fiddle:
var WIDTH = [];
var HEIGHT = [];
var SRC = [];
$(window).load(function()
{
grabData();
displayImgs();
});
function grabData()
{
$("#fileInput").on("change",function(e)
{
var file = e.target.files;
for(var i = 0; i<file.length; i++)
{
var reader= new fileReader();
var img = new Image();
reader.onload = function(e)
{
SRC = e.target.result;
img.onload = function()
{
WIDTH = this.width;
HEIGHT = this.height;
}
}
reader.readAsDataURL(file);
console.log(WIDTH);
}
console.log(WIDTH);
});
}
function displayImgs()
{
/*display images*/
for(var i = 0; i<SRC.length; i++)
{
$("body").append("<img src="+SRC[i]+" width="+WIDTH[i]+" height="+HEIGHT[i]+">");
}
}
try below code, tested in fiddle and working - http://jsfiddle.net/02468Lr9/
var WIDTH = [];
var HEIGHT = [];
var SRC = [];
$(document).ready(function() {
grabData();
;
});
function grabData() {
$("#fileInput").on("change",function(e) {
var file = e.target.files;
for(var i = 0; i<file.length; i++) {
var reader= new FileReader();
var img = new Image();
reader.onload = function(e) {
SRC.push(e.target.result);
img.onload = function() {
alert(this.width);
WIDTH.push(this.width);
HEIGHT.push(this.height);
displayImgs();
}
img.src = e.target.result;
}
reader.readAsDataURL(file[i]);
}
});
}
function displayImgs()
{
/*display images*/
for(var i = 0; i<SRC.length; i++) {
console.log(WIDTH);
$("body").append("<img src="+SRC[i]+" width="+WIDTH[i]+" height="+HEIGHT[i]+">");
}
}
The log result is undefined because you log it outside the onload function, and for that it runs before the images load and the value is still undefined.

Drag&drop and rendering thumbnails

I'm trying to make drag n' drop upload file in JS. I've written code as follow:
<div id="drop_zone">
<div style="clear: both"></div>
</div>
<output id="list"></output>
<script type="text/javascript">
var Vector = function() {
var _array = [];
this.add = function(item) {
_array.push(item);
};
this.delete = function(index) {
_array.splice(index, 1);
};
this.foreach = function(callback) {
for(i=0; i<_array.length; i++) {
callback(_array[i]);
}
};
this.length = function() {
return _array.length;
};
this.clear = function() {
_array = [];
};
};
var Snap = function(args) {
this.name = args.name || null;
this.type = args.type || null;
this.size = args.size || null;
this.modified = args.modified || null;
this.source = args.source || null;
}
var images = new Vector();
function handleFileSelect(evt) {
evt.stopPropagation();
evt.preventDefault();
var files = evt.dataTransfer.files;
if(files.length != 0) {
for(var i=0, f; f = files[i]; i++) {
var image = new Snap({
name : escape(f.name),
type : f.type||'n/a',
size : f.size,
modified : f.lastModifiedDate ? f.lastModifiedDate.toLocaleString() : 'n/a'
});
var file = files[i];
var filereader = new FileReader;
filereader.onload = function(e) {
image.source = this.result;
};
filereader.readAsDataURL(file);
images.add(image);
}
}
alert(images.length());
render();
}
function render() {
var list = document.getElementById('list');
images.foreach(function(elem) {
var div = document.createElement('div');
var divtext = elem.name + '(<i>' + elem.type + '</i>), ' + elem.size + ' <small>[' + elem.modified + ']</small>';
div.innerHTML = divtext;
list.appendChild(div);
var img = document.createElement('img');
img.src = elem.source;
document.getElementById('drop_zone').appendChild(img);
});
}
function handleDragOver(evt) {
evt.stopPropagation();
evt.preventDefault();
evt.dataTransfer.dropEffect = 'copy';
}
var dropZone = document.getElementById('drop_zone');
dropZone.addEventListener('dragover', handleDragOver, false);
dropZone.addEventListener('drop', handleFileSelect, false);
</script>
It's not working as I wish.
This view is after I drag image first time. images.length = 1
This view is after I drag image second time. images.length actually = 2, not 3, so Vector images works as it is supposed to work.
View after third dragging, one and the same image. images.length = 3, not 6, so when it comes to Vector, it's ok.
I haven't no idea how to make it works.
Thanks in advance.

Categories