How to display paragraphs and images from div in order? - javascript

I am building a small web-tool where editors can write content by using buttons to add paragraphs and images. I store the elements with an id ((number of element) starting at 0 and incremented for every new element) and load with a button in order to a div "preview" where the content is supposed to be displayed as in the web page later on.
My issue is that, for a reason I don't understand, the image is always displayed below all the paragraphs instead of being in order. Presumably there is an easy fix, but I am very new to HTML, CSS and JS and couldn't find the solution online.
Sorry if this is a stupid mistake or the solution was already posted somewhere.
Javascript handling the preview rendering:
// Preview current document status
document.getElementById("previewButton").addEventListener("click", function() {
// Clear
document.getElementById("preview").innerHTML = "";
// Add all elements properly
var section = document.getElementById("preview");
var id = "preview";
for (var counter = 0; counter < element_counter; counter++) {
var type = document.getElementById(counter).nodeName;
// If text element
if (type === "TEXTAREA") {
var paragraph = document.createElement("p");
var text = document.getElementById(counter).value;
paragraph.setAttribute("id", id + counter);
paragraph.setAttribute("class", "flow-text");
paragraph.append(text);
section.appendChild(paragraph);
}
// If image element
if (type === "INPUT") {
var file = document.getElementById(counter).files[0];
var reader = new FileReader();
reader.onload = function(e) {
var image = document.createElement("img");
image.setAttribute("id", id + counter);
image.setAttribute("src", e.target.result);
image.setAttribute("class", "materialboxed responsive-img");
section.appendChild(image);
}
reader.readAsDataURL(file);
}
}
});

This might work. I can't test though without your code. However basically the principle at work is to isolate some of the vars so they represent distinct instantiations. And then immediately add the image element to the DOM. The reader.onload is expected to run asynchronously still.
enter code here if (type === "INPUT") {
(function() {
var file = document.getElementById(counter).files[0];
var reader = new FileReader();
var image = document.createElement("img");
image.setAttribute("id", id + counter);
image.setAttribute("class", "materialboxed responsive-img");
section.appendChild(image);
reader.onload = function(e) {
image.setAttribute("src", e.target.result);
}
reader.readAsDataURL(file);
}());
}

Related

Image duplication after multiple file input

