I am trying to dynamically load an image tag, and on the very next line, trying to change its SRC attribute. It is not working. Could it be because it does not allow enough 'time' for the image tag to load into a receptacle DIV (#Div_Extend_2), before its SRC attribute get changed? The whole image upload form is loaded dynamically, and if the image tag is included in the first dynamic inclusion, it works; I am able to change the SRC atribute of the image. But if the img tag is put there using load(), just before the change attribute statement: $("#IMG_wlpst_PREV").attr('src',"IMAGES/Apples_in_a_basket.JPG"); is executed, it doesn't work.
Please note, in the CSS I have put display: none; for the image, when its included as part of the POST_IMG_1.PHP file.
Thank you, all help appreciated!! Please stay safe in this coronavirus period..
The main HTML document is as follows:
<div id='DIV_MAINPOST'>
<div id="DV_post_type">
<div id="div_POST_TXT">TEXT</div>
<div id="div_POST_IMG">Image!</div>
</div>
<div id="DIV_ERROR"> </div>
<div id="Div_Extend_1"> </div>
</div>
Javascript:
$('#DIV_MAINPOST').click(function(e){
switch(e.target.id)
{ case "div_POST_TXT":
$('#Div_Extend_1').html("");
break;
case "div_POST_IMG":
$('#Div_Extend_1').load('POST_IMAGE_1.php');
break;
} });
$('#DIV_MAINPOST').on('submit','#FORM_img', function(e){
alert("formsubmit");
e.preventDefault();
var FD = new FormData(this);
var FIL = FD.get("file_");
var ERS = 0;
if(FIL.length===0)
{ ERS++;
$("#DIV_ERROR").html("Error: No file");
}else if(!((FIL.type=='image/jpeg' ) || (FIL.type=='image/jpg') || (FIL.type=='image/png') || (FIL.type=='image/bmp')))
{ ERS++;
$("#DIV_ERROR").html("Err: Not Image");
}else if(FIL.size > (6*1024*1024)) //> 4MB
{ ERS++;
$("#DIV_ERROR").html("Err: Too Large");
}
if(ERS==0)
{ $("#IMG_wlpst_PREV").show(); //case: 1 tag is present with POST_IMG_1.php, default css is display: none;
$("#Div_Extend_2").load('POST_IMAGE_2.php'); // case: 2 loading tag with this stmt
$("#IMG_wlpst_PREV").attr('src',"IMAGES/Apples_in_a_basket.JPG"); //updating its info
} });
});
POST_IMG_1.PHP
<FORM method='post' action='PHP/FILE_UPLOAD_CHECK.PHP' id="FORM_img" enctype='multipart/form-data'>
<INPUT type='file' name='file_' size='10'></INPUT>
<button type='submit' value='upload'>Upload</button>
</FORM>
<div id="Div_Extend_2">
<img id="IMG_wlpst_PREV"></img> //case 1:: img tag included in the same file (which is also load()'ed, works fine. SRC gets updated.
//case 2:: this tag is not present, but the "Div_Extend_2" div is still present in POST_IMG_1.php.
</div>
POST_IMG_2.PHP
<img id="IMG_wlpst_PREV"></img> //case 2::if loaded using $("#Div_Extend_2").load('POST_IMG_2.PHP'), doesn't work;
CSS
#DIV_MAINPOST
{ width: 310px;
background-color: grey;
display: flex;
flex-direction: column;
}
#DV_post_type
{ order: 1;
flex-direction: row;
display: flex;
}
#div_POST_TXT
{ order: 1;
width: 150px;
border: 2px solid black;
background-color: pink;
}
#div_POST_IMG
{ order: 2;
width: 150px;
border: 2px solid black;
background-color: pink;
}
#DIV_ERROR
{ order: 2;
border: 1px solid red;
width: 300px;
height: 30px;
color: red;
}
#Div_Extend_1
{ order: 3;
}
#IMG_wlpst_PREV
{ display: none; //case 1
width: 300px;
height: 300px;
}
Related
My goal is to have text change onmouseover from "hello" (without a link) to "Google" and provide an 'href' on the resulting "Google" text, and then revert to "hello" onmouseout without a link.
The code below works in changing the text from "hello" to "Google" but,
the link on "Google" does not work (even though I can right-click on "Google" and open the link on another tab)
the text does not change back to "hello" onmouseout.
Thanks for your help in advance!
Here is my code:
<style>
.container {
margin-top: 6vw;
margin-left: 40%;
margin-right: 40%;
}
</style>
<div class="container">
<h1>
<div class="hello" id="hello1" onmouseover="changeText()" onmouseout="changeText(this,'Hello.')">Hello.</div>
</h1>
</div>
<script>
function changeText() {
if (document.getElementById("hello1")) {
a = document.getElementById("hello1")
a.innerHTML = 'Google'
}
}
</script>
try this way onmouseout="this.innerHTML='Hello.';"
function changeText() {
if (document.getElementById("hello1")) {
a = document.getElementById("hello1")
a.innerHTML = 'Google'
}
}
.container {
margin-top: 6vw;
margin-left: 40%;
margin-right: 40%;
}
<div class="container">
<h1>
<div class="hello" id="hello1" onmouseover="changeText()" onmouseout="this.innerHTML='Hello.';">Hello.</div>
</h1>
</div>
By changing a class of a parent tag, any and all child tags can be affected via CSS. Having the HTML ready when the page loads and then hiding it is better than constantly creating and destroying HTML for trivial effects.
The events "mouseenter" and "mouselrave" are handled by a property event handler and an event listener. Either one is sufficient, but avoid using attribute event handlers:
<div onmouselame="lameAttributeEventHandler()">...</div>
Details are commented in the example below
// Reference the <header>
const hdr = document.querySelector('.title');
/* This is a property event handler
// Whenever the mouse enters within the borders of
// the <header>:
// '.google' class is added
// '.hello' class is removed
*/
hdr.onmouseenter = function(event) {
this.classList.add('google');
this.classList.remove('hello');
};
/* This is an even listener
// Whenever the mouse exits the <header> the
// opposite behavior of the previous handler
// happens
*/
hdr.addEventListener("mouseleave", function(event) {
this.classList.add('hello');
this.classList.remove('google');
});
.title {
height: 50px;
margin-top: 3vh;
border: 3px solid black;
text-align: center;
}
h1 {
margin: auto 0;
}
.hello span {
display: inline-block;
}
.hello a {
display: none;
}
.google a {
display: inline-block;
}
.google span {
display: none;
}
<header class="title hello">
<h1>
<span>Hello</span>
Google
</h1>
</header>
You can try this, May it help u to solve the problem
<!DOCTYPE html>
<head>
<title>change text on mouse over and change back on mouse out
</title>
<style>
#box {
float: left;
width: 150px;
height: 150px;
margin-left: 20px;
margin-top: 20px;
padding: 15px;
border: 5px solid black;
}
</style>
</head>
<html>
<body>
<div id="box" onmouseover="changeText('Yes, this is Onmouseover Text')" onmouseout="changeback('any thing')" >
<div id="text-display" >
any thing
</div>
</div>
<script type="text/javascript">
function changeText(text)
{
var display = document.getElementById('text-display');
display.innerHTML = "";
display.innerHTML = text;
}
function changeback(text)
{
var display = document.getElementById('text-display');
display.innerHTML = "";
display.innerHTML = text;
}
</script>
</body>
</html>
Hi I am trying to replace the choose file button with an image. I am using javascript to create the button but when I am inspecting the website, it shows me a html script of the button which is of type= file.
To create it, I used:
input = createFileInput(handleFile);
input.elt.style["width"] = "40%";
input.elt.style["font-size"]="3vmin";
function handleFile(file) {
print(file);
if (file.type === 'image') {
imgFile = file.data;
img = createImg(file.data);
img.hide();
canvas.image(img, 0, 0, 224, 224);
image(img, 0, 0, width, height/2);
img.remove();
}
mode = 1;
tint = false;
}
Can anyone suggest how I can change the generic button with an image.
I think you can cheat and position an image over the input, then add a click handler to the image and pass it through to the input button below.
Is this what you are trying to achieve?
const input = document.querySelector("#avatar");
const button = document.querySelector("#button");
button.addEventListener('click', event => input.click(event));
.body {
font-family: sans-serif;
}
label {
display: inline-block;
padding: 1em 0;
}
.wrapper {
position: relative;
}
#avatar {
display: block;
height: 50px;
border: 1px solid #333;
}
#button {
position: absolute;
left: 1px;
top: 1px;
}
<div class="body">
<label for="avatar">Choose a profile picture:</label>
<div class="wrapper">
<input type="file" id="avatar" name="avatar">
<img id="button" src="https://via.placeholder.com/75x50/333333/ffffff?text=Avatar"></img>
</div>
</div>
In chrome, following input element can be dragged and dropped to the bottom area of the input.
I expect this behavior.
<input type="file" class="input-file">
<style>
.input-file {
display: block;
width: 300px;
height: 300px;
border: 1px solid red;
margin: 10px;
}
</style>
However, it is different inside Shadow DOM.
Following input element can be dragged and dropped to only the "choose file" button located the left top area of the input.
Dropped file is opened not chosen when file is droppped to the bottom area of the input.
customElements.define("foo-bar", class extends HTMLElement {
constructor(){
super()
this.attachShadow({mode: "open"}).innerHTML = `
<input type="file" class="input-file">
<style>
.input-file {
display: block;
width: 300px;
height: 300px;
border: 1px solid red;
margin: 10px;
}
</style>
`
}
})
document.body.innerHTML = "<foo-bar></foo-bar>"
I think that this is a bug caused by events not being notified outside of Shadow DOM.
Is there a workaround?
The workaround is to process the drop event.
this.shadowRoot.querySelector( 'input' ).ondrop = ev => {
console.log( 'dropped in', ev.dataTransfer.items.length )
for ( var i = 0 ; i < ev.dataTransfer.items.length ; i++ ) {
if (ev.dataTransfer.items[i].kind === 'file') {
var file = ev.dataTransfer.items[i].getAsFile()
console.log( 'file[' + i + '].name = ' + file.name )
}
}
ev.preventDefault()
}
Don't forget to invoke the preventDefault() method to abort the file opening.
I know this is an old question but the bug is still not fixed. I found a CSS workaround for Chrome to use the input button instead of the input for the draft & drop. In my case I used an opacity of 0 so the design is not an issue for me.
customElements.define("foo-bar", class extends HTMLElement {
constructor(){
super()
this.attachShadow({mode: "open"}).innerHTML = `
<input type="file" />
<style>
input {
display: block;
width: 300px;
height: 300px;
border: 1px solid red;
margin: 10px;
}
input::-webkit-file-upload-button {
width: 300px;
height: 300px;
}
</style>
`
}
})
<foo-bar></foo-bar>
i want that before the actual image gets loaded a spinner should be shown so that my website can load faster
window.addEventListener('load', function(){
var allimages= document.getElementsByTagName('img');
for (var i=0; i<allimages.length; i++) {
if (allimages[i].getAttribute('data-src')) {
allimages[i].setAttribute('src', allimages[i].getAttribute('data-src'));
}
}
}, false)
<img src="https://loremflickr.com/400/600" data-src="images/banguet-hall-location-icon.png" class="secEightImg" />
<img src="http://www.jettools.com/images/animated_spinner.gif" data-src="images/banguet-hall-location-icon.png" class="secEightImg" />
<script>
</script>
the problem is the actual image is shown two times and instead of spinner a broken image (which is shown when no image is found) is shown first
please help
If you want a spinner per image, just add the spinner URL as the initial src attribute for all of them:
<img src="spinner.gif" data-src="actual-image.png" />
Then, once the page loads, change all those src for the real URL (data-src) and listen for the load and error events on each image.
For each of them, add a .loaded class or .error class to the images and style them as you want. For example, you could hide the ones that could not be loaded, show a custom "error" image (using background-image) or style them as you wish, like in this example:
function imageLoaded(e) {
updateImage(e.target, 'loaded');
}
function imageError(e) {
updateImage(e.target, 'error');
}
function updateImage(img, classname) {
// Add the right class:
img.classList.add(classname);
// Remove the data-src attribute:
img.removeAttribute('data-src');
// Remove both listeners:
img.removeEventListener('load', imageLoaded);
img.removeEventListener('error', imageError);
}
window.addEventListener('load', () => {
Array.from(document.getElementsByTagName('img')).forEach(img => {
const src = img.getAttribute('data-src');
if (src) {
// Listen for both events:
img.addEventListener('load', imageLoaded);
img.addEventListener('error', imageError);
// Just to simulate a slow network:
setTimeout(() => {
img.setAttribute('src', src);
}, 2000 + Math.random() * 2000);
}
});
})
html,
body {
margin: 0;
height: 100%;
}
.images {
width: 100%;
height: 100%;
background: #000;
display: flex;
align-items: center;
overflow-x: scroll;
}
.margin-fix {
border-right: 1px solid transparent;
height: 16px;
}
img {
width: 16px;
height: 16px;
margin: 0 64px;
}
img.loaded {
width: auto;
height: 100%;
margin: 0;
}
img.error {
background: red;
border-radius: 100%;
/* You could add a custom "error" image here using background-image */
}
<div class="images">
<img
src="https://i.stack.imgur.com/RvfGz.gif"
data-src="https://d39a3h63xew422.cloudfront.net/wp-content/uploads/2014/07/20145029/driven-by-design-the-incomparable-lancia-stratos-1476934711918-1000x573.jpg" />
<img
src="https://i.stack.imgur.com/RvfGz.gif"
data-src="https://car-images.bauersecure.com/pagefiles/76591/1752x1168/ford_racing_puma_01.jpg?mode=max&quality=90&scale=down" />
<img
src="https://i.stack.imgur.com/RvfGz.gif"
data-src="http://doesntexist.com/image.jpg" />
<span class="margin-fix"></span>
</div>
The problem is that the spinner image you use initially might take some time to load.
One solution would be to use a data URI, so instead of:
<img src="https://i.stack.imgur.com/RvfGz.gif" data-src="actual-image.png" />
You would have:
<img src="data:image/gif;base64,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cXVlcnknPmZ1bmN0aW9uLm15c3FsLXF1ZXJ5PC9hPl06IENhbid0IGNvbm5lY3QgdG8gbG9jYWwgTXlTUUwgc2VydmVyIHRocm91Z2ggc29ja2V0ICcvdmFyL3J1bi9teXNxbGQvbXlzcWxkLnNvY2snICgyKSBpbiA8Yj4vaG9tZS9hamF4bG9hZC93d3cvbGlicmFpcmllcy9jbGFzcy5teXNxbC5waHA8L2I+IG9uIGxpbmUgPGI+Njg8L2I+PGJyIC8+CjxiciAvPgo8Yj5XYXJuaW5nPC9iPjogIG15c3FsX3F1ZXJ5KCkgWzxhIGhyZWY9J2Z1bmN0aW9uLm15c3FsLXF1ZXJ5Jz5mdW5jdGlvbi5teXNxbC1xdWVyeTwvYT5dOiBBIGxpbmsgdG8gdGhlIHNlcnZlciBjb3VsZCBub3QgYmUgZXN0YWJsaXNoZWQgaW4gPGI+L2hvbWUvYWpheGxvYWQvd3d3L2xpYnJhaXJpZXMvY2xhc3MubXlzcWwucGhwPC9iPiBvbiBsaW5lIDxiPjY4PC9iPjxiciAvPgo8YnIgLz4KPGI+V2FybmluZzwvYj46ICBteXNxbF9xdWVyeSgpIFs8YSBocmVmPSdmdW5jdGlvbi5teXNxbC1xdWVyeSc+ZnVuY3Rpb24ubXlzcWwtcXVlcnk8L2E+XTogQ2FuJ3QgY29ubmVjdCB0byBsb2NhbCBNeVNRTCBzZXJ2ZXIgdGhyb3VnaCBzb2NrZXQgJy92YXIvcnVuL215c3FsZC9teXNxbGQuc29jaycgKDIpIGluIDxiPi9ob21lL2FqYXhsb2FkL3d3dy9saWJyYWlyaWVzL2NsYXNzLm15c3FsLnBocDwvYj4gb24gbGluZSA8Yj42ODwvYj48YnIgLz4KPGJyIC8+CjxiPldhcm5pbmc8L2I+OiAgbXlzcWxfcXVlcnkoKSBbPGEgaHJlZj0nZnVuY3Rpb24ubXlzcWwtcXVlcnknPmZ1bmN0aW9uLm15c3FsLXF1ZXJ5PC9hPl06IEEgbGluayB0byB0aGUgc2VydmVyIGNvdWxkIG5vdCBiZSBlc3RhYmxpc2hlZCBpbiA8Yj4vaG9tZS9hamF4bG9hZC93d3cvbGlicmFpcmllcy9jbGFzcy5teXNxbC5waHA8L2I+IG9uIGxpbmUgPGI+Njg8L2I+PGJyIC8+CjxiciAvPgo8Yj5XYXJuaW5nPC9iPjogIG15c3FsX3F1ZXJ5KCkgWzxhIGhyZWY9J2Z1bmN0aW9uLm15c3FsLXF1ZXJ5Jz5mdW5jdGlvbi5teXNxbC1xdWVyeTwvYT5dOiBDYW4ndCBjb25uZWN0IHRvIGxvY2FsIE15U1FMIHNlcnZlciB0aHJvdWdoIHNvY2tldCAnL3Zhci9ydW4vbXlzcWxkL215c3FsZC5zb2NrJyAoMikgaW4gPGI+L2hvbWUvYWpheGxvYWQvd3d3L2xpYnJhaXJpZXMvY2xhc3MubXlzcWwucGhwPC9iPiBvbiBsaW5lIDxiPjY4PC9iPjxiciAvPgo8YnIgLz4KPGI+V2FybmluZzwvYj46ICBteXNxbF9xdWVyeSgpIFs8YSBocmVmPSdmdW5jdGlvbi5teXNxbC1xdWVyeSc+ZnVuY3Rpb24ubXlzcWwtcXVlcnk8L2E+XTogQSBsaW5rIHRvIHRoZSBzZXJ2ZXIgY291bGQgbm90IGJlIGVzdGFibGlzaGVkIGluIDxiPi9ob21lL2FqYXhsb2FkL3d3dy9saWJyYWlyaWVzL2NsYXNzLm15c3FsLnBocDwvYj4gb24gbGluZSA8Yj42ODwvYj48YnIgLz4K" data-src="actual-image.png" />
As you can see, your HTML document will grow fast using this approach, which is a problem.
A better approach might be to use CSS to add the spinner so that you only include the data URI once. To do that, you need to add an empty src attribute to your images initially anyway:
<img src data-src="actual-image.png" />
Or:
<img src="" data-src="actual-image.png" />
If you don't put it, the image will have an annoying gray border you can't get rid of until you add a src attribute.
function imageLoaded(e) {
updateImage(e.target, 'loaded');
}
function imageError(e) {
updateImage(e.target, 'error');
}
function updateImage(img, classname) {
// Add the right class:
img.classList.add(classname);
// Remove the data-src attribute:
img.removeAttribute('data-src');
// Remove both listeners:
img.removeEventListener('load', imageLoaded);
img.removeEventListener('error', imageError);
}
window.addEventListener('load', () => {
Array.from(document.getElementsByTagName('img')).forEach(img => {
const src = img.getAttribute('data-src');
if (src) {
// Listen for both events:
img.addEventListener('load', imageLoaded);
img.addEventListener('error', imageError);
// Just to simulate a slow network:
setTimeout(() => {
img.setAttribute('src', src);
}, 2000 + Math.random() * 2000);
}
});
})
html,
body {
margin: 0;
height: 100%;
}
.images {
width: 100%;
height: 100%;
background: #000;
display: flex;
align-items: center;
overflow-x: scroll;
}
.margin-fix {
border-right: 1px solid transparent;
height: 16px;
}
img {
width: 16px;
height: 16px;
margin: 0 64px;
background-image: url("data:image/gif;base64,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cXVlcnknPmZ1bmN0aW9uLm15c3FsLXF1ZXJ5PC9hPl06IENhbid0IGNvbm5lY3QgdG8gbG9jYWwgTXlTUUwgc2VydmVyIHRocm91Z2ggc29ja2V0ICcvdmFyL3J1bi9teXNxbGQvbXlzcWxkLnNvY2snICgyKSBpbiA8Yj4vaG9tZS9hamF4bG9hZC93d3cvbGlicmFpcmllcy9jbGFzcy5teXNxbC5waHA8L2I+IG9uIGxpbmUgPGI+Njg8L2I+PGJyIC8+CjxiciAvPgo8Yj5XYXJuaW5nPC9iPjogIG15c3FsX3F1ZXJ5KCkgWzxhIGhyZWY9J2Z1bmN0aW9uLm15c3FsLXF1ZXJ5Jz5mdW5jdGlvbi5teXNxbC1xdWVyeTwvYT5dOiBBIGxpbmsgdG8gdGhlIHNlcnZlciBjb3VsZCBub3QgYmUgZXN0YWJsaXNoZWQgaW4gPGI+L2hvbWUvYWpheGxvYWQvd3d3L2xpYnJhaXJpZXMvY2xhc3MubXlzcWwucGhwPC9iPiBvbiBsaW5lIDxiPjY4PC9iPjxiciAvPgo8YnIgLz4KPGI+V2FybmluZzwvYj46ICBteXNxbF9xdWVyeSgpIFs8YSBocmVmPSdmdW5jdGlvbi5teXNxbC1xdWVyeSc+ZnVuY3Rpb24ubXlzcWwtcXVlcnk8L2E+XTogQ2FuJ3QgY29ubmVjdCB0byBsb2NhbCBNeVNRTCBzZXJ2ZXIgdGhyb3VnaCBzb2NrZXQgJy92YXIvcnVuL215c3FsZC9teXNxbGQuc29jaycgKDIpIGluIDxiPi9ob21lL2FqYXhsb2FkL3d3dy9saWJyYWlyaWVzL2NsYXNzLm15c3FsLnBocDwvYj4gb24gbGluZSA8Yj42ODwvYj48YnIgLz4KPGJyIC8+CjxiPldhcm5pbmc8L2I+OiAgbXlzcWxfcXVlcnkoKSBbPGEgaHJlZj0nZnVuY3Rpb24ubXlzcWwtcXVlcnknPmZ1bmN0aW9uLm15c3FsLXF1ZXJ5PC9hPl06IEEgbGluayB0byB0aGUgc2VydmVyIGNvdWxkIG5vdCBiZSBlc3RhYmxpc2hlZCBpbiA8Yj4vaG9tZS9hamF4bG9hZC93d3cvbGlicmFpcmllcy9jbGFzcy5teXNxbC5waHA8L2I+IG9uIGxpbmUgPGI+Njg8L2I+PGJyIC8+CjxiciAvPgo8Yj5XYXJuaW5nPC9iPjogIG15c3FsX3F1ZXJ5KCkgWzxhIGhyZWY9J2Z1bmN0aW9uLm15c3FsLXF1ZXJ5Jz5mdW5jdGlvbi5teXNxbC1xdWVyeTwvYT5dOiBDYW4ndCBjb25uZWN0IHRvIGxvY2FsIE15U1FMIHNlcnZlciB0aHJvdWdoIHNvY2tldCAnL3Zhci9ydW4vbXlzcWxkL215c3FsZC5zb2NrJyAoMikgaW4gPGI+L2hvbWUvYWpheGxvYWQvd3d3L2xpYnJhaXJpZXMvY2xhc3MubXlzcWwucGhwPC9iPiBvbiBsaW5lIDxiPjY4PC9iPjxiciAvPgo8YnIgLz4KPGI+V2FybmluZzwvYj46ICBteXNxbF9xdWVyeSgpIFs8YSBocmVmPSdmdW5jdGlvbi5teXNxbC1xdWVyeSc+ZnVuY3Rpb24ubXlzcWwtcXVlcnk8L2E+XTogQSBsaW5rIHRvIHRoZSBzZXJ2ZXIgY291bGQgbm90IGJlIGVzdGFibGlzaGVkIGluIDxiPi9ob21lL2FqYXhsb2FkL3d3dy9saWJyYWlyaWVzL2NsYXNzLm15c3FsLnBocDwvYj4gb24gbGluZSA8Yj42ODwvYj48YnIgLz4K");
}
img.loaded {
width: auto;
height: 100%;
margin: 0;
}
img.error {
background: red;
border-radius: 100%;
/* You could add a custom "error" image here using background-image */
}
<div class="images">
<img
src
data-src="https://d39a3h63xew422.cloudfront.net/wp-content/uploads/2014/07/20145029/driven-by-design-the-incomparable-lancia-stratos-1476934711918-1000x573.jpg" />
<img
src
data-src="https://car-images.bauersecure.com/pagefiles/76591/1752x1168/ford_racing_puma_01.jpg?mode=max&quality=90&scale=down" />
<img
src
data-src="http://doesntexist.com/image.jpg" />
<span class="margin-fix"></span>
</div>
Other approaches might be to just hide the images initially with display: none for example, in which case you might want a wrapper around them to show something like an empty box to indicate the users that something will be shown in there, or even a spinner made with other elements if you want/need to get fancy.
What you can do is something like:
$(".sly-main-slider div img").attr('src', "#");
$(".sly-main-slider").addClass("loading");
$(".sly-main-slider div").hide();
$(".sly-main-slider div img").load(function() {
$(".sly-main-slider div").show();
$(".sly-main-slider").removeClass("loading");
}).attr('src', "https://loremflickr.com/400/600");
.loading {
position: absolute;
top: 10%;
left: 10%;
z-index: 2000;
background: url(http://1.bp.blogspot.com/-nfXo9GWbDtM/VOn0vr4yLMI/AAAAAAAABCA/dDNgd7_QCFo/s1600/block-loader.gif) no-repeat center center;
height: 32px;
width: 32px;
}
.loading:after {
position: absolute;
top: 8px;
left: 40px;
content: 'Loading...';
}
body {
position: relative;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='sly-main-slider'>
<div>
<img src="https://loremflickr.com/400/600" alt="" />
</div>
</div>
I am implementing a 'blades' experience in a page. When I append an additional Blade into the Container...the previous blades 'pop' down.
Q: How do I append a new element into view without effecting previous elements?
MY FIDDLE:
I created a JSFiddle...but the service is not currently available...I will append it shortly.
https://jsfiddle.net/PrisonerZ3RO/oynae1hd/4/#
MY CSS:
<style>
/** DASHBOARD CONTAINER **/
.dashboard-container { border-right: solid 1px #000; margin-top: 5px; margin-bottom: 5px; overflow-x: scroll; white-space: nowrap; width: 100%; }
.dashboard-container .widget { clear: both; display: inline-block; vertical-align: top; }
/** FORM CONTAINER **/
.form-container { border: 1px solid #ccc; border-radius: 3px; height: 500px; margin-bottom: 5px; padding: 5px; width: 500px; }
/** BLADE CONTAINER **/
.blade-container .blade { border: 1px solid #ccc; border-radius: 3px; display: inline-block; height: 506px; margin-right: 2px; padding: 2px; width: 200px; }
</style>
MY HTML:
<script id="tmplBlade" type="text/template">
<div class="blade">
Blade
</div>
</script>
<div class="dashboard-container">
<div class="widget">
<div class="form-container">
Form Controls go here
<input id="btnAppend" type="button" value="Append Blade" />
</div>
</div>
<div class="widget">
<div class="blade-container">
</div>
</div>
</div>
MY JAVASCRIPT:
<script type="text/javascript">
$(document).ready(function () {
function PageController()
{
var that = this,
dictionary = {
elements: { btnAppend: null, bladeContainer: null },
selectors: { btnAppend: '#btnAppend', bladeContainer: '.blade-container', tmplBlade: '#tmplBlade' }
};
var initialize = function () {
// Elements
dictionary.elements.btnAppend = $(dictionary.selectors.btnAppend);
dictionary.elements.bladeContainer = $(dictionary.selectors.bladeContainer);
// Events
dictionary.elements.btnAppend.on('click', that.on.click.btnAppend);
};
this.on = {
click: {
btnAppend: function (e) {
var html = $(dictionary.selectors.tmplBlade).html().trim();
var $element = $(html);
$element.hide();
dictionary.elements.bladeContainer.prepend($element);
// Slide-in
$element.show('slide', { direction: 'left' });
}
}
};
initialize();
}
var pageController = new PageController();
});
</script>
I've come across this problem before. The only way I've found to get around it is to do the following:
1) Create a .hidden class width margin-left: -200px
2) Add a CSS transition on margin-left to the .blade class
3) Apply the .hidden class to a new blade
4) Show the new blade
5) Remove the .hidden class from the new blade
Please see the following fork of your fiddle for a working solution: https://jsfiddle.net/yxL4embt/
How do I append a new element into view without effecting previous elements?
I'm not sure if I entirely get what you're asking since you'll always be affecting the other elements by moving them over when you append a new element. You can, however, prevent the pop-down effect you're seeing. The .ui-effects-wrapperadded by jQuery UI is display: block, so add the following to your CSS:
.blade-container .ui-effects-wrapper {
display: inline-block !important;
}
Then make sure your other blades are always aligned to the top of your container:
.blade-container .blade {
...
...
vertical-align: top;
}
This will bump all the blades over (right) and allow a new blade to slide in from the left.