JavaScript - Oop - Maintain Prototype Instances (this) Beyond Ajax Callbacks And Onclick Events
I'm pretty new to Javascript and just started with some OOP concepts, so this might be an obvious one and I apologize if the question is much longer than it should be...
Basically I am trying to create a reusable class object with several internal functions, that is completely abstracted, meaning the class object itself should never have to reference the global declarations or window object. This class should be aware of itself at any point in the execution of it's own functions, and that is what I'm having trouble with at the moment. What I'm trying to do is create reusable javascript "Apps" for my HTML web application, where multiple instances can be instantiated and used independently from one another. My main problem is "this" loses context in the Ajax callback and onclick handlers. I'm not sure how to persist the context of "this", or at least keep a reference to prototype instance itself. Let's set up a simple class called "App" to demonstrate what I mean... Code: var myApp = new App("MyFirstApp"); function App(argName) { this.name = argName; this.GetDirectory("C:\Program Files"); } App.prototype.GetDirectory = function(argPath) { // "this" equals the App object instance (good!), meaning this.name should equal "MyFirstApp" Ajax.GetDirectory(argPath, this.GetDirectoryCallback, this.GetDirectoryTimeout, this.GetDirectoryError); } App.prototype.GetDirectoryCallback = function(argFilePaths) { // "this" equals the "window" object (bad!), meaning this.name should equal a null reference // argFilePaths contains a string of file paths (delimited using ;) returned by the server var mFilePaths = split(argFilePaths, ";"); // for each file path, add a div to the document body containing that file path, with an onclick handler for (var i in mFilePaths) { var mFilePath = mFilePaths[i]; var mFilePathDiv = document.createElement("div"); mFilePathDiv.innerHTML = mFilePath; mFilePathDiv.setAttribute("onclick", "javascript:this.FilePathDivClickHandler();return false;"); document.getElementById("body").appendChild(mFilePathDiv); } } App.prototype.FilePathDivClickHandler = function() { // I need a reference to the App object instance here, but I'm not sure where to grab it... // what I want to do is call GetDirectory again, referencing the div's innerHTML which contains another file path, like this: this.GetDirectory(event.target.innerHTML); } The onclick handler using "this" is obviously not going to work because "this" is a reference to the "window" object which does not have a function called FilePathDivClickHandler(). So what I can do is nest the GetDirectoryCallback() function inside the GetDirectory() function so that GetDirectoryCallback() can reference the variables in the outer function (GetDirectory). Code: App.prototype.GetDirectory = function(argPath) { // "this" equals the App object instance (good!), meaning this.name should equal "MyFirstApp" // "this" will still lose context inside the callback, so we can set up a variable called "instance" that the callback can reference var instance = this; Ajax.GetDirectory(argPath, GetDirectoryCallback, GetDirectoryTimeout, GetDirectoryError); function GetDirectoryCallback(argFilePaths) { // "this" equals the window object (bad!), meaning this.name should equal a null reference // "instance" equals the App object instance (good!), meaning instance.name should equal "MyFirstApp" // argFilePaths contains a string of file paths (delimited using ;) returned by the server var mFilePaths = split(argFilePaths, ";"); // for each file path, add a div to the document body containing that file path, with an onclick handler for (var i in mFilePaths) { var mFilePath = mFilePaths[i]; var mFilePathDiv = document.createElement("div"); mFilePathDiv.innerHTML = mFilePath; mFilePathDiv.setAttribute("onclick", "javascript:instance.FilePathDivClickHandler();return false;"); document.getElementById("body").appendChild(mFilePathDiv); } } } Even though we have persisted the App object instance through the use of the "instance" variable in the outer function, the onclick event handler still does not work; when it fires, "instance" is an unknown object. Would placing the FilePathDivClickHandler() function inside the GetDirectory() function, much like what was done with the callback, allow me to use "instance" correctly for the onclick handler? Similar TutorialsWith input box if you type something and refresh the page, the previous words that you typed in will be filtered and be display in a scroll down form in which you can click it. My question is, when I click the input type is it possible to scroll down, and display values that comes from a database? It should also filter the scroll down results. If it's possible I don't know how to do it. I tried googling but I can't find an explanation on how to do it. Thanks. <input type="text" value="" onclick=""> Hi Guys I have been trying to implement a way of using `onclick` to fill out a form field, with a Value assigned by a clickable rollover image. So i have a image rollover of a PC, i give the PC a Value? ID? of `PC No34` When the image is clicked it updates its Value of PC No34 to a Form text field which is named `pcid` the Form is on the same page as the PC rollover image. I have been trying most of the day but not getting it. Pls help Thanks for any help with this Willo Hi, I am having a slight difficulty and hope someone can easily set me straight. I am trying to use the following code to track a button click and the second onclick event, the urchin tracking is not being completed but the first function is.... can someone please hopefully set me straight easily on the code? Many thanks Steve123. Code: <input type="submit" name="Submit" value="Buy Product" class="buy" onClick="document.form.submit();javascript:urchinTracker('/html/productdeals_button.asp')"> Is it possible to add an onclick event to an iframe or perhaps a DIV that holds an iframe? In specific I am using the Facebook Open Graph like button: Code: <iframe src="http://www.facebook.com/plugins/like.php?layout=button_count&show_faces=true&width=450&action=like&colorscheme=light&href=http://urltoshare.com/" scrolling="no" frameborder="0" allowTransparency="true" style="border:none; overflow:hidden; width:450px; height:21px"></iframe> What I would like to do is add a simple onclick event to it so that I can run a process when the user clicks on it, at the moment I am just trying alert but cannot get it to work. By setting the iframe within a DIV with height/width specs set would an onclick event work within the DIV? OK, I'm filling in for a coworker on a radio stations website. The station currently streams live online. I want to add an event tracking so I can track how many people are streaming. I'm really new to js, but I think I figured it out (keyword is "think"). However, there was already an onclick event within the anchor tag. Can I have two in the same tag? Is there a better way to do this? Code: <a href="/fmstream/listen.asx" onclick="window.open(this.href,'Listen','resizable=no,location=no,menubar=no,scrollbars=no,status=no,toolbar=no,fullscreen=no,dependent=no,width=400,height=400,status'); return false" onClick="pageTracker._trackEvent('Stream','Listen_Button','Stream_Live');"> <img src="/images/filecabinet/folder1/listen1.png" alt="listen1"></a> Hi all, I hope that someone can help me with this strange problem I have here. I have some script which changes a button and changes the onclick event. The strange thing is that although it is changing it. All the events have the same parameter even though my code is giving each button's onclick event it's own unique parameter. Here's my Code. Code: var AllocPeople = window.opener.document.getElementById('AllocPeople'); if(AllocPeople.value.length > 0) { var people = AllocPeople.value.split(","); var Controls = new Array(); for(var P in people) { var id = people[P]; Controls[P] = document.getElementById('bt_AP_'+id); Controls[P].innerHTML = "Deallocate"; Controls[P].onclick = function() {Remove_Player(id)}; } } Thanking you all in advance. I am a Javascript newbie. I'm trying to code a page that has thumbnails of smaller images that when each image is clicked a larger image will load above the thumbnails, plus text within a div will change, plus more Javascript behind a shopping cart button will change. I'm not sure if this is even possible and have been searching and experimenting with the code without success. To view the webpage I'm working on: http://toymakerpress.com/website/Fre.../TestPage.html If you click on the dog image you can see where I'm headed (I also haven't had any luck loading the shopping cart button with it's unique Javascript code). Here is my code so far: The shopping cart button (I would like this code to swap out everytime I load a new image): Code: <a href="https://www.e-junkie.com/ecom/gb.php?c=cart&i=A0085&cl=82487&ejc=2" rel="nofollow" target="ej_ejc" class="ec_ejc_thkbx" onclick="javascript:return EJEJC_lc(this);"><img src="../images/addtocart1.gif" border="0" alt="Add to Cart"/></a> The code I'm working on for each thumbnail image: Code: <td><div align="center"> <a href="javascript:changeImage('../images/FreePlans/littledog-4Lg.jpg') "javascript:="javascript:"" onClick="load_content('orderform','more content') "><img src="../images/FreePlans/littledog-4.jpg" width="140" height="140" border="0" /></a></div></td> Thanks! HTML TARGET: Code: <div id="login_link" style="margin-top:-142px;margin-left:245px;height:142px;"> <img id="login_link" src="menu_button.png" /><a href="#"><img src="menu_button.png" /></a></div> </div> I'm trying to get menu_button.png to change to menu_button2.png on mouseover... I'd also like it to play a sound on click like "click.wav" I can't rename the div because it controls the slider Heres my current project table: http://bit.ly/dbwH23 I tried to put it in a span and have the span referance to the next tag but it didn't seem to work at least not in firefox. I'm going to keep lookin around but i'm not used to these types of code structure. I was thinking of Embeding a flash file inside the div instead but that might be overkill. Anyone know of a solution that might work? Hi, all~..According to ECMAScript, the root of the prototype chain is Object.Prototype. Each object has an internal property [[Prototype]] that could be another object or NULL.... However, it also says that every function has the Function prototype object: Function.Prototype, it confused me, because a function is an object, for a function object, what is its function prototype and object prototype..For example: Code: var x = function (n) {return n+1;}; what is the relationships of x, Object.Prototype and Function.Prototype Thx a lot !!!!!!!!! Hi, Need some help please. I have the following function: Code: <script type="text/javascript"> function getVote(int) { if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); } else {// code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { document.getElementById("ajax").innerHTML=xmlhttp.responseText; } } var questionid = document.question.questionid.value; xmlhttp.open("GET","result.php?id="+questionid+"&vote="+int,true); xmlhttp.send(); } </script> I then have the following onClick: Code: <input type="radio" name="vote" value="1" onClick="getVote(this.value);" /> <input type="radio" name="vote" value="2" onClick="getVote(this.value);" /> Currently, all is good and works perfectly, the div 'ajax' refreshes ajax style with 'result.php' and I can take the value. But what I now need to do is refresh two divs. I have tried everything from putting two onClicks on the radio button, within the 'getVote' function calling in the second function and many more alternatives. The second function is pretty much the same, just a different div ID: Code: <script type="text/javascript"> function getTotal(int) { if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); } else {// code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function() { if (xmlhttp.readyState==4 && xmlhttp.status==200) { document.getElementById("total").innerHTML=xmlhttp.responseText; } } xmlhttp.open("GET","total.php?id="+questionid+"&vote="+int,true); xmlhttp.send(); } </script> The problem I have, I think, is that both functions need to use 'xmlhttp.open', and it seems once one has ran, the functions end. Any ideas gratefully received. Thanks. I am using a freebie script that changes css elements using onClick when you hit a button. I have 12 choices I want to add, and don't want 12 buttons, but rather a dropdown list. 2 button examples (and js code) is: <input onclick="changecss('li','background','url(images/list_02.jpg) no-repeat 10.2em .12em')" value="Change to BG 2" type="button" /> <input onclick="changecss('li','background','url(images/list_03.jpg) no-repeat 10.2em .12em')" value="Change to BG 3" type="button" /> How do I convert this to a SELECT list?? Thank you! Hey guys, here's my code Code: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Untitled Document</title> <script src="jquery-1.3.2.min.js" type="text/javascript"></script> <style type="text/css"> #box { background: red; width: 300px; height: 300px; display: none; } #box2 { background: green; width: 300px; height: 300px; display: none; } </style> <script type="text/javascript"> $(function() { $('a.about').click(function() { $('#box').stop().slideToggle(2000); }); }); $(function() { $('a.contact').click(function() { $('#box2').stop().slideToggle(2000); }); }); </script> </head> <body> <div id="box"></div> <div id="box2"></div> <a href="#" class="about" />about</a> <a href="#" class="contact" />contact</a> </body> </html> Basically I want to make it so that if you click about, and about is open, once you click contact it closes about before opening contact? I'm not sure how to approach this though whether I should use if statements or something? I'm pretty new to jquery Hey guys. I have a weird issue (you kind of have to see it for yourself to understand). If you double click on the next or previous button quickly (within 500 miliseconds of each other) it creates a double of the next slide. http://insidehb.com/imageofday/ Let me know if you can help. Thanks. See http://forums.mathannotated.com/gui-...-layout-4.html. When you click the "More" tab, the browser forgets the active tab styling and current tab contents; I don't want these to change - all I want to change on the click "More" tab action is the navigation tab. But my browser should maintain the styling for the last active tab and continue to display its corresponding tab contents. Yet it forgets these details when the user clicks "More". In particular, when user navigates back and forth between the two tab sets, whatever was the last styled active tab remains styled as such. Browser should remember this. Code: $(document).ready(function() { //When page loads... $(".tab_content").hide(); //Hide all content $("ul.tabs li:first").addClass("active").show(); //Activate first tab $(".tab_content:first").show(); //Show first tab content //On Click Event $("ul.tabs li").click(function() { $("ul.tabs li").removeClass("active"); //Remove any "active" class $(this).addClass("active"); //Add "active" class to selected tab $(".tab_content").hide(); //Hide all tab content var activeTab = $(this).find("a").attr("href"); //Find the href attribute value to identify the active tab + content $(activeTab).fadeIn(); //Fade in the active ID content return false; }); //Your additions //When page loads... $("#button_set_2").hide(); //Hide 2nd button set; added by YOU //On Click Event: hide 1st button set, show 2nd $("li#more_forward").click(function() { $("#button_set_1").hide(); $("div#button_set_2").show(); }) //On Click Event: hide 2nd button set, show 1st again $("li#more_backward").click(function() { $("#button_set_2").hide(); $("div#button_set_1").show(); }) }); Hi, I have a a html/PHP page divided into two, on the left div I have a list of subjects and on the right div I have used AJAX to populate this side with a list of questions (taken from database), this list depends on the selection made on the left. Each of the questions in the list has a checkbox, I want to be able to make selections using the checkboxes and then click on the other subjects but if I was to go back to the page with my selections the checkboxes checked previously will already be there. Any ideas on how I can do this? I would appreciate any help. Hello Everyone, I am facing problem with divs indexes persistancy on sorting when browser refreshing. checkout this fiddle once and help me. Sortable-arindam - JSFiddle Here how can i maintain the divs persistancy on sorting when page refreshing. Thanks in Advance Satish Chandragiri hi, I'm trying to inherit with prototype but I'm not able to do so. The problem is that I have a few functions which use some common variables and common functions and I want to inherit a Resource object with all these parameters. I also whant this inheritance to be done when I load the function, so no extra functions are loaded unless I need them. Here's the code Code: function Resource(){ this.url=''; this.object=new Object(); this.id=''; this.categories=new Array(); } function Users(){ Users.prototype=new Resource(); this.url='user/'; this.name=''; this.email=''; }; function test(){ var users = new Users(); alert(users.id); }; When I run the test function for the first time I get an undefined. a second time works fine. I I get the prototype definition outside the User() function it also works fine, but I want the inherited function to be loaded when I need it. Any ideas? As always, thank you for your help. Anyone wanna give me some pointers on how prototypes work exactly? ;o Especially in the context of this code: Code: var chatscroll = new Object(); chatscroll.Pane = function(scrollContainerId){ this.bottomThreshold = 20; this.scrollContainerId = scrollContainerId; this._lastScrollPosition = 100000000; } chatscroll.Pane.prototype.activeScroll = function(){ var _ref = this; var scrollDiv = document.getElementById(this.scrollContainerId); var currentHeight = 0; var _getElementHeight = function(){ var intHt = 0; if(scrollDiv.style.pixelHeight)intHt = scrollDiv.style.pixelHeight; else intHt = scrollDiv.offsetHeight; return parseInt(intHt); } var _hasUserScrolled = function(){ if(_ref._lastScrollPosition == scrollDiv.scrollTop || _ref._lastScrollPosition == null){ return false; } return true; } var _scrollIfInZone = function(){ if( !_hasUserScrolled || (currentHeight - scrollDiv.scrollTop - _getElementHeight() <= _ref.bottomThreshold)){ scrollDiv.scrollTop = currentHeight; _ref._isUserActive = false; } } if (scrollDiv.scrollHeight > 0)currentHeight = scrollDiv.scrollHeight; else if(scrollDiv.offsetHeight > 0)currentHeight = scrollDiv.offsetHeight; _scrollIfInZone(); _ref = null; scrollDiv = null; } It's code to make the scrollbars autoscroll down. Full article and extra info he http://radio.javaranch.com/pascarell...837038219.html I sort of understand it but I'm not clear on what prototypes are. Code: /** * @class TestInheritance * * This is a class and it's constructor all in one but the constructor is not set yet */ function TestInheritance(){ this.testName; return this; } /** * @extends Util * Make sure this is called after the constructor/class declaration */ TestInheritance.prototype = new Util(); /** * @ctor TestInheritance * Set it to itself if there isn't an explicit constructor */ TestInheritance.prototype.constructor = TestInheritance; /** * @extends Util * This specifically is set to allow TestInheritance to access it's parent's identity */ TestInheritance.prototype.parent = new Util(); /** * @extends Util * @argument testName String * All functions are called after setting the prototype */ TestInheritance.prototype.setTestName = function(testName){ this.testName = testName; } How would I reference the same Util class on both the prototype and the parent? im currently using a prototype add on for one of my sites and id like to convert it to mootools... problem is, i dont know the first thing about prototype! i stumbled upon this before i learned any javascript and ive gotten to know mootools and like using it... heres the code, let me know if anyone can help! Code: /** * @author Bruno Bornsztein <bruno@missingmethod.com> * @copyright 2007 Curbly LLC * @package Glider * @license MIT * @url http://www.missingmethod.com/projects/glider/ * @version 0.0.3 * @dependencies prototype.js 1.5.1+, effects.js */ /* Thanks to Andrew Dupont for refactoring help and code cleanup - http://andrewdupont.net/ */ Glider = Class.create(); Object.extend(Object.extend(Glider.prototype, Abstract.prototype), { initialize: function(wrapper, options){ this.scrolling = false; this.wrapper = $(wrapper); this.scroller = this.wrapper.down('div.scroller'); this.sections = this.wrapper.getElementsBySelector('div.section'); this.options = Object.extend({ duration: 1.0, frequency: 3 }, options || {}); this.sections.each( function(section, index) { section._index = index; }); this.events = { click: this.click.bind(this) }; this.addObservers(); if(this.options.initialSection) this.moveTo(this.options.initialSection, this.scroller, { duration:this.options.duration }); // initialSection should be the id of the section you want to show up on load if(this.options.autoGlide) this.start(); }, addObservers: function() { var controls = this.wrapper.getElementsBySelector('div.controls a'); controls.invoke('observe', 'click', this.events.click); }, click: function(event) { this.stop(); var element = Event.findElement(event, 'a'); if (this.scrolling) this.scrolling.cancel(); this.moveTo(element.href.split("#")[1], this.scroller, { duration:this.options.duration }); Event.stop(event); }, moveTo: function(element, container, options){ this.current = $(element); Position.prepare(); var containerOffset = Position.cumulativeOffset(container), elementOffset = Position.cumulativeOffset($(element)); this.scrolling = new Effect.SmoothScroll(container, {duration:options.duration, x:(elementOffset[0]-containerOffset[0]), y:(elementOffset[1]-containerOffset[1])}); return false; }, next: function(){ if (this.current) { var currentIndex = this.current._index; var nextIndex = (this.sections.length - 1 == currentIndex) ? 0 : currentIndex + 1; } else var nextIndex = 1; this.moveTo(this.sections[nextIndex], this.scroller, { duration: this.options.duration }); }, previous: function(){ if (this.current) { var currentIndex = this.current._index; var prevIndex = (currentIndex == 0) ? this.sections.length - 1 : currentIndex - 1; } else var prevIndex = this.sections.length - 1; this.moveTo(this.sections[prevIndex], this.scroller, { duration: this.options.duration }); }, stop: function() { clearTimeout(this.timer); }, start: function() { this.periodicallyUpdate(); }, periodicallyUpdate: function() { if (this.timer != null) { clearTimeout(this.timer); this.next(); } this.timer = setTimeout(this.periodicallyUpdate.bind(this), this.options.frequency*1000); } }); Effect.SmoothScroll = Class.create(); Object.extend(Object.extend(Effect.SmoothScroll.prototype, Effect.Base.prototype), { initialize: function(element) { this.element = $(element); var options = Object.extend({ x: 0, y: 0, mode: 'absolute' } , arguments[1] || {} ); this.start(options); }, setup: function() { if (this.options.continuous && !this.element._ext ) { this.element.cleanWhitespace(); this.element._ext=true; this.element.appendChild(this.element.firstChild); } this.originalLeft=this.element.scrollLeft; this.originalTop=this.element.scrollTop; if(this.options.mode == 'absolute') { this.options.x -= this.originalLeft; this.options.y -= this.originalTop; } }, update: function(position) { this.element.scrollLeft = this.options.x * position + this.originalLeft; this.element.scrollTop = this.options.y * position + this.originalTop; } }); |