I have an Angular application that has multiple accordion groups. They are closed by default. One section is quite large so when it opens, the users need to scroll down if they want to see the end of the section. This section has some calculations on it. The problem is that I have a calculate button on the top of the section so when the user wants to recalculate it they have to scroll to the top again to see the button.
Is there any possibility to get the location when the user reached a certain location so it would trigger a ng-if with an overlay button.
Thanks,
Brent
You can use the JQuery .scroll(), it might look like this:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $document) {
$scope.pos = {
scrollPos:0
};
$("#outer").scroll(function() {
$scope.pos.scrollPos = $("#outer").scrollTop().valueOf();
$scope.$apply();
});
});
#outer {
overflow: auto;
height: 250px;
width: 200px;
border: solid 1px #ccc;
}
.inner {
height: 1000px;
position: relative;
width: 198px;
}
.top {
position: absolute;
top: 0px;
}
.bottom {
position: absolute;
bottom: 0px;
}
.scrolled {
position: fixed;
top: 30px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
{{pos.scrollPos}}<br>
<div id="outer">
<div class="inner">
<div class="scrolled ng-hide" ng-show="pos.scrollPos > 50">Passed Point.</div>
<div class="top">Top</div>
<div class="bottom">Bottom</div>
</div>
</div>
</div>
Yes this can be achieved with javascript try reading through this article on Mozilla it will help you achieve your goal, basically it lets you know the position of the mouse on the client. Apart from this if there is a specific element on the page that you need to know if the cursor is inside you can use Jquery and mouseenter event and then trigger some action.
Related
I have a html element which is displayed when a button is clicked. It‘s kinda like a popup. I want to check if it’s in the ViewPort of the browser and then place it inside the ViewPort . Is there a right way to achieve that?
At the moment I’m checking the height of the ViewPort and compare it to the point where the element will be attached to. So I do something like this:
If(window.innerHeight > yPointWhereElementIsAttachedTo + heightOfElement) //attach element;
But what is the right way to do it?
This can be achieved by using position: fixed; on an element with positioning.
For example:
.fixed {
position: fixed;
width: 300px;
height: 100px;
background: red;
left: 10px;
top: 40px;
}
.wrapper {
min-height: 4000px;
}
<div class="wrapper">
<div class="fixed">
I am fixed in the viewport
</div>
</div>
You could use scrollIntoView() if a more dynamic approach is required.
var elmnt = document.getElementById("content");
elmnt.scrollIntoView();
https://www.w3schools.com/jsref/met_element_scrollintoview.asp
I haven't found much out there specifically relating to Angular, but is there a way to grey out/disable the screen on a button click? Right now I have a button which is tied to saving some data, but I need to show a loading icon and not allow the user to edit any other fields while the save is in progress.
I currently have it set to where I can show the loading icon fine on the screen, I'm just wondering what I need to do so that the user isn't able to edit the DOM.
Right now I just have a spinner that is tied to an *ngIf, which displays towards the top of my page.
HTML:
<div id="nav">
<button type="submit"
class="btn btn-primary"
style="height: 46px;
width: 188px;
margin: 0 auto;
display:block;"
(click)="saveHandler()">
Save & Calculate
</button>
</div>
<span id="nav" *ngIf="saveInProgress">
<div class="submit-spinner" style="margin-top: 20px; display:block">
</div>
</span>
What I ended up doing was simply adding a new CSS ID tag to the root CSS file (styles.css). This way I'm able to reference the ID tag from anywhere in my application in order to apply this to anything within my project.
I drive the toggling of the CSS element with a variable, this way I'm able to execute logic in order to toggle the grey/disable. The grey/disablement starts out on a button click, and ends when the save has completed from the database. The user is unable to edit any field on screen and is forced to wait for the completion of the save before modifying any more fields.
Here's the documentation that helped me achieve this: https://www.w3schools.com/howto/tryit.asp?filename=tryhow_css_overlay
Here's what I added to styles.css at the root project level:
#overlay {
position: fixed;
display: none;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.5);
z-index: 2;
cursor: pointer;
}
Here's my HTML of my component where I applied the styling (I added this right at the bottom of my HTML file):
<div id="overlay">
<span id="nav" *ngIf="saveInProgress">
<div class="spinner" style="display: block; position: fixed">
</div>
</span>
<span id="nav" *ngIf="saveInProgress">
<div class="submit-message" style="display: block; color: #FFFFFF; position: fixed; left: 49.7%; top: 54.5%;">
Saving...
</div>
</span>
</div>
Here's my logic in the corresponding TS component:
save(): Observable<any> {
if(...) {
this.saveInProgress = true;
document.getElementById("overlay").style.display = "block";
}
....some more logic....
if(...){
this.saveInProgress = false;
document.getElementById("overlay").style.display = "none";
}
}
You can add the following css property to #nav (use div instead of span). This should work, as it will create an overlay over your website content so that the content is not accessible:
#nav {
background: #e9e9e9;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
opacity: 0.5;
}
Also, It would be very helpful if you provide a working example on a website like jsfiddle, stackblitz etc so that we can have a look at what it is you're trying to accomplish.
Update:
Also, give this div an 'id' other than 'nav' so that the css does not conflict between your content and overlay.
// JavaScript Document
$('.page').hide();
$(".btns").click(function(e){
e.preventDefault(); //this method stops the default action of an element from happening.
var $me = $(this); //$(this) references .btns, the object in local scope.
var $myContent = $($me.attr('href')); //pulls href of page 01, 02, or 03.
$('.page').hide(); //hides all pages
$myContent.fadeIn();//fades in clicked href connected to btn
$(".btns").removeClass('selected');//
$me.addClass('selected');
});
*{
border-spacing: 0px;
}
body{
margin: 0px;
padding: 0px;
}
.circle-container {
position: relative;
width: 24em;
height: 24em;
padding: 2.8em;
/*2.8em = 2em*1.4 (2em = half the width of a link with img, 1.4 = sqrt(2))*/
border: dashed 1px;
border-radius: 50%;
margin: 1.75em auto 0;
}
.circle-container a {
display: block;
position: absolute;
top: 50%; left: 50%;
width: 4em; height: 4em;
margin: -2em;
}
.circle-container img { display: block; width: 100%; }
.deg0 { transform: translate(12em); }
<div class="body_content">
<div class="page" id="page_01">
<h2>1. Category 1</h2>
</div>
</div>
<div class="circle-container">
<nav class="navigation">
<a href="#page_01" class="btns deg0" >
<img id="one" src="imgs/button.png" alt="page01"/>
</a>
</nav>
</div>
I have a unique situation that I would like to discuss with you all. I am trying to create a web page that has a circular navigation, as shown here enter image description here
Each one of these buttons would display content when clicked, like an in-page link. The JQuery is as shown enter image description here
The concept seems simple enough, force all content to hide, when a user clicks a button, the page content linked to that button shows. It works when the links are inline or block display, but when in a circle, the links don't work, the button content doesn't show. Has anyone worked with a similar issue? Or would anyone have a potential solution? I apologize for the vagueness of the questions but the issue seems multi-faceted. Any advice or ideas would be greatly appreciated.
Are you sure your jQuery reference is working? I don't see any issue with the code, the click event should fire when you click on the links. Check the console for any errors, I strongly believe jQuery might not get loaded.
It seems that AngularJS default prevents event propagation. Here is a test on jsfiddle.
As you can see from the link above, the div covering the links prevent the event propagate the the div under it, so the links are not working when clicked. This is just a testing case, in the real situation, the div got other function and need to be there, so removing the div is not an option.
So, how can I make the mouse click propagate to the links under div?
The code in case you don't want to click on the link, or the link becomes dead link some day in the far future. (And to fit the rules on Stack Overflow)
HTML
<div class="container">
<div class="unrelated">
<a href="http://stackoverflow.com">Stack overflow
</a>Google
</div>
<div class="scope" ng-app="myApp" ng-controller="testing">
<div class="half-cover" ng-click="leftShow = false" ng-show="leftShow == true">
Click to remove one
</div><div class="half-cover" ng-click="rightShow = false" ng-show="rightShow == true">
Click to remove one
</div>
</div>
</div>
Javascript
var myApp = angular.module('myApp',[]);
myApp.controller('testing', ['$scope', MyCtrlFunction]);
function MyCtrlFunction($scope) {
$scope.leftShow = true;
$scope.rightShow = true;
}
CSS
.container {
position: relative;
height: 300px;
width: 500px;
background-color: white;
}
.unrelated {
position: absolute;
width: 100%;
height: 100%;
}
.unrelated a{
display: inline-block;
width: 50%;
height: 100%;
line-height: 300px;
text-align: center;
}
.scope {
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 100%;
z-index: 1000;
}
.half-cover {
display: inline-block;
height: 100%;
width: 50%;
background-color: black;
color: white;
line-height: 300px;
text-align: center;
}
I am not sure, it's very confusing example, but problem is not about propogation
Problem that you hide your sides, but your .scope still overlay with height 100%;
So I do following:
HTML
<div class="container" ng-app="myApp">
<div class="unrelated">
<a href="http://stackoverflow.com">Stack overflow
</a>Google
</div>
<div ng-controller="testing">
<div class="scope {{ checkShow() }}" >
<div class="half-cover" ng-click="leftShow = false" ng-show="leftShow == true">
Click to remove one
</div><div class="half-cover" ng-click="rightShow = false" ng-show="rightShow == true">
Click to remove one
</div>
</div>
</div>
</div>
JS
$scope.checkShow = function(){
if($scope.leftShow == false && $scope.rightShow == false) {
return 'hidden-scope';
} else {
return ''
}
}
It really confusing, because ng-if was not working somehow, weird interpolation erros when I tried {{rightShow && leftShow ? '' : '.hidden-scope'}}, so I decided to end it with $scope.checkShow
CSS
.hidden-scope {
height: 0;
}
JSFiddle demo
This is not an issue regarding event propogation.. your div (the one with scope class and ng-controller) is super-imposed on the div with unrelated class because of z-index: 1000.
One of the (simple) ways you can access stuff below is by decreasing the z-index. So, applying an ng-class that does it for us. This can be any condition or function.
ng-class="{'hideit': !leftShow && !rightShow}"
where,
div.hideit {
z-index: -1
}
forked working fiddle
I'm attempting to show an interval within a bar. Initially I was using the jQuery plugin for range, but it did not work like I wanted.
I have several different bulleted pointed within my bar. Whenever someone clicks within or near the point (in the class sliderInterval) I want the class rangeSection to be added to that area, basically showing that certain interval active. However, the rangeSection doesn't even show up, nor I am certain I am doing this correctly.
In addition, since I am doing this with intervals. I want to be able to give those intervals values, so that when one is selected I can display that value.
This is what I am trying to get it to look like:
I added a snippet to show what I have done so far. Any advise?
$(function interval() {
$(".slideInterval").click(function() {
$(this).addClass(".rangeSection");
});
});
#sliderBar {
border-radius: 15px;
width: 90%;
height: auto;
margin: 25px 10%;
background: blue;
}
.rangeSection {
width: 100px;
height: 100%;
color: purple;
position: absolute;
z-index: 1;
}
.intervalCircle {
border-radius: 50%;
height: 15px;
width: 15px;
background: red;
z-index: 1;
position: absolute;
}
.sliderInterval {
display: inline-block;
padding: 10px 8%;
}
.sliderInterval:first-child {
padding-left: 0;
}
.intervalCircle:first-child {
padding-left: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="sliderBar">
<div class="rangeSection"></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle" ></span></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle" ></span></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle"></span></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle"></span></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle"></span></div>
<div class="sliderInterval" onclick="interval()"><span class="intervalCircle"></span></div>
</div>
try this one.
You can use the .ready(); function of the jQuery library and set the .click() listener on all the .sliderInterval elements. I added the active class as well.
try it here:
https://jsfiddle.net/8cxLLts1/
$(document).ready(function(){
$(".sliderInterval").click(function() {
$(this).addClass("active");
});
});
EDIT: actually, if you use toggleClass() instead of addClass(), you'll be able to turn on and off a specific section
Using onclick in your html attribute and then binding a click event also in js could be considered redundant and unnecessary. Try removing the onclick attribute from your html and then adjust your js like so:
$(document).ready(function(){
})
.on('click', '.sliderInterval', function(){
$(this).addClass(".rangeSection");
});
Bind it to the document itself and this will help with your event delegation naturally. Also, take care to double check your class names - your js is missing the 'r' in '.sliderInterval'.