There may be a better way of doing this...so please suggest if there is.
I've got some javascript that calls an AIR function. This AIR functions creates a new HTML element and adds it to the "Stage" like so:
// guid is the ID given to the new window (HTML element) by javascript
private function createNewWindow(guid:String):void {
var frame:HTML = new HTML();
frame.id = guid;
addElement(frame);
}
Now I've also got a function that sets the location of the frame based on its id...this is where I'm struggling.
// set the location of the window referenced by it's id (guid)
private function setLocation(guid:String, location:String):void {
// psuedocode. Obviously it won't work.
stage.getById(guid).location = location;
}
So, how do I "get" my HTML element based on its ID?
Short answer, you don't. This isn't javascript, this is a OO language and as such, you need to change your thought process. What are you trying to do? Create several html windows within an air application? If you want to have an id based approach, you're going to need to store the id and the pointer to the component in an data structure (like a dictionary).
private var _components:Dictionary = new Dictionary();
this._components['someId'] = someComponent;
And from there you can add a function that just saves/returns the components. I'm not entirely sure what's your approach and what you're trying to accomplish, but my gut tells me you're not doing something right.
Related
I need to add an overlay to an existing OpenSeadragon viewer object which isn't created by my code, but elsewhere in the application.
I have got to a point where I know that the viewer has been created as I can access the various html elements that are created via jQuery. However I can't work out if there's any way to create a viewer from an existing reference.
I've tried using the id of the viewer div in:
var viewer = OpenSeadragon(id: "open-seadragon-viewer-id");
but this doesn't seem to work.
Is there any way to do this or can you only get the viewer within the code that initialised it?
Here's one crazy thought... you could monkey-patch some portion of OSD in order to grab the viewer...
var viewer;
var originalIsOpen = OpenSeadragon.Viewer.prototype.isOpen;
OpenSeadragon.Viewer.prototype.isOpen = function() {
// Now we know the viewer!
viewer = this;
// Reinstate the original, since we only need to run our version once
OpenSeadragon.Viewer.prototype.isOpen = originalIsOpen;
// Call the original
return originalIsOpen.call(this);
}
It's kind of tacky, but should work. Note this assumes there is only one viewer on the page... if there are more than one, the same principle could work but you would need to keep track of an array of viewers.
BTW, I'm using isOpen, because it's simple and it gets called every frame. Other functions could work as well.
EDIT: fixed code so we are using the prototype. I still haven't actually tested this code so there may still be bugs!
This solution does not directly answer the question, as it relies on your own code creating the OpenSeaDragon object. It is an implementation of #iangilman's mention of storing the viewer in a global variable. However others may find it useful. (Note that passing a global variable to a function requires a workaround - see Passing a global variable to a function)
The code demonstrates how to use the same OpenSeaDragon object to display different pictures.
var viewer3=null; //global variable
var newURL1='image/imageToDisplay1.png';
var newURL2='image/imageToDisplay2.png';
var elementID='myID';
//the loadScan function will display the picture using openSeaDragon and can be called as many times as you want.
loadScan("viewer3",newURL1,elementID);
loadScan("viewer3",newURL2,elementID);
//the actual function
function loadScan(theViewer,newURL,theID) {
//if object has already been created, then just change the image
if (window[theViewer]!=null) {
window[theViewer].open({
type: 'image',
url: newURL
});
} else {
//create a new OpenSeadragon object
window[theViewer] = OpenSeadragon({
prefixUrl: "/myapp/vendor/openseadragon/images/",
id: theID,
defaultZoomLevel: 1,
tileSources: {
url: newURL,
type: 'image'
}
});
}
}
I am working on a project that is being built around SignalR then JavaScript appending the data to elements.
$("#" + div).html(html);
The problem I am having is that I am calling the server every 2 seconds
$.connection.hub.start().done(function () {
chat.server.send("0", 1);
setInterval(function () {
chat.server.send("0", 1);
}, 2000);
});
This means it's then updating every div, every time the server returns the data, I have been looking for a way to get JavaScript to handle only updating elements if the data returned has changed, there were two ways I was going to go about doing this.
Get the HTML content from the div and do a comparison, however that was flawed because different browsers return different HTML, so that's a no
The second way was to store the content in a global variable and when it runs again, compare the global against the current, if it's different update
However I am looking at possibly something built into JavaScript which could handle this for me, currently I am using .html but when looking into this more, I found out that it first does .empty() and re-appended the data and I'm looking for something that'll only update if it's different.
-- EDIT --
How the project is currently setup is that I have a class containing different properties of what needs to be displayed, e.g.
public class MyClass {
public List<DivOneContent> Content1;
public List<DivTwoContent> Content2;
}
On the server side I have it fetch the content and populate the class
public void Send(string tab, string subTab = null)
{
MyClass data = PrepareModel(tab, subTab);
Clients.Client(Context.ConnectionId).broadcastObject(data);
}
When this is this is turned back to the client side, I have JavaScript functions which take one of the properties and appends that as needed
// First param is the content and the second one is the div ID
devious.htmlStringBuilder.buildContentOne(data.Content1, "Content1");
In the function I just loop and build a string and append such string to the div using .html
I have an <a> tag which I'm using to redirect the user to another xpage.
Its href property is:
<a target="_blank" href="http://serv/MyBase.nsf">
I use a simple view listing a doc. which contains the server and the name of the application.
So, I want to use some #DbLookup function in javascript to get into 2 var the above server and app name:
var server = #Unique(#DbColumn(#DbName(), "myVw", 1);
var name = #Unique(#DbColumn(#DbName(), "myVw", 2);
var concat = server+"/"+name;
return concat;
How can I compute the href property to return the concat variable?
Create a Link control xp:link and calculate the URL in attribute value:
<xp:this.value><![CDATA[#{javascript:var server .... }]]></xp:this.value>
Knut's approach is correct, but your code isn't :-). For every XPages load (or refresh) you do 4 #DbLookup. You can do a set of optimisations here:
Combine the result you want in the view itself, so you only need one lookup
Cache the value in the session (or application scope)
something like this (add nice error handling):
if (sessionScope.myHref) {
// Actually do nothing here
} else {
sessionScope.myHref = #Unique(#DbColumn(#DbName(), "myVw", 3);
}
return sessionScope.myHref;
The 3rd column would have the concatenation in the view already. That little snippet does a lookup only once per session. If it is the same for all users, use the applicationScope then it is even less.
Is it possible to instantiate an element on Mootools based on the automatic UID that mootools create?
EDIT: To give more info on what is going. I'm using https://github.com/browserstate/history.js to make a history within an ajax page. When I add a DOM element to it (which does not have an id), at some point it passes through a JSON.toString methods and what I have of the element now is just the uid.
I need to recreate the element based on this UID, how could I go about doing that? Do I need to first add it to the global storage to retrieve later? If so, how?
in view of edited question:
sorry, I fail to understand what you are doing.
you have an element. at some point the element is turned into an object that gets serialised (all of it? prototypes etc?). you then take that data and convert to an object again but want to preserve the uid? why?
I don't understand how the uid matters much here...
Using global browser storage also serialises to string so that won't help much. Are we talking survival of page loads here or just attach/detach/overwrite elements? If the latter, this can work with some tweaking.
(function() {
var Storage = {};
Element.implement({
saveElement: function() {
var uid = document.id(this).uid;
Storage[uid] = this;
return this;
}
});
this.restoreElement = function(uid) {
return Storage[uid] || null;
}
})();
var foo = document.id("foo"), uid = foo.uid;
console.log(uid);
foo.saveElement().addEvent("mouseenter", function() { alert("hi"); } );
document.id("container").set("html", "");
setTimeout(function() {
var newElement = restoreElement(uid);
if (newElement)
newElement.inject(document.body);
console.log(newElement.uid);
}, 2000);
http://jsfiddle.net/dimitar/7mwmu/1/
this will allow you to remove an element and restore it later.
keep in mind that i do container.set("html", ""); which is not a great practice.
if you do .empty(), it will GC the foo and it will wipe it's storage so the event won't survive. same for foo.destroy() - you can 'visually' restore the element but nothing linked to it will work (events or fx).
you can get around that by using event delegation, however.
also, you may want to store parent node etc so you can put it back to its previous place.
I have asp.net web application.where i am creating the User as registration for a particular Firm.In this firm there are 3 type of user as of now. as Admin, Dealer, Manager. so according to this I am changing the UI page.
Means When Admin (Admin is default entry) going create let say Dealer, then there is different UI except General information fields (like name ,contact details and all). and when creating the manager there is different UI fields, except than General information fields.
To reuse the page i am using this way , when selected Manager then related his UI fields get only visible, same for dealer. obviously there is a dropdown control from where i am selecting User type.
But some how , later on if one more User type get added by firm, I need to generate functionality according to New User type. how can i handle if I don not want to change existing code. sense is how can i write the generic code so that I should not need to change in code behind or in javascript again.
Where as all this things are in planning and under implementation for now. but before to go a head I must clear this thing. I am planning to change the UI structure in javascript as usual way , i means
if selected User Type is "Dealer then make visible these div's ELSE If User Type is Manager then make visible these divs
I want to write generic javacript , though new user type get added.
You could maintain the field <-> user type relation in a database and dynamically add labels and textboxes in the PageLoad of your Page.
Then when a new type of user comes along you'd simply need to add to your data.
Your user type should also be in a database.
Of course, the code that lets your users create other users would also have to be flexible enough. So you'd need a CanCreate table that dictates who can create what type of user. :)
EDIT Expanded how to build your Content
Actually, I like your idea about storing the html elements in the database. That'd save you using reflection to dynamically get the propertyvalue. However, I don't think you'll be able to use databinding and all that.
So instead I'd do something like this:
public enum ControlType
{
Label,
TextBox,
...
}
Make a table something like
UserType
PropertyName
PropertyLabelName
FieldLabelType (int)
FieldContentType (int)
Then on pageload you get the UserType, pull the data from the table, find the div where you want to put the data and then add the controls like:
(pseudocode)
Control label = null;
switch (FieldLabelType)
{
case ControlType.Label:
var label = new Label()
{
.. all kinds of properties
Text = PropertyLabelName
};
control = label;
break;
case ???
...
}
if (label != null)
fielddiv.Add(label);
Control field = null;
switch (FieldContentType)
{
case ControlType.TextBox:
var textbox = new TextBox()
{
.. all kinds of properties
Text = new Binding( ... Path = PropertyName)
};
control = textbox;
break;
case ???
}
if (field != null)
fielddiv.Add(field);
Of course, you'd need to do some positioning to get it all looking pretty. Perhaps chuck in a table or something in code?