How to Angularize Mobile menu with ng-show & ng-click? - javascript

http://plnkr.co/edit/F8K66L?p=preview
I have a li menu which at 300px goes to display:none, while the mobile_nav button turns on.
Now currently in my Controller I'm using this
main.js
$scope.mobileMenu = function() {
var menu = document.getElementById('main_nav');
if (menu.style.display == 'block') {
menu.style.display = 'none';
} else {
menu.style.display = 'block';
}
};
If I open the mobile menu, then close it, it stays closed on a larger view when resized, even though I have display:block in the CSS. Also need the mobile menu to close if an item is clicked inside of it.
Tried this, but without any luck
index.html
<div
ng-click="isMobileNavOpen = !isMobileNavOpen"
class="mobile_nav">
=
</div>
<nav id="main_nav" ng-init="isMobileNavOpen = true" ng-show="isMobileNavOpen">
<ul>
<li><a ui-sref="home">Home</a></li>
<li><a ui-sref="about">About</a></li>
</ul>
</nav>
style.css
// the button
.mobile_nav {
display: none;
}
#media all and (max-width: 300px) {
.mobile_nav {
display: block;
}
#main_nav {
display: none;
}
#main_nav li {
float: none;
margin-bottom 20px;
}
#main_nav a {
width: 100%;
}
}

Found the perfect library!
https://github.com/AnalogJ/matchmedia-ng
^ Here is the code that fixed my issue (needed an Angular way to detect size)
var unregister = matchmedia.onPhone( function(mediaQueryList){
$scope.isPhone = mediaQueryList.matches;
});
Did have to use the overrides to adjust to my pixel specifications:
angular.module('myapp', ['matchmedia-ng']).config(['matchmediaProvider', function (matchmediaProvider) {
matchmediaProvider.rules.phone = "(max-width: 500px)";
matchmediaProvider.rules.desktop = "(max-width: 1500px)";
}]);
Also had to go ahead with 2 different navs :/ will still try to play around with this a bit to see if I can get it down to using just 1 nav:
<div class="mobile_nav noselect">
<div ng-click="isMobileNavOpen = !isMobileNavOpen" class="icon-menu"></div>
</div>
<nav id="main_nav">
<nav id="mobile_nav" ng-show="isMobileNavOpen">

Related

how to shorten the breadcrumb when it appears in mobile website

