check if new window is still open - node-webkit

Ive been reading the node-webkit wiki and may have missed or just dont understand from the documentation,
so i have been trying lots of ways which i think is how one would check to see if a new window is open or not,
One way im checkig is storing the 'new_win' var in "on('loaded')" and "on('close')".
I would like to know if what i am doing is ok, or whats an more efficent way.
var new_win;
function openPopUp(){
if(new_win){
console.log("New win was already opened");
}else{
console.log("Opened a new window");
}
var gui = require('nw.gui');
new_win = gui.Window.open('popup_page.html', {});
new_win.on('loaded', function(){
new_win = true
});
new_win.on('close', function() {
this.close(true);
new_win = false
});
}

Currently there is a trick to do this: An exception will be thrown on accessing to Win.window after it's closed.

Related

Phantomjs dump dom object

I'm new to Phantomjs. For debugging on a remote server, I often want to dump a DOM object to look at the structure (similar to Data::Dumper in Perl). This currently is for scraping a couple of sites.
I've thought JSON.stringify may help with this, but it still displays an object name like "[object HTMLDocument]"
Edit: I have also looked at JavaScript: how to serialize a DOM element as a string to be used later? , but I can't seem to inject jquery in phantomjs (still looking for a solution to that, and would prefer no depencencies), and the other answer doesn't seem to work. As I assume it would be a common case for Phantom to analyse the DOM, I thought it would be common for phantom users to have a solution to this.
var page = require('webpage').create();
var system = require('system');
page.onConsoleMessage = function(msg) {
console.log( msg );
}
page.open('http://www.test.com', function(status) {
if(status !== "success") {
console.log( status );
} else {
page.evaluate(function() {
var headline = document.querySelectorAll('div');
console.log( JSON.stringify( headline ) ); // HERE???
});
}
phantom.exit();
});
Is there any way to do this, or am I approaching this wrong ?
in page.evaluate(), you can use XMLSerializer.serializeToString() to convert whatever DOM node you want to string.
page.evaluate(function() {
var s = new XMLSerializer();
return s.serializeToString(document.getElementById('div'));
});
I haven't tried it with "querySelectorAll", since it may return array instead of standalone DOM node, but it definitely works for DOM nodes.
MDN Link

How to use deferred.when with eventlistner and eventhandler?

