Windows 8 Javascript app XML Object - javascript

I'm currently trying to make a HTML/JavaScript Windows 8 modern application in which I want to access a local XML file that is in the installation directory.
After reading many ideas and code snippets around the web, I came up with a convoluted asynchronous method of accessing the file, which works. However, is this the best/correct way to do something as simple as accessing a local XML file?
Additionally, I'd like to be able to have a function load the xml file, and save the XMLDocument object as a "global" variable, so that on button presses and other triggers, the XMLDocument object can be accessed and parsed. This is where all the problems start, since one method is async, and then the variables are undefined, etc....
(function () {
"use strict";
WinJS.UI.Pages.define("/pages/reader/reader.html", {
// This function is called whenever a user navigates to this page. It
// populates the page elements with the app's data.
ready: function (element, options) {
// TODO: Initialize the page here.
var button = document.getElementById("changeText");
button.addEventListener("click", this.buttonClickHandler, false);
var dropdown = document.getElementById("volumeDropdown");
dropdown.addEventListener("change", this.volumeChangeHandler, false);
var loadSettings = new Windows.Data.Xml.Dom.XmlLoadSettings;
loadSettings.prohibitDtd = false;
loadSettings.resolveExternals = false;
//previous attempt, also didn't work:
//this.xmlDoc = null;
//this.loadXMLdoc(this, this.testXML);
//also not working:
this.getXmlAsync().then(function (doc) {
var xmlDoc = doc;
});
//this never works also, xmlDoc always undefined, or an error:
//console.log(xmlDoc);
},
buttonClickHandler: function (eventInfo) {
// doesn't work, xmlDoc undefined or error:
console.log(xmlDoc);
},
volumeChangeHandler: function (eventInfo) {
var e = document.getElementById("volumeDropdown");
// of course doesn't work, since I can't save the XMLDocument object into a variable (works otherwise):
var nodelist2 = xmlDoc.selectNodes('//volume[#name="volumeName"]/chapter/#n'.replace('volumeName', list[0]));
var volumeLength = nodelist2.length;
for (var index = 0; index < volumeLength; index++) {
var option = document.createElement("option");
option.text = index + 1;
option.value = index + 1;
var volumeDropdown = document.getElementById("chapterDropdown");
volumeDropdown.appendChild(option);
}
},
getXmlAsync: function () {
return Windows.ApplicationModel.Package.current.installedLocation.getFolderAsync("books").then(function (externalDtdFolder) {
externalDtdFolder.getFileAsync("book.xml").done(function (file) {
return Windows.Data.Xml.Dom.XmlDocument.loadFromFileAsync(file);
})
})
},
loadXMLdoc: function (obj, callback) {
var loadSettings = new Windows.Data.Xml.Dom.XmlLoadSettings;
loadSettings.prohibitDtd = false;
loadSettings.resolveExternals = false;
Windows.ApplicationModel.Package.current.installedLocation.getFolderAsync("books").then(function (externalDtdFolder) {
externalDtdFolder.getFileAsync("book.xml").done(function (file) {
Windows.Data.Xml.Dom.XmlDocument.loadFromFileAsync(file, loadSettings).then(function (doc) {
var nodelist = doc.selectNodes("//volume/#name");
var list = [];
for (var index = 0; index < nodelist.length; index++) {
list.push(nodelist[index].innerText);
};
for (var index = 0; index < list.length; index++) {
var option = document.createElement("option");
option.text = list[index] + "new!";
option.value = list[index];
var volumeDropdown = document.getElementById("volumeDropdown");
volumeDropdown.appendChild(option);
};
var nodelist2 = doc.selectNodes('//volume[#name="volumeName"]/chapter/#n'.replace('volumeName', list[0]));
var volumeLength = nodelist2.length;
for (var index = 0; index < volumeLength; index++) {
var option = document.createElement("option");
option.text = index + 1;
option.value = index + 1;
var volumeDropdown = document.getElementById("chapterDropdown");
volumeDropdown.appendChild(option);
};
obj.xmlDoc = doc;
callback(obj);
})
})
});
},
initializeXML: function (doc, obj) {
console.log("WE ARE IN INITIALIZEXML NOW")
obj.xmlDoc = doc;
},
testXML: function (obj) {
console.log(obj.xmlDoc);
},
});
})();
In summary with all these complicated methods failing, how should I go about doing something as simple as loading an XML file, and then having it available as an object that can be used by other functions, etc.?
Thanks for your help!
PS:
I'm very new to JavaScript and Windows 8 Modern Apps/ WinAPIs.
Previous experience all in Python and Java (where doing this is trivial!).

