How to change the CSS property of the DOM element with AngularJS - javascript

I created a function validateCode() and when a user clicks on the button validateCode() will trigger.
I want to change the height of the <div class="loginForm"> </div> when the button clicks.
I was trying : http://jsfiddle.net/Lvc0u55v/10358/

Here is a solution using ngClass:
angular
.module('LoginForm', [])
.controller('mainController', [function() {
var self = this;
self.validateCode = function() {
self.setLoginFormModified = true;
};
}]);
.loginForm {
height:140px;
width:150px;
background-color:blue;
}
.loginFormModified {
height: 500px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<section
ng-app="LoginForm"
ng-controller="mainController as ctrl"
ng-class="{'loginForm': true, 'loginFormModified': ctrl.setLoginFormModified}">
<button ng-click="ctrl.validateCode()">
Click me
</button>
</section>

This is another method you can take into consider too.
This is suitable for simple style changing. It is suggested to create function to modified multiple styles, if you have more complicated cases.
.loginForm {
height: 140px;
width: 150px;
background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<section class="loginForm" ng-app="LoginForm"
ng-controller="mainController" ng-style="modified&&{'height':'500px'}">
<button ng-click="modified=true">
Click me
</button>
</section>
<script>
var app = angular.module('LoginForm', []);
app.controller('mainController',[function(){}]);
</script>

define two style properties as follow :
<style>
.loginFormInitialStyle{
height:140px;
width:150px;
background-color:blue;
}
.loginFormChangeStyle{
height:500px;
width:150px;
background-color:blue;
}
</style>
then use ng-class instead of class as follow
<div ng-class="loginForm"></div>
then define $scope.loginForm object with two properties loginFormInitialStyle and loginFormChangeStyle with default values.
$scope.loginForm = {"loginFormInitialStyle":true, loginFormChangeStyle:false}
then in your on-click function just change the values of loginFormObject
$scope.onClick = function(){
$scope.loginForm = {"loginFormInitialStyle":false, loginFormChangeStyle:true}
}

Related

Making multilayer accordions with pure JS and using nextElementSibling

New to Javascript. I recently posted a question about creating multiple multilayer accordions. I got some great feedback, but someone mentioned that if my HTML was set up correctly, I could achieve the same goal by using nextElementSibling and thus have much cleaner JS.
I figured out how to do this using only queryselect. See the below example:
HTML:
<div class="mainAccordion">
<h2>dropdown one</h2>
<h3>dropdown two</h3>
<p>content content content content</p>
</div>
CSS:
.mainAccordion {
background-color:lightblue;
width:200px;
margin:auto;
padding:3%;
}
.mainAccordion :nth-child(1){
background-color: blue;
padding:3%;
cursor:pointer;
color:white;
}
.mainAccordion :nth-child(2){
background-color:yellow;
cursor:pointer;
max-height:0;
overflow:hidden;
}
.mainAccordion :nth-child(3){
font-weight:bold;
max-height:0;
overflow:hidden;
}
And the JS:
var mainAccordion = document.querySelector(".mainAccordion").addEventListener("click", function(e) {
if (e.target.nextElementSibling.style.maxHeight) {
e.target.nextElementSibling.style.maxHeight = null;
} else {
e.target.nextElementSibling.style.maxHeight = e.target.nextElementSibling.scrollHeight + "px";
}
});
This works as intended. However, when I introduce multiple multilayer accordions and switch to "querySelectorAll", it stops working. Also depending on the browser, I sometimes get an error message saying my "addEventListener" is not a function.
See below:
HTML:
<div class="mainAccordion">
<h2>dropdown one</h2>
<h3>dropdown two</h3>
<p>content content content content</p>
</div>
<div class="mainAccordion">
<h2>dropdown one</h2>
<h3>dropdown two</h3>
<p>content content content content</p>
</div>
CSS:
body {
display:flex;
width: 900px;
margin:auto;
}
.mainAccordion {
background-color:lightblue;
width:200px;
margin:auto;
padding:3%;
}
.mainAccordion :nth-child(1){
background-color: blue;
padding:3%;
cursor:pointer;
color:white;
}
.mainAccordion :nth-child(2){
background-color:yellow;
cursor:pointer;
max-height:0;
overflow:hidden;
}
.mainAccordion :nth-child(3){
font-weight:bold;
max-height:0;
overflow:hidden;
}
and JS:
var mainAccordion = document.querySelectorAll(".mainAccordion").addEventListener("click", function(e) {
if (e.target.nextElementSibling.style.maxHeight) {
e.target.nextElementSibling.style.maxHeight = null;
} else {
e.target.nextElementSibling.style.maxHeight = e.target.nextElementSibling.scrollHeight + "px";
}
});
I've tried changing "querySelectorAll(".mainAccordion") to getElementsByClassName("mainAccordion") but also doesn't work.
Is forEach somehow involved?
Note: I know you can also achieve the same goal by toggling a class that has the "max-height:0;overflow:hidden". However, this was how I was initially taught to do accordions.
This is for my own practice.
I appreciate the help.
Try this:
let accordionElements = document.querySelectorAll(".mainAccordion");
accordionElements.forEach(element => {
element.addEventListener("click", function(e) {
if (e.target.nextElementSibling.style.maxHeight) {
e.target.nextElementSibling.style.maxHeight = null;
} else {
e.target.nextElementSibling.style.maxHeight = e.target.nextElementSibling.scrollHeight + "px";
}
})
});
It's because with querySelector() an HTML Element is return. With querySelectorAll() it's a NodeList. In your sample code you try to attach an event to a node list which is not possible.
You need to loop inside and then attaching the event to each HTML Element inside.
i think that the problem is that the querySelector() returns the first Element within the document that matches the specified selector. then the event listener will be applied to the first element found.
the querySelectorAll() returns a list. you could use it with forEach like this
var mainAccordion = document.querySelectorAll(".mainAccordion");
console.log(mainAccordion);
mainAccordion.forEach(accordion => {
accordion.addEventListener("click", function(e) {
if (e.target.nextElementSibling.style.maxHeight) {
e.target.nextElementSibling.style.maxHeight = null;
} else {
e.target.nextElementSibling.style.maxHeight =
e.target.nextElementSibling.scrollHeight + "px";
}
});
});

Faded text not reappearing

I'm working on a random wiki viewer, and its been a slog, but i'm finally at the point where i think that at least the UI's functionality is done. The only problem is that after i fade some text on the "random" button, and replace it with an iframe which is then removed when the button is clicked again, the text doesn't seem to fade back in. Any ideas?
https://codepen.io/EpicTriffid/pen/WOYrzg
$(document).ready(function() {
//Random Button
var but1status = "closed"
var randFrame = ("#randframe")
$(".button1").on("click",function () {
var but = $(".button1");
var cross = $("#cross1");
but.animate({marginTop:"10%", width:"100%", height:"100vh"}, "fast");
$(".b1text").animate({opacity:0});
cross.delay(1000).fadeIn();
but1status = "open"
if (but1status == "open") {
setTimeout(randFrame,1000)
function randFrame (){
$(".button1").html("<iframe class='randframe' src='demo_iframe.htm' height='100%' width='100%' style='border:none'></iframe>");
$("#cross1").click(function() {
$('.button1').removeAttr('style');
$("#cross1").fadeOut('fast');
$('.randframe').remove();
$(".b1text").animate({opacity:"1"});
});
};
};
});
You are emptying the HTML of .button1 when you do:
$(".button1").html(....
In order to get it back, you need to add:
$(".button1").html('<div class="b1text">Random</div>');
after
$('.randframe').remove();
Your button is missing the text Random
When you call:
$(".button1").html(...
you are replacing the inside html of the object with the iframe.
When you remove .randframe you need then re-add the text for your button.
Instead of:
$('.randframe').remove()
you can call this which will accomplish both:
$('.button1').html('random');
Efficiency tip: You did a good job of saving references to your jquery variables but and cross, why not use them?
but.html(...
cross.click(function (){...
This line effectively replaces whatever you have in the button 1 div
$(".button1").html("<iframe class='randframe' src='demo_iframe.htm' height='100%' width='100%' style='border:none'></iframe>");
Your cross1.click function does not re-populate the button1 div, I would recommend
$("#cross1").click(function() {
$('.button1').removeAttr('style');
$('.button1').html('Random');
$("#cross1").fadeOut('fast');
$(".b1text").animate({opacity:"1"});
});
Here you go with the solution https://codepen.io/Shiladitya/pen/WOLNpw
$(document).ready(function() {
//Random Button
var but1status = "closed"
var randFrame = ("#randframe")
$(".button1").on("click",function () {
var but = $(".button1");
var cross = $("#cross1");
but.animate({marginTop:"10%", width:"100%", height:"100vh"}, "fast");
$(".b1text").fadeOut();
cross.delay(1000).fadeIn();
but1status = "open"
if (but1status == "open") {
setTimeout(randFrame,1000)
function randFrame (){
$(".button1").html("<iframe class='randframe' src='demo_iframe.htm' height='100%' width='100%' style='border:none'></iframe>");
$("#cross1").click(function() {
but.removeAttr('style');
cross.fadeOut('fast');
$('.randframe').remove();
but.html('<div class="b1text">Random</div>');
});
};
};
});
//Search Button
var but2 = "closed"
$(".button2").click(function () {
var but = $(".button2");
var btext = $(".b2text");
var cross = $("#cross2");
but.animate({marginTop:"10%", width:"100%", height:"100vh"}, "fast");
btext.fadeOut();
cross.delay(2000).fadeIn()
but2 = "open"
$("#cross2").click(function() {
$('.button2').removeAttr('style');
$('.b2text').fadeIn(1500);
$("#cross2").fadeOut('fast');
})
})
});
#spacer {
margin:0;
padding:0;
height:50px;
}
body {
min-height: 100%;
min-width: 1024px;
width:100%;
margin-top:4em;
padding:0;
background-color: teal;
}
h1 {
color:white;
font-family:"cabin";
text-align:center;
}
#cross1 {
position:relative;
font-size:3em;
color:white;
margin-top:6px;
float: left;
display:none;
}
#cross2 {
position:relative;
font-size:3em;
color:white;
margin-top:6px;
float: right;
display:none;
}
#randframe {
display:none;
}
.button1 {
position:absolute;
height:2.6em;
width:5em;
font-size:1.5em;
text-align:center;
color: white;
font-family:"cabin";
border:solid;
border-radius:25px;
padding:10px;
box-sizing:border-box;
transition: all 2s ease;
}
.button2 {
position:absolute;
right:0;
height:2.6em;
width:5em;
font-size:1.5em;
text-align:center;
color: white;
font-family:"cabin";
border:solid;
border-radius:25px;
padding:10px;
box-sizing:border-box;
transition: all 2s ease;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<head>
<link href="https://fonts.googleapis.com/css?family=Josefin+Slab" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Raleway" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Crimson+Text" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Cabin" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<div class="container">
<div class="row">
<div class="col-xs-12">
<h1>Wiki Viewer</h1>
</div>
</div>
</div>
<div id="spacer"></div>
<div class="container">
<div class="row">
<div class="col-xs-12">
<div class="button1">
<div class="b1text">Random</div>
</div>
<div class="button2">
<div class="b2text">Search</div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<div class="text-center">
<i id="cross1" class="glyphicon glyphicon-remove"></i>
</div>
</div>
<div class="col-xs-12">
<div class="text-center">
<i id="cross2" class="glyphicon glyphicon-remove"></i>
</div>
</div>
You need to keep the content inside the ".button1" to reuse after the iframe is removed.
Try using callbacks. So change your #cross1 fadout to
$("#cross1").fadeOut('fast',function(){
$('.randframe').remove();
$(".b1text").animate({opacity:"1"});
});
Also, this may not be affecting your code, but you're missing some semi colons after some variable declarations.
Not all methods have callbacks in JQuery, but when available, they are useful because basically it means that your code is not fired until the other thing is completely done. This happens a lot with fading and opacity.

How to create a function to get next id of element in jquery and call this function?

I've created a custom function goToNext() it's just supposed to alert the id of the next element that i've clicked on.
I want to call this custom function inside another click function.
For now when I click on first element it alerts id_2 (next from the first, so it's ok) but if you click the second element it doesn't return id_3 (like it's supposed to be) but it return id_2 same if you click on the last element (supposed to alert the first)
this is my jsfiddle example here
function goToNext() {
var get_next_id = $('.btn').next().attr("id");
alert(get_next_id);
}
$('.btn').click(function() {
goToNext();
});
.btn {
width: 50px;
height: 50px;
margin: 10px auto;
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="btn" id="id-1">
1
</div>
<div class="btn" id="id-2">
2
</div>
<div class="btn" id="id-3">
3
</div>
Try this
function goToNext($btn){
var get_next_id = $btn.next().attr("id");
alert(get_next_id);
}
$('.btn').click(function(){
goToNext($(this));
});
You have to use this
function goToNext(thisObj){
var get_next_id = $(thisObj).next().attr("id");
if(get_next_id!=undefined)
alert(get_next_id);
else
alert($(thisObj).parents().find("div:first").attr("id"));
}
$('.btn').click(function(){
goToNext(this);
});
.btn{
width:50px;
height:50px;
margin:10px auto;
background-color:yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class ="btn" id="id-1">
1
</div>
<div class ="btn" id="id-2">
2
</div>
<div class ="btn" id="id-3">
3
</div>
You need to use reference this
function goToNext(e){
var get_next_id = $(e).next().attr("id");
alert(get_next_id);
}
$('.btn').click(function(){
goToNext(this);
});
Updated Fiddle

Angular Routing, Different background Images for each route page

I'm trying to set a different background image on the body of my separate partials.
But the images are just being loaded into the div area and not the whole body as i wanted, could any one of you be having an idea on how to solve this?
Here is my code
angular.module('controller',[])
app.controller('AboutCtrl',['$scope', function($scope){
$scope.title="The About page"
}])
app.controller('ServiceCtrl',['$scope', function($scope){
$scope.title="Our services page"
}])
app.controller('ContactCtrl',['$scope', function($scope){
$scope.title="How to contact us page"
}])
app.controller('MyCtrl', ['$rootScope', function ($rootScope) {
$rootScope.bgimg = "img/home.jpg";
}])
#bg {
position: fixed;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
}
#bg img {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
min-width: 50%;
min-height: 50%;
}
<body >
<div id="bg img" ng-controller="MyCtrl" style="background-image: url({{ bgimg }})">
</div>
</body
Can you not just move your main controller up to the body tag?
<body id="bg img" ng-controller="MyCtrl" style="background-image: url({{ bgimg }})">
<div ng-controller="OtherCtrl">
As I mentioned in my comments you create a service that holds the background variable. Then you create get/set methods to allow you to make changes.
var app = angular.module('controller',[])
.service('SessionService', function(){
var vm = this;
this.bgImg = "https://c1.staticflickr.com/1/31/37271521_47df0e4547_b.jpg";
return {
setBgImg: function(newBgImg){
vm.bgImg = newBgImg;
},
getBgImg: function(){
return vm.bgImg;
}
}
})
Then you inject the SessionService into the Main controller you have set on Body. And call the get method to retrieve the background variable.
app.controller('SessionCtrl', ['$scope','SessionService',function($scope, SessionService) {
this.getBgimg = SessionService.getBgImg;
}]);
<body id="bg img" ng-controller="SessionCtrl as vm" style="background-image: url({{ vm.getBgimg() }})">
Finally for every Controller you'd like to make the change, inject the service into the controller as well and call the Set method. In this example I have it being called from a button click function.
app.controller('ContactCtrl',['$scope','SessionService', function($scope,SessionService){
$scope.ContactTitle="How to contact us page";
$scope.winter = "";
$scope.changeBg = function(){
SessionService.setBgImg('http://alvaradoconsultinggroup.com/wp-content/uploads/2014/10/success.jpg');
}
}]);
<div ng-controller="ContactCtrl">
<p style="font-size: 25px;color: white;">{{ContactTitle}}</p>
<button ng-click="changeBg()">Change Back</button>
</div>
I piggybacked off Brian Baker's plunker to show you the changes in action here.
https://plnkr.co/edit/RjgwdwuOFJgMct4y3qUS?p=preview

How to exclude the container from this javascript code?

This question relates to the last i asked on this site - Using javascript to "link" from html background image?.
I received a good answer which worked, however the link for the background image is also applied to the container. How would I go about ensuring that only clicking on the background image (of the id body) and not the container links to whatever website?
I hope I have been clear enough. Many thanks in advance.
The html:
<html>
<head>
<link href = "style1.css" rel = "stylesheet" type = "text/css">
</head>
<div id = "header">
Header
</div>
<body>
<div id = "body">
<div class = "container">
</div>
</div>
</body>
</html>
<script>
document.getElementById('body').onclick = function() {
window.location = 'http://www.google.com/';
}
</script>
The CSS code:
#header{
width:100%;
height:50px;
background-color:black;
}
#body {
width:100%;
height:2000px;
background-image:url('uploads/1.jpg');
cursor:pointer;
}
.container{
width: 1000px;
margin-right: auto;
margin-left: auto;
height: 1000px;
background-color:white;
}
In your click handler, you can check the element that was clicked on, if it's not body (meaning it's a child), then don't do anything.
document.getElementById('body').onclick = function(e) {
// e.target is what you clicked on
// this is always what the event was bound to
if(e.target === this){
window.location = 'http://www.google.com/';
}
}
Try add this code in your script:
document.querySelector('#body .container').onclick = function() {return false; }
To have:
<script>
document.getElementById('body').onclick = function() {
window.location = 'http://www.google.com/';
}
document.querySelector('#body .container').onclick = function() {return false; }
</script>
You could also do a return false
document.getElementById('body').onclick = function(e)
{
if(!(e.target===this))
return false;
console.log("click");
//window.location = 'http://www.google.com/';
}

Categories