Storing .css() method in a variable - javascript

I've Googled my face off with no luck including searching this site. I just want a simple clear answer.
Here is my HTML:
<div id="main-navigation">
<ul>
<li>
home
</li>
</ul>
</div>
Here is the css method I'm using which I've tested and works:
// Layout 1
$('#default').click(function() {
if('true' == 'true') {
// General Values
$(hmnavUL).css({ backgroundColor: bgDefault });
});
Here is the variable I've created:
var bgSet = $(hmnavUL).css({ backgroundColor: bgDefault });
Here is what I'm trying to achieve:
// Layout 1
$('#default').click(function() {
if('true' == 'true') {
// General Values
bgSet
});
The result:
The Browser completely ignores my "bgSet" variable, but it acknowledges the style when I don't use a variable. It's not giving me any errors either with my preferred version. Anything you can tell me about my syntax would be appreciated. I'm assuming it's my syntax.
I've linked a photo example to demonstrate the my desired end product (note: I can't attach images yet).
(Default Layout, Second Layout, Remove All Styles)
Desired result: Result

The variable doesn't contain what you expect it to do. The code isn't kept in the variable, it's executed right away and the return value from the css method (which is the jQuery object) is stored in the variable.
You can't put a "macro" in a variable and have it executed by referencing the variable. The closest thing to what you are trying to do would be to put the code in a function, so that it can be executed later:
var bgSet = function() {
$(hmnavUL).css({ backgroundColor: bgDefault });
});
// Layout 1
$('#default').click(function() {
if('true' == 'true') {
// General Values
bgSet();
}
});

It looks like you want to toggle and element's css properties based on click eventHandler. You've got the right idea, but you're javascript is slightly off. Here's an example that should perform the function you want:
// Function to change the css of an element
function makeRed(elem){
elem.css({ "background-color" : "red" });
};
// Attach an event handler..
$("#clickMe").click(function(){
// Store the object as a variable
var obj = $("#foo"); // <-- The element you want to change the bg of
// Run your function.
makeRed(obj);
});
#foo{
width: 50px;
height: 50px;
background-color: blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.1/jquery.min.js"></script>
<div id="foo"></div><br />
<button id="clickMe">Click Me!</button>
This is really about learning how javascript selectors, functions and variables work.. Although your question is phrased in a sort-of obtuse way for StackOverflow, I appreciate that you posted your code and that you're trying to learn. :)

Related

Need help converting jQuery to VanillaJS