when i view my website in mobile with lot of filters, the breadcrumb length becomes too large. so i want to replace all the li tags that are behind the second last li. that means all the li except first, last and last-1 li need to be replaced with dots.
Anybody can help me fix this with jquery, javascript, or css?
<ul class="left">
<li class="active">Airways</li>
<li>Trauma</li>
<li>Medical</li>
<li>OB | Peds</li>
<li>Patient Assessment</li>
<li>Proprietary</li>
<li>Trauma</li>
<li>Medical</li>
<li>OB | Peds</li>
<li>Patient Assessment</li>
<li>Proprietary</li>
</ul>
This is just example code i have added here.
You can try with jquery like this. Basically if it is a smaller width device, and if it is not first, last or second last child, the text of the link tag is replaced by '..' .
<script>
$(document).ready(function () {
if (window.matchMedia("(max-width: 767px)").matches)
{
// The viewport is less than 768 pixels wide
console.log("This is a mobile device.");
$('ul.left li').each(function() {
$this = $(this); // cache $(this)
if (! $this.is(':first-child') && ! $this.is(':nth-last-child(2)') && ! $this.is(':last-child') ) {
$this.find('a').text("..");
}
});
}
});
</script>
This is my first answer on stack overflow, hope this is what you want this is the codepen link
https:// codepen.io/vatzkk/pen/yLYMJeG
HTML
<script src="https://kit.fontawesome.com/a076d05399.js"></script>
<ul class="left" id="bread">
<li class="active">Airways</li>
<li id="dropdown" style="display:none">
<div class="dropdown" >
<i class="dropbtn">...</i><i class="fas fa-caret-down"></i>
<div class="dropdown-content" id="dropdown-list">
</div>
</div>
</li>
<li>Trauma</li>
<li>Medical</li>
<li>OB | Peds</li>
<li>Patient Assessment</li>
<li>Proprietary</li>
<li>Trauma</li>
<li>Medical</li>
<li>OB | Peds</li>
<li>Patient Assessment</li>
<li>Proprietary</li>
</ul>
Javascript
//you can add your conditions over here
document.getElementById("dropdown").style.display="block";
var arr=[...document.getElementById("bread").children];
var dropdownItems=arr.slice(2,-2);
dropdownItems.map(item=>{
document.getElementById("bread").removeChild(item);
document.getElementById("dropdown-list").appendChild(item);
});
Pure CSS Working example: https://jsfiddle.net/3o8vuwd6/2/
First give your list a class
<ul class="left breadcrumblist">
CSS:
/* This is just to give it some styling as you haven't given any */
.breadcrumblist li {
list-style: none;
display: inline-block;
padding-right: 0.5em;
}
.breadcrumblist li + li::before{
content: "/";
padding-right: 0.5em;
}
/* adjust to your breakpoint. 9999 just so it works on large screen as an example */
#media only screen and (max-width: 9999px) {
/* hide all */
.breadcrumblist li{
display: none;
}
/* show first and last */
.breadcrumblist li:first-child,
.breadcrumblist li:last-child{
display: inline-block;
}
/* add ... to the end of the first one */
.breadcrumblist li:first-child::after{
content: "...";
padding-left: 0.5em;
}
/* fiddle with the content we added in styling */
.breadcrumblist li + li::before{
content: "";
padding-right: 0;
}
}
Thank you all for your guidance and finally i made something work according to my requirement and also i want to share it here because in case in future if someone looks for the same issue he or she can be benefited from this. This is also from the modifications that all you have just posted above.
<ul class="left" id="bread_cumb">
$(document).ready(function(){
if (window.matchMedia("(max-width: 767px)").matches)
var width = $(window).width();
if (width < 720) {
$('#bread_cumb li:not(:first-child):not(:nth-child(2)):not(:last-
child):not(:nth-last-child(2))').html('<span style="margin-
left:7px;margin-right:7px;"> ... </span>');
var last =$('#bread_cumb li:last-child').text();
var re = /^([A-Za-z0-9_'",.!##$%^&*()-+=?/\|:]+)[\s,;:]+([a-z]+)/i;
var m = re.exec(last);
$('#bread_cumb li:last-child').html('<a>'+m[1]+' '+m[2]+'...</a>');
}
});
Thanks all for your valuable ideas.

Is there a better way than this to create a toggle function just with JavaScript (no JQuery at all)?

I have a nav bar in the form of a ul with several li elements and with the last li (named 'more') having its own sub-menu in the form of another ul. I was trying (and was successful) in making it so that the sub-menu's original state is visibility:visible; and then when the user clicks on li name 'more' it would toggle between visibility: visible; and visibility: hidden;
I used JavaScript and a counter with an if statement. The reason why I used the counter was because when I tried:
if(document.querySelector('#subMenu').style.visibility == "hidden")...;
But it wouldn't toggle.
My questions are:
Would this method of creating the toggle function be deemed acceptable in a professional front end developer workplace?
Is there a better way to toggle between visible and hidden on clicking an element using JavaScript ONLY (trying to get better at JavaScript)?
The code is as follows(I have only included the relevant code):
HTML
<ol id = "leftNav" class = "bothNavs">
<li class = "navs" id = "more">More<div class = "arrow"></div>
<ul class = "subMenu">
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
</li>
</ol>
CSS
.subMenu {
width: 160%;
padding: 5px 0px;
padding-left: 7px;
margin-left: 6px;
position: absolute;
top: 100%;
left:0px;
visibility: hidden;
box-shadow: 0px 2px 3px rgba(0,0,0,0.2);
background: #2D2D2D;
list-style: outside none none;
z-index: 1001;
}
JavaScript
var more = document.querySelector('#more');
var subMenu = document.querySelector('.subMenu');
var counter =0;
more.addEventListener("click", toggle);
function toggle () {
if(counter === 0){
subMenu.style.visibility = "visible";
counter += 1;
} else {
subMenu.style.visibility = "hidden";
counter -= 1;
}
};
Thank you in advance for your answers.
I feel a better way of toggling visibility (or any style) is to toggle a class.
Consider something like this in your CSS:
.subMenu.is-visible {
visibility: visible;
}
Then your function just needs to look like this:
var menu = document.querySelector('.subMenu');
document.getElementById('more').addEventListener('click', function () {
menu.classList.toggle('is-visible');
}, false);
For a toggle you should use a boolean value rather than int:
var more = document.querySelector('#more');
var subMenu = document.querySelector('.subMenu');
var clicked = false;
more.addEventListener("click", function(evt) {
// This is called a ternary operator, it's basically
// a really simple if/else statement
subMenu.style.visibility = (clicked) ? "visible " : "hidden";
// This will set clicked to the opposite (not) value of what
// it currently is. Being that we're using a boolean
// it will toggle true/false
clicked = !clicked;
});
You should also read (and vote for) this - What is the difference between visibility:hidden and display:none?
You should not embed a <ul> inside a <li> element. There's all sorts of reasons why, but mostly it messes with the hierarchy and makes the HTML less meaningful.
Also the last time I had to tackle this problem it ended up looking something like this:
var subMenu = document.querySelector('.subMenu');
if (clicked) {
subMenu.style.visibility = "visible";
} else {
subMenu.style.visibility = "hidden";
}
Consider making it id instead of class incase you have other submenus it interferes with.
If you don't really need a counter, use a boolean:
var more = document.querySelector('#more');
var subMenu = document.querySelector('.subMenu');
more.addEventListener("click", toggle);
function toggle () {
subMenu.style.visibility = subMenu.style.visibility != "hidden" ? "hidden" : "visible";
};
.subMenu {
width: 60%;
background: #2D2D2D;
list-style: outside none none;
color: white
}
<ol id = "leftNav" class = "bothNavs">
<li class = "navs" id = "more">More<div class = "arrow"></div>
<ul class = "subMenu" style="visibility: hidden">
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
</li>
</ol>
Ideally, you'd modify this code to toggle a class instead of an inline CSS style, as James suggested in his answer.

Scroll to top button showing when not on top of the page

I would like to have a scroll to top arrow fixed in my page using angular bootstrap.
Currently I have
<div class="col-md-1">
<div class="affix">
<div>
<a th:href="#{/}" href="#" target="_self"><img id="image" src="source" alt="yoli" width="50px" /></a>
</div>
Scroll to top
</div>
</div>
<div class="col-md-6">
<div id="search-bar" ng-include="blabla"></div>
<li ng-repeat="something"></li>
</div>
However when the "Scroll to top" is click it only works first time since the url changes to ...#search-bar and when you click it again nothing happens. So how do I scroll to top without changing the url?
And also question how do I make the "Scroll to top" only show when the search-bar is not showing?
I was thinking about using $anchorScroll and using id'ed numbers on li and if it's higher then "element-3" then show the button, however not sure if that would work.
UPDATE:
I am thinking of following this example, that is using navigation bars that is #search and #results and make the #search href visible on #results active and #results one hidden.
You can do this without jQuery as well:
function filterPath(string) {
return string
.replace(/^\//, '')
.replace(/(index|default).[a-zA-Z]{3,4}$/, '')
.replace(/\/$/, '');
}
const locationPath = filterPath(location.pathname);
document.querySelectorAll('a[href*="#"]').forEach(link => {
let thisPath = filterPath(link.pathname) || locationPath;
if ((location.hostname == link.hostname || !link.hostname)
&& (locationPath == thisPath)
) {
let hashName = link.hash.replace(/#/, '');
if (hashName) {
let targetEl = document.getElementById(hashName);
if (targetEl) {
link.addEventListener('click', () => {
event.preventDefault();
targetEl.scrollIntoView({
top: 50,
left: 0,
behavior: "smooth"
});
});
}
}
}
});
Here is how you can do it. Create a button:
Scroll To Top
CSS:
.scrollToTop{
width:100px;
height:130px;
padding:10px;
text-align:center;
background: whiteSmoke;
font-weight: bold;
color: #444;
text-decoration: none;
position:fixed;
top:75px;
right:40px;
display:none;
background: url('arrow_up.png') no-repeat 0px 20px;
}
.scrollToTop:hover{
text-decoration:none;
}
JavaScript:
$(document).ready(function(){
//Check to see if the window is top if not then display button
$(window).scroll(function(){
if ($(this).scrollTop() > 100) {
$('.scrollToTop').fadeIn();
} else {
$('.scrollToTop').fadeOut();
}
});
//Click event to scroll to top
$('.scrollToTop').click(function(){
$('html, body').animate({scrollTop : 0},800);
return false;
});
});
You can find a demo here. The source presented is taken from here.

Adding a class to a link inside a <li> element on scrolling

Is it possible to add a class to a link inside a li element when a certain part of the page is active?
I have a one page website and would like to change the color of the link when that specific part of the page is reached via scroll.
Here's my HTML:
<header id="header">
<section class="container">
<nav>
<a class="logo" href="index.html">Logo</a>
<div id="menu">
<ul id="links">
<li>Services</li>
<li>About</li>
<li>Clients</li>
<li class="last">Contact</li>
</ul>
</div>
</nav>
</section>
</header>
And here's the CSS:
#menu li a {
color:#7a7a7a;
text-decoration: none;
font-size: 12px;
margin-right:20px;
}
#menu li.last a {
color:#7a7a7a;
text-decoration: none;
font-size: 12px;
margin-right:0px;
}
#menu li.current a {
color: #0086be;
}
What I would like to do is to add the class .current to the link inside the li element whenever that specific part of the page is reached.
I believe this is only possible with Javascript, can anyone point me the right path to achieve this?
Thanks in advance
I think you want something like scrollspy in bootstrap,
you can use it or you can find https://gist.github.com/pascaldevink/2380129 bypascaldevink
or here is the fiddle http://jsfiddle.net/ia_archiver/Kb7xq/
You will require jquery for this,
$.fn.scrollspy = function ( option ) {
return this.each(function () {
var $this = $(this)
, data = $this.data('scrollspy')
, options = typeof option == 'object' && option
if (!data) $this.data('scrollspy', (data = new ScrollSpy(this, options)))
if (typeof option == 'string') data[option]()
})
}
$.fn.scrollspy.Constructor = ScrollSpy
$.fn.scrollspy.defaults = {
offset: 10
}
$(function () {
$('[data-spy="scroll"]').each(function () {
var $spy = $(this)
$spy.scrollspy($spy.data())
})
})
}(window.jQuery);
Using hover function you can achieve this.i.e. on hover of specific part of the page you add the class to the link present inside the li. e.g.
$('#specificPartOfPageId').hover(function(){
$('#links').children().children('a').addClass('current');
});
This would add .current class to every link present inside that UL element.
Hope this helps.
If I have understood correctly, I guess this is what you require: jsFiddle. The CSS and the HTML code remains the same and this is the jQuery code which I've used:
$(window).scroll(function() {
var scroll = $(window).scrollTop();
if (scroll > 500) {
$("#links li:first-child").addClass("current");
}
if (scroll > 750) {
$("#links li:first-child").removeClass("current");
$("#links li:nth-child(2)").addClass("current");
}
var scrollBottom = $(window).scrollTop() + $(window).height();
if (scroll < 500) {
$("#links li:first-child").removeClass("current");
}
if (scroll < 750) {
$("#links li:nth-child(2)").removeClass("current");
}
});
Basically what happens is that when you scroll down to 500px, the li:first-child is automatically assigned the current class. You can modify the jQuery to suit your needs by adding more if queries as per your needs. You can target different <li>'s in your list using different child-selectors like li:first-child, li:nth-child(2) etc.

