Flex - determine which button was clicked in Dialog - apache-flex

I am using browseForSave() to give the user a chance to save a file before navigating back to a previous screen. As of now the cancel button on the save dialog just closes the save dialog. I want to see if the cancel button was clicked, and if so continue navigating back to the previous screen without saving. Right now the person has to save the file in order to move back. Below is the code I'm using.
public function save(e:MouseEvent):void{
if (currentFile) {
if (stream != null)
{
stream.close();
}
stream = new FileStream();
stream.openAsync(currentFile, FileMode.WRITE);
stream.addEventListener(IOErrorEvent.IO_ERROR, writeIOErrorHandler);
var str:String = mainTextField.text;
str = str.replace(/\r/g, "\n");
str = str.replace(/\n/g, File.lineEnding);
stream.writeUTFBytes(str);
stream.close();
dataChanged = false;
}
else
{
saveAs(null);
}
}
private function saveAs(event:MouseEvent):void
{
var fileChooser:File;
if (currentFile)
{
fileChooser = currentFile;
}
else
{
fileChooser = File.documentsDirectory.resolvePath('untitled.html')
}
fileChooser.browseForSave("Save As");
fileChooser.addEventListener(Event.SELECT, saveAsFileSelected);
}

If this is AIR, you could listen for the 'cancel' event. If not, I don't think you can.

Related

Codename One: Connecting and populating a drop-down menu with an SQLite database

I am trying to connect an SQLite database file to a picker component (accepting strings). This should act similar to a drop-down menu. I have tried to follow previous advice and examples, but without success.
As indicated in a previous post, I have saved the database file in the source folder of the application. View of the source folder where I have saved the database file (highlighted).
The code I have used to implement my app is as follows with the below layout.
//-----------------------
database code
//-----------------------
public class MyApplication {
private Form current;
private Resources theme;
public void init(Object context) {
theme = UIManager.initFirstTheme("/theme");
// Pro only feature, uncomment if you have a pro subscription
// Log.bindCrashProtection(true);
}
private Container Home() {
Container home = new Container(new BoxLayout(BoxLayout.Y_AXIS));
return home;
}
private Container AddItem() {
Container addItem = new Container(new BoxLayout(BoxLayout.Y_AXIS));
TextArea item = new TextArea("Add Item");
addItem.addComponent(item);
Picker selectItem = new Picker();
selectItem.setType(Display.PICKER_TYPE_STRINGS);
//----------------------------------------------------------------------------------
Database db = null;
Cursor cur = null;
try {
db = Display.getInstance().openOrCreate("FoodAndBeverage.db");
if(selectItem.getText().startsWith("Still Water")) {
cur = db.executeQuery(selectItem.getText());
int columns = cur.getColumnCount();
addItem.removeAll();
if(columns > 0) {
boolean next = cur.next();
if(next) {
ArrayList<String[]> data = new ArrayList<>();
String[] columnNames = new String[columns];
for(int iter = 0 ; iter < columns ; iter++) {
columnNames[iter] = cur.getColumnName(iter);
}
while(next) {
Row currentRow = cur.getRow();
String[] currentRowArray = new String[columns];
for(int iter = 0 ; iter < columns ; iter++) {
currentRowArray[iter] = currentRow.getString(iter);
}
data.add(currentRowArray);
next = cur.next();
}
Object[][] arr = new Object[data.size()][];
data.toArray(arr);
addItem.add(BorderLayout.CENTER, new Table(new DefaultTableModel(columnNames, arr)));
} else {
addItem.add(BorderLayout.CENTER, "Query returned no results");
}
} else {
addItem.add(BorderLayout.CENTER, "Query returned no results");
}
} else {
db.execute(selectItem.getText());
addItem.add(BorderLayout.CENTER, "Query completed successfully");
}
addItem.revalidate();
} catch(IOException err) {
Log.e(err);
addItem.removeAll();
addItem.add(BorderLayout.CENTER, "Error: " + err);
addItem.revalidate();
} finally {
Util.cleanup(db);
Util.cleanup(cur);
}
//---------------------------------------------------------------------------------------------
addItem.addComponent(selectItem);
TextField quantity = new TextField("", "Quantity (ml or g)", 4, TextArea.NUMERIC);
addItem.addComponent(quantity);
Button add = new Button("Add");
addItem.addComponent(add);
TextArea results = new TextArea("Results");
addItem.addComponent(results);
return addItem;
}
private Container Settings() {
Container settings = new Container(new BoxLayout(BoxLayout.Y_AXIS));
TextArea nutrients = new TextArea("Target");
settings.addComponent(nutrients);
TextField volume = new TextField("", "Volume (ml)", 4, TextArea.NUMERIC);
settings.addComponent(volume);
TextArea duration = new TextArea("Hydration Duration");
settings.addComponent(duration);
settings.add("Start:");
Picker start = new Picker();
start.setType(Display.PICKER_TYPE_TIME);
settings.addComponent(start);
settings.add("End:");
Picker end = new Picker();
end.setType(Display.PICKER_TYPE_TIME);
settings.addComponent(end);
Button save = new Button("Save");
settings.addComponent(save);
return settings;
}
public void start() {
if(current != null)
{
current.show();
return;
}
Form home = new Form("Hydrate", new BorderLayout());
Tabs t = new Tabs();
t.addTab("Home", Home());
t.addTab("Intake", AddItem());
t.addTab("Settings", Settings());
home.add(BorderLayout.NORTH, t);
home.show();
}
public void stop() {
current = Display.getInstance().getCurrent();
}
public void destroy() {
}
}
I would therefore appreciate any advice and guidance on exactly where I am going wrong and how to implement the suggested changes in my code.
I'm assuming the file under src does indeed end with the extension db as the Windows hidden extensions nonsense is turned on.
This code will NOT open a db placed in src:
db = Display.getInstance().openOrCreate("FoodAndBeverage.db");
You need to do something like this to implicitly initialize the DB the first time the app is installed:
String path = Display.getInstance().getDatabasePath("FoodAndBeverage.db");
FileSystemStorage fs = FileSystemStorage.getInstance();
if(!fs.exists(path)) {
try (InputStream is = Display.getInstance().getResourceAsStream(getClass(), "/FoodAndBeverage.db");
OutputStream os = fs.openOutputStream(path)) {
Util.copy(is, os);
} catch(IOException err) {
Log.e(err);
}
}
db = Display.getInstance().openOrCreate("FoodAndBeverage.db");
Notice that the code above doesn't check for updates of the DB so assuming the DB is read only you might want to update/merge it with app updates.
The above code doesn't work on Android device, this works only on simulator. I have tested multiple times in the android device. In the real android device ,the database is not loaded at all, shows sql exception error
"No such table sql exception".
Looks like preloaded sqlite .db file is never tested on real Android device.

