javascript function vs jquery namespace function, the difference? - javascript

How come a javascript function like this below...
function stars() {
var mOpacity = $('#area').css('opacity');
if (mOpacity = 1) {
$('#title').find('.stars').animate({"marginTop":"-170px",opacity:1}, 3000)
.animate({opacity: 0}, 400)
.animate({"marginTop":"60px",opacity:0},0, stars);
}
}
stars();
...breaks my browser when I try to do something like this....
$.stars = function() {
var mOpacity = $('#area').css('opacity');
if (mOpacity = 1) {
$('#title').find('.stars').animate({"marginTop":"-170px",opacity:1}, 3000)
.animate({opacity: 0}, 400)
.animate({"marginTop":"60px",opacity:0},0, $.stars());
}
}
$.stars();
What is the lesson here between the 2 styles of functions?
Thanks
Ok based on everyones feedback to see more code, here is a full gimplse of the code on my .js file...
function mIntro() {
/********PRE-GAME ANIMATION*********/
$('#area').css({'opacity':0}).delay(1000).animate({opacity:1},300);
$('#title').find('.age').css({'opacity':0}).delay(2000).animate({opacity:1}, 3000);
function stars() {
var mOpacity = $('#area').css('opacity');
if (mOpacity = 1) {
$('#title').find('.stars').animate({"marginTop":"-170px",opacity:1}, 3000)
.animate({opacity: 0}, 400)
.animate({"marginTop":"60px",opacity:0},0, stars);
}
}
stars();
}
$(function() {
mIntro();
});
I have jquery connected to this .js page and I just can't understand why stars has to be in-cased in a traditional javascript function and not flexibile for a jquery namespace function. I bet it has something to do with the animate tag that re-calls stars, but I am not sure...
Thanks or any advice!!!

You're inadvertently calling it in the second snippet:
.animate(..., $.stars());
You should code it the same way: pass the function, not the result of calling it:
Function: stars $.stars
Result of calling: stars() $.stars()

The difference is that your first example is contained directly within the window object whereas the second example is contained in the jQuery ($) object (note that the $ object is then contained within the window object). As far as why it breaks when you attempt to use the jQuery namespace, I cant say without seeing all of your code, however $ is probably not defined.

Related

Using a click event to have a menu appear - but not working with new code with Knockout and Jquery

Previously I had this code that was working to spoof a click event in a knockout method.
self.addProductToCart = function(data) {
var $productNotification = $(".product-notification");
ax.Cart.addCartItem({product_id:data.id, name:data.name, description:data.description});
$productNotification.slideDown(1000).fadeOut(200, function() { $('#cart-nav a.first').click();});};
Now they want to use css3 to animate so I took that the slideDown method out and replaced it with this and it's not working. I am probably missing something stupid here. Thank you
self.addProductToCart = function(data) {
var $productNotification = $(".product-notification");
ax.Cart.addCartItem({product_id:data.id, name:data.name, description:data.description});
$('body').addClass("test");
(function() { $('#cart-nav a.first').click();});};
As Roy J stated in the comments, you have an anonymous function that is not executing. It doesn't even appear that the anonymous function is necessary. Try changing this line:
(function() { $('#cart-nav a.first').click();});};
To this:
$('#cart-nav a.first').click();

Convert String to Function in Javascript

I have a little problem with creating a new function from a string.
The example: I have a div, and some buttons. One of the buttons just make my div animating, nothing else. But the other button make the div animating and after the animation is complete, call a new function.
I have to handle the new, following function as a variable, because there will be a lot of function I have to call after the div animated.
Here is an example I made: http://jsfiddle.net/AmVSq/3/. I hope you can understand my problem.
I found the new Function(); in JavaScript but it just left me in doubt and the JS console did not log anything.
Can somebody tell me what am I doing wrong?
Thank you so much..
In JavaScript, functions are "first class" objects. This means you can assign them to variables and pass them to other functions as parameters.
There is no need to create a function from a string when you can pass the function name itself, like so:
<div>Close Div then do something</div>
and the script:
function close_div( next_function ) {
$('#wrap').animate({ 'height': '-=100px' }, 300, function() {
if ( next_function ) {
// do the following function
next_function();
}
});
}
--- jsFiddle DEMO ---
In fact, for your purposes, you can simply pass next_function right along to the animate function, like this:
function close_div( next_function ) {
$('#wrap').animate({ 'height': '-=100px' }, 300, next_function);
}
There's no need to check if next_function is undefined, because .animate will do that for you.
What you're doing wrong is using new Function at all. The correct way is to just pass the function, which are objects like anything else in JavaScript:
http://jsfiddle.net/minitech/AmVSq/6/
<div>Close Div</div>
<div>Close Div then do something</div>
<div>Close Div then do another thing</div>
<div id="wrap"></div>​
function close_div( next_function ) {
$('#wrap').animate({ 'height': '-=100px' }, 300, function() {
if(next_function) {
next_function();
}
});
}
function alert_me() {
alert( 'The animation is complete' );
}
function confirm_me() {
confirm('Are you sure?');
}
Or, more concisely, $('#wrap').animate({height: '-100px'}, 300, next_function);.
The chrome console displays the result properly:
> f = new Function("alert('hello');");
function anonymous() {
alert('hello');
}
> f(); //executes it.
But using string to create function, or passing strings to functions to execute it is really bad practice.
function test(callback) {
callback();
}
test(function() { alert("hello"); });
You don't need to make the function into a string, you can pass functions as arguments to other functions in Javascript.
For example:
function get_message1() {
return "hello world";
}
function get_message2() {
return "yay for first-class functions";
}
function print_message(message_func) {
console.log(message_func())
}
print_message(get_message1);
print_message(get_message2);

