My target is to set or remove class depending on component boolean with Angular 2. For example: isRed = true > add class "red", if isRed = false > remove class "red". How is that possible? Code tried:
isRed: boolean;
constructor() {
$(document).scroll(function(){
var scrollTop = $(this).scrollTop();
if(window.location.hash) {
} else{
this.isRed = true;
}
if(scrollTop > 50) {
this.isRed = true;
}
else {
this.isRed = false;
}
});
}
and html:
[ngClass]="{red: isRed}"
The most concise way is IMHO
[class.red]="isRed"
update
The cause of your problem is function in
$(document).scroll(function(){
it should use arrow function
$(document).scroll(() => {
otherwise this within the callback won't point to the current class, but instead to the caller.
I'd suggest you try to avoid jQuery with Angular2. Use instead
class MyComponent {
constructor(private elRef:ElementRef) {}
isRed:boolean;
#HostListener('document:scroll', ['$event'])
onScroll(event:any) {
var scrollTop = this.elRef.nativeElement.scrollTop;
// or
$(this.elRef.nativeElement).scrollTop();
if(window.location.hash) {
} else{
this.isRed = true;
}
if(scrollTop > 50) {
this.isRed = true;
}
else {
this.isRed = false;
}
}
}
This is javascript so I would try something like:
isRed; // there's no need to initialize this variable
since the constructor has its own scope but hey,
do it if you wish so
Also it doesn't seem that you are working inside an object since you are using ; instead of , which means that you shouldnt use ":" but rather "="
Related
I build an object and gather all elements by class name, then on changing the with I want to do some work on them. When I construct the object it works, but within WidthChecker() when do some work on a width change the become undefined.
class SlickController {
constructor () {
this.$mobileSlicksCarousels;
}
Init() {
this.$mobileSlicksCarousels = document.getElementsByClassName("slick_carousels_mobile-only"); // view in console says this is valid, I see the objects
this.WidthChecker();
}
WidthChecker() {
var width = $(window).width();
$(window).on('resize', function() {
console.log(this.$mobileSlicksCarousels); // they become undefined in here, lost and none of the content afterwords be seen
if ($(this).width() !== width) {
width = $(this).width();
if (width < 491) {
this.$mobileSlicksCarousels.forEach( carousel => {
this.SlickMobile(carousel);
});
} else if (width > 490) {
this.$mobileSlicksCarousels.forEach( carousel => {
this.UnSlickMobile(carousel);
});
}
}
});
}
SlickMobile (toSlick) {
console.log(toSlick);
toSlick.slick();
}
UnSlickMobile (unSlick) {
unSlick.slick('unslick');
}
}
// call and start width checker
slick_Controller.Init();
I assume the issue is when I called $(window).on('resize', function() { because the function doesn't see the parent variables, but I'm not sure how else to approach calling a function directly on resize.
You can store this in a variable before jumping to function or you can bind function but then you lose jquery context and cannot use $(this) expression.
Take a look at the examples
class Test {
constructor () {
this.property = 1;
}
Func() {
var width = $(window).width();
const that = this;
$(window).on('load', function() {
console.log(that.property);
console.log($(this).width());
});
}
Func1() {
var width = $(window).width();
$(window).on('load', (function() {
console.log(this.property);
console.log($(window).width());
}).bind(this));
}
Func2() {
var width = $(window).width();
$(window).on('load', this.OnResize.bind(this));
}
OnResize(event) {
console.log(this.property);
console.log($(event.target).width());
}
}
const test = new Test();
test.Func();
test.Func1();
test.Func2();
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I'm trying to check if an element is display block, and if it is then i want to execute some code. Below is my code, its a large function but where I'm trying to check if a div is display block is at the bottom, and if it is display block then i want to execute the blur method.
As you can see near the bottom, I started writing if ($suggestionsWrapper === and my intention was to write if suggestions wrapper is display none, then do this. I just can't figure out how to execute this, what I've written doesn't work. Also I am new to all of this so sorry if this is really messy or doesn't make sense, still very much learning.
//Header Search Handler
function headerSearchHandler(){
var $searchInput = $(".header-search input[type=text]"),
$searchSubmit = $(".header-search input[type=submit]"),
$mobSearchBtn = $(".mobile-search-btn"),
$myAccountText = $(".menu-utility-user .account-text"),
$miniCart = $("#header #mini-cart"),
$searchForm = $(".header-search form"),
$headerPromo = $(".header-promo-area");
$suggestionsWrapper = $('#suggestions-wrapper');
//
$mobSearchBtn.on("click touchend", function(e) {
$(this).hide();
//$myAccountText.hide();
$searchInput.show();
$searchInput.addClass('grey-line');
$searchSubmit.show();
$miniCart.addClass("search-open");
$searchForm.addClass("search-open");
setTimeout(function() {
$searchInput.addClass("active").focus();
}, 100);
e.stopPropogation();
});
$searchInput.on("click touchend", function(e) {
$searchInput.addClass('grey-line');
e.stopPropogation();
}).blur(function(e) {
var $this = $(this);
if($this.hasClass("active")){
$this.removeClass("active");
$searchSubmit.hide();
$mobSearchBtn.show();
$miniCart.removeClass("search-open");
$searchForm.removeClass("search-open");
}
});
$searchInput.focus(function(e){
$(this).css('width', '145px');
})
if ($suggestionsWrapper.css('display') == 'none') {
$searchInput.blur(function(e){
$(this).removeClass('grey-line');
$(this).css('width', '145px');
}
})
}//End Header Search Handler
You can create a helper method to check if display is block or not :
function checkDisplay(element) {
return $(element).css('display') == 'block';
}
Then you can check it like :
if(checkDisplay("#myElement")){
console.log("Display is Block")
}
else {
console.log("Display is NOT Block")
}
here is an example : https://jsfiddle.net/fafgqv7v/
You can do something like this I think:
if ($suggestionsWrapper.css('display') == 'block')
{
// true
} else {
// false
}
Based off of your code I think you have the }) wrong, it should be:
if ($suggestionsWrapper.css('display') == 'none') {
$searchInput.blur(function(e){
$(this).removeClass('grey-line');
$(this).css('width', '145px');
})
}
I hope this helps!
I need help in updating the CSS for selectedElement, currently, this works but only for the first element.
Basically, I have a link, when I click on it:
(click)="showUserDetails($event)"
I'm passing the x & y coordinates to my method and want to use this to update the css and enabled a boolean flag which shows the div:
showUserDetails(el: any) {
let target = el.target || el.srcElement;
let selectUsername = (document.getElementById('userDetailsInfo') as HTMLInputElement);
selectUsername.style.top = target.offsetY + "px";
selectUsername.style.left = target.offsetX + "px";
this.selected = true;
el.preventDefault();
}
Currently, the above code only seems to work for the first element and I'm trying to figure out a way to have it so based on the clicked element, go up the dom and find me the div with the id of 'userDetailsInfo' and apply the top/left values to that, and not just to the first item.
I actually solved it like so:
private hostEl: HTMLElement;
constructor(el: ElementRef) {
this.hostEl = el.nativeElement;
}
ngOnInit() {
window.addEventListener('scroll', this.scroll, true);
}
ngOnDestroy() {
window.removeEventListener('scroll', this.scroll, true);
}
//Get the header
let header = (document.querySelector('.header') as HTMLInputElement);
if (window.pageYOffset >= 100){
header.classList.add('sticky');
} else {
header.classList.remove('sticky');
}
Let's say I got 12 divs of class subClass, each ending with individual number: subClass-1 , subClass-2 and so on. Also, for each of those classes I got same function, for example:
function toggleAreas1() {
var $hide = $('.toggle-areas-1 > .row:visible');
$hide.fadeOut(function() {
if ($hide.next().length) {
$hide.next().fadeIn();
} else {
$hide.prevAll().last().fadeIn();
}
});
}
But for obvious reasons, I don't want to use 12 different, yet almost identical functions, when I easily could use one, more universal.
I was thinking about something along these lines:
function toggleAreas1(index) {
for (i = 0; i < 12; i++) {
index = i++
var $hide = $('.toggle-areas-index > .row:visible');
}
$hide.fadeOut(function() {
if ($hide.next().length) {
$hide.next().fadeIn();
} else {
$hide.prevAll().last().fadeIn();
}
});
}
But of course it doesn't work, for my js skills are non-existent. What should I do to fix my problem?
function toggleAreas1() {
var $hide = $("[class^=toggle-areas] > .row:visible");
$hide.fadeOut(function() {
if ($hide.next().length) {
$hide.next().fadeIn();
} else {
$hide.prevAll().last().fadeIn();
}
});
}
try changing
var $hide = $('.toggle-areas-index > .row:visible');
to
var $hide = $('.toggle-areas-'+index+' > .row:visible');
You would need the + operator for gluing an integer variable to strings:
i.e.
var $hide = $('.toggle-areas-' + index + ' > .row:visible');
try this:
function toggleAreas1() {
var $hide = $('[class^=toggle-areas] > .row:visible').each(function(){
$(this).fadeOut(function() {
// do what you need
});
});
You can use string concatenation for building jQuery selectors:
for (i = 1; i <= 12; i++)
{
var $hide = $('.toggle-areas-' + i + ' > .row:visible'); // .toggle-areas-1, .toggle-areas-2 etc.
$hide.fadeOut(function() {
if ($hide.next().length) {
$hide.next().fadeIn();
} else {
$hide.prevAll().last().fadeIn();
}
});
}
However, why don't you just give them the one common class like toggle-areas? You can add this class in addition to your existent:
<div class="toggle-areas toggle-areas-1"></div>
<div class="toggle-areas toggle-areas-2"></div>
<div class="toggle-areas toggle-areas-3"></div>
Then, you will be able to do both:
// Affects all toogle-areas
$(".toogle-areas").fadeOut(function() {
if ($hide.next().length) {
$hide.next().fadeIn();
} else {
$hide.prevAll().last().fadeIn();
}
});
and
// Affects only toogle-areas-2
$('.toggle-areas-2 > .row:first').show().nextAll().hide();
What you are looking for are attribute substring selectors.
So if your class begins with subClass use: [class^=subClass]
$('[class^=subClass]');
Note though that this tests against the full attribute string so if there is something else in front it will not match, ie class="class1 subClass-1" in which case you can use the other two $=, *= selectors. The first one doing an ends with match, the second doing a contains match.
jQuery('[class^=subClass]').css({
background:'#ffff00',
});
[class^=subClass] {
width:48px;
height:48px;
margin-bottom:3px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="subClass-1"></div>
<div class="subClass-2"></div>
<div class="subClass-3"></div>
I have the following code in a jQuery JavaScript document running on a page (THIS IS CURRENT):
$(window).resize(function(){
detectscreen();
});
function windowWidth() {
if(!window.innerWidth) {
// user is being a git, using ie
return document.documentElement.clientWidth;
} else {
return window.innerWidth;
}}
gearsExists = false;
function detectscreen() {
shouldExist = windowWidth() >= 1300;
if (shouldExist != gearsExists) {
if (shouldExist) {
$('body').append('<div id="gearsfloat"></div>');
$('#clickGoTop').fadeTo(0,0);
$('#clickGoTop').hover(function() {
$(this).stop().fadeTo(500,1);
}, function() {
$(this).stop().fadeTo(500,0);
});
} else {
$('#gearsfloat').remove();
$('#clickGoTop').remove();
}
gearsExists = shouldExist;
}
}
This code is from my previous question, branched here simply because I think it is related.
The problem here is that the beginning is fine: it is displayed. However, if the screen is resized to less than 1300, it disappears; still good.
Now I make the window again larger than 1300. Suddenly the gear element is doubled. Another screen squish and largen and BAM, there's three now. Do this several times and it quickly adds up.
How can I stop this?
If you hook any code in resize event, make sure that your code doesn't resize the window again. Otherwise, resize event will fire again and your code will go in infinite loop.
Also, in your code, you are not using the global gearsExists variable. Remove the 'var' at the bottom of the method to use the global variable.
function detectscreen() {
// Your original code
//var gearsExists = shouldExist; //This code will create new local variable.
gearsExists = shouldExist;
}
}
EDIT: Here's what I would do:
//We will add only one variable to the global scope.
var screenManager = function()
{
var pub = {};
var inResizeHandler = false;
pub.getWindowWidth = function()
{
return window.innerWidth || document.documentElement.clientWidth;
};
pub.manage = function()
{
//if we are already in the resize handler, don't do anything.
if(inResizeHandler)
return;
inResizeHandler = true;
if(pub.getWindowWidth() < 1300)
{
$('#gearsfloat').remove();
//You don't have to remove clickGoTop because it is part of gearsfloat.
inResizeHandler = false;
return;
}
if($('#gearsfloat').length > 0)
{
inResizeHandler = false;
return false;
}
$('body').append('<div id="gearsfloat"></div>');
$('#clickGoTop').fadeTo(0,0);
$('#clickGoTop').hover(
function() {$(this).stop().fadeTo(500,1);},
function() {$(this).stop().fadeTo(500,0);
});
inResizeHandler = false;
};
pub.init = function()
{
$(window).resize(pub.manage);
};
return pub;
}();
$(document).ready( function() { screenManager.init(); } );
EDIT:
Final working version:
http://jsbin.com/ufipu
Code:
http://jsbin.com/ufipu/edit
Haha! After a while, I decided to ignore everything said by everyone else for a while (sorry) and try to see if I could figure it out myself, and I did!
Thanks to SolutionYogi for all the help, but the code he gave me was out of my expertise; it was impossible to debug. My solution is not as pretty as his (if you can help optimize, please do), but it works:
function WinWidth() {
// check width of content
if(!window.innerWidth) {
// you git, how dare you use ie
return document.documentElement.clientWidth;
} else {
return window.innerWidth;
}
};
function gearsAction() {
if(WinWidth() >= 1300) {
$('body').append(
'<div id="gearsfloat"></div>');
$('#clickGoTop').fadeTo(0,0);
$('#clickGoTop').hover(
function() {$(this).stop().fadeTo(500,1);},
function() {$(this).stop().fadeTo(500,0);});
};
};
$(document).ready(function() {
gearsAction();
});
$(window).resize(function() {
$('#gearsfloat').remove();
gearsAction();
});