Adobe AIR application remember and set window state in JavaScript - javascript

I have a single window AIR application created with FlashDevelop and would like it to remember the size and position of the window when the user closes it. When it re opens it would resize and go to that position.
Found an AS3 script that will do that but my application has no AS3. There is only an html and js file.
When the window is closed it should save the state of the window and when it's opened it should load the saved state and resize/move to the saved state. Here is what I have on $(document).ready
var width = screen.width;
var height = screen.height;
var p=new DOMParser();
var xml,x,y,windowWidth,windowHeight;
var f = window.runtime.flash.filesystem.File
.applicationDirectory.resolvePath("appPosition.xml");
if (f.exists){
var s = new window.runtime.flash.filesystem.FileStream();
try {
s.open(f,window.runtime.flash.filesystem.FileMode.READ);
xml=p.parseFromString(s.readUTFBytes(s.bytesAvailable),"text/xml");
x = parseInt(xml.childNodes[0].getAttribute("x"),10);
y = parseInt(xml.childNodes[0].getAttribute("y"),10);
windowWidth = parseInt(xml.childNodes[0].getAttribute("width"),10);
windowHeight =
parseInt(xml.childNodes[0].getAttribute("height"),10);
x = (x >= width) ? 20 : x;
y = (y >= height) ? 0 : y;
x = (x <= (width*-1)) ? 20 : x;
y = (y <= (height*-1)) ? 0 : y;
if (windowWidth >= (width-60) && windowHeight >= (height-60)) {
//the x and y are not set
window.runtime.flash.display.NativeWindow.x =20;
window.runtime.flash.display.NativeWindow.y = 0;
window.resizeTo(900,600);
// not yet sure if the following works
window.runtime.flash.display.NativeWindow.maximize();
}else{
// x and y don't do anything here either
window.runtime.flash.display.NativeWindow.x = x;
window.runtime.trace("sitting window x:",x);
window.runtime.flash.display.NativeWindow.y = y;
window.resizeTo(windowWidth,windowHeight);
}
}catch (e) {
window.runtime.trace(e.message);
}finally{
s.close();
}
return;
When the window is closed I want my function to save the state of the window but whatever I try the function is never called: $(window).on("close"... or window.onclose= or <document onunluoad=... The lengthy guide doesn't seem to have anything on how to get the current window:
http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/scripting/pdfs/javascript_tools_guide.pdf
Creating windows is covered and once having it you can manipulate it but I never create a window, the application.xml looks like this:
...
<initialWindow>
<title>App Title</title>
<content>main.html</content>
...
So I have the following questions:
How do I add event listeners to the current window?
How do I set current window x and y when it loads?
Can I size and move the window before it is visible as right now it
seems to resize but looks kind of flaky as it opens initially at
default size and then reiszes to the previously stored values.

Solved it using window.nativeWindow (note the lower case n of nativeWindow, it's upper case in AS3). Here is the code:
$(document).ready(function(){
var width = screen.width;
var height = screen.height;
var p=new DOMParser();
var xml,x,y,windowWidth,windowHeight;
var f = window.runtime.flash.filesystem.File
.applicationDirectory.resolvePath("appPosition.xml");
if (f.exists){
var s = new window.runtime.flash.filesystem.FileStream();
try {
s.open(f,window.runtime.flash.filesystem.FileMode.READ);
xml=p.parseFromString(s.readUTFBytes(s.bytesAvailable),"text/xml");
x = parseInt(xml.childNodes[0].getAttribute("x"),10);
y = parseInt(xml.childNodes[0].getAttribute("y"),10);
windowWidth = parseInt(xml.childNodes[0]
.getAttribute("width"),10);
windowHeight = parseInt(xml.childNodes[0]
.getAttribute("height"),10);
x = (x >= width) ? 20 : x;
y = (y >= height) ? 0 : y;
x = (x <= (width*-1)) ? 20 : x;
y = (y <= (height*-1)) ? 0 : y;
if (windowWidth >= (width-60) && windowHeight >= (height-60)) {
window.nativeWindow.x =20;
window.nativeWindow.y = 0;
window.resizeTo(866,600);
window.nativeWindow.height = height-60;
window.nativeWindow.maximize();
}else{
window.nativeWindow.x = x;
window.nativeWindow.y = y;
window.resizeTo(windowWidth,windowHeight);
}
}catch (e) {
window.runtime.trace(e.message);
}finally{
s.close();
window.nativeWindow.visible=true;
}
return;
}
try{
window.nativeWindow.x = 20;
window.nativeWindow.y = 0;
window.nativeWindow.width = 866;
window.nativeWindow.height = height-60;
window.nativeWindow.visible=true;
}catch(e){
window.runtime.trace(e.message);
}
window.nativeWindow.addEventListener
(window.runtime.flash.events.Event.CLOSING, function(e){
var xml = '<position x="'+window.nativeWindow.x
+'" y="'+window.nativeWindow.y+'" width="'
+ window.nativeWindow.width + '" height="'
+ window.nativeWindow.height + '"/>';
var f = window.runtime.flash.filesystem.File.
applicationDirectory.resolvePath("appPosition.xml");
f = new window.runtime.flash.filesystem.File(f.nativePath);
var s = new window.runtime.flash.filesystem.FileStream();
try{
s.open(f,window.runtime.flash.filesystem.FileMode.WRITE);
s.writeUTFBytes(xml);
}catch (e){
window.runtime.trace(e.message);
}finally{
s.close();
}
});
});
In the application.xml:
<initialWindow>
<title>app title</title>
<content>main.html</content>
<systemChrome>standard</systemChrome>
<transparent>false</transparent>
<visible>false</visible>
Setting visible false makes it smoothly appear in the last position the user closed it.

Related

How to prevent randomly generated images from overlapping using Javascript

I'm trying to spawn randomly generated targets on the screen using a function to copy an invisible image of the target to be spawned at a random place within the screen using window object properties.
For this to happen I think the image have to have position set to absolute, but then several images may be spawned in a way that they will overlap, how can I prevent this from happening?
The div element where I copy my first image and also store the other copies.
<div id="targetsDiv">
<img src="target2.png" alt="target_shot" class="target" />
</div>
Inside the script:
var x_pixels = window.innerWidth - 180;
var y_pixels = window.innerHeight - 180;
var x_midScreen = window.innerWidth / 2;
var y_midScreen = window.innerHeight / 2;
var xRandom = Math.floor(Math.random()*x_pixels) +1;
var yRandom = Math.floor(Math.random()*y_pixels) +1;
var targetCollection = document.getElementById("targetsDiv");
var targetCopy = targetCollection.innerHTML
var targetList = document.getElementsByClassName("target");
targetList[0].style.display = "none";
var targetNr = 1;
var numberOfSpawns = 3;
function spawnTargets () {
while (targetNr <= numberOfSpawns) {
if ((xRandom < x_midScreen - 126 || xRandom > x_midScreen + 26) || (yRandom < y_midScreen - 126 || yRandom > y_midScreen + 26)) {
targetCollection.innerHTML += targetCopy;
targetList[targetNr].style.left = xRandom + "px";
targetList[targetNr].style.top = yRandom + "px";
targetNr++;
}
xRandom = Math.floor(Math.random()*x_pixels) +1;
yRandom = Math.floor(Math.random()*y_pixels) +1;
}
}
PS: I appreciate all help, tips and tweaks that you guys provide:) Thanks for helping
The area you want to exclude in the centre of the screen is rather large, and on my little laptop, there isn't even any room to still show the random positioned images.
But anyway, this piece of code should do the job -- I added some infinite loop protection which on my PC was a life-saver:
HTML (added style attribute)
<div id="targetsDiv">
<img src="target2.png" alt="target_shot" class="target"
style="visibility:hidden"/>
</div>
JavaScript:
window.addEventListener('load', function () {
var targetCollection = document.getElementById("targetsDiv");
var template = document.getElementsByClassName("target")[0];
var targetWidth = template.offsetWidth;
var targetHeight = template.offsetHeight;
var x_pixels = window.innerWidth - targetWidth;
var y_pixels = window.innerHeight - targetHeight;
var x_midScreen = window.innerWidth / 2;
var y_midScreen = window.innerHeight / 2;
function spawnTargets (numberOfSpawns) {
var targets = [];
var count = 0; // infinite recursion protection
for (var i = 0; i < numberOfSpawns; i++) {
do {
do {
var x = Math.floor(Math.random()*x_pixels);
var y = Math.floor(Math.random()*y_pixels);
if (count++ > 200) {
console.log('give up');
return;
}
} while ((x >= x_midScreen-450 && x <= x_midScreen+300) && (y >= y_midScreen-350 || y <= y_midScreen+200));
for (var j = 0; j < i; j++) {
if (x >= targets[j].x - targetWidth && x <= targets[j].x + targetWidth &&
y >= targets[j].y - targetHeight && y <= targets[j].y + targetHeight) break; // not ok!
}
} while (j < i);
targets.push({x, y});
img = document.createElement('img');
img.src = template.src;
img.setAttribute('width', targetWidth + 'px');
img.setAttribute('height', targetHeight + 'px');
img.className = template.className;
targetCollection.appendChild(img);
img.style.left = x + "px";
img.style.top = y + "px";
}
}
spawnTargets(3);
});

Scroll then snap to top not unsnapping

I'm trying to create snap to top divs that cover the entire page and I have it working, it's just that after they snap to the top they don't unsnap and stay fixed to the top. I'm using the answer given by mu is too short from this previous question scroll then snap to top but I can't get it to unsnap.
Here's a jsbin of the code.
var h = 0;
var notif;
var notif2;
var init;
var docked = false;
function getSize() {
h = window.innerHeight;
notif = document.getElementById("notif");
notif2 = document.getElementById("notif2");
var fl = document.getElementById("floater");
init = notif.scrollTop;
notif.style.top = "" + h + "px";
var h2 = h / 2;
fl.style.marginTop = "" + h2 + "px";
notif.style.height = "" + h + "px";
var twoh = 3 * h2;
notif2.style.top = "" + h + "px";
notif2.style.height = "" + h + "px";
}
window.onscroll = function() {
if (!docked && (notif.offsetTop - document.body.scrollTop < 0)) {
console.log("in loop");
notif.style.top = 0;
notif.style.position = 'fixed';
notif2.style.marginTop = "" + h + "px";
docked = true;
} else if (docked && document.body.scrollTop <= init) {
notif.style.position = 'block';
while (notif.style.top <= h) {
var ab = Math.abs(notif.offsetTop)
var ab2 = Math.abs(document.body.scrollTop);
notif.style.top = init + 'px';
}
if (notif.style.top == h || notif.style.top == h - 1) {
docked = false;
}
}
};
<body onload="getSize()">
<div class="contain">
<div id="floater">
<h1 class="white">Hello, World</h1>
Link 1 Link 2
</div>
</div>
<div class="announcements" id="notif">
Please cover the previous text on the page. If this works i will be really excited.
</div>
<div class="announcements2" id="notif2">
Cover the white page.
</div>
</body>
Save the values used before you set these, and reset them when you "un-dock". Simply setting "docked" to show that you're un-docked is not enough.
This code is an example of how to do that from your staring point.
Here's how I saved it and got something like the behaviour you mention
var h = 0;
var notif;
var notif2;
var init;
var docked = false;
// holding space for reset values
var holdNotifyStyleTop;
var holdNotifyOffsetTop;
var holdNotif2StyleMarginTop;
function getSize() {
h = window.innerHeight;
notif = document.getElementById("notif");
notif2 = document.getElementById("notif2");
var fl = document.getElementById("floater");
init = notif.offsetTop;
notif.style.top = ""+h+"px";
var h2 = h/2;
fl.style.marginTop = ""+h2+"px";
notif.style.height = ""+h+"px";
var twoh = 3*h2;
notif2.style.top=""+h+"px";
notif2.style.height = ""+h+"px";
}
window.onscroll = function () {
if (!docked && (notif.offsetTop - document.body.scrollTop < 0)) {
console.log("--- DOCKING ---");
// save current values
holdNotifyStyleTop = notif.style.top;
holdNotifyOffsetTop = notif.offsetTop;
holdNotif2StyleMarginTop = notif2.style.marginTop;
notif.style.top = 0;
notif.style.position = 'fixed';
notif2.style.marginTop=""+h+"px";
docked = true;
} else if (docked && document.body.scrollTop <= init) {
console.log("--- Un-DOCKING ---");
notif.style.top = holdNotifyStyleTop;
notif.style.position = 'relative';
notif2.style.marginTop=holdNotif2StyleMarginTop;
notif.offsetTop = holdNotifyOffsetTop;
docked = false;
}
};

Float DIV is not fixed

I install Float Left Right Advertising plugin on my site: www.displej.me and I set banners at the side of site. But when you scroll baners are not fixed, they follow page but they are refreshing and blinking. Also, when I'm scrolling down they stay fixed aside and later start to follow the page. Ths is JS code:
function FloatTopDiv()
{
startLX = ((document.body.clientWidth -MainContentW)/2) - (LeftBannerW+LeftAdjust) , startLY = TopAdjust;
startRX = ((document.body.clientWidth -MainContentW)/2) + (MainContentW+RightAdjust) , startRY = TopAdjust;
var d = document;
function ml(id)
{
var el=d.getElementById?d.getElementById(id):d.all?d.all[id]:d.layers[id];
el.sP=function(x,y){this.style.left=x + 'px';this.style.top=y + 'px';};
el.x = startRX;
el.y = startRY;
return el;
}
function m2(id)
{
var e2=d.getElementById?d.getElementById(id):d.all?d.all[id]:d.layers[id];
e2.sP=function(x,y){this.style.left=x + 'px';this.style.top=y + 'px';};
e2.x = startLX;
e2.y = startLY;
return e2;
}
window.stayTopLeft=function()
{
if (document.documentElement && document.documentElement.scrollTop)
var pY = document.documentElement.scrollTop;
else if (document.body)
var pY = document.body.scrollTop;
if (document.body.scrollTop > 200){startLY = 3;startRY = 3;} else {startLY = TopAdjust;startRY = TopAdjust;};
ftlObj.y += (pY+startRY-ftlObj.y)/1;
ftlObj.sP(ftlObj.x, ftlObj.y);
ftlObj2.y += (pY+startLY-ftlObj2.y)/1;
ftlObj2.sP(ftlObj2.x, ftlObj2.y);
setTimeout("stayTopLeft()", 1);
}
ftlObj = ml("divAdRight");
//stayTopLeft();
ftlObj2 = m2("divAdLeft");
stayTopLeft();
}
function ShowAdDiv()
{
var objAdDivRight = document.getElementById("divAdRight");
var objAdDivLeft = document.getElementById("divAdLeft");
objAdDivRight.style.display = "block";
objAdDivLeft.style.display = "block";
FloatTopDiv();
}
What to do? I try to change the numbers in the code but not sucsses.
clear:both
is something I would try to keep the sides free from the centered divs movements.

Internet explorer 10 and top.window.pageYOffset

I use window.pageYOffset to find the position of the scroll bar (works fine in firefox), however it is always undefined in IE10
I have tried using:
window.pageYOffset // undefined
document.body.scrollTop // always 0
document.documentElement.scrolltop // undefined
top.window.scrollY // undefined
is this a known issue with IE10?
this is with compatibility mode enabled. Without it, pageYOffset works as expected. We have to use compatibility mode as it's a requirement for our clients
the code displays a calander, which needs to be displayed against a text box. it's position is altered when the user has scrolled on the page:
UPDATED WITH CODE:
function showCalendar(e, datePicker) {
top.calendarReturnFunc = function(value, controlId) {
getDatePicker(controlId).dateBox.hasDate = "True";
dateChosen(value, controlId, true);
};
top.datePickerActive = function() { return true; };
var itop = top.window.screenTop != undefined ? top.window.screenTop : parseInt(top.window.screenY) + parseInt(130);
var ileft = top.window.screenLeft != undefined ? top.window.screenLeft : parseInt(top.window.screenX);
var x = e.screenX - parseInt(ileft);
var y;
if (typeof top.window.pageYOffset === "undefined") {
y = (e.screenY - parseInt(itop) - datePicker.yOffset) + document.documentElement.scrollTop; //IE10?...
}
else {
y = (e.screenY - parseInt(itop) - datePicker.yOffset) + top.window.pageYOffset; //works fine in firefox
}
if (datePicker.alignLeft) {
x -= 180;
}
if (!datePicker.alignBottom) {
y -= 178;
}
_calendar.style.left = x + "px";
_calendar.style.top = y + "px";
_calendar.style.display = "block";
_calendar.datePicker = datePicker;
_calendar.callingFrame = this;
_calendar.src = datePicker.calendarUrl + "&Date=" + escape(datePicker.dateBox.value);
}
You can use document.documentElement.scrollTop for IE. You didn’t capitalise the T in scrollTop in your sample.

loop into js object

i have this js object:
var tags = [{ 'x' : '42','y' : '25','id' : '1', 'linea' : '1'},{ 'x' : '378','y' : '24','id' : '2', 'linea' : '1'}];
i try to loop in this way:
for(var i = 0; i < tags.length; i++){
var x = tags[i].x -10;
var y = tags[i].y -10;
var offsetX = x + 20;
var offsetY = y + 20;
if( left >= x && left <= offsetX ){
$(myDiv).bind('click',function(){
document.location.href = 'x.php?a='+ tags[i].linea +'&b=' + tags[i].id;
}).css('cursor','pointer');
}else{
$(myDiv).unbind('click').css('cursor','none');
}
}
But i loose the first!
Is this the correcy way??
Thanks!
You don't loose the first (sounds like it was a car key). You problem is your anonymous function, that closes over its parent scope when executed( for your .bind() method). It creates, what we call, a Closure.
Its a very common mistake in ECMAscript there. You need to invoke an additional context to avoid this issue.
$(myDiv).bind('click',(function( index ){
return function() {
document.location.href = 'x.php?a='+ tags[index].linea +'&b=' + tags[index].id;
};
}( i ))).css('cursor','pointer');
If you don't do that, all of those anonymous function context will share the same parent context in their scope-chain. Without describing that too much in detail now, it'll end up that all event handlers would reference the same variable i.
Beside that, it looks like you're binding multiple click event handlers to the same element myDIV. Each handler would cause the browser to redirect to another url, so, this will bring trouble. I can't even tell if the first or the last handler will win this race.
Variable scope.. change to this and it should work fine:
var lineA = tags[i].linea;
var id = tags[i].id;
$(myDiv).bind('click',function(){
document.location.href = 'x.php?a='+ lineA +'&b=' + id;
}).css('cursor','pointer');
The problem is with i being the loop iterator, so when you click myDiv it will have the last value always.
Edit: after looking into it, I could see you are taking the wrong approach. What you are after is identifying where the user clicked inside the <div> and redirect to different location according to your array. For this, such code should work:
var tags = [{ 'x' : '42','y' : '25','id' : '1', 'linea' : '1'},{ 'x' : '378','y' : '24','id' : '2', 'linea' : '1'}];
$("#myDiv").bind('click',function(event) {
var left = event.pageX - $(this).position().left;
for(var i = 0; i < tags.length; i++){
var x = tags[i].x -10;
var y = tags[i].y -10;
var offsetX = x + 20;
var offsetY = y + 20;
if( left >= x && left <= offsetX ){
var lineA = tags[i].linea;
var id = tags[i].id;
document.location.href = 'x.php?a='+ lineA +'&b=' + id;
break;
}
}
});
The code should be pretty clear, anyway it's not possible to have only parts of the element with hand cursor - I advise you not to mess too much as it will be really complicated.
Live test case.
Edit 2: Having the "clickable" parts of the element with different cursor is easier than I initially thought, you just have to handle the onmousemove event as well and in there set the cursor:
var posLeft = $("#myDiv").position().left;
$("#myDiv").bind('click',function(event) {
var tag = GetHoveredTag(event);
if (tag) {
var lineA = tag.linea;
var id = tag.id;
document.location.href = 'x.php?a='+ lineA +'&b=' + id;
}
}).bind("mousemove", function(event) {
var tag = GetHoveredTag(event);
var cursor = (tag) ? "pointer" : "";
$(this).css("cursor", cursor);
});
function GetHoveredTag(event) {
var left = event.pageX - posLeft;
for(var i = 0; i < tags.length; i++){
var x = tags[i].x -10;
var y = tags[i].y -10;
var offsetX = x + 20;
var offsetY = y + 20;
if( left >= x && left <= offsetX )
return tags[i];
}
return 0;
}
Updated fiddle.

Categories

Resources