jQuery: Call a function twice

I'm trying to run a function twice. Once when the page loads, and then again on click. Not sure what I'm doing wrong. Here is my code:
$('div').each(function truncate() {
$(this).addClass('closed').children().slice(0,2).show().find('.truncate').show();
});
$('.truncate').click(function() {
if ($(this).parent().hasClass('closed')) {
$(this).parent().removeClass('closed').addClass('open').children().show();
}
else if ($(this).parent().hasClass('open')) {
$(this).parent().removeClass('open').addClass('closed');
$('div').truncate();
$(this).show();
}
});
The problem is on line 13 where I call the truncate(); function a second time. Any idea why it's not working?
Edit jsFiddle here: http://jsfiddle.net/g6PLu/
That's a named function literal.
The name is only visible within the scope of the function.
Therefore, truncate doesn't exist outside of the handler.
Instead, create a normal function and pass it to each():
function truncate() { ...}
$('div').each(truncate);
What's the error message do you get?
You should create function and then call it as per requirement
Define the function
function truncate(){
$('div').each(function(){
});
}
Then call the function
truncate();
Another approach is to establish, then trigger, a custom event :
$('div').on('truncate', function() {
$(this).......;
}).trigger('truncate');
Then, wherever else you need the same action, trigger the event again.
To truncate all divs :
$('div').trigger('truncate');
Similarly you can truncate just one particular div :
$('div#myDiv').trigger('truncate');
The only prerequisite is that the custom event handler has been attached, so ...
$('p').trigger('truncate');
would do nothing because a truncate handler has not been established for p elements.
I know there's already an accepted answer, but I think the best solution would be a plugin http://jsfiddle.net/g6PLu/13/ It seems to be in the spirit of what the OP wants (to be able to call $('div').truncate). And makes for much cleaner code
(function($) {
$.fn.truncate = function() {
this.addClass('closed').children(":not('.truncate')").hide().slice(0,2).show();
};
$.fn.untruncate = function() {
this.removeClass('closed').children().show();
};
})(jQuery);
$('div').truncate();
$('.truncate').click(function() {
var $parent = $(this).parent();
if ($parent.hasClass('closed')) {
$parent.untruncate();
} else {
$parent.truncate();
}
});

Javascript different variable scope on AJAX call

