"$.______ is not a function" error. What is wrong? - javascript

I'm trying to add an image rotator to my site but for some reason firebug tells me the function I need to call to start the rotator isn't defined. My jQuery file is loading just fine and the image rotator script is loading so I'm not sure what is wrong. The site is heritage.newcoastmedia.com but I'll go ahead and post the script:
;(function($) {
$.fn.featureList = function(options) {
var tabs = $(this);
var output = $(options.output);
new jQuery.featureList(tabs, output, options);
return this;
};
$.featureList = function(tabs, output, options) {
function slide(nr) {
if (typeof nr == "undefined") {
nr = visible_item + 1;
nr = nr >= total_items ? 0 : nr;
}
tabs.removeClass('current').filter(":eq(" + nr + ")").addClass('current');
output.stop(true, true).filter(":visible").fadeOut();
output.filter(":eq(" + nr + ")").fadeIn(function() {
visible_item = nr;
});
}
var options = options || {};
var total_items = tabs.length;
var visible_item = options.start_item || 0;
options.pause_on_hover = options.pause_on_hover || true;
options.transition_interval = options.transition_interval || 5000;
output.hide().eq( visible_item ).show();
tabs.eq( visible_item ).addClass('current');
tabs.click(function() {
if ($(this).hasClass('current')) {
return false;
}
slide( tabs.index( this) );
});
if (options.transition_interval > 0) {
var timer = setInterval(function () {
slide();
}, options.transition_interval);
if (options.pause_on_hover) {
tabs.mouseenter(function() {
clearInterval( timer );
}).mouseleave(function() {
clearInterval( timer );
timer = setInterval(function () {
slide();
}, options.transition_interval);
});
}
}
};
});
And here is the script to start the image rotator:
<script language="javascript">
$(document).ready(function() {
$.featureList(
$("#tabs li a"),
$("#output li"), {
start_item : 1
}
);
});
</script>

Your code creates an anonymous function, but doesn't call it.
You need to call the function by adding (jQuery) at the end.

