How to reset jQuery toggled classes applied throughout the page? (AngularProject) - javascript

The below CSS is applied on click of link available at one element:
<a class="vehicleinfo avai-vehicle-info-anc-tag" ng-click="vehicleInfo($event)">Vehicle Info
<span class="s-icon red-down-arrow"> </span>
</a>
$scope.vehicleInfo = function(event) {
var el = jQuery(event.currentTarget),
featuredcarbox = el.closest(".avilablecar.available-car-box");
featuredcarbox.find(".avlcarimagetab img").toggleClass("slide-left");
featuredcarbox.toggleClass("bg-grey");
el.toggleClass("icon-remove");
featuredcarbox.find(".available-car-fac").toggleClass("hidden");
}
I want to remove all the above toggled classes applied at each element (vehicle) on calling one function.
How can I achieve??

too simple.....i think. if you need to remove toggled classes just replace toggleClass to removeClass. as i show in new function/
$scope.vehicleClassRessetInfo = function(event) {
var el = jQuery(event.currentTarget),
featuredcarbox = el.closest(".avilablecar.available-car-box");
featuredcarbox.find(".avlcarimagetab img").removeClass("slide-left");
featuredcarbox.removeClass("bg-grey");
el.removeClass("icon-remove");
featuredcarbox.find(".available-car-fac").removeClass("hidden");
}

You are probably looking for ng-class with a ternary operator. Ng-class works like this:
<div ng-class="(foo == 1) ? 'classes if-true' : 'classifFalse'"
The "(foo == 1)" part can be an expression, an evaluated function, or a variable from the controller.
I don't have enough to work with to put it in a fiddle I don't think, but here is what I would do...
HTML:
<a ng-class="(applyClassses == true) ? 'vehicleinfo avai-vehicle-info-anc-tag' : ''" ng-click="vehicleInfo($event)">Vehicle Info
<span class="s-icon red-down-arrow"></span>
</a>
Controller:
$scope.vehicleInfo = function() {
if () {
$scope.applyClasses = true;
}
else {
$scope.applyClasses = false;
}
}

Related

Toggle visibility for multiple divs with one function: navigation bar

My Assignment: Hi! I am doing an assignment in school where I am supposed write code in Javascript in order to toggle visibility for the submenus each belonging to their own topmenu in a navigation bar for a webpage. The visibility should be set to hidden by default and should be shown when a topmenu is clicked on.
I know how to toggle visibility for ONE submenu belonging to a topmenu, but fail to make my code work for multiple elements. My HTML-code:
<a class="left_top1" onclick = "toggle()">Opinion</a><br>
<div class="left_submenu_1" style="display: none;">
<a class="left_sub1">Leaders</a><br>
<a class="left_sub1">Debates</a><br>
</div>
<br>
<a class="left_top2" onclick = "toggle()">Economy</a><br>
<div class="left_submenu_2" style="display: none;">
<a class="left_sub2">News</a><br>
<a class="left_sub2">Your Economy</a><br>
</div>
My Problem: The topmenus I speak of are "Opinion" and "Economy". The visibility of the div with the class "left_submenu_1" should be toggled when you click the topmenu "left_top1". Thus should the visibilily of the div with the class "left_submenu_2" be toggled when you click the topmenu "left_top2". This is what I fail to do. My Javascript code is so far:
function toggle() {
var e = document.querySelectorAll("div.left_submenu_1, div.left_submenu_2");
for (var i=0; i < e.length; i++) { // I know this will enable/disable the visibility for ALL elements selected from the querySelectorAll, which should NOT happen
if(e[i].style.display == "none") {
e[i].style.display = "block";
} else if(e[i].style.display == "block") {
e[i].style.display = "none";
}
}
}
Anyone who knows how to solve this issue of mine? I know there are errors in the for-loop (as I wrote next to it), but this is the best I can manage for now.
Please note: We are NOT allowed to use jQuery or to give the topmenus id:s, as the idea is to use one general function to toggle the visibility. Furthermore, the code which enables the toggle-function should be done in Javascript.
I would approach it by passing the class name of the div to be shown (or hidden) into the function to begin with.
HTML
<a class="left_top1" onclick = "toggle('.left_submenu_1')">Opinion</a>
Then in the function you can grab the element and toggle it's display state.
JavaScript
function toggle(qs) {
var e = document.querySelector(qs);
e.style.display = e.style.display === 'block' ? 'none' : 'block';
}
The e.style.display === 'block' ? 'none' : 'block' part is saying if the elements display state is equal to block, return none, otherwise return block.
The return value is set as the new element display state due to the e.style.display = beforehand.
Tring to make it work modifying it as less as possible :
- use onClick="toggle(this)" in the anchors tags
- use a bit different toggle function like:
function toggle (el) {
var e = document.querySelectorAll('.' + el.className.replace('top', 'submenu_'))[0];
e.style.display = e.style.display.match(/none/) ? '' : 'none';
}
hope it helps, but I have to suggest You to make a small step forward and search for event delegation. Bye

