-2

I have a custom jquery plugin I am working on to import forms to elements on a page. The plugin is saved on a file called jquery-library.js and this is imported into my page along with another jquery library jquery.min.js. I can get my plugin to work if I hard code the variable it ajax's to but not if I use this or $(this).

Here is my php page code:

<head>
    <meta charset="utf-8">

    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script src="scripts/jquery-library.js"></script>

    <link href='https://fonts.googleapis.com/css?family=PT+Sans+Narrow:400,700' rel='stylesheet' type='text/css'>
    <link type="text/css" href="css/main.css" rel="stylesheet"/>

    <script>
        $(document).on('click', '#add', function(){
            $("div#form-import-container").loadForm("add", "websites");
        });
    </script>   

    <title>Senneca Portal | Adminstration Panel</title>
</head>
<body>
    <?php require_once("include/header.php"); ?>
    <section id="content">
        <section id="left-side-bar">
            <img id="side-profile-pic" src=""/>
            <div id="page-sub-nav-container">
                <p class="sub-nav-title"><?php echo $pageDisplay; ?></p>
                <nav id="side-nav">
                    <ul>
                        <li><a <?php if($page == "overview"){ echo "class='active'";}; ?> href="administration.php">Overview</a></li>
                        <li><a <?php if($page == "websites"){ echo "class='active'";}; ?> href="administration.php?page=websites">Websites</a></li>
                        <li><a <?php if($page == "products"){ echo "class='active'";}; ?> href="administration.php?page=products">Products</a></li>
                        <li><a <?php if($page == "libraries"){ echo "class='active'";}; ?> href="administration.php?page=libraries">Libraries</a></li>
                        <li><a <?php if($page == "colors"){ echo "class='active'";}; ?> href="administration.php?page=colors">Colors</a></li>
                        <li><a <?php if($page == "testimonials"){ echo "class='active'";}; ?> href="administration.php?page=testimonials">Testimonials</a></li>
                        <li><a <?php if($page == "users"){ echo "class='active'";}; ?> href="administration.php?page=users">Users</a></li>
                    </ul>
                </nav>
            </div>
        </section>
        <section id="data">
            <button id="add">Add New</button>
            <h2><?php echo $pageDisplay." - ".$page; ?></h2>
            <!-- Area for form import -->
            <div id="form-import-container"></div>

loadForm is my custom plugin I have been making and here is the code for that.

    (function($){
    $.fn.loadForm = function(action, formName){
        $.ajax({url: "include/forms/"+action+"-"+formName+".php", success: function(result){
            $("div#form-import-container").html(result);
        }});
    };
}(jQuery));

This works fine but I want the ajax to import to any element I call the function on.

so this doesnt work and I need it too

(function($){
    $.fn.loadForm = function(action, formName){
        $.ajax({url: "include/forms/"+action+"-"+formName+".php", success: function(result){
            $(this).html(result);
        }});
    };
}(jQuery));

Why will this not import anything to the element I have the function called on? nothing happens I get no errors and nothing telling me that its error'd out if I add the error function to the ajax call. I dont see what I am doing wrong the this call it should add the content to the element that the function was called on.

Alex Beyer
  • 147
  • 1
  • 8
  • 2
    Possible duplicate of [How to access the correct \`this\` / context inside a callback?](http://stackoverflow.com/questions/20279484/how-to-access-the-correct-this-context-inside-a-callback) – James Thorpe Dec 10 '15 at 16:45
  • 1
    In your code above, `this` is within the `success` callback and no longer references the element that `loadForm` was called on. The duplicate shows ways around this. Also note that jQuery plugins [_usually_ `return this` so you can chain function calls together](https://learn.jquery.com/plugins/basic-plugin-creation/#chaining). – James Thorpe Dec 10 '15 at 16:46
  • Ah that makes that makes so much more sense. I didn't realize that the ajax call threw off the this reference to a new one. Thank you for the reference I must have been typing in the wrong stuff to find answers similar before I posted the question. – Alex Beyer Dec 10 '15 at 16:52
  • How does your... plugin differ from using, say, $.fn.load other than shortening the url you pass in? you seem to be re-inventing the wheel, or if anything your plugin can be simplified to just forward to $.fn.load. – Kevin B Dec 10 '15 at 17:04

2 Answers2

2

You've overcomplicated your plugin. jQuery has a method that already does what you are trying to do, so it would only make sense to have your plugin use it (or even use the method directly without your plugin.)

(function($){
    $.fn.loadForm = function(action, formName){
        this.load("include/forms/"+action+"-"+formName+".php");
    };
}(jQuery));

This sidesteps the problem you were having by eliminating the callback altogether. Or, you could just not have the plugin, which I think is cleaner, and easier to maintain/debug should any problems arise.

$(document).on('click', '#add', function(){
    $("div#form-import-container").load("include/forms/add-websites.php");
});

As far as your plugin goes, the important thing to remember is that this within the main plugin context will be the jQuery collection, which is why I was able to use this.load(... directly, however within your ajax success callback, it will actually be whatever the ajax method defines it as or window/undefined. In your case the ajax method defines this as the options passed in, however, the ajax method has an option called context that will instead replace the context with whatever you pass in. therefore, your version of the plugin can be fixed like this:

(function($){
    $.fn.loadForm = function(action, formName){
        $.ajax({
            url: "include/forms/"+action+"-"+formName+".php", 
            context: this, // pass `this` as the context of the success callback
            success: function(result){
                this.html(result); // this is already a jQuery collection, no need to wrap it
            }
        });
    };
}(jQuery));
Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • Good point! Guess there's a chance that the OP may want to do further processing once they've got past this point, but if it is exactly as posted, using `.load` is a better approach. – James Thorpe Dec 10 '15 at 17:13
  • This is good to know I will use this in the future but I have to custom build the plugins I am using right now for a project at school :/ not always the faster but wants us to understand more about the jquery plugin programming style. – Alex Beyer Dec 10 '15 at 17:14
  • @AlexBeyer Understandable. I added a section to my answer that shows how to get your version of the plugin working with a correct context. Vixed's answer below solves the problem in basically the same way. – Kevin B Dec 10 '15 at 17:21
  • Awesome that works perfectly thank you for explaining your answer. – Alex Beyer Dec 10 '15 at 19:16
0

Just store your this element. That's it!

(function($){
    $.fn.loadForm = function(action, formName){
        var el=this;
        $.ajax({url: "include/forms/"+action+"-"+formName+".php", success: function(result){
            el.html(result);
        }});
    };
}(jQuery));
Kevin B
  • 94,570
  • 16
  • 163
  • 180
Vixed
  • 3,429
  • 5
  • 37
  • 68