You cannot do $.featureList(
See Chrome error:
The plugin needs to applied to an object

You've just slightly missed out on the right syntax for creating a plugin. What you really want is:
(function($) {
$.fn.featureList = function() { // etc; }
$.featureList = function() { // yet more etc; }
})(jQuery);

Related

Resume a function after clearInterval

I have this code:
jQuery(function($) { // DOM is ready
var $el = $("header tr"),
tot = $el.length,
c = 0;
var timer = setInterval(function() {
$el.removeClass("current").eq(++c % tot).addClass("current");
}, 3000);
$el.first().addClass("current");
$el.on({
mouseenter: function(e) {
clearInterval(timer);
}
});
$el.mouseout({
timer;
});
});
I want to suspend the function on mouseover and resume it on mouse out but I cant get the latter right. How can I resume it?
Thank you.
There are two ways:
Set a flag that the function being called by the interval checks, and have the function not do anything if it's "suspended."
Start the interval again via a new setInterval call. Note that the old timer value cannot be used for this, you need to pass in the code again.
Example of #1:
jQuery(function($) { // DOM is ready
var $el = $("header tr"),
tot = $el.length,
c = 0,
suspend = false; // The flag
var timer = setInterval(function() {
if (!suspend) { // Check it
$el.removeClass("current").eq(++c % tot).addClass("current");
}
}, 3000);
$el.first().addClass("current");
$el.on({
mouseenter: function(e) {
suspend = true; // Set it
},
mouseleave: function(e) {
suspend = false; // Clear it
}
});
});
Example of #2:
jQuery(function($) { // DOM is ready
var $el = $("header tr"),
tot = $el.length,
c = 0,
timer = 0;
// Move this to a reusable function
var intervalHandler = function() {
$el.removeClass("current").eq(++c % tot).addClass("current");
};
// Probably best to encapsulate the logic for starting it rather
// than repeating that logic
var startInterval = function() {
timer = setInterval(intervalHandler, 3000);
};
// Initial timer
startInterval();
$el.first().addClass("current");
$el.on({
mouseenter: function(e) {
clearInterval(timer); // Stop it
}
mouseleave: function(e) {
startInterval(); // Start it
}
});
});
Checkout these prototypes:
//Initializable
function Initializable(params) {
this.initialize = function(key, def, private) {
if (def !== undefined) {
(!!private ? params : this)[key] = (params[key] !== undefined) ? params[key] : def;
}
};
}
function PeriodicJobHandler(params) {
Initializable.call(this, params);
this.initialize("timeout", 1000, true);
var getTimeout = function() {
return params.timeout;
};
var jobs = [];
function Job(params) {
//expects params.job() function
Initializable.call(this, params);
this.initialize("timeout", getTimeout(), true);
this.initialize("instant", false);
var intervalID = undefined;
this.start = function() {
if (intervalID !== undefined) {
return;
}
if (this.instant) {
params.job(true);
}
intervalID = setInterval(function() {
params.job(false);
}, params.timeout);
};
this.stop = function() {
clearInterval(intervalID);
intervalID = undefined;
};
}
this.addJob = function(params) {
jobs.push(new Job(params));
return jobs.length - 1;
};
this.removeJob = function(index) {
jobs[index].stop();
jobs.splice(index, 1);
};
this.startJob = function(index) {
jobs[index].start();
};
this.stopJob = function(index) {
jobs[index].stop();
};
}
Initializable simplifies member initialization, while PeriodicJobHandler is able to manage jobs in a periodic fashion. Now, let's use it practically:
var pjh = new PeriodicJobHandler({});
//It will run once/second. If you want to change the interval time, just define the timeout property in the object passed to addJob
var jobIndex = pjh.addJob({
instant: true,
job: function() {
$el.removeClass("current").eq(++c % tot).addClass("current");
}
});
jQuery(function($) { // DOM is ready
var $el = $("header tr"),
tot = $el.length,
c = 0;
var timer = setInterval(function() {
$el.removeClass("current").eq(++c % tot).addClass("current");
}, 3000);
$el.first().addClass("current");
$el.on({
mouseenter: function(e) {
jobIndex.stop();
}
});
$el.mouseout({
jobIndex.start();
});
});
With Javascript, it is much easy and efficient.
You can change the interval in setInterval function.
It is checking whether suspend variable is false or true, here suspend variable is setting to true, if mouseEnter function is called and set to false if mouseLeave function is called.
var displayMsg = document.getElementById('msg').innerHTML;
var i = 0;
var suspend = false;
var sequence = setInterval(update, 100);
function update() {
if (suspend == false) {
var dispalyedMsg = '';
dispalyedMsg = displayMsg.substring(i, displayMsg.length);
dispalyedMsg += ' ';
dispalyedMsg += displayMsg.substring(0, i);
document.getElementById('msg').innerHTML = dispalyedMsg;
i++;
if (i > displayMsg.length) {
i = 0;
}
}
}
document.getElementById('msg').addEventListener('mouseenter', mouseEnter);
document.getElementById('msg').addEventListener('mouseleave', mouseLeave);
function mouseEnter() {
suspend = true;
}
function mouseLeave() {
suspend = false;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
#msg {
width: 680px;
height: 100px;
border: 1px solid #ccc;
padding-left: 15px;
}
</style>
</head>
<body>
<div id="msg">
Today is only 15% discount. Hurry up to grab. Sale will end sooooooooooooon!!!!
</div>
<div id="output"></div>
<script src="marquee.js"></script>
</body>
</html>

Uncaught TypeError: $(...).find(...).once is not a function in bootstrap/js/bootstrap.js?

I have installed bootstrap theme for building responsive theme then I installed jquery_update module as documentation in theme project and everything seems ok expect below js error appears in inspect elements console:
Uncaught TypeError: $(...).find(...).once is not a function in
bootstrap/js/bootstrap.js?o5l669
Any one please can help me?
this is the bootstrap.js:
/**
* #file
* bootstrap.js
*
* Provides general enhancements and fixes to Bootstrap's JS files.
*/
var Drupal = Drupal || {};
(function($, Drupal){
"use strict";
Drupal.behaviors.bootstrap = {
attach: function(context) {
// Provide some Bootstrap tab/Drupal integration.
$(context).find('.tabbable').once('bootstrap-tabs', function () {
var $wrapper = $(this);
var $tabs = $wrapper.find('.nav-tabs');
var $content = $wrapper.find('.tab-content');
var borderRadius = parseInt($content.css('borderBottomRightRadius'), 10);
var bootstrapTabResize = function() {
if ($wrapper.hasClass('tabs-left') || $wrapper.hasClass('tabs-right')) {
$content.css('min-height', $tabs.outerHeight());
}
};
// Add min-height on content for left and right tabs.
bootstrapTabResize();
// Detect tab switch.
if ($wrapper.hasClass('tabs-left') || $wrapper.hasClass('tabs-right')) {
$tabs.on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
bootstrapTabResize();
if ($wrapper.hasClass('tabs-left')) {
if ($(e.target).parent().is(':first-child')) {
$content.css('borderTopLeftRadius', '0');
}
else {
$content.css('borderTopLeftRadius', borderRadius + 'px');
}
}
else {
if ($(e.target).parent().is(':first-child')) {
$content.css('borderTopRightRadius', '0');
}
else {
$content.css('borderTopRightRadius', borderRadius + 'px');
}
}
});
}
});
}
};
/**
* Bootstrap Popovers.
*/
Drupal.behaviors.bootstrapPopovers = {
attach: function (context, settings) {
if (settings.bootstrap && settings.bootstrap.popoverEnabled) {
var elements = $(context).find('[data-toggle="popover"]').toArray();
for (var i = 0; i < elements.length; i++) {
var $element = $(elements[i]);
var options = $.extend(true, {}, settings.bootstrap.popoverOptions, $element.data());
$element.popover(options);
}
}
}
};
/**
* Bootstrap Tooltips.
*/
Drupal.behaviors.bootstrapTooltips = {
attach: function (context, settings) {
if (settings.bootstrap && settings.bootstrap.tooltipEnabled) {
var elements = $(context).find('[data-toggle="tooltip"]').toArray();
for (var i = 0; i < elements.length; i++) {
var $element = $(elements[i]);
var options = $.extend(true, {}, settings.bootstrap.tooltipOptions, $element.data());
$element.tooltip(options);
}
}
}
};
/**
* Anchor fixes.
*/
var $scrollableElement = $();
Drupal.behaviors.bootstrapAnchors = {
attach: function(context, settings) {
var i, elements = ['html', 'body'];
if (!$scrollableElement.length) {
for (i = 0; i < elements.length; i++) {
var $element = $(elements[i]);
if ($element.scrollTop() > 0) {
$scrollableElement = $element;
break;
}
else {
$element.scrollTop(1);
if ($element.scrollTop() > 0) {
$element.scrollTop(0);
$scrollableElement = $element;
break;
}
}
}
}
if (!settings.bootstrap || !settings.bootstrap.anchorsFix) {
return;
}
var anchors = $(context).find('a').toArray();
for (i = 0; i < anchors.length; i++) {
if (!anchors[i].scrollTo) {
this.bootstrapAnchor(anchors[i]);
}
}
$scrollableElement.once('bootstrap-anchors', function () {
$scrollableElement.on('click.bootstrap-anchors', 'a[href*="#"]:not([data-toggle],[data-target])', function(e) {
this.scrollTo(e);
});
});
},
bootstrapAnchor: function (element) {
element.validAnchor = element.nodeName === 'A' && (location.hostname === element.hostname || !element.hostname) && element.hash.replace(/#/,'').length;
element.scrollTo = function(event) {
var attr = 'id';
var $target = $(element.hash);
if (!$target.length) {
attr = 'name';
$target = $('[name="' + element.hash.replace('#', '') + '"');
}
var offset = $target.offset().top - parseInt($scrollableElement.css('paddingTop'), 10) - parseInt($scrollableElement.css('marginTop'), 10);
if (this.validAnchor && $target.length && offset > 0) {
if (event) {
event.preventDefault();
}
var $fakeAnchor = $('<div/>')
.addClass('element-invisible')
.attr(attr, $target.attr(attr))
.css({
position: 'absolute',
top: offset + 'px',
zIndex: -1000
})
.appendTo(document);
$target.removeAttr(attr);
var complete = function () {
location.hash = element.hash;
$fakeAnchor.remove();
$target.attr(attr, element.hash.replace('#', ''));
};
if (Drupal.settings.bootstrap.anchorsSmoothScrolling) {
$scrollableElement.animate({ scrollTop: offset, avoidTransforms: true }, 400, complete);
}
else {
$scrollableElement.scrollTop(offset);
complete();
}
}
};
}
};
})(jQuery, Drupal);
I have same issue and my solution is exclude bootstrap.js on my custom theme.
also you can alter bootstrap.js
Maybe The problem is because of two version ov jquery load on your page, inspect your javascript and if there is two version of jquery, let one exist and remove another.
In my case, there are 2 jquery files (core, theme). I removed it from theme. it works perfectly fine.

Trigger a event when the user is on the page

I have this code
$(document).ready(function(){
var fade_in = function(){
$(".quote").fadeIn();
}
setTimeout(fade_in, 2000);
var fade_out = function() {
$(".quote").fadeOut();
}
setTimeout(fade_out, 10000);
});
What it does is that the div "quote" slowly fades in, stays for a few seconds and then fades out. What I want is that all this happens when the user is on the page, if you're not in the page,the text fades in, fades out and you miss it. How can I do that?
There are two ways
First : (bit old)
$(document).ready(function() {
window.onfocus = function() {
var fade_in = function() {
$(".quote").fadeIn();
}
setTimeout(fade_in, 2000);
var fade_out = function() {
$(".quote").fadeOut();
}
setTimeout(fade_out, 10000);
};
});
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="quote">quote</div>
Second :
function getHiddenProp() {
var prefixes = ['webkit', 'moz', 'ms', 'o'];
// if 'hidden' is natively supported just return it
if ('hidden' in document) return 'hidden';
// otherwise loop over all the known prefixes until we find one
for (var i = 0; i < prefixes.length; i++) {
if ((prefixes[i] + 'Hidden') in document)
return prefixes[i] + 'Hidden';
}
// otherwise it's not supported
return null;
}
function isHidden() {
var prop = getHiddenProp();
if (!prop) return false;
return document[prop];
}
// use the property name to generate the prefixed event name
var visProp = getHiddenProp();
if (visProp) {
var evtname = visProp.replace(/[H|h]idden/, '') + 'visibilitychange';
document.addEventListener(evtname, visChange);
}
function visChange() {
var txtFld = document.getElementById('visChangeText');
if (txtFld) {
if (!isHidden()) {
var fade_in = function() {
$(".quote").fadeIn();
}
setTimeout(fade_in, 2000);
var fade_out = function() {
$(".quote").fadeOut();
}
setTimeout(fade_out, 10000);
};
}
}
}
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="quote">quote</div>
This will execute when page div visible
$(document).ready(function(){
$( "div:visible" ).click(function() {
$( this ).css( "background", "yellow" );
});
});

Convert script for working with multiple instances

Lets see this script, that it's a simple carrousel
$script = {
init: function(){
this.heros(3000);
},
heros: function (time) {
var t;
var $hero = $('.hero');
var $images = $('.hero > div');
$hero.data('current', 0);
var $bullets = $('<div>').addClass('bullets');
for ( var i = 0; i<$images.length; i++ ) {
var $item = $('<span>');
$item.on('click', function () {
clearTimeout(t);
play( $(this).index() );
});
if(i==0) { $item.addClass('active') }
$bullets.append( $item );
}
var play = function (current) {
if(current==undefined) {
current = $hero.data('current');
}
var nextMargin;
if ( (current+1) == $images.length ) {
nextMargin = 0 ;
$hero.data('current',0);
} else {
nextMargin = (current + 1 )*100;
$hero.data('current', (current + 1));
}
$images.eq(0).css('marginLeft', -nextMargin + '%');
$bullets.find('span').eq($hero.data('current')).addClass('active').siblings().removeClass('active');
clearTimeout(t);
t = setTimeout(play, time);
}
$hero.append($bullets);
t = setTimeout(play, time);
},
}
The thing is that it works great, but only if there's just one .hero element.. if there are multiple the bullets mix up and it doesn't respect the .length
I know that option one should be rewrite it again, but Does anyone of you sees a quick fix that would make it reusable?
A single fiddle: https://jsfiddle.net/6z8n5pnq/
A multiple fiddle: https://jsfiddle.net/6z8n5pnq/1/
-EDIT-
I tried:
Defining a previous function, that is called on init
preheros: function(time) {
var self = this;
$('.heros').each(function(){
self.heros($(this), time);
});
},
And editing The begining of heros:
heros: function ($hero, time) {
var t;
/*var $hero = $('.hero');*/
var $images = $hero.find('>div');
but no success...
any idea?
-EDIT-
GOD, it's $('.hero').each not $('.heros').each it was working!
The easiest way to do this is to isolate context for each .hero component by using $(selector).each function. Slightly corrected your fiddle https://jsfiddle.net/6z8n5pnq/2/
function apply($hero, time){
var t;
var $images = $hero.children('div');
//all your logic here...
}
$script = {
init: function () {
this.heros(3000);
},
heros: function (time) {
$('.hero').each(function(){
apply($(this), time);
});
},
}

mootools | Hide and show animation

I have a mootools code:
(function() {
var index = 0;
Element.implement({
toggle: function() {
var args = Array.slice(arguments, 0);
count = args.length - 1;
return this.addEvent("click", function() {
args[index].apply(this, arguments);
index = (count > index) ? index + 1 : 0;
});
},
resetToggle: function() {
index = 0;
}
});
})();
document.getElement(".toggle").toggle(
function() {
document.id("menu").setStyle("display", "block");
}, function() {
document.id("menu").setStyle("display", "none");
}
);
});
How to hide/show div.menu container with animation?
Thanks!
haha this looks like my old toggle code :) do:
document.id('menu').setStyles({
display: 'block',
opacity: 0
}).fade(1);
and the opposite.
update to:
(function(){
var Element = this.Element,
Elements = this.Elements;
[Element, Elements].invoke('implement', {
toggle: function(){
var args = Array.prototype.slice.call(arguments),
count = args.length-1,
// start at 0
index = 0;
return this.addEvent('click', function(){
var fn = args[index];
typeof fn === 'function' && fn.apply(this, arguments);
// loop args.
index = count > index ? index+1 : 0;
});
}
});
}());
If you want to make a animation you could use reveal() / dissolve() available in MooTools-More
document.getElement(".toggle").toggle(function () {
document.id("menu").reveal();
}, function () {
document.id("menu").dissolve();
});
Note you had a pair }); too much in your code (last line)
Example
But if you would use more, there is already a .toggle() method you can use, that would give you just show/hide like this.

Categories

Resources