Add method to chaining in jQuery plugin - javascript

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.

Related

Appending function to Custom Event in Prototype JS

I'm working with a 3rd party product where I am extending the UI with my own custom functionality. Within part of that I need to call an event after the UI has been updated with an AJAX call. Luckily the app fires a call to a Custom Event using the Prototype JS library after the call is complete, like this:
$(document.body).fire("ns:customevent");
If I add my own custom event with the same name then this works as expected
$(document).observe("ns:customevent", function(event) {
//do custom stuff here
});
[I could not get $(document.body).observe() to work here but I don't think that really matters.]
My concern here is that there may be other parts of the app that have registered functions against that event, and I am (blindly) overwriting them with my own, which will lead to issues further down the line.
Does Prototype append custom functions even though they have the same name or does it in fact overwrite them? If it does overwrite them then how can I append my function to anything that is already existing? Is there anyway of viewing what
I would imagine something like this, but I hardly know Protoype and my JS is very rusty these days.
var ExistingCustomEvent = $(document.body).Events["ns:customevent"];
$(document).observe("ns:customevent", function(event) {
ExistingCustomEvent();
//do custom stuff here
});
I can't add my event handler or add in code to call my own function, I want to try avoiding the 3rd party library (if that would even be possible).
Thanks.
As an FYI for anyone else that stumbles upon this question, following the comment from Pointy it turns out that Prototype does append the functions to the custom event.
I verified this by trying the following and both alerts fired.
$(document).observe("ns:customevent", function(event) {
alert("ALERT 1");
});
$(document).observe("ns:customevent", function(event) {
alert("ALERT 2");
});
Great :)

How does Ractive's proxy-load work?

I want to know when a DOM element generated by Ractive is ready. In my case, I want to use jquery to attach an autocomplete function onto the element. Ideally it would go something like this:
Template:
{{#list}}
<input type="text" proxy-load="attach-typeahead">
{{/list}}
Javascript:
ractive.on("attach-typeahead", function(event){
$(event.node).typeahead(...);
})
But the event never fires even though I remeber seeing proxy-load mentioned somewhere in the documentation. What's the proper way to do what I'm trying to do? Thanks.
Codler's answer is spot on - transitions can be used to attach behaviour to nodes (and detach it, with outro).
As of the latest (0.3.8) version, there's another method, which behaves similarly but is slightly more streamlined for this purpose: decorators.
The documentation hasn't been written yet (my bad), but you can see a typeahead decorator here. A decorator is simply a function that gets called as soon as a node is added to the DOM, and which returns an object with a teardown() method that gets called as soon as the node is removed from the DOM.
You can make a decorator globally available like so:
Ractive.decorators.foo = function ( node ) {
// do some setup work with the node here...
return {
teardown: function () {
// do any necessary cleanup here
}
};
};
Or you can specify per-instance decorators, as in the fiddle.
Another decorator example here, this time a sortable list.
The proxy-events are mentioned here in the documentation of ractive. Your example doesn't work because the input element does not have a native load event.
All the ractive functions have a complete function callback that fires when the rendering has completed. Maybe you can use that.
You can use the intro attribute. It is a transition in ractive. When the DOM are created, intro will be called.
You can find more info here https://github.com/RactiveJS/Ractive/wiki/Transitions

jQuery Plugin - Public method - Data only targeting one element

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

Hammer.js with plain javascript

How to use hammer JS events without JQuery selectors just using plain Javascript methods?
Bind hammer to a container element:
var hammer = new Hammer(document.getElementById("container"));
Now, on every gesture that is performed on the container element,
you'll receive a callback object with information on the gesture.
Some example functions:
hammer.ondragstart = function(ev) { };
hammer.ondrag = function(ev) { };
hammer.ondragend = function(ev) { };
hammer.onswipe = function(ev) { };
hammer.js is available as completely standalone version, so you don't need to import jquery resources. See: http://eightmedia.github.com/hammer.js/
Full documentation: https://github.com/eightmedia/hammer.js#documentation
Just a quick look over the GitHub documentation:
var hammer = new Hammer(document.getElementById("container"));
creates a 'hammer' without jQuery. After that you can set callback functions, you don't need any jQuery for that too. But beware! HammerJS might need jQuery internally, so it is possible you can't leave out the <script src="path/to/jquery.js"></script>
The short answer is: just use the plain old DOM API. You're not obliged, or forced to use nothing but jQuery once you've included it.
var someElements = document.querySelectorAll('.someClass');//not jQuery, perfectly valid
var byId = document.getElementById('someId');
var sameScript = $('#anotherId');//nothing stops me from doing this... using jQ for some things
If you find the DOM API a bit clunky (which it is), you might as well do something like this:
var pureDOMRef = $('someID')[0];//returns "normal" Element object, removes jQ wrapper
var multiple = Array.prototype.slice.apply($('.classSelector'),[0]);//returns Array
Just play around, switch back and forth if you want to, nothing wrong with that
The new version of hammer.js provides a JQuery plugin which has to be understand first that it's not a plugin from JQuery - it is FOR JQuery. So if you use JQuery for your site for other purposes then it's convenient that you can basically 'apply' a plugin from hammer at a JQuery selector like this:
$(element).hammer(options).bind("pan", myPanHandler);
Since hammer.js has a modern OOP pattern it can use instances for multiple data handling at once, hence every JQuery element that is bound to hammer is an instance. (IMHO) JQuery slows down by some ms, if you don't mind use this plugin or stay with Vanilla.
http://hammerjs.github.io/jquery-plugin/

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

Categories

Resources