Meteor.startup(func) - when is the DOM "ready" in Meteor? - dom

http://docs.meteor.com/#meteor_startup
Concerning Meteor.startup(func)
On a client, the function will run as soon as the DOM is ready.
At what point is the "DOM ready"?
The reason why I ask is because you can have a Meteor template that uses many other templates (ie. other DOM elements) inside of it and have many other things loading at different times depending on how long those things take to load (ie. more DOM elements).
In the past I've loaded Javascript files on Meteor.startup but they were still loaded too early because the entire DOM actually had not been loaded yet.
Meteor.startup( function() {
//load JS files now
});
So what does it mean by "DOM ready?" It most definitely does not mean "When the DOM is loaded in its entirety."

Meteor.startup actually runs when all the files have completely downloaded from the server (javascript files). If you place your code to run at startup without putting it in a Meteor.startup it may not run because it would run where the JS/html has not been fully downloaded yet
This is when the 'DOM is ready', but not necessarily when your HTML is rendered, because this (the HTML) renders when the DOM is ready too.
If you're looking for something that runs after both the DOM is ready and after your page's html is ready look for the template's .rendered callback - http://docs.meteor.com/#template_rendered
The confusion may come from the concept of $(document).ready in JQuery, but this applies because the page is already rendered on the server side so you can assume its also rendered on the client (since its downloaded that way). In Meteor pages are rendered on the client so there is this slight difference.

Here's what the .startup method actually does on the client:
Meteor.startup = function (cb) {
var doScroll = !document.addEventListener &&
document.documentElement.doScroll;
if (!doScroll || window !== top) {
if (loaded)
cb();
else
queue.push(cb);
} else {
try { doScroll('left'); }
catch (e) {
setTimeout(function() { Meteor.startup(cb); }, 50);
return;
};
cb();
}
};

Related

Javascript DOM addressing into a sub-window DOM element

Given this screenshot of a Firefox DOM rendering, I'm interested in reading that highlighted element down a ways there and writing to the "hidden" attribute 3 lines above it. I don't know the Javascript hierarchy nomenclature to traverse through that index "0" subwindow that shows in the first line under window indexed "3" which is the root context of my code's hierarchy. That innerText element I'm after does not appear anywhere else in the DOM, at least that I can find...and I've looked and looked for it elsewhere.
Just looking at this DOM, I would say I could address that info as follows: Window[3].Window[0].contentDocument.children[0].innerText (no body, interestingly enough).
How this DOM came about is a little strange in that Window[0] is generated by the following code snippet located inside an onload event. It makes a soft EMBED element, so that Window[0] and everything inside is transient. FWIW, the EMBED element is simply a way for the script to offload the task of asynchronously pulling in the next .mp4 file name from the server while the previous .mp4 is playing so it will be ready instantly onended; no blocking necessary to get it.
if (elmnt.contentDocument.body.children[1] == 'undefined' || elmnt.contentDocument.body.children[1] == null)
{
var mbed = document.createElement("EMBED");
var attsrc = document.createAttribute("src")
mbed.setAttributeNode(attsrc);
var atttyp = document.createAttribute("type")
mbed.setAttributeNode(atttyp);
var attwid = document.createAttribute("width")
mbed.setAttributeNode(attwid);
var atthei = document.createAttribute("height")
mbed.setAttributeNode(atthei);
elmnt.contentDocument.body.appendChild(mbed);
}
elmnt.contentDocument.body.children[1].src=elmnt.contentDocument.body.children[0].currentSrc + '\?nextbymodifiedtime'
elmnt.contentDocument.body.children[1].type='text/plain'
I know better than to think Window[3].Window[0]...... is valid. Can anyone throw me a clue how to address the DOM steps into the contentDocument of that Window[0]? Several more of those soft Windows from soft EMBED elements will eventually exist as I develop the code, so keep that in mind. Thank you!
elmnt.contentWindow[0].document.children[0].innerText does the trick

Unity WebGL remain localData after app update