I am trying to use one Deferred.when statement which can return an object after the completion of an eventhandler. My code looks like something below. Can someone guide me how to make it work? I am using dojo 1.7.
define(["dojo/_base/declare","dojo/_base/lang", "dojo/_base/xhr",
"dojo/_base/json","dojo/_base/Deferred","dijit/registry","dojo/_base/connect",
"dojo/query","dojo/on","dojo/dom-attr","dojo/dom","dojo/has","dojo/json","dojo/dom-style"],
function(declare,lang,xhr,json,Deferred,registry,connect,$,on,attr,dom,has,json,domStyle)
{
declare("model.Item", [],
{
deferred:null,
item:null,
Load: function(){
this.deferred = new Deferred();
var overlay = registry.byId("readFromStore");
overlay.show();
Deferred.when(connect.connect(registry.byId("storeReadOK"),"onClick",this,this.loadFromStorage), (return (this.deferred)));
// I want modification for the above line.
}
loadFromStorage:function()
{
// Do something here
this.deferred.callback(this.item);
}
return model.Item;
}
);
I also tried this below code for the Load function but it is also not working.
Load: function(){
this.deferred = new Deferred();
connect.connect(registry.byId("storeReadOK"),"onClick",this,this.loadFromStorage);
var overlay = registry.byId("readFromStore");
overlay.show();
// Deferred.when(connect.connect(registry.byId("storeReadOK"),"onClick",this,this.loadFromStorage),(overlay.hide()));
return this.deferred;
}
This below code is working fine and I was facing problem due to some other bug in my code which i have rectified and is working fine now. Thanks to all the people who tried to help me.
Load: function(){
this.deferred = new Deferred();
connect.connect(registry.byId("storeReadOK"),"onClick",this,this.loadFromStorage);
var overlay = registry.byId("readFromStore");
overlay.show();
return this.deferred;
}

Organizing JS code with Alloy and CommonJS in Titanium projects

I'm learning with Titanium to make iPhone/Android apps. I'm using Alloy MVC framework. I never used javascript before, apart from simple scripts in HTML to access the DOM or something like that, so I never needed to structure the code before.
Now, with Titanium, I must use a lot of JS code and I was looking for ways to structure my code. Basically I found 3 ways to do it: prototype, namespace and functions inside functions.
Simple example for each:
Prototype:
NavigationController = function() {
this.windowStack = [];
};
NavigationController.prototype.open = function(windowToOpen) {
//add the window to the stack of windows managed by the controller
this.windowStack.push(windowToOpen);
//grab a copy of the current nav controller for use in the callback
var that = this;
windowToOpen.addEventListener('close', function() {
if (that.windowStack.length > 1)
{
that.windowStack.pop();
}
});
if(Ti.Platform.osname === 'android') {
windowToOpen.open();
} else {
this.navGroup.open(windowToOpen);
}
};
NavigationController.prototype.back = function(w) {
//store a copy of all the current windows on the stack
if(Ti.Platform.osname === 'android') {
w.close();
} else {
this.navGroup.close(w);
}
};
module.exports = NavigationController;
Using it as:
var NavigationController = require('navigator');
var navController = new NavigationController();
Namespace (or I think is something like that, coz the use of me = {}):
exports.createNavigatorGroup = function() {
var me = {};
if (OS_IOS) {
var navGroup = Titanium.UI.iPhone.createNavigationGroup();
var winNav = Titanium.UI.createWindow();
winNav.add(navGroup);
me.open = function(win) {
if (!navGroup.window) {
// First time call, add the window to the navigator and open the navigator window
navGroup.window = win;
winNav.open();
} else {
// All other calls, open the window through the navigator
navGroup.open(win);
}
};
me.setRightButton = function(win, button) {
win.setRightNavButton(button);
};
me.close = function(win) {
if (navGroup.window) {
// Close the window on this nav
navGroup.close(win);
}
};
};
return me;
};
Using it as:
var ui = require('navigation');
var nav = ui.createNavigatorGroup();
Functions inside functions:
function foobar(){
this.foo = function(){
console.log('Hello foo');
}
this.bar = function(){
console.log('Hello bar');
}
}
// expose foobar to other modules
exports.foobar = foobar;
Using it as:
var foobar = require('foobar').foobar
var test = new foobar();
test.bar(); // 'Hello bar'
And now my question is: which is the better to maintain code clean and clear? It seems that prototype is clear an easy to read/mantain. Namespace confuses me a bit but only needs to execute the initial function to be "available" (no use of new while declaring it, I suppose because it returns the object?namespace? "me"). Finally, functions inside functions is similar to the last, so I don't know exactly the difference, but is useful to export only the main function and have all the inside functions available for use it later.
Maybe the last two possibilities are the same, and I'm messing concepts.
Remember that I'm searching for a good way to structure the code and have functions available to other modules and also inside the own module.
I appreciate any clarification.
In the examples that they release, Appcelerator appears to follow the non-prototype approach. You can see it in the examples they have released: https://github.com/appcelerator/Field-Service-App.
I've seen a lot of different approaches to structuring applications in Titanium before Alloy. Since Alloy, I've found following the development team's examples helpful to me.
With that being said, it seems to me that all of this is still under interpretation and open to change and community development. Before Alloy there were some great community suggestions on structuring an app and I believe that it is still open with Alloy. Often when I find someone's example code I see something they did with it that appears to organize it a bit better than I thought of. It seems to make it a bit easier.
I think you should structure your application in a way that makes sense to you. You may stumble on to a better and easier way of developing applications with Alloy, because you are looking at it critically.
I haven't found a lot of extensive Alloy examples, but Field-Service-App makes sense to me. They have a nice separation of the elements in the application beyond MVC. Check it out.

dojo - programmatic way to show invalid message

dojo newbie - giving it a shot.
After submitting a form, If an error is returned from the server I would like to show that message on the dijit.form.ValidationTextBox
var user_email = dijit.byId("login_user_email");
user_email.set("invalidMessage", data["result"]["user_email"]);
//need to force show the tooltip but how???
Any help much appreciated.
See it in action at jsFiddle.
Just show tooltip:
var textBox = bijit.byId("validationTextBox");
dijit.showTooltip(
textBox.get("invalidMessage"),
textBox.domNode,
textBox.get("tooltipPosition"),
!textBox.isLeftToRight()
);
Temporarily switch textBox validator, force validation, restore the original validator:
var originalValidator = textBox.validator;
textBox.validator = function() {return false;}
textBox.validate();
textBox.validator = originalValidator;
Or do both at once.
I think you can show the tooltip via myVTB.displayMessage('this is coming from back end validation'); method
you need to do the validation in the validator-method. like here http://docs.dojocampus.org/dijit/form/ValidationTextBox-tricks
you also need to focus the widget to show up the message! dijit.byId("whatever").focus()
#arber solution is the best when using the new dojo. Just remember to set the focus to the TextBox before calling the "displayMessage" method.
I am using dojo 1.10 which works create as follows:
function showCustomMessage(textBox, message){
textBox.focus();
textBox.set("state", "Error");
textBox.displayMessage(message);
}
Dojo reference guid for ValidationTextBox: https://dojotoolkit.org/reference-guide/1.10/dijit/form/ValidationTextBox.html
I know this question is ancient, but hopefully this'll help someone. Yes, you should use validators, but if you have a reason not to, this will display the message and invalidate the field:
function(textbox, state /*"Error", "Incomplete", ""*/, message) {
textbox.focus();
textbox.set("state", state);
textbox.set("message", message);
}
You can call directly the "private" function:
textBox._set('state', 'Error');
You get the same result as #phusick suggested but with less code and arguably in a more direct and clean way.
Notes:
_set is available to ValidationTextBox as declared on its base class dijit/_WidgetBase.
Live demo:
http://jsfiddle.net/gibbok/kas7aopq/
dojo.require("dijit.form.Button");
dojo.require("dijit.form.ValidationTextBox");
dojo.require("dijit.Tooltip");
dojo.ready(function() {
var textBox = dijit.byId("validationTextBox");
dojo.connect(dijit.byId("tooltipBtn"), "onClick", function() {
dijit.showTooltip(
textBox.get('invalidMessage'),
textBox.domNode,
textBox.get('tooltipPosition'), !textBox.isLeftToRight()
);
});
dojo.connect(dijit.byId("validatorBtn"), "onClick", function() {
// call the internal function which set the widget as in error state
textBox._set('state', 'Error');
/*
code not necessary
var originalValidator = textBox.validator;
textBox.validator = function() {return false;}
textBox.validate();
textBox.validator = originalValidator;
*/
});
});

Detecting browser print event

Is it possible to detect when a user is printing something from their browser?
To complicate matters, if we are presenting a user with a PDF document in a new window is it possible to detect the printing of that document ( assuming the user prints it from the browser window)?
The closest I've been able to find is if we implement custom print functionality (something like this) and track when that is invoked
I'm primarily interested in a solution that works for internet explorer (6 or later)
You can now detect a print request in IE 5+, Firefox 6+, Chrome 9+, and Safari 5+ using the following technique:
(function() {
var beforePrint = function() {
console.log('Functionality to run before printing.');
};
var afterPrint = function() {
console.log('Functionality to run after printing');
};
if (window.matchMedia) {
var mediaQueryList = window.matchMedia('print');
mediaQueryList.addListener(function(mql) {
if (mql.matches) {
beforePrint();
} else {
afterPrint();
}
});
}
window.onbeforeprint = beforePrint;
window.onafterprint = afterPrint;
}());
I go into more detail into what this is doing and what it can be used for at http://tjvantoll.com/2012/06/15/detecting-print-requests-with-javascript/.
For Internet Exploder, there are the events window.onbeforeprint and window.onafterprint but they don't work with any other browser and as a result they are usually useless.
They seem to work exactly the same for some reason, both executing their event handlers before the printing window opens.
But in case you want it anyway despite these caveats, here's an example:
window.onbeforeprint = function() {
alert("Printing shall commence!");
}
For anyone reading this on 2020.
The addListener function is mostly deprecated in favor of addEventListener except for Safari:
if (window.matchMedia) {
const media = window.matchMedia("print");
const myFunc = mediaQueryList => {
if (mediaQueryList.matches) {
doStuff();
}
};
try {
media.addEventListener("change", myFunc);
} catch (error) {
try {
media.addListener(myFunc);
} catch (error) {
console.debug('Error', error)
}
}
}
Reference: This other S.O question
If it's only for tracking purposes, perhaps you could set a background url in CSS print media to a server page (.aspx, .php, etc) and then do something on the server?
This guy claims it works.
This is not as versitile as TJ's solution, but it may be less buggy (see TJs blog post for issues he found) when only tracking is needed.