ok I'm not sure if I'm doing this right so if I'm going about it all wrong please explain.
I have a javascript object which is drawing html based on ajax data.
I am then trying to use jquery to handle events on the html output from an instance of the above object. However I would like to call a function and get a property out of the instance of the javascript object which was used to draw the html.
so my code looks something like this:
function obj1 (){
this.property1 = "propvalue";
this.dosomething = function () {
// does some processing
}
this.drawhtml = function () {
// outputs html
}
}
// jquery to handle events
$(document).ready(function(){
// .edit is a class in the html outputted from the drawhtml
$('body').on('click','.edit',function () {
// call the dosomething from the object
});
});
// create instance of object could be multiple on on page
var instance1 = new obj1;
instance1.drawhtml();
Thanks,
You can just use the instance you created before:
// jquery to handle events
$(document).ready(function(){
// .edit is a class in the html outputted from the drawhtml
$('body').on('click','.edit',function () {
instance1.dosomething();
});
});
// create instance of object could be multiple on on page
var instance1 = new obj1(); // added parentesis so it's valid javascript
instance1.drawhtml();
EDIT: Additional information starting from the comments:
The best way to handle this is to tie your event handler to the object itself. Something like this:
function obj1 (){
this.property1 = "propvalue";
this.dosomething = function () {
// does some processing
}
this.drawhtml = function () {
var elem = $("<div>my super dooper HTML</div>");
elem.on('click', this.dosomething);
}
}
Related
I create component from Trumbowyg plugin to vue.js library. I need add two way binding in this beautiful wysiwyg editor.
How to rewrite buildEditor() method?
This method is private. how to do it correctly?
<script>
jQuery.trumbowyg = {
// options object
};
(function (navigator, window, document, $, undefined) {
$.fn.trumbowyg = function (options, params) {
// ... code ...
$(this).data('trumbowyg', new Trumbowyg(this, options));
// ... code ...
};
var Trumbowyg = function (editorElem, o) {
var t = this;
// ... code ...
t.init();
};
Trumbowyg.prototype = {
init: function () {
var t = this;
t.buildEditor();
// ... code ...
},
buildEditor: function () {
// i need rewrite this method
}
// code for otner method
};
})(navigator, window, document, jQuery);
// -------------------------------------
// other file. I want init this plugin
// here do need to rewrite buildEditor() method? What best way to do this?
$('.selector').trumbowyg();
If this plugin doesn't return 'Trumbowyg' variable it's not possible. I recommend fork this plugin and create your own version with your settings.
The best way to do it would be to fork the plugin yourself, as Slava answered. But technically you're able to modify that function.
Whenever you construct a class, that instance has its own constructor property. This is equal to the class function.
So, if you can get access to an instance of Trumbowyg, you're able to use its class:
$foo.trumbowyg(...)
var trumbowyg = $foo.data('trumbowyg')
var TrumbowygClass = trumbowyg.constructor
Now we can modify its prototype:
TrumbowygClass.prototype.buildEditor = function() {
// ...
}
You might want to make $foo be a temporary or unused element. That's because it'll have called the old buildEditor (as soon as you ran $foo.trumbowyg()), not your own modified version.
After you've set the prototype function you could run it on the element you actually want to use trumbowyg on (e.g. $('#target'))
As an example:
(function() {
window.makeInstance = function() {
return new HiddenClass()
}
var HiddenClass = function() {
this.setGreeting()
this.showGreeting()
}
HiddenClass.prototype.setGreeting = function() {
this.greeting = 'Hello, world!'
}
HiddenClass.prototype.showGreeting = function() {
console.log(this.greeting)
}
})()
var myTempInstance = makeInstance()
// Should log 'Hello, world!'
var HiddenClass = myTempInstance.constructor
console.log(HiddenClass) // Should be the HiddenClass function
// Now we overwrite our function..
HiddenClass.prototype.setGreeting = function() {
this.greeting = 'Redefined!'
}
var myUsedInstance = makeInstance()
// Should log 'Redefined!', since we redefined setGreeting
// And later we can use `myUsedInstance`.
// In this code myTempInstance is like $foo, and myUsedInstance
// is like $('#target').
I have a JavaScript module that I would like to create a jQuery plugin interface to.
The module itself is like this:
var Foo = (function () {
"use strict";
var self = {};
self.add = function (selector, otherParam)
{
// Does things unto selector.
// Precisely what it does doesn't matter.
};
return self;
}());
and is used, with success, like this:
Foo.add(a);
Now, I would like to create a plugin that interfaces to this module,
so I can use it somewhat like this:
$.fn.foo = Foo;
$.fn.foo.add = function (param) {
var selector = this;
Foo.add(selector, param);
}
$(elem).foo.add(a);
The problem I'm facing is that I can't get "this" working in .add().
The best way I managed to do it was to not have Foo be self-initializing,
and use a syntax like:
$.fn.foo = Foo;
$(elem).foo().add(a);
It works, but I find it less aesthatically pleasing and less "clean".
Is there a way to do this? Am I on the wrong approach altogether?
Thankful for any input, and I apologize in advance if this has already been answered or is unfit in any other way.
I did search for answers, but I'm not well-versed in plugin authoring nor an expert on jQuery itself.
TL;DR: I have a module like Foo above, and would like to access it's members like a jQuery plugin.
Here is a simplified version of the pattern I normally use (error checking and extra features removed).
It uses a single class function and a plugin bridge extension method to allow attachment to multiple elements. Methods are called by using a string option value:
var Foo = (function () {
"use strict";
// Constructor
function Foo($element, options){
this.$element = $element;
this.options = options
this.fooVal = 0;
}
// Create method (called from bridge)
Foo.prototype.onCreate = function(){
this.fooVal = ~~this.$element.text()
};
// Add the specified val to the elements current value
Foo.prototype.add = function (val) {
this.fooVal += val;
// Update the element text with the new value
this.$element.text(this.fooVal);
};
return Foo;
})();
// Create a bridge to each element that needs a Foo
$.fn.foo = function (options, args) {
this.each(function () {
var $element = $(this);
// Try to get existing foo instance
var foo = $element.data("Foo");
// If the argument is a string, assume we call that function by name
if (typeof options == "string") {
foo[options](args);
}
else if (!foo) {
// No instance. Create a new Foo and store the instance on the element
foo = new Foo($element, options);
$element.data("Foo", foo);
// Record the connected element on the Foo instance
foo.$element = $element;
// Call the initial create method
foo.onCreate();
}
});
}
// testing
console.clear();
$('#test').foo();
$('#button2').click(function () {
$('#test').foo("add", 2);
});
$('#button10').click(function () {
$('#test').foo("add", 10);
});
For your example Foo takes the initial value from the element text and subsequent "add" calls modify that value.
JSFiddle: http://jsfiddle.net/TrueBlueAussie/o2u7egfy/3/
Notes:
~~ is just a fast short-cut for parseInt()
You could supply an initial value via the options parameter (ignored in first example). See following:
e.g.
// Create method (called from bridge)
Foo.prototype.onCreate = function(){
this.fooVal = this.options.value || ~~this.$element.text()
// Set initial value
this.$element.text(this.fooVal);
};
and start with
$('#test').foo({value: 999});
JSFiddle: http://jsfiddle.net/TrueBlueAussie/o2u7egfy/4/
I want to make a library of functions like this (similar to what jquery is doing)
var myLib = function (idOfAnElement){
var myElement = document.getElementById(idOfAnElement);
return{
getHeight: function (){
return myElement.style.height;
},
getWidth: function (){
return myElement.style.width;
}
}
}
My problem is, that I don't know how to return
myElement
by default, if there is no other function called like
myLib('myId').getHeight; // Returns Height
myLib('myId') // Is supposed to return the HTML-Element with id = 'myId'
Create a privileged method returning the value of private myElement property itself
var myLib = function (idOfAnElement){
var myElement = document.getElementById(idOfAnElement);
return{
getHeight: function (){
return myElement.style.height;
},
getWidth: function (){
return myElement.style.width;
},
getElement: function() {
return myElement;
}
}
}
myLib('myId').getElement();
What you want can be achieved simply by adding the methods you want to the element object,
Javascript allows easy adding methods to existing objects, even the this pointer will point to the bound object.
var myLib = function (idOfAnElement){
var myElement = document.getElementById(idOfAnElement);
myElement.getHeight: function (){
return this.style.height;
}
myElement.getWidth: function (){
return this.style.width;
}
return myElement;
}
Note: While it works, I wouldn't recommend it.
You need to take care not to overwrite existing methods/fields and if multiple libraries will take the same approach a collision is likely.
And this is NOT what jQuery is doing: they create a wrapper object. To get the element from jQuery you need to use [0] for example $('#myEl')[0].
I am using a boilerplate plugin design which looks like this,
;(function ( $, window, document, undefined ) {
var pluginName = "test",
defaults = {};
function test( element, options ) {
this.init();
}
test.prototype = {
init: function() {}
}
$.fn.test = function(opt) {
// slice arguments to leave only arguments after function name
var args = Array.prototype.slice.call(arguments, 1);
return this.each(function() {
var item = $(this), instance = item.data('test');
if(!instance) {
// create plugin instance and save it in data
item.data('test', new test(this, opt));
} else {
// if instance already created call method
if(typeof opt === 'string') {
instance[opt].apply(instance, args);
}
}
});
};
})( jQuery, window, document );
Now say i have two <div> with same class container.
And now i would call my test plugin on these divs like so,
$(".container").test({
onSomething: function(){
}
});
Now when function onSomething is called from inside my plugin how can i call that plugin public methods referring to the instance onSomething function was called from?
For example something happened with the first container div and onSomething function was called for only first container div.
To make it a bit more clear I have tried to pass this instance to the onSomething function, that way i expose all plugin data and then i can do something like,
onSomething(instance){
instance.someMethod();
instance.init();
//or anything i want
}
To me me it looks quite wrong so there must be a better way... or not?
Well im not sure if it is the best idea, but you could pass the current object as a parameter. Let's say onSomething : function(obj) { }
So whenever "onSomething" is called by the plugin, you can call it like this: "onSomething(this)" and then refer to the object asobject`
Lets give a specific example.
var plugin = function (opts) {
this.onSomething = opts.onSomething;
this.staticProperty = 'HELLO WORLD';
this.init = function() {
//Whatever and lets pretend you want your callback right here.
this.onSomething(this);
}
}
var test = new Plugin({onSomething: function(object) { alert(object.staticProperty) });
test.init(); // Alerts HELLO WORLD
Hope this helps, tell me if its not clear enough.
Oh wait, thats what you did.
I am struggling with methods in JavaScript.
obj = function(){
this.getMail = function getMail (){
}
//Here I would like to run the get mail once but this.getMail() or getMail() wont work
}
var mail = new obj();
mail.getMail();
How do I make the method in a way that I can run it both inside the object and from the outside
Thanks
When you define the function use the name just once, like this:
obj = function(){
this.getMail = function(){
alert("bob");
}
}
Now you can use this.getMail() in there, you can see a working example here.
here you go:
var obj = function() {
function getMail() {
alert('hai!');
}
this.getMail = getMail;
//Here I would like to run the get mail once but this.getMail() or getMail() wont work
getMail();
}
var mail = new obj();
mail.getMail();
Building a robust definition for your object is recommended. Build a prototype for it, then if you ever need two or more, you can make instances of them. I show below how to build a prototype, add methods that call eachother, and how to instantiate the object.
obj = function () {} //define the empty object
obj.prototype.getMail = function () {
//this is a function on new instances of that object
//whatever code you like
return mail;
}
obj.prototype.otherMethod = function () {
//this is another function that can access obj.getMail via 'this'
this.getMail();
}
var test = new obj; //make a new instance
test.getMail(); //call the first method
test.otherMethod(); //call the second method (that has access to the first)