Automatically initialise a custom jQuery plugin - javascript

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 :)

Related

jQuery proxy not getting correct context

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?

BackboneJS not creating the Wrapper div

I am creating a simple backbone template popup. Backbone is not creating the Wrapping <div> element that it was suppose to create. When the template is being generated there is no <div class="theme-overlay"> is generated. Backbone dumps the html from template without any wrapper.
I have searched around but I haven't found any similar issue. I am very new with Backbone so I think I am missing something.
NOTE: I am working with WordPress environment that is why there is an wp global variable wp.Backbone is an internal adaptation of Backbone for avoiding conflict with PHP. Using Backbone.View.extend() instead of wp.Backbone.View.extend() gives me the same result.
Find Code Below
window.wp = window.wp || {};
(function($){
var importer = {};
importer.data = _kallzuDemoSettings;
_.extend( importer, { model: {}, view: {}, routes: {}, router: {}, template: wp.template });
importer.View = wp.Backbone.View.extend({
template: wp.template('demo'),
el: '#theme-overlay',
className: 'theme-overlay',
events: {
'click .close' : 'collapse'
},
render: function(demo_title){
var data = _.find(importer.data.demos, function(item){
return item.name == demo_title;
});
if( data == undefined ){
alert( 'No data found!');
return;
}
this.$el.html( this.template( data ) ); // insert into dom
},
collapse: function( event ) {
var self = this;
event = event || window.event;
if ( $( event.target ).is( '.close' ) ) {
// Add a temporary closing class while overlay fades out
$( 'body' ).addClass( 'closing-overlay' );
// With a quick fade out animation
this.$el.fadeOut( 130, function() {
// Clicking outside the modal box closes the overlay
$( 'body' ).removeClass( 'closing-overlay' );
// Handle event cleanup
self.closeOverlay();
});
}
},
closeOverlay: function() {
$( 'body' ).removeClass( 'modal-open' );
this.remove();
this.unbind();
this.trigger( 'importer:collapse' );
},
});
window.installDemo = function( demo_title ){
var view = new importer.View();
view.render( demo_title );
}
})(jQuery);
I don't think other part of the script like the template isn't necessary to show. But if you need them let me know in the comment.
You should remove the el: '#theme-overlay' and instead append the view to it after init.
window.installDemo = function( demo_title ){
var view = new importer.View();
view.$el.appendTo('#theme-overlay')
view.render( demo_title );
}
This way, your wrapper div will be created and then appended to the div.
The DOM should end up looking like:
<div id="theme-overlay">
<div class="theme-overlay"><!-- your rendered content --></div>
</div>

jquery autocomplete with different sources

I hope you can help me. I'm looking for a possibility to make my jquery autocompleter use a different source whether the first input is a digit or a letter (on the fly). I tried days and could not make it working.
Thats the autocomplete code:
$(function() {
$("#ac1").autocomplete(
'search.php', //or blub.php
{onItemSelect: function(item) {
var text = 'test';
$("#num1").val(item.data);
var selector = $("#num1").val();
var additionalradius = selector.substring(0,3);
var zip = selector.substring(6);
$("#num1").val(additionalradius);
$("#3rd").val(zip);
alert (additionalradius);
}},
{selectFirst: true}
);
});
So I need something like "if first key in field #ac1 is a number, then use search.php. Else use blub.php" in that code shown. Any idea? Thank you for you help.
To set the source option in search event ( that is triggered before a search is performed ) is one way to do it.
$("#ac1").autocomplete({
source: 'search.php',
search: function( event, ui ) {
if ( isNaN( parseInt( $(this).val().charAt(0) ) ) )
$(this).autocomplete( 'option', 'source', 'blub.php' );
else
$(this).autocomplete( 'option', 'source', 'search.php' );
}
});
EDIT:
$("#ac1").autocomplete({
source: 'search.php',
search: function( event, ui ) { /* code from search function here */ },
select: function( event, ui ) { /* code for item select here */ }
/* additional options */
});

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();

Why a separately defined function does not work on a "domready" event in JavaScript?

I am quite new to JavaScript. I am trying to set equal heights to some elements. I managed to do everything except moving the function outside the "addEvent" declaration.
In other words, this code works:
window.addEvent('domready', function() {
var elements = $$( 'div#leftcolumn div.module_menu' );
if( elements && elements.length > 1 ) {
var heights = [];
elements.each( function( el ) {
heights.push( el.getStyle('height').toInt() );
});
maxHeight = Math.max.apply( Math, heights ) + "px";
elements.each( function( el ) {
el.setStyle('height', maxHeight );
});
delete(heights);
}
}
);
while this code does NOT work:
function matchHeight( selector ) {
var elements = $$( selector );
if( elements && elements.length > 1 ) {
var heights = [];
elements.each( function( el ) {
heights.push( el.getStyle('height').toInt() );
});
maxHeight = Math.max.apply( Math, heights ) + "px";
elements.each( function( el ) {
el.setStyle('height', maxHeight );
});
delete(heights);
}
}
window.addEvent( 'domready', matchHeight( 'div#leftcolumn div.module_menu' ) );
I already test with simpler functions and it works, like e.g:
window.addEvent('domready', function() { alert('test'); } )
is equivalent to
function giveMessage() { alert('test'); }
window.addEvent( 'domready', giveMessage())
why is that?
It's because you need to remove the parenthesis; a function is an object, and you need to pass the function, not its return value. So, for your first example, you should have:
window.addEvent('domready', function() { matchHeight('div#leftcolumn div.module_menu'); } );
Instead. For your second example, it's:
function giveMessage() { alert('test'); }
window.addEvent( 'domready', giveMessage)
Again, you pass the object giveMessage, not the result obtained after invoking it.
You forgot to put your matchHeight call in a closure. Change your last line to:
window.addEvent( 'domready', function(){matchHeight( 'div#leftcolumn div.module_menu' )} );
K so that link is looking for a pointer to the function. When you pass it an anonymous function (as in eg #1) that function is created/stored in memory, and that location is passed in. Your second case though, JS executes the function (because of your brackets+arguments) and then passes the result as the pointer... which isn't want you want.
What you'd need to do instead is:
function setup() {
matchHeight( 'div#leftcolumn div.module_menu');
}
window.addEvent('domready',setup);
Or still use an anonymous function:
window.addEvent('domready',
function() {matchHeight( 'div#leftcolumn div.module_menu');});
FWIW window.addEvent isn't totally cross-browser compatible, see also window.attachEvent

Categories