I am pretty new to flex, so forgive me if this is an obvious question.
Is there a way to open the Security.showSettings (flash.system.Security) with a callback? or at least to detect if it is currently open or not?
My flex application is used for streaming audio, and is normally controlled by javascript, so I keep it hidden for normal use (via absolute positioning it off the page).
When I need microphone access I need to make the flash settings dialog visible, which works fine, I move it into view and open the dialog.
When the user closes it, I need to move it back off the screen so they don't see an empty flex app sitting there after they change their settings.
thanks :)
If you do something like this, it will work in some situations:
var mic:Microphone = Microphone.getMicrophone();
mic.addEventListener(StatusEvent.STATUS, onMicStatus);
If you are just trying to use the microphone and relying on Flash to pop up the dialog to ask the user for permission, Flash will open a dialog with two buttons, Allow and Deny. When the user clicks one of the buttons the StatusEvent will fire, the dialog will close, and you can move the flex app out of the way.
If you are manually opening the settings panel (via Security.showSettings), you get the panel with Allow and Deny radio buttons, and the event will fire when the user clicks on the radio buttons, not when they close the panel, which is probably of less help to you.
Update: flex 4 solution
So when I moved to the flex 4 and started compiling my mxml with adobe's open source mxmlc compiler, the solution below no longer worked because the alert doesn't lose focus when you're in the settings anymore.
As far as I could tell I had to move to a less elegant solution where the user must click "OK" on the alert box every time they are done with the settings.
Here is the new code:
private function setup_smart_hide():void {
// Call this function whenever you make the flex app visible (or add it
// to a show_flex() function if you have such a thing set up)
alert = Alert.show('Click "OK" to continue.', 'Thanks!', Alert.OK, null, function(e:CloseEvent):void {
// calls the external javascript to hide the flex app
hide_self();
});
}
OLD: (flex 3) Got this working...
private function setup_smart_hide():void {
alert = Alert.show('Thanks');
alert.addEventListener(FocusEvent.FOCUS_IN, function(event:FocusEvent):void {
// javascript to hide the flex app
ExternalInterface.call("SB.flex.hide");
});
alert.addEventListener(FocusEvent.FOCUS_OUT, function(event:FocusEvent):void {
// javascript to show the flex app
ExternalInterface.call("SB.flex.show");
});
alert.setFocus();
}
Which is run first thing in the init() function... the only problem is (like Wesley said), the focusOut event occurs when the flex app itself loses focus as well.
Related
im working on making a photo gallery app more accessible.
the app has a feature of showing expanded view of an image when clicked.
one of the a11y requirements is that when a user focus an image and click enter the expand mode will open and the focus will go inside the expanded view, and will be set on one of the buttons in it. it work's fine without screen reader, or with screen reader on mac. but on windows
when using screen reader it seems that the code that fires is the one that subscribed to the click event and not the keydown event. because the flag that suppose to be set to true on keydown is false (both events fire the same function but the keydown also add the enterClicked variable set to true).
this is the div that hold the image and subscribed to the events:
<div
tabindex="0"
id="{{media.id}}"
data-ng-repeat="media in row track by media.id"
data-ng-mouseenter="events.toggleVideoPlay(media.type, media.id, media.link, ( rowNummer ) * (row.length) + ($index + 1))" class="imgContainer"
ng-keydown="$event.keyCode == 13 ? events.openExpandMode(media.id, true) : null"
data-ng-click="events.openExpandMode(media.id)"
>
openExpandMode function:
$scope.events.openExpandMode = (mediaId, isEnterClicked) => {
const state = {
isEnterClicked,
mediasId,
currentIndex,
pagination: $scope.mediasPagination,
settings: {
isUserName: $scope.settings.user_name_checkbox,
isTemplate: !$scope.userConnected && !$scope.userConnectedWithOldApi,
isLikeComments: $scope.settings.like_comments_checkbox,
isDescriptions: $scope.settings.description_checkbox,
isComments: $scope.settings.comments_checkbox,
theme: $scope.settings.expand_theme,
lang: $translate.use()
}
};
localStorageService.set('state', state);
}
expand mode component init:
const _init = () => {
if ($scope.isOpenFromEnter) {
document.getElementById('nextArrow').setAttribute('data-focus-visible-added', "");
document.getElementById('nextArrow').className += ' focus-visible';
document.getElementById('nextArrow').focus();
}
}
is there a way to stop windows screen reader event interception ?
Short answer
It's common to send a click event instead of a press enter event.
The best is probably to adapt your code so that click and enter do the same thing, and that either or both event can be sent, because
you only have a quite limited influence on which is sent or not and when
Longer answer
You haven't indicated which screen reader you were using (Jaws or NVDA), but anyway, it's common for both to send a click event when pressing enter, instead of sending key events.
Reasons for that may seem strange and illogical at first, but there are at least two good ones:
It's certainly as much illogical to have two different things happening when clicking or pressing enter. IN all applications since GUI exist, most often, both do the same action (the only exception I can think of right now is multiline or rich text fields).
Scren readers existed before web accessibility, and accessibility is still rarely implemented nowadays. Sending a click event when pressing enter provide a minimal usability in all the places where designers didn't even thought that the keyboard could be used instead of the mouse.
By the way, screen reader or not, guess which event is sent if you press enter when the focus is on a link or a button?
Depending on the browser, the answer isn't unanimous as far as I know.
And on the screen reader side, it isn't unanimous either. Some even allow to configure the exact behavior to take, in order to adapt to different more or less unaccessible sites.
is there a way to stop windows screen reader event interception ?
You can stop some form of interception by calling preventDefault in your event listener function, if the click event is generated by the browser.
By doing so, you can actually do something different on click and on enter. But ask yourself first if it is really justified. Think about my first point above.
However, you can't prevent screen readers from intercepting keyboard events, translate them to something else and send or don't send them to your page.
There exists the ARIA application mode, but it has several important implications, so you shouldn't use it unless you have true good reasons.
To wrap up, the best is probably to adapt your code so that click and enter do the same thing, and that either or both event can be sent.
adding role="application" to the container div fixed it.
my goal is to hide the content of my homepage when someone visits. onClick to begin button the content should be shown. Content should stay open when user goes to other page and comes back to homepage. But it will be hidden when user closes the window and opens up the homepage again. To achieve this goal I have put the following code but it keeps the content open even when user closes and opens the window. So please help me out.
if (! localStorage.noFirstVisit) {
// hide the element
$("#content").hide();
// check this flag for escaping this if block next time
localStorage.noFirstVisit = "1";
}
Another issue is when the content shows the design gets little messed up(by widening the divs, bringing horizontal scroll)
$(".roll-button").click(function(){
$("#content").show();
});
I would highly appreciate if you check website, suggest me fix or show me proper way to achieve this goal. url:iamicongroup.com
You can totally use sessionStorage to detect whether it is new tab(window) or not.
When you first visit this page, set sessionStorage.noFirstVisit = "1";.
After you go to another page and back, sessionStorage.noFirstVisit is still "1".
But when you close the tab or browser and open the page newly again, sessionStorage.noFirstVisit will be undefined.
Documentation is here
The documentation also provide the difference between sessionStorage and localStorage.
I would suggest reading this: Detect Close windows event by Jquery
It goes over window unloading (beforeunload), which I believe is what you're after. You can set/unset your localstorage values there based on certain criteria being met; for example:
$(window).on("beforeunload", function() {
if(localStorage.noFirstVisit = "1" {
// do something
localStorage.noFirstVisit = "[someValue]"
}
else {
// do something
localStorage.noFirstVisit = "1"
}
})
Another issue is when the content shows the design gets little messed up(by widening the divs, bringing horizontal scroll)
how about adding something like 'ng-cloak' in angular, to avoid the undesirable flicker effect caused by show/hide.
when clicking the roll-button, it prevents the divs from showing unfinished..
I have a YAHOO.widget.Button of the type "menu". My task is simple: The menu is shown when the user clicks on the button, and is hidden when the user clicks elsewhere on the screen.
Here's my code on jsfiddle:
http://jsfiddle.net/tRssn/
What I've tried so far:
1. Setting the clicktohide property of the Menu widget to true (see above code)
and
2. Subscribe to the blur event on the Button/Menu widget and close the menu if it's visible.
Approach 1 doesn't work for some reason and approach 2 works with IE and Mozilla, but not Chrome.
Shouldn't there be an easy way to do this?
Any help appreciated!
Okay, I was able to solve this by explicitly creating a YAHOO.widget.Menu object, rendering it, and then assigning it as the menu to the YAHOO.widget.Button object.
http://jsfiddle.net/tRssn/1/
Strangely, I have to set the config for the Menu widget like this instead of at the time of the creation:
oButton.getMenu().cfg.config.clicktohide.value = true;
I have been recently studying and learning Flash AC3 and my intention was to make a small voice recorder for my website. I have been using google and the search engines and get different answers here and there but still it is not exactly working properly.
The problem I am having is, the flash plugin is 215x50 pixels. I know that unless it is 215x138 pixels, the flash player security panel will automatically NOT open.
I devised a work around which is that if and when the security is being called to open, I would resize the DIV the flash object is in using a javascript function called ResizeFlash to a size of 215x138 and then back again to 215x50 after the user makes a choice whether or not they allow the microphone.
Now I have been scratching my head for a few days because I DO get the following code to work and it does resize the DIV, but it does not resize the DIV back. I think I might have the call to ResizeFlash in the wrong place (???). I am not familiar enough to know where it might be wrong.
I keep rearranging the code to see if that would work and I would get times where it does resize to 215x138, open the Security Panel, then resize back to 215x50 but then the recording would not begin, as if I were stuck somewhere in a loop.
I hope that someone can please take some time and just take a glance at this code and show me the right way to handle this. Thank you very much!
Here is the code:
public function Main():void
{
recButton.stop();
submitButton.enabled = false; // These reset everything, maybe in wrong place??
activity.stop();
addListeners();
mic = Microphone.getMicrophone();
if (mic == null)
{
// no camera is installed
}
else if (mic.muted)
{
// user has disabled the access in security settings
mic.addEventListener(StatusEvent.STATUS, onMicStatus, false, 0, true); // listen out for their new decision
Security.showSettings('2'); // show security settings window to allow them to change security settings
}
else
{
// you have access
mic.setUseEchoSuppression(true); //... also this might be in wrong place?
// .. I would like this to always be on
}
}
private function addListeners():void
{
recButton.addEventListener(MouseEvent.MOUSE_UP, startRecording);
submitButton.addEventListener(MouseEvent.MOUSE_UP, onSend);
recorder.addEventListener(RecordingEvent.RECORDING, recording);
recorder.addEventListener(Event.COMPLETE, recordComplete);
activity.addEventListener(Event.ENTER_FRAME, updateMeter);
}
function onMicStatus(event:StatusEvent):void
{
if (event.code == "Microphone.Unmuted")
{
mic.removeEventListener(StatusEvent.STATUS, onMicStatus);
ExternalInterface.call('ResizeFlash', '215', '50'); // When the user presses allow, resize the div back to 215x50
}
}
private function startRecording(e:MouseEvent):void
{
recorder.record();
e.target.gotoAndStop(2);
recButton.removeEventListener(MouseEvent.MOUSE_UP, startRecording);
recButton.addEventListener(MouseEvent.MOUSE_UP, stopRecording);
}
private function stopRecording(e:MouseEvent):void
{
recorder.stop();
e.target.gotoAndStop(1);
recButton.removeEventListener(MouseEvent.MOUSE_UP, stopRecording);
recButton.addEventListener(MouseEvent.MOUSE_UP, startRecording);
}
I know that I have something in there in the wrong order..! I appreciate any comments.
Resizing the app back to 215x50 in the Microphone's status event handler may be too soon, as you have suggested.
Just a hunch, but that status event is dispatched immediately when the user clicks the "Allow" radio button in the Flash security panel. The panel is still open. In fact, if you leave it open and click between allow/deny it will get dispatched each time...
When the security panel is up, there are some things you cannot do. I wonder if using ExternalInterface (to resize the app) is falling into this bucket.
I would suggest the following:
Test your resize functionality without the security panel in the mix. Make sure this code successfully resizes the app in both directions.
Then have a look at this question about how to detect when the user actually closes the security panel. There are two approaches there, one is very hacky (the BitmapData.draw() hack) but I know it works. I suggest trying the second one, and commenting/upvoting there if it does work (I will too). It's a more elegant way to detect when the user closes the dialog, but I haven't had a chance to try it.
When you detect the dialog is closed, resize the app.
I try to understand Firefox's behavior regarding the added "prevent this page from creating additional dialogs" on dialog boxes.
Using jquery, if I add the following listeners :
//html
<input class="testInput" />
//javascript
$('.testInput')
.click(function(){ alert('clicked') })
.keyup(function(){ alert('keyup') })
When clicking on the input, the alert box appears normally, until the
~13th time.
When hitting a key, on the other hand, the second message box already
appears with the message "prevent this page from creating additional
dialogs". Actually, there seems to be some tiemout, and if I wait
like 2 seconds between two keystrokes, the message disappears.
From my informal tests, 2. actually applies whenever the alert box is not called from within a onclick callback (e.g : keyup callback, displaying an alert box in answer to an ajax action...)
I am using Firefox 9.0.1 under Ubuntu, as far as I know I haven't tweaked firefox's settings regarding these thresholds.
I imagine it happens with any recent version of any browser.
I am using the jQuery library, but I don't think it is relevant here.
My question is :
What are the exact rules which make this warning appear in a dialog box ?
[Edit]
Using Chromium/Ubuntu (version 17.0.963.26), the threshold seems to be only the delay between two dialog boxes.
You can test this from jsfiddle here (thx Rory McCrossan)
The exact rule(s): A timed interval between the dialog boxes popping up.
The value used to determine this is set in SUCCESSIVE_DIALOG_TIME_LIMIT
Check out line 2614 in the link below the snippet:
nsGlobalWindow::DialogOpenAttempted()
TimeDuration dialogDuration(TimeStamp::Now() - topWindow->mLastDialogQuitTime);
if (dialogDuration.ToSeconds() < Preferences::GetInt("dom.successive_dialog_time_limit",SUCCESSIVE_DIALOG_TIME_LIMIT)){topWindow->mDialogAbuseCount++;return (topWindow->GetPopupControlState() > openAllowed || topWindow->mDialogAbuseCount > MAX_DIALOG_COUNT);}topWindow->mDialogAbuseCount = 0; return false;}
Link to source
You can kick around the Firefox source if you like. Note that different browsers will have different rules.
The relevant code for Firefox is in nsGlobalWindow.cpp and nsGlobalWindow.h (the links below are to line numbers, and so will slowly rot as the source changes). It appears to be controlled by the constants MAX_DIALOG_COUNT (10) in nsGlobalWindow.h and SUCCESSIVE_DIALOG_TIME_LIMIT (3, units are seconds). nsGlobalWindow.cpp keeps a count (mDialogAbuseCount). Apparently, the dialogDuration function either increments or clears mDialogAbuseCount depending on whether the dialog has been open longer than the SUCCESSIVE_DIALOG_TIME_LIMIT. The AreDialogsBlocked function uses the mDialogAbuseCount (in part) to decide whether they're blocked.
So in short: If you're repeatedly opening pop-ups and then closing them within three seconds, after 10 or so you'll trigger something.