jQuery proxy not getting correct context - javascript

I am using the jQuery boilerplate and am trying to call one function from within another function and thought that Proxy might be the way to achieve that. Unfortunately I can't seem to get this to work.
Below is a heavily stripped down version of the code I am using, but you should be able to get the idea. Inside the ajax success method, I am trying to call the function customSelect so that I can reapply my select styling on elements created when the ajax is run. Unfortunately I'm unable to get this to work:
;( function( $, window, document, undefined ) {
"use strict";
var pluginName = "serviceFinder",
defaults = {
propertyName: "value"
};
// The actual plugin constructor
function Plugin ( element, options ) {
this._name = pluginName;
this.init();
}
// Avoid Plugin.prototype conflicts
$.extend(Plugin.prototype, {
init: function() {
this.customSelect("lm-service-finder__field--select");
},
/**
* When a user selects a product
*/
selectProduct: function(e){
// Send the ID of the selected product so that we can get the variations for that product.
$.ajax({
type: 'POST',
url: themeVars.ajax,
dataType: 'json',
data: {
'product_id': selectedProductId,
action: 'servicefinder_get_product_attributes' //this is the name of the AJAX method called in WordPress
}, success: function (result) {
$.proxy(Plugin.customSelect);
},
error: function () {
console.log("error");
}
});
},
/**
* Custom select field styling
*/
customSelect: function(selector) {
console.log("Apply select field styling");
},
});
$.fn[ pluginName ] = function( options ) {
return this.each( function() {
if ( !$.data( this, "plugin_" + pluginName ) ) {
$.data( this, "plugin_" +
pluginName, new Plugin( this, options ) );
}
} );
};
} )( jQuery, window, document );
I have seen a couple of other similar questions here, but with no answer. Hope someone can assist?

Related

javascript eventlistener not working for ajax loaded content

Hello I have loaded div via ajax and wanted to give javascript eventlistener with addEventListener method but this not working. Here below is my code
var QuantityMiniCart = function() {
var infor = document.querySelectorAll( '.mini-cart-product-infor' );
if ( ! infor.length ) {
return;
}
};
(function () {
document.addEventListener('DOMContentLoaded',function () {
QuantityMiniCart();
})
})();
infor.forEach(
function( ele, i ) {
input = ele.querySelector( 'input.qty' ),
}
// Check valid quantity.
input.addEventListener(
'change',
function() {
}
);
}
);
here is ajax code
$.ajax({
type: 'POST',
url: add_mini_cart_ajax.ajax_url,
data: {
action : 'mode_theme_update_mini_cart'
},
success: function( response ) {
$('.confirm-product').html(response);
},
error: function(e) {
console.log(e)
return;
}
});
The .confirm-product containing .mini-cart-product-infor which is loading from ajax. Please help for this
querySelectorAll can only select elements which exist at the time that command is run. It can't do anything which elements which don't exist yet!
So if you're loading more content via AJAX, after you've run the code shown in your question, then you'll need to separately add event listeners to any newly-downloaded elements, once the AJAX call is complete.

Automatically initialise a custom jQuery plugin

I'm in the process of creating a new accordion plugin using the jQuery Boilerplate as a starting point.
I'm a jQuery novice when it comes to building plugins but it currently seems to be working great.
The user can initialize the plugin the traditional way ( $('elem').plugin({"option":"value"}) ) or inline, on the element itself ( <div data-plugin='{"option":"value"}'> ).
The issue is the plugin needs to be called outside of the plugin code, inside a document ready for each method ( For example - $('elem').plugin() ).
What I want to do with this plugin is have the plugin automatically initialize on set element(s) within the markup, such as <div data-accordion>. I've tried wrapping the element in a jQuery wrapper,inside a document ready but it doesn't seem to work.
The code for the boilerplate is:
;( function( $, window, document, undefined ) {
"use strict";
var pluginName = "defaultPluginName",
defaults = {
propertyName: "value"
};
function Plugin ( element, options ) {
this.element = element;
this.settings = $.extend( {}, defaults, options );
this._defaults = defaults;
this._name = pluginName;
this.init();
}
$.extend( Plugin.prototype, {
init: function() {
this.yourOtherFunction( "jQuery Boilerplate" );
},
yourOtherFunction: function( text ) {
$( this.element ).text( text );
}
} );
$.fn[ pluginName ] = function( options ) {
return this.each( function() {
if ( !$.data( this, "plugin_" + pluginName ) ) {
$.data( this, "plugin_" +
pluginName, new Plugin( this, options ) );
}
} );
};
} )( jQuery, window, document );
Hope someone out there can help.
Thanks :)

