I'm trying to figure out how this custom jQuery functions work by experimenting a bit. I can't however get it to work properly. I'm trying to call the prepareSlide function in my setInterval but it says prepareSlide is not defined
$('document').ready(function(){
jQuery('.item_holder').itemSlider({
start: 1,
carousel: true
});
});
$.fn.itemSlider = function (details) {
var currentSlideNumber = (details && details.start > 0) ? details.start : 1;
this.prepareSlide = function(slideNumber) {
alert(1)
}
//Set an interval
var itemToSlide = currentSlideNumber + 1;
slideTimer = setInterval("prepareSlide(" + itemToSlide + ")", 5000);
}
You should provide a function to the first argument of setInterval. Also, to provide the context properly to the function invocation, a quick method is to preserve this by having another variable reference it, which in this case, we call self
var self = this;
slideTimer = setInterval(function(){
self.prepareSlide(itemToSlide)
}, 5000);
Related
I want to be able to increment/change the value of a parameter inside an object. I want the value to change by accessing the value of a variable that is incrementing inside another function.
The example code below shows what I am trying to do. I would like options.number to increase as i inside masterLoop increases.
I know that i isn't defined in the scope of function calc(), but I can't think of a way to retrieve the value of i while maintaining this general code structure.
(function masterLoop(i) {
setTimeout(function() {
++i;
masterLoopStage = i;
console.log('Stage is: ' + i);
masterLoop(i);
}, 5000)
})(1);
function calc() {
number = i; // I know i isn't defined in this scope, but I can't figure out how access the incrementing value of i inside this function
return number;
}
var options = {
number: calc() // I want this vale to increase along with i inside masterLoop()
};
setInterval(function() {
console.log(options.number);
}, 5000);
Typically, in cases like this, I would try to use a return to retrieve a value, but I wasn't able to find a solution with that either since the incrementing value is inside a setInterval and thus its scope isn't available to the return.
Here is an example of that:
function calc() {
var foo = 1;
setInterval(function() {
var foo = foo + 1;
}, 1000);
return foo; // the incrementing value of foo is not available outside the scope of setIterval, so this won't work. The return also won't work inside setInterval.
}
var optionsConstant = {
maxVolume: 10
};
var options = {
maxVolume: optionsConstant.maxVolume + calc() // I want calc() to be able to increment along with foo in the setInterval above.
};
setInterval(function() {
var maxVolume = options.maxVolume;
console.log('maxVolume: ' + maxVolume);
}, 5000);
Taking your second attempt, you could make calc an immediately invoked function expression -- providing a closure -- and in it return a function that has access to foo.
Then, to keep the final syntax of options.maxVolume, you should define that property as a getter, so that in fact it will execute some code when accessed, calling calc():
var calc = (function () { // create closure for foo
var foo = 1;
setInterval(function() {
foo = foo + 1; // remove var!
}, 100);
return function calc() { // return a function
return foo;
}
})();
var optionsConstant = {
maxVolume: 10
};
var options = {
get maxVolume() { // make it a getter
return optionsConstant.maxVolume + calc();
}
};
setInterval(function() {
var maxVolume = options.maxVolume;
console.log('maxVolume: ' + maxVolume);
}, 500);
Can you declare the increment variable outside the masterloop function scope so the other functions can access it and read its' value when needed?
You'll need to make sure to re-initialize it's value when appropriate.
I think you need to use a closure. Here's one example:
let returnI = (function masterLoop(i) {
setTimeout(function() {
++i;
masterLoopStage = i;
console.log('Stage is: ' + i);
return masterLoop(i);
}, 5000)
})(1);
function calc() {
number = returnI;
return number;
}
var options = {
number: calc()
};
setInterval(function() {
console.log(options.number);
}, 5000);
As below code, I make an object named "test", and give it properties and method.
The property came from its argument.
And I try to call the method every 2 sec after onload, and the result shows undefined.
But if I only call the method not using setInterval(), like this
window.onload = function() {
giveword.showWord();
}
I'll be able to show the text "Hi".. Why is that?
var giveword = new test("Hi");
function test(word) {
this.word = word;
}
test.prototype.showWord = function() {
document.getElementById("msg_box").innerHTML = this.word;
}
window.onload = function() {
setInterval(giveword.showWord, 2000);
}
Thanks for help...
The reason is because in your test.prototype.showWord function your this object is referring to the context in which the function is called, which is the window object when called from setInterval.
I think what you want to do is use a closure to make the context of showWord() be the giveword instance like this:
var giveword = new test("Hi");
function test(word) {
this.word = word;
}
test.prototype.showWord = function() {
document.getElementById("msg_box").innerHTML = this.word;
}
window.onload = function(){
setInterval(function(){giveword.showWord();}, 2000); // <<-- here's the closure
}
The difference is that with the closure you're telling the setInterval function to call a function within the context as it was when the setInterval was declared. When setInterval was declared there was a variable in scope called giveword that had a method showWord() that returns the value of your initial input. (Closures are hard to explain, and I'm afraid you'd be best served by someone else explaining them if you need more info.)
This solution this now so easy, use an arrow function in setInterval. Here is an example using setInterval inside of an object method.
const mobile = {
make: 'iPhone',
model: 'X',
battery: 10,
charging: false,
charge: function() {
if(this.battery < 100) {
this.charging = true;
console.info('Battery is charging...');
let interval = setInterval(() => {
this.battery = this.battery + 10;
console.info(mobile.battery);
if( this.battery === 100){
this.charging = false;
clearInterval(interval);
console.info('Battery has finished charging.');
}
}, 100);
}
else {
console.info('Battery does not need charging.');
}
}
}
I am passed 3 html elements as parameters to JS function. JS function is in separate file. I have problem to bind 'click' event with _confBtn object (which is parameter). My complete JS file:
window.HAS = window.HAS || {};
HAS.MyApp = HAS.MyApp || {};
(function (_this, $, undefined) {
var _sessionTimeOut = false;
var _startCountDown = false;
var _counterTime;
var _countDownTime;
var _dialogWrap;
var _confBtn;
var _counter;
_this.init = function (showDialogTime, logofCountDownTime, dialogWrap, counter, confirmationButton) {
_counterTime = 5;
_countDownTime = 0;
_dialogWrap = $('#' + dialogWrap);
_confBtn = $('#' + confirmationButton);
_counter = $('#' + counter);
alert(_confBtn.text());
createSessionTimeOut();
$(document).bind("mousemove keypress mousedown mouseup", resetTimeOut);
}
_confBtn.on('click', function () {
window.clearInterval(_startCountDown);
_dialogWrap.css('visibility', 'hidden');
createSessionTimeOut();
$(document).bind("mousemove keypress mousedown mouseup", resetTimeOut);
});
function createSessionTimeOut() {
_sessionTimeOut = window.setTimeout(function () {
_dialogWrap.removeAttr("style");
_counter.text(_counterTime);
$(document).unbind("mousemove keypress mousedown mouseup");
startCountDown();
}, 2000);
}
function startCountDown() {
_startCountDown = window.setInterval(function () {
if (_counterTime >= 0) {
_counter.text(_counterTime--);
}
_countDownTime++;
if (_countDownTime >= 4) {
logOutUser();
return;
}
}, 1000);
}
function resetTimeOut() {
window.clearTimeout(_sessionTimeOut);
_sessionTimeOut = false;
createSessionTimeOut();
}
function logOutUser() {
$.ajax({
url: '/MyApp/Account/LogOut',
type: 'GET',
success: function () {
document.location.href = '/MyApp/Account/Login';
}
})
}
}(window.HAS.MyApp.SessionTimeOut = window.HAS.MyApp.SessionTimeOut || {}, jQuery));
I call in separate page like in following:
SessionTimeOut.init('5', '5', 'dialog-wrap', 'confirm-button', 'counter');
I have issue with _confBtn when I try to call click event. Browser show that is undefined.
Please help.
It would probably better to do something more dynamic like this:
function SomeFunction (element1,element2) {
var e1 = $("#"+element1),
e2 = $("#"+element2);
// Do something with variables e1 and e2
}
and you would call like this:
//html:
<div id="one"><div>
<div id="two"><div>
//javasctript:
SomeFunction('one','two');
No, you are mixing a function declaration with a function call somehow. You can't provide function arguments when defining a function. This however will work fine:
function someFunction($element1, $element2) {
//Do something with the elements
}
someFunction($("#element1"), $("#element2"));
Note that $element1 and $element2 are just variable names, and the leading $ doesn't have anything to do with jQuery. It is just a common convention to identify variables referencing jQuery selections.
You can of course do it, just by using the normal jQuery way of including multiple selectors. Your code is slightly incorrect because you are actually only defining the function without calling it, and you are not supposed to pass arguments/variables into the function when defining it.
Unless you have the intention to distinguish between two groups of elements, I would refrain from declaring elements individually as you have used in your question, because sometimes you will never know the length of the selected items.
function someFunction($ele) {
// jQuery objects will be accessible as $ele
}
// Call the function
someFunction($('#selector1, #selector2'));
However, if the former is the case, you can always do so:
function someFunction($ele1, $ele2) {
// jQuery objects will be accessible as $ele1 and $ele2 respectively
// Example: $ele1.hide();
// $ele2.show();
}
// Call the function
someFunction($('#selector1'), $('#selector2'));
For example, you can refer to this proof-of-concept JSfiddle: http://jsfiddle.net/teddyrised/ozrfLwwt/
function someFunction($ele) {
// jQuery objects will be accessible as $ele
$ele.css({
'background-color': '#c8d9ff'
});
}
// Call the function
someFunction($('#selector1, #selector2'));
If you want to pass some elements to function you can use jQuery constructor to standardize arguments
function SomeFunction (element1,element2) {
element1 = $(element1);
element2 = $(element2);
// and you have 2 jQuery objects...
}
// and now you can pass selector as well as jQuery object.
SomeFunction($('div.a'),'#b');
You can pass paramters as much as you want this way. I use jQuery in this code and created a simple function.
var item=$("#item-id");
var item1=$("#item1-id");
makeReadOnly(item,item1);
function makeReadOnly(){
for(var i=0;i<arguments.length;i++){
$(arguments[i]).attr("readonly", true);
}
}
I'v got code that checks current position of right top corner of some element:
function checkContentPos(e) {
var positionLeft = 0,
checkTabPos = null,
pos;
e = $(e).filter('li');
alert($(e).attr('class'));
//alert($(e).attr('class'));
checkTabPos = setInterval(
function () {
ii++;
debug(ii);
pos = $(e).offset();
pos['left'] += parseInt($(e).css('width'));
positionLeft = pos.left;
debug(positionLeft);
}, 40);
function stopCheckTabPos() {
debug('stopCheckTabPos invoked')
clearInterval('checkTabPos');
}
setTimeout(stopCheckTabPos, 400);
return(positionLeft);
};
But I looks like its looped to instanity. After setTimeout it's still constantly invoked.
clearInterval('checkTabPos');
Don't use quotes here. How would that even work? You need to pass in the identifier returned by setInterval, not some arbitrary string.
You're invoking clearInterval with the string 'checkTabPos' when you should be using it with the variable
function stopCheckTabPos() {
debug('stopCheckTabPos invoked')
clearInterval(checkTabPos);
}
I am totally stumped here.
I have a bunch of messages, each within a div "msg_feed_frame_$i" which increases, so message 1 is in div "msg_feed_frame_1", msg 2 is in "msg_feed_frame_2", etc etc. I want to fade these messages in one by one using jquery, but for some reason no matter what I do with settimeout and setinterval, the code immediately fades them all in simultaneously.
This is what i've got so far:
function feed(i)
{
var div = "#msg_feed_frame_";
var fader = div.concat(i);
$(fader).fadeIn(2000);
}
function timefade()
{
var num = 1;
for (num=1; num<=10; num++)
{
var t=setTimeout(feed(num),1000);
}
}
$(document).ready(function(){
timefade();
});
Your problem is that the for loop executes quickly and sets a timeout 1000ms from now for each function call. Here's one way you could remedy this:
function feed(i) {
var div = "#msg_feed_frame_";
var fader = div.concat(i);
$(fader).fadeIn(2000);
}
function timefade() {
var num = 1;
var fadeIt = function(i) {
return function() { feed(i); };
};
for (num = 1; num <= 4; num++) {
var t = setTimeout(fadeIt(num), num * 1000);
}
}
$(document).ready(function() {
timefade();
});
Additionally, your original code was passing setTimeout the results of the feed(i) function call (undefined), and it expects an object of type function. I added a helper function that returns a reference to a function that will call feed with the correct argument.
Capturing the value of num inside a function is called a closure, and it can be confusing at first. Check this post out for some good explanations of closures inside loops and while they're necessary.
Here's your example, working: http://jsfiddle.net/andrewwhitaker/tpGXt/
Try using jQuery's .delay() function...
function feed(i){
var div = "#msg_feed_frame_";
var fader = div.concat(i);
$(fader).fadeIn(2000).delay(1000);
}
function timefade(){
var num = 1;
for (num=1; num<=10; num++){
feed(num);
}
}
$(document).ready(function(){
timefade();
});