Caliburn.Micro Screen.CanClose() and MessageDialog().ShowAsync()

I'm currently using Caliburn.Micro 2.0 for my Windows Phone 8.1 project (Universal App) and I'm having problem with conditionally cancelling page close after user clicks a MessageDialog button.
It seems that Caliburn closes page after leaving CanClose() method, not waiting for the callback which is called after async MessageDialog.
public class MyViewModel: Screen
{
public override async void CanClose(Action<bool> callback)
{
MessageDialog dlg = new MessageDialog("Close?","Confirmation");
dlg.Commands.Add(new UICommand() { Id = 0, Label = "Yes" });
dlg.Commands.Add(new UICommand() { Id = 1, Label = "No" });
var result = await dlg.ShowAsync();
callback((int)result.Id == 0);
}
}
The only solution I have at the moment is set a field with a flag indicating if the page can be closed. On the user attempt to navigate back I tell Caliburn to abort the close and I display the confirmation dialog. When I get the result I set the flag to true and navigate back manually. This causes another call to CanClose, but this time I set the callback to true and skip the dialog part.
I don't like this solution much, but it is only way I managed to solve this problem.
private bool canClose = false;
public override async void CanClose(Action<bool> callback)
{
callback(canClose);
if (!canClose)
{
MessageDialog dlg = new MessageDialog("Close?","Confirmation");
dlg.Commands.Add(new UICommand() { Id = 0, Label = "Yes" });
dlg.Commands.Add(new UICommand() { Id = 1, Label = "No" });
var result = await dlg.ShowAsync();
if ((int)result.Id == 0)
{
canClose = true;
navigationService.GoBack();
}
}
}
PS: I don't use MessageDialog directly in my ViewModel, I'm using a dialog service interface for popups. I just used it here to demonstrate the issue.
While the enhancement CanClose isn't set, this is my approach utilize Navigating event to solve this 'problem'
If user could just GoBack() would be easy to handle, but in my case, there's many options to navigate. So, the only way that I found to solve it is described below:
public MyViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
_navigationService.Navigating += OnGoBack;
}
private async void OnGoBack(object sender, NavigatingCancelEventArgs e)
{
e.Cancel = true;
var dlg = new MessageDialog("Close?", "Confirmation"); //Dialog for demo purpose only!
dlg.Commands.Add(new UICommand() { Id = 0, Label = "Yes" });
dlg.Commands.Add(new UICommand() { Id = 1, Label = "No" });
var result = await dlg.ShowAsync();
if ((int) result.Id != 0) return;
_navigationService.Navigating -= OnGoBack;
if (e.NavigationMode == NavigationMode.Back)
_navigationService.GoBack();
else
{
var myViewModel = Type.GetType($"YourNameSpaceViewModels.{e.SourcePageType.Name}Model");
_navigationService.NavigateToViewModel(myViewModel);
}
}
Explaination:
$"YourNameSpaceViewModels.{e.SourcePageType.Name}Model"
Here I get the full path to my class where user want to goto
And so, I navigate to it _navigationService.NavigateToViewModel(myViewModel);