$('.tabLabel').click(function() {
if (!$(this).hasClass('activeTab')) {
$('.tabLabel').removeClass('activeTab');
$(this).addClass('activeTab');
$('.tab').toggleClass('activeTabContent');
}
});
var tabLabels = document.querySelectorAll('.tabLabel');
Array.from(tabLabels).forEach(function(tabLabel) {
tabLabel.addEventListener('click', function(e) {
var activeTabLabel = e.target.classList.contains("activeTab");
if (!activeTabLabel) {
tabLabel.classList.remove('activeTab');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
<div class="tabLabel activeTab">
<p>Tab One</p>
</div>
<div class="tabLabel">
<p>Tab Two</p>
</div>
</div>
I have this click function that I'm getting a bit lost in converting to "Vanilla" Js (plain js). Any help would be appreciated. I've tried so far what I can but the lexical this is what is confusing me.
UPDATE: I'm still having troubles but I can at least console.log the elements that I want to target.
// Working Code in jQuery
$('.tabLabel').click(function() {
if (!$(this).hasClass('activeTab')) {
$('.tabLabel').removeClass('activeTab');
$(this).addClass('activeTab');
$('.tab').toggleClass('activeTabContent');
}
});
// My attempt at converting
// Does not work. returns err => Cannot read property 'remove' of undefined || Cannot read property 'toggle' of undefined
var tabLabels = document.querySelectorAll('.tabLabel');
var tab = docuement.querySelectorAll('.tab');
Array.from(tabLabels).forEach(function(tabLabel) {
tabLabel.addEventListener('click', function(e) {
if (!this.classList.contains('activeTab')) {
tabLabel.classList.remove('activeTab');
this.classList.add('activeTab');
tab.classList.toggle('activeTabContent');
}
});
});
The Problem:
Your code tabLabel.classList.remove('activeTab'); doesn't work because you define your tabLabel in a different scope. It is defined when you create your click listener, however the click listener event is in a completely different scope when it's fired, so it ends up being 'undefined'. This was the root of your problem.
The 'this' keyword can be tricky, especially in embedded callback functions because it's really easy to lose track of what scope you're currently in. I always find it is helpful to console.log(this) just to make sure it is targeting what I want.
Edit- For more information on the 'this' keyword, I suggest checking out all the resources here:
How does the "this" keyword work?
The Solution:
Below is a modified version of your vanilla JS code that toggles the activeTab class between the two on click.
var tabLabels = document.querySelectorAll('.tabLabel');
var tabs = document.querySelectorAll('.tab');
tabLabels.forEach(function(tabLabel) {
tabLabel.addEventListener('click', function(e) {
if (!this.classList.contains('activeTab')) {
tabLabels.forEach(function(tl){
tl.classList.remove('activeTab');
});
this.classList.add('activeTab');
tabs.forEach(function(tab) {
tab.classList.toggle('activeTabContent');
}
}
});
});
A couple things to note:
You had a typo in the definition of your tab variable, 'docuement' should be 'document'.
You don't need to do Array.from(tabLabels).forEach(), querySelectorAll already created an array. You'll see that I modified that.
Edit- As frederickf clarified, querySelectorAll doesn't create an array, but a NodeList. https://developer.mozilla.org/en-US/docs/Web/API/NodeList
We have to iterate over your tabLabels array again to remove the 'activeTab' class for each item before we apply it to the clicked control.
Hope that helps!

Javascript/Jquery Boolean help: Hiding/Showing Divs

Can someone explain to me what i am doing wrong in this code?
http://jsfiddle.net/14njfqef/
var isLoggedIn = function(state){
if(state == true) {
$("#content-container").show();
$("#account2").show();
$("#account").hide();
}
else(state == false){
$("#content-container").hide();
$("#account2").hide();
$("#account").show();
}
}
onload=function() {
isLoggedIn(false);
}
On load i want the divs to hide but then when i click the button i want the divs to show?
Is the boolean function set out in the correct way?
Piece below tries to re-arrange piece at OP. onload not appear clearly defined , not addressed , though could be attached to an event , i.e.g., window.onload = onload . Wrapped blocks in jquery .ready() event . Removed js onclick markup from html , included at script element , or loaded from file at jquery .on("click") event . Added strict comparison operator === (an added =) to if / else if statements. Changed input type to button. Added if to else portion of composition (see link posted at comments by Felix Kling).
Try
$(function() {
var isLoggedIn = function(state){
if(state === true) {
$("#content-container").show();
$("#account2").show();
$("#account").hide();
}
else if(state === false){
$("#content-container").hide();
$("#account2").hide();
$("#account").show();
}
};
isLoggedIn(false);
$("input[type=button]").click(function() {
isLoggedIn(true)
})
});
jsfiddle http://jsfiddle.net/guest271314/14njfqef/3/
changed your html to
<input type="submit" value="Boolean" id="toggle"/>
rewrote your js as
// JQuery run at start effectivly
$(document).ready(function() {
function isLoggedIn(state) {
if(state == true) {
$("#content-container").show();
$("#account2").show();
$("#account").hide();
}
else {
$("#content-container").hide();
$("#account2").hide();
$("#account").show();
}
}
// JQuery attaching a click event using an anonymous function
// and hard coding your isLoggedIn to true, passing variables is a bit more complicated.
$('#toggle').click(function() {isLoggedIn(true)});
isLoggedIn(false);
})
Well there's a few things I am not sure if you are aware of so I feel there's some responsibility on my end to make sure they are mentioned. They are a number of syntactical errors in your post that are stopping this from working so instead of addressing them I feel its necessary to update your view on what JQuery you are using as well as your selector choice.
First I would add a class structure to all of the div's to target them all at once so you can save on some lines of code. In production it's always better to have less code for all of your visitors to download because even a little bit of code can get out of control after enough hits on a webpage. Having to serve it kills speed and so does having to process three separate jquery selections as opposed to one.
I would change the HTML to...
<body>
<div id='content-container' class='boxes'>
Content Container
</div>
<div id='account' class='boxes'>
account
</div>
<div id='account2' class='boxes'>
account2
</div>
<input id="validateButton" type="submit" value="Boolean">
</body>
This way you can simply target all divs with $(".boxes"); ... I wouldn't recommend getting into the habbit of using $("div");
Next I would change the JQuery to being more JQuery friendly code. Its not always useful to use an onload event from pure Javascript to handle JQuery driven functions in correct time to the loading of DOM objects. Therefore you should use $( document ).ready( handler ) to handle this load event properly just in case it causes you problems down the road. The more common shorthand of this ready event is a simple $(function() { }); wrapper.
The rest of the code can be re-arranged to this....
var isLoggedIn = false; //<--Instantiate to false, make global to window level scope
//Load event Corrected For JQuery
$(function() {
$(".boxes").hide(); //<--Hide on load
//Add A Proper Updated Click Event To Button
$("#validateButton").click(function() {
isLoggedIn = true; //<--Should include real functionality not hand coded to true
checkLoginAndRespond(); //<--Validate Login Status
});
});
function checkLoginAndRespond() {
//If Logged, Show
if(isLoggedIn) {
$(".boxes").show();
//Else Don't
} else { $(".boxes").hide(); }
} //end function
Lastly, the version. New versions of JQuery have not been released for some time and seem to not be in the making so its a safe bet to use their most recent versions as it has thousands of pages of help for its syntax and it's very stable. I would recommend anything in the 2.0 or higher series JQuery.
I am assuming you have JQuery library loaded. Try
if (state) {
$("#content-container").show();
$("#account2").show();
$("#account").hide();
}
else{
$("#content-container").hide();
$("#account2").hide();
$("#account").show();
}
to solve your problem.

jquery show another link then hide itself

I have this following jquery on my view:
$(document).ready(function() {
$(function() {
$('#link1').click(function() {
$('#link2').show();
$('#link1').hide();
$('#frame').attr('src', 'http://google.com/');
});
});
});
$(document).ready(function() {
$(function() {
$('#link2').click(function() {
$('#link1').show();
$('#link2').hide();
$('#frame').attr('src', 'http://yahoo.com/');
});
});
});
On pageload, the link2 is set to hide. What the jQuery does is: when the link with id link1 is clicked, it will show the link with idlink2 and hide itself. And vice versa.
My problem is it seems that my jQuery code can still be simplified. Is there other ways I can do what I wanted with simpler version? Thanks for the help!
Working example : http://jsfiddle.net/cuJBm/
$(document).ready(function() {
$(function() {
var linkSet = $('#link1').add('#link2')
linkSet.click(function() {
linkSet.toggle();
});
});
});
The add method allows you to add a different selector to the set of matchers, thus binding both clicks simultaneously. By saving the constructed set to a variable (linkSet), it stops you from having to traverse the DOM twice.
The only two assumption made here, are
1) That in the initial state only one is visible.
2) That the id structure is meaningful, useful, and classes will not suffice.
http://jsfiddle.net/cuJBm/1/
To answer your second question about setting an attribute on #frame. There are numerous ways of doing this. Perhaps the simplest is to add the following to your .click handler (after the toggle).
if ($(this).attr('id')=='link1'){
$('#frame').attr('src', 'www.google.com');
} else if ($(this).attr('id')=='link2'){
$('#frame').attr('src', 'www.yahoo.com');
}
Personally, I would probably add a custom attribute to your link elements, something like:
<a id='link1' iframe-source='www.google.com'>
<a id='link2' iframe-source='www.yahoo.com'>
And then: (again, just after the toggle):
source = $(this).attr('iframe-source');
$('#frame').attr(src, source);
The reason for saving source if is that if you attempt to get $(this) within the .attr on $('frame'), it will (as always) return the currently matched element, ie $('#frame').
Alternately (and very similiarly to the above approach), you could use the innerHTML of the link. For example:
<a id='link1'>link1<span style="display:none">www.google.com</span></a>
<a id='link2'>link2<span style="display:none">www.yahoo.com</span></a>
And then: (again, just after the toggle):
source = $(this).find('span').text();
$('#frame').attr(src, source);
Personally, I dislike this last method as it pollutes the DOM structure, leading to slightly more expensive rendering times, and (in my opinion) less readable code. Practically, all three methods work just fine.
<p class="link" style="display:none;" data-link="http://google.com/">sfdf</p>
<p class="link" data-link="http://yahoo.com/">ee</p>
$('.link').click(function() {
$('.link').toggle();
$('#frame').text($(this).data("link"));
});
jsfiddle :http://jsfiddle.net/xqDus/1/
Use jQuery toggle()
just add this
Google
Yahoo
target is id of the frame
$(function() {
$('#link1, #link2').click(function() {
$('#link1, #link2').toggle();
});
});

How to get Information about an element without a callback

I have different container that get reloaded on different events. I have plenty of them, so I gave each container the class load.
This is how all of them look like:
<div class="load" data-href="facebook">
</div>
I also have a function, that is triggered by various actions:
function get_timing(time)
{
$(".load").load("myfolder/mod_"+$(this).attr("data-href")+".php?action="+time, function() {
alert('Here I could use this:' + $(this).attr("data-href"));
}
}
I know that I cannot use this in the example above, I could only use it in the callback. My question is: How can I use attributes of the object to define the path of the load function.
This is how it could work:
function get_timing(time)
{
$(".load").fadeIn(10, function()
{
$(this).load("myfolder/mod_"+$(this).attr("data-href")+".php?action="+time, function() {
alert('loaded');
}
}
}
Is there a way to do this without the asynchronus function (in this case .fadIn) around)
Hope I could explain my problem - thank you in advance!
If you want to go along with classes you can reference them via an index:
var element = $(".load").get(0);
console.log($(element).attr("data-href"));
Note that you have to re-jQueryfy element via $(element) in order to access attr()
If you want to read out all elements with a given class I recommend $.each()
//$.each($(".load"), function(index, value){
$(".load").each(function(index, value){
console.log( $(value).attr("data-href"));
});
Try to give your container an id:
<div class="load" data-href="facebook" id="facebookcontainer">
</div>
Then instead of using this, you can use $("#facebookcontainer") in your javascript.

How do get a parent node without having a starting reference point?

I want to provide a method for my web app that allows a user to call my function anywhere within his code (inside script tags) that will display a fade-in/fade-out message. What I don't know how to do is determine where I am at in the DOM without having a starting reference point.
Function:
function displayMessage(message) {
// Display a notification if the submission is successful.
$('<div class="save-alert">' + message + '</div>')
.insertAfter($('')) // Do not know how to know where to put the message.
.fadeIn('slow')
.animate({ opacity: 1.0 }, 2000)
.fadeOut('slow', function () {
$(this).remove();
});
}
The HTML:
<!-- Some HTML -->
<div>
<script type="text/javascript">
displayMessage("My message.");
</script>
</div>
<!-- Some more HTML. -->
There isn't any reliable way to get this information. You should do what most other libraries do -- have the user pass in the ID or reference of an element to your displayMessage function so that you can use it.
Generally there are two ways, one, as Casablanca noted you provide a div in the DOM to append the message. Second, and this is the one I think you want, is to create a div node on the DOM itself. That way you have total control. After all it is going to fade out when you're done. Might as well kill it from the dom as well. This is what fancylightbox (and I am sure many others) does with the DOM. You'd want to place it right at the beginning of the body, so there are no other containing elements, and style it as you wish - likely so it floats somewhere near the middle of the page like a lightbox/dialog box.
Unless you want to take in a css selector or an id as argument there is also an alternative to create a jQuery widget. This way you can use it like:
$("#msgArea").messageWidget("displayMessage");
or even reuse it many times
$("#msgArea").messageWidget("displayMessage", "message to display");
Sample boilerplate widget:
(function( $ ) {
$.widget("ui.messageWidget", {
// default options
options: { message: undefined},
// constructor
_create: function() {
if (this.options.message !== undefined) {
this.displayMessage(this.options.message);
}
},
// Displays the message
displayMessage: function() {
this.element.append("your div's and messages");
},
// Allows constructor/setter arguments
_setOption: function( key ) {
$.Widget.prototype._setOption.apply( this, arguments );
}
});
}(jQuery));
You probably want to use fixed positioning to put your box at a place relative to the browser's viewport, regardless of where a user has scrolled to in the document.

Categories

Resources