I am learning JS and have created a carousel with a caption underneath.
How do I get the Prev/Next buttons to affect the caption as well as the image? I've tried combining the if statements in several ways but have failed miserably.
Relevant HTML:
<span id="prev" class="arrow">❮</span>
<div class="karussell" id="karussell">
<img class="karu" name="esislaid">
</div>
<span id="next" class="arrow">❯</span>
<div class="caption">
<h3 id="esikiri"></h3>
</div>
JS:
var p = 0;
var s = 0;
var esileht = [];
var aeg = 5000;
var kiri = [];
//Image List
esileht[0] = 'img/tooted/raamat/graafvanalinn2016.jpg';
esileht[1] = 'img/tooted/kaart/kaart_taskus_esipool.jpg';
esileht[2] = 'img/tooted/kaart/graafkaart_esikylg.jpg';
//Captions
kiri[0] = 'Raamat "Tallinn. Graafiline vanalinn"';
kiri[1] = 'Tallinna vanalinna graafiline kaart (suur formaat)';
kiri[2] = 'Tallinna vanalinna graafiline kaart (väike formaat)';
// Left and Right arrows
//Eelmine
function eelmine(){
if (p === 0){
p = esileht.length;
}
p = p - 1;
return esileht[p];
}
//Jargmine
function jargmine(){
p = p + 1;
p = p % esileht.length;
return esileht[p];
}
document.getElementById('prev').addEventListener('click', function (e){
document.querySelector('#karussell img').src = eelmine();
}
);
document.getElementById('next').addEventListener('click', function (e) {
document.querySelector('#karussell img').src = jargmine();
}
);
//Change Image
function changePilt (){
document.esislaid.src = esileht[p];
if(p < esileht.length -1){
p++;
} else {
p = 0;
}
setTimeout("changePilt()", aeg);
}
//Change Caption
function changeKiri(){
document.getElementById('esikiri').innerHTML = kiri[s];
if(s < kiri.length - 1){
s++;
}
else {
s = 0;
}
setTimeout('changeKiri()', aeg);
}
document.body.onload = function(){
changePilt();
changeKiri();
};
CSS, just in case:
.karussell {
position: relative;
width: 100%;
max-height: 600px;
overflow: hidden;
}
.arrow {
cursor: pointer;
position: absolute;
top: 40%;
width: auto;
color: #00A7E0;
padding: 16px;
font-weight: bold;
font-size: 18px;
border-radius: 3px;
transition: 0.6s ease;
}
#next {
right: 0;
}
#prev {
left: 0;
}
.arrow:hover {
background-color: rgba(0,0,0,0.8);
}
.caption {
text-align: center;
color: #00A7E0;
padding: 2px 16px;
}
.karu {
max-width: 75%;
animation-name: fade;
animation-duration: 2s;
}
#keyframes fade {
from {opacity: 0.4}
to {opacity: 1}
}
#media (max-width:767px){.karu{max-width: 95%;}}
I made a fiddle to try to illustrate (had to paste the js into the html tab to gt it to work for some reason): Fiddle
Really you just need to use the .innerHTML() feature and do exactly what you already have. Either create a eelmine2() function (or something like that) and call it again, grabbing the content from kiri[] or instead just return the p and use it in two places:
document.getElementById('prev').addEventListener('click', function (e){
document.querySelector('#karussell img').src = eelmine();
document.querySelector('#esikiri').innerHTML = eelmine2();
});
function eelmine2(){
if (p === 0){
p = kiri.length;
}
p = p - 1;
return kiri[p];
}
or
document.getElementById('prev').addEventListener('click', function (e){
var change = eelmine();
document.querySelector('#karussell img').src = esileht[change];
document.querySelector('#esikiri').innerHTML = kiri[change];
});
function eelmine(){
if (p === 0){
p = kiri.length;
}
p = p - 1;
return p;
}
This assumes your code is using the same global vars inside public functions that you have set up in your Fiddle. You should fix that to have variables passed into the functions before going live with all of this, but I'm not addressing that any further here.
Related
i am trying to add tooltip and data over hover of a sprite inside using the data visualization api. I have achieved adding the sprite viewable, but it is not mentioned as to how we add a tooltip on hover. Docs just mention there is a DATAVID_OBJECT_HOVERING event that is triggered to the viewer object, and we can add a callback on it. Also the code is not clear. Attaching hyperion demo's code below which only adds a callback to the onhover event on sprite and no mention of tooltip and data passed to it. Where in the code that is present as in this website i am seeing the tooltip with some data. this is the link https://hyperion.autodesk.io/ and code is this https://github.dev/Autodesk-Forge/forge-dataviz-iot-reference-app
async function onModelLoaded(viewer) {
const dataVizExt = viewer.getExtension("Autodesk.DataVisualization");
const DATAVIZEXTN = Autodesk.DataVisualization.Core;
var styleMap = {};
// Create model-to-style map from style definitions.
Object.entries(SensorStyleDefinitions).forEach(([type, styleDef]) => {
styleMap[type] = new DATAVIZEXTN.ViewableStyle(
DATAVIZEXTN.ViewableType.SPRITE,
new THREE.Color(styleDef.color),
styleDef.url
);
});
const viewableData = new DATAVIZEXTN.ViewableData();
viewableData.spriteSize = 16;
let startId = 1;
devices.forEach((device) => {
let style = styleMap[device.type] || styleMap["default"];
const viewable = new DATAVIZEXTN.SpriteViewable(device.position, style, startId);
viewableData.addViewable(viewable);
startId++;
});
await viewableData.finish();
dataVizExt.addViewables(viewableData);
/**
* Called when a user clicks on a Sprite Viewable
* #param {Event} event
*/
function onItemClick(/* event */) {}
/**
* Called when a user hovers over a Sprite Viewable
* #param {Event} event
*/
function onItemHovering(event) {
console.log("Show tooltip here", event.dbId);
}
const DataVizCore = Autodesk.DataVisualization.Core;
viewer.addEventListener(DataVizCore.MOUSE_CLICK, onItemClick);
viewer.addEventListener(DataVizCore.MOUSE_HOVERING, onItemHovering);
}
May check out my BIM360SensorTooltip at forge-bim360-assets.viewer/BIM360IotConnectedExtension.js#L300. The core concept is like the following
Create your custom tooltip by JavaScript DOM API.
To add a tooltip for a sprite, just add some codes in your onItemHovering event to create/show your custom tooltip.
Here is an example of my BIM360SensorTooltip (removed BIM360 prefix):
class SensorTooltip extends THREE.EventDispatcher {
constructor(parent) {
super();
this.parent = parent;
this.init();
}
get viewer() {
return this.parent.viewer;
}
get dataVizTool() {
return this.parent.dataVizTool;
}
init() {
const container = document.createElement('div');
container.classList.add('bim360-sensor-tooltip');
this.container = container;
const bodyContainer = document.createElement('div');
bodyContainer.classList.add('bim360-sensor-tooltip-body');
container.appendChild(bodyContainer);
this.bodyContainer = bodyContainer;
bodyContainer.innerHTML = 'No Data';
this.viewer.container.appendChild(container);
}
setVisible(visible) {
if (visible) {
this.bodyContainer.classList.add('visible');
} else {
this.bodyContainer.classList.remove('visible');
}
}
setPosition(point) {
const contentRect = this.bodyContainer.getBoundingClientRect();
const offsetX = contentRect.width / 2;
const spriteSize = this.dataVizTool.viewableData.spriteSize;
const offsetY = contentRect.height + 0.7 * spriteSize / this.parent.viewer.getWindow().devicePixelRatio;
const pos = new THREE.Vector3(
point.x - offsetX,
point.y - offsetY,
0
);
this.container.style.transform = `translate3d(${pos.x}px, ${pos.y}px, ${pos.z}px)`;
}
setPositionByWordPoint(point) {
this.setPosition(this.viewer.worldToClient(point));
}
async show(sensor) {
if (!sensor) return;
this.bodyContainer.innerHTML = '';
const nameSpan = document.createElement('span');
nameSpan.classList.add('bim360-sensor-tooltip-name');
this.bodyContainer.appendChild(nameSpan);
const assetInfo = this.parent.dataProvider.assetInfoCache[sensor.externalId];
let nameString = 'Unknown asset';
if (assetInfo) {
nameString = `Asset [${assetInfo.assetId}]`;
}
nameSpan.innerHTML = `${nameString} ${sensor.name}`;
const valueSpan = document.createElement('span');
valueSpan.classList.add('bim360-sensor-tooltip-value');
this.bodyContainer.appendChild(valueSpan);
let cachedData = this.parent.dataHelper.getDataFromCache(sensor.id, sensor.name);
if (cachedData) {
let value = Utility.getClosestValue(cachedData, Utility.getTimeInEpochSeconds(this.parent.currentTime));
let valueString = `${value.toFixed(2)}`;
if (sensor.dataUnit)
valueString += ` ${sensor.dataUnit}`;
valueSpan.innerHTML = valueString;
}
this.setVisible(true);
this.setPosition(this.viewer.worldToClient(sensor.position));
}
hide() {
this.bodyContainer.innerHTML = 'No Data';
this.setVisible(false);
}
}
const tooltip = new SensorTooltip(yourExtesionLoadedTheDataVisulationExtesion);
const onSensorHovered => (event) {
if (event.hovering && dbId2DeviceIdMap) {
const deviceId = dbId2DeviceIdMap[event.dbId];
const { sensors } = dataProvider;
if (!sensors || sensors.length <= 0) return;
const sensor = sensors.find(s => s.externalId == deviceId);
if (!sensor) return;
tooltip.show(sensor);
} else {
tooltip.hide();
}
};
viewer.addEventListener(
Autodesk.DataVisualization.Core.MOUSE_HOVERING,
onSensorHovered
);
and its CSS style see https://github.com/yiskang/forge-bim360-assets.viewer/blob/bim360-iot-connected/bim360assets/wwwroot/css/main.css#L182
/** DataViz Sensor Tooltip **/
/*https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_tooltip*/
.bim360-sensor-tooltip {
visibility: hidden;
position: absolute;
display: inline-block;
border-bottom: 1px dotted black;
top: 0;
left: 0;
width: 170px;
}
.bim360-sensor-tooltip .bim360-sensor-tooltip-body {
width: 170px;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
position: absolute;
z-index: 1;
left: 50%;
margin-left: -85px;
opacity: 0;
transition: opacity 0.3s;
visibility: hidden;
width: 170px;
background-color: #555;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
position: absolute;
z-index: 1;
opacity: 0;
transition: opacity 0.3s;
font-size: 12px;
}
.bim360-sensor-tooltip .bim360-sensor-tooltip-body::after {
content: "";
position: absolute;
top: 100%;
left: 50%;
margin-left: -5px;
border-width: 5px;
border-style: solid;
border-color: #555 transparent transparent transparent;
}
.bim360-sensor-tooltip .bim360-sensor-tooltip-body.visible {
visibility: visible;
opacity: 1;
}
.bim360-sensor-tooltip-name {
display: flex;
justify-content: center;
font-weight: bold;
font-size: 12px;
padding-top: 1px;
padding-bottom: 3px;
}
.bim360-sensor-tooltip-value {
font-size: 13px;
display: flex;
justify-content: center;
}
Looking for a way to change link colour in JavaScript within a specific ID on scroll.
That's my CSS.
#header_nav {
transition: 0.4s;
position: fixed;
top: 0;
height: 130px;
}
#main-logo {
transition: 0.4s;
height: 52px;
width: 169.92px;
}
#main-nav a{
color: #f3f5f6;
transition: 0.4s;
}
And here is the JavaScript
function scrollFunction() {
if (document.body.scrollTop > 0 || document.documentElement.scrollTop > 0) {
document.getElementById("header_nav").style.height = "70px";
document.getElementById("main-logo").style.width = "118.944px";
document.getElementById("main-logo").style.height = "36.4px";
document.getElementById("main-logo").style.filter = "invert(0)";
document.getElementById("header_nav").style.backgroundColor = "#F1F1F3";
document.getElementById("logo").style.fontSize = "25px";
document.getElementById("main-nav a").style.color = "#223732";
} else {
document.getElementById("header_nav").style.height = "130px";
document.getElementById("header_nav").style.backgroundColor = "transparent";
document.getElementById("main-logo").style.filter = "invert(1)";
document.getElementById("main-logo").style.width = "169.92px";
document.getElementById("main-logo").style.height = "52px";
document.getElementById("logo").style.fontSize = "35px";
document.querySelectorAll(".main-nav a").style.color = "#f3f5f6";
}
}
You can see where I have the code that doesn't work:
document.getElementById("main-nav a").style.color = "#223732";
Is there a way I can select just the link in javascript D from that id as I have it in CSS?
You can first select the main-nav by id and then it's children by tag name, something like:
var mainNav = document.getElementById("main-nav");
mainNav.getElementsByTagName("a")[0].style.color = "#223732";
Not that getElementsByTagName() returns an array with all elements of that tag.
I'm having problems with a functionality that I have to implement, I'm looking to do this (check the second section) -> https://www.jacquemus.com/fr/simon
The letters need to fade in and fade out, based on the scroll, this is what I got so far
<div class="ml3">
<h1>THIS IS MY TEXT THAT IT'S GOING TO SHOW IN SCROLL</h1>
</div>
:root {
--percentage: 0;
}
body {
background-color: #000;
margin: 0;
height: 120vh;
}
.ml3 {
position: sticky;
top: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
span {
font-family: Helvetica;
margin: 0;
padding: 0;
font-size: 48px;
color: #fff;
letter-spacing: -0.3px;
}
.ml3 span{
opacity: var(--percentage);
}
var textWrapper = document.querySelector('.ml3');
textWrapper.innerHTML = textWrapper.textContent.replace(/\S/g, "<span class='letter'>$&</span>");
var letter = document.querySelectorAll('.letter');
var i = 0;
var currentID = 0;
var slideCount = letter.length;
document.addEventListener('scroll', (e) => {
let scrolled = document.documentElement.scrollTop / (document.documentElement.scrollHeight - document.documentElement.clientHeight);
var nextID = currentID + 1;
if(nextID < slideCount){
letter[nextID].style.setProperty('--percentage', `${scrolled / 1}` * nextID);
}
currentID = nextID;
});
https://codepen.io/federicomartin/pen/eYdBbQm
As you can see, it's no near what I want, but I really don't know how to do it, if someone could help me, would be awesome! Thanks!
I like that effect a lot!! Thank for submitting that question! ;)
So here is a something to help you continue on this challenge.
In the scroll handler, I replaced:
var nextID = currentID + 1;
if(nextID < slideCount){
letter[nextID].style.setProperty('--percentage', `${scrolled / 1}` * nextID);
}
currentID = nextID;
with:
letter.forEach(function (l, i) {
if (i / letter.length < scrolled) {
l.style.setProperty("--percentage", 1);
}else{
l.style.setProperty("--percentage", 0);
}
});
It compares the scrolled percentage you calculated with the letter index "percentage" in the letter collection to set it's opacity to 0 or 1.
I would then adjust the scrollHeight of the body with the real text to reveal... Below, I used height: 600vh; and may be a bit too much. ;)
var textWrapper = document.querySelector(".ml3");
textWrapper.innerHTML = textWrapper.textContent.replace(
/\S/g,
"<span class='letter'>$&</span>"
);
var letter = document.querySelectorAll(".letter");
var i = 0;
var currentID = 0;
var slideCount = letter.length;
document.addEventListener("scroll", (e) => {
let scrolled =
document.documentElement.scrollTop /
(document.documentElement.scrollHeight -
document.documentElement.clientHeight);
// var nextID = currentID + 1;
// if (nextID < slideCount) {
// letter[nextID].style.setProperty(
// "--percentage",
// `${scrolled / 1}` * nextID
// );
// }
// currentID = nextID;
letter.forEach(function (l, i) {
// console.log("====",i / letter.length, i, letter.length)
if (i / letter.length < scrolled) {
l.style.setProperty("--percentage", 1);
} else {
l.style.setProperty("--percentage", 0);
}
});
});
:root {
--percentage: 0;
}
body {
background-color: #000;
margin: 0;
height: 1120vh;
}
.ml3 {
position: sticky;
top: 0;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
span {
font-family: Helvetica;
margin: 0;
padding: 0;
font-size: 48px;
color: #fff;
letter-spacing: -0.3px;
}
.ml3 span {
opacity: var(--percentage);
}
<div class="ml3">
<h1>THIS IS MY TEXT THAT IT'S GOING TO SHOW IN SCROLL</h1>
</div>
CodePen
I've built a small balloon game , trying to learn the foundations,
anyways I've successfully rendered balloons, i can see them both on the page however the move functions doesn't work,it should do so on page load that I've set in the index.html body(the startGame func) , code looks fine,however nothing happens.
var gNextId = 100
var gBaloons = createBalloons()
var gInterval = null
function startGame() {
renderBaloons();
gInterval = setInterval(() => {
moveBalloons();
}, 500);
}
function renderBaloons() {
var strHtml = ''
for (var i = 0; i < gBaloons.length; i++) {
var balloon = gBaloons[i]
strHtml += `
${balloon.txt}
`
}
document.querySelector('.balloon-container').innerHTML = strHtml
}
function moveballoons() {
var elballoons = document.querySelectorAll('.balloon')
for (var i = 0; i > gBaloons.length; i++) {
var balloon = gBaloons[i]
var elballoon = elballoons[i]
balloon.bottom += balloon.speed
elballoon.style.bottom = balloon.bottom + 'px'
}
if (balloon.bottom >= 800) clearInterval(gInterval)
}
function createBalloons() {
var ballons = [
createBalloon('A'),
createBalloon('B'),
createBalloon('C')
];
return ballons
}
function createBalloon(txt) {
return {
id: gNextId++,
bottom: 0,
speed: 45,
txt: txt
}
}
body {
background-color: lightblue;
}
.balloon {
position: absolute;
width: 170px;
height: 200px;
border-radius: 40%;
bottom: 0;
transition: 3s;
background-color: yellow;
text-align: center;
font-weight: bold;
}
.balloon1 {
left: 200px;
background-color: rgb(3, 61, 23);
}
.balloon2 {
left: 600px;
background-color: rgb(182, 24, 50);
}
.fade {
opacity: 0;
}
In the moveballoons() function the following line:
for (var i = 0; i > gBaloons.length; i++) {
Should be
for (var i = 0; i < gBaloons.length; i++) {
Note: I've swapped > with <
I couldn't the get example running, so there could well be other reasons as to why this is not working but that is definitely an issue.
Title says it all really. Here is an example of what I'm trying to achieve navigation color change image based on background
The problem is that it needs to work with a site that's using a scroll-jacking parallax type effect, here is the site I'm trying to achieve this effect with demo website
Modify the scroll script a bit
Check demo here
Created the function toggleHeaderColor to check the current section. Since the scroll script is indexing each section in order 0 (i.e. section_1) ,1 (i.e. section_2),2 (i.e. section_2),3 (i.e. section_3),4 (i.e. section_2) and so on. Every time you scroll it gets updated.
In scroll script there are two function nextItem() and previousItem()form which we get the current slide index and on that we can call our function to toggle dark class on header elements.
JS:
var sectionBlock = $(".section-item");
var getCurrentSlideAttr = 0;
function toggleHeaderColor(getCurrentSlideAttr) {
if (getCurrentSlideAttr == 0) {
$(".menu-link, .menu-link-logo, .menu-link-last").removeClass("dark");
}
if (getCurrentSlideAttr == 1) {
$(".menu-link, .menu-link-logo, .menu-link-last").addClass("dark");
}
if (getCurrentSlideAttr == 2) {
$(".menu-link, .menu-link-logo, .menu-link-last").removeClass("dark");
}
if (getCurrentSlideAttr == 3) {
$(".menu-link, .menu-link-logo, .menu-link-last").removeClass("dark");
}
if (getCurrentSlideAttr == 4) {
$(".menu-link, .menu-link-logo, .menu-link-last").addClass("dark");
}
}
var ticking = false;
var isFirefox = /Firefox/i.test(navigator.userAgent);
var isIe =
/MSIE/i.test(navigator.userAgent) ||
/Trident.*rv\:11\./i.test(navigator.userAgent);
var scrollSensitivitySetting = 30;
var slideDurationSetting = 800;
var currentSlideNumber = 0;
var totalSlideNumber = $(".section-item").length;
function parallaxScroll(evt) {
if (isFirefox) {
delta = evt.detail * -120;
} else if (isIe) {
delta = -evt.deltaY;
} else {
delta = evt.wheelDelta;
}
if (ticking != true) {
if (delta <= -scrollSensitivitySetting) {
ticking = true;
if (currentSlideNumber !== totalSlideNumber - 1) {
currentSlideNumber++;
nextItem();
}
slideDurationTimeout(slideDurationSetting);
}
if (delta >= scrollSensitivitySetting) {
ticking = true;
if (currentSlideNumber !== 0) {
currentSlideNumber--;
}
previousItem();
slideDurationTimeout(slideDurationSetting);
}
}
}
function slideDurationTimeout(slideDuration) {
setTimeout(function() {
ticking = false;
}, slideDuration);
}
var mousewheelEvent = isFirefox ? "DOMMouseScroll" : "wheel";
window.addEventListener(mousewheelEvent, _.throttle(parallaxScroll, 60), false);
function nextItem() {
getCurrentSlideAttr = currentSlideNumber;
toggleHeaderColor(getCurrentSlideAttr);
var $previousSlide = $(".section-item").eq(currentSlideNumber - 1);
$previousSlide
.css("transform", "translate3d(0,-130vh,0)")
.find(".content-wrapper")
.css("transform", "translateY(40vh)");
currentSlideTransition();
}
function previousItem() {
//console.log($(".section-item").eq(currentSlideNumber).attr('id'))
getCurrentSlideAttr = currentSlideNumber;
toggleHeaderColor(getCurrentSlideAttr);
var $previousSlide = $(".section-item").eq(currentSlideNumber + 1);
$previousSlide
.css("transform", "translate3d(0,30vh,0)")
.find(".content-wrapper")
.css("transform", "translateY(30vh)");
currentSlideTransition();
}
function currentSlideTransition() {
var $currentSlide = $(".section-item").eq(currentSlideNumber);
$currentSlide
.css("transform", "translate3d(0,-15vh,0)")
.find(".content-wrapper")
.css("transform", "translateY(15vh)");
}
Update
You can actually choose a specific text color over white/black backgrounds using css blend modes.
Example with specific colors (green over white and red over black in this case):
html, body {
margin: 0;
}
h1 {
position: fixed; top: 0; left: 0;
width: 100vw;
text-align: center;
mix-blend-mode: difference;
color: white;
z-index: 1;
}
div {
position: relative;
width: 100vw;
height: 100vh;
background: white;
margin: 0;
}
div:nth-of-type(2n) {
background: black;
}
div:after {
content: '';
position: absolute; top: 0; left: 0;
width: 100%;
height: 100%;
z-index: 2;
}
div:nth-of-type(2n):after {
background: red;
mix-blend-mode: multiply;
}
div:nth-of-type(2n + 1):after {
background: green;
mix-blend-mode: screen;
}
<h1>Scroll to see effect</h1>
<div></div>
<div></div>
<div></div>
I think the only way you would be able to choose the exact partial colors using SVG text or paths.
A simple example with mix-blend-mode:
html, body {
margin: 0;
}
h1 {
position: fixed; top: 0; left: 0;
width: 100vw;
text-align: center;
mix-blend-mode: difference;
color: white;
z-index: 1;
}
div {
width: 100vw;
height: 100vh;
background: black;
}
div:nth-of-type(2n) {
background: white;
}
<h1>Scroll to see effect</h1>
<div></div>
<div></div>
<div></div>
Browser support
https://css-tricks.com/reverse-text-color-mix-blend-mode/
Try Adding mix-blend-mode property.
Add this property to your .navigation-menu class
CSS
.navigation-menu{
mix-blend-mode: difference;
}
Hope this Helps...