Returning Arraylist from recursive function for ASP.Net

Please refer the attached screenshot. I have an array of the checkbox and a button for the post back in ASP.Net page. I have written a function as follows to determine what all check boxes have been checked on the button click event: The following code is a part of the business component which is called from ASP.Net. Please let me know how can I return actionArray back to calling functon in ASP.Net page.
public void checkBoxValidation(Control parent, string strKey)
{
XmlDocument getCyleXML = new XmlDocument();
string strChkID="", strActionXPath = "",strAction="";
ArrayList actionArray = new ArrayList();
// Loop through all the controls on the page
foreach (Control c in parent.Controls)
{
// Check and see if it's a checkbox.
if ((c.GetType() == typeof(CheckBox)))
{
// Since its a checkbox, see if this is checked.
if (((CheckBox)(c)).Checked == true)
{
// Find the ID of the checkbox
strChkID = ((CheckBox)(c)).ID.ToString();
getCyleXML = CycleXML(strKey);
strActionXPath = "/Actions/Action[checkbox='" + strChkID + "']/*[self::Name]";
strAction = getCyleXML.SelectSingleNode(strActionXPath).ToString();
actionArray.Add(strAction);
}
}
// Now we need to call itself (recursion) because all items (Panel, GroupBox, etc) is a container so we need to check
// all containers for any checkboxes.
if (c.HasControls())
{
checkBoxValidation(c, strKey);
}
}
}
The code should be like this :
public ArrayList checkBoxValidation(Control parent, string strKey, ArrayList actionArray)
{
XmlDocument getCyleXML = new XmlDocument();
string strChkID="", strActionXPath = "",strAction="";
if(actionArray == null) { actionArray = new ArrayList(); }
// Loop through all the controls on the page
foreach (Control c in parent.Controls)
{
// Check and see if it's a checkbox.
if ((c.GetType() == typeof(CheckBox)))
{
// Since its a checkbox, see if this is checked.
if (((CheckBox)(c)).Checked == true)
{
// Find the ID of the checkbox
strChkID = ((CheckBox)(c)).ID.ToString();
getCyleXML = CycleXML(strKey);
strActionXPath = "/Actions/Action[checkbox='" + strChkID + "']/*self::Name]";
strAction = getCyleXML.SelectSingleNode(strActionXPath).ToString();
actionArray.Add(strAction);
}
}
// Now we need to call itself (recursion) because all items (Panel, GroupBox, etc) is a container so we need to check
// all containers for any checkboxes.
if (c.HasControls())
{
checkBoxValidation(c, strKey, actionArray);
}
}
return actionArray;
}

A simple secenario to implement JavaScript ASP.NET C#, question rephrased