Uncaught TypeError: undefined is not a function with custom jQuery Plugin

I have made a wrapper plugin for the jquery autocomplete plugin as we use it everywhere on our projects and need to globally change it at times, however whenever i reference the plugin i get the error: Uncaught TypeError: undefined is not a function my pluggin looks like so:
(function ($) {
$.fn.CustomAutocomplete = function (options) {
//Settings
alert("test");
var settings = $.extend({
//Defaults
ContollerMethodLink: "",
ReturnElement: ""
}, options);
$(this).autocomplete({
source: function (request, response) {
var employees = new Array();
$.ajax({
async: false,
cache: false,
type: "POST",
url: ContollerMethodLink,
data: { "query": request.term },
success: function (data) {
for (var i = 0; i < data.length; i++) {
employees[i] = { label: data[i].Key, Id: data[i].Value };
}
}
});
response(employees);
},
select: function (event, ui) {
//fill selected customer details on form
var id = ui.item.Id;
$('#' + settings.ReturnElement).val(id);
}
});
}
})(jQuery);
I then call it like so:
$(document).ready(function() {
$('#AddReportingEmpText').CustomAutocomplete({
ReturnElement: "AddReportingEmpId",
ContollerMethodLink: "#(Url.Action("Method", "Controllers"))",
});
});
However when i try to use this i get the said error in a random empty space right above $(document).ready(function() { if i hard code out the ajax request in the spot where i am currently calling my plugin, everything works fine. Any ideas?
Edit:
worth noting this is my JS File call:
<script src="http://code.jquery.com/jquery-1.9.1.js" type="text/javascript"></script>
<script src="http://code.jquery.com/ui/1.10.2/jquery-ui.js" type="text/javascript"></script>
I then call my plugin file and the debugger shows me it is being properly included
This appears to be well known problem with recent versions of Chrome. Using FF browser will provide with more detailed information about the error

Dynamically added elements don't wrap

In my plug-in I need to wrapp all sidebar's children in a div to let them overflow but if those elements are loaded dynamically the function does not work and I don't know either how to make it work.
The code is:
<div class="sidebar">
</div>
var $sidebar = $( '.sidebar' );
$sidebar.load( 'external-page.ext' );
$sidebar.MyPlugin();
$.fn.MyPlugin = function() {
this.wrapInner( '<div />' );
});
If those elements are not loaded dynamically there is no problem.
Firstly the code was:
$sidebar.wrapInner( '<div/>' );
and this just works fine if elemens are not loaded dynamically, so I tried this way:
var children = $sidebar.children();
$( document ).on( 'load', children, function() {
$( this ).wrapAll( '<div />' );
});
but, of course it does not work.
Can you please help me?
I thought that this rule would have worked this time too but it didn't. What did I mistake?
You can find the whole code here.
And a demo here
MORE DETAILS
I want to handle this issue from the inside, not from the outside! I don't know if users will load content dinamically or not. that's the point.
So there is a way to handle this issue inside the plugin and not outside?
From the manual
http://api.jquery.com/load/
Callback Function
If a "complete" callback is provided, it is executed after
post-processing and HTML insertion has been performed. The callback is
fired once for each element in the jQuery collection, and this is set
to each DOM element in turn.
Try the following code and see if this works:
$sidebar.load( 'external-page.ext', function() { $sidebar.MyPlugin(); } );
Thanks.
$.load() makes an ajax call to load the data ,
So there is a possibility that your this.wrapInner( '<div />' ) method has invoked before any data is loaded inside the div.sidebar.
Make sure this.wrapInner( '<div />' ) is called after all data has been loaded successfully using the complete callback.
$.load() trigger callback for each div ,call your plugin from callback
$sidebar.load('http://fiddle.jshell.net/vikrant47/ncagab2y/1/show/', function () {
$(this).MyPlugin();
}
});
DEMO
OR
If you are using $.load() only to load inside multiple elements then you could probably use one of the more powerful jQuery ajax methods (i.e., get() or post() or ajax()).
$.get('http://fiddle.jshell.net/vikrant47/ncagab2y/1/show/', {}, function(data) {
$sidebar.html(data).MyPlugin();
});
DEMO using $.get() Method
UPDATE-
Answer to the comment-
You should not have to worry about weather user gonna call your plugin like this $sidebar.load(...).MyPlugin().User must be aware enough about how to handle asynchronous methods.
You can not make your plugin work until there is some data inside div.slider
but ,you can add ajax loading functionality inside your plugin like -
$(document).ready(function () {
$.fn.MyPlugin = function (options) {
var $elem=this;
var init = function () {
options.load = $.extend({}, $.fn.MyPlugin.defaultOptions.load, options.load);
load();
}
//adding load method to load data dynamically
var load = function () {
if (!options.load.url) {
alert("url can not be empty");
} else {
$.ajax({
url: options.load.url,
type: options.load.type,
data: options.load.data,
success: function (response) {
options.load.success.call(this, response);
$elem.html(response).wrapInner('<div class="wrapper"/>');//wrap after data has been loaded successfully
},
error : function (jqXHR, textStatus, errorThrown) {
alert("error occured" + textStatus + " ," + errorThrown)
}
})
}
}
init();
}
$.fn.MyPlugin.defaultOptions = {
load: {
tye: "get",
data: {},
success: function () {}
}
};
Now use your plugin like-
var $sidebar = $('.sidebar');
$sidebar.MyPlugin({
load: {
url: 'http://fiddle.jshell.net/vikrant47/ncagab2y/1/show/'
}
});
});
DEMO with load
Try adding adding below piece to plugin . Added at lines 84 - 110 at gist .
var target = $sidebar.get(0);
// create an observer instance
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
// do stuff when
// `childList` modified
// i.e.g.,
$.each(mutation.addedNodes, function (k, v) {
$(v)
.wrapInner('<div data-'
+ dataName
+ '="sub-wrapper"></div>')
})
});
});
// configuration of the observer:
var _config = {
childList: true
};
// pass in the target node, as well as the observer options
observer.observe(target, _config);
jsfiddle http://jsfiddle.net/guest271314/s5wzptc8/
See MutationObserver

Jquery Plugin return On Selection/Click

On getting no answer on my previous question , I decided to go on with this plugin structure.
(function ( $ ) {
$.fn.myPlugin = function (options) {
options = $.extend( {}, $.fn.myPlugin.defaults, options );
return this.each(function (i, el) {
("someiD").live("click",function() {
UpdateCounter();
});
});
};
$.fn.myPlugin.defaults = {
///options here for overiding
};
}(jQuery));
I have made a plugin in which I have to select a button to increase a counter and then I don't know how to get the updated values of the counter that is OnSelect/OnClick of the button.... Can anyone give me any insights on how should I be dealing with this without changing my plugin structure?
Basically like this:
(function ( $ ) {
$.fn.myPlugin = function (options) {
options = $.extend( {}, $.fn.myPlugin.defaults, options );
// $(this) is your selected element, #someSelect in this case
$(this).on('select', function(e) {
console.log('selected!')
})
};
// execute your plugin on the selected element
$('#someSelect').myPlugin();

Categories