Have this issue here: I want to upload several images at once and show them directly afterwards in the browser. Everything is fine. However, doing this on mobile, sometimes I don't get all the images, but duplicates of another one from the file array. I have a suspicion, that this has to do with hardware limitations, since on PC everything works fine, but not on mobile.
Here is the fiddle. You can check it via mobile to see if duplicates appear.
So in result I get this on mobile. It wasn't two images in the selection, only one:
Here I have the Javascript snippet. Is there any room for improvement? Espacially onload processes are really confusing me from time to time. Is there any chance to write it better?
Javascript:
jQuery('.upload-mobile').change(function(){
jQuery('body').toggleClass( "loading" );
var imagecounter = jQuery(this)[0].files.length;
var loadcounter = 0;
for(var i = 0; i<imagecounter;i++){
for(var p = 1;p<=12;p++){
if(jQuery('#preview'+p).length<=0){
jQuery('.image-collection').prepend(jQuery('<div></div>',{id:'preview'+p,css:{'display':'inline-block'}}));
break;
};
}
var file = this.files[i];
var reader = new FileReader();
reader.onload = function(e){
for(var w = 1;w<=12;w++){
if(jQuery('#preview'+w).children().length>0) {
}
else{
var img = document.createElement("img");
img.src = e.target.result;
img.id = 'img'+w;
img.className += " img-responsive";
img.className += " border-blue";
img.className += " image-small";
img.className += " image-cover";
img.style.display='none';
document.getElementById("preview"+w).appendChild(img);
break;
}
}
loadcounter++;
if(loadcounter==imagecounter){
var count = jQuery('.image-collection').children().length;
jQuery('.image-small').delay('1500').fadeIn('3000', function(){
jQuery('#image-counter').text(count+'/12');
jQuery('body').removeClass( "loading" );
if( jQuery('#image-counter').text()=='12/12'){
jQuery('#upload-photos').fadeOut('200', function(){
jQuery('#three-cube-compact').fadeIn('200');
})
}
});
}
};
var image = reader.readAsDataURL(file);
}
});
EDIT:
I tried to use the forEach function. I didn't use the for each loops earlier, so I can not say much about the difference between foreach and for. I can't say if it works better or not, but I have seen less duplicates (maybe I didn't check to often to asume good functionality of it). It almost works, but maybe there is another way to make it work flawlessly?
Javascript:
jQuery('.upload-mobile').change(function(){
jQuery('body').toggleClass( "loading" );
var imagecounter = jQuery(this)[0].files.length;
var loadcounter = 0;
Array.from(this.files).forEach(function (image, index){
for(var p = 1;p<=12;p++){
if(jQuery('#preview'+p).length<=0){
jQuery('.image-collection').prepend(jQuery('<div></div>',{id:'preview'+p,css:{'display':'inline-block'}}));
break;
};
};
var reader = new FileReader();
reader.onload = function(e){
for(var w = 1;w<=12;w++){
if(jQuery('#preview'+w).children().length>0) {
}
else{
var img = document.createElement("img");
img.src = e.target.result;
img.id = 'img'+w;
img.className += " img-responsive";
img.className += " border-blue";
img.className += " image-small";
img.className += " image-cover";
img.style.display='none';
document.getElementById("preview"+w).appendChild(img);
break;
}
}
loadcounter++;
if(loadcounter==imagecounter){
var count = jQuery('.image-collection').children().length;
jQuery('.image-small').delay('1500').fadeIn('3000', function(){
jQuery('#image-counter').text(count+'/12');
jQuery('body').removeClass( "loading" );
if( jQuery('#image-counter').text()=='12/12'){
jQuery('#upload-photos').fadeOut('200', function(){
jQuery('#three-cube-compact').fadeIn('200');
})
}
});
}
};
var pic = reader.readAsDataURL(image);
});
});
EDIT2:
The fiddle was updated
EDIT3:
Added an image of the mobile screen. I also figured out it might has something to do with the file explorer on the mobile device. When I select using the first file explorer, I don't get the duplication bug:
However, by clicking on Browse ("Durchsuchen" on the image), I get to another file explorer. And using that one creates this "duplication bug":
Is there maybe a way to solve this or maybe to disable the Browse button?

Attempting to change an image onclick via PHP/Javascript/HTML

I've looked at numerous other answers regarding this but haven't found a solution that has worked. I'm using a PHP page that contains some HTML code, with Javascript working some functions. Ideally I would select an image on the page, the image will become colored green as it is selected. I would then like to deselect the image and have it return to the original state. I can only get half-way there however. What am I missing? Is it something with post back?
Here's some code examples:
The HTML:<div onclick="changeImage(1)" id="toolDiv1"><img id="imgCh1" src="/images/Tooling/1.png"></div>
The Javascript function:
function changeImage(var i){
var img = document.getElementById("imgCh" + i + ".png");
if (img.src === "images/Tooling/" + i + ".png"){
img.src = "images/Tooling/" + i + "c.png";
}
else
{
img.src = "images/Tooling/" + i + ".png";
}
}`
The "1c.png" image is the one that is selected and should replace "1.png". There are multiple divs on this page that hold multiple images, which are named 2/2c, 3/3c, which is why the var i is included. Any insight? Thanks in advance.
You could do it something like this, it would also allow for different file names.
<img class="selectable" src="/images/Tooling/1.png"
data-original-source="/images/Tooling/1.png"
data-selected-source="/images/Tooling/1c.png">
<img class="selectable" src="/images/Tooling/2.png"
data-original-source="/images/Tooling/2.png"
data-selected-source="/images/Tooling/2c.png">
 
var images = document.getElementsByClassName('selectable');
for (var image of images) {
image.addEventListener('click', selectElementHandler);
}
function selectElementHandler(event) {
var image = event.target,
currentSrc = image.getAttribute('src'),
originalSrc = image.getAttribute('data-original-source'),
selectedSrc = image.getAttribute('data-selected-source'),
newSrc = currentSrc === originalSrc ? selectedSrc : originalSrc;
image.setAttribute('src', newSrc);
}
 
With comments:
// find all images with class "selectable"
var images = document.getElementsByClassName('selectable');
// add an event listener to each image that on click runs the "selectElementHandler" function
for (var image of images) {
image.addEventListener('click', selectElementHandler);
}
// the handler receives the event from the listener
function selectElementHandler(event) {
// the event contains lots of data, but we're only interested in which element was clicked (event.target)
var image = event.target,
currentSrc = image.getAttribute('src'),
originalSrc = image.getAttribute('data-original-source'),
selectedSrc = image.getAttribute('data-selected-source'),
// if the current src is the original one, set to selected
// if not we assume the current src is the selected one
// and we reset it to the original src
newSrc = currentSrc === originalSrc ? selectedSrc : originalSrc;
// actually set the new src for the image
image.setAttribute('src', newSrc);
}
Your problem is that javascript is returning the full path of the src (you can try alert(img.src); to verify this).
You could look up how to parse a file path to get the file name in javascript, if you want the most robust solution.
However, if you're sure that all your images will end in 'c.png', you could check for those last 5 characters, using a substring of the last 5 characters:
function changeImage(var i){
var img = document.getElementById("imgCh" + i);
if (img.src.substring(img.src.length - 5) === "c.png"){
img.src = "images/Tooling/" + i + ".png";
}
else
{
img.src = "images/Tooling/" + i + "c.png";
}
}

how to get photo compleet url form form in array

I am trying to use jquery to take a picture from my comp via a form.
- So I want the entire URL out of the form in an array
It works + / - in Dreamweaver, but not in the explorer browsers not even chrome
The end goal is a calendar with picture / app for people with disabilities, but as long as I get to go through the phone gap
var foto= new Array();
var i=-1;
//foto=["toets.png"];
$('#fotouit').append("FOTO UIT");
$('#knop01').click(function(){
$('input:file[name=foto]').each(function(){
//alert($(this).val());
foto.push($(this).val());
foto.forEach( function(){
i++;
$('#fotouit').append(foto[i]);
$('#fotouit').append('<img src=" '+ foto[i] + ' " width="100" height="100" />');
});
});
})
I don't think it is possible to get the URL of the picture in you computer's local filesystem, but you can use Javascript's FileReader API to read the contents of the uploaded file (in your case, the picture). The read contents can be used in the src of the img element as you did in your example code.
This is an in depth explanation of what you're trying to accomplish: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications
Example:
function handleFiles(files) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
var imageType = /image.*/;
if (!file.type.match(imageType)) {
continue;
}
var img = document.createElement("img");
img.classList.add("obj");
img.file = file;
preview.appendChild(img); // Assuming that "preview" is a the div output where the content will be displayed.
var reader = new FileReader();
reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);
reader.readAsDataURL(file);
}
}
Note:
You can use the multiple attribute on a file input to allow selecting many files with one input
You can use the file inputs change event to immediately capture the files rather than providing a second button to click

Add or remove slides using jQuery FlexSlider

Is it possible to add or remove slides in runtime using FlexSlider?
The new version of FlexSlider 2 already supports this methods.
slider.addSlide(obj, pos) accepts two parameters, a string/jQuery object and an index.
slider.removeSlide(obj) accepts one parameter, either an object to be removed, or an index.
This is just what I saw after looking at this thread.
The slider and the carousel object can be instantiated and added to like this:
$('#slider').data('flexslider').addSlide("");
$('#carousel').data('flexslider').addSlide("");
The click on the carousel to scroll to the particular image doesn't work, but the scroll buttons on both work.
The actual implementation of FlexSlider doesn't support it.
If you modify the actual implementation to return the slider object, with this object you can stop the slider, remove the slide you want and then recreate the slider.
After trying lots of different ideas, I got this solution to add or remove a new image or video in Flexslider dynamically and its working fine.
JQuery code:
$("#add2").change(function(event)
{
var fuData = document.getElementById('add2');
var files = event.target.files;
for(var i = 0; i< files.length; i++)
{
var file = files[i];
var filename = file.name;
var Extension =
filename.substring(filename.lastIndexOf('.') + 1).toLowerCase();
if(Extension == 'png' || Extension == 'jpg' || Extension == 'jpeg' || Extension == 'svg'){
var reader = new FileReader();
reader.onload = function(e)
{
var img = document.createElement("IMG");
img.src = e.target.result;
div = "<li><img src="+img.src+" /></li>";
$('.flexslider').data('flexslider').addSlide($(div));
}
}
else if (Extension == 'mp4')
{
var reader = new FileReader();
reader.onload = function(event){
var video = document.createElement("video");
video.src = event.target.result;
div = " <li><video src="+video.src+" width='100%' height='500' controls></video></li>";
$('.flexslider').data('flexslider').addSlide($(div));
}
}
else
{
alert(filename+' '+'is not in supported format');
$("#add2").val('');
}
reader.readAsDataURL(file);
}
});
function remove()
{
var slider = $('.flexslider').data('flexslider');
slider.removeSlide(slider.currentSlide);
}
HTML code:
<input type="file" id= "add2" multiple>
<button id="remove" onclick="remove()" value="Remove">Remove</button>
as per the code, with browse file, you can select multiple images and videos to add in Flexslider and with remove button, you can remove a current slide.I also added some validation so only image or video will be add in a slider. It will give an alert if you select any other extension. I created this code as per my requirement, you can customize it accordingly to your requirements.

Smilie system: Event to add image in textarea fails

I'm trying to create a personalized smilies system to train my JavaScript.
To accomplish that I have an offline system to save the various user smilies (I only save the urls).
After obtaining the data I try to make them appear above the textarea I want. So far so good!
Now, the problem comes when it's time to add the events to the images.
I try to add event listeners to each image but no matter which image I press only the last image event is triggered.
This is: all images appear side by side correctly but what is inserted in the textarea is the last image that is iterated in the cycle.
Meaningful code:
/* Insert the code in the right place in the textarea*/
function putInTxtarea(text, textarea) {
// Mozilla text range replace.
if (typeof(textarea.selectionStart) != "undefined") {
var begin = textarea.value.substr(0, textarea.selectionStart);
var end = textarea.value.substr(textarea.selectionEnd);
var scrollPos = textarea.scrollTop;
textarea.value = begin + text + end;
if (textarea.setSelectionRange)
{
textarea.focus();
textarea.setSelectionRange(begin.length + text.length, begin.length + text.length);
}
textarea.scrollTop = scrollPos;
}
// Just put it on the end.
else {
textarea.value += text;
textarea.focus(textarea.value.length - 1);
}
var elem = document.createElement("div");
elem.id = "mySmilies";
elem.innerHTML = "";
for each (url in smiliesUrl){
var img = document.createElement("img");
img.src = url;
img.style.cursor = "pointer";
img.addEventListener('click',
function(){putInTxtarea('[img]'+url+'[/img]', document.getElementsByName('message')[0]);
};, false); // here is the event attaching
elem.appendChild(img);
}
Don't use for each...in. This is a construct only available in Firefox (at least it is non-standard).
You are making the typical creating-a-function-in-a-loop mistake. JavaScript has only function scope. Every function you create in the loop has references to the same variables (url in your case) and this variable will have the value of the last URL after the loop finished. You need to introduce a new scope:
function createClickHandler(url) {
var target = document.getElementsByName('message')[0];
return function() {
putInTxtarea('[img]'+url+'[/img]', target);
}
}
// assuming smiliesUrl is an array
for(var i = smiliesUrl.length;i--;) {
var url = smiliesUrl[i];
var img = document.createElement("img");
img.src = url;
img.style.cursor = "pointer";
img.addEventListener('click', createClickHandler(url), false);
elem.appendChild(img);
}
Another possible is to simply access the image from the event handler. It should available via this:
img.addEventListener('click', function(){
putInTxtarea('[img]'+this.src+'[/img]',
document.getElementsByName('message')[0]);
};, false);
This seams to be a closure issue. the variable url points to the url used in the loop, and at the time of execution it is always be the last url.
for(url in smiliesUrl){
var img = document.createElement("img");
img.src = url;
img.style.cursor = "pointer";
var func = function(jUrl){
return function(){
putInTxtarea('[img]' + jUrl + '[/img]',
document.getElementsByName('message')[0]);
};
}(url);
img.addEventListener('click', func, false);
}
For more on closures in javascript see This question

Categories

Resources