JavaScript - Private Methods That Point To Object References In Closures
Hey all,
I am having issues with below script. Firebug returns: form[0] is undefined [Break on this error] $(form[0].elements).each(function() { I have this under my form: <script> var thisForm = $('#validateForm'); thisForm.validation(); </script> Code: (function($) { /* Validation Singleton */ var Validation = function() { var rules = { email : { check: function(value) { if(value) return testPattern(value,".+@.+\..+"); return true; }, msg : "Enter a valid e-mail address." }, url : { check : function(value) { if(value) return testPattern(value,"https?://(.+\.)+.{2,4}(/.*)?"); return true; }, msg : "Enter a valid URL." }, required : { check: function(value) { if(value) return true; else return false; }, msg : "This field is required." } } var testPattern = function(value, pattern) { var regExp = new RegExp("^"+pattern+"$",""); return regExp.test(value); } return { addRule : function(name, rule) { rules[name] = rule; }, getRule : function(name) { return rules[name]; } } } /* Form factory */ var Form = function(form) { var fields = []; $(form[0].elements).each(function() { var field = $(this); if(field.attr('validation') !== undefined) { fields.push(new Field(field)); } }); this.fields = fields; } Form.prototype = { validate : function() { for(field in this.fields) { this.fields[field].validate(); } }, isValid : function() { for(field in this.fields) { if(!this.fields[field].valid) { this.fields[field].field.focus(); return false; } } return true; } } /* Field factory */ var Field = function(field) { this.field = field; this.valid = false; this.attach("change"); } Field.prototype = { attach : function(event) { var obj = this; if(event == "change") { obj.field.bind("change",function() { return obj.validate(); }); } if(event == "keyup") { obj.field.bind("keyup",function(e) { return obj.validate(); }); } }, validate : function() { var obj = this, field = obj.field, errorClass = "errorlist", errorlist = $(document.createElement("ul")).addClass(errorClass), types = field.attr("validation").split(" "), container = field.parent(), errors = []; field.next(".errorlist").remove(); for (var type in types) { var rule = $.Validation.getRule(types[type]); if(!rule.check(field.val())) { container.addClass("error"); errors.push(rule.msg); } } if(errors.length) { obj.field.unbind("keyup") obj.attach("keyup"); field.after(errorlist.empty()); for(error in errors) { errorlist.append("<li>"+ errors[error] +"</li>"); } obj.valid = false; } else { errorlist.remove(); container.removeClass("error"); obj.valid = true; } } } /* Validation extends jQuery prototype */ $.extend($.fn, { validation : function() { var validator = new Form($(this)); $.data($(this)[0], 'validator', validator); $(this).bind("submit", function(e) { validator.validate(); if(!validator.isValid()) { e.preventDefault(); } }); }, validate : function() { var validator = $.data($(this)[0], 'validator'); validator.validate(); return validator.isValid(); } }); $.Validation = new Validation(); })(jQuery); Similar TutorialsHey all, I am confused about the true difference between the two below examples. Code: first example: // Demonstrating a problem with closures and loops var myArray = [“Apple”, “Car”, “Tree”, “Castle”]; var closureArray = new Array(); // Loop through myArray and create a closure for each that outputs that item for (var i = 0; i < myArray.length; i++) { var theItem = myArray[i]; closureArray[i] = function() { document.write(theItem + “ < br / > ”); } } // Loop through the closures and execute each one. for (var i = 0; i < closureArray.length; i++) { closureArray[i](); } Here we iterate through the length of myArray, assigning the current index of myArray to theItem variable. We declare closureArray 4 times as an anonymous function. The anonymous function in turn declares the predefined write() function, which is passed parameters. Since write() is in closureArray() a closure is created??? During each iteration, theItem is reassigned its value. The four closures reference this value. Since they reference this same value and since this value is reassigned ultimately to the value of the fourth index position, tHe time we execute closureArray later on, all four closures output the same string. This is because all four closures are within the same scope "the same environment" and therefore are referencing the same local variable, which has changed. I have a couple of problems with this example: 1) I thought a closure is a function that is returned - the inner function is not returned above. 2) theItem is not even a local variable of the parent function (closureArray) - I thought in order for a closure to work, the inner function only accesses the local variables of the outer function, but in this case the local variable is defined OUTSIDE of the parent function. 3) The guy says the "the four closures are sharing the same environment." The thing is even in the second example, they are sharing the same environment. Second example: Code: // A correct use of closures within loops var myArray = [“Apple”, “Car”, “Tree”, “Castle”]; var closureArray = new Array(); function writeItem(word) { return function() { document.write(word + “ < br / > ”); } } // Loop through myArray and create a closure for each that outputs that item for (var i = 0; i < myArray.length; i++) { var theItem = myArray[i]; closureArray[i] = writeItem(theItem); } // Loop through the closures and execute each one. for (var i = 0; i < closureArray.length; i++) { closureArray[i](); } Here we iterate over the length of myArray (4 times), assigning the index of myArray to theItem variable. We also return a function reference to the closureArray during each iteration (closureArray[i]), where i is index number so we assign 4 functon references. So when we iterate through myArray, we immediatelly call the writeItem() fucntion passing an argument of theItem at its current value. This returns a child anonymous function and when that child function is called, it will execute a block that calls the predefined write() method. We assign that returned anonymous function to the variable closureArray. Hence, closureArray holds a reference to that anonymous function. So closureArray during each iteration holds a reference to the anonymous function and we later call closureArray, which in turn calls the anonymous function, therefore calling the predefined write() function to output the local variable of the parent function. This outputs each distinct index of myArray. QUESTION: This is because since we created the closure, when we call writeItem, passing theItem argument, since theItem is a local variable of the parent function of the closure, it is never destroyed when we later call closureArray (the reference to the child anonymous function)? Yet weren't we using a closure in the first example as well? So whey wasn't those variables preserved? I don't think it has anything to do with assigning a returned anonymous function to closureArray. Even though an anonymous function creates a new memory position in the javascript engine, therefore not overwriting the other function references we create during the iteration, it's still referring to a local variable declared outside the reference. So if it's about the closure retaining value of parent's local variable even after exiting the parent function allowing for the current indexes to be preserved, then why did the closure in the first example fail to retain each index? Thanks for response I created a method for displaying an object's properties: Code: renderfunction = false; function showProperty (object, property) { document.write ('<td class="type">' + (typeof object[property]) + '</td>' + '<td class="name">' + property + '</td>'); document.writeln('<td class="value">' + ( (typeof object[property] != 'function') ? object[property] :( (property != 'showProperties') ? ( renderfunction ? object[property]() : ('<span class="self">NOT RENDERED</span>') ) : ('<span class="self">THIS</span>') ) ) + '</td>'); document.writeln('<td class="hasOwnProperty" >' + ( object.hasOwnProperty(property) ? "Local" : "Inherited" ) + '</td>'); if (typeof object[property] == 'function') { document.writeln ('<td class="function">' + object[property] + '</td>'); } else { document.writeln ('<td class="function"> </td>'); } } As long as renderfunction = false, the object is fine coming out of this function. However, if I change renderfunction to true, all my properties become undefined. Why isn't this working as I expect it to? How should I fix it? Thanks in advance, -Brian. Do many programmers remember most of the object properties and methods or do they use IDE or references to find those specific objects. I'm starting to learn Javascript and seeing all the different type of objects available can be depressing. This is in reference to Crockford's articles found he http://javascript.crockford.com/prototypal.html http://javascript.crockford.com/private.html I'm attempting to understand the use of privileged methods when used with Object.create. I put together a quick demo (code below) that shows what happens when I use Object.create to create a new object based on one that has a privileged method. The outcome is not pleasant, as changing the value in the first object also changes it in the second. Unless I am reading Crockford's articles incorrectly, this makes Object.create almost useless for anything but objects that have only public members. I've seen many JavaScript programmers use closures extensively to create private members, and that still holds to be a good programming practice. However I still can't find an elegant way to create inheritance in combination with closures in JavaScript, given downfalls such as the one I mentioned above. With all of that said I still think Crockford has a nice way of programming, creating factory functions that produce objects, staying away from the prototype property and making the language look more functional. Here's the code to demonstrate what I'm referring to. Firebug needs to be enabled to view the console.debug output, otherwise convert them to alerts. Code: if (typeof Object.create !== 'function') { Object.create = function (o) { function F() {} F.prototype = o; return new F(); }; } var o = (function() { var msg = "hi"; return { msg: function(m) { if (m === undefined) { return msg; } msg = m; } }; })(); var foo = Object.create(o); var bar = Object.create(foo); console.debug(foo.msg()); // "hi" foo.msg("what?"); console.debug(foo.msg()); // "what?" console.debug(bar.msg()); // "what?" I get programming. Really, I do. But this closure thing has me lost and needing a nice, simple explanation. Here's the code from the dojo tutorial: <script type="text/javascript"> dojo.require("dijit.form.Button"); // this is just to make the demo look nicer var arrFruit = ["apples", "kiwis", "pineapples"]; function populateData() { dojo.forEach(arrFruit, function(item, i) { var li = dojo.doc.createElement("li"); li.innerHTML = i + 1 + ". " + item; dojo.byId("forEach-items").appendChild(li); }); } </script> It is the anonymous function(item, i) that is perplexing me. As I see it, this use is not CREATING a function. It is calling a function called "function." Clearly, I am not up-to-speed. I am confounded as to how, within function(), "item" is KNOWN to refer to the value of the array element, and "i" is KNOWN to refer to the current element in the dojo.forEach() function. In my mind, I see a call to function, trying to pass parameters to it which were never defined above. The way I see it is: function myfunction(item, i) {code here} myfunction(this, that); In this example, I would get an error because "this" and "that" are not defined. Help, please!!! I tried a a few tutorials but still can't get it, can any simply closures please?
Recently I had an issue while trying to copy an array: I couldn't understand why modifying the new array caused modifications in the old array Old Pedant cleared that up nicely for me in http://www.codingforums.com/showthread.php?t=240020 Now I'm trying to understand closures, and scope and all that fun stuff thanks to Venegal's great tutorial at reallifejs.com and I have the following: Code: <script> window.USER = (function(){ var Employees = [['Alex',1,'ft',1],['Olivia',2,'ft',1],['Brenda',3,'ft',1],['Michael',4,'ft',1]]; var info = ['Start String']; var Setup = function(){ } return{ CheckLogin : function(login){ this.info = Employees[login]; }, Reset : function(){ }, info:info, Emp:Employees }; })(); </script> And I think I got all the kinks worked out, but there was one thing that I don't understand... Based on my other thread I expected the modification of USER.info to overwrite values in USER.Emp Don't get me wrong, I didn't want that to happen, I am just confused as to why it didn't I used the following buttons to test the values of USER.info and USER.Emp but again, writing to USER.info did not overwrite anything in USER.Emp.... Code: <script> document.write('<button onclick="alert(USER.info)">USER.info read</button>'); document.write('<button onclick="USER.info=\'Test String\'">USER.info write</button>'); document.write('<button onclick="alert(USER.Emp)">Employees read</button>'); document.write('<button onclick="USER.CheckLogin(0)">Check Login</button>'); </script> So what I guess I'm asking is why? Or maybe: what is happening here, and how does it differ from my last issue? Was it maybe a scope issue? Or maybe something more sinister...? Hello everyone, I have been working on this function but no luck so far. Basically this is a simple vertical navigation menu, and I am just trying to to show or hide the sub-menus (unordered lists) with onmouseover & onmouseout. I can do this very easily with just css or inline events, but I'm just trying to figure it out the way I already set it up. So I am looping through the ULs first, then I loop through the LIs. Furthermore I find the right LI elements by checking their class names, and if they exist I trigger the onmouseover & onmouseout events on them so the ULs will appear/disappear. The issue is that this works only for the last list item because I am guessing of a closure. So instead of getting each item individually at each event, instead it gives me the last list item. I have searched the web for a while now about closures and such, but all the examples I find talk about nested functions and a single loop, which isn't my case because I have two loops and only one function. Any help would be appreciated. HTML Code: Code: <div id="navWrapper"> <ul> <li class="triggers"><a href="#">Item 1</a> <ul class="subMenu"> <li><a href="#">Item 1.1</a></li> <li><a href="#">Item 1.2</a></li> <li><a href="#">Item 1.3</a></li> </ul> </li> <li class="triggers"><a href="#">Item 2</a> <ul class="subMenu"> <li><a href="#">Item 2.1</a></li> <li><a href="#">Item 2.2</a></li> <li><a href="#">Item 2.3</a></li> </ul> </li> <li class="triggers"><a href="#">Item 3</a> <ul class="subMenu"> <li><a href="#">Item 3.1</a></li> <li><a href="#">Item 3.2</a></li> <li><a href="#">Item 3.3</a></li> </ul> </li> </ul> </div> Javascript Code: Code: <script type="text/javascript"> function hoverSh () { var navWrap = document.getElementById('navWrapper'); var uls = navWrap.getElementsByTagName('ul'); var listItems = navWrap.getElementsByTagName('li'); for (var i=0; i<uls.length; i++) { if (uls[i].className == "subMenu") { var theUls = uls[i]; for (var j=0, c=listItems.length; j<c; j++) { if (listItems[j].className == "triggers") { var theItems = listItems[j]; theItems.onmouseover = function () {//alert(this.nodeName + i);return false; theUls.style.display = 'block'; } theItems.onmouseout = function () { theUls.style.display = 'none'; } }//end inner if }//end inner loop w/ j }//end if }//end outer loop w/ i } window.onload = hoverSh; </script> Any links pointing to simplified tutorials on closures would be helpful too. I thought I understood them but I guess not! im new to webpage programming,but do hav some basic c/c++ programming skill. in order for me to understand the following codes, what should i read? i had read thru w3schools.com html and javascript tutorials but it is stil difficult for me to understand the codes,can somebody help me?thanks! Code: function getQuery() { var scoping = "&project=${currentProject}&projectScopeUp=" + projectScopeUp + "&projectScopeDown=" + projectScopeDown; var paging = "&pagesize=100"; return { "currentProject" : "/iteration:current/project", "#storyType" : "/typedefinition?query=(Name = \"Hierarchical Requirement\")", "taskUnit" : "${iteration/workspace/workspaceConfiguration/taskUnitName}", "storyStates" : "${#storyType/attributes[name=schedule state]/allowedvalues/stringvalue}", "iteration" : "/iteration:current?fetch=name,objectid&order=StartDate", "iterations" : "/iterations?fetch=name,objectid&order=StartDate,Name&project=${currentProject}&projectScopeUp=false&projectScopeDown=false" + paging, "users" : "/users?fetch=displayname,loginname,emailaddress,objectid" + paging, "tasks" : "/tasks?fetch=taskindex,name,objectid,formattedid,owner,blocked,estimate,todo,actuals,state,workproduct&query=(Iteration = ${iteration})" + scoping + paging, "stories" : "/hierarchicalrequirement?fetch=rank,blocked,formattedid,name,objectid,owner,project,schedulestate,taskestimatetotal,taskremainingtotal,taskactualtotal,tasks&order=Rank&query=(Iteration = ${iteration})" + scoping + paging, "defects" : "/defect?fetch=rank,blocked,formattedid,name,objectid,owner,project,schedulestate,taskestimatetotal,taskremainingtotal,taskactualtotal&order=Rank&query=(Iteration = ${iteration})" + scoping + paging, "defectsuite" : "/defectsuite?fetch=rank,blocked,formattedid,name,objectid,owner,project,schedulestate,taskestimatetotal,taskremainingtotal,taskactualtotal&order=Rank&query=(Iteration = ${iteration})" + scoping + paging, "testsets" : "/testset?fetch=rank,blocked,formattedid,name,objectid,owner,project,schedulestate,taskestimatetotal,taskremainingtotal,taskactualtotal&query=(Iteration = ${iteration})" + scoping + paging }; } is there a way to shorten something like: document.scoresheet["HomeTotalHCaps"].value to a simple short name like var1.value ? So I am using JavaScript to make a table on a page and what I want to do is have the JavaScript create the table, and then allow the user to fill it with data. I have been able to make the JavaScript create the table, my question is how to reference the cells in my script that adds data to the cell. I want the users to be able to click a button an add data into different cells so i figured giving them each an Id and referring to that Id in the button is the best way to do it. How can I edit my code to give each cell a different Id? Or is there a better way of doing this? My table code looks like this (i have filled it with random data so it is not just a blank table). <code> <script type="text/javaScript"> window.onload = fnInit; function fnInit() { // Declare variables and create the header, footer, and caption. var oTable = document.createElement("TABLE"); var oTHead = document.createElement("THEAD"); var oTBodyam = document.createElement("TBODY"); var oTBodypm = document.createElement("TBODY"); var oTFoot = document.createElement("TFOOT"); var oCaption = document.createElement("CAPTION"); var oRow, oCell; var i, j; // Declare stock data that would normally be read in from a stock Web site. var heading = new Array(); heading[0] = ""; heading[1] = "Monday"; heading[2] = "Tuesday"; heading[3] = "Wednesday"; heading[4] = "Thursday"; heading[5] = "Friday"; var block = new Array(); block[0] = "8:30"; block[1] = "9:55"; block[2] = "11:20"; block[3] = "12:45"; block[4] = "2:10"; block[5] = "3:35"; block[6] = "5:00"; block[7] = "6:30"; var stock = new Array(); stock[0] = new Array(block[0],"88.625","85.50","85.81","99.54","55.46"); stock[1] = new Array(block[1],"102.75","97.50","100.063","49.54","55.46"); stock[2] = new Array(block[2],"56.125","54.50","55.688","99.54","55.46"); stock[3] = new Array(block[3],"71.75","69.00","69.00","99.54","55.46"); stock[4] = new Array(block[4],"71.75","69.00","69.00","99.54","55.46"); stock[5] = new Array(block[5],"71.75","69.00","69.00","99.54","55.46"); stock[6] = new Array(block[6],"71.75","69.00","69.00","99.54","55.46"); stock[7] = new Array(block[7],"71.75","69.00","69.00","99.54","55.46"); // Insert the created elements into oTable. oTable.appendChild(oTHead); oTable.appendChild(oTBodyam); oTable.appendChild(oTBodypm); oTable.appendChild(oTFoot); oTable.appendChild(oCaption); // Set the table's border width and colors. oTable.border=1; oTable.bgColor="lightslategray"; // Insert a row into the header and set its background color. oRow = document.createElement("TR"); oTHead.appendChild(oRow); oTHead.setAttribute("bgColor","lightskyblue"); // Create and insert cells into the header row. for (i=0; i<heading.length; i++) { oCell = document.createElement("TH"); oCell.innerHTML = heading[i]; oRow.appendChild(oCell); } // Insert rows and cells into bodies. for (i=0; i<stock.length; i++) { var oBody = (i<3) ? oTBodyam : oTBodypm; oRow = document.createElement("TR"); oBody.appendChild(oRow); for (j=0; j<stock[i].length; j++) { oCell = document.createElement("TD"); oCell.innerHTML = stock[i][j]; oRow.appendChild(oCell); } } </code> Hi Guys, What is the best way to create a javascript class that has all its methods and properties private unless I want them to be public? Many thanks for any help, S A webapp i'm working on needs to be able to use UTF8 characters, and be able to write them to a disk (using XP Universal Connect) - just like my previous webapps. However, when i write normal text to the output file, i get no problems. When i try to write a Chinese character (e.g. 你) to the output file, i just get a comma " ' " character written in it's place. here is the function that is writing the data to the disk: Code: function SaveToDisk(FileName, Content) { try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); } catch (e) { alert("Permission to save file was denied."); } var file = Components.classes["@mozilla.org/file/local;1"] .createInstance(Components.interfaces.nsILocalFile); file.initWithPath( FileName ); if ( file.exists() == false ) { file.create( Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 420 ); } var outputStream = Components.classes["@mozilla.org/network/file-output-stream;1"] .createInstance( Components.interfaces.nsIFileOutputStream ); outputStream.init( file, 0x04 | 0x08 | 0x20, 420, 0 ); var output = Content; var result = outputStream.write( output, output.length ); outputStream.close(); } I checked my browser, and it's already in UTF8 mode when i am writing this file. I'm curious as to what is not working. Is there some special value that i need to change in my SaveToDisk() function? hey guys, i've just started programming in javascript, and now i am studying how to use OOP in javascript. i've read most of the tutorials but none of them has mentioned anything about the public, private and protected stuff. so i guess my question is - does oo in javascript deal with public,private and protected methods or variables? thanks in adv. Hi, every time I try and alert: [ { number:0, secondnumber:0 }, { number:2, secondnumber:1 }, { number:1, secondnumber:2 } ] it just shows [object object], [object object], [object object]. Why is this and what can I do to make the record be shown as it is above in an alert? Thanks. Hello all, I want to sell online private lessons using Skype. I'd like to display on my front page a schedule with my available time-slots so that the customer may click a time-slot and be sent to the product/lesson detail view to complete the purchase. 1. Would it be possible for a JQuery calendar/schedule plugin to know that the customer has completed the purchase and therefore make it impossible for another user to purchase the same time-slot (by changing it's appearance and making it unclickable for example)? 2. Can a JQuery plugin be adapted to that use? 3. Would it be very complex to do for a developer? Thanks for your advice I can't get any info from Firebug except that one line, uncaught exception [object Object]. The code fully worked, then I needed to make it dynamically create Sortables from the scriptaculous library based on how many X were in a table in my database, which I've done, and I'm thinking it may be a simple slight parse error of some type, I'm not too good with Javascript, because now my script barely works. I've double checked the script's source code, the PHP variables are exactly what they should be. Code: print<<<HERE Sortable.create('sortlist$box', { tag: 'img', overlap:'horizontal',constraint:false, containment: $list, dropOnEmpty: true, onChange: function(item) { var list = Sortable.options(item).element; if(changeEffect) changeEffect.cancel(); changeEffect = new Effect.Highlight('changeNotification', {restoreColor:"transparent" }); }, onDrop: function(item) { var thing=Sortable.options(item).element.identify(); var anchors = document.getElementById(thing).childNodes.length-2; if(anchors > 20){ alert('This box had 20 creatures in it already, your last action has not been saved.'); window.location.reload(); } else{ new Ajax.Request("saveImageOrder.php", { method: "post", parameters: { data: Sortable.serialize("sortlist$box") } }); } } }); HERE; $box++; } ?> }); </script> if you solve this I'll send ya $10 via paypal |