So my first stab at web development is proceeding reasonably well.
However... I want to have two separate drop down menus, but the JavaScript functions are interfering with each other... That is, if both functions are active at the same time, clicking on one drop down will cause the other drop down to react or stop working. It is probably something massively stupid, but I have little time left. here is the code:
//Control sliding menu on screens smaller than a specified breakpoint.
(function(menu_button, links, breakpoint)
{
"use strict";
var menulink = document.getElementById(menu_button),
menu = document.getElementById(links);
menu.className = "start";
setTimeout(function()
{
menu.className = "collapsed";
}, 20);
menuLink.onclick = function()
{
if (menu.className === "displayed")
{
menu.className = "collapsed";
}
else
{
menu.className = "displayed";
}
return false;
};
window.onresize = function()
{
if (window.innerWidth < breakpoint)
{
menu.className = "collapsed";
}
};
})("menuLink", "navLinks", 700);
That was function No.1, here is No.2:
function dropFunction()
{
"use strict";
document.getElementById("myDropdown").classList.toggle("drop");
}
window.onclick = function(e)
{
"use strict";
if (!e.target.matches('.dropbtn'))
{
var dropdowns = document.getElementsByClassName("dropdownContent");
for (var d = 0; d < dropdowns.length; d++)
{
var openDropdown = dropdowns[d];
if (openDropdown.classList.contains("drop"))
{
openDropdown.classList.remove("drop");
}
}
}
}
and HTML if at all usefull:
<nav>
<p id="menuLink">MENU</p>
<ul class="displayed" id="navLinks">
<li>Home</li>
<li>Portfolio</li>
<li>Shop</li>
<li>Contact</li>
</ul>
</nav>
<div class="dropdownContent" id="myDropdown">
<img class="externalLink" src="images/faceBook.png" style="width:20px">
<img class="externalLink" src="images/linkedIn.png" style="width:20px">
<img class="externalLink" src="images/soundCloud.png" style="width:20px">
</div>
and CSS:
.nav
{
display: inline;
position: absolute;
bottom: 220px;
padding-right: 60px;
width: 100%;
background-color: transparent;
font-family: "verdana";
font-size: 20px;
text-align: center;
}
.nav li
{
display: inline;
}
.nav a
{
display: inline-block;
padding: 50px;
text-decoration: none;
color: #E4E4E4;
}
.nav a:hover
{
color: #FFFFFF;
text-shadow: 0px 0px 15px #FFFFFF;
}
.nav a:active
{
color: #5B4CA8;
}
li.drops
{
display: inline-block;
}
.dropdownContent
{
display: none;
position: absolute;
background-color: transparent;
box-shadow: none;
minimum-width: 20px;
}
.dropdownContent a
{
color: transparent;
text-decoration: none;
display: block;
text-align: center;
}
.drop
{
display: block;
}
#menuLink
{
width: 100%;
background-color: transparent;
list-style-type: none;
padding: 0;
margin: 0;
text-align: center;
}
#menuLink a
{
text-decoration: none;
font-family: "helvetica";
color: #E4E4E4;
}
#menuLink a:hover
{
color: #FFFFFF;
text-shadow: 0px 0px 15px #FFFFFF;
}
#menuLink a:active
{
color: #5B4CA8;
}
#navLinks
{
position: absolute;
list-style-type: none;
width: 100%;
background-color: transparent;
padding: 0;
margin: 0;
text-align: center;
z-index: 1;
opacity: 1;
-webkit-transition: all ease-out 0.5s;
transition: all ease-out 0.5s;
}
#navLinks a
{
display: block;
padding: 10px;
font-family: "helvetica";
color: #E4E4E4;
text-decoration: none;
font-size: 18px;
}
#navLinks a:hover
{
color: #FFFFFF;
text-shadow: 0px 0px 15px #FFFFFF;
}
#navLinks a:active
{
color: #5B4CA8;
}
#navLinks.start
{
display: none;
}
#navLinks.collapsed
{
top: -12em;
opacity: 0;
}
Thanks for your help!
You have used the window.Onlcick event to specify behaviors for the dropdowns if the user is not clicking on something with class "drop". This event will fire if you click on any item in that window because events bubble up like that in JavaScript.
Related
I made a nav bar using nav and li tags, including a notifications icon, I am trying to make notifications nested list to show notifications, and use JavaScript to toggle/hide the menu, so far no luck. I've been looking for snippets online to support my logic, but I am stuck in the styling part and the JavaScript functionality. code below:
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function myFunction() {
document.getElementById("myDropdown").classList.toggle("show");
}
// Close the dropdown if the user clicks outside of it
window.onclick = function(e) {
if (!e.target.matches('.dropbtn')) {
var myDropdown = document.getElementById("myDropdown");
if (myDropdown.classList.contains('show')) {
myDropdown.classList.remove('show');
}
}
}
html {
scroll-behavior: smooth;
}
* {
font-family: 'Roboto', sans-serif;
font-style: normal;
padding: 0;
margin: 0;
text-decoration: none;
}
.container {
display: flex;
flex-direction: column;
min-height: 100vh;
}
main {
flex: 1;
}
::-webkit-scrollbar {
width: 1.32vmin;
}
/*
::-webkit-scrollbar-track{
border: 0.53vmin solid rgba(7, 67, 146, 0.17);
box-shadow: inset 0 0 0.33vmin 0.26vmin rgba(7, 67, 146, 0.17);
}
*/
::-webkit-scrollbar-thumb {
background: #074392;
border-radius: 0vmin;
}
::-webkit-scrollbar-button {
height: 7.45vmin;
background: #074392;
}
body {
font-weight: 400;
font-size: 2.12vmin;
background-color: #FFFFFF;
/*overflow: hidden;*/
height: 100%;
}
h1 {
margin-left: 3vmin;
}
h5 {
margin: 2vmin 3vmin;
position: absolute;
width: 14.72vmin;
font-weight: 500;
font-size: 2.65vmin;
letter-spacing: 0.79vmin;
color: #FFFFFF;
display: inline;
}
nav {
background-color: #074392;
height: 7.42vmin;
width: 100%;
/*position: relative;*/
/*overflow: hidden;*/
position: sticky;
top: 0;
}
img.logo {
margin: 1.855vmin 3vmin;
height: 3.5vmin;
width: 7vmin;
}
nav ul {
float: right;
margin: 1.855vmin 2vmin;
}
nav ul li {
display: inline-block;
}
nav ul li::before {
content: " ";
padding: 0vmin 0.5vmin;
}
nav ul li a {
color: white;
/*margin: 0vmin 1vmin;*/
/*border-top-left-radius: 1.326vmin;
border-top-right-radius: 1.326vmin;
border-bottom-left-radius: 1.326vmin;
border-bottom-right-radius: 1.326vmin;*/
}
a.active,
a:hover {
font-variation-settings: 'FILL' 1;
}
.checkbtn {
color: #ffffff;
float: left;
cursor: pointer;
display: none;
margin: 1.855vmin 3vmin;
}
#check {
display: none;
}
#check:checked~ul {
left: 0;
}
.dropdown {}
.dropdown .dropbtn {
cursor: pointer;
border: none;
outline: none;
background-color: #074392;
color: #FFFFFF;
}
.dropdown:hover .dropbtn,
.dropbtn:focus {
color: #FFFFFF;
font-variation-settings: 'FILL' 1;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #0743922B;
width: 37.5vmin;
overflow-wrap: break-word;
transform: translateX(-56%);
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
z-index: 1;
}
.dropdown-content a {
float: none;
color: black;
padding: 12px 16px;
text-decoration: none;
display: block;
text-align: justify;
}
.dropdown-content a:hover {
background-color: #0743922B;
}
.show {
display: block;
}
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD#20..48,100..700,0..1,-50..200" />
<div class="container">
<nav>
<input type="checkbox" id="check">
<label for="check" class="checkbtn">
<i class="material-symbols-rounded" style="font-size:3.5vmin;" title="Menu">menu</i>
</label>
<h5>LOGO</h5>
<ul>
<li>
<i class="material-symbols-rounded" style="font-size:3.5vmin;" title="Home">home</i>
</li>
<!-- <li> <i class="material-symbols-rounded" style="font-size:3.5vmin;" title="Notifications">notifications</i> -->
<li class="dropdown"><button class="dropbtn" onclick="myFunction()"><i class="material-symbols-rounded" style="font-size:3.5vmin;" title="Notifications">notifications</i></button>
<div class="dropdown-content" id="myDropdown">
<div>Link 1</div>
<div>Link 2</div>
<div>Link asasdasdasdasdasdsadsadasdasdasdasd asddasdas asd asd asd dasd asd</div>
</div>
</li>
<li>
<i class="material-symbols-rounded" style="font-size:3.5vmin;" title="Tasks">task</i>
</li>
<li>
<i class="material-symbols-rounded" style="font-size:3.5vmin;" title="Profile">person</i>
</li>
</ul>
<script type="text/javascript" src="JS/ActiveTab.js"></script>
<script type="text/javascript" src="JS/ToggleNotifications.js"></script>
</nav>
<main>
<h1>Example Page</h1>
</main>
</div>
By default set a display: none on the dropdown element and set a display: block on the hover pseudo-class of the dropdown element so when a hover event is triggered the dropdown appears.
Also, you can use classList.toggle method to remove if exists or to add if not exist the class.
Remove
Just add the following to the .css:
#myDropdown {
display: none;
}
#myDropdown.show {
display: block;
}
Remove onclick="myFunction()". And replace the .js with:
const myDropdown = document.getElementById('myDropdown')
addEventListener('click', event => {
let dropbtn = event.target.closest('button.dropbtn')
if (!dropbtn) return myDropdown.classList.remove('show')
console.log('hii')
myDropdown.classList.toggle('show')
})
I have a basic slider that moves below tabs when you click them, but i would like for it to change color depending on WHICH TAB it currently is. Here is a snippet :
var element = document.querySelectorAll("#home, #web, #design");
for (var i = 0; i < element.length; i++) {
element[i].addEventListener("click",function(x){
if(document.querySelector(".active")){
document.querySelector(".active").classList.remove("active");
}
x.currentTarget.classList.add("active");
});
}
#menu {
width: 50%;
margin: 0;
margin-left: 15em;
text-decoration: none;
list-style: none;
text-align: center;
}
#menu ul, #menu li {
display: inline;
}
#menu a {
display: inline-block;
width: 25%;
padding: .75rem 0;
text-decoration: none;
color: lightgray;
transition: color .15s;
}
#menu a:active {
color: white;
}
#menu a:hover {
color: white;
}
#home.active ~ hr {
margin-left: 14.5%
}
#web.active ~ hr {
margin-left: 40%
}
#design.active ~ hr {
margin-left: 65.5%
}
#slider {
height: .25rem;
width: 20%;
margin: 0;
background: tomato;
border: none;
transition: 0.3s ease-in-out;
}
<nav>
<ul id="menu">
<li id="home" class="active">Accueil</li>
<li id="web">Web</li>
<li id="design">Design</li>
<hr id="slider"/>
</ul>
</nav>
I hope this isn't too stupid or bad, i was trying to figure it out but no luck on my end so hopefully this isn't too much of an issue. Thank you for your time.
With your current code I'd do something like this
var element = document.querySelectorAll("#home, #web, #design");
for (var i = 0; i < element.length; i++) {
element[i].addEventListener("click",function(x){
if(document.querySelector(".active")){
document.querySelector(".active").classList.remove("active");
}
x.currentTarget.classList.add("active");
var id= x.target.parentElement.id
if (id == "web"){
document.getElementById('slider').style.background = "blue";
}
});
}
So you can extract the ID of clicked list element e.g. web and then change the CSS with a series of if statements. However I'd recommend making CSS classes and assigning them based on the ID of the clicked element.
For elements that have no relevance in the (DOM), like an aesthetic border, pseudo elements are usually used, you could manipulate them in a better way, I hope I can help you!
https://developer.mozilla.org/es/docs/Web/CSS/Pseudoelementos
#menu {
width: 100%;
margin: 0;
//margin-left: 15em;
text-decoration: none;
list-style: none;
text-align: center;
}
#menu li::before {
content: "";
position: absolute;
bottom: -10px;
width: 70%;
height: 2px;
opacity: 0;
}
#home.active::before {
opacity: 1;
background-color: red;
}
#web.active::before {
opacity: 1;
background-color: blue;
}
#design.active::before {
opacity: 1;
background-color: green;
}
#menu ul, #menu li {
display: inline;
position: relative;
}
#menu a {
display: inline-block;
width: 25%;
padding: .75rem 0;
text-decoration: none;
color: lightgray;
transition: color .15s;
}
#menu a:active {
color: white;
}
#menu a:hover {
color: white;
}
I'm making a menu using this tutorial: https://www.w3schools.com/howto/howto_js_dropdown_sidenav.asp
I added this code to highlight currently selected link:
$("#sidenav a").each(function() {
if (this.href == window.location.href) {
$(this).addClass("active");
}
});
How do I keep the dropdown open if a link in the dropdown is highlighted?
Just to add - my sidenav includes more than one dropdown.
Edit
My HTML:
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function() {
// this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
});
}
$("#sidenav a").each(function() {
if (this.href == window.location.href) {
$(this).addClass("active");
}
});
.sidenav {
height: 100%;
width: 16%;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #212529;
overflow-x: hidden;
}
.sidenav a,
.dropdown-btn {
padding: 11px 8px 11px 16px;
text-decoration: none;
color: #ffffff;
display: block;
border: none;
background: none;
width: 100%;
text-align: left;
cursor: pointer;
outline: none;
}
.sidenav a:hover,
.dropdown-btn:hover {
background-color: #808080;
color: #f1f1f1;
}
a.active {
background-color: #002f7c;
}
.main {
margin-left: 200px;
font-size: 20px;
padding: 0px 10px;
}
.current-menu-item {
background: #33b5e5;
}
.dropdown-container {
display: none;
background-color: #262626;
padding-left: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sidenav" id="sidenav">
Users
<button class="dropdown-btn">Computers</button>
<div class="dropdown-container">
Assigned
Unassigned
</div>
<button class="dropdown-btn">Monitors</button>
<div class="dropdown-container">
Assigned
Unassigned
</div>
Licenses
Reports
Logs
</div>
with jquery function closest you can select the closest parent element with the specific selector $(this).closest(".dropdown-btn") selects the closest parent with class "dropdown-btn".
so after selecting that, you can simulate click action on it or make it visible directly .
var dropdown = document.getElementsByClassName("dropdown-btn");
var i;
for (i = 0; i < dropdown.length; i++) {
dropdown[i].addEventListener("click", function() {
// this.classList.toggle("active");
var dropdownContent = this.nextElementSibling;
if (dropdownContent.style.display === "block") {
dropdownContent.style.display = "none";
} else {
dropdownContent.style.display = "block";
}
});
}
$("#sidenav a").each(function() {
if (this.href == window.location.href) {
$(this).addClass("active");
$("dropdown-btn").css({display : "none"});
$(this).closest(".dropdown-btn").css({display : "block"});
}
});
.sidenav {
height: 100%;
width: 16%;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #212529;
overflow-x: hidden;
}
.sidenav a,
.dropdown-btn {
padding: 11px 8px 11px 16px;
text-decoration: none;
color: #ffffff;
display: block;
border: none;
background: none;
width: 100%;
text-align: left;
cursor: pointer;
outline: none;
}
.sidenav a:hover,
.dropdown-btn:hover {
background-color: #808080;
color: #f1f1f1;
}
a.active {
background-color: #002f7c;
}
.main {
margin-left: 200px;
font-size: 20px;
padding: 0px 10px;
}
.current-menu-item {
background: #33b5e5;
}
.dropdown-container {
display: none;
background-color: #262626;
padding-left: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sidenav" id="sidenav">
Users
<button class="dropdown-btn">Computers</button>
<div class="dropdown-container">
Assigned
Unassigned
</div>
<button class="dropdown-btn">Monitors</button>
<div class="dropdown-container">
Assigned
Unassigned
</div>
Licenses
Reports
Logs
</div>
If you use jQuery, it is possible to select previous element of the link container and then fire click event on it to call the function that toggles the dropdown menu. So, you could use the following snippet, just replace $(this).attr("href") === "#1" with this.href == window.location.href.
$(".dropdown-btn").click(function() {
$(this).toggleClass("active").next().toggle();
});
$(".sidenav a").each(function() {
if ($(this).attr("href") === "#1") {
$(this)
.addClass("active")
.closest(".dropdown-container")
.prev(".dropdown-btn")
.trigger("click");
}
});
/* Fixed sidenav, full height */
.sidenav {
height: 100%;
width: 200px;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
padding-top: 20px;
}
/* Style the sidenav links and the dropdown button */
.sidenav a, .dropdown-btn {
padding: 6px 8px 6px 16px;
text-decoration: none;
font-size: 20px;
color: #818181;
display: block;
border: none;
background: none;
width:100%;
text-align: left;
cursor: pointer;
outline: none;
}
/* On mouse-over */
.sidenav a:hover, .dropdown-btn:hover {
color: #f1f1f1;
}
/* Main content */
.main {
margin-left: 200px; /* Same as the width of the sidenav */
font-size: 20px; /* Increased text to enable scrolling */
padding: 0px 10px;
}
/* Add an active class to the active dropdown button */
.active {
background-color: green;
color: white;
}
/* Dropdown container (hidden by default). Optional: add a lighter background color and some left padding to change the design of the dropdown content */
.dropdown-container {
display: none;
background-color: #262626;
padding-left: 8px;
}
/* Optional: Style the caret down icon */
.fa-caret-down {
float: right;
padding-right: 8px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ" crossorigin="anonymous">
<div class="sidenav">
About
Services
Clients
Contact
<button class="dropdown-btn">Dropdown
<i class="fa fa-caret-down"></i>
</button>
<div class="dropdown-container">
Link 1
Link 2
Link 3
</div>
Search
</div>
I'm making jQuery to click the Next and Previous span tab to control the image slideshow but it's not working.
function slideshow() {
var $active = $('div#slider-wrap img.active-img');
var $next = $active.next();
$next.addClass('active-img');
$active.removeClass('active-img');
}
$(function() {
setInterval(slideshow, 5000);
});
$('#tab-container a').on('click', function() {
var element = this.id;
console.log(element);
$('.images').trigger("slideshow", element);
});
/* next and previous jquery code */
$(document).ready(function() {
var divs = $('.images>img');
var now = 0; // currently shown div
divs.hide().first().show(); // hide all divs except first
$("#previous").click(function() {
divs.eq(now).hide();
now = (now + 1 < divs.length) ? now + 1 : 0;
divs.eq(now).show(); // show next
});
$("#next").click(function() {
divs.eq(now).hide();
now = (now > 0) ? now - 1 : divs.length - 1;
divs.eq(now).show(); // show previous
});
});
* {
margin: 0;
padding: 0;
}
#slider-wrap {
position: relative;
}
.slideshow .images {
width: 100%;
height: 350px;
overflow: hidden;
margin: 0 auto;
}
.slideshow .images img {
position: absolute;
width: 100%;
max-width: 960px;
height: auto;
}
.active-img {
z-index: 99;
}
#tab-container {
border-bottom: #ccc 1px solid;
border-top: #ccc 1px solid;
overflow: hidden;
width: 50%;
margin-top: 265px;
}
#tab-container span {
display: block;
float: left;
width: 42.995%;
padding: 10px 0;
text-align: center;
font-size: 12px;
text-transform: uppercase;
border-right: #ccc 1px solid;
letter-spacing: 1px;
font-family: 'corporate_condensed', sans-serif;
}
#tab-container a:nth-of-type(2) span {
border-right: 0;
}
#tab-container a,
#tab-container a:hover,
#tab-container a:active,
#tab-container a:visited {
text-decoration: none;
font-weight: bold;
color: #000;
cursor: pointer;
}
#tab-container span:hover {
color: #fff;
background: #444;
}
#tab-container span.active {
color: #fff;
background: #444;
}
#tab-container a span.active,
.c-slider #tab-container a:hover span.active,
.c-slider #tab-container a:active span.active,
.c-slider #tab-container a:visited span.active {
color: #fff;
}
#slider_time {
display: none;
}
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<div id="slider-wrap">
<div class="slideshow">
<div class="images">
<img src="http://tympanus.net/Tutorials/FullscreenSlitSlider/images/1.jpg" alt="" class="active-img">
<img src="http://tympanus.net/Tutorials/FullscreenSlitSlider/images/2.jpg" alt="">
<img src="http://tympanus.net/Tutorials/FullscreenSlitSlider/images/3.jpg" alt="">
<img src="http://tympanus.net/Tutorials/FullscreenSlitSlider/images/4.jpg" alt="">
</div>
</div>
</div>
<div id="tab-container">
<a><span id="previous" class="">Previous</span></a>
<a><span id="next"class="">Next</span></a>
</div>
<div style="clear:both"></div>
Previous and next tabs are not aligning properly with equal width. I'm having this problem all the time.
When you open chat and click on a name, it calls $scope.openChat(user) which pushes a name to the $scope.chat.openChats array. The ng-repeat is suppoused to watch this array for new values but does NOT update. I tried using $scope.$apply() after I push the value to array but get this error
Error: [$rootScope:inprog] http://errors.angularjs.org/1.3.14/$rootScope/inprog?p0=%24apply
Thanks for any help! Heres my codepen.
HTML
<div ng-app="MyApp" ng-controller="AppCtrl">
<div id="menubar">
<div class="logo"><img src="http://i.imgur.com/yS9Ug9Z.png"/></div>
<ul class="middle">
<div class="r1">Project Name <i class="glyphicon glyphicon-pencil"></i></div>
<ul class="r2">
<li class="dropdown">
<button href="#" data-toggle="dropdown" class="dropdown-btn">File</button>
<ul class="dropdown-menu">
<li>Action 1</li>
<li>Action 2</li>
<li>Action 3</li>
</ul>
</li>
<li class="dropdown">
<button href="#" data-toggle="dropdown" class="dropdown-btn">Edit</button>
<ul class="dropdown-menu">
<li>Action 1</li>
<li>Action 2</li>
<li>Action 3</li>
</ul>
</li>
<li class="dropdown">
<button href="#" data-toggle="dropdown" class="dropdown-btn">Help</button>
<ul class="dropdown-menu">
<li>Action 1</li>
<li>Action 2</li>
<li>Action 3</li>
</ul>
</li>
</ul>
</ul>
<div class="menu-btns">
<button id="comment-btn"><i class="material-icons">assignment</i> <span>Comment</span></button>
<button id="share-btn"><i class="material-icons">supervisor_account</i> <span>Share</span></button>
<button id="chat-btn" ng-click="openChatDialog()"><i class="material-icons">chat</i> <span>Chat</span></button>
</div>
<button id="user-btn"></button>
<div id="user-drop" class="shadow-1">
<ul>
<li>Smile</li>
<li>You</li>
<li>Goodlookin</li>
<li>Get Shwify</li>
<li>Cellar Door Is Beautiful</li>
<hr/>
<li>Your Profile</li>
<ul class="links">
<li>Link1</li>
<li>Link2</li>
<li>Link3</li>
</ul>
</ul>
</div>
</div>
<div id="chat-cntnr">
<div ng-repeat="chat in chat.openChats track by $index" class="chat-box"></div>
</div>
</div>
JS
angular.module('MyApp', ['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.controller('AppCtrl', function($scope, $mdDialog) {
//CHAT
$scope.chat = {};
$scope.chat.openChats = [];
$scope.collaborators = ['Dan', 'Miles', 'Ryan', 'kevin'];
var chatCntnr = document.getElementById('chat-cntnr');
// open a chat box
var isChatOpen = function(user) {
if ($scope.chat.openChats.indexOf(user) < 0) return false;
else return true;
};
$scope.openChat = function(user) {
if (!isChatOpen(user)) {
if (chatCntnr.style.display !== 'flex') {
chatCntnr.style.display = 'flex';
}
$scope.chat.openChats.push(user);
$scope.$apply();
}
};
// CHAT DIALOG
$scope.openChatDialog = function() {
$mdDialog.show({
controller: 'AppCtrl',
template: '<md-button ng-click="openChat(\'everybody\')">Everybody</md-button><md-button ng-repeat="user in collaborators" ng-click="openChat(user)"><svg class="status-light" height="17" width="17"><circle cx="8" cy="8" r="8" fill="lightGreen" /></svg>{{user}}</md-button>',
hasBackdrop: false,
clickOutsideToClose: true,
openFrom: '#chat-btn',
closeTo: '#chat-btn'
})
};
});
// chat dialog
// chat
/**
* MENUBAR
*/
var dropdownBtns = document.querySelectorAll('.middle .dropdown-btn');
var dropdowns = document.querySelectorAll('.middle .dropdown');
var userBtn = document.getElementById('user-btn');
var userDrop = document.getElementById('user-drop');
document.addEventListener('click', (e) => {
if (userDrop.classList.contains('open')) {
userDrop.classList.toggle('open');
}
});
userBtn.addEventListener('click', (e) => {
userDrop.classList.toggle('open');
e.stopPropagation();
})
for (var i = 0; i < dropdownBtns.length; i++) {
(function() {
var dropdownBtn = dropdownBtns[i];
var k = i;
dropdownBtn.addEventListener('mouseover', () => {
var x = isDropOpen();
if (x > -1 && x !== k) {
dropdowns[x].classList.toggle('open');
dropdowns[k].classList.toggle('open');
}
})
})();
}
var isDropOpen = () => {
for (var i = 0; i < dropdowns.length; i++) {
var dropdownClasses = dropdowns[i].classList;
if (dropdownClasses.contains('open')) return i;
}
return -1;
}
/**
* menubar
*/
CSS
html, body {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
html ul, body ul {
padding: 0;
margin: 0;
}
#menubar {
font-family: sans-serif;
background-color: black;
display: flex;
position: relative;
white-space: nowrap;
}
#menubar .logo {
display: flex;
align-items: center;
padding: 10px;
background-color: lightGrey;
}
#menubar .logo img {
height: 40px;
}
#menubar .middle {
padding: 10px;
padding-top: 8px;
padding-bottom: 0px;
color: white;
width: 100%;
position: relative;
font-family: inherit;
margin-left: 8px;
margin-right: 20px;
}
#menubar .middle .r1 {
font-size: 20px;
}
#menubar .middle .r1 i {
position: relative;
top: -1px;
font-size: 12px;
font-weight: 700;
margin-left: 2px;
cursor: pointer;
}
#menubar .middle .r1 i:hover {
color: lightGrey;
}
#menubar .middle .r2 {
margin-top: 2px;
margin-left: -6px;
font-size: 15px;
padding-bottom: 6px;
}
#menubar .middle .r2 li {
display: inline-block;
}
#menubar .middle .dropdown-btn {
position: relative;
outline: 0;
background-color: transparent;
border: none;
cursor: pointer;
padding: 2px 6px;
z-index: 100;
margin: 0 1px;
margin-top: 1px;
}
#menubar .middle .dropdown-btn:hover {
background-color: grey;
}
#menubar .middle .open .dropdown-btn {
background-color: black;
margin: 0 !important;
border: white 1px solid;
border-bottom: none;
}
#menubar .middle .dropdown-menu {
background-color: black;
border: white 1px solid;
border-radius: 0;
margin-top: -1px;
z-index: 10;
}
#menubar .middle .dropdown-menu li {
display: block;
}
#menubar .middle .dropdown-menu a {
color: white;
}
#menubar .middle .dropdown-menu a:hover {
background-color: dodgerBlue;
}
#menubar .menu-btns {
display: flex;
margin: 12px;
margin-right: 0px;
color: white;
right: 0;
}
#menubar .menu-btns button {
outline: 0;
position: relative;
background-color: transparent;
border-radius: 2px;
border: #343436 3px solid;
margin: 0 5px;
padding: 2px 12px;
font-size: 15px;
white-space: nowrap;
}
#menubar .menu-btns button:hover {
background-color: #4d4d50;
}
#menubar .menu-btns button i {
position: relative;
top: 5px;
color: #aeaeae;
}
#menubar .menu-btns button span {
position: relative;
top: -3px;
}
#user-btn {
margin: 10px;
margin-bottom: 8px;
outline: 0;
width: 70px;
background: url("https://www.fillmurray.com/70/92");
border: none;
border-radius: 2px;
}
#chat-btn {
background-color: #343436 !important;
}
#chat-btn:hover {
background-color: #4d4d50 !important;
}
.shadow-1 {
box-shadow: 0 2px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24);
transition: all 0.2s ease-in-out;
}
#user-drop {
display: none;
position: absolute;
right: 0;
top: 100%;
background-color: white;
}
#user-drop ul {
list-style-type: none;
padding: 6px 0;
padding-bottom: 2px;
font-size: 15px;
font-weight: 500;
}
#user-drop ul li {
cursor: pointer;
padding: 4px 16px;
padding-right: 38px;
}
#user-drop ul li:hover {
background-color: #e7e7e7;
}
#user-drop ul hr {
margin: 8px 0;
border-top: black 1px solid;
}
#user-drop ul .links {
padding-top: 0;
}
#user-drop ul .links li {
display: inline-block;
padding-right: 2px;
font-size: 11px;
color: darkGrey;
}
#user-drop ul .links li:hover {
background-color: white;
color: black;
}
#user-drop.open {
display: initial;
}
md-dialog {
position: absolute;
right: 25px;
top: 80px;
}
md-dialog svg {
position: absolute;
left: 16px;
top: 11px;
}
#chat-cntnr {
display: none;
position: fixed;
bottom: 0;
right: 0;
}
#chat-cntnr .chat-box {
height: 250px;
width: 200px;
background-color: blue;
border: 1px solid black;
margin: 0 4px;
}
#chat-cntnr .chat-box:last-child {
margin-right: 0;
}
The problem is that $mdDialog is creating another (isolated) scope. To use your existing scope you have to call it like this:
$mdDialog.show({
scope: $scope,
controller: 'AppCtrl',
...
For further information check this post.
Also, you have to remove $scope.$apply(): you have to call it only when changes happen outside Angular (in a setTimeout() for example).
Why do I need to link the scope?
Short answer: because $mdDialog documentation says so
The dialog is always given an isolate scope.
Long answer: $mdDialog is a service that basically adds a directive to the page
The dialog's template must have an outer < md-dialog > element
Since directives can be added multiple times in a page, by default they have an isolated scope (see Angular documentation on directive), but you can link your scope to a directive if you need it.