jQuery Plugin - Public method - Data only targeting one element - javascript

I'm trying to write a plugin that will select multiple elements and then apply some private methods to them (see code below). Then I also want to give the user the ability to trigger the activation of the plugin's methods manually with a .activate() function.
Here is my code :
MARKUP : https://github.com/simonwalsh/jquery.imagepox/blob/master/demo/index.html
JS : https://github.com/simonwalsh/jquery.imagepox/blob/master/dist/jquery.imagepox.js
Basically, when I select multiple items and then try to use the manual activation like so :
$(".pox-wrapper").imagepox({ // NOTE: selects two elements
manualActivation: true
});
var manual = $(".pox-wrapper").data('imagepox');
setTimeout(function(){
manual.activate();
}, 5000);
It will only apply the activate() method to the first element in the query...
This is my first jQuery plugin and I've been able to handle everything so far but I'm not sure about this one or even if it is the right way to effectively call a public method. I also tried using a custom event with an event listener in the plugin but it still only applies the methods on the first element in the page.
Thanks in advance :)

its not your plugin's fault. data does not work like that, it doesnt know how to return data from a collection of elements. Because think about it, each element in the collection contains its own data object!
So when you call data on a collection, it returns the data from the first one. The quick solution would be to change the innards of the setTimeout into a loop over all the elements in the set and call activate on them.
setTimeout(function(){
$(".pox-wrapper").each(function(){
$(this).data('imagepox').activate();
})
}, 5000);
It seems to me that you want to add functions to collections of jquery objects. This is the usecase of a jquery plugin. You can create a lightweight one like this:
$.fn.imagepox.activate = function(){ //do this after you create your plugin!
return this.each(function(){
var $this = $(this);
var data = $this.data('imagepox');
if(data){
data.activate();
}
});
};
now you can call it like this:
$(".pox-wrapper").imagepox.activate()

Related

Add method to chaining in jQuery plugin

I am trying to write an auto complete jQuery plugin.
The desired usage:
$('.advancedSelect').advancedSelect({/*plugin options*/}).change(function(){})/*.otherJQueryMethods*/;
The implementation:
$.fn.advancedSelect = function({
return this.each(function(){
var $advSel = $('<input/>');
var $el = $(this).after($advSel).hide();
/* my codes on desired functionalities */
/* how is it possible to trigger the chained change method */
});
});
In a comment on my soon-to-be-deleted answer (as it answered a question other than your real question, as it turns out), you've said:
I was wondering whether we could have a syntax like this:
$('.advancedSelect').advancedSelect({/*plugin options*/}).onChange(function(){}).css({})
-and by .css I meant any other jQuery's methods.
I would suggest either this:
$('.advancedSelect').advancedSelect({/*other plugin options*/, onChange: function(){}}).css({})
or this:
$('.advancedSelect').advancedSelect({/*plugin options*/}).advancedSelect("onChange", function(){}).css({})
... with a fairly strong preference for the first one. :-)
Re that first option, an adjunct you see a lot is an optional "options" method you can use later to change options::
// Initial setup
$('.advancedSelect').advancedSelect({/*other plugin options*/, onChange: function(){}}).css({})
// Later, I need to change something
$('.advancedSelect').advancedSelect("options", { onChange: function(){}});
Side note: If this change-like method is to register a change handler, why not just use jQuery's change (or on with some plugin-specific event name) and have your plugin raise an event? That's how I would handle any kind of event-related thing in a plugin. Look at bootstrap's use of shown.bs.modal and such, for instance.

Get selected time in javascript control

