i've a little problem with an event throwing from a plugin. My plugin is throwing an event calling 'initNewHeight' and this is working fine. And now i want to send the changed value in the plugin to the function whitch called this plugin...
like so:
(function($) {
$.fn.meAutoSize = function (options, callback){
var $this = $(this);
var $options = options || {};
/* Optionen welche übergeben wurden in eine Variable speichern und mit den Standardwerten verbinden */
$options = $.extend($.fn.meAutoSize.defaults, options);
/* Event an den EventHandler binden */
$this.bind("initEvent", function() { options.init.call(); });
/* Initialize Event auslösen, neu Inhalte laden */
$this.trigger("initEvent", $this);
/* Initialize Event auslösen, neu Inhalte laden */
$this.bind("initEventNewHeight", function() { options.initNewHeight.call() });
var newHeight = 12
$this.trigger("initEventNewHeight", $this, newHeight);
};
// Standard-Optionen für das Plugin
$.fn.meAutoSize.defaults = {
init: function() {},
initNewHeight: function(el, newHeight) {}
}
})(jQuery);
$('.autoheight').meAutoSize({
init: function() {
$('#Init').html('init function')
},
initNewHeight: function(el, newHeight) {
$('#NewHeight').html('NewHeight: ' + el +', ' + newHeight)
}
});
but this way doesn't work.
so you can see it here: http://jsfiddle.net/Tabes/qRPfm/
try changing, this:
$this.bind("initEventNewHeight", function() { options.initNewHeight.call() });
to:
$this.bind("initEventNewHeight", function() { options.initNewHeight.call($this, $this, 120) });
There are a lot of issues with your plugin and I strongly advise you to read at least this tutorial.
Updated Fiddle Note that I did not fixed the points mentionned below, I just made it work like you expected
If you pass multiple arguments to trigger, you need to wrap them in an array.
$this.trigger("initEventNewHeight", [$this, newHeight]);
Within a jQuery object prototype function (your plugin function), this points to the jQuery object, not a DOM node. Therefore, var $this = $(this); doesn't do what you think it does. Also, the way your code is structured will cause issues if the jQuery set on which your plugin is called encapsulates multiple DOM elements.
Your plugin function should look like:
return this.each(function {
/*apply plugin to 'this', which now is a DOM node*/
});
bind is deprecated, use on.
Arguments do not fall of the sky, I do not see how you expected to get any value at all since you were not passing any.
$this.bind("initEventNewHeight", function(e, el, newHeight) {
//passing el is not necessary since the context will already be $this
options.initNewHeight.call($this, el, newHeight);
});
You should consider using the DOM element itself as an event emitter and leverage the jQuery event architecture to publish your events rather than relying on callbacks functions like you do.
//E.g.
var someEvent = $.Event('myCustomEvent');
someEvent.someParam = 'some value';
$(domElOfYourPlugin).trigger(someEvent);
Now clients can register handlers like $(domElOfYourPlugin).on('myCustomEvent', ...)
Related
I need to find which event handlers are registered over an object.
For example:
$("#el").click(function() {...});
$("#el").mouseover(function() {...});
$("#el") has click and mouseover registered.
Is there a function to find out that, and possibly iterate over the event handlers?
If it is not possible on a jQuery object through proper methods, is it possible on a plain DOM object?
As of jQuery 1.8, the event data is no longer available from the "public API" for data. Read this jQuery blog post. You should now use this instead:
jQuery._data( elem, "events" );
elem should be an HTML Element, not a jQuery object, or selector.
Please note, that this is an internal, 'private' structure, and shouldn't be modified. Use this for debugging purposes only.
In older versions of jQuery, you might have to use the old method which is:
jQuery( elem ).data( "events" );
You can do it by crawling the events (as of jQuery 1.8+), like this:
$.each($._data($("#id")[0], "events"), function(i, event) {
// i is the event type, like "click"
$.each(event, function(j, h) {
// h.handler is the function being called
});
});
Here's an example you can play with:
$(function() {
$("#el").click(function(){ alert("click"); });
$("#el").mouseover(function(){ alert("mouseover"); });
$.each($._data($("#el")[0], "events"), function(i, event) {
output(i);
$.each(event, function(j, h) {
output("- " + h.handler);
});
});
});
function output(text) {
$("#output").html(function(i, h) {
return h + text + "<br />";
});
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="el">Test</div>
<code>
<span id="output"></span>
</code>
For jQuery 1.8+, this will no longer work because the internal data is placed in a different object.
The latest unofficial (but works in previous versions as well, at least in 1.7.2) way of doing it now is -
$._data(element, "events")
The underscore ("_") is what makes the difference here. Internally, it is calling $.data(element, name, null, true), the last (fourth) parameter is an internal one ("pvt").
Shameless plug, but you can use findHandlerJS
To use it you just have to include findHandlersJS (or just copy&paste the raw javascript code to chrome's console window) and specify the event type and a jquery selector for the elements you are interested in.
For your example you could quickly find the event handlers you mentioned by doing
findEventHandlers("click", "#el")
findEventHandlers("mouseover", "#el")
This is what gets returned:
element
The actual element where the event handler was registered in
events
Array with information about the jquery event handlers for the event type that we are interested in (e.g. click, change, etc)
handler
Actual event handler method that you can see by right clicking it and selecting Show function definition
selector
The selector provided for delegated events. It will be empty for direct events.
targets
List with the elements that this event handler targets. For example, for a delegated event handler that is registered in the document object and targets all buttons in a page, this property will list all buttons in the page. You can hover them and see them highlighted in chrome.
You can try it here
I use eventbug plugin to firebug for this purpose.
I've combined both solutions from #jps to one function:
jQuery.fn.getEvents = function() {
if (typeof(jQuery._data) === 'function') {
return jQuery._data(this.get(0), 'events') || {};
}
// jQuery version < 1.7.?
if (typeof(this.data) === 'function') {
return this.data('events') || {};
}
return {};
};
But beware, this function can only return events that were set using jQuery itself.
To check for events on an element:
var events = $._data(element, "events")
Note that this will only work with direct event handlers, if you are using $(document).on("event-name", "jq-selector", function() { //logic }), you will want to see the getEvents function at the bottom of this answer
For example:
var events = $._data(document.getElementById("myElemId"), "events")
or
var events = $._data($("#myElemId")[0], "events")
Full Example:
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" type="text/javascript"></script>
<script>
$(function() {
$("#textDiv").click(function() {
//Event Handling
});
var events = $._data(document.getElementById('textDiv'), "events");
var hasEvents = (events != null);
});
</script>
</head>
<body>
<div id="textDiv">Text</div>
</body>
</html>
A more complete way to check, that includes dynamic listeners, installed with $(document).on
function getEvents(element) {
var elemEvents = $._data(element, "events");
var allDocEvnts = $._data(document, "events");
for(var evntType in allDocEvnts) {
if(allDocEvnts.hasOwnProperty(evntType)) {
var evts = allDocEvnts[evntType];
for(var i = 0; i < evts.length; i++) {
if($(element).is(evts[i].selector)) {
if(elemEvents == null) {
elemEvents = {};
}
if(!elemEvents.hasOwnProperty(evntType)) {
elemEvents[evntType] = [];
}
elemEvents[evntType].push(evts[i]);
}
}
}
}
return elemEvents;
}
Example usage:
getEvents($('#myElemId')[0])
As of 1.9 there is no documented way to retrieve the events, other than to use the Migrate plugin to restore the old behavior. You could use the _.data() method as jps mentions, but that is an internal method. So just do the right thing and use the Migrate plugin if you need this functionality.
From the jQuery documentation on .data("events")
Prior to 1.9, .data("events") could be used to retrieve jQuery's
undocumented internal event data structure for an element if no other
code had defined a data element with the name "events". This special
case has been removed in 1.9. There is no public interface to retrieve
this internal data structure, and it remains undocumented. However,
the jQuery Migrate plugin restores this behavior for code that depends
upon it.
I created a custom jQuery selector that checks against both jQuery's cache of assigned event handlers as well as elements that use the native method for adding them:
(function($){
$.find.selectors[":"].event = function(el, pos, match) {
var search = (function(str){
if (str.substring(0,2) === "on") {str = str.substring(2);}
return str;
})(String(match[3]).trim().toLowerCase());
if (search) {
var events = $._data(el, "events");
return ((events && events.hasOwnProperty(search)) || el["on"+search]);
}
return false;
};
})(jQuery);
Example:
$(":event(click)")
This will return elements that have a click handler attached to them.
In a modern browser with ECMAScript 5.1 / Array.prototype.map, you can also use
jQuery._data(DOCUMENTELEMENT,'events')["EVENT_NAME"].map(function(elem){return elem.handler;});
in your browser console, which will print the source of the handlers, comma delimited. Useful for glancing at what all is running on a particular event.
Events can be retrieved using:
jQuery(elem).data('events');
or jQuery 1.8+:
jQuery._data(elem, 'events');
Note:
Events bounded using $('selector').live('event', handler)
can be retrieved using:
jQuery(document).data('events')
jQuery is not letting you just simply access the events for a given element.
You can access them using undocumented internal method
$._data(element, "events")
But it still won't give you all the events, to be precise won't show you events assigned with
$([selector|element]).on()
These events are stored inside document, so you can fetch them by browsing through
$._data(document, "events")
but that is hard work, as there are events for whole webpage.
Tom G above created function that filters document for only events of given element and merges output of both methods, but it had a flaw of duplicating events in the output (and effectively on the element's jQuery internal event list messing with your application).
I fixed that flaw and you can find the code below. Just paste it into your dev console or into your app code and execute it when needed to get nice list of all events for given element.
What is important to notice, element is actually HTMLElement, not jQuery object.
function getEvents(element) {
var elemEvents = $._data(element, "events");
var allDocEvnts = $._data(document, "events");
function equalEvents(evt1, evt2)
{
return evt1.guid === evt2.guid;
}
for(var evntType in allDocEvnts) {
if(allDocEvnts.hasOwnProperty(evntType)) {
var evts = allDocEvnts[evntType];
for(var i = 0; i < evts.length; i++) {
if($(element).is(evts[i].selector)) {
if(elemEvents == null) {
elemEvents = {};
}
if(!elemEvents.hasOwnProperty(evntType)) {
elemEvents[evntType] = [];
}
if(!elemEvents[evntType].some(function(evt) { return equalEvents(evt, evts[i]); })) {
elemEvents[evntType].push(evts[i]);
}
}
}
}
}
return elemEvents;
}
I have to say many of the answers are interesting, but recently I had a similar problem and the solution was extremely simple by going the DOM way. It is different because you don't iterate but aim directly at the event you need, but below I'll give a more general answer.
I had an image in a row:
<table>
<td><tr><img class="folder" /></tr><tr>...</tr></td>
</table>
And that image had a click event handler attached to it:
imageNode.click(function () { ... });
My intention was to expand the clickable area to the whole row, so I first got all images and relative rows:
tableNode.find("img.folder").each(function () {
var tr;
tr = $(this).closest("tr");
// <-- actual answer
});
Now in the actual anwer line I just did as follows, giving an answer to the original question:
tr.click(this.onclick);
So I fetched the event handler directly from the DOM element and put it into the jQuery click event handler. Works like a charm.
Now, to the general case. In the old pre-jQuery days you could get all events attached to an object with two simple yet powerful functions gifted to us mortals by Douglas Crockford:
function walkTheDOM(node, func)
{
func(node);
node = node.firstChild;
while (node)
{
walkTheDOM(node, func);
node = node.nextSibling;
}
}
function purgeEventHandlers(node)
{
walkTheDOM(node, function (n) {
var f;
for (f in n)
{
if (typeof n[f] === "function")
{
n[f] = null;
}
}
});
}
Try jquery debugger plugin if you're using chrome: https://chrome.google.com/webstore/detail/jquery-debugger/dbhhnnnpaeobfddmlalhnehgclcmjimi?hl=en
Another way to do it is to just use jQuery to grab the element, then go through actual Javascript to get and set and play with the event handlers. For instance:
var oldEventHandler = $('#element')[0].onclick;
// Remove event handler
$('#element')[0].onclick = null;
// Switch it back
$('#element')[0].onclick = oldEventHandler;
I combined some of the answers above and created this crazy looking but functional script that lists hopefully most of the event listeners on the given element. Feel free to optimize it here.
var element = $("#some-element");
// sample event handlers
element.on("mouseover", function () {
alert("foo");
});
$(".parent-element").on("mousedown", "span", function () {
alert("bar");
});
$(document).on("click", "span", function () {
alert("xyz");
});
var collection = element.parents()
.add(element)
.add($(document));
collection.each(function() {
var currentEl = $(this) ? $(this) : $(document);
var tagName = $(this)[0].tagName ? $(this)[0].tagName : "DOCUMENT";
var events = $._data($(this)[0], "events");
var isItself = $(this)[0] === element[0]
if (!events) return;
$.each(events, function(i, event) {
if (!event) return;
$.each(event, function(j, h) {
var found = false;
if (h.selector && h.selector.length > 0) {
currentEl.find(h.selector).each(function () {
if ($(this)[0] === element[0]) {
found = true;
}
});
} else if (!h.selector && isItself) {
found = true;
}
if (found) {
console.log("################ " + tagName);
console.log("event: " + i);
console.log("selector: '" + h.selector + "'");
console.log(h.handler);
}
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="parent-element">
<span id="some-element"></span>
</div>
It's been a while since I've done a jQuery plugin and I'm working off a pretty common boilerplate with options and internal events. In one of the internal methods I need to trigger a custom event so that other pages can capture the event and work with it. More specifically in this usage, at the end of drawing on a canvas element I want to be able to capture the event outside of the plugin in order to grab the canvas content for sending elsewhere agnostic of the plugin itself.
However, it doesn't appear that the trigger call is either firing or finding the bound event from the other page. None of the console messages show up in Firebug.
Here's my sample plugin (simplified):
; (function ($, window, document, undefined) {
"use strict";
var $canvas,
context,
defaults = {
capStyle: "round",
lineJoin: "round",
lineWidth: 5,
strokeStyle: "black"
},
imgElement,
options,
pluginName = "myPlugin";
function MyPlugin(element, opts) {
this.imgElement = element;
this.options = $.extend({}, defaults, opts);
this._defaults = defaults;
this._name = pluginName;
this.init();
}
$.extend(MyPlugin.prototype, {
init: function () {
var $imgElement = $(this.imgElement);
$canvas = $(document.createElement("canvas")).addClass("myPluginInstances");
$imgElement.after($canvas);
context = $canvas[0].getContext("2d");
$canvas.on("mousedown touchstart", inputStart);
$canvas.on("mousemove touchmove", inputMove);
$canvas.on("mouseup touchend", inputEnd);
}
});
$.fn.myPlugin = function (opts) {
return this.each(function () {
if (!$.data(this, "plugin_" + pluginName)) {
$.data(this, "plugin_" + pluginName, new MyPlugin(this, opts));
}
});
};
function inputStart(event) {
//...processing code
}
function inputMove(event) {
//...processing code
}
function inputEnd(event) {
//...processing code
// Trigger custom event
$(this.imgElement).trigger("mydrawevent", [this.toDataURL()]);
}
}(jQuery, window, document));
Then from a separate page in the document.ready the event is bound:
$(".myPluginInstances").myPlugin().on("mydrawevent", function (e, data) {
console.log("mydrawevent");
console.log(data);
});
From Firebug I am seeing that the imgElement does have the listener bound:
mydrawevent
-> function(a)
-> function(e, data)
I've tried quite a few things such as calling the trigger on different DOM elements, passing the event parameter data in and out of the array, defining a callback method instead (which had its own issues), and more. I have a feeling the problem is something dumb and right in front of me but I could use more sets of eyes to double check my sanity.
As further explanation for my response to Vikk above, the problem was indeed scoping and understanding which objects were bound to what parts of the plugin. In my case, the internal methods that are private event handlers were bound to my canvas element but the plugin itself was being instantiated on the img element which is at least a temporary requirement of this particular implementation.
Based on this, from the internal event handler the use of $(this) meant that it was trying to use trigger on my canvas element and not the img element which had the mydrawevent listener attached to it from outside the plugin.
i have written following jquery plugin. what i am trying to do is, when the user click on a link make the relevant div display: block base on the data attribute. But this plugin does not work. i have bn trying to figure this out for last two days. But i failed.
My HTML
<div class="container1">
asd
<div class="window1" data-window="a">
asd
</div>
</div>
<hr>
<div class="container2">
asdf1
asdf2
asdf3
<div class="window2" data-window="b">
asdf1
</div>
<div class="window2" data-window="c">
asdf2
</div>
<div class="window2" data-window="d">
asdf3
</div>
</div>
<script src="jquery-1.11.0.min.js"></script>
<script src="script.js"></script>
<script>
$('.container1').myPlugin({
link: $('.link1'),
container : $('.window1')
});
$('.container2').myPlugin({
link: $('.link2'),
container : $('.window2')
});
</script>
plugin
(function ($, window, document, undefind) {
MyPlugin = {
init : function (options, element) {
$.fn.myPlugin.config = $.extend({}, $.fn.myPlugin.config, options);
var link = $.fn.myPlugin.config.link;
link.on('click', this.secondFunc);
},
secondFunc : function () {
var dataLinkId = $(this).data('link'),
container = $($.fn.myPlugin.config).filter('[data-section="' + dataLinkId + '"]');
container.show();
}
};
$.fn.myPlugin = function(options) {
return this.each(function () {
var rezG = Object.create(MyPlugin);
rezG.init(options, this);
});
};
$.fn.myPlugin.config = {
link: $('.link'),
container : $('.container')
};
})(jQuery, window, document);
CSS
.window1, .window2 {
display: none;
}
DEMO
You need to use var to make sure your variables are all local and not global.
var MyPlugin = {
// ...
};
Also, in the init function, you are doing this:
$.fn.myPlugin.config = $.extend({}, $.fn.myPlugin.config, options);
This is overwriting $.fn.myPlugin.config which is the default options. This means that all elements that call myPlugin() will use the same config. You need to set the config on just the one instance.
this.config = $.extend({}, $.fn.myPlugin.config, options);
Your secondFunc doesn't have a reference to the object (rezG) instance, so it cannot access the config. You need to pass that to secondFunc(). One way is to use a closure to capture the instance.
secondFunc: function (rezG) {
return function(){
var dataLinkId = $(this).data('link'),
container = $(rezG.config.container).filter(function(){
return $(this).data('window') == dataLinkId;
});
container.show();
};
}
Then you bind it like so:
link.on('click', this.secondFunc(this));
Note that in secondFunc, you need to use config.container(not just config which is the object), and also your attribute is data-window, not data-section.
Updated demo: http://jsfiddle.net/K82gg/7/
Your plugin could be as simple as
(function ($, window, document, undefind) {
$.fn.myPlugin = function(options) {
// When $(stuff).myPlugin(...) is called
// this keyword inside of myPlugin function is referencing a set
// of elements plugin was called upon
// e.g. for call like $('.container1').myPlugin();
// this keyword will reference all elements selected by
// $('.container1') not jquery wrapped,
// in general it can be a any number.
return this.each(function pluginImplementation () {
// Here we iterate over the set, and for each element in the set
// we do some pretty standard click
var container = $(this);
// I use 'click.myPlugin' event instead just 'click' ale to later on
// do $(..).off('click.myPlugin') to remove only handlers that were
// attached by plugin (a good practice)
container.on('click.myPlugin', options.linkSelector, function(){
var dataLinkId = $(this).data('link');
container.find('[data-window="' + dataLinkId + '"]').toggle();
})
});
};
})(jQuery, window, document);
See the jsfiddle
However the code above may have a problem luginImplementation () function is created on each iteration and if the body of that function would be something more complicated it would be a mess. That is why it's better to create pluginImplementation () outside.
(function ($, window, document, undefind) {
// Notice that pluginImplementation () now accepts parameters
// They make it possible for pluginImplementation to know which
// elements it's working with
function pluginImplementation (container, options) {
container.on('click.myPlugin', options.linkSelector, function(){
var dataLinkId = $(this).data('link');
container.find('[data-window="' + dataLinkId + '"]').toggle();
})
}
$.fn.myPlugin = function(options) {
return this.each(function () {
pluginImplementation($(this), options);
});
};
})(jQuery, window, document);
The demo
That separation may be not good enough. You may want your plugin to be more OOP and what not. So you can go all OOPy like that:
(function ($, window, document, undefind) {
// For that purpose we create a class
// That describes behavior that our plugin provides
//
function MyPlugin(container, options) {
this.container = container;
this.options = options;
// To the topic of maintainability
// This could be parametrised as an option at plugin instantiation
this.eventName = 'click.myPlugin';
}
MyPlugin.prototype.attachClickHandlers = function() {
var self = this;
// This gets a little messy with all the thises vs selfs and a
// noname function wrapping the handler.
// The point is to preserve this keyword reference
// inside of clickHandler method.
// If I would have just self.clickHandler as a handler there
// this keyword inside of self.clickHandler would reference to
// whatever $(...).on binds handlers to i.e. triggering element.
// I need this keyword inside of self.clickHandler to point to
// "current" instance of MyPlugin, that's why I have wrapping
// function. It just lets me call clickHandler in the right context.
// clickHandler method also needs to know what link is being clicked
// so we pass that in as parameter.
self.container.on(self.eventName,
self.options.linkSelector,
function() {
self.clickHandler($(this));
})
}
MyPlugin.prototype.clickHandler = function(clickedLink) {
var dataLinkId = clickedLink.data('link');
this.container.find('[data-window="' + dataLinkId + '"]').toggle();
}
$.fn.myPlugin = function(options) {
return this.each(function () {
var pluginInstance = new MyPlugin($(this), options);
pluginInstance.attachClickHandlers();
});
};
})(jQuery, window, document);
In this implementation MyPlugin is a class (in javascript sense of the word class) which enables you to tackle each specific point in the way it behaves. and introduce all sorts of OOP features.
The demo
Sorry for how stupid this is going to sound. My JS vocabulary is terrible and I had absolutely no idea what to search for.
I'm using jQuery.
So I've got this code:
var example = {
open: function(element){
alert(element.text());
},
init: function(){
$("a").click(example.open);
}
};
$(document).ready(function(){example.init();)
So here's the problem: I want to pass an argument to example.open() when I click the "a" element. It doesn't seem like I can, though. In order for the example.open method to just…exist on page-load and not just run, it can't have parentheses. I think. So there's no way to pass it an argument.
So I guess my question is…how do you pass an argument to a function that can't have parentheses?
Thanks so much.
Insert another anonymous function:
var example = {
open: function(element){
alert(element.text());
},
init: function(){
$("a").click(function()
{
example.open($(this));
});
}
};
You can also try this version because jQuery set the function's context (this) to the DOM element:
var example = {
open: function(){
alert($(this).text());
},
init: function(){
$("button").click(example.open);
}
};
Since jQuery binds the HTML element that raised the event into the this variable, you just have to pass it as a regular parameter:
var example = {
open: function(element){
alert(element.text());
},
init: function(){
$("a").click(function() {
// jQuery binds "this" to the element that initiated the event
example.open(this);
});
}
}
$(document).ready(function(){example.init();)
You can pass the anchor through its own handler:
var example = {
open: function( element ){
alert(element.text());
},
init: function(){
$("a").on("click", function() {
example.open( $(this) );
});
}
};
$(document).ready(function() {
example.init();
});
I don't understand what you actually want to do;
however, I can give a try:
var example = {
open: function(event){
event.preventDefault();
alert($(event.target).text()+' : '+event.data.x);
},
init: function(){
$("a").bind('click',{x:10},example.open);
}
};
$(example.init);
demo:
http://jsfiddle.net/rahen/EM2g9/2/
Sorry, I misunderstood the question.
There are several ways to handle this:
Wrap the call in a function:
$('a').click( function(){ example.open( $(this) ) } );
Where $(this) can be replaced by your argument list
Call a different event creator function, which takes the arguments as a parameter:
$('a').bind( 'click', {yourvariable:yourvalue}, example.open );
Where open takes a parameter called event and you can access your variable through the event.data (in the above it'd be event.data.yourvariable)
Errors and Other Info
However your element.text() won't just work unless element is a jQuery object. So you can jQueryify the object before passing it to the function, or after it's received by the function:
jQuery the passed object:
function(){ example.open(this) } /* to */ function(){ example.open($(this)) }
jQuery the received object:
alert(element.text()); /* to */ alert($(element).text());
That said, when calling an object without parameters this will refer to the object in scope (that generated the event). So, really, if you don't need to pass extra parameters you can get away with something like:
var example = {
open: function(){ // no argument needed
alert($(this).text()); // this points to element being clicked
},
init: function(){
$("a").click(example.open);
}
};
$(document).ready(function(){
example.init();
}); // your ready function was missing closing brace '}'
I just started writing Plugins for jQuery. I found a good tutorial how to start with it, but one point I missed. I want register a independent plugin-object for each element and I need them events.
Here the code I got atm:
(function($){
var MyPlugin = function(pElement, pOptions)
{
var element = $(pElement);
var object = pElement;
var settings = $.extend({
param: 'defaultValue'
}, pOptions || {});
this.onfocus = function() {
element.val('Focus');
};
this.onblur = function() {
element.val('Blur');
}
// DO I NEED THIS?
object.onfocus = this.onfocus;
object.onblur = this.onblur;
};
$.fn.myplugin = function(options)
{
return this.each(function()
{
var element = $(this);
if (element.data('myplugin')) { return };
var myplugin = new MyPlugin(this, options);
element.data('myplugin', myplugin);
});
};
})(jQuery);
Do I need to copy my public methods "onfocus" and "onblur" from "this" to "object"? Is there a better way?
The best guide for writing jQuery plugins is probably jQuery's own.
jQuery's event system is the best way of handling events for your plugin. If you're using jQuery 1.7+ (which I recommend, if it's possible), .on() and .off() are your workhorses. Not only can you bind browser events like focus and blur, you can create completely custom events like 'iamasuperstar' and trigger them manually with this.trigger( 'iamasuperstar' ).
So you'd do something like this for your plugin:
element.on( 'focus', function() {} )
element.on( 'blur', function() {} )
...and whatever else you need.
Why not:
object.onfocus = function() {
element.val('Focus');
};
object.onblur = function() {
element.val('Blur');
}