There are a couple of things going on here that should help you out.
First, there are three different loading events for a PageControl, corresponding to methods in your page class. The ready method (which is the only one the VS project template includes) gets called only at the end of the process, and is thus somewhat late in the process for doing an async file load. It's more appropriate to do this work within the init method, which is called before any elements have been created on the page. (The processed method is called after WinJS.UI.processAll is complete but before the page has been added to the DOM. ready is called after everything is in the DOM.)
Second, your getXMLAsync method looks fine, but your completed handler is declaring another xmlDoc variable and then throwing it away:
this.getXmlAsync().then(function (doc) {
var xmlDoc = doc; //local variable gets discarded
});
The "var xmlDoc" declares a local variable in the handler, but it's discarded as soon as the handler returns. What you need to do is assign this.xmlDoc = doc, but the trick is then making sure that "this" is the object you want it to be rather than the global context, which is the default for an anonymous function. The pattern that people generally use is as follows:
var that = this;
this.getXmlAsync().then(function (doc) {
that.xmlDoc = doc;
});
Of course, it's only after that anonymous handler gets called that the xmlDoc member will be valid. That is, if you put a console.log at the end of the code above, after the });, the handler won't have been called yet from the async thread, so xmlDoc won't get be valid. If you put it inside the handler immediately after that.xmlDoc = doc, then it should be valid.
This is all just about getting used to how async works. :)
Now to simplify matters for you a little, there is the static method StorageFile.getFileFromApplicationUriAsync which you can use to get directly to in-package file with a single call, rather than navigating folders. With this you can load create the XmlDocument as follows:
getXmlAsync: function () {
return StorageFile.getFileFromApplicationUriAsync("ms-appx:///books/book.xml").then((function (file) {
return Windows.Data.Xml.Dom.XmlDocument.loadFromFileAsync(file);
}).then(function (xmlDoc) {
return xmlDoc;
});
}
Note that the three /// are necessary; ms-appx:/// is a URI scheme that goes to the app package contents.
Also notice how the promises are chained instead of nested. That's typically a better structure, and one that allows a function like this to return a promise that will be fulfilled with the last return value in the chain. This can then be used with the earlier bit of code that assigns that.xmlDoc, and you avoid passing in obj and a callback (promises are intended to avoid such callbacks).
Overall, if you have any other pages in your app to which you'll navigate, you'll really want to load this XML file and create the XmlDocument once for the app, not with the specific page. Otherwise you'd be reloading the file every time you navigate to the page. For this reason, you could choose to do the loading on app startup, not page load, and use WinJS.Namespace.define to create a namespace variable in which you store the xmlDoc. Because that code would load on startup while the splash screen is visible, everything should be ready when the first page comes up. Something to think about.
In any case, given that you're new to this space, I suggest you download my free ebook, Programming Windows Store Apps with HTML, CSS, and JavaScript, 2nd Edition, where Chapter 3 has all the details about app startup, page controls, and promises (after the broader introductions of Chapters 1 and 2 of course).

Related

call and read external JS file - Angular

I have an external (on a server) JS file I am calling and need to read.
This is for Captcha use.
I am having an issue since the TlvJs object is undefined while calling the JS file.
When debugging, I have noticed that the $(document).ready is being executed before the TlvJS was actually declared.
When using the files locally (keeping them in assets folder), first, the TlvJS is being declared and just then the $(document).ready.
How can I make the TlvJS object declared first, even when the file is calling externally?
Please note, I can't control the order of the objects inside this JS file.
$(document).ready(function () {
//select all controls
var elements = document.querySelectorAll('div[tjs-control]');
//iterate thru all found controls
for (var i = 0; i < elements.length; i++) {
var elm = elements[i];
switch ($(elm).attr('js-control')) {
//Captcha control
case "TlvJs.UI.Captcha":
var cap = TlvJs.UI.Captcha($(elm).attr('id'));
var options = $(elm).attr('js-options');
setInstanceProps(options, cap);
cap.url = SetClientProtocol(cap.url);
cap.initCaptcha();
$.prototype.Captcha = cap;
break;
}
}
});
var TlvJs = {
UI: {
Captcha: function (tagId) {
var cap;
cap = Captcha(tagId);
return cap;
},
FileUploader: function (options) {
return FileUploader(options);
}
},
Utils: {
},
Navigation: {
}
};
Currently, I am adding the JS files manually inside a .ts file since when adding the Js files inside the index.html the elm element in the JS file is undefined. That way, the Html page wasn't actually loaded yet.
The first way I have tried (with index.html) which cause the "unknown" elm element:
<script src="http://xxx/Services/CaptchaServicesDistributed/Scripts/TlvJs-Captcha.js"></script>
<script src="http://xxx/Services/CaptchaServicesDistributed/Scripts/TlvBaseJs.js"></script>
The second (and current) way is :
let tlvBaseScript = document.createElement("script");
tlvBaseScript.defer = true;
tlvBaseScript.src = this._configService.getTlvBaseScriptUrl();
tlvBaseScript.type = "text/javascript";
document.getElementsByTagName("head")[0].appendChild(tlvBaseScript);

passing parameters to a functionX from functionY running in a loop based on link clicked

function loadGroups() {
new Ajax.Request("https://www.xyz.com/groups.json", {
method: 'get',
onSuccess : function(transport) {
var response = JSON.parse(transport.responseText);
for (var i=0; i<response.length; i++) {
var hostname = response[i];
var tr = new Element("tr", { id: hostname });
var link = new Element("a");
link.setAttribute("href", id=hostname);
link.innerHTML = hostname;
# PROBLEM
# This onClick always sends response[-1] instead of response[i]
link.onclick = function() { loadHosts(hostname); return false; };
var td1 = new Element("td", { className: hostname });
link.update(hostname);
td1.appendChild(link);
tr.appendChild(td1);
table.appendChild(tr);
}
}
});
}
response = ['john', 'carl', 'jia', 'alex']
My goal is in this case 4 links should be displayed on the page and whenever a link is clicked the corresponding value should be passed to function - loadHosts. But the problem is always the last value gets sent as parameter to loadHosts function. The display of links is fine it is just the click on these links passing always the last element of array. I also tried loadHosts(link.href) , loadHosts(link.id)
Your problem is with the way closures work, you have a click handler inside a for loop that is using a variable defined inside the for loop. By the time the click handler runs, your variable has a different value than when you attached the handler because the loop has finished and it now has a different value.
Try something like this:
for (var i=0; i<response.length; i++) {
var hostname = response[i];
//...
link.onclick = (function(hn) {
return function() { loadHosts(hn); return false; };
})(hostname);
}
This uses a immediately invoked function expression (IIFE) to copy the value of hostname to the a new variable hn during the loop. Now when the handler is executed, it will be bound to the correct value.
Here's a blog post that explains the problem (and solution).
Also note that for loops don't define a variable scope. Variables defined in your for loop belong to the enclosing function scope. So hostname exists outside of your for loop which is why it holds the value of the last cycle through the loop in your click handler rather than the value when you attached the handler. It also explains why link.href doesn't work either. The variable link is attached to the enclosing function scope too rather than limited to the loop.
you should really go with the solution of #MattBurland but if you like, you could also tie the variable to the object itself.
link.hostname = response[i];
link.onclick = function() { loadHosts(this.hostname); return false; };
see simple example here: http://jsfiddle.net/xeyqs/

Accessing an object's parent

Ok, first up I know an object has no reference to it's container unless explicitly defined, so I am looking for a work around here.
Take the following code (heavily simplified from my use case for readability):
var cid = 0;
var Command = function(c) {
this.id = cid += 1;
this.transient = false;
return this;
}
var sid = 0;
var CommandSet = function() {
this.id = sid += 1;
this.commands = [];
this.transients = 0;
return this;
}
CommandSet.prototype.parent = null;
CommandSet.prototype.recurse = function(callback) {
callback.call(this);
if (this.parent instanceof CommandSet) {
this.parent.recurse(callback);
}
}
CommandSet.prototype.createSubset = function() {
var set = new CommandSet();
set.parent = this;
set.commands = this.commands;
set.transients = this.transients;
return set;
}
CommandSet.prototype.addCommand = function(c) {
if (c instanceof Command) {
this.commands.push(c);
if (c.transient) {
this.recurse(function() {
this.transients++;
});
}
}
return this;
}
CommandSet.prototype.toggleTransient = function(c) {
if (c instanceof Command) {
c.transient = true;
this.recurse(function() {
this.transients++;
});
}
return this;
}
If I then do the following (http://jsfiddle.net/5KGd8/1/):
var s1 = new CommandSet();
var c1 = new Command();
var c2 = new Command();
s1.addCommand(c1).addCommand(c2);
var s2 = s1.createSubset();
var s3 = s1.createSubset();
s2.toggleTransient(c1);
console.log(s1);
console.log(s2);
console.log(s3);
s1 now has 1 transient, s2 now has 1 transient but s3 still has none despite containing a reference to the same Command objects.
Possible solutions:
I could build a reference into each command which stores all the
sets it is located inside and iterate through those, however this is
going to cause some serious memory issues as the real nature of my
application requires that subsets can be garbage collected (The user
will create a lot of them anonymously often without realising) and this will retain a
reference to them after they have been used. The parent reference is fine as I want the parent set to exist as long as it has a surviving subset.
I could explicitly force the user to run a delete function on a
subset when it is no longer needed which would remove all internal references to it but this complicates things for
them and I like things to work automagically. The nature of my application means I would like the user to create subsets at times where they may not even realise they have done so (Through other functions which create and perform on subsets).
Can anyone think of a way to solve this problem without the issues described in my two solutions?
Sorry, this is not an answer but want to make sure I understand the problem.
A CommandSet can have Commands, when you change a Command's transient property you would like the CommandSet(s) that contain that Command to have an updated counter of transient the Commands it contains.
If the story ends here you could simply have Command maintain a list of CommandSet that the Command is in and update it's containers.
This would not work however because you would have CommandSets created in a function and when these go out of scope they won't be garbage collected because the Command(s) they contain would hold a reference to them. These commands would not go out of scope with the CommandSets because they are also contained in other (global) CommandSets.
Re assigning a primitive type (transients) does not re assign that in the subset or main set, but what if transients was not a primitive?
In the constructor:
this.transients = {count:0};
In createSubset
set.transients = this.transients
In the toggleTransient
this.transients.count++; or --
No matter if you fiddle with transients in subset or main set, as long as you use the toggleTransient it'll change count for all.

Trouble with my javascript function, I think with document.getElementById('vodObj').innerHTML

I am trying to write a JavaScript function that will update the labels and attributes of my CSS menu. The CSS menu I create dynamically with PHP and a database, and I want to update the CSS menu so the top item is the currently selected one, and the currently selected one does not appear in the list below it. Now that you know what I am trying to accomplish, here is my code:
var vodName = Array();
var vodAddress = Array();
var vodDate = Array();
function switchVod(vodID) {
alert("switchVod ran");
var x = document.getElementById("vod1");
var y = x.getElementsByTagName("span");
y[0].innerHTML = vodName[vodID];
for (var i = 0; i < vodName.length; i++) {
if (i != vodID) {
var gameNum = i + 2;
var gameID = "vod" + gameNum;
var x = document.getElementByID(gameID);
var y = x.getElementsByTagName("span");
y[0].innerHTML = vodName[i]
x.onclick = function () {
switchVod(id);
}
}
}
alert("after for loop");
alert("1"); //works
document.getElementById('vodObj').innerHTML = 'some string';
alert("2"); //doesn't work
document.getElementById("vodDate").innerHTML = " some string ";
alert("finished"); //doesn't work
}
Deeper in the webpage, after getting my information from the database and storing the strings I need in the vodName, vodAddress, and vodDate arrays, and creating the CSS menu and <div id="vodObj"> and <div id="vodDate">, I initialize the page by calling
window.onload = switchVod(0);
It wasn't doing what I hoped, so I added some alert() calls to see how far into the function it was going before failing. alert("after for loop") worked, as did alert("1"). But, alert("2") does not pop up, and neither does alert("finished"), so I think the problem is with document.getElementById('vodObj').innerHTML = 'some string';.
Any ideas of what I could be doing wrong?
window.onload = switchVod(0);
executes switchVod and assigns the return value to window.onload. So it is very likely that the elements you are trying to access (#vodObj in particular) are not loaded yet.
You have to assign a function to window.onload:
window.onload = function() {
switchVod(0);
};
See also Why does jQuery or a DOM method such as getElementById not find the element?
There is an other problem which will encounter eventually:
x.onclick = function () {
switchVod(id);
}
You never defined id anywhere, and if you define it inside the loop, you will run into closure issues. See JavaScript closure inside loops – simple practical example for a solution.
y[0].innerHTML = vodName[vodID];
At this point vodName is an empty array. Actually throughout all of this, you never provide any values to vodName. Please provide complete document.

Javascript function objects

I edited the question so it would make more sense.
I have a function that needs a couple arguments - let's call it fc(). I am passing that function as an argument through other functions (lets call them fa() and fb()). Each of the functions that fc() passes through add an argument to fc(). How do I pass fc() to each function without having to pass fc()'s arguments separately? Below is how I want it to work.
function fa(fc){
fc.myvar=something
fb(fc)
}
function fb(fc){
fc.myothervar=something
fc()
}
function fc(){
doessomething with myvar and myothervar
}
Below is how I do it now. As I add arguments, it's getting confusing because I have to add them to preceding function(s) as well. fb() and fc() get used elsewhere and I am loosing some flexibility.
function fa(fc){
myvar=something
fb(fc,myvar)
}
function fb(fc,myvar){
myothervar=something
fc(myvar,myothervar)
}
function fc(myvar,myothervar){
doessomething with myvar and myothervar
}
Thanks for your help
Edit 3 - The code
I updated my code using JimmyP's solution. I'd be interested in Jason Bunting's non-hack solution. Remember that each of these functions are also called from other functions and events.
From the HTML page
<input type="text" class="right" dynamicSelect="../selectLists/otherchargetype.aspx,null,calcSalesTax"/>
Set event handlers when section is loaded
function setDynamicSelectElements(oSet) {
/**************************************************************************************
* Sets the event handlers for inputs with dynamic selects
**************************************************************************************/
if (oSet.dynamicSelect) {
var ySelectArgs = oSet.dynamicSelect.split(',');
with (oSet) {
onkeyup = function() { findListItem(this); };
onclick = function() { selectList(ySelectArgs[0], ySelectArgs[1], ySelectArgs[2]) }
}
}
}
onclick event builds list
function selectList(sListName, sQuery, fnFollowing) {
/**************************************************************************************
* Build a dynamic select list and set each of the events for the table elements
**************************************************************************************/
if (fnFollowing) {
fnFollowing = eval(fnFollowing)//sent text function name, eval to a function
configureSelectList.clickEvent = fnFollowing
}
var oDiv = setDiv(sListName, sQuery, 'dynamicSelect', configureSelectList); //create the div in the right place
var oSelected = event.srcElement;
if (oSelected.value) findListItem(oSelected)//highlight the selected item
}
Create the list
function setDiv(sPageName, sQuery, sClassName, fnBeforeAppend) {
/**************************************************************************************
* Creates a div and places a page in it.
**************************************************************************************/
var oSelected = event.srcElement;
var sCursor = oSelected.style.cursor; //remember this for later
var coords = getElementCoords(oSelected);
var iBorder = makeNumeric(getStyle(oSelected, 'border-width'))
var oParent = oSelected.parentNode
if (!oParent.id) oParent.id = sAutoGenIdPrefix + randomNumber()//create an ID
var oDiv = document.getElementById(oParent.id + sWindowIdSuffix)//see if the div already exists
if (!oDiv) {//if not create it and set an id we can use to find it later
oDiv = document.createElement('DIV')
oDiv.id = oParent.id + sWindowIdSuffix//give the child an id so we can reference it later
oSelected.style.cursor = 'wait'//until the thing is loaded
oDiv.className = sClassName
oDiv.style.pixelLeft = coords.x + (iBorder * 2)
oDiv.style.pixelTop = (coords.y + coords.h + (iBorder * 2))
XmlHttpPage(sPageName, oDiv, sQuery)
if (fnBeforeAppend) {
fnBeforeAppend(oDiv)
}
oParent.appendChild(oDiv)
oSelected.style.cursor = ''//until the thing is loaded//once it's loaded, set the cursor back
oDiv.style.cursor = ''
}
return oDiv;
}
Position and size the list
function configureSelectList(oDiv, fnOnClick) {
/**************************************************************************************
* Build a dynamic select list and set each of the events for the table elements
* Created in one place and moved to another so that sizing based on the cell width can
* occur without being affected by stylesheet cascades
**************************************************************************************/
if(!fnOnClick) fnOnClick=configureSelectList.clickEvent
if (!oDiv) oDiv = configureSelectList.Container;
var oTable = getDecendant('TABLE', oDiv)
document.getElementsByTagName('TABLE')[0].rows[0].cells[0].appendChild(oDiv)//append to the doc so we are style free, then move it later
if (oTable) {
for (iRow = 0; iRow < oTable.rows.length; iRow++) {
var oRow = oTable.rows[iRow]
oRow.onmouseover = function() { highlightSelection(this) };
oRow.onmouseout = function() { highlightSelection(this) };
oRow.style.cursor = 'hand';
oRow.onclick = function() { closeSelectList(0); fnOnClick ? fnOnClick() : null };
oRow.cells[0].style.whiteSpace = 'nowrap'
}
} else {
//show some kind of error
}
oDiv.style.width = (oTable.offsetWidth + 20) + "px"; //no horiz scroll bars please
oTable.mouseout = function() { closeSelectList(500) };
if (oDiv.firstChild.offsetHeight < oDiv.offsetHeight) oDiv.style.height = oDiv.firstChild.offsetHeight//make sure the list is not too big for a few of items
}
Okay, so - where to start? :) Here is the partial function to begin with, you will need this (now and in the future, if you spend a lot of time hacking JavaScript):
function partial(func /*, 0..n args */) {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
var allArguments = args.concat(Array.prototype.slice.call(arguments));
return func.apply(this, allArguments);
};
}
I see a lot of things about your code that make me cringe, but since I don't have time to really critique it, and you didn't ask for it, I will suggest the following if you want to rid yourself of the hack you are currently using, and a few other things:
The setDynamicSelectElements() function
In this function, you can change this line:
onclick = function() { selectList(ySelectArgs[0], ySelectArgs[1], ySelectArgs[2]) }
To this:
onclick = function() { selectList.apply(null, ySelectArgs); }
The selectList() function
In this function, you can get rid of this code where you are using eval - don't ever use eval unless you have a good reason to do so, it is very risky (go read up on it):
if (fnFollowing) {
fnFollowing = eval(fnFollowing)
configureSelectList.clickEvent = fnFollowing
}
And use this instead:
if(fnFollowing) {
fnFollowing = window[fnFollowing]; //this will find the function in the global scope
}
Then, change this line:
var oDiv = setDiv(sListName, sQuery, 'dynamicSelect', configureSelectList);
To this:
var oDiv = setDiv(sListName, sQuery, 'dynamicSelect', partial(configureSelectListAlternate, fnFollowing));
Now, in that code I provided, I have "configureSelectListAlternate" - that is a function that is the same as "configureSelectList" but has the parameters in the reverse order - if you can reverse the order of the parameters to "configureSelectList" instead, do that, otherwise here is my version:
function configureSelectListAlternate(fnOnClick, oDiv) {
configureSelectList(oDiv, fnOnClick);
}
The configureSelectList() function
In this function, you can eliminate this line:
if(!fnOnClick) fnOnClick=configureSelectList.clickEvent
That isn't needed any longer. Now, I see something I don't understand:
if (!oDiv) oDiv = configureSelectList.Container;
I didn't see you hook that Container property on in any of the other code. Unless you need this line, you should be able to get rid of it.
The setDiv() function can stay the same.
Not too exciting, but you get the idea - your code really could use some cleanup - are you avoiding the use of a library like jQuery or MochiKit for a good reason? It would make your life a lot easier...
A function's properties are not available as variables in the local scope. You must access them as properties. So, within 'fc' you could access 'myvar' in one of two ways:
// #1
arguments.callee.myvar;
// #2
fc.myvar;
Either's fine...
Try inheritance - by passing your whatever object as an argument, you gain access to whatever variables inside, like:
function Obj (iString) { // Base object
this.string = iString;
}
var myObj = new Obj ("text");
function InheritedObj (objInstance) { // Object with Obj vars
this.subObj = objInstance;
}
var myInheritedObj = new InheritedObj (myObj);
var myVar = myInheritedObj.subObj.string;
document.write (myVar);
subObj will take the form of myObj, so you can access the variables inside.
Maybe you are looking for Partial Function Application, or possibly currying?
Here is a quote from a blog post on the difference:
Where partial application takes a function and from it builds a function which takes fewer arguments, currying builds functions which take multiple arguments by composition of functions which each take a single argument.
If possible, it would help us help you if you could simplify your example and/or provide actual JS code instead of pseudocode.

Categories