Allow chaining in jQuery plugin - javascript

it's been a long day and I can't seem to figure out why one of my custom jQuery plugins won't chain.
What i'm trying to do is write a line of characters out one at a time in an element then when done remove the text then write the next line
The plugin:
(function($) {
$.fn.writeDialogue = function(content) {
var contentArray = content.split(""),
current = 0,
elem = this,
write = setInterval(function() {
if(current < contentArray.length) {
elem.text(elem.text() + contentArray[current++]);
} else {
clearInterval(write);
return this;
}
}, 100);
};
})(jQuery);
Pretty much i'm trying to chain it in this way:
$('#element').writeDialogue(textLine1).empty().writeDialogue(textLine2);
Can't get it to work, any ideas?

This is because your code is async. so you have to move return this:
(function($) {
$.fn.writeDialogue = function(content) {
var contentArray = content.split(""),
current = 0,
elem = this,
write = setInterval(function() {
if(current < contentArray.length) {
elem.text(elem.text() + contentArray[current++]);
} else {
clearInterval(write);
}
}, 100);
return this; // THERE
};
})(jQuery);

Related

clearinterval() outside of jquery plugin

I create plugin something like this
timer plugin
(function($) {
$.fn.timer = function(options) {
var defaults = {
seconds: 60
};
var options = $.extend(defaults, options);
return this.each(function() {
var seconds = options.seconds;
var $this = $(this);
var timerIntval;
var Timer = {
setTimer : function() {
clearInterval(timerIntval);
if(seconds <= 0) {
alert("timeout");
}else {
timerIntval = setInterval(function(){
return Timer.getTimer();
}, 1000);
}
},
getTimer : function () {
if (seconds <= 0) {
$this.html("0");
} else {
seconds--;
$this.html(seconds);
}
}
}
Timer.setTimer();
});
};
})(jQuery);
and I call the plugin like this.
$(".myTimer").timer({
seconds : 100
});
i called the plugin at timerpage.php. When i changed the page to xxx.php by clicking another menu, the timer interval is still running and i need to the clear the timer interval.
i created a webpage using jquery ajax load. so my page was not refreshing when i change to another menu.
my question is, how to clear the timer interval or destroy the plugin when i click another menu?
Please try with following modifications:
timer plugin:
(function($) {
$.fn.timer = function(options) {
var defaults = {
seconds: 60
};
var options = $.extend(defaults, options);
return this.each(function() {
var seconds = options.seconds;
var $this = $(this);
var timerIntval;
var Timer = {
setTimer : function() {
clearInterval(timerIntval);
if(seconds <= 0) {
alert("timeout");
}else {
timerIntval = setInterval(function(){
return Timer.setTimer();
}, 1000);
$this.data("timerIntvalReference", timerIntval); //saving the timer reference for future use
}
},
getTimer : function () {
if (seconds <= 0) {
$this.html("0");
} else {
seconds--;
$this.html(seconds);
}
}
}
Timer.setTimer();
});
};
})(jQuery);
Now in some other JS code which is going to change the div content
var intervalRef = $(".myTimer").data("timerIntvalReference"); //grab the interval reference
clearInterval(intervalRef); //clear the old interval reference
//code to change the div content on menu change
For clearing timer associated with multiple DOM element, you may check below code:
//iterate ovel all timer element:
$("h3[class^=timer]").each(function(){
var intervalRef = $(this).data("timerIntvalReference"); //grab the interval reference
clearInterval(intervalRef);
});
Hope this will give an idea to deal with this situation.
Instead of var timerIntval; set the variable timerInterval on the window object, then you will have the access this variable until the next refresh.
window.timerIntval = setInterval(function() {
Then when the user clicks on any item menu you can clear it:
$('menu a').click(function() {
clearInterval(window.timerIntval);
});
Live example (with multiple intervals)
$('menu a').click(function(e) {
e.preventDefault();
console.log(window.intervals);
for (var i = 0; i < window.intervals.length; i++) {
clearInterval(window.intervals[i]);
}
});
(function($) {
$.fn.timer = function(options) {
var defaults = {
seconds: 60
};
var options = $.extend(defaults, options);
return this.each(function() {
if (!window.intervals) {
window.intervals = [];
}
var intervalId = -1;
var seconds = options.seconds;
var $this = $(this);
var Timer = {
setTimer : function() {
clearInterval(intervalId);
if(seconds <= 0) {
alert("timeout");
} else {
intervalId = setInterval(function(){
//Timer.getTimer();
return Timer.getTimer();
}, 1000);
window.intervals.push(intervalId);
}
},
getTimer : function () {
if (seconds <= 0) {
$this.html("0");
} else {
seconds--;
$this.html(seconds);
}
}
}
Timer.setTimer();
});
};
})(jQuery);
$(".myTimer").timer({
seconds : 100
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<menu>
Menu 1
</menu>
<div class="myTimer"></div>
<div class="myTimer"></div>
Just notice that it's little bit risky because you can only run it once otherwise the interval id of the second will override the first.

Dots for Children in div. A jQuery headache - PART 2

So this is part 2 of my previous question (was advised to start a new question for this one).Just for reference here is my previous post: Dots for Children in div. A jQuery headache
My question now is: How does one go about adding an "active" class/id to the "imgdots" div for styling purposes?For example:Say I'm on image 4 then I want the 4th "imgdots" div to be another colour.Again, any help would be much appreciated! EDITI have set up a fiddle containing what I have thus far. The initial image slider was from a tutorial I followed and kinda pieced it all together from there. Here is the link: jsfiddle.net/Reinhardt/cgt5M/8/
Have you seen nth child css?
http://www.w3schools.com/cssref/sel_nth-child.asp
#showContainer:nth-child(4)
{
background:#ff0000;
}
Try
/* The jQuery plugin */
(function ($) {
$.fn.simpleShow = function (settings) {
var config = {
'tranTimer': 5000,
'tranSpeed': 'normal'
};
if (settings) $.extend(config, settings);
this.each(function () {
var $wrapper = $(this),
$ct = $wrapper.find('.showContainer'),
$views = $ct.children();
var viewCount = $views.length;
var $imgdotholder = $('<div class="imgdotholder"></div>').appendTo('.wrapper');
for (var i = 0; i < viewCount; i++) {
$('<div class="imgdots"></div>').appendTo($imgdotholder);
}
var $imgdots = $imgdotholder.children();
var timer, current = 0;
function loop() {
timer = setInterval(next, config.tranTimer);
}
function next(idx) {
$views.eq(current).hide();
current = idx == undefined ? current + 1 : idx;
if (isNaN(current) || current < 0 || current >= viewCount) {
current = 0;
}
$views.eq(current).fadeIn(config.tranSpeed);
$imgdots.removeClass('current').eq(current).addClass('current');
}
$imgdots.click(function(){
clearInterval(timer);
next($(this).index());
})
$wrapper.find('.btn_nxt').click(function(){
clearInterval(timer);
next();
});
$ct.hover(function(){
clearInterval(timer);
}, loop);
$views.slice(1).hide();
$imgdots.eq(0).addClass('current');
loop();
});
return this;
};
})(jQuery);
/* Calling The jQuery plugin */
$(document).ready(function () {
/**/
$(".wrapper").simpleShow({
'tranTimer': 3000,
'tranSpeed': 800
});
});
Demo: Fiddle

Gallery not working on iPad/Mobile Devices

For some reason my gallery isn't working on Mobile devices including iPad, works fine on desktop. Instead of allowing a user to click through, all images appear stacked. The link to my site. The code is
located here
// scroll gallery init
function initCarousel() {
var isTouchDevice = /MSIE 10.*Touch/.test(navigator.userAgent) || ('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch;
jQuery('div.view-gallery').scrollGallery({
mask: 'div.frame',
slider: '>ul',
slides: '>li',
btnPrev: 'a.btn-prev',
btnNext: 'a.btn-next',
pagerLinks: '.pagination li',
circularRotation: false,
autoRotation: false,
switchTime: 3000,
animSpeed: 500,
onInit: function(obj){
obj.resizeFlag = true;
obj.win = jQuery(window);
//obj.win.unbind('resize orientationchange load', obj.onWindowResize);
obj.resizeSlides = function(){
obj.slideOffset = obj.slides.eq(0).outerWidth(true) - obj.slides.eq(0).width();
if(!obj.resizeFlag) obj.slides.css({width: ''});
else obj.slides.css({width: obj.mask.width()/2 - obj.slideOffset});
obj.calculateOffsets();
obj.refreshPosition();
obj.refreshState();
}
if(isTouchDevice){
ResponsiveHelper.addRange({
'..767': {
on: function(){
setTimeout(function(){
obj.resizeFlag = true;
obj.resizeSlides();
obj.win.bind('resize orientationchange load', obj.resizeSlides);
}, 100);
}
},
'768..': {
on: function(){
obj.resizeFlag = false;
obj.win.unbind('resize orientationchange load', obj.resizeSlides);
obj.resizeSlides();
}
}
});
}
}
});
jQuery('.scrollable-gallery').scrollableGallery();
}
/*
* scrollableGallery
*/
;(function($) {
function ScrollableGallery(options) {
this.options = {
scrollableArea: '.frame',
listItems: '.list-items',
btnPrev: '.btn-prev',
btnNext: '.btn-next',
animSpeed: 500
}
$.extend(this.options, options);
this.init();
}
ScrollableGallery.prototype = {
init: function() {
this.findElements()
this.setStructure();
this.addEvents();
},
findElements: function() {
this.holder = $(this.options.holder);
this.scrollableArea = this.holder.find(this.options.scrollableArea);
this.listItems = this.scrollableArea.find(this.options.listItems);
this.items = this.listItems.children();
this.lastItem = this.items.last();
this.btnPrev = this.holder.find(this.options.btnPrev);
this.btnNext = this.holder.find(this.options.btnNext);
this.scrollAPI = new jcf.modules.customscroll({
replaces: this.scrollableArea[0]
});
},
setStructure: function() {
var that = this;
if (that.listItems.css('position') === 'static') {
that.listItems.css('position', 'relative');
}
setTimeout(function() {
that.refreshState();
}, 50);
},
refreshState: function() {
this.listItems.css('width', 32700);
this.listItems.css('width', this.lastItem.position().left + this.lastItem.outerWidth(true) + 1);
this.scrollableArea.add(this.scrollableArea.parent()).css({
width: '',
height: ''
});
this.scrollAPI.refreshState();
},
addEvents: function() {
var that = this;
that.btnPrev.bind('click', function(e) {
e.preventDefault();
that.prevSlide();
});
that.btnNext.bind('click', function(e) {
e.preventDefault();
that.nextSlide();
});
win.bind('resize orientationchange load', function() {
that.refreshState();
});
},
nextSlide: function() {
var that = this;
var curPos = this.scrollableArea.scrollLeft();
var pos;
for (var i = 0; i < that.items.length; i++) {
pos = that.items.eq(i).position().left;
if (pos > curPos) {
that.scrollAnimate(curPos, pos);
break;
}
}
},
prevSlide: function() {
var that = this;
var curPos = this.scrollableArea.scrollLeft();
var pos;
for (var i = that.items.length - 1; i >= 0; i--) {
pos = that.items.eq(i).position().left;
if (pos < curPos) {
that.scrollAnimate(curPos, pos);
break;
}
}
},
scrollAnimate: function(from, to) {
var that = this;
var start = new Date().getTime();
setTimeout(function() {
var now = (new Date().getTime()) - start;
var progress = now / that.options.animSpeed;
var result = (to - from) * progress + from;
that.scrollAPI.hScrollBar.scrollTo(result);
if (progress < 1) {
setTimeout(arguments.callee, 10);
} else {
that.scrollAPI.hScrollBar.scrollTo(to);
}
}, 10);
}
}
var win = $(window);
$.fn.scrollableGallery = function(options) {
return this.each(function() {
if (!$(this).data('ScrollableGallery')) {
$(this).data('ScrollableGallery', new ScrollableGallery($.extend({}, {holder: this}, options)));
}
});
}
}(jQuery));
After looking through your code, there were numerous errors with syntax. I have cleaned them up as best as I could, this should help you out.
http://jsfiddle.net/wvWrY/1/
For example, this area was missing a semicolon (no way to call the findElements function, as JS will simply skip to the next line without a semicolon there.)
init: function() {
this.findElements()
this.setStructure();
this.addEvents();
Run your code through a linter, it will greatly improve your syntax structure and ensure little leave out errors like semicolons and commas and brackets aren't omitted.
EDIT: Ok, having looked at your code it appears this is actually due to the !importants in your allmobile.css file. The width and height are set to max-width: 100% (this breaks it because the way the slider works is to extend the gallery as far off screen as possible) and the height to auto (this breaks it because it allows the images to just keep piling on). Once you remove those for the page, it become much much much better and actually works.

Problem with jquery inside OOP function

Hello I'm trying to get value of hidden element in my OOP function. Here is code:
var refreshTimeout;
var rms = new RMS();
rms.refresh();
function RMS() {
this.refresh = function(){
alert($("#ids").val());
$.post(refreshUrl, {ids: $("#ids").val()}, function(response){
var result = $.parseJSON(response);
if (result != null) {
$("#rms").attr("value", result.rms);
}
refreshTimeout = setTimeout(function() { rms.refresh(); }, 2000);
});
}
}
The problem is that $("#ids").val() works in firebug console but not inside rms.refresh()...
What I'm doing wrong?
Your invocation of $('#ids').val() looks fine, so long as the DOM is loaded at this point (i.e. inside a $(document).ready() block).
Your timer function looks a little suspect, though. You're referring to rms which is in the outer scope, when you should be referring to whatever the current object is.
Similarly your timer-related values should be properly encapsulated inside the class, since otherwise you can't have more than one instance.
// class definition - can be loaded anywhere
var RMS = function(ids, rms) {
var self = this;
var timer = null;
var delay = 2000;
this.refresh = function() {
$.post(refreshUrl, {ids: $(ids).val()},
function(response) {
var result = $.parseJSON(response);
if (result != null) {
$(rms).attr("value", result.rms);
}
timer = setTimeout(function() {
self.refresh();
}, delay);
}
);
};
};
// invocation deferred until the DOM is ready
$(document).ready(function() {
var rms = new RMS('#ids', '#rms');
rms.refresh();
});
Try this code:
$(document).ready(function(){
var refreshTimeout,
rms = new RMS();
rms.refresh();
function RMS() {
this.refresh = function(){
$.post(refreshUrl, {ids: $('#ids').val()}, function(response){
if (typeof(response) != 'undefined') {
$('#rms').attr('value', response.rms);
}
refreshTimeout = setTimeout(function() { rms.refresh(); }, 2000);
}, 'json');
}
}
});

$ is not a function errors

I'm getting a few Javascript errors and was wondering if anyone could help me out with them. I'm fairly new to js and could really use the help. That being said here is the page with the errors. http://www.gotopeak.com .
Here is the error:
Uncaught TypeError: Property '$' of object [object DOMWindow] is not a function
error is on line 44
Here is the code:
var hoverButton = {
init : function() {
arrButtons = $$('.hover_button');
for (var i=0; i<arrButtons.length; i++) {
arrButtons[i].addEvent('mouseover', hoverButton.setOver);
arrButtons[i].addEvent('mouseout', hoverButton.setOff);
}
},
setOver : function() {
buttonImageSource = this.src;
this.src = buttonImageSource.replace('_off.', '_hover.');
},
setOff : function() {
buttonImageSource = this.src;
if (buttonImageSource.indexOf('_hover.') != -1) {
this.src = buttonImageSource.replace('_hover.', '_off.');
}
}
}
window.addEvent('domready', hoverButton.init);
var screenshots = {
numScreens : 0,
currScreen : 0,
screenContainerAnimation : null,
screenFadeSpeed : 200,
animating : false,
initialized: false,
init : function() {
var arrScreens = $$('#screen_container .screenshot');
screenshots.numScreens = arrScreens.length;
screenshots.screenContainerAnimation = new Fx.Tween('screen_container', {
duration: 300,
transition: Fx.Transitions.Quad.easeInOut
});
var indicatorMold = $('indicatorMold');
for(i=0; i<arrScreens.length; i++) {
var screenShot = arrScreens[i];
screenShot.id = 'screenshot' + (i+1);
var screenIndicator = indicatorMold.clone();
screenIndicator.id = 'indicator' + (i+1);
screenIndicator.inject('screen_indicators');
screenIndicator.href = 'javascript: screenshots.setActiveScreen('+ (i+1)*1 +')';
screenShot.removeClass('hidden');
if (i==0) {
var initialScreenHeight = screenShot.getCoordinates().height;
$('screen_container').setStyle('height', initialScreenHeight);
screenshots.currScreen = 1;
screenIndicator.addClass('active');
}
else {
screenShot.setStyle('opacity',0);
screenShot.setStyle('display','none');
}
} // loop
screenshots.initialized = true;
},
next : function() {
if (screenshots.initialized) {
var nextNum = screenshots.currScreen + 1;
if (nextNum > screenshots.numScreens) {
nextNum = 1;
}
screenshots.setActiveScreen(nextNum);
}
return false;
},
previous : function() {
if (screenshots.initialized) {
var prevNum = screenshots.currScreen - 1;
if (prevNum < 1) {
prevNum = screenshots.numScreens;
}
screenshots.setActiveScreen(prevNum);
}
return false;
},
setActiveScreen : function(screenNum) {
if(screenshots.animating == false) {
screenshots.animating = true;
var currScreen = $('screenshot' + screenshots.currScreen);
var currIndicator = $('indicator' + screenshots.currScreen);
var newScreen = $('screenshot' + screenNum);
var newIndicator = $('indicator' + screenNum);
currScreen.set('tween', {
duration: screenshots.screenFadeSpeed,
transition: Fx.Transitions.Quad.easeInOut,
onComplete: function() {
currIndicator.removeClass('active');
currScreen.setStyle('display','none') ;
}
});
currScreen.tween('opacity', 0);
function resizeScreen() {
newScreen.setStyle('display','block');
var newScreenSize = newScreen.getCoordinates().height;
screenshots.screenContainerAnimation.start('height', newScreenSize);
}
function fadeInNewScreen() {
newScreen.set('tween', {
duration: screenshots.screenFadeSpeed,
transition: Fx.Transitions.Quad.easeInOut,
onComplete: function() {
newIndicator.addClass('active');
screenshots.animating = false;
}
});
newScreen.tween('opacity', 1);
}
resizeScreen.delay(screenshots.screenFadeSpeed);
fadeInNewScreen.delay(screenshots.screenFadeSpeed + 400);
screenshots.currScreen = screenNum;
}
}
}
window.addEvent('load', screenshots.init) ;
I would be very grateful and appreciative of any help that I receive on this issue.
Your page is loading mootools once, jQuery twice and jQuery UI twice. Because both jQuery and mootools define a function named '$', this gives you conflicts.
You can fix this by using a self executing closure that maps the non-conflicted version of '$' to a local '$' variable you can actually use.
(function($) {
// your code
})(document.id);
More information on MooTools' "Dollar Safe Mode" can be found here.
Edit: please ignore. The above answer by igorw is the correct one. Sorry.
Try converting your $ symbols to "jQuery". $ is a shortcut to JQuery. $ is reserved for Prototype in Wordpress.
Edit: you can also try jQuery.noConflict(). It relinquishes control of $ back to JQuery (or the first library that implements it), so it does not cause conflict with other libraries that also implement $.
this is what I did and solved everything, Go to the index.php file, after calling jquery immediately, place <script type="text/javascript">jQuery.noConflict();</script>

Categories