Detect scrollbar appear/dissapear in the Grid - actionscript-3

I have a Grid component and it's verticalScrollPolicy is set to "auto".
And every time when verticalScrollBar appears or disappears, I want to handle this event.
I tried to listen to the RESIZE event:
private function onGridResize(event:Event):void
{
if (_grid.verticalScrollBar && _grid.verticalScrollBar.visible)
{
trace("scroll on");
}
else
{
trace("scroll off");
}
}
but it does not work: it seems to me, that RESIZE event actually dispatches before grid visual update and scrollbar appear/disappear.
I tried to listen ChildExistenceChangedEvent.CHILD_ADD and ChildExistenceChangedEvent.CHILD_REMOVE events as well, but it doesn't work for me too.
Maybe I just don't see some obvious solution.
Thanks in advance for any help or advise.

You do not specify which grid. (Spark, MX, or one of ours (http://www.flexicious.com/Home/Ultimate) )
One thing you could do is throw a validateNow prior to checking:
private function onGridResize(event:Event):void
{
_grid.validateNow(); //add this.
if (_grid.verticalScrollBar && _grid.verticalScrollBar.visible)
{
trace("scroll on");
}
else
{
trace("scroll off");
}
}
The other thing you could also do, is use a timer or call later.
private function onGridResize(event:Event):void
{
callLater(checkForScrollBar); //check for scrollbar would have the code above.
}

Perhaps you can listen for the "show" event of the ScrollBar itself. Something along the lines of this should work:
_grid.verticalScrollBar.addEventListener(ComponentEvent.SHOW, onGridResize);
I haven't tested this, but I'm pretty sure it should work. (Of course, you may want to rename onGridResize to something more suitable like onVerticalScrollShow.)
By the way, you don't have to check that the ScrollBar exists; in pure AS3 at least, they are instantiated along with the DataGrid and exist regardless of their ScrollPolicy value.
The reason the resize event appears to fire right away is because it is dispatched as soon as its dimensions change. I'm assuming that in your application, the user drags to manually adjust the grid's size, and thus the events fires as soon as any adjustment is made.

Related

addEventListener not working when menu buttons removed *Fixed*

In my main I have a menu of buttons, and a map added which is a class of it's own, I wanted it so that when I click on a "view map" button, it would remove the buttons so the map could be viewed, problem is when the specific button is removed it seems to stop the event listener working.
Here's the code, I've tried to chop it down as much as I can just to show you the part that's the problem.
public function Main () {
drawButtons(); // draws all the buttons and adds them to the buttonList array
// the buttons are all made from a "ButtonClass".
addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
public function onMouseUp(Event:MouseEvent):void {
else if (Event.target.name == "viewMapB") {
// imagine removeChild(buttonList[1-8]) commands here.
removeChild(buttonList[9]); // when this is removed, eventlistener wont work
stage.addEventListener(KeyboardEvent.KEY_UP, keyPressedUp);
stage.focus = stage; // This line fixed the problem
}
}
private function keyPressedUp(event:KeyboardEvent):void {
trace("ping");
// goneBack("main"); // brings back the menu that was removed
}
experimenting seems to show that it's only when I remove buttonList[9] that this problem arises, but all the work arounds I could think of so far refuse to work.
Edit 1: to show where the mouseEvent comes from.
Edit 2: Attempted adding stage.addeventlistenever to main as well. No luck, but found that after clicking on the button, if I click again afterwards (the map covers the whole stage area), the eventlistener works again. Now trying to figure out why that is...
Edit 3: Seemed the problem had something to do with focus. Adding "stage.focus = stage;" in after the KEY_UP event listener seems to have fixed it. Learn something everyday! Also thank you to those who helped solve this weird problem.

Get div to ignore everything but single clicks

I have a map, which has about 3-5 divs on it. When someone clicks a div, it flips and a text appears on the back of the div. But if someone has the curser on a div and scrolls, the map should behave like it always does and zoom.
I found this in another question: http://jsfiddle.net/ZqfTX/. Is there a way to say
dblclick: function(){$(this).[IGNORE]} ?
My idea is only an idea. If you have another way to do it, even better.
This should take care of what you want. Here is an updated jsFiddle which sets a timeout and prevents a double click from occurring. You can set whatever amount of time you want before a second single click is allowed. It also detects the scroll of the mouse wheel and alerts up or down based on the direction of the scroll.
From your OP and comments, I believe this should accomplish everything you were asking. As far as the animation of your div, I don't know what you are doing with it so that part would need to be changed to do what you want.
The code snippet below was found and modified from this other SO post and many thanks to that poster: How to disable double clicks or timeout clicks with jQuery?
Preventing Double Click
jQuery('.flip').click(function() {
var $this = jQuery(this);
if ($this.data('activated')) return false; // Pending, return
$this.data('activated', true);
setTimeout(function() {
$this.data('activated', false)
}, 1500); // Time to wait until next click can occur
doFlip(); // Call whatever function you want
return false;
});
function doFlip() {
if ($('.flip').find('.card').hasClass('flipped')) {
$('.flip').find('.card').removeClass('flipped');
} else {
$('.flip').find('.card').addClass('flipped');
}
}
On a side note, if you do not want the user to have the ability to even single click the div a second time, take a look at jQuery's .one() event handler attachment as it only allows execution once per element. Not sure if you want to have the ability to click it a second time but figured I'd throw it out there just in case.
If you want to prevent double click, you can try to use event.preventDefault
$(".yourClass").dblclick(function (e) {
e.preventDefault();
});
Looks like you'll have to bind event handlers for the events you want to pass through to the map and perform the zooming actions manually. This might help:
https://code.google.com/p/jquery-ui-map/

How to know if a popup is already showing up on the screen in flex

I need to know if a popup (which is a singleton titlewindow, hence would be initialized only once) is already shown in the screen or not, if not then i will call a function to show it up, otherwise do something else.
I tried findPopup.focusEnabled //findPopup is the titlewindow class for popup
But it is always true irrespective of whether the popup is shown in the screen currently or not.
Thanks.
Use isPopUp
Set to true by the PopUpManager to indicate that component has been
popped up.
All objects rendered on the screen have a root:DisplayObject property. If it is removed from the screen, then root will be null. If your concern is whether the pop-up is in front of everything else, then use popUpObj.parent.setChildIndex(popUpObj, popUpObj.parent.numChildren - 1) to ensure it (more on this below). You will need to iterate through all of the parent until you reach the root itself. (With the PopUpManager, I believe that the MovieClip is added directly to the root, so it should only be once, but I don't recall at the moment)
Everything else is obvious:
is alpha = 1?
visible = true?
is width > 5
is height > 5
... I could continue, but I think the idea is pretty clear.
On testing visibility of obscured objects:
Honestly, this is easiest to do on the root.
var firstParent:DisplayObjectContainer = /*
find the ancestor which is on
the root. You may need to look up
"path to root AS3"
*/
var num:int = root.numChildren;
//iterate backwards to exclude things below the target clip.
for( var i:int = num - 1; i >= 0; i-- )
{
var kid:DisplayObject = root.getChildAt( i );
if( kid == firstParent ) break; // no sense in continuing.
if( firstParent.hitTestObject( kid ) )
{
// kid at least partially obscures the pop-up. Do something with it.
}
}
You can check if the object exists with an if block
if(findPopup)
findPopUp.visible=true;
assuming you turned of the visibility off to hide the window. You can of course destroy the object and recreate it if desired. In this case, you don't need that if block because it'll be reconstructed from scratch.
You can still use that if logic to be sure if somewhere in your code, something has already created your popup object. Maybe another class will be doing that behind the scenes so the basic idea is to guarantee that such object exists or not.
[Edit:]
Didn't know you were using PopUpManager. Please use Ranhiru Cooray's answer.
A reminder that PopUpManager has it's own method to put a pop up in front of all other objects: bringToFront(popup)
[/Edit]
Are you trying to find out if the pop up has been added to the stage or if it is still actually visible on the screen and not hidden behind other display objects ?
If it's the first, you could find out with a search (flex 3)
// popUpContainer is the object containing the pop up
if (popUpContainer.contains(FindPopup.getInstance()))
{
// The popup was added to stage
}
else
{
popUpContainer.addChild(FindPopup.getInstance());
}
If it's the second, you could make sure it is visible by adding it to the application root and making sure it has the highest index. But it's hard to test if it's actually being shown on the screen, since it could be 40% or 60% hidden behind other objects.
// Placing the pop up on top of other display objects in the application root
this.setChildIndex(FindPopup.getInstance(), this.numChildren - 1);

Clicking Text Element in Tween Halts Animation

I've been having some trouble with tweens. Here's a description of my usage:
I have a system where a textbox is the child of a movieclip. When you click the "Next" button, the movieclip fades to 0-alpha and upon completion, the text in the textbox is changed (to the next index in an array) and it tweens back in to 100-alpha. This makes a nice transition through the text.
My issue is that sometimes it doesn't tween back in, only out, leaving the user with an empty box where text should be.
However, I'd asked this question previously with the thought that it was "Timing out". Now, after significant testing I realised that it only happens if I click or select some of the text on the text box. Could it have something to do with this text selection intefering with the changeText function below... (it's the same text box, just the text changes).
Has anyone else experienced similar faults?
CODE:
function changeClick(e:MouseEvent):void {
if (e.currentTarget==btnRight) {
newDirect="right";
} else {
newDirect="left";
}
if (newDirect=="right") {
if (pageTotal!=pageCurrent) {
tweenText=new Tween(b_textB,"alpha",Strong.easeOut,1,0,.5,true);
tweenText.addEventListener(TweenEvent.MOTION_FINISH, changeText);
}
} else {
if (pageCurrent!=1) {
tweenText=new Tween(b_textB,"alpha",Strong.easeOut,1,0,.5,true);
tweenText.addEventListener(TweenEvent.MOTION_FINISH, changeText);
}
}
}
function changeText(e:TweenEvent):void {
var newText:String;
var pageCurrentConstant:int=pageCurrent;
if (newDirect=="right") {
for (var i=0; i<=(pageTotal-1); i++) {
if ((pageCurrentConstant-1)==i) {
if (i!=pageTotal-1) {
newText=pageText[i+1];
pageCurrent++;
} else {
newText=pageText[i];
}
}
}
} else {
for (var j=0; j<=pageTotal; j++) {
if (pageCurrentConstant==j) {
if (j!=0) {
newText=pageText[j-2];
pageCurrent--;
} else {
newText=pageText[j];
}
}
}
}
b_textB.htmlText=newText;
tweenText=new Tween(b_textB,"alpha",Strong.easeOut,0,1,.5,true);
drawWidget();
}
changeClick is initiated by either btnRight or btnLeft to navigate through the text
Try disabling the text selection, with b_textB.selectable = false
You will be able to quickly rule out the possibility of a selection issue. But the sometimes in your question strongly indicates that's what the issue is.
If you need the text to be selectable when it's visible, just switch it off and on at the start and end of the tweens.
Hope this solves it.
Oh by the way, here's a list of several completely free alternatives to the Tween class... (Greensock's Tween packages are not free.)
Between AS3
Desuade Motion ... This one in particular is awesome.
Tweener
Tweensy
Twease
Update...
The only way you can solve this and allow the user to select the text, is to make a duplicate textfield that's selectable, and toggle visible off for this when the tween begins and on again when it ends, the alpha property on the effected textfield will then work properly.
Pretty kludgy I know, but it will get the effect to work, and allow the user to select the text when it's visible.
You may also try to wrap the original textfield in a Sprite and do the alpha Tween on that instead, however I don't guarantee that will be a 100% fix.
The standard Tween class is kind of stupid in many situations. When using it, you have to be careful that you don't overwrite or remove its instance, as the Garbage Collection could start then. In the same way it always requires you to specify a start value which can lead to disrupting behaviour in the animation.
I'm not exactly sure what exactly your problem is, and with that less code it is hard to reproduce it (you might want to provide a full working example code if you still experience the problem). However I suggest you to try out a different tweening framework. I for myself have made very good experience with Greensock's TweenLite. It might have a weird syntax (at least I could imagine a better one), but in general it works really well, and I have solved very many problems with the standard Tween class by simply using TweenLite instead.

Removing resize handlers on contentEditable div

I created a contentEditable div to use as a rich textarea. It has resize handlers around it that I'd like to get rid of. Any idea how I'd do this?
Edit: This appears to be happening because I am absolutely positioning the div, so Firefox adds an infuriating _moz_resize attribute to the element which I cannot turn off.
Just as a side note, you can disable Firefox's automatic resize handle feature by sending the (somewhat poorly-documented) enableObjectResizing command to the document:
document.execCommand("enableObjectResizing", false, false);
AFAIK, this can only safely be done once the document has loaded, and there's no way I know of to disable the grabber, which is a separate feature.
It looks like I'll be able to work around this by adding a wrapper div and absolutely positioning the wrapper and then making the inner div contentEditable.
In Chrome 39, these handles don't seem to exist, even if you wanted them to.
In Firefox, one can simply use execCommand, like ZoogieZork answered.
But in Internet Explorer this can't be turned off. It must be worked around.
In WYMeditor development, here's what I've found.
The following results in:
In IE, the resize UI shows up for a split second and then disappears. There seems to be no way for the user to use it.
Images are text selected on mouseup
Ability to drag images. In some browsers, they may have to be selected before dragging. As written in the previous item, a simple mouseup will result in an image being selected.
Images are selected using text selection and not "control selection" (that which provides the resize UI).
This is the best I could come up with after hours of very deep breaths. I think it is good enough if you really want to get rid of those handles.
In IE, Setting oncontrolselect to return false on the image, really does prevent those handles from appearing, and you can do it cleverly, by attaching the following handler to the mousedown event:
function (evt) {
var img;
function returnFalse() {
return false;
}
if (evt.tagName.toLowerCase() === "img") {
img = evt.target;
img.oncontrolselect = returnFalse;
}
}
It actually doesn't work completely well. The reason that it didn't work very well is that in order to begin a drag and drop operation on the image, one had to press and hold the mouse, without moving it, for a split second, and only then begin moving it for the drag. If one pressed the mouse and immediately began dragging, the image would remain in its place and not be dragged.
So I didn't do that.
What I did is the following. In all browsers, I used mouseup to text select the target image exclusively. In non-IE and IE11, synchronously:
function (evt) {
if (evt.target.tagName.toLowerCase() === "img") {
selectSingleNode(img); // In my case, I used Rangy
}
}
In IE 7 through 10, asynchronously:
function (evt) {
if (evt.target.tagName.toLowerCase() !== "img") {
return;
}
window.setTimeout(function () {
selectSingleNode(img); // In my case, I used Rangy
}, 0);
}
This made sure that after those handles show up, they disappear ASAP, because the image loses its "control selection" because that selection is replaced with a regular text selection.
In Internet Explorer 7 through 11, I attached a handler to dragend that removes all selection:
function (evt) {
if (evt.target.tagName.toLowerCase() === "img") {
deselect(); // I use Rangy for this, as well
}
}
This makes the handles that show up after drag and drop, disappear.
I hope this helps and I hope you can make it even better.
I just face that problem.
I tried document.execCommand("enableObjectResizing", false, false); but, the move icon was still appearing. What just fix my problem was just e.preventDefault() when onmousedown event occurs.
element.onmousedown = function(e){
e.preventDefault();
}
for IE11 (I havn't tested the older versions of IE, but I feel like it would work) you can add contenteditable="false" attribute to the img tag. This will prevent any re-sizing from being done while keeping drag and drop in place.
... just the best fix ever
<div contenteditable="true">
<label contenteditable="false"><input/></label>
</div>
or any html element that wraps your input/img
Works on IE11 like a charm
Have you tried adding the style
border: none;
to the div?