How can I automatically merge unnecessary html tags

How can I merge a tags with the same url together if they are beside each other. For instance, I am dealing with html that looks similar to this:
<div>
<a href='/url.com'>This is</a><a href='/url.com'> the </a><a href='/url.com'>same link.</a>
This is not linked but might have some <b>bolding</b> or not.
<a href='/url.com'>These are</a><a href='/url2.com'> two different links.</a>
</div>
Through jQuery, I would like the inside of the div to be:
<div>
<a href='/url.com'>This is the same link.</a>
This is not linked but might have some <b>bolding</b> or not.
<a href='/url.com'>These are</a><a href='/url2.com'> two different links.</a>
</div>
I can merge tags together by iterating through each pair of a tags to see if they share (1) the same link and (2) the same parent, but then I get output like this:
<div>
<a href='/url.com'>This is the same link.These are</a>
This is not linked but might have some <b>bolding</b> or not.
<a href='/url2.com'> two different links.</a>
</div>
I'm not sure how to realize that there's text in the middle.
EDIT: Here's what I've tried
$('a').addClass('linkCheck');
while ($('.linkCheck').length > 0) {
first_to_check = $('.linkCheck:first');
first_to_check.removeClass('linkCheck');
if ($('.linkCheck').length > 0) {
second_to_check = $('.linkCheck:first');
replaced = false;
if (first_to_check.attr('href') == second_to_check.attr('href')) {
found_first = false;
old_content_html = $('#divID').html();
old_content_text = $('#divID').text();
first_to_check.parent().children().each(function () {
if (found_first == true && $(this).get(0) == second_to_check.get(0)) {
html = second_to_check.html();
second_to_check.remove();
first_to_check.html(first_to_check.html() + html);
found_first = false;
replaced = true;
if ($('#divID').text() != old_content_text) {
replaced = false;
$('#divID').html(old_content_html);
}
return false;
}
if ($(this).get(0) == first_to_check.get(0)) {
found_first = true;
}
else {
found_first = false;
}
});
}
if (replaced == true) {
first_to_check.addClass('linkCheck');
}
}
}
For each anchor, see if its next sibling is an anchor with the same href. If so, append its sibling's contents() and remove the sibling.
You'll need to use the DOM nextSibling to handle text nodes correctly, because jQuery's next() method skips over them.
Repeat as long as duplicate adjacent hrefs are found:
function merge() {
var merged;
do {
merged = false;
$('a').each(function() {
var nexta = $(this.nextSibling);
if (nexta.attr('href') === $(this).attr('href')) {
$(this).append(nexta.contents());
merged = true;
nexta.remove();
}
});
} while (merged);
} //merge
merge();
$('pre').text($('div').html());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<a href='/url.com'>This is</a><a href='/url.com'> the </a><a href='/url.com'>same link.</a>
This is not linked and has <b>bolding</b>.
<a href='/url.com'>These are</a><a href='/url2.com'> two different links.</a>
<br>
<a href='/url.com'>This is</a><a href='/url.com'> the </a><a href='/url.com'>same link.</a>
This is not linked and does not have bolding.
<a href='/url.com'>These are</a><a href='/url2.com'> two different links.</a>
</div>
<hr>
Output:
<pre></pre>
It may seem like this will be a simple operation but it won't. The reason being is that the text in the middle is not a node of it's own but instead just the innerHTML of the parent DIV. Basically what you will need to do is get your tags by tag name, and in order to check if they are adjacent to one another use the following code.
var linkTags=document.getElementsByTagName("A");
for(i=0; i<linkTags.length-1; i++){
j=i+1;
indexOfI=document.innerHTML.indexOf(linkTags[i].outerHTML);
lengthOfI=linkTags[i].outerHTML.length;
indexOfJ=document.innerHTML.indexOf(linkTags[j].outerHTML);
if(indexOfI+lengthOfI==indexOfJ){
//ELEMENTS ARE ADJACENT
}else{
testFlag=true;
//GET CONTENTS BETWEEN ELEMENTS AS STRING
var testString=document.innerHTML.substr(indexOfI+lengthOfI, indexOfJ);
//TEST CONTENTS FOR WHITESPACE
for(k=0; k<testString.length; k++;){
if(testString.char(k)!=" " && testString.char(k)!="\n"){
//SET FLAG INDICATING NON WHITESPACE CHARACTER FOUND
testFlag=false;
//SET K TO LOOPS MAX TO BREAK LOOP
k=testString.length;
}
}
if(testFlag){
//ELEMENTS ARE ADJACENTWITH WHITESPACE BETWEEN
}
}
}
Of course with this adjacency check you are automatically assured that they are of the same parent as well as there is no way to open or close the parent tags and still remain adjacent in the code.
You can try this... Add a class for which anchors need to be verified. $.each through all of the <a> tags. filtering the outstanding items that haven't been verified to see if the href and html() matches. If they match remove them. Then remove the verify class from the item so that on the next each loop the items that have been verified aren't included.
$('a').addClass('verify').each(function () {
var $this = $(this);
//you can change the html() to text() is you are only worried about match the innerText
$('a.verify').not(this).filter(function () {
return ($(this).html() == $this.html() && $(this).attr('href') == $this.attr('href'))
}).remove();
$this.removeClass('verify')
});

