I have created a show and function using Angular. At the moment i have the basics working. When the user hovers over tile the class is added and removed.
<article class="col-sm-6" ng-mouseenter="showHiddenTile()" ng-mouseleave="hideHiddenTile()">
<div class="grid-block--img">
<img src="/assets/homepage/home-tile5.png">
<div class="grid-headings">
<h2>a new<br/>home for<br/>whiskey</h2>
<p><span class="heading--bold">WORK.</b><span> Food and Beverage Design<
</div>
<div class="grid-block-hidden" ng-class="{isVisble: tileBlock}">My overlay</div>
</div>
</article>
I want to use this show and hide function multiple times throughout the site. At the moment when I hover over one of the elements it adds the isActive class to all elements instead of individually.
Angular code
// SHOW AND HIDE FUNCTION
$scope.showHiddenTile = function() {
$scope.tileBlock = true;
}
$scope.hideHiddenTile = function() {
$scope.tileBlock = false;
}
How can I target the isVisble class individually?
Have an array
$scope.array = [];
push it to array when mouseenter event
function showMethod(element){
$scope.array.push(element);
}
slice it from array when mouseleave event
function hideMethod(element){
$scope.array.slice($scope.array.indexOf(element),1);
}
use this condition in ng-class
ng-class="array['blockName'] != -1"
You could do something like:
<article class="col-sm-6" ng-mouseenter="showHiddenTile('block-id')" ng-mouseleave="hideHiddenTile('block-id')">
And:
$scope.showHiddenTile = function(blockId) {
$scope.tileBlock[blockId] = true;
}
$scope.hideHiddenTile = function(blockId) {
$scope.tileBlock[blockId] = false;
}
$scope.isShowTitle = function(blockId) {
return $scope.tileBlock[blockId];
}
And:
<div class="grid-block-hidden" ng-class="{isVisble: isShowTitle('block-id'}">My overlay</div>
And then have a unique block-id per article.
why not have 2 styles
.grid-block-hidden{
//style when mouse is not on
}
grid-block-hidden:hover{
//style on hover
//isVisble class
}
Related
I've been playing around with jQuery for ages but am finally trying to learn clean Vanilla JS.
I have a list of elements:
<div id="seriesList" class="seriesList rollable">
<div class="seriesLink" series="7">
<h3 class="name">Carrow Road</h3><p class="location">Norwich</p>
</div>
<div class="seriesLink" series="6">
<h3 class="name">White Heart Lane</h3><p class="location">London</p>
</div>
<div class="seriesLink" series="5">
<h3 class="name">Parc des Princes</h3><p class="location">Paris</p>
</div>
</div
I'm toggling a series of GSAP animation after clicking one of the .seriesLink. The first one i'm trying to achieve is making every elements exept the one clicked disapear.
i.e: I click on #carrow-road — #white-lane and #parc-des-princes would disapear.
I have this:
document.querySelectorAll(".seriesLink").forEach(item => {
item.addEventListener('click', event => {
// ForEach.Not ?
document.getElementById("seriesList").classList.toggle("rollable");
document.getElementById("home").classList.add("scrollable");
document.getElementById("rightPanel").classList.remove("scrollable");
tlOpenSeries.play();
})
})
The "class" system in Javascript is getting me lost, as I don't seem to be able to target my elements successfully.
I can't find a way to "reproduce" the each.not jquery provides. Any idea? Shall I add a class first to the clicked element and then target all elements without this "active" class? Is there a shortcut?
Many thanks
To accomplish that in vanilla JS you have to loop through the elements and check if the current element is not the clicked element.
Demo:
var divs = document.querySelectorAll(".seriesLink");
divs.forEach(item => {
item.addEventListener('click', event => {
for(var i = 0; i < divs.length; i++){
if(event.currentTarget != divs[i]){ // check here
divs[i].style.display = "none";
}
}
//.......
//.......
});
});
<div id="seriesList" class="seriesList rollable">
<div class="seriesLink" series="7">
<h3 class="name">Carrow Road</h3><p class="location">Norwich</p>
</div>
<div class="seriesLink" series="6">
<h3 class="name">White Heart Lane</h3><p class="location">London</p>
</div>
<div class="seriesLink" series="5">
<h3 class="name">Parc des Princes</h3><p class="location">Paris</p>
</div>
</div>
you can use filter:
const seriesLinks = document.querySelectorAll(".seriesLink");
seriesLinks.forEach(item => {
item.addEventListener('click', event => {
seriesLinks
.filter(i => i != item)
.forEach(i => // your logic... //);
//... rest of your code ... //
})
})
but anymay i think that a good practice is to split the code to simple little functions, for example hideAllExceptCurrent (allElemArray, currentElem), hideAllToggleCurrent (allElemArray, currentElem)
I am using this template
https://codepen.io/candroo/pen/wKEwRL
But the link on button does not work. The close the animation without go to the page.
If I disable the js script the links works, so, I suspect that is something with the Js. script, but I could not find the error.
One card code:
<div class="card-flap flap1">
<div class="card-description">
This grid is an attempt to make something nice that works on touch devices. Ignoring hover states when they're not available etc.
</div>
<div class="card-flap flap2">
<div class="card-actions">
Read more
</div>
</div>
</div>
</div>
The JavaScript code:
$(document).ready(function(){
var zindex = 10;
$("div.card").click(function(e){
e.preventDefault();
var isShowing = false;
if ($(this).hasClass("show")) {
isShowing = true
}
if ($("div.cards").hasClass("showing")) {
// a card is already in view
$("div.card.show")
.removeClass("show");
if (isShowing) {
// this card was showing - reset the grid
$("div.cards")
.removeClass("showing");
} else {
// this card isn't showing - get in with it
$(this)
.css({zIndex: zindex})
.addClass("show");
}
zindex++;
} else {
// no cards in view
$("div.cards")
.addClass("showing");
$(this)
.css({zIndex:zindex})
.addClass("show");
zindex++;
}
});
});
So I have a mini slide menu in my website there is a menu you can choose what you want to read. There are points to click, when u clicked it the point get a red background.
But there is a problem.
When i click one point and then an other point the first clicked point have to lose his background.
Here is my HTML:
<div id="slide_button" onClick="clicked(this);"><dir class="button_1"></dir></div>
<div id="slide_button" onClick="clicked(this);"><dir class="button_2"></dir></div>
<div id="slide_button" onClick="clicked(this);"><dir class="button_3"></dir></div>
<div id="slide_button" onClick="clicked(this);"><dir class="button_4"></dir></div>
<div id="slide_button" onClick="clicked(this);"><dir class="button_5"></dir></div>
Here is my JS:
function clicked(slide_button) {
slide_button.getElementsByTagName("dir")[0].style.backgroundColor="red";
}
HERE IS AN EXAMPLE ON FIDDLE.
My "QUESTION IS" what i have to do to solve that?
What should I pay attention?
First you need to fix your HTML becaue your id values aren't unique. In fact, you don't even need id values, so you should use "slide_button" as a class. You can then use it to select all the buttons:
<div onClick="clicked(this);" class="slide_button"><dir></dir></div>
<div onClick="clicked(this);" class="slide_button"><dir></dir></div>
<div onClick="clicked(this);" class="slide_button"><dir></dir></div>
<div onClick="clicked(this);" class="slide_button"><dir></dir></div>
<div onClick="clicked(this);" class="slide_button"><dir></dir></div>
The CSS needs to be changed now so "slide_button" is a class selector, instead of an id selector:
.slide_button {
display: inline-block;
}
As for clearing the background, clear all of them before coloring the selected one red:
function clicked(slide_button) {
var buttons = document.getElementsByClassName('slide_button');
for(var i = 0; i < buttons.length; i++) {
buttons[i].getElementsByTagName('dir')[0].style.backgroundColor = '';
}
slide_button.getElementsByTagName('dir')[0].style.backgroundColor = 'red';
}
jsfiddle
This uses just JavaScript with no JQuery, but if you are using JQuery, you might as well use it here. The code is a lot shorter and easier to follow.
Here's a JQuery version:
$(function() {
$('.slide_button').click(function() {
var $button = $(this);
$button.children(':first').css({ backgroundColor: 'red' });
$button.siblings().children(':first').css({ backgroundColor: '' });
});
});
Note: This registers a click-handler, so you can get rid of the "onclick" attirbutes.
jsfiddle
You have to select all other points and set their background to none.
Or remeber which point is selected and on select another just remove background on last and remeber current point, then set its background to red.
See fiddle: http://fiddle.jshell.net/399Dm/5/
At first id should be unique per element.
<div class="slide_button"><dir class="button"></dir></div>
<div class="slide_button"><dir class="button"></dir></div>
<div class="slide_button"><dir class="button"></dir></div>
<div class="slide_button"><dir class="button"></dir></div>
<div class="slide_button"><dir class="button"></dir></div>
Second, you should store reference of clicked element if you want later remove background color, and instead of inline event handlers or binding all elements would be better if you use event delegation.
Demonstration
(function () {
"use strict";
// getting parent node of divs, due to bind click event. then
var ele = document.querySelector(".slide_button").parentNode,
prev = null; // store previous clicked element
ele.addEventListener("click", clickHandler); // event handler.
function clickHandler(e) {
var t = e.target; // get target of clicked element
// filter by target node name and class. edit: removed class checking
if (t.nodeName.toLowerCase() === "dir") {
// checking value of prev !== null and it's not same element.
if (prev && prev !== t) {
prev.style.backgroundColor = "";
}
prev = t; // store clicked element
t.style.backgroundColor = "red";
}
}
}());
I have fixed the fiddle so that it works hopefully as you plan.
http://jsfiddle.net/399Dm/8/ There you go!
var forEach = function(ctn, callback){
return Array.prototype.forEach.call(ctn, callback);
}
function clear(element, index, array) {
element.getElementsByTagName("dir")[0].style.backgroundColor="";
}
function clicked(slide_button) {
forEach(document.getElementsByClassName("slide_button"), clear);
//.style.backgroundColor="";
slide_button.getElementsByTagName("dir")[0].style.backgroundColor="red";
}
I had a slightly different method than #atlavis but a similar result.
http://fiddle.jshell.net/2AGJQ/
JSFIDDLE DEMO
jQuery
$('.slide_button').click(function(){
$('.slide_button dir').css("background-color", "inherit");
$(this).find('dir').css("background-color", "red");
});
HTML - Your markup is invalid because you have duplicate ids. Make them classes as below instead.
<div class="slide_button" >
<dir class="button_1"></dir>
</div>
<div class="slide_button">
<dir class="button_2"></dir>
</div>
<div class="slide_button">
<dir class="button_3"></dir>
</div>
<div class="slide_button">
<dir class="button_4"></dir>
</div>
<div class="slide_button">
<dir class="button_5"></dir>
</div>
CSS change
.slide_button {
display: inline-block;
}
If you can look at the following jsfiddle, I used jQuery to get what you want.
In my code, I've got 4 divs aligned inline.
What I want is, on clicking any div, it resizes to fill the space of all 4 divs (width:1000px)
and hides the other divs.
And on reclicking the div, it'll resize to the original dimensions.
This is what i've done till now.
<div class="gallery-image-replenish" id="bloc2" onclick="document.getElementById('bloc2').style.width = '980px'">
</div>
As of now, on click this resizes the div below the other divs. I know there's a method to hide the other divs, but I don't know how to do that.
With this kind of HTML:
<div class="gallery-image-replenish" id="bloc1"></div>
<div class="gallery-image-replenish" id="bloc2"></div>
<div class="gallery-image-replenish" id="bloc3"></div>
<div class="gallery-image-replenish" id="bloc4"></div>
you can use this kind of JS:
var handler = function(e){
e.target.style.width = "1000px";
for (j = divs.length; j--; ) {
if (divs[j].id != e.target.id) {
divs[j].style.display = "none";
}
}
}
var divs = document.getElementsByClassName('gallery-image-replenish'); //array of divs
var div;
for (i = divs.length; i--; ) {
div = divs[i];
div.addEventListener('click', handler);
}
Is it possible to use jQuery (jquery.com) on your project?
Because it would save a lot of code (and make it more readable!).
It would look like this (not tested, but probably works :P):
<div id="bloc1" class="gallery-image-replenish">1</div>
<div id="bloc2" class="gallery-image-replenish">2</div>
<div id="bloc3" class="gallery-image-replenish">3</div>
<div id="bloc4" class="gallery-image-replenish">4</div>
<script>
jQuery(document).ready(function(){
var galleryElements = $('.gallery-image-replenish');
galleryElements.click(function(){
var clickedElement = $(this);
if (clickedElement.hasClass('expanded')) { // if it has the class expanded, remove it (and show other elements again)
clickedElement.removeClass('expanded');
galleryElements.show();
} else { // if it has not got the expanded css class hide other and add class to expanded
galleryElements.not(clickedElement).hide(); // hide every other div
$(this).addClass('expanded'); // add stylesheet class for the new bigger width
}
});
});
</script>
The pure javascript way to hide an element is:
document.getElementById('otherdiv1').style.display = 'none';
Following is a solution which uses a common javascript function to perform what you want:-
<div class="gallery-image-replenish" id="bloc1" onclick="manageDivs(this.id)"> </div>
<div class="gallery-image-replenish" id="bloc2" onclick="manageDivs(this.id)"> </div>
<div class="gallery-image-replenish" id="bloc3" onclick="manageDivs(this.id)"> </div>
<div class="gallery-image-replenish" id="bloc4" onclick="manageDivs(this.id)"> </div>
<script type="text/javascript">
function manageDivs(divId)
{
document.getElementById(divId).style.width = '980px'";
//to hide rest of the divs
for(i=1;i<=4;i++)
{
if(divId!='bloc'+i)
document.getElementById('bloc'+i).style.display = 'none';
}
}
</script>
This is a simple exemple ,
var activ = false;
$('.aligned').live('click',function(){
if(!$(this).hasClass('actif')) {
$('.aligned').css('width','0');
$('.aligned').removeClass('actif');
$(this).css('width','1000px');
$(this).addClass('actif');
} else {
$('.aligned').css('width','250px');
}
});
you can use jQuery animate for more visual effect
I am trying to figure out if there is a way around doing .hasClass() multiple times to see if the active element I am working with has one of currently four specific classes, I am also trying to figure out the most optimized way to do this while the element(s) that are acting as the trigger (or the active element) has multiple classes in it mostly for styling purposes.
Example of the HTML:
<div class="form_row">
<div class="primary_row">1</div>
</div>
<div class="form_row">
<div class="primary_row subexists">1</div>
<div class="primary_row_sub">1a</div>
</div>
<div class="form_row">
<div class="primary_row subexists">1</div>
<div class="primary_row_sub subexists">1a</div>
<div class="secondary_row">2</div>
</div>
<div class="form_row">
<div class="primary_row subexists">1</div>
<div class="primary_row_sub subexists">1a</div>
<div class="secondary_row subexists">2</div>
<div class="secondary_row_sub">2a</div>
</div>
I am in the progress of currently building it up, so this is still a rough draft, but its safe to assume more classes will exist on various elements per the need. The Four main classes I am worried about are primary_row, primary_row_sub, secondary_row, secondary_row_sub. I am building a click handler like:
$('.form_row > div').click(function()
{
//code
});
in this click handler I want to be able to detect if the element clicked is one of the four mentioned above. Where if it is, I want to do something based on which. So determining which class is of the element clicked, rather than building four click handlers one for each type. I am hoping I can keep it optimized and contained to a single handler. Any ideas?
One option:
var classMap = {"one": function () { alert("one");},
"two": function () { alert("two");},
"three": function () { alert("three");}
}
, classes = "";
$('div').click(function (e) {
classes = this.className.split(" ");
for (key in classMap) {
if ($.inArray(key, classes) !== -1) {
classMap[key]();
}
}
});
http://jsfiddle.net/wp9X7/5/
if ($(this).is(".primary_row")) {
...
} elseif ($(this).is(".primary_row_sub")) {
...
} and so on