42

Here is my code:

(function($){
    $.fn.pluginbutton = function (options) {
        myoptions = $.extend({ left: true });
        return this.each(function () {
            var focus = false;
            if (focus === false) {
                this.hover(function () {
                    this.animate({ backgroundPosition: "0 -30px" }, { duration: 0 });
                    this.removeClass('VBfocus').addClass('VBHover');
                }, function () {
                    this.animate({ backgroundPosition: "0 0" }, { duration: 0 });
                    this.removeClass('VBfocus').removeClass('VBHover');
                });
            }
            this.mousedown(function () {
                focus = true
                this.animate({ backgroundPosition: "0 30px" }, { duration: 0 });
                this.addClass('VBfocus').removeClass('VBHover');
            }, function () {
                focus = false;
                this.animate({ backgroundPosition: "0 0" }, { duration: 0 });
                this.removeClass('VBfocus').addClass('VBHover');
            });
        });
    }
});


$(document).ready(function () {
    $('.smallTabsHeader a').pluginbutton();
});

It gives me an error. What's wrong?

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Phil Jackson
  • 10,238
  • 23
  • 96
  • 130

7 Answers7

104

This problem is "best" solved by using an anonymous function to pass-in the jQuery object thusly:

The Anonymous Function Looks Like:

<script type="text/javascript">
    (function($) {
        // You pass-in jQuery and then alias it with the $-sign
        // So your internal code doesn't change
    })(jQuery);
</script>

This is JavaScript's method of implementing (poor man's) 'Dependency Injection' when used alongside things like the 'Module Pattern'.

So Your Code Would Look Like:
Of course, you might want to make some changes to your internal code now, but you get the idea.

<script type="text/javascript">
    (function($) {
        $.fn.pluginbutton = function(options) {
            myoptions = $.extend({ left: true });
            return this.each(function() {
                var focus = false;
                if (focus === false) {
                    this.hover(function() {
                        this.animate({ backgroundPosition: "0 -30px" }, { duration: 0 });
                        this.removeClass('VBfocus').addClass('VBHover');
                    }, function() {
                        this.animate({ backgroundPosition: "0 0" }, { duration: 0 });
                        this.removeClass('VBfocus').removeClass('VBHover');
                    });
                }
                this.mousedown(function() {
                    focus = true
                    this.animate({ backgroundPosition: "0 30px" }, { duration: 0 });
                    this.addClass('VBfocus').removeClass('VBHover');
                }, function() {
                    focus = false;
                    this.animate({ backgroundPosition: "0 0" }, { duration: 0 });
                    this.removeClass('VBfocus').addClass('VBHover');
                });
            });
        }
    })(jQuery);
</script>
Prisoner ZERO
  • 13,848
  • 21
  • 92
  • 137
10

The problem arises when a different system grabs the $ variable. You have multiple $ variables being used as objects from multiple libraries, resulting in the error.

To solve it, use jQuery.noConflict just before your (function($){:

jQuery.noConflict();
(function($){
$.fn.pluginbutton = function (options) {
...
Kamyar
  • 18,639
  • 9
  • 97
  • 171
  • fire fox returns $(".smallTabsHeader a").pluginbutton is not a function – Phil Jackson May 24 '11 at 11:49
  • the above causes massive amounts of errors throughout the page – Phil Jackson May 24 '11 at 11:52
  • 1
    I thought you mentioned "Jquery is not a function". Please edit your question's title and remove jquery from the title. It belongs to tags section. – Kamyar May 24 '11 at 11:53
  • 1
    I thought with no-conflict mode, you started with something like `var $j = jQuery.noConflict();`. Then wherever you would have normally used `$(...)` you would use `$j(...)`. I don't know how else it would resolve conflicts with other functions named `$`. – Cᴏʀʏ May 24 '11 at 11:54
  • this is not the problem at all. The OP specifically handles that issue in his code. The problem is that the OP does not pass a reference to the jQuery object in his anonymous function (*nor does he invoke it*). (*..plus some additional wrong handling of `this`*) – Gabriele Petrioli May 24 '11 at 11:54
10

change

});


$(document).ready(function () {
    $('.smallTabsHeader a').pluginbutton();
});

to

})(jQuery); //<-- ADD THIS


$(document).ready(function () {
    $('.smallTabsHeader a').pluginbutton();
});

This is needed because, you need to call the anonymous function that you created with

(function($){

and notice that it expects an argument that it will use internally as $, so you need to pass a reference to the jQuery object.

Additionally, you will need to change all the this. to $(this)., except the first one, in which you do return this.each

In the first one (where you do not need the $()) it is because in the plugin body, this holds a reference to the jQuery object matching your selector, but anywhere deeper than that, this refers to the specific DOM element, so you need to wrap it in $().

Full code at http://jsfiddle.net/gaby/NXESk/

Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
3

It works on my case:

import * as JQuery from "jquery";
const $ = JQuery.default;
Luillyfe
  • 6,183
  • 8
  • 36
  • 46
1

When converting an ASP.Net webform prototype to a MVC site I got these errors:

TypeError: $(...).accordion is not a function
$("#accordion").accordion(


$('#dialog').dialog({
TypeError: $(...).dialog is not a function

It worked fine in the webforms. The problem/solution was this line in the _Layout.cshtml

@Scripts.Render("~/bundles/jquery")

Comment it out to see if the errors go away. Then fix it in the BundlesConfig:

bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
"~/Scripts/jquery-{version}.js"));
Gaurav Aggarwal
  • 9,809
  • 6
  • 36
  • 74
Jeremy Thompson
  • 61,933
  • 36
  • 195
  • 321
-1

I solved it by renaming my function.

Changed

function editForm(value)

to

function editTheForm(value)

Works perfectly.

rmooney
  • 6,123
  • 3
  • 29
  • 29
-2

In my case, the same error had a much easier fix. Basically my function was in a .js file that was not included in the current aspx that was showing. All I needed was the include line.

Ash
  • 1,269
  • 3
  • 25
  • 49