Highlight div if child element name matches location.hash

I'm in an AngularJS web project.
I would like to highlight a div when clicking on an anchor link. The structure is as follows:
<div interaction-list-item="" sfinx-interaction="interaction" class="ng-isolate-scope">
...
<a name="iid_7923"></a>
...
</div>
And the anchor link sets the location.hash to the similar upon clicking, so a URL could look like this: http://localhost:9000/#/home#iid_7923. This iid_ is dynamic, with different id's after the _
I've tried several jQuery solutions that ends up with really ugly and long code:
$(".indicator.active.line-D").click(function () {
// more similar code..
if ($("div:contains('D4')") && $("a:contains('D4')")) {
$(".col-md-6.interactionscol:contains('D4')").css("border", "3px solid #428bca");
setTimeout(function () {
$(".col-md-6.interactionscol:contains('D4')").css("border", "");
}, 1000);
}
// more similar code..
});
The purpose of this snippet is that upon clicking the anchor lnik, check for the div and anchor matching eachother and then apply CSS onto it, removing it after 1 second.
How could I do this smarter - if location.hash contains for example #iid_7923 and the div with a tag which name has the same, highlight it!
I just can't figure it out. Thanks in advance.
UPDATE: I would like to achieve similar to this: target selector
But my code for the anchor is not similar to the classical way.. it looks like this:
$scope.scrollToInteraction = function (iid) {
$location.hash(iid);
$anchorScroll();
};
Using angular, make your hash public in either a controller or for the whole application using the $rootScope:
angular.module('foo').run(['$location', '$rootScope', function($location, $rootScope) {
$rootScope.currentHash = function() {
return $location.hash();
};
}]);
And then in your html just use a directive to style your div:
<div data-ng-class="{'active': currentHash() == 'iid_7923'}">
Note the missing # in your currentHash().
You can use the onhashchange event to add a class to the parent element.
var lastParent = null;
window.addEventListener('hashchange', function() {
// Remove class from previous target parent
if(lastParent)
{
lastParent.className = (' '+lastParent.className+' ').replace(' hastarget ',' ');
lastParent = null;
}
// Remove the '#' from the location hash
var targetId = document.location.hash.substr(1);
var target = document.getElementById(targetId);
// Try to support the name attribute
if(!target)
{
var nameTargets = document.getElementsByName(targetId);
// If nothing found, don't do anything
if(nameTargets.length == 0) return;
target = nameTargets[0];
}
// If the element does not have any parent, add the class to the <html> tag
lastParent = target.parentElement || document.documentElement;
lastParent.className += ' hastarget';
}, false);
JSFiddle demo

I try to make it blink, but it won't work