During hover on parent element, show child (dropdown nav)

I'm trying to make a stupid horizontal nav bar with a drop-down on some of the items. The way I decided to do it is just by putting the drop-down in a div tag. This is easily changeable, i just don't like to go heavy on the html side.
Basically I just want my drop down to work when you hover over the parent element. Additional css is going to be used to make it pretty and positioned better.
Here's my js:
var dropdown = $('.dropdown');
var parent = dropdown.parent();
$(parent).hover(
function () {
dropdown.css('display', 'block');
}
);
Here's my css:
div.nav {
text-align: center;
}
div.nav > ul > li {
margin-top: 15px;
text-align: center;
font-size: 1.25em;
}
div.nav > ul > li {
display: inline-block;
list-style-type: none;
}
div.nav a {
padding: 1em;
}
div.dropdown {
display: none;
background-color: black;
position: absolute;
}
Here's my html:
<div class="nav">
<ul>
<li>Home</li>
<li>
Sample Game
<div class="dropdown">
About it
<br>
Game
</div>
</li>
<li>TP Solutions</li>
<li>Projects</li>
<li>Contact Me</li>
</ul>
<div class="clear"></div>
You should not be using "parent" as a variable name, as it's a reserved word.
$(document).ready(function() {
var $dropdown = $('.dropdown'),
$parent = $dropdown.parent();
$parent.on("mouseover",
function () {
$dropdown.css('display', 'block');
}
);
$parent.on("mouseout",
function () {
$dropdown.css('display', 'none');
}
);
});
According to the oreder this has to be done:
add a jQuery plugin first
Then add your script
so the order will be like this:
<script src='https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js'>
</script>
<script>
$(function(){
var dropdown = $('.dropdown');
var parent = dropdown.parent();
$(parent).hover(function () {
dropdown.css('display', 'block');
});
});
</script>
Please try the below code.
$(".nav").on("mouseenter","li",function(){
$(this).find(".dropdown").show();
});
$(".nav").on("mouseleave","li",function(){
$(this).find(".dropdown").hide();
});
In your code " dropdown.parent(); " -> this will refer all the parents which have child dropdown and will show the menu. we need to refer current hover parent. Please check the working example in below link.
http://jsfiddle.net/renjith/wX48f/
There are so many good solutions to use jQuery and CSS to show a drop down menus. So you don't need to reinvent the wheel. Here are some examples that you might be able to find one to fit your need.

Categories

Resources