Air HTML Component and HTML_RENDER event - flex4

We are currently using the mx:HTML component to render complex HTML pages (which was pretty disturbing..:)). For some reasons, we need, when the HTML is rendered, to capture an image of the displayed page. So i use the following code to do this :
on initialization :
frameHtml.addEventListener(Event.HTML_RENDER, cacheFrameHTML);
and the cacheFrameHTML function :
private function cacheFrameHTML(event:*):void {
...
cacheImage.source = new Bitmap( ImageSnapshot.captureBitmapData(frameHtml));
...
}
For some unknown reason, the result image is sometime completly blank. It seems that there is a short delay between HTML_RENDER event and effective rendering of the HTML component. I tried to delay the image capture with a timer which seems to work, but that is not pretty clean.
So my question is :
- is there anyone who know a trick to only trigger the capture when the HTML frame is effectivly displayed?
- at least, is there anyway to test if the result BitmapData is blank or have only white pixels?:b
Thanks a lot
Antoine

Have you tried to use the callLater method?
The callLater() method queues an operation to be performed for the next screen refresh, rather than in the current update
private function cacheFrameHTML(event:*):void {
...
callLater(saveImage);
...
}
private function saveImage():void
{
cacheImage.source = new Bitmap( ImageSnapshot.captureBitmapData(frameHtml));
}

Related

StaticImage in a layer. Is the change of source synchronous or asynchronous?

I'm developing a an application which displays images ( png ) in a layer of an OpenLayer's map. So far so good, it works like a charm. Nonetheless it may happen
that the requested image has to be created on the fly by the server and then a delay of few or more seconds can be observed before the image appears on the client's side. To make the user understand that displaying the image takes some time I use an animation that appears when the request is sent to the server and should disappear when the image is served and displayed (see code below). What I observe though is that the animation never appears exactly as is the service of the image was processed in an asynchronous way. I really would like to know if my interpretation is correct and in such a case which can of event I should trap and only then make the animation disappear.
document.getElementById('loading').style.display='block';
_im_layer_1 = new ol.layer.Image({
source: new ol.source.ImageStatic({
url: 'http://'+server+':'+port+'/png/?path="'+_path+'"&si='+_sliceIndex,
projection: _projection_1,
imageExtent: _extent
})
});
console.log("adding the image layer");
_map_1.addLayer(_im_layer_1);
document.getElementById('loading').style.display='none';
I was expecting to listen to the source with
imageStaticSource.on('change', evt => {
console.log('no event, contrary to what I would expect');
});
but it fails contrary to what I expected from the API docs.
So, looking at the code, I've seen there is an imageLoadFunction option for the ol.source.ImageStatic constructor. When not set, this function fallback to a default one. I've created a new one, derived from the default and made some changes to demonstrate how you can get the start of the loading event and then the end of it.
You will find a demo derived from the official sample that should illustrate the process. Try it on you side as the demo does not wait some seconds to return the image, contrary to your use case.
var imageLoadFunction = function(image, src) {
// Where you start showing the loader using a variable
console.time('loader');
image.getImage().addEventListener('load', function() {
// Where you should mention to stop the loader
console.timeEnd('loader');
});
image.getImage().src = src;
};
var imageStaticSource = new ol.source.ImageStatic({
attributions: '© xkcd',
url: 'https://imgs.xkcd.com/comics/online_communities.png',
projection: projection,
imageLoadFunction: imageLoadFunction,
imageExtent: extent
});

p5.js global and instance mode confusion

