I might have the same method name across different and disparate objects:
Frame.hide = function() {
//
}
Dialog.hide = function() {
//
}
Treasure.hide = function() {
//
}
Is it good to keep method names across the application unique, such as:
Frame.hideFrame = function() {
//
}
Dialog.hideDialog = function() {
//
}
The best efforts of an IDE such as Webstorm, can't differentiate between the 3 hide() methods in the top snippet. As our application is growing bigger and bigger (we are at around 80 classes now), it is becoming almost impossible to navigate around code sometimes because method names are the same, and refactoring becomes downright dangerous.
Well, that's a matter of taste really. I personally do not like repeating object names in the functions.
So I favor :
Frame.hide = function() {}
Frame.show = function() {}
Frame.validate = function() {}
over:
Frame.hideFrame = function() {}
Frame.showFrame = function() {}
Frame.validateFrame = function() {}
Your IDE should never force you to do things which might not be the preferable way, in such cases you might want to search for another IDE (Netbeans?)
Related
I have trouble to solve a scope issue. Actually I'm working on a project for an HMI browser frontend. It's should visualise variables from an automation system. For the HMI it's required that the user can switch between different pages. To solve the general process flow I have created a state machine function, which coordinates loading, drawing and interaction with user. My problem now is that I use setTimeout to call the run function (which is actually my state machine) and now run in trouble with var-scope.
Look at following code:
function frontend() {
// Public properties:
this.soundEnable = true;
// Private Properties:
var p1 = 0;
var p2 = [1,2,3];
var p3 = {a:1, b:2, c:3};
var runState = 1;
var runWait = false:
// Public Methods
// stops the state machine until m_continue is called
this.m_wait = function() {
runWait = true;
}
// continues the state machine
this.m_continue = function() {
if (runWait) {
runWait = false;
setTimeout(run, 100);
}
}
// Private Methods
function drawFrame(finish_callback) {
...<Drawing of HMI-Objects on the canvas>...
finish_callback();
}
function run() {
switch (runState) {
case 1:
this.m_stop();
drawFrame(this.m_continue());
case 2:
for(i=0; i<p3.length; i++) {
p2.push(externalObjectCreator(p3[i]));
}
}
if (!runWait) {
runState++;
setTimeout(run, 100);
}
}
// Constructor
...<code to assign public and private properties>...
// Finally call the state machine to activate the frontend
runState = 1;
run();
}
Problem is scope in run-Function. In case of the first call from end of constructor everything is ok. run can access all the private properties and manipulate them. But when it is called later on via setTimeout from m_continue or by itself I can't access the private properties. In firebug I can just see the public properties and functions and none of the private properties I need.
Using of global variables will help, but is not possible, because on multi monitor solution I have 2 separated canvas objects which need to show a separated version of the HMI - for that case I need 2 instances of frontend running parallel in one browser window.
Does anyone know a solution for that problem? I'm on the end of my knowledge and totally confused.
The easiest way will be to define your scope like. Any many renound javascript libraries also use this technique.
this.m_continue = function() {
that = this;
if (runWait) {
runWait = false;
setTimeout(that.run, 100);
}
}
Otherwise you may also use scope binding using apply
You should bind the run function in each setTimeout, since run uses this.
setTimeout(run.bind(this), 100);
I am using the Javascript Module Pattern to try and implement C# enumeration-like functionality. I have two ways that I am currently thinking about implementing this functionality but I do not understand all the benefits or advantages of one way versus the other.
Here is implementation 1:
var MyApp = (function (app) {
// Private Variable
var enums = {
ActionStatus: {
New: 1,
Open: 2,
Closed: 3
}
};
// Public Method
app.getEnum = function (path) {
var value = enums;
var properties = path.split('.');
for (var i = 0, len = properties.length; i < len; ++i) {
value = value[properties[i]];
}
return value;
};
return app;
})(MyApp || {});
// Example usage
var status = MyApp.getEnum("ActionStatus.Open");
And now implementation 2:
var MyApp = (function (app) {
// Public Property
app.Enums = {
ActionStatus: {
New: 1,
Open: 2,
Closed: 3
}
};
return app;
})(MyApp || {});
// Example usage
var status = MyApp.Enums.ActionStatus.Open;
The main difference is in using a "private" variable vs a "public" property to store the enums. I would think implementation 1 is a little slower but I was not sure if keeping the enums as "private" reduced the memory usage. Can anyone explain the difference in memory footprint and performance for the two (if any)? Any other suggestions/advice are appreciated.
...but I was not sure if keeping the enums as "private" reduced the memory usage
The opposite, if anything: You still have to have the enums object, and you have to have a function to access it.
In terms of speed, I wouldn't worry about it. The added function call won't make any real difference (I looked into it when worried about using the new forEach and such, and even on IE6 with its massively slow JS engine, it just doesn't matter).
In a couple of years, you'll probably be able to have the best of both worlds: Enums that are read-only, thanks to ECMAScript5's Object.defineProperties feature:
var Enums = Object.defineProperties({}, {
ActionStatus: {
value: Object.defineProperties({}, {
New: {value: 1},
Open: {value: 2},
Closed: {value: 3}
})
}
});
// Usage
var n = Enums.ActionStatus.New; // 1
By default, properties created with defineProperties are read-only.
In fact, you can basically have that now if you add an ES5 "shim" to create Object.defineProperties on browsers that don't yet have it natively. The "shimmed" version would create read-write properties, since only the natively-supported version can really create read-only properties, but you can write the code now and know that it will work as you like on modern browsers (about half of all web surfers currently have them) while still working, just with less robustness, on less-modern ones.
And of course, EMCAScript6 may take things further, but that's still a future thing.
I want to create an object that can parse a certain filetype. I've looked at some of the files in the File API and I want my object to work about the same. So basically, what I want is this:
A function, called CustomFileParser. I want to be able to use it as the following:
var customFileParser = new CustomFileParser();
customFileParser.parsed = paresed;
customFileParser.progress = progress;
customFileParser.parse(file);
function parsed(event){
//The file is loaded, you can do stuff with it here.
}
function progess(event){
//The file load has progressed, you can do stuff with it here.
}
So I was thinking on how to define this object, but I'm not sure how to define these events and how I should do this.
function customFileParser(){
this.parse = function(){
//Do stuff here and trigger event when it's done...
}
}
However, I'm not sure how to define these events, and how I can do this. Anyone can give me a hand?
Javscript is prototype-based OOP language, not class-based like most other popular languages. Therefore, the OOP constructs are a bit different from what you might be used to. You should ignore most websites that try to implement class-based inheritance in JS, since that's not how the language is meant to be used.
The reason people are doing it because they are used to the class-based system and are usually not even aware that are alternatives to that, so instead of trying to learn the correct way, they try to implement the way that they are more familiar with, which usually results in loads and loads of hacks or external libraries that are essentially unnecessary.
Just use the prototype.
function CustomFileParser(onParsed, onProgress) {
// constructor
this.onParsed = onParsed;
this.onProgress = onProgress;
};
CustomFileParser.prototype.parse = function(file) {
// parse the file here
var event = { foo: 'bar' };
this.onProgress(event);
// finish parsing
this.onParsed(event);
};
And you can use it like so
function parsed(event) {
alert(event);
}
function progress(event) {
alert(event);
}
var customFileParser = new CustomFileParser(parsed, progress);
var file = ''; // pseudo-file
customFileParser.parse(file);
From what it sounds to me i think you need your program to look like this
function customFileParser( onparse , progress){
this.onparse = onparse;
this.progressStatus = 0;
this.progress = progress;
this.parser = function (chunk)
}
this.parse = function(){
// Do stuff of parsing
// Determine how much data is it
// Now make a function that parses a bit of data in every run
// Keep on calling the function till the data is getting parsed
// THat function should also increase the percentage it think this can be done via setTimeout.
// After every run of the semi parser function call the progress via something like
this.parser();
if(progressStatus <100){
this.progress(this.progressStatus);
}else{
this.parsed();
}
}
}
and u can create instance of that object like
var dark = new customFileParser( function () { // this tells what to
do what parsed is complete } , function (status) { // this tells what
to do with the progress status } ) ;
using the method i suggested. you can actually define different methods for all the instances of the object you have !
I'm sorry if this question has been asked before, but I'm not even sure what search terms to use to find the answer and when I try to search I never get anything specific to this question.
I'm using Javascript and I am wondering if it is possible to do something like this:
find(x); // find a document (for example)
find.inFolder(y); // find a folder's documents (for example)
In other words, can I have a function that can also be used as an object/class? I know I could run find() once and return a hash so that find.inFolder() would work, but I'm hoping there's a way where I could continue to call find().
Can it be done with prototype? (my "prototype" knowledge is very limited)
function find() {}
find.prototype.inFolder = function() {}
Can it be done inside a hash? [I know this code doesn't work]
var find = {
() : function() {},
inFolder : function() {}
}
To push it even further, is there a way to have the results of .inFolder() be sent to the find() function this way:
find().inFolder();
I know you might say that I don't understand the concept of javascript, and you'd be mostly correct, but I've seen people do some pretty amazing stuff with JS so I thought I'd ask the pros out there.
Thanks in advance for any help.
What you're describing is a Fluent interface (if you want something to search for). You could accomplish something like what you're trying to achieve like this:
var find = function() {
this.inFolder = function() {
return this; // Although to stop chaining, you could return nothing here.
};
return this;
};
find().inFolder(); // .inFolder().inFolder()...
This is a great pattern, especially when leveraged in projects like jQuery:
$("#element").find(".child_element").first();
Each call returns a jQuery object with .find(), .first() and many other functions, which lets you write intuitive and fluid code.
I kind of liked your find().inFolder() example, so here's an expanded version:
var find = function(file) {
this.folders = {
"Documents": ["Foo.txt", "Bar.txt"],
"Downloads": ["File.exe"],
"Misc": ["Picture.jpg"]
};
this.file = file;
this.inFolder = function(folder) {
var files = this.folders[folder];
return files.indexOf(this.file) >= 0;
};
return this;
};
alert(find("Foo.txt").inFolder("Documents")); // True
alert(find("File.exe").inFolder("Downloads")); // True
alert(find("Picture.jpg").inFolder("Downloads")); // False
http://jsfiddle.net/andrewwhitaker/TCdTd/
You can assign, a function to a member of another function:
find = function(x) { .... }
find.inFolder = function(y) { ... }
jsFiddle.
I'm not sure I understand the question however.
I've been struggling lately with understanding the best way to organize jQuery code. I asked another question earlier and I don't think I was specific enough (found in this question here).
My problem is that the richer you make an application, the quicker your client side gets out of control. Consider this situation...
//Let's start some jQuery
$(function() {
var container = $("#inputContainer");
//Okay let's list text fields that can be updated
for(var i=0; i < 5; i++) {
//okay let's add an event for when a field changes
$("<input/>").change(function() {
//okay something changed, let's update the server
$.ajax({
success:function(data) {
//Okay - no problem from the server... let's update
//the bindings on our input fields
$.each(container.children(), function(j,w) {
//YIKES!! We're deep in here now!!
$(w).unbind().change(function() {
//Then insanity starts...
}); // end some function
}); //end some loop
} // what was this again?
}); //ending something... not sure anymore
}).appendTo(container); //input added to the page... logic WAY split apart
}; //the first loop - whew! almost out!
}); //The start of the code!!
Now this situation isn't too far from impossible. I'm not saying this is the right way to do it, but it's not uncommon to find yourself several levels down into a jQuery command and starting to wonder how much more logic can add before the screen begins to melt.
My question is how are people managing this or organizing to limit the complexity of their code?
I listed how I'm doing it in my other post...
Just want to add to what was mentioned previously that this:
$.each(container.children(), function(j,w) {
$(w).unbind().change(function() { ... });
});
can be optimized to:
container.children().unbind().change(function() { ... });
It's all about chaining, a great way to simplify your code.
So far, I do it like this:
// initial description of this code block
$(function() {
var container = $("#inputContainer");
for(var i=0; i < 5; i++) {
$("<input/>").changed(inputChanged).appendTo(container);
};
function inputChanged() {
$.ajax({
success: inputChanged_onSuccess
});
}
function inputChanged_onSuccess(data) {
$.each(container.children(), function(j,w) {
$(w).unbind().changed(function() {
//replace the insanity with another refactored function
});
});
}
});
In JavaScript, functions are first-class objects and can thus be used as variables.
Well, for one, having a good IDE that understands javascript can help tremendously, even if just to identify matching demarcations (braces, parens, etc).
If your code starts to really get that complex, consider making your own static object to organize the mess - you don't have to work so hard to keep everything anonymous.
var aCustomObject = {
container: $("#inputContainer"),
initialize: function()
{
for(var i=0; i < 5; i++)
{
$("<input/>").changed( aCustomObject.changeHandler );
}
},
changeHandler: function( event )
{
$.ajax( {success: aCustomObject.ajaxSuccessHandler} );
},
ajaxSuccessHandler: function( data )
{
$.each( aCustomObject.container.children(), aCustomObject.updateBindings )
},
updateBindings: function( j, w )
{
$(w).unbind().changed( function(){} );
}
}
aCustomObject.initialize();
In my opinion the method described by BaileyP is what I use to start off with then I normally abstract everything into more re-usable chunks, especially when some functionality expands to the point where it's easier to abstract it into a plugin then have it specific to one site.
As long as you keep the large blocks of code in a seperate file and coded nicely you can then end up with some really clean syntax.
// Page specific code
jQuery(function() {
for(var i = 0; i < 5; i++) {
$("<input/>").bindWithServer("#inputContainer");
}
});
// Nicely abstracted code
jQuery.fn.bindWithServer = function(container) {
this.change(function() {
jQuery.ajax({
url: 'http://example.com/',
success: function() { jQuery(container).unbindChildren(); }
});
});
}
jQuery.fn.unbindChildren = function() {
this.children().each(function() {
jQuery(this).unbind().change(function() {});
});
}
Somebody wrote a post on the similar topic.
jQuery Code Does not have to be Ugly
For instance, the author, Steve Wellens, suggests to not use anonymous functions, as it makes code harder to read. Instead, push the function reference into the jQuery methods, like so:
$(document).ready(DocReady);
function DocReady()
{
AssignClickToToggleButtons();
ColorCodeTextBoxes();
}
Another takeaway from the article is to assign a jQuery object to a concrete variable, which makes the code look cleaner, less dependent on the actual jQuery object, and easier to tell what a certain line of code is doing:
function ColorCodeTextBoxes()
{
var TextBoxes = $(":text.DataEntry");
TextBoxes.each(function()
{
if (this.value == "")
this.style.backgroundColor = "yellow";
else
this.style.backgroundColor = "White";
});
}
Stick some of the anon functions into global scope functions (or your own "namespace" object), especially the re-used functions, and it begins to look less like what you posted. Kind of like what you linked to.
I described my approach in your other post. Short form:
do not mix javascript and HTML
use classes (basically start to see your application as a collection of widgets)
only have a single $(document).ready(...) block
send jQuery instances into your classes (instead of using plugins)
Use http://coffeescript.com/ ;)
$ ->
container = $ '#inputContainer'
for i in [0...5]
$('<input/>').change ->
$.ajax success: (data) ->
for w in container.children()
$(w).unbind().change ->
alert 'duh'