I had asked this question before, but I got no correct answer.
So, this is a simple thing:
textbox.text='user typing';
Button: store the value to a variable and a database.
Very simple, nothing to it.
But there should be no post back, that is the page must not load again.
Try Ajax? I tried it, but it is not working.
I lost a lot of time trying to implement this using JavaScript Ajax and read many many posts.
But for some reason I cannot implement the functionality correctly.
var xmlHttp;
var is_ie = (navigator.userAgent.indexOf('MSIE') >= 0) ? 1 : 0;
var is_ie5 = (navigator.appVersion.indexOf("MSIE 5.5")!=-1) ? 1 : 0;
var is_opera = ((navigator.userAgent.indexOf("Opera6")!=-1)||(navigator.userAgent.indexOf("Opera/6")!=-1)) ? 1 : 0;
//netscape, safari, mozilla behave the same???
var is_netscape = (navigator.userAgent.indexOf('Netscape') >= 0) ? 1 : 0;
function btnClick(){
if (strReportURL.length > 0)
{
//Create the xmlHttp object to use in the request
//stateChangeHandler will fire when the state has changed, i.e. data is received back
// This is non-blocking (asynchronous)
xmlHttp = GetXmlHttpObject(handler);
//Send the xmlHttp get to the specified url
xmlHttp_Get(xmlHttp, "AjaxHanlder.aspx?Data="+txtData.Text,handler);
}
}
//stateChangeHandler will fire when the state has changed, i.e. data is received back
// This is non-blocking (asynchronous)
function handler()
{
//readyState of 4 or 'complete' represents that data has been returned
if (xmlHttp.readyState == 4 || xmlHttp.readyState == 'complete')
{
//Gather the results from the callback
var result = xmlHttp.responseText;
//Populate the innerHTML of the div with the results
document.getElementById('lblResult').innerHTML = result;
}
}
// XMLHttp send GET request
function xmlHttp_Get(xmlhttp, url,handler) {
xmlhttp.open('GET', url, true);
xmlhttp.onreadystatechange = handler;
xmlhttp.send(null);
}
function GetXmlHttpObject(handler) {
var objXmlHttp = null; //Holds the local xmlHTTP object instance
//Depending on the browser, try to create the xmlHttp object
if (is_ie){
//The object to create depends on version of IE
//If it isn't ie5, then default to the Msxml2.XMLHTTP object
var strObjName = (is_ie5) ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP';
//Attempt to create the object
try{
if(!objXmlHttp)
objXmlHttp = new ActiveXObject(strObjName);
//objXmlHttp.onreadystatechange = handler;
}
catch(e){
//Object creation errored
alert('IE detected, but object could not be created. Verify that active scripting and activeX controls are enabled');
return;
}
}
else if (is_opera){
//Opera has some issues with xmlHttp object functionality
alert('Opera detected. The page may not behave as expected.');
return;
}
else{
// Mozilla | Netscape | Safari
objXmlHttp = new XMLHttpRequest();
objXmlHttp.onload = handler;
objXmlHttp.onerror = handler;
}
//Return the instantiated object
return objXmlHttp;
}
///AJAX HANDLER PAGE
public class AjaxHandler : System.Web.UI.Page
{
private void Page_Load(object sender, System.EventArgs e)
{
if(Request.QueryString["Data"]!=null)
{
StoreYourData(Request.QueryString);
}
}
}

Close/kill the session when the browser or tab is closed