I have two p5 sketches, and I want to use them in the same space of a website. So that after clicking a button, the sketches switch. So I made three different files. The first two, are the sketches, and they are wrapped in a function (instance mode). The third sketch is a code written in global mode, because It has the information that loads a button right when the website is first accesed, and it has the information containing what the button is supposed to do: call the other sketches.
The code looks like this:
var playing = false;
var button;
function setup() {
var col = color(185,185,185,150);
button = createButton('Play');
button.position(20,20);
button.parent('black');
button.style("background-color", col);
button.style("padding", "10px 20px");
button.style("font-size", "14px");
button.mousePressed(toggleCanvas); // attach button listener
}
function mousePressed() {
}
function toggleCanvas() {
if (playing) {
if(myp5r){
myp5r.remove();
runSketch();
button.html('Stop');
}else{
runSketch();
button.html('Stop');
}
}else {
if(myp5){myp5.remove();
stopSketch();
button.html('Play');
}else{
stopSketch();
button.html('Play');}
}
playing = !playing;
}
I have been warned, to not mix global and instance mode, although my "common sense" says that it is ok to use a global mode for the button. Because I want it to be loading first, along with the page.
I noticed that weird things happen, though. Like, I get a blank space added beneath the footer, it looks horrible. And, even more worse, button is not appearing in the correct spot in the site. I already ckecked that css has position:relative for example. And the design works in localhost, but not in the site.

Nativescript Android - hide keyboard

In my Nativescript app, the application starts with the login page. On iOS everything looks good, but on android, the username field is focused and the keyboard is showing. Is there a way to prevent this from happening?
So far I have tried:
Getting a reference of another element (a label) and calling lbl.focus() in the page's onLoaded event
getting a reference of the username textfield and calling txt.dismissSoftInput() and txt.android.clearFocus()
None of this worked. Is there another way to hide the keyboard when the page is loaded?
Thank you
I guess the username field is either textview or textfield. If so, try this on loaded callback:
var myTextview = page.getViewById("myTextView");
myTextView.dismissSoftInput();
So I ended up implementing a different solution. This may not be the best approach, but it serves its purpose in my case and I wanted to share it for those of you that face a similar scenario.
in page's loaded event I included this code:
if (page.android) {
var un = page.getViewById('username');
var p = page.getViewById('password');
un.android.setFocusable(false);
p.android.setFocusable(false);
setTimeout(function () {
un.android.setFocusableInTouchMode(true);
p.android.setFocusableInTouchMode(true);
}, 300);
}
The key here is the setTimeout function (Thanks Emil Oberg for pointing me to the right direction). As far as I understand, here is what is happening:
The page loads and we call setFocusable(false) on the only 2 text fields to prevent Android from setting the focus on them
Then we wait 300ms to allow Android to do its initialization
When the timeout executes, call setFocusableInTouchMode(true) to allow the fields to gain focus.
At this point the page is loaded without any fields to be in focus and with the keyboard hidden. If the user taps any of the fields the keyboard will appear and they can proceed to log in as usual.
As I mentioned, this may not be the best, or correct, approach, but works for me. Hope this can save someone the time to research the issue.
You want to clear the focus of the field in the loaded callback:
var searchBar = page.getViewById('my-search-bar-id');
if (searchBar.android) {
searchBar.android.clearFocus();
}
What about combining both tips above?
onClear(args) {
const searchBar = <SearchBar>args.object;
if (isAndroid && searchBar.android != undefined){//avoid random unpleasant error
setTimeout(() => { // the key here was this timeout
searchBar.android.clearFocus();
}, 1)
}
}

jQuery .load() wait till content is loaded