We released our game on several platforms, including WebGL. This game saves some local stuff (app language, local users...) into the PlayerPrefs, using the browser's IndexedDB API.
Though we noticed after uploading a new version of the app on our server, the data in the PlayerPrefs is gone.
Is there any way of keeping these data, after a new upload of the game?
I've read taht WebGL can't write to disk, so reading/saving a file on disk isn't possible.
Some topics about this problem mention the use of cookies, but couldn't find any decent documentation on how to use this.
Is there a decent solution to fix this?
Kind regards,
Carsten
yes Unity is saving all data (including PlayerPrefs) to IndexedDB.
You can see these files i.e. in Chrome DevTools under "Application":
Storage-> IndexedDB -> /idbfs {{YOUR SERVER}} -> FILE_DATA
We you make a new build with a different Unity-Version or a different machine the hash-value changes. So the saved files from the old build can not be found by Applicaton.persistentDataPath
A workaround can be using the LocalStorage from your browser if you are only saving strings or numbers.
You can write some javascript functions (for example in <script> tags in your template file) to store your text data there - it very similar to the PlayerPrefs:
var saveData = function(yourkey, yourdata){
localStorage.setItem(yourkey, yourdata);
}
to save values. And
var loadData = function(yourkey){
localStorage.getItem(yourkey);
}
to get them.
Create a plugin.jslib file in Unity Editor and call these functions:
mergeInto(LibraryManager.library, {
GetData: function(yourkey){
if(typeof loadData !== 'undefined'){
loadData(Pointer_stringify(yourkey));
} else {
console.log("Javacript function not available...");
}
},
SetData: function(yourkey, yourdata){
if(typeof saveData !== 'undefined'){
saveData(Pointer_stringify(yourkey), Pointer_stringify(yourdata));
} else {
console.log("Javacript function not available...");
}
}
});
Now you can call them from Script as metioned here

How to stop automatically closing browser when writing protractor test cases

I am new to writing test cases using protractor for non angular application. I wrote a sample test case.Here the browser closes automatically after running test case.How can I prevent this. Here is my code
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function() {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
});
});
I was also struggling with a similar issue where i had a test case flow where we were interacting with multiple application and when using Protractor the browser was closing after executing one conf.js file. Now when I looked into the previous response it was like adding delay which depends on how quick your next action i performed or it was hit or miss case. Even if we think from debugging perspective most of the user would be performing overnight runs and they would want to have browser active for couple of hours before they analyze the issue. So I started looking into the protractor base code and came across a generic solution which can circumvent this issue, independent of any browser. Currently the solution is specific to requirement that browser should not close after one conf.js file is executed, then could be improved if someone could add a config parameter asking the user whether they want to close the browser after their run.
The browser could be reused for future conf.js file run by using tag --seleniumSessionId in command line.
Solution:
Go to ..\AppData\Roaming\npm\node_modules\protractor\built where your
protractor is installed.
Open driverProvider.js file and go to function quitDriver
Replace return driver.quit() by return 0
As far as my current usage there seems to be no side effect of the code change, will update if I came across any other issue due to this change. Snapshot of code snippet below.
Thanks
Gleeson
Snapshot of code snippet:
Add browser.pause() at the end of your it function. Within the function itself.
I found Gleeson's solution is working, and that really helped me. The solution was...
Go to %APPDATA%Roaming\npm\node_modules\protractor\built\driverProviders\
Find driverProviders.js
Open it in notepad or any other text editor
Find and Replace return driver.Quit() to return 0
Save the file
Restart your tests after that.
I am using
node v8.12.0
npm v6.4.1
protractor v5.4.1
This solution will work, only if you installed npm or protractor globally; if you have installed your npm or protractor locally (in your folder) then, you have to go to your local protractor folder and do the same.
I suggest you to use browser.driver.sleep(500); before your click operation.
See this.
browser.driver.sleep(500);
element(by.css('your button')).click();
browser.driver.sleep(500);
Add a callback function in It block and the browser window doesn't close until you call it.
So perform the action that you need and place the callback at your convenience
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function(callback) {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
// Have all the logic you need
// Then invoke callback
callback();
});
});
The best way to make browser NOT to close for some time, Use browser.wait(). Inside the wait function write logic for checking either visibilityOf() or invisibilityOf() of an element, which is not visible or it will take time to become invisible on UI. In this case wait() keep on checking the logic until either condition met or timeout reached. You can increase the timeout if you want browser visible more time.
var EC=protractor.ExpectedConditions;
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function() {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
browser.wait(function(){
EC.invisibilityOf(submitBtnElm).call().then(function(isPresent){
if(isPresent){
return true;
}
});
},20000,'error message');
});
});
I'm sure there is a change triggered on your page by the button click. It might be something as subtle as a class change on an element or as obvious as a <p></p> element with the text "Saved" displayed. What I would do is, after the test, explicitly wait for this change.
[...]
return protractor.browser.wait(function() {
return element(by.cssContainingText('p', 'Saved')).isPresent();
}, 10000);
You could add such a wait mechanism to the afterEach() method of your spec file, so that your tests are separated even without the Protractor Angular implicit waits.
var submitBtnElm = $('input[data-behavior=saveContribution]');
it('Should Search', function() {
browser.driver.get('http://localhost/enrollments/osda1.html');
browser.driver.findElement(by.id('contributePercentValue')).sendKeys(50);
submitBtnElm.click().then(function() {
});
browser.pause(); // it should leave browser alive after test
});
browser.pause() should leave browser alive until you let it go.
#Edit Another approach is to set browser.ignoreSynchronization = true before browser.get(...). Protractor wouldn't wait for Angular loaded and you could use usual element(...) syntax.
Protractor will close browsers, that it created, so an approach that I am using is to start the browser via the webdriver-reuse-session npm package.
DISCLAIMER: I am the author of this package
It is a new package, so let me know if it solves your problem. I am using it with great success.

