Javascript, render objects in a tree list - javascript

I try to build a small tool for get the structure of my js running in a browser.
I create a gits for that: https://gist.github.com/M3kH/6615963
But is no way to make work on the browser without crashes.
What you think I'm doing wrong?
Did you think Async way would prevent browser crashes?
How can I get the property of a element is a function? I need to
executed it?
I have some cases like in jquery plugins where looks like:
;(function($, window, document, undefined) {
$.fn.namePlugin = function(options) {
options = $.extend( {}, $.fn.namePlugin.options,options );
return this.each(function(){
// This is the builder
$.fn.namePlugin.options.functionA();
});
}
// Here where I fill all the functions
$.fn.namePlugin.options = { functionA: function(){} };
});
Did you think I have some ways for get the return function as a loop?
I would like to build an utility for get the list of the function, for document it in a second moment.
Thanks in advance,
Mauro.

Related

Pure Javascript plugin development

I need to develop a pure javascript plugin wich can be accessed like jquery typed plugins ( $('.pluginWrapper').pluginInit();
However i need to to use pure javascript and i was thinking maybe about 2 supported formats:
document.getElementById('pluginWrapper').pluginInit();
pluginInit(document.getElementById('pluginWrapper'));
I know that you have to do an IIFE to wrap it and call it via object methods but i do not know how i can bind that to an element.
I am mentioning that i am a begginer so please can someone please explain something about this. Cheers!
You would be safer developing a plugin interface that simply exposes plugins as functions which take an element as an argument.
function MyPlugin(element) {
// do stuff with element
element.setAttribute('data-plugin-id', 'pluginName');
}
The other approach involves extending Element.prototype. Which could potentially be a dangerous action in production software.
However, it is still possible.
Element.prototype.pluginInit = function() {
// the element is accessible as `this`
this.setAttribute('data-plugin-id', 'pluginName');
}
A function is easy for everyone to understand. Plugin writers don't have to understand any interfaces for creating and registering plugins, they just need to know that they should write functions that take elements as arguments.
There's a great talk from Rich Hickey (the creator of Clojure) called Simplicity Matters in which he stresses that the worst thing you can do is add additional complexity when simple solutions will do.
In this case, you don't need anything more complex than a function which takes an element as an argument.
If it is completely essential that you have control of the function, you could write a simple interface for registering and initiating plugins.
function Plugin(element) {
if(element === null) {
throw new TypeError("Element must not be null!");
}
// get all the plugin names from the store
var pluginNames = Object.keys(Plugin.store);
// make sure `this` is set to the element for each plugin
var availablePlugins = pluginNames.reduce(function(plugins, name) {
plugins[name] = Plugin.store[name].bind(element);
return plugins;
}, {});
// return an object containing all plugins
return availablePlugins;
}
// we'll store the plugins in this object
Plugin.store = {};
// we can register new plugins with this method
Plugin.register = function(name, pluginFn) {
Plugin.store[name] = pluginFn;
};
Which you could use like this.
Plugin.register('myPlugin', function() {
this.setAttribute('data-plugin-id', 'myPlugin');
});
Plugin(document.getElementById('pluginWrapper')).myPlugin();
If you want the plugin function to take a selector, the same way as jQuery, then you can use document.querySelectorAll inside your definition for Plugin.
function Plugin(selector) {
var element = document.querySelectorAll(selector);
if(element === null) {
throw new TypeError("Element must not be null!");
}
// get all the plugin names from the store
var pluginNames = Object.keys(Plugin.store);
// make sure `this` is set to the element for each plugin
var availablePlugins = pluginNames.reduce(function(plugins, name) {
plugins[name] = Plugin.store[name].bind(element);
return plugins;
}, {});
// return an object containing all plugins
return availablePlugins;
}
Then you would use it like this instead.
Plugin.register('myPlugin', function() {
this.setAttribute('data-plugin-id', 'myPlugin');
});
Plugin('#pluginWrapper').myPlugin();

Adding code to a javascript module pattern from an outside file

First of all I'm pretty new to javascript.
I have wrote a javascript plug-in that filters html records. Using Knockout.js, basically keyword/s are typed into a text box and the plug-in filters through the html records to reveal the records that contain the keyword/s.
I have wrote the javascript using the Module pattern, and would like the opportunity for the .js file to stand alone, whilst also giving the user the opportunity to change ways in which the filter works.
Here is a brief and simple overview of the structure of my .js file:
$(function(){
var s,
Filter = {
settings:{
//default settings
},
initialise: function(){
s = this.settings;
this.someFunction1;
this.someFunction2;
},
someFunction1: function(){
//
},
someFunction2: function(){
//
},
}
Filter.initialise();
});
As you can see, I have specified one function to be called - initialise. Within initialise I have set the variable s (declared at the same level as the module) to point to settings so that all sub functions of the module can access it.
What I want to know is, is it possible for the overriding settings to be passed via the html file that calls the .js file?
Ideally I would like there to be default settings for the plug-in, but give the user the option to specify/override certain settings unique to their need.
Any help would be appreciated. Thanks.
First up, there's a few peculiarities in your code.
One thing is that you have this.someFunction1; (and one for the second function) in your initialize function, but that doesn't quite do anything. It's just a statement.
Another thing is that you declare Filter as an object, but you're missing , (commas) between the various properties.
Finally, you declare someFunction2 twice (though I assume it's an copy/paste error?), and you're missing a semi-colon.
To find these problems you can use a JavaScript linting tool, for example JSHint. Try copy-pasting your question's code there and you'll see all those issues pop up.
If I fix those issues I get to this:
$(function(){
var s,
Filter = {
settings:{
//default settings
},
initialise: function(){
s = this.settings;
},
someFunction1: function(){
//
},
someFunction2: function(){
//
}
};
Filter.initialise();
});
Currently in this code, the Filter is only visible in the outer closure. To make it available to other bits of code you'll have to export it, either to your own namespace object or as a jQuery plugin.
The first option is possible, but will require a bit more work and assumptions about your setup. So let me stick to showing the second option. The jQuery's plugin tutorial is pretty good, but I've based the following code on this blogpost because it's a bit more complete IMO:
(function($) {
$.filter = function(element, options) {
var defaults = {
// default settings
}
var filter = this;
filter.settings = {};
var initialise = function() {
filter.settings = $.extend({}, defaults, options);
filter.element = element;
// code goes here
}
// This function is *public*, just save it in a 'var' instead of setting it
// as a property of 'plugin' to keep it private to your plugin.
filter.someFunction1 = function() {
//
}
filter.someFunction2 = function() {
//
}
initialise();
}
})(jQuery);
In this code the jQuery extend function is used above to extend default settings with user provided options.
You can call your plugin in its most basic form like this:
var options = { filterEmptyOptions: true, showTimeZone: false, /* etc */ };
$.filter($('#myDiv'), options);
Additionally you could save the result of last line and call the plugin's public methods later on.

jQuery Plugin - Providing an API

I am currently developing a rather complex jQuery plugin. One that I am designing to be extensible. The quandary I have is how to exactly provide my users with the APIs available to them.
There are two methods that I can come up with:
Provide the API via an object in the global scope
This is the method I am currently using. I do it similar to this:
(function ($, win, undefined) {
//main plugin functionality
function pluginStuff() { /*...including method calling logic...*/ }
//register function with jQuery
$.fn.extend({ Plugin: pluginStuff });
//register global API variable
win.PluginAPI = { extendMe: {}, getVar: function() {} };
})(jQuery, window);
Unfortunately since I impliment the standard $().plugin('method') architecture its a little strange to have to use the jQuery method for some things and the API variable for others.
Provide the API via an object placed in jQuery
I toyed with this method as well but its best practice to take up only a single slot in jQueries fn scope, as not to crowd the jQuery variable. In this method I would put my api variable in $.fn instead of the window:
//register function with jQuery
$.fn.extend({ Plugin: pluginStuff });
//register global API variable
$.fn.PluginAPI = { extendMe: {}, getVar: function() {} };
I would rather not break this convention and take up two places.
Now that I write this I can see a third option where I assign my plugins slot in jQuery's fn scope to be an object:
$.fn.Plugin = { plugin: pluginStuff, api: { extendMe: {}, getVar: function() {} } };
but how well received would this be if users had to do $('#elm').Plugin.plugin({ setting: 'value' }) to create a new instance of the plugin?
Any help or pointers would be greatly appreciated.
Please Note: I'm am not looking for a way to incorporate the API object into my plugin functionality. I am looking for a way to keep it separately modularized, but intuitively available for use/extension.
You could always do like
var plugin = function plugin() { /* do the main stuff */ };
// api stuff here
plugin.getVar = function() { };
plugin.extendMe = {};
$.fn.Plugin = plugin;
Or stick the extra stuff in an object that you assign to plugin.api.
Any way you do it, though, you're going to have to worry a bit about settings bleeding into each other. Since everything's going to be using the same function, regardless of how you choose to set it up, you'll need a way to keep invocations of the plugin separate from one another. Perhaps using something like, say, this.selector (in your plugin function) as a key into an associative array of properties, for example. I'd normally recommend .data() to attach settings to individual elements, but that doesn't help much if the same element gets the plugin called for it twice.
The method I eventually decided to use was registering the plugin under the fn namespace and the api variable under the jQuery $ namespace. Since methods and options set operate on an instance of the plugin $.fn is the best choice.
However, the API is global and does not link to a single instance. In this case $.fn doesn't quite fit. What I ended up using was something similar to this:
(function ($, win, undefined) {
//main plugin functionality
function pluginStuff() { /*...including method calling logic...*/ }
//register function with jQuery
$.fn.Plugin = pluginStuff;
//register global API variable
$.Plugin = { extendMe: {}, getVar: function() {} };
})(jQuery, window);
now you can create an use a plugin object as expected:
$('#elm').Plugin();
$('#elm').Plugin('option', 'something', 'value');
$('#elm').Plugin('method');
and you can easily extend and access the API:
$.extend($.Plugin.extendMe, {
moreStuff: {}
});
$.Plugin.getVar('var');
Thanks for the help everyone!

Function listener in JavaScript and/or jQuery

Wondering if there is an elegant way to listen for a function in JavaScript and/or jQuery.
Rather than listening for a $('#mything').click(function(){ //blah }) I'd like to listen for when a specific function is fired off. I don't want to edit the function as it's within a library that I don't want to hack directly.
I did find this: http://plugins.jquery.com/project/jqConnect which connects functions.
But wondering about a better technique.
The only way to do this is to override the function (ie, hack the library):
(function() {
var oldVersion = someLibrary.someFunction;
someLibrary.someFunction = function() {
// do some stuff
var result = oldVersion.apply(this, arguments);
// do some more stuff
return result;
};
})();
Edit: To run your code after the library function has run, just call the library function first, storing the result in a variable. Then, run your code, and finally return the previously stored result. I've updated my example above to accomodate running code either before or after the library function.

Creating a jquery dialog as an API

In my current application I am using jquery UI dialog at many places , so I am planning to create a method like
var MYAPP = MYAPP || {};
MYAPP.overlay = (function(){
$("#id").dialog();
}());
This is my idea but now the problem is my overlay is used for different purpose like overlay form, video, confirmation message etc. Is there a way I can have all the option inside my API . so I just have to call MYAPP.overlay("video",some other parameter) and it will create the overlay without have to repeat the code again and again....any idea or suggestion will be appreciated..
I'm not sure what you are trying to accomplish with the immediately executing anonymous function, but you can do something like this:
MYAPP.overlay = function MYAPP$overlay(id, paramsObj) {
// do something based on element type, id, or params obj here.
$(id).dialog();
// possibly return something if needed.
};
yes you can use parameters. here is a very generic way of doing it:
MYAPP.overlay = (function(){
// complex code ....
return function(arg) {
alert(arg);
}
})();
// example
MYAPP.overlay('hello');
will alert hello

Categories

Resources