I'm trying to create notifications system in my company's ERP, similar to Facebook one. For now, after few hours of work, it looks like this:
Each menu item is a lielement. Each element can have one of classes that will modify it's background color:
selected is blue, shown on a picture
restricted is red
Now, what I'm trying to achieve is to make li background blink on some events (when new message comes in and list is not opened (and also selectedclass is not present)).
The problem is: it won't blink. :(
here's snap of my html (excluding messagebox)
<li class="notifications-topmenu-button selected">
<a href="#">
<div class="notifications-topmenu-button-wrapper">
<div class="notifications-topmenu-button-icon">
<img class="transparent" width="13" height="13" align="absmiddle" src="/images/icons/notifications.png" title="Powiadomienia" alt="Powiadomienia">
</div>
<div class="notifications-topmenu-button-counter" style="display: block;">3</div>
</div>
</a>
<span class="divider"> : </span>
</li>
<li class="selected">
Strona główna
<span class="divider"> : </span>
</li>
Also, there's some JavaScript initiating object (don't mind comments):
function notificationsObject(){
var nl = new Object();
//atrybuty klasy
nl.liElement = $('.notifications-topmenu-button');
nl.menuButton = $('.notifications-topmenu-button-wrapper');
nl.menuButtonCounter = nl.menuButton.find('.notifications-topmenu-button-counter');
nl.notificationsCount = jQuery.trim(nl.menuButtonCounter.text());
nl.notificationsList = $('.notifications-list-wrapper');
nl.blinkingInterval = null;
nl.startBlinking = function(){
nl.blinkingInterval = setInterval(function(){
if(nl.liElement.hasClass('restricted') == false){
console.debug(nl.liElement.addClass('restricted'));
}
else {
nl.liElement.removeClass('restricted');
}
}, 1000);
}
nl.stopBlinking = function(){
if(nl.blinkingInterval != null) nl.blinkingInterval = null;
}
(more 'class' functions)
return nl;
}
Now to test it, I simply call
$(document).ready(function(){
var notifications = notificationsObject();
notifications.startBlinking();
});
Of course I call it after function declaration.
funny fact is that when I change nl.startBlinking function setInterval internals to only add restrictedclass, it works. I'm pretty sure it must be some typo or stupid error, but I can't find it.
Please, help!
Try to use the toggleClass function instead of checking classes yourself like:
setInterval(function(){
nl.liElement.toggleClass('restricted');
}, 1000);
jQuery reference: http://api.jquery.com/toggleClass/
I put all your code into a Fiddle here and it worked. Not sure what the problem is.
added css
.restricted{
visibility:hidden;
}
Also removed (more 'class' functions) line. But I assume you just added that to the post and it's not part of your code.
Ok, problem solved.
the thing was that this function
nl.startBlinking = function(){
nl.blinkingInterval = setInterval(function(){
if(nl.liElement.hasClass('restricted') == false){
console.debug(nl.liElement.addClass('restricted'));
}
else {
nl.liElement.removeClass('restricted');
}
}, 1000);
}
started executing on declaration.
so when I called
$(document).ready(function(){
var notifications = notificationsObject();
notifications.startBlinking();
});
I had not one, but two intervals working at the same time.
Add and remove the 2 classes in stead of only restricted
if(nl.liElement.hasClass('restricted') == false){
nl.liElement.addClass('restricted');
nl.liElement.removeClass('selected');
}
else {
nl.liElement.removeClass('restricted');
nl.liElement.addClass('selected');
}

Selecting a single class from a multi class element