I have a problem with my variable scope in a simple slider script that I´ve written (I don't want to use a readymade solution because of low-bandwidth). The slider script is called on statically loaded pages (http) as well as on content loaded through AJAX. On the statically loaded page (so no AJAX) the script seems to work perfect. However when called through AJAX the methods called can't find the elements of the DOM, which halts the necessay animation that is needed for the slider.
All the events are handled through even delegation (using jQuery's on() function), this however provided no solution. I'm quite sure it has something to do with the structure and variable scope of the script, but am unable to determine how to change the structure. So I'm looking for a solution that works in both situations (called normal or through AJAX).
I tried to declare the needed variables in every function, this however resulted in some akward bugs, like the multiplication of the intervals I set for the animation, because of the function scope. Hope somebody can help me in the right direction.
// Slider function
(function (window, undefined) {
var console = window.console || undefined, // Prevent a JSLint complaint
doc = window.document,
Slider = window.Slider = window.Slider || {},
$doc = $(doc),
sliderContainer = doc.getElementById('slider_container'),
$sliderContainer = $(sliderContainer),
$sliderContainerWidth = $sliderContainer.width(),
slider = doc.getElementById('slider'),
$slider = $(slider),
$sliderChildren = $slider.children(),
$slideCount = $sliderChildren.size(),
$sliderWidth = $sliderContainerWidth * $slideCount;
$sliderControl = $(doc.getElementById('slider_control')),
$prevButton = $(doc.getElementById('prev')),
$nextButton = $(doc.getElementById('next')),
speed = 2000,
interval,
intervalSpeed = 5000,
throttle = true,
throttleSpeed = 2000;
if (sliderContainer == null) return; // If slider is not found on page return
// Set widths according to the container and amount of children
Slider.setSliderWidth = function () {
$slider.width($sliderWidth);
$sliderChildren.width($sliderContainerWidth);
};
// Does the animation
Slider.move = function (dir) {
// Makes use of variables such as $sliderContainer, $sliderContainer width, etc.
};
// On ajax call
$doc.on('ajaxComplete', document, function () {
Slider.setSliderWidth();
});
// On doc ready
$(document).ready(function () {
Slider.setSliderWidth();
interval = window.setInterval('Slider.move("right")', intervalSpeed);
});
// Handler for previous button
$doc.on('click', '#prev', function (e) {
e.preventDefault();
Slider.move('left');
});
// Handler for next button
$doc.on('click', '#next', function (e) {
e.preventDefault();
Slider.move('right');
});
// Handler for clearing the interval on hover and showing next and pervious button
$doc.on('hover', '#slider_container', function (e) {
if (e.type === 'mouseenter') {
window.clearInterval(interval);
$sliderControl.children().fadeIn(400);
}
});
// Handler for resuming the interval and fading out the controls
$doc.on('hover', '#slider_control', function (e) {
if (e.type !== 'mouseenter') {
interval = window.setInterval('Slider.move("right")', intervalSpeed);
$sliderControl.children().fadeOut(400);
}
});
})(window);
The HTML example structure:
<div id="slider_control">
<a id="next" href="#next"></a>
<a id="prev" href="#prev"></a>
</div>
<div id="slider_container">
<ul id="slider">
<li style="background-color:#f00;">1</li>
<li style="background-color:#282">2</li>
<li style="background-color:#ff0">3</li>
</ul>
</div>
I notice you have
Slider.setSliderWidth = function() {
$slider.width($sliderWidth);
$sliderChildren.width($sliderContainerWidth);
};
which is called on ajax complete.
Does you ajax update the DOM giving a new DOM element that you could get to by doc.getElementById('slider')? Then your var slider and jquery var $slider are likely pointing to things that no longer exist (even if there is a dom element with slider as the id). To rectify, whenever the ajax is invoked that replaces that element, reinitialize slider and $slider to point to the new jquery wrapped element using the same initialization you have.
slider = doc.getElementById('slider');
$slider = $(slider);
Edit:
I'm not sure where you're going with the variable scope issue, but take a look at this example.
<pre>
<script>
(function(){
var a = "something";
function x (){
a += "else";
}
function y() {
a = "donut";
}
function print (){
document.write(a +"\n");
}
print ();
x();
print ();
y();
print ();
x();
print ();
})();
document.write(typeof(a) + "\n");
</script>
</pre>
It outputs into the pre tag
something
somethingelse
donut
donutelse
undefined
This isn't all that different from what you're already doing. As long as a is not a parameter of a method and is not declared with var in a nested scope, all references to a in code defined within your function(window,undefined){ ...} method will refer to that a, given that a is defined locally by var to that method. Make sense?
To begin, surely you can replace all the getElementById using a jQuery approach. i.e. replace $(doc.getElementById('next')) with $('#next')
I think that when you use on it doesn't search the element for the selector as you are assuming. So you would have to use:
$doc.on('click', '#slider_control #prev',function(e){
e.preventDefault();
Slider.move('left');
});
Wait, what gets loaded through Ajax? The slider-html code? In that case, the Slider has already been 'created' and a lot of your variables will point to nowhere (because these DOM elements did not existed when the variables were initialized). And they will never do so either.

Why is this javascript function not defined?

I have this javascript code:
$(function(){
var currentCarouselItem = 1; //set carousel to first slide
var runCarousel = 1;
$(window).load(function(){
setTimeout('autoScroll()', 10000);
});
function autoScroll(num){
if (runCarousel == 1) {
$('.carouselItem.' + currentCarouselItem).animate({left: '975px'}, 'slow', function(){
$(this).removeClass('active');
$(this).attr('style','');
var nextItem = currentCarouselItem + 1;
if (nextItem == 7) {
nextItem = 1;
}
$('.carouselItem.' + nextItem).animate({left: '110px'}, 'slow', function(){
$(this).addClass('active');
})
})
}
}
})
Whenever I run the site it throws a console error: Uncaught ReferenceError: autoScroll is not defined
Any idea why it thinks it is not defined?
setTimeout('autoScroll()', 10000);
Why put it in quotes?
setTimeout(autoScroll, 10000);
That's for starters.
Additionally, you have scoping issues here.
I could try answering it for you, but I think this guy does a lot better job:
JQuery, setTimeout not working
I think this is because your autoScroll function is inside closure created by outermost $(function(){}). Therefore eval (used to evaluate your string in setTimeout) can't find it, as it runs in a 'global' scope.
You can move the definition of autoScroll outside.
Also, as jcolebrand suggested, remove quotes.
I think it is because when you pass in a string as the first argument for setTimeout() that javascript basically runs eval() from the global scope on that string. autoScroll lives within the scope of $(function() { }) and therefore can't be "seen" from the global scope.
Try changing it to setTimeout(autoScroll, 10000);
There a couple of problems with your code, but the reason that the autoScroll function is not defined is that it defined within the scope of your document ready function, but is executed via eval after the document ready has gone out of scope without the proper closure.
$('.carouselItem.' + currentCarouselItem).animate({left: '975px'}, 'slow', function(){
$(this).removeClass('active');
$(this).attr('style','');
var nextItem = currentCarouselItem + 1;
if (nextItem == 7) {
nextItem = 1;
}
$('.carouselItem.' + nextItem).animate({left: '110px'}, 'slow', function(){
$(this).addClass('active');
});
});
For starters you need a semi colon at the end of functions like this,

Categories