I'm using the following JavaScript Control:
http://www.ama3.com/anytime/
How do I get the selected date in the control? So I can pass it to a postback page?
I tried finding it, but I'm just not very good at JavaScript :(
Which function do I have to call?
// Initialization
$(document).ready(function () {
//alert("welcome");
$("#DateTimeDemo").AnyTime_picker(
{ format: "%Y-%m-%d %H:%i: %E",
formatUtcOffset: "%: (%#)",
hideInput: true,
placement: "inline"
});
// Asp.net code
<input type="text" id="DateTimeDemo" style="background-color:Green;" />
I assume the code will be something like this:
var x = getBlaBla();
Where x is something that I can use to pass to C# for postback info. I think I'll have to use JQuery to select the object I'll be taking the date out of.
Edit:
Okay I think I have to use something like this:
$("#DateTimeDemo").AnyTime_current(g, k);
what do the g and the k stand for? What do I have to pass?
As Joe Johnson earlier commented, you will likely want to attach an event handler. With this method, whenever your input changes within the DateTimeDemo field, you can do something with that value.
$(function() {
$("#DateTimeDemo").change(function() {
var dt = $("#DateTimeDemo").val();
alert(dt);
// do something with dt.
});
});
I think I'll have to use JQuery to select the object
You never "have" to use jQuery, or any library. You can add an in–line listener like:
<select ... onchange="someFunc(this.value);" ...>
Where the logic for adding the listener is on the server, so no different to adding it at the client (but faster and more robust than any client–side method).
Or add it as a DOM property sometime after the element is created in the document (use the load event or a script at the bottom of the page):
document.getElementById('selectID').onchange = function(){someFunc(this.value);};
Or use addEventListener:
document.getElementById('selectID').addEventListener('change', function(){...}, false);
but include support for other browsers too (e.g. an addEvent function).

How to completely remove a jQuery.prototype plugin?

Let's say I have a plugin, for example:
(function (jQuery) {
var somevars = 0;
jQuery.fn.someFunc = function () {
// do some work
};
jQuery.fn.myPlugin = function (options) {
// do some initialization etc...
}
})(jQuery);
jQuery(document).ready(function () {
jQuery(".someclass").myPlugin();
});
Now let's say I want to remove it completely with something like:
jQuery(".someclass").destroy("myPlugin");
How can I do that? Completely remove the plugin from the object, functions, data, events, everything.
UPDATE
Assume no method to destroy itself exist, assume you are using someone else plugin which self bind to few elements on the page when initialized, and assume after some interaction with the user you need to completely remove it with all its binding.
Is it possible? Or the only solution is to go through the code of the plugin and discover how to remove it and add some methods to remove it?
Given how many things a plugin could be doing, changing the DOM, binding events here and there, there's no way to remove it and clean up with some magical command.

Listening and firing events with Javascript and maybe jQuery

In my JavaScript and Flex applications, users often perform actions that I want other JavaScript code on the page to listen for. For example, if someone adds a friend. I want my JavaScript app to then call something like triggerEvent("addedFriend", name);. Then any other code that was listening for the "addedFriend" event will get called along with the name.
Is there a built-in JavaScript mechanism for handling events? I'm ok with using jQuery for this too and I know jQuery makes extensive use of events. But with jQuery, it seems that its event mechanism is all based around elements. As I understand, you have to tie a custom event to an element. I guess I can do that to a dummy element, but my need has nothing to do with DOM elements on a webpage.
Should I just implement this event mechanism myself?
You have a few options:
jQuery does allow you to do this with objects not associated with the document. An example is provided below.
If you're not already using jQuery on your page, then adding it is probably overkill. There are other libraries designed for this. The pattern you are referring to is called PubSub or Publish/Subscribe.
Implement it yourself, as you've suggested, since this is not difficult if you're looking only for basic functionality.
jQuery example:
var a = {};
jQuery(a).bind("change", function () {
alert("I changed!");
});
jQuery(a).trigger("change");
I would implement such using MVVM pattern with knockjs library.
Just create an element, and use jquery events on it.
It can be just a global variable, doesn't even have to be connected to the DOM.
That way you accomplish your task easily and without any extra libs.
Isn't it possible to bind onchange events in addition to click events? For instance, if addFriend is called and modifies a list on the page, you could bind the change event to then invoke additional functionality.
$('#addFriendButton').click( function() {
// modify the #friendList list
});
$('#friendList').change( function() {
myOtherAction();
});
This is total Host independent, no need for jQuery or dom in this case!
function CustomEvents(){
//object holding eventhandlers
this.handlers_ = {};
}
//check if the event type does not exist, create it.
//then push new callback in array.
CustomEvents.prototype.addEventListner = function (type, callBack){
if (!this.handlers_[type]) this.handlers_[type] = [];
this.handlers_[type].push(callBack);
}
CustomEvents.prototype.triggerEvent = function (type){
//trigger all handlers attached to events
if (!this.handlers_[type]) return;
for (var i=0, handler; handler = this.handlers_[type][i]; i++)
{
//call handler function and supply all the original arguments of this function
//minus the first argument which is the type of the event itself
if (typeof handler === "function") handler.apply(this,arguments.slice(1));
}
}
//delete all handlers to an event
CustomEvents.prototype.purgeEventType = function(type){
return delete this.handlers_[type];
}
test:
var customEvents = new CustomEvents();
customEvents.addEventListner("event A", function(arg){alert('Event A with arguments' + arg);));
customEvents.triggerEvent("event A", "the args");
EDIT added arguments passing

editableText plugin enabling problem

I've been experimenting with this plugin http://valums.com/edit-in-place/, so far so good... But i ran into this problem. I want to update my page when update or new request to save data is sent but if i update this function(edit-in-place) it will add second set of buttons, third, fourth and so on. How could i tell it that it would update just on that returned data, but not all elements? I have an idea it has to do something with each function of jquerys, but I'm not sure as I'm quite new to jquery. Thanks for any help!
You can give the selector a context, so for example if you're doing this now:
$('.editableText').editableText({
newlinesEnabled: false
});
In your ajax callback, give it a context when calling it in the success or complete method, wherever you're adding elements, like this:
$.ajax({
...options here...
success: function(data) {
$('.editableText', data).editableText({
newlinesEnabled: false
});
//insert the elements somewhere...
}
});
The , data gives it a context (you can see options for $(selector, context) here), this means it's only searching for elements of that class within the returned data/html, not all elements on the page. This should eliminate your repetition issue of it selecting and running the plugin on elements it's already run on.

Categories

Resources