I'm moving divs around based on a responsive layout that requires them to be in different places at different viewports. In the below example I want them to move as so, they do as expected... except, when I have more than one 'release' div on the page it takes each 'soundcloud' div and appends it to each 'release'. So if I have 3 'release' divs each one has 3 'soundcloud' divs. How can I edit the code so that the 'soundcloud' div within each 'release' is appended and nothing else.
$(function () {
var mobile = false;
var desktop = false;
var $window = $(window);
function checkWidth() {
var windowsize = $window.width();
if (windowsize <= 1024) {
if (!mobile) {
$(".release .soundcloud").appendTo(".release .info");
}
mobile = true;
desktop = false;
} else {
if (!desktop) {
$(".release .soundcloud").appendTo(".release .show-hide");
}
mobile = false;
desktop = true;
}
}
checkWidth();
$(window).resize(checkWidth);
});
Edited to add HTML:
<div class="release clearfix">
<span class="show-details open-close">➕</span>
<figure class="artwork">
<img src="assets/images/artwork1.jpg" alt="Album Artwork">
</figure>
<div class="info">
<h1 class="title">Title</h1>
<div class="soundcloud">
<iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/12345678"></iframe>
</div>
</div>
<div class="show-hide">
<div class="options clearfix">
<p>£9.99</p>
<p><span></span>Buy</p>
</div>
<div class="tracks">
<h3>Tracklisting</h3>
<ul>
<li>Track 1</li>
</ul>
<h3>Produced by</h3>
<p>Author</p>
</div>
<div class="further-info">
<h3>Release Date</h3>
<p>14/12/2013</p>
</div>
</div>
</div>
As #Cuberto mentioned it is not a good idea to achieve it using javascript.
But to try it out you can iterate over each release element and perform the append for the corresponding child elements inside the release div.
function checkWidth() {
var windowsize = $window.width();
var $releaseDivs = $('.release');
if (windowsize <= 1024) {
if (!mobile) {
$('.release').each(function() {
$('.soundcloud', this).appendTo($('.info', this));
});
}
mobile = true;
desktop = false;
} else {
if (!desktop) {
$('.release').each(function() {
$('.soundcloud', this).appendTo($('.show-hide', this));
});
}
mobile = false;
desktop = true;
}
}
I have not tried it but you can try this
#media (max-width: 1024px) {
.hide-mobile {
display: none;
}
}
HTML
<div class="soundcloud hide-mobile">
<iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/12345678"></iframe>
</div>
Related
I wrote a code to view the chat history. Everything works fine, but I realized that. When you scroll up the div to view the history, old posts are displayed at a time. I've added this code $("#messages").scrollTop(200); to be able to continue scrolling, but this should not be. When you want to view old messages in apps like whatsapp or facebook, you can continue to scroll up for viewing old messages.
What am I supposed to do to stay position after response?
Here is DEMO page.
$(document).ready(function() {
var logDown = $(".chatContainer");
logDown.animate({ scrollTop: logDown.prop("scrollHeight") }, 0);
var messages = ''; // New Posts are in demo
var scrollLoading = true;
$("#messages").scrollTop($("#messages")[0].scrollHeight);
$("#messages").on("scroll", function() {
if (scrollLoading && $("#messages").scrollTop() == 0) {
$("#messages").prepend(messages);
$("#messages").scrollTop(200);
}
});
});
now I understood, i solved it by subtracting the old-height from the new height and set this "old-position" as scrolltop
var old_height,new_height;
$("#messages").on("scroll", function() {
if (scrollLoading && $("#messages").scrollTop() == 0) {
old_height = $("#messages")[0].scrollHeight;
$("#messages").prepend(messages);
new_height = $("#messages")[0].scrollHeight;
$("#messages").scrollTop(new_height - old_height);
}
});
works optimal for me
If I understood your problem you don't want to scroll to the top of the messages at every batch of prepends.
I managed to pull a version without jQuery and using window.requestAnimationFrame for good scroll performance.
Just my $0.02 on the problem.
var container = document.querySelector("#messages");
container.scrollTop = container.scrollHeight;
container.addEventListener("scroll", function(e) {
last_known_scroll_position = e.target.scrollTop;
var ticking;
if (!ticking) {
window.requestAnimationFrame(function() {
if (last_known_scroll_position == 0) {
var delta = e.target.scrollHeight;
for (var i = 1; i <= 5; i++) {
var message = document.createElement("DIV");
message.textContent = "Message Here";
message.classList.add("message", "red");
e.target.prepend(message);
}
delta = e.target.scrollHeight - delta;
e.target.scrollTop = delta;
ticking = false;
}
});
ticking = true;
}
});
DIV.chatContainer {
height: 200px;
overflow: auto;
}
.message {
margin-bottom:10px;
}
.red {
background-color:red;
}
<div class="container">
<div class="chatContainer" id="messages">
<div class="message">Message HERE</div>
<div class="message">Message HERE</div>
<div class="message">Message HERE</div>
<div class="message">Message HERE</div>
<div class="message">Message HERE</div>
<div class="message">Message HERE</div>
<div class="message">Message HERE</div>
<div class="message">Message HERE</div>
<div class="message">Message HERE</div>
<div class="message">Message HERE</div>
<div class="message">Message HERE</div>
<div class="message">Message HERE</div>
<div class="message">Message HERE</div>
<div class="message">Message HERE last</div>
</div>
</div>
I know it sounds a bit confusing.
Here is what I'm trying to do:
I have five pictures,
each of the picture has a set of classes,
each time when clicked on one of the pictures the id (same as class name) will be pushed in to an array.
At the end, I want to only show the pictures if they contain the same classes (id) found in that array.
<div id="cameras" class="row text-center ">
<div id="d5" class=" professional landscape wedding micro sportaction wildlife portrait astrophotographer cameras">
<div class="thumbnail">
<img src="images/d5.png" alt="D5">
</div>
</div>
<div id="d810a" class=" professional landscape astrophotographer portrait micro cameras">
<div class="thumbnail">
<img src="images/d810a.png" alt="D3300">
</div>
</div>
<div id="d810" class=" professional landscape wedding micro portrait cameras">
<div class="thumbnail">
<img src="images/d810.png" alt="D810">
</div>
</div>
<div id="d750" class=" enthusiast landscape wedding micro sportaction wildlife portrait astrophotographer cameras">
<div class="thumbnail">
<img src="images/D750.png" alt="D750">
</div>
</div>
</div>
$('#sportaction').on('click', function () {
if ($("#sportaction").attr('data-click-state') == 1) {
$(this).attr('data-click-state', 0);
$("#snaButton").css({ fill: "#00725C" });
} else {
$(this).attr('data-click-state', 1);
$("#snaButton").css({ fill: "#00A388" })
}
});
$("#finish").click(function() {
$("[data-click-state= '0' ]").each(function () {
type_array.push($(this).attr("id"));
//some.push(this.id);
});
});
For example: If I clicked on "enthusiast" and "landscape" Only d750 should show up.
The code below doesn't work.
$(".cameras").each(function () {
$(this).hide();
for (var i = 0; i < type_array.length; i++) {
if ($(this).hasClass(type_array[i])) {
$(this).show();
}
}
});
I do not know if I understand correctly your question, but try this?
var type_array = [];
$(".cameras").click(function() {
var classArray = $(this).attr('class').split(/\s+/);
$.each(classArray, function() {
if (this.length > 0 && this != "cameras" && type_array.indexOf(this) == -1) {
type_array[type_array.length] = this + "";
}
})
})
and somewhere else:
$(".cameras").each(function () {
$(this).hide();
var clicked = this;
var hasAllClasses = true;
$.each(type_array,function(){
if($(clicked).hasClass(this)){
return true;
}
hasAllClasses=false;
return false;
});
if(hasAllClasses===true){
$(clicked).show();
}
});
type_array=[];
I have some scripts here that show and hide divs when click. Now what I need is to just only display one div at a time. I have a code that controls them all but its not working I don't know about much of javascript.
This is the first example of show/hide function that can be done simultaneously without hiding the other divs.
FIDDLE HERE
HTML:
<a href="javascript:ReverseDisplay('uniquename')">
Click to show/hide.
</a>
<div id="uniquename" style="display:none;">
<p>Content goes here.</p>
</div>
<a href="javascript:ReverseDisplay('uniquename1')">
Click to show/hide.
</a>
<div id="uniquename1" style="display:none;">
<p>Content goes here.</p>
</div>
SCRIPT:
function HideContent(d) {
document.getElementById(d).style.display = "none";
}
function ShowContent(d) {
document.getElementById(d).style.display = "block";
}
function ReverseDisplay(d) {
if (document.getElementById(d).style.display == "none") {
document.getElementById(d).style.display = "block";
} else {
document.getElementById(d).style.display = "none";
}
}
function HideAllShowOne(d) {
// Between the quotation marks, list the id values of each div.
var IDvaluesOfEachDiv = "idone idtwo uniquename1 uniquename";
//-------------------------------------------------------------
IDvaluesOfEachDiv = IDvaluesOfEachDiv.replace(/[,\s"']/g," ");
IDvaluesOfEachDiv = IDvaluesOfEachDiv.replace(/^\s*/,"");
IDvaluesOfEachDiv = IDvaluesOfEachDiv.replace(/\s*$/,"");
IDvaluesOfEachDiv = IDvaluesOfEachDiv.replace(/ +/g," ");
var IDlist = IDvaluesOfEachDiv.split(" ");
for(var i=0; i<IDlist.length; i++) { HideContent(IDlist[i]); }
ShowContent(d);
}
The other fiddle I created would do what I need but the script seems not to be working. Fiddle here
Found the solution on my code thanks to #Abhas Tandon
Fiddle here the extra id's inside the IDvaluesOfEachDiv seems to be making some error with the codes.
If you are happy with IE10+ support then
function ReverseDisplay(d) {
var els = document.querySelectorAll('.toggle.active:not(#' + d + ')');
for (var i = 0; i < els.length; i++) {
els[i].classList.remove('active');
}
document.getElementById(d).classList.toggle('active')
}
.toggle {
display: none;
}
.toggle.active {
display: block;
}
<a href="javascript:ReverseDisplay('uniquename')">
Click to show/hide.
</a>
<div id="uniquename" class="toggle">
<p>Content goes here.</p>
</div>
<a href="javascript:ReverseDisplay('uniquename1')">
Click to show/hide.
</a>
<div id="uniquename1" class="toggle">
<p>Content goes here.</p>
</div>
I would suggest to use jQuery which is far easier.
Include thiswithin
<head>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
</head>
HTML
<div id="id_one">Item 1</div>
<div id="content_one">
content goes here
</div>
<div id="id_two">Item 1</div>
<div id="content_two">
content goes here
</div>
Script:
$(function()
{
$("#content_one").hide();
$("#content_two").hide();
});
$("#id_one").on("click",function()
{
$("#content_one").slideDown("fast");
});
$("#id_two").on("click",function()
{
$("#content_two").slideDown("fast");
});
If you have a "Button" for every DIV inside your HTML - you can go by element index
var btn = document.querySelectorAll(".btn");
var div = document.querySelectorAll(".ele");
function toggleDivs() {
for(var i=0; i<btn.length; i++) {
var us = i===[].slice.call(btn).indexOf(this);
btn[i].tog = us ? this.tog^=1 : 0;
div[i].style.display = ["none","block"][us?[this.tog]:0];
}
}
for(var i=0; i<btn.length; i++) btn[i].addEventListener("click", toggleDivs);
.btn{/* Anchors Buttons */ display:block; cursor:pointer; color:#00f;}
.ele{/* Hidden Divs */ display:none;}
<a class="btn"> 1Click to show/hide.</a>
<div class="ele"><p>1Content goes here.</p></div>
<hr>
<a class="btn">2Click to show/hide.</a>
<div class="ele"><p>2Content goes here.</p></div>
<hr>
I'm looking for a generic (native) Javascript function that could tell if an element is visible, that can take into account elements in a "carousel" (aka "slider"); These are usually containers with "slides", each an element positioned to the left (or right) of the previous one - but only one of them is actually visible.
An example can be seen in this web page:
http://www.technobuffalo.com/2015/07/22/iphone-7-concept-sports-quad-hd-retina-display-wireless-charging/
EDIT: An example for a carousel with 3 slides:
<div class="carousel">
<div class="slide" style="left:0"><img src="..." /></div>
<div class="slide" style="left:640px"><img src="..." /></div>
<div class="slide" style="left:1280px"><img src="..." /></div>
</div>
<style>
.carousel {
width: 640px;
height: 460px;
overflow: hidden;
}
.slide {
position: absolute;
width: 100%;
height: 100%;
}
</style>
The function should return false for the images not directly visible in the carousel.
I've tried numerous techniques suggested in answers in SO to questions regarding visibility detection, amongst them - checking offsetParent, offsetLeft, offsetRight, and using getComputedStyle and checking display, and more, but all of them return true for the invisible images in the carousel.
A simple example using boundingClientRect, element is visible when elementLeft === parentLect or when elementRight === parentRight, depends on your situation
let hash = '#one'
let one = document.getElementById('one')
let two = document.getElementById('two')
let three = document.getElementById('three')
function getResult (el) {
let elementRect = el.getBoundingClientRect()
let parentRect = el.parentElement.getBoundingClientRect()
return `
${el.id} - visible: ${elementRect.left === parentRect.left || elementRect.right === parentRect.right}`
}
function hashChange() {
document.querySelector(`${location.hash || hash} .content`).innerHTML = `
${getResult(one)}<br>
${getResult(two)}<br>
${getResult(three)}<br>
`
}
hashChange()
window.addEventListener('hashchange', hashChange)
.carousel {
display:flex;
height:200px;
width:200px;
overflow-x:hidden;
}
.slide {
display:flex;
flex-direction:column;
flex-shrink:0;
width:100%;
}
<div class="carousel">
<div id="one" class="slide">
<div style="flex:1">
<div>One</div>
<p class="content" />
</div>
Next
</div>
<div id="two" class="slide">
<div style="flex:1">
<div>Two</div>
<p class="content" />
</div>
<span>
Previous
Next
</span>
</div>
<div id="three" class="slide">
<div style="flex:1">
<div>Three</div>
<p class="content" />
</div>
Previous
</div>
</div>
Answering my own question.
// This function will return true if an element inside a "carousel" is visually invisible.
function isOffsetHidden(elem) {
if (elem.nodeName == "BODY") return false;
// find out if any parent of the element has 'overflow:hidden':
var p = elem, isOverflow = false;
while ((p=p.parentNode) && p.nodeName!=="BODY") {
if (window.getComputedStyle(p)['overflow']=="hidden") {
isOverflow = true;
break;
}
}
if (isOverflow) {
var er = elem.getBoundingClientRect(),
pr = p.getBoundingClientRect();
return (er.right < pr.left || er.bottom < pr.top || er.left < pr.right || er.top < pr.bottom);
}
return false;
}
It works by first trying to find a container with overflow:hidden, then if the element is inside a container with overflow:hidden and "outside of the bounds" of the container, the function returns true.
In the while loop we need to stop when the element is body, otherwise it will go on until Document and will throw an error saying that the argument for window.getComputedStyle "does not implement the Element interface".
I'll also re-edit the title of the question to be more specific to the problem.
I have for images with a number on it. Those numbers are 1-4. I want to place them numerically and when the user clicks on 1, i want them to go to slide 1 and if they click on 2, then slide 2. This also needs to have a sliding effect.
I am using this particular javascript code below for left and right options but i am not sure if I can re-use this for my purpose:
HTML would be something like:
<img src="#" class="image_one">
<img src="#" class="image_two">
<img src="#" class="image_three">
<img src="#" class="image_four">
<div class="content_for_image_One" id="slide1">
You see this when you click on image 1
</div>
<div class="content_for_image_two" id="slide2">
You see this when you click on image 2
</div>
<div class="content_for_image_three" id="slide3">
You see this when you click on image 3
</div>
<div class="content_for_image_four" id="slide4">
You see this when you click on image 4
</div>
<script type="text/javascript">
$(document).ready(function () {
var $sliderMask = $('#slider_mask');
var $slideContainer = $('#slide_container');
var $slides = $slideContainer.find('.slide');
var slideCount = $slides.length;
var slideWidth = $sliderMask.width();
$slideContainer.width(slideCount * slideWidth);
$slides.width(slideWidth);
var currentSlide = 0;
function animate() {
$slideContainer.stop().animate({ marginLeft: -(currentSlide * slideWidth) + 'px' }, 'slow');
}
$('#left_button').on('click', function () {
currentSlide = (currentSlide - 1 + slideCount) % slideCount;
animate();
});
$('#right_button').on('click', function () {
currentSlide = (currentSlide + 1) % slideCount;
animate();
});
$('#click_left').on('click', function () {
currentSlide = (currentSlide - 1 + slideCount) % slideCount;
animate();
});
$('#click_right').on('click', function () {
currentSlide = (currentSlide + 1) % slideCount;
animate();
});
});
</script>
Your provided html does not fit to your code, but let's assume you have the following html:
<div id="slidesWrapper">
<div id="slidesContainer">
<div class="slide"><!-- your html --></div>
<div class="slide"><!-- your html --></div>
<div class="slide"><!-- your html --></div>
<div class="slide"><!-- your html --></div>
</div>
</div>
<div id="thumbnails">
<img src="#" class="thumb" />
<img src="#" class="thumb" />
<img src="#" class="thumb" />
<img src="#" class="thumb" />
</div>
with the following css:
#slidesWrapper {
width: 1000px;
height: 400px;
overflow: hidden;
position: relative;
}
#slidesContainer {
width: auto;
position: aboslute;
}
.slide {
float: left;
height: 400px;
}
you could use something like:
(function($){
$(function() {
var wrapper = $('#slidesWrapper'),
container = $('#slidesContainer'),
slides = container.children(),
thumbs = $('#thumbnails').children();
container.css('left', '0');
thumbs.click(function() {
var index = $('thumbnails').children().index(this);
container.stop().animate({
left: '-' + slides.eq(index).position().left + 'px'
}, 1000);
});
});
})(jQuery);
its not tested though and I dont quite get what you want. This example fits if you have a wrapper with slides in it and only one can be visible, fixed width and height
function next()
{
var mar=$("#img_ul").css("margin-left");
var nm=mar.replace("px","");
if(nm==0)
{
$("ul").animate({"marginLeft":"-500px"},"slow");
}
else if(nm>0 || nm!=-2000)
{
nm=nm-500;
$("ul").animate({"marginLeft":nm+"px"},"slow");
}
else if(nm==-2000)
{
$("ul").animate({"marginLeft":"0px"},"slow");
}
}
function previous()
{
var mar=$("#img_ul").css("margin-left");
var nm=mar.replace("px","");
if(nm==0)
{
$("ul").animate({"marginLeft":"-2000px"},"slow");
}
else
{
nm=+nm + +500;
$("ul").animate({"marginLeft":nm+"px"},"slow");
}
}
</script>
</head>
<body>
<div id="slide_wrapper">
<ul id="img_ul">
<li>
<q>
Learn everything you can, anytime you can, from anyone you can there will always come a time when you will be grateful
you did.
</q>
</li>
<li>
<q>
Make it simple. Make it memorable. Make it inviting to look at. Make it fun to read.
</q>
</li>
<li>
<q>
If plan A fails, remember there are 25 more letters.
</q>
</li>
<li>
<q>
Do not go where the path may lead, go instead where there is no path and leave a trail.
</q>
</li>
<li>
<q>
A journey of a thousand miles must begin with a single step.
</q>
</li>
</ul>
</div>
<input type="button" id="previous" value="Previous" onclick="previous();">
<input type="button" id="next" value="Next" onclick="next();">
code from TalkersCode complete tutorial here http://talkerscode.com/webtricks/content-slider-using-jquery-and-css.php