I'm trying to select a specific class (in this case page1, page2, page3 etc.)
I've written this code that works fine for a single class, i've tried using .match() to exclude the .plink class picked up in dis but can't get it working.
$(function(){
$("a.plink").click(function() {
var dis = $(this).attr("class"); // This is the problem line, I need it to contain 'page1' ONLY. Not 'page1 plink'.
$("#page1,#page2,#page3").hide();
$("#" + dis).show();
return false;
});
});
The HTML that is associated with this is:
<div id="page-links">
<a class="page1 plink" href="#">About</a>
<a class="page2 plink" href="#">History</a>
<a class="page3 plink" href="#">Backstage</a>
</div>
EDIT:
These are the DIV's being shown and hidden:
<div id="page1">
<?php include_once("page1.php");?>
</div>
<div id="page2">
<?php include_once("page2.php");?>
</div>
<div id="page3">
<?php include_once("page3.php");?>
</div>
Is there a simple way to achieve this without regular expression matching?
$(function(){
var pages = $('div[id^=page]');
$("a.plink").click(function() {
var dis = $(this).attr("class").replace(' plink', '');
pages.hide().filter('#' + dis).show();
return false;
});
});
This should be
$("." + dis).show();
for class and in your example there are all classes.
As you mentioned simple way so it could be
$("a.plink").click(function() {
$(".plink").hide();
$(this).show();
return false;
});
According to your question after edit
$("a.plink").click(function() {
$('div[id^="page"]').not('#page-links').hide();
pid=$(this).attr('class').split(' ')[0];
$('#'+pid).show();
return false;
});
Here is a fiddle.
The JavaScript code is not correct. With the "#" you select ids from the html-element.
As you have only classes, the right way is to do it with "."
So this would be correct:
$(function(){
$("a.plink").click(function() {
var dis = $(this).attr("class");
$(".page1,.page2,.page3").hide();
$("." + dis).show();
return false;
});
});
I didn't test it, but I think you have to change something with the var dis.
If you click on .page1, the variable dis would contain "page1 plink".
$("." + dis).show();
would be
$(".page1 plink").show();
So I recommend to split the two classes, as it should be like
$(".page1 .plink").show();
You are trying to associate functionality of a click by appending classes. It would make more sense to put id of the div you want to show in the href
html:
<div id="page-links">
<a class="plink" href="#page1">About</a>
<a class="plink" href="#page2">History</a>
<a class=" plink" href="#page3">Backstage</a>
</div>
<div id="page1">
Content 1
</div>
<div id="page2">
Content 2
</div>
<div id="page3">
Content 3
</div>
​javascript:
jQuery(function ($) {
var pages = [];
function showPage(page) {
var i;
for(i = 0; i < pages.length; i++)
{
if(page === pages[i]) {
$(pages[i]).show();
} else {
$(pages[i]).hide();
}
}
}
// Store each href in a pages array and add handlers
$('.plink').each( function() {
var page = $(this).attr('href');
pages.push(page);
$(this).attr('href', '#');
$(this).click(function () {
showPage(page);
});
});
// show the first page
if(pages.length > 0) {
showPage(pages[0]);
}
});​
Example:
http://jsfiddle.net/38qLB/
And just so I don't avoid the actual question, which is how do you select a class from a multi class element, you should follow this example of splitting up the class name Get class list for element with jQuery if you truly insist on using classes to make your link/div association
You don't really want to exclude the plink class, because that will bring you confusion and trouble when you need to add another class. Instead you want to extract just the pageX class:
// Regex for extracting pageXX
var reg = /^(.*\s)?(page\d+)([^\d].*)?$/;
dis = reg.exec(dis)[2];
I haven't testet this 100%, but put these two lines in right after var dis = $(this).attr("class"); and you should hopefully be good to go.
i down't know if i get your question right
to get all classes with class plink u can use
var klasses $("a.plink");
now u can loop true the items
var yourClasses = Array();
for(var klass in klasses)
{
var word = klass.attr('class').replace(" plink", "");
yourClasses.push(word);
}
now you have all the classes wich have the class plink
hope this was where u where looking for
If I was just doing a minor tweak to fix your existing structure I would do something like this:
$(document).ready(function() {
$('a.plink').click(function() {
var id = $.trim(this.className.replace('plink', ''));
/*adding a "page" class to each of the page divs makes hiding the visible one a bit easier*/
$('div.page').hide();
/*otherwise use the version from sheikh*/
//$('div[id^="page"]').not('#page-links').hide();
$('div#' + id).show();
});
});
The main change I would recommend to your existing markup would be to add a common "page" class to each of the page divs. Here is a fiddle
If I was starting on this from scratch I would probably take a slightly different approach in which I define an "active" class and toggle which elements have it rather than using show/hide on the divs. And that would end up looking something like this:
Markup:
<div id="page-links">
<a class="plink active" href="#page1">About</a>
<a class="plink" href="#page2">History</a>
<a class="plink" href="#page3">Backstage</a>
</div>
<div id="page1" class='page active'> </div>
<div id="page2" class='page'> </div>
<div id="page3" class='page'> </div>
CSS:
div.page
{
height: 300px;
display:none;
}
div.page.active
{
display:block;
}
a.plink
{
padding-left:5px;
padding-right:5px;
}
a.plink.active
{
background-color:#ddd;
}
div#page1
{
background-color:blue;
}
div#page2
{
background-color:green;
}
div#page3
{
background-color:red;
}
Script:
$(document).ready(function() {
$('a.plink').click(function() {
var id = $(this).attr('href');
$('.active').removeClass('active');
$(this).addClass('active');
$('div' + id).addClass('active');
});
});
Or the fiddle here.
Oh and to answer the title question rather than just the end behavior described...
var classes = this.className.split(' ');
var id;
for (var i = 0; i < classes.length; i++) {
if(classes[i].substring(4) === classes[i].replace('page', '')) {
id = classes[i];
break;
}
}
should end up with id containing the "page#" value associated with the link that was clicked regardless of its position in the list of classes.

Categories