Highlight clicked hyperlink in angularjs - javascript

Below is my HTML code,
<div id="Navigation" class="md-dialog-full">
<div class="products-options">
<a ng-click='addType("Physical")' href="javascript:void(0);">
<h1>Physical</h1>
<label>An item that is shipped to your customers</label>
</a>
<a ng-click='addType("Digital")' href="javascript:void(0);">
<h1>Digital</h1>
<label>Content that is downloaded</label>
</a>
<a ng-click='addType("Service")' href="javascript:void(0);">
<h1>Services</h1>
<label>Provide a Service</label>
</a>
</div>
</div>
I want to highlight the selected hyperlink, I have tried many methods in internet but almost all are linked with the URL of the hyperlink. Please help. I have succeed in using hover to highlight when hovering over a link but I'm stuck in highlighting the clicked link.

If you say your code does not have url paths, I'm assuming that all of this needs to happen within the same view and the same controller. In that case, you can put a variable on the scope, say selectedLink, and use ng-class to apply the proper styling:
<div id="Navigation" class="md-dialog-full">
<div class="products-options">
<a ng-click='addType("Physical");selectedLink = "Physical"' href="javascript:void(0);" ng-class="{'selected': selectedLink === 'Physical'}">
<h1>Physical</h1>
<label>An item that is shipped to your customers</label>
</a>
<a ng-click='addType("Digital");selectedLink = "Digital"' href="javascript:void(0);" ng-class="{'selected': selectedLink === 'Digital'}">
<h1>Digital</h1>
<label>Content that is downloaded</label>
</a>
<a ng-click='addType("Service");selectedLink = "Service"' href="javascript:void(0);" ng-class="{'selected': selectedLink === 'Service'}">
<h1>Services</h1>
<label>Provide a Service</label>
</a>
</div>
</div>
css:
.selected { color: yellow; }

You can try something like this:
<a ng-click='addType("Physical"); visited = true' ng-class="{'visited' : visited}" href="javascript:void(0);"></a>

<div id="Navigation" class="md-dialog-full">
<div class="products-options">
<a ng-click='addType("Physical")' href="javascript:void(0);" class="{selectedPhysical}">
<h1>Physical</h1>
<label>An item that is shipped to your customers</label>
</a>
<a ng-click='addType("Digital")' href="javascript:void(0);" class="{selectedDigital}">
<h1>Digital</h1>
<label>Content that is downloaded</label>
</a>
<a ng-click='addType("Service")' href="javascript:void(0);" class="{selectedService}">
<h1>Services</h1>
<label>Provide a Service</label>
</a>
</div>
</div>
in your controller
$scope.addType = function(type){
if(type == 'Physical'){
$scope.selectedPhysical = 'selectedLink'
$scope.selectedDigital = ''
$scope.selectedService = ''
}
else if(type == 'Digital'){
$scope.selectedDigital = 'selectedLink'
$scope.selectedService = ''
$scope.selectedPhysical = ''
}
else{
$scope.selectedService = 'selectedLink'
$scope.selectedDigital = ''
$scope.selectedPhysical = ''
}
}
add css for selectedLink
.selectedLink{
color : Blue;
font-size: 1.2em;
//whatever the changes you want to made for the active link text
}
If you are using this you can overwrite the browser Active pseudo class

Related

Calling a function in another function to reduce repeated code