Can somebody tell me how can I close/kill the session when the user closes the browser? I am using stateserver mode for my asp.net web app. The onbeforeunload method is not proper as it fires when user refreshes the page.
You can't. HTTP is a stateless protocol, so you can't tell when a user has closed their browser or they are simply sitting there with an open browser window doing nothing.
That's why sessions have a timeout - you can try and reduce the timeout in order to close inactive sessions faster, but this may cause legitimate users to have their session timeout early.
As said, the browser doesn't let the server know when it closes.
Still, there are some ways to achieve close to this behavior. You can put a small AJAX script in place that updates the server regularly that the browser is open. You should pair this with something that fires on actions made by the user, so you can time out an idle session as well as one that has closed out.
As you said the event window.onbeforeunload fires when the users clicks on a link or refreshes the page, so it would not a good even to end a session.
http://msdn.microsoft.com/en-us/library/ms536907(VS.85).aspx describes all situations where window.onbeforeonload is triggered. (IE)
However, you can place a JavaScript global variable on your pages to identify actions that should not trigger a logoff (by using an AJAX call from onbeforeonload, for example).
The script below relies on JQuery
/*
* autoLogoff.js
*
* Every valid navigation (form submit, click on links) should
* set this variable to true.
*
* If it is left to false the page will try to invalidate the
* session via an AJAX call
*/
var validNavigation = false;
/*
* Invokes the servlet /endSession to invalidate the session.
* No HTML output is returned
*/
function endSession() {
$.get("<whatever url will end your session>");
}
function wireUpEvents() {
/*
* For a list of events that triggers onbeforeunload on IE
* check http://msdn.microsoft.com/en-us/library/ms536907(VS.85).aspx
*/
window.onbeforeunload = function() {
if (!validNavigation) {
endSession();
}
}
// Attach the event click for all links in the page
$("a").bind("click", function() {
validNavigation = true;
});
// Attach the event submit for all forms in the page
$("form").bind("submit", function() {
validNavigation = true;
});
}
// Wire up the events as soon as the DOM tree is ready
$(document).ready(function() {
wireUpEvents();
});
This script may be included in all pages
<script type="text/javascript" src="js/autoLogoff.js"></script>
Let's go through this code:
var validNavigation = false;
window.onbeforeunload = function() {
if (!validNavigation) {
endSession();
}
}
// Attach the event click for all links in the page
$("a").bind("click", function() {
validNavigation = true;
});
// Attach the event submit for all forms in the page
$("form").bind("submit", function() {
validNavigation = true;
});
A global variable is defined at page level. If this variable is not set to true then the event windows.onbeforeonload will terminate the session.
An event handler is attached to every link and form in the page to set this variable to true, thus preventing the session from being terminated if the user is just submitting a form or clicking on a link.
function endSession() {
$.get("<whatever url will end your session>");
}
The session is terminated if the user closed the browser/tab or navigated away. In this case the global variable was not set to true and the script will do an AJAX call to whichever URL you want to end the session
This solution is server-side technology agnostic. It was not exaustively tested but it seems to work fine in my tests
Please refer the below steps:
First create a page SessionClear.aspx and write the code to clear session
Then add following JavaScript code in your page or Master Page:
<script language="javascript" type="text/javascript">
var isClose = false;
//this code will handle the F5 or Ctrl+F5 key
//need to handle more cases like ctrl+R whose codes are not listed here
document.onkeydown = checkKeycode
function checkKeycode(e) {
var keycode;
if (window.event)
keycode = window.event.keyCode;
else if (e)
keycode = e.which;
if(keycode == 116)
{
isClose = true;
}
}
function somefunction()
{
isClose = true;
}
//<![CDATA[
function bodyUnload() {
if(!isClose)
{
var request = GetRequest();
request.open("GET", "SessionClear.aspx", true);
request.send();
}
}
function GetRequest() {
var request = null;
if (window.XMLHttpRequest) {
//incase of IE7,FF, Opera and Safari browser
request = new XMLHttpRequest();
}
else {
//for old browser like IE 6.x and IE 5.x
request = new ActiveXObject('MSXML2.XMLHTTP.3.0');
}
return request;
}
//]]>
</script>
Add the following code in the body tag of master page.
<body onbeforeunload="bodyUnload();" onmousedown="somefunction()">
I do it like this:
$(window).bind('unload', function () {
if(event.clientY < 0) {
alert('Thank you for using this app.');
endSession(); // here you can do what you want ...
}
});
window.onbeforeunload = function () {
$(window).unbind('unload');
//If a string is returned, you automatically ask the
//user if he wants to logout or not...
//return ''; //'beforeunload event';
if (event.clientY < 0) {
alert('Thank you for using this service.');
endSession();
}
}
Not perfect but best solution for now :
var spcKey = false;
var hover = true;
var contextMenu = false;
function spc(e) {
return ((e.altKey || e.ctrlKey || e.keyCode == 91 || e.keyCode==87) && e.keyCode!=82 && e.keyCode!=116);
}
$(document).hover(function () {
hover = true;
contextMenu = false;
spcKey = false;
}, function () {
hover = false;
}).keydown(function (e) {
if (spc(e) == false) {
hover = true;
spcKey = false;
}
else {
spcKey = true;
}
}).keyup(function (e) {
if (spc(e)) {
spcKey = false;
}
}).contextmenu(function (e) {
contextMenu = true;
}).click(function () {
hover = true;
contextMenu = false;
});
window.addEventListener('focus', function () {
spcKey = false;
});
window.addEventListener('blur', function () {
hover = false;
});
window.onbeforeunload = function (e) {
if ((hover == false || spcKey == true) && contextMenu==false) {
window.setTimeout(goToLoginPage, 100);
$.ajax({
url: "/Account/Logoff",
type: 'post',
data: $("#logoutForm").serialize(),
});
return "Oturumunuz kapatıldı.";
}
return;
};
function goToLoginPage() {
hover = true;
spcKey = false;
contextMenu = false;
location.href = "/Account/Login";
}
It is not possible to kill the session variable, when the machine unexpectly shutdown due to power failure. It is only possible when the user is idle for a long time or it is properly logout.
For browser close you can put below code into your web.config :
<system.web>
<sessionState mode="InProc"></sessionState>
</system.web>
It will destroy your session when browser is closed, but it will not work for tab close.
Use this:
window.onbeforeunload = function () {
if (!validNavigation) {
endSession();
}
}
jsfiddle
Prevent F5, form submit, input click and Close/kill the session when the browser or tab is closed, tested in ie8+ and modern browsers, Enjoy!

Resources