How to prevent jQuery $('body').load('something.php'); from changing any DOM till all the content from something.php (including images,js) is fully loaded
-Lets say some actual content is:
Hello world
And something.php content is:
image that loads for 10 seconds
20 js plugins
After firing .load() function nothing should happen, till images an js files are fully loaded, and THEN instantly change the content.
some preloader may appear, but its not subject of question.
[edit]----------------------------------------------------------------------
My solution for that was css code (css is loaded always before dom is build) that has cross-browser opacity 0.
.transparent{
-moz-opacity: 0.00;
opacity: 0.00;
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha"(Opacity=0);
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=0);
filter:alpha(opacity=0);
}
And it prevent from bad flickr of content usually but not always. Now its possible to detect somehow that content is loaded by jQuery ajax and apply some show timeout and so on. But in fact question is still open.
To make now a little more simple example for that question:
How to begin changing DOM after $('body').load('something.php') with 3000ms delay after clicking the link that fire .load('something.php') function? (Browser should start downloading instantly, but DOM changing has to be initiated later)
Use .get instead and assign the contents in the success callback:
$.get('something.php', function(result) {
$('body').html(result);
});
There are some implementation details you may have to solve yourself, but here's a rough solution:
Don't use .load() directly. It can't be changed to wait for all images to load.
Use $.get() to fetch the HTML into a variable, let's call it frag.
Use $(frag).find('img').each(fn) to find all images and dump each this.src inside a preloader.
var images = [],
$frag = $(frag),
loaded = 0;
function imageLoaded()
{
++loaded;
// reference images array here to keep it alive
if (images.ready && loaded >= images.length) {
// add $frag to the DOM
$frag.appendTo('#container');
}
}
$frag.find('img').each(function() {
var i = new Image();
i.onload = i.onerror = imageLoaded;
i.src = this.src;
images[images.length] = i;
});
// signal that images contains all image objects that we wish to monitor
images.ready = true;
Demo
Once all images are loaded, append the earlier frag to the DOM using $frag.appendTo('#container').
Here is a quick proof of concept that loads relevant images before inserting an HTML fragment into the DOM: http://jsfiddle.net/B8B6u/5/
You can preload the images using the onload handler to trigger iterations:
var images = $(frag).find('img'),
loader = $('<img/>');
function iterate(i, callback) {
if (i > 0) {
i--;
loader.unbind("load");
loader.load(function() {
iterate(i, callback);
});
loader.attr('src', images[i].src);
}else{
callback();
}
}
iterate(images.length,function(){
$('#container').html(frag);
});
This should work, since each image is loaded after the previous one has finished loading.
Have you tried this?
$(function(){$('body').load('something.php')});
Edit: I just realized you are actually wanting to wait for the stuff to load before it get's placed in the body.
Here are three links to similar questions.
Preloading images with jQuery
Is it possible to preload page contents with ajax/jquery technique?
Preloading images using PHP and jQuery - Comma seperated array?
You can probably adapt those to scripts too.
This might work too.
$.ajax({
'url': 'content.php',
'dataType': 'text',
'success': function(data){
var docfrag = document.createDocumentFragment();
var tmp = document.createElement('div'), child;
//get str from data here like: str data.str
tmp.innerHTML = str;
while(child = tmp.firstChild){
docfrag.appendChild(child);
}
$('body').append(docfrag);
}
});
It's a longer way of doing what Shadow Wizard suggests, but it will probably work.
Hm. Never mind. Jack's answer looks the best. I'll wait a while and if no one likes my answer I'll delete it.
Edit: It looks like appending to documentfragments can do http requests.
Any script using createDocumentFrament may benefit from preloading.
In this question they want no http requests even though that's what createDocumentFragment is doing:
Using documentFragment to parse HTML without sending HTTP requests.
I can't be sure if this is true for all browsers or just when the console.log is run, but it could be a good option for preloading if this behavior is universal.

AJAX Loader doesn't stay untill the new content is loaded

I am using AJAX functionality to make my WordPress pages load in real time. I use the following approach to make it load in real time
var toLoad = $(this).attr('href')+' #container';
$('#container').slideUp('300',loadContent);
$('#load').remove();
$('#wrapper').append('<span id="load">LOADING...</span>');
$('#load').fadeIn('normal');
window.location.hash = $(this).attr('href').substr(0,$(this).attr('href').length-5);
function loadContent() {
$('#container').load(toLoad,'',showNewContent())
}
function showNewContent() {
$('#container').slideDown('400',hideLoader());
}
function hideLoader() {
$('#load').fadeOut('normal');
}
return false;
The problem i am facing is that the loading... text appear for half a second and the old content appears again.. and then after 4-5 seconds, it just replaces the new content with the old one.
How can i keep the Loading Text until the content is fully loaded.
Question is not perfectly clear to me,
But,
$('#container').load(toLoad,'',showNewContent())
should be changed to
$('#container').load(toLoad,'',showNewContent)
and,
$('#container').slideDown('400',hideLoader());
to
$('#container').slideDown('400',hideLoader);
We pass the function reference ( we dont call them )
Also, I dont think there's any .fadeIn('normal').
It would be either .fadeIn('slow') or .fadeIn('fast')
Also,
lines following this
$('#container').slideUp('300',loadContent);
do not wait for animation completion. They gets called instantly.
I guess, you would want them to put in loadContent function

Resources