I have two functions one thats triggered on a mouseenter event and the other on mouseleave. Both of these functions are repeated three times.
On mouseenter the classlist "active" is addded 5x and the text content is changed.
On mouseleave the classlist active is removed 5x and the text content is set to an empty string, and the original image is displayed again.
When the mouseenter event listener is triggered, Depending on which image is being hovered (3 images).
the text content property that gets added various between the three "Photosnap" "Dine" "Nike".
As-well as the background color that gets triggered various between "red" "blue" "pink".
Hover state shown as red left image and normal state shown as right image
-The image shown here is one of three. It is displayed with a red background and the text content of "photosnap".
-The other with a blue background and the text content of "Dine".
-The third and final with a pink background and the text content of "Nike".
I hope this paints a clear picture i am having a hard time making this a code snippet.
I am trying to refactor this javascript so its not so repetitive. I'm new to javascript and having a hard time getting this to work as something other than what i currently have. I'm not clear on how to make a function that i can call inside of other functions to cut down on the repeated code. Or possibly use the "this" keyword ?
Javascript--
// //Photosnap Project #1 ---------------------------------------------------------
// Content in project on hover
let projectTitle = document.querySelector('.projectTitlePhotosnap');
let projectLine = document.querySelector('.hoverLinePhotosnap');
// View live View code text wrapper
let projectRowWrap = document.querySelector('.flexWrapperRowPhotosnap');
// Background color + image
let photosnapBackground = document.querySelector('.photosnapBackground');
let photosnapImg = document.querySelector('.photosnap');
// Mouse in add background color title and links
photosnapBackground.addEventListener('mouseenter', function() {
photosnapBackground.classList.add('active');
photosnapImg.classList.add('active');
projectTitle.textContent = 'Photosnap';
projectTitle.classList.add('active');
projectLine.classList.add('active');
projectRowWrap.classList.add('active');
});
// Mouse out remove all
photosnapBackground.addEventListener('mouseleave', function() {
photosnapBackground.classList.remove('active');
photosnapImg.classList.remove('active');
dineBackground.classList.remove('active');
dineImg.classList.remove('active');
projectTitle.textContent = '';
projectTitle.classList.remove('active');
projectLine.classList.remove('active');
projectRowWrap.classList.remove('active');
});
//Dine Project #2 ---------------------------------------------------------------
// Content in project on hover
let projectTitleDine = document.querySelector('.projectTitleDine');
let projectLineDine = document.querySelector('.hoverLineDine');
// View live View code text wrapper
let projectRowWrapDine = document.querySelector('.flexWrapperRowDine');
// Background color + image
let dineBackground = document.querySelector('.dineBackground');
let dineImg = document.querySelector('.dine');
// Mouse in add background color title and links
dineBackground.addEventListener('mouseenter', function() {
dineBackground.classList.add('active');
dineImg.classList.add('active');
projectTitleDine.textContent = 'Dine';
projectTitleDine.classList.add('active');
projectLineDine.classList.add('active');
projectRowWrapDine.classList.add('active');
});
// Mouse out remove all
dineBackground.addEventListener('mouseleave', function() {
dineBackground.classList.remove('active');
dineImg.classList.remove('active');
projectTitleDine.textContent = '';
projectTitleDine.classList.remove('active');
projectLineDine.classList.remove('active');
projectRowWrapDine.classList.remove('active');
});
//Nike Project #3 ---------------------------------------------------------------
// Content in project on hover
let projectTitleNike = document.querySelector('.projectTitleNike');
let projectLineNike = document.querySelector('.hoverLineNike');
// View live View Code wrapper
let projectRowWrapNike = document.querySelector('.flexWrapperRowNike');
// Background color + image
let nikeBackground = document.querySelector('.nikeBackground');
let nikeImg = document.querySelector('.nike');
// Mouse in add background color title and links
nikeBackground.addEventListener('mouseenter', function() {
nikeBackground.classList.add('active');
nikeImg.classList.add('active');
projectTitleNike.textContent = 'Nike';
projectTitleNike.classList.add('active');
projectLineNike.classList.add('active');
projectRowWrapNike.classList.add('active');
});
// Mouse out remove all
nikeBackground.addEventListener('mouseleave', function() {
nikeBackground.classList.remove('active');
nikeImg.classList.remove('active');
projectTitleNike.textContent = '';
projectTitleNike.classList.remove('active');
projectLineNike.classList.remove('active');
projectRowWrapNike.classList.remove('active');
HTML--
<!-- Projects desktop -->
<div id="horizontalScroll" class="horizontalScroll projectsContainer">
<!-- Photosnap -->
<div class="projectsWrapper photosnapBackground">
<span class="testFunc hoverTitleFont projectTitlePhotosnap"></span>
<div class="testFunc hoverLine hoverLinePhotosnap"></div>
<img src="assets/projects/photosnap-desktop-p.jpg" alt="photosnap project" class="photosnap">
<div class="testFunc flexWrapperRow flexWrapperRowPhotosnap">
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Live</span>
</a>
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Code</span>
</a>
</div>
</div>
<!-- Dine -->
<div class="projectsWrapper dineBackground">
<span class="testFunc hoverTitleFont projectTitleDine"></span>
<div class="testFunc hoverLine hoverLineDine"></div>
<img src="assets/projects/dine-desktop-p.png" alt="dine project" class="dine">
<div class="testFunc flexWrapperRow flexWrapperRowDine">
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Live</span>
</a>
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Code</span>
</a>
</div>
</div>
<!-- Nike -->
<div class="projectsWrapper nikeBackground">
<span class="hoverTitleFont projectTitleNike"></span>
<div class="hoverLine hoverLineNike"></div>
<img src="assets/projects/nike-desktop-p.png" alt="nike project" class="nike">
<div class="flexWrapperRow flexWrapperRowNike">
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Live</span>
</a>
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Code</span>
</a>
</div>
</div>
</div>
Yes you're using 3 times the same function, so we sure can do better.
Here is a first simple idea, make a loop on the tree elements :
JAVASCRIPT
let slide = ['Photosnap', 'Dine', 'Nike'] ;
for (let i = 0; i < slide.length ; i++ ) {
let lowercaseName = slide[i].toLowerCase() ;
let projectTitle = document.querySelector('.projectTitle' + slide[i]);
let projectLine = document.querySelector('.hoverLine' + slide[i]);
// View live View code text wrapper
let projectRowWrap = document.querySelector('.flexWrapperRow'+ slide[i]);
// Background color + image
let background = document.querySelector('.'+ lowercaseName+'Background');
let img = document.querySelector('.'+ lowercaseName);
// Mouse in add background color title and links
background.addEventListener('mouseenter', function() {
background.classList.add('active');
img.classList.add('active');
projectTitle.textContent = slide[i];
projectTitle.classList.add('active');
projectLine.classList.add('active');
projectRowWrap.classList.add('active');
});
// Mouse out remove all
background.addEventListener('mouseleave', function() {
background.classList.remove('active');
img.classList.remove('active');
background.classList.remove('active');
img.classList.remove('active');
projectTitle.textContent = '';
projectTitle.classList.remove('active');
projectLine.classList.remove('active');
projectRowWrap.classList.remove('active');
});
}
Another approche, or to upgrate this solution can be use "data" attribute, like "data-id" or "data-color" you can give the name you want and have as many "data" atributes you want on DOM element.
You could save classname too, catching element's child of the main block with .childNodes.
I would suggest some updation in html structure before we move to javascript.
We want to keep HTML as much strucutural as we want. So that similar elements can be easily selected.
Make it easier to group project related element.
Remove unnecessary class name.
Added comments where every necessary.
<!-- Projects desktop -->
<div id="horizontalScroll" class="horizontalScroll projectsContainer">
<!-- Photosnap -->
<div class="projectsWrapper photosnap Background"> <!-- Remove backgound here, if you its needed for class selection in css seperate it -->
<span class="testFunc hoverTitleFont projectTitle"></span> <!-- Remove photosnap-->
<div class="testFunc hoverLine"></div> <!-- Remove hoverLinePhotosnap-->
<img src="assets/projects/photosnap-desktop-p.jpg" alt="photosnap project" class="photosnapImg"> <!-- Since there is only 1 img tag inside photosnap we can select through img tag-->
<div class="testFunc flexWrapperRow"> <!-- remove flexWrapperRowPhotosnap-->
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Live</span>
</a>
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Code</span>
</a>
</div>
</div>
<!-- Dine -->
<div class="projectsWrapper dine Background"> <!-- seperated background-->
<span class="testFunc hoverTitleFont projectTitle"></span> <!--remove Dine-->
<div class="testFunc hoverLine"></div> <!--remove hoverLineDine-->
<img src="assets/projects/dine-desktop-p.png" alt="dine project" class="dineImg">
<div class="testFunc flexWrapperRow"> <!--removed flexWrapperRowDine-->
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Live</span>
</a>
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Code</span>
</a>
</div>
</div>
<!-- Nike -->
<div class="projectsWrapper nike Background"> <!--seperated backgound-->
<span class="hoverTitleFont projectTitle"></span> <!--removed nike-->
<div class="hoverLine"></div> <!--removed hoverLineNike-->
<img src="assets/projects/nike-desktop-p.png" alt="nike project" class="nikeImg">
<div class="flexWrapperRow"> <!--removed flexWrapperRowNike-->
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Live</span>
</a>
<a target="_blank" rel="noopener noreferrer" href="">
<span class="hoverIconFont">View Code</span>
</a>
</div>
</div>
</div>
Now we have our proper html structure we can move to js
A function to add class and other property to the element
A function to remove class from the element
// property being an object {textContent: "photosnap", backgroundColor: "red"}
function addProperty(element, property) {
// I belive there are 4 Elements that need to be selected
const title = element.querySelector("projectTitle");
const projectLine = element.querySelector("hoverLine");
const projectRowWrap = element.querySelector("flexWrapperRow");
const image = element.querySelector("img");
// if removing looks like code duplicate elements can be pushed to an array, and iterate over it to add/remove the class
/*
const elementList = [];
elementList.push(element);
elementList.push(image);
elementList.push(title);
elementList.push(projectLine);
elementList.push(projectRowWrap);
elementList.forEach(el => {
el.classList.add("active");
});
*/
title.textContent = property.textContent;
element.classList.add("active");
image.classList.add("active");
title.classList.add("active");
projectLine.classList.add("active");
projectRowWrap.classList.add("active");
}
function removeProperty(element) {
const title = element.querySelector("projectTitle");
const projectLine = element.querySelector("hoverLine");
const projectRowWrap = element.querySelector("flexWrapperRow");
const image = element.querySelector("img");
title.textContent = "";
element.classList.remove("active");
image.classList.remove("active");
title.classList.remove("active");
projectLine.classList.remove("active");
projectRowWrap.classList.remove("active");
}
const element = document.querySelector("photosnap");
element.addEventListener("mouseenter", (event) => {
const eventElement = event.target;
const property = { textContent: "photosnap" };
addProperty(eventElement, property);
});
element.addEventListener("mouseleave", (event) => {
removeProperty(event.target);
});

Selecting anchors within div by div id

New to JS, just dipping in to solve a problem (I bet everyone says that!). I need to write a script to select an anchor and insert an <img>.
There are several <a>'s within a div that has an id of _nwa_social_logins. I need to add an img tag to one of those. I'm not sure of the best way of doing this.
It's a captive portal page served up by a product we use, and the bit I'm interested in looks like this:
<div id="_nwa_social_logins">
<a class="btn btn-facebook" href="<url>/guest/social-media.php?oauth_init=1&oauth=facebook" title="">
<i class="icon-facebook"></i> Facebook
</a>
<a class="btn btn-linkedin" href="https://<url>/guest/social-media.php?oauth_init=1&oauth=linkedin" title="">
<i class="icon-linkedin"></i> LinkedIn
</a>
<a class="btn btn-google" href="https://<url>/guest/social-media.php?oauth_init=1&oauth=google" title="">
<i class="icon-google"></i> Google
</a>
<a class="btn btn-twitter" href="https://<url>/guest/social-media.php?oauth_init=1&oauth=twitter" title="">
<i class="icon-twitter"></i> Twitter
</a>
<a class="btn btn-github" href="https://<url>/guest/social-media.php?oauth_init=1&oauth=azure" title=""><img src="images/icon-microsoft.png" align="middle">Microsoft Azure AD
</a>
<a class="btn btn-github" href="https://<url>/guest/social-media.php?oauth_init=1&oauth=amazon" title="">Amazon</a>
</div>
So far I have
let items = document.querySelector('#_nwa_social_logins a');
To be honest I don't know how to even check if that has selected anything.
I need to select the Amazon anchor and set an <img> for the button. If the selection above gives me a list of <a>s (objects?) can I loop through them and look for one that has an href value that ends with 'amazon'?
Thank you
You can do this:
<script>
window.addEventListener('load', () => {
let links = document.querySelectorAll('#_nwa_social_logins a');
links.forEach((link, index) => {
if (link.getAttribute("href").toLowerCase().lastIndexOf('amazon') >= 0)
link.innerHTML = '<img src="someimage">';
});
});
</script>

I need to change html class attribute for every ng-repeat element with button

i have html div where i use ng-repeat that gives me back elements from array
<div>
<div class="col-sm-3" ng-repeat="el in vm.filmovi " id="filmovi">
<img src="http://image.tmdb.org/t/p/w500/{{el.poster_path}}" style="width:100%;"><br>
<a ng-click="vm.set_favorit(el)" style="cursor:hand; color:white;" uib-tooltip="Postavi u omiljene">
<i class="glyphicon" ng-class="{'glyphicon-star-empty':el.favorit!=true, 'glyphicon-star':el.favorit==true}"
aria-hidden="true"></i></a>
<a href="http://www.imdb.com/title/{{el.imdb_id}}/" style="color:white;">
<strong>{{ el.title | limitTo: 20 }}{{el.title.length > 20 ? '...' : ''}}</strong></a>
<a class="glyphicon glyphicon-share-alt" style="margin-left:5px; color:white;" ng-click="vm.open()" uib-tooltip="share" ></a><br>
{{el.popularity}} <br>
<a style="color:white;" href="#" ng-click="vm.filter(genre)" ng-repeat="genre in el.genres"><small>{{genre.name}} </small></a>
<div ng-init="x = 0">
<span uib-rating ng-model="x" max="5"
state-on="'glyphicon-star'"
state-off="'glyphicon-star-empty'"></span></div>
</div>
</div>
now i created a button that changes value of id "filmovi"
<li><a href="#" ng-hide="vm.ulogovan" ng-click="vm.dugme();" >losta</a></li>
and created function vm.dugme() that gets element by id and sets class atribute to col-sm-4
vm.dugme=function(){
document.getElementById("filmovi").setAttribute("class","col-sm-4");
};
but when i did that only the first element changed
but i need for all of them to change to col-sm-4 , any suggestion?
Don't do DOM manipulation from angularjs controller. Instead make use of directive provided by angular.
You could use ng-class with expression so that whenever expression gets satiesfied the class will be added over that DOM. To add class put addColSm4 flag inside a controller and change that flag from dugme method of your controller. Also by looking at screenshot it seems like you need col-sm-3 class at the beginning, afterwards you need to apply col-sm-4.
HTML
<div class="row">
<div class="col-sm-3" ng-repeat="el in vm.filmovi"
ng-class="{'col-sm-4': vm.addColSm4, 'col-sm-3': !vm.addColSm4 }" >
.. Html will stay as is ..
</div>
</div>
<li>
<a href="#" ng-hide="vm.ulogovan"
ng-click="vm.dugme()">
losta
</a>
</li>
Code
vm.dugme = function (){
vm.addColSm4 = true;
};
Demo Plunker

How to change the innerHtml content using 'data-id' attribute using jquery?

<li data-id="528">
<a title="LOGIN" class="dropdown-toggle" href="#">
<i class="glyphicon glyphicon-user"></i>LOGIN</a>
<div style="width: 350px;" data-width="350" data-class="menu-login-row">My other content</div>
</li>
I Have this html I want to change the content by data-id like given below
<li data-id="528">
<a title="LOGOUT" href="/logout">
<i class="glyphicon glyphicon-user"></i>LOGOUT</a>
<div style="width: 350px;" data-width="350" data-class="menu-login-row">My other content</div>
</li>
Is this possible if, Please advice me
Thank you.
Yes it's possible.
Like this
var a=$('li[data-id="528"]').find('a');
a.attr('href','/logout');
a.contents().filter(function() {
return this.nodeType == 3
}).each(function(){
this.textContent = this.textContent.replace('LOGIN','LOGOUT');
});
You can get the element by attribute selector, and use .html() to modify content:
$('[data-id="528"]').html('<a title="LOGOUT" href="/logout"><i class="glyphicon glyphicon-user"></i>LOGOUT</a><div style="width: 350px;" data-width="350" data-class="menu-login-row">My other content</div>')
Actually you can modify innerHtml of an jquery element by .html()
$(selector).html(whatEverYouWant);
Try it.
var htmlData = '<a title="LOGOUT" href="/logout">';
htmlData+= '<i class="glyphicon glyphicon-user"></i>LOGOUT</a>';
htmlData+='<div style="width: 350px;" data-width="350" data-class="menu-login-row">My other content</div>';
jQuery('li[data-id="528"]').html(htmlData);
You can write just one line code for this
$('li[data-id="528"]').find('a').attr("title","LOGOUT").attr("href","/logout").html('<i class="glyphicon glyphicon-user"></i>LOGOUT</a>');

Incrementing +1 the class in javascript

Hi im doing a PHP loop where I set a class, this loop make a list of items, and each one of them will have a "share" button that will open a window, (div display:none) the javascript open this div, and it works perfect..
My problem is that in this moment I have inserted the <script> code inside the loop so each item has its own <script></script> code...
Is there any way to do just one and take that code out of the php loop, so I can improve the code.
<script>
$('a.sharebtnc').click(
function(event) {
event.stopPropagation();
$('div.redescompartir').fadeToggle(300);
}
);
</script>
In the Loop well I just add to the class the id like this (id :32 )
<script>
$('a.sharebtnc32').click(
function(event) {
event.stopPropagation();
$('div.redescompartir32').fadeToggle(300);
}
);
</script>
How can I make this script works for all elements no matter the id number, I have no idea, but I know this is the correct way of doing this , right?
The HTML is very simple, its the same for each item... I mean each item has its own div with for <a href="" > </a> elements
<a href="#" class="sharebtnc(id)">
<div class="redescompartir(id)">
<a href="" >Twitter </a>
<a href="" >Facebook </a>
<a href="" >Google </a>
<a href="" >Foursquare </a>
</div>
Add a new class and attribute to the input element like
instead of
<a class="sharebtnc32" />
use
<a class="sharebtnc sharebtnc32" data-id="32"/>
then
jQuery(function ($) {
$('.sharebtnctl').click(function (event) {
event.stopPropagation();
$('.redesopenclose' + $(this).data('id')).fadeToggle(300);
});
})
My preferred method: PHP to generate link between the two elements, then a small snippet of JS to grab which particular one was clicked.
PHP:
$num = 100;
for ($x = 0; $x < $numItems; $x++) {
echo "
<a href='#' class='sharebtn' target='$x'>Share</a>
<div class='redescompartir' id='$x'>
<a href=''>Twitter</a>
<a href=''>Facebook</a>
<a href=''>Google</a>
<a href=''>Foursquare</a>
</div>
";
}
HTML output:
<a href="#" class="sharebtn" target='32'>Share</a>
<div class="redescompartir" id='32'>
<a href="" >Twitter </a>
<a href="" >Facebook </a>
<a href="" >Google </a>
<a href="" >Foursquare </a>
</div>
JS:
$('a.sharebtn').on('click', function(e) {
e.stopPropagation();
var target = $(e.currentTarget).attr('target');
$('#'+target).fadeToggle(300);
});
This way you only need a single <script></script> tag, which your user's broswers will thank you for. :)

Categories