How to wait for RPCs from another presenter?

Im using gwt-platform and I have 2 Presenters ( MainpagePresenter and SecondpagePresenter). MainpagePresenter is my DefaultPlace.
So, onModuleLoad I am starting to load data from the server part with rpc and saving my data into the client cache. I implemented a PopupPanel to show a loading screen like this:
PopupPanel loadingPanel = new PopupPanel(false, true);
this.loadingPanel.add(new Label("loading..."));
this.loadingPanel.center();
this.loadingPanel.show();
So the user can't click on anything before everything is loaded sucessfully.
The Panel will be hidden when onSucess() from the rpc is called.
My SecondpagePresenter gets the saved data from the cache onReset().
#Override
protected void onReset()
{
super.onReset();
this.data = (Data) this.cache.get("Data");
}
Everything works fine, but when I am browsing the second page and do a browser refresh, the code of SecondpagePresenter will still be called before my data is received.
The only solution I found so far is to implement a while loop like this:
while(cache.get("data") != null)
{
Window.alert("loading");
}
This prevents the code to continue but the user has to click on an "OK"-Button.
So my questions is: Is there a way to block the code from SecondpagePresenter to get called before the data from my MainpagePresenter is loaded successfully?

Ink file picker callback called too early. How to detect when the file is available?

When uploading a file using filepicker.io, the filepicker.pick success callback is getting called before the file is actually available. Here's the code:
filepicker.pick({
mimetypes: ['image/*'],
container: 'modal',
services:['COMPUTER', 'FACEBOOK', 'INSTAGRAM', 'WEBCAM']
},
function(inkBlob){
$('img.foo').attr('src', inkBlob.url);
},
function(FPError){
console.log(FPError.toString());
});
I get a url in the inkBlob that comes in the callback, but sometimes if I insert that url into the dom (as above), I get a 404. Other times it works. I'm looking for a reliable way to know when I can use the file returned by filepicker. I figured the success callback was it, but there seems to be this race condition.
I realize I could wrap the success callback in a setTimeout, but that seems messy, and I'd like to not keep the user waiting if the file is actually available.
You can also use an event listener.
I have an ajax call that downloads an image after it's cropped by Ink. This call was failing sporadically. I fixed it by doing roughly the following:
filepicker.convert(myBlob,
{
crop: cropDimensions
},
function(croppedBlob) {
function downloadImage() {
...
}
var imageObj = new Image();
imageObj.onLoad(downloadImage()); //only download when image is there
imageObj.src = croppedBlob.url;
}
);
I have the same issue as you. My workaround was to attach an onError event to the image and have it retry on a 404 (can set a limit of retries to avoid infinite loop), but it's quite ugly and messy, so it would be great if someone came around with a better solution.