right now I have totally no idea what could cause this strange bug and I hope to able to describe it as good as possible, but the code has grown big and to post all of it wont result in a clear question.
1. Setup:
A Box2dWeb animation in the background, where the triggering of the Step() method is done by window.requestAnimationFrame following the game loop implementation here in the »That's it« section. Every time the »draw« method is called, the b2body's transformation is handed over to a <div> and to a <g>. The <div> sets up the desired animation and the <g> acts as monitor of the body and resides into an inline <svg>.
Clicks are globally caught and if the user clicks on the <div> or on the <path> the target gains focus what leads to applying forces on the b2body.
2. Bug:
All in all everything works as expected, the animation runs fluid for the <div> and its corresponding <g>, clicking on both, the focus state changes correctly, BUT in chromium and Safari the <g> stops showing up the animation, when the user clicked on the <g>.
Here is the code that is used to set the transformation from the b2Body to the <g>:
function draw(){
var str = this._sprite.transform;
var mtrs = this._transformItem.matrix;
mtrs.a = str.a1;
mtrs.c = str.a2;
mtrs.e = str.a3;
mtrs.b = str.b1;
mtrs.d = str.b2;
mtrs.f = str.b3;
this._transformItem.setMatrix( mtrs );
}
where this._transformItem points to <g>.transform.baseVal.getItem( 0 ) and this._sprite.transform to a transform matrix of custom typ.
Here is the code to catch the clicks:
function getClickTargets( target ){
var targets = { 'sprite' : null, 'link' : null };
while( target ){
if( target.nodeName.toLowerCase() === 'a' &&
targets.link == null ){
targets.link = target;
}
if( target.hasAttribute &&
target.hasAttribute( 'data-sprite-id' ) &&
targets.sprite == null ){
targets.sprite = this._stage.getSpriteById(
target.getAttribute( 'data-sprite-id' ) );
}
if( target.nodeName.toLowerCase() == 'path' ){
var attr = target.getAttributeNS( NS, 'monitor-for-sprite' );
if( attr != '' ){
targets.sprite = this._stage.getSpriteById( attr );
}
}
if( targets.link != null && target.sprite != null ){
break;
}
target = target.parentNode;
}
return targets;
};
In FF, IE9/10, Chrome and Opera everything runs as it should and the only thing that causes the misbehavior is that a »click« happens with a <path> as target. The matrices a correct because the animation keeps on running correct for the <div>.
What could cause this, where should I search, does anybody has an idea or had a similar bug?
EDIT:
Might this be caused by the fact that the events are caught and processed »asynchronously« to the overall running »update ticks« ?
Edit 2:
I noticed that the same problem occurs if I am starting the web inspector and watch the elements, but than all <g> elements freeze.
Edit 3:
I have got it running now, at least in chromium, but I guess Safari will do it also. I slightly changed the »draw« function to this:
function(){
var str = this._sprite.transform;
var mtrs = this._transformItem.matrix;
mtrs.a = str.a1;
mtrs.c = str.a2;
mtrs.e = str.a3;
mtrs.b = str.b1;
mtrs.d = str.b2;
mtrs.f = str.b3;
//this._transformItem.setMatrix( mtrs ); //old line
this._transformList.replaceItem(
this._transformList.createSVGTransformFromMatrix( mtrs ), 0 ); //new working line
}
If somebody knows why it only works with a new »SVGTransform« it would be nice to let me know. Otherwise I assume that this is a kind of bug.
Related
I'm trying to insert images into Google Docs (other GSuite apps later) from an Add-On. I've succeeded in fetching the image and inserting it when getCursor() returns a valid Position. When there is a selection (instead of a Cursor), I can succeed if it's text that's selected by walking up to the Parent of the selected text and inserting the image at the start of the paragraph (not perfect, but OK).
UPDATE: It seems that I was using a deprecated method (getSelectedElements()), but that didn't fix the issue. It seems the issue is only with wrapped images as well (I didn't realize that the type of the object changed when you changed it to a wrapped text).
However, when an wrapped-text Image (presumably a PositionedImage) is highlighted (with the rotate and resize handles visible in blue), both getSelection() and getCursor() return null. This is a problem as I would like to be able to get that image and replace it with the one I'm inserting.
Here's my code... any help would be great.
var response = UrlFetchApp.fetch(imageTokenURL);
var selection = DocumentApp.getActiveDocument().getSelection();
if (selection)
{
Logger.log("Got Selection");
var replaced = false;
var elements = selection.getRangeElements();
if (elements.length === 1
&& elements[0].getElement().getType() === DocumentApp.ElementType.INLINE_IMAGE)
{
//replace the URL -- this never happens
}
//otherwise, we take the first element and work from there:
var firstElem = elements[0].getElement();
Logger.log("First Element Type = " + firstElem.getType());
if (firstElem.getType() == DocumentApp.ElementType.PARAGRAPH)
{
var newImage = firstElem.asParagraph().insertInlineImage(0, response);
newImage.setHeight(200);
newImage.setWidth(200);
}
else if (firstElem.getType() == DocumentApp.ElementType.TEXT)
{
var p = firstElem.getParent();
if (p.getType() == DocumentApp.ElementType.PARAGRAPH)
{
var index = p.asParagraph().getChildIndex(firstElem);
var newImage = p.asParagraph().insertInlineImage(index, response);
newImage.setHeight(200);
newImage.setWidth(200);
}
}
} else {
Logger.log("Checking Cursor");
var cursor = DocumentApp.getActiveDocument().getCursor();
if (cursor)
{
Logger.log("Got Cursor: " + cursor);
var newImage = cursor.insertInlineImage(response);
var p = cursor.getElement();
var size=200;
newImage.setHeight(size);
newImage.setWidth(size);
}
}
You are using the deprecated 'getSelectedElements()' method of the Range class. You may notice it's crossed out in the autocomplete selection box.
Instead, use the 'getRangeElements()' method. After selecting the image in the doc, the code below worked for me:
var range = doc.getSelection();
var element = range.getRangeElements()[0].getElement();
Logger.log(element.getType() == DocumentApp.ElementType.INLINE_IMAGE); //logs 'true'
I have been looking into this issue for a few hours now and I can't find a way to fix it. I am using ckeditor 4.3(also try 4.5) with a custom colour picker to change font colour.
All work well in chrome, firefox, opera and safari yet not in IE. The problem come from
editor.getSelection().getRanges()[0].startContainer
which gave me a span in chrome which is what I want and p in IE which is one level high.
Here a litle exemple :
_me.editor.focus();
var range = _me.editor.getSelection().getRanges()[0];
AddLinkColor(range.startContainer, value.Value);
var AddLinkColor = function (element, color)
{
var selectedChild = null;
if (element.getChildren) { selectedChild = element.getChildren(); }
if (selectedChild)
{
if (selectedChild.count)
{
for (var i = 0; i < selectedChild.count() ; i++)
{
var childElement = selectedChild.getItem(i);
if (childElement.getStyle && childElement.getStyle('color') != '' && childElement.getStyle('color') != color) childElement.setStyle('color',` color);
if (childElement.getChildCount && childElement.getChildCount() > 0) AddLinkColor(childElement, color);
if (element.$.tagName == 'A') element.setStyle('color', color);
}
}
}
};
Any other face the same issue?
I have tried all the variant of startContainer that gave a dom element, like commonAncestor and such still same problem.
Selection behaves differently in different browsers, because there's no specification as well as the platforms behave differently in general. As long as the results reflect the real position of the selection everything is fine. That's nothing surprising and nothing to worry about. The only problem is that you need to handle all those different selections and this makes creating an editor so hard. Therefore, CKEditor API contains many tools to simplify this job.
Yea I was afraid so, thanks, made a litle fix not quite sexy but it work
if(element.getName() != "span") { selectedChild = element.getChildren().getItem(0).getChildren(); }
else { selectedChild = element.getChildren(); }
I wan't to cull all animations that are not visible to the user. I have tried a crude way where I simply do not call AnimationController.update() if the animated object is not visible. This does not work as I wan't though. Since when a culled object comes back into view it will play the last applied animation (even ones that I applied when they where culled) This is as expected I guess. Animations still needs to be applied to culled object as they might come into view halfway through an animation for example.
I am now looking at subclassing AnimationController, and change the update() method to take into consideration if the object is culled or not. If it is I wan't to only update the "time" and not do any "heavy" operations at all.
My problem is that I am not sure what are the heavy parts an what is the bare minimum I need to update/advance. So I was hoping someone with more insight to the AnimationController class could help me out a bit? Any help welcome, thanks!
/** Update any animations currently being played.
* #param delta The time elapsed since last update, change this to alter the overall speed (can be negative). */
public void update (float delta) {
if (paused) return;
if (previous != null && ((transitionCurrentTime += delta) >= transitionTargetTime)) {
removeAnimation(previous.animation);
justChangedAnimation = true;
animationPool.free(previous);
previous = null;
}
if (justChangedAnimation) {
target.calculateTransforms();
justChangedAnimation = false;
}
if (current == null || current.loopCount == 0 || current.animation == null) return;
justChangedAnimation = false;
updating = true;
final float remain = current.update(delta);
if (remain != 0f && queued != null) {
inAction = false;
animate(queued, queuedTransitionTime);
queued = null;
updating = false;
update(remain);
return;
}
if (previous != null)
applyAnimations(previous.animation, previous.offset + previous.time, current.animation, current.offset + current.time,
transitionCurrentTime / transitionTargetTime);
else
applyAnimation(current.animation, current.offset + current.time);
updating = false;
}
I was hoping I could do something like only advance transitionCurrentTime, remain and current.time when culled...?
I'm trying to determine with Javascript if anything is selected within the CKEditor. I wish there was a bool like editor.hasSelection(). I started out using editor.getSelection().getSelectedText() === "", but if an element with no "text" is selected (like an img) then that will be a blank string, giving me a false negative. I also looked into editor.getSelection().getSelectedElement(), but that gives null if more than one element is selected.
Is there anything that does this that I'm not seeing in the API?
Looks to me as though there is nothing in the CKEditor selection API to do this directly. However, I think the following will do it, although I agree that it's a shame (and surprising) there is no equivalent of the isCollapsed property of the native browser Selection object.
This is untested but looks as though it will work:
function hasSelection(editor) {
var sel = editor.getSelection();
var ranges = sel.getRanges();
for (var i = 0, len = ranges.length; i < len; ++i) {
if (!ranges[i].collapsed) {
return true;
}
}
return false;
}
// Example:
alert( hasSelection(editor) );
Anybody know where I can find a table of browsers and whether or not they support CSS3 animations and keyframes? Thanks
Can I Use is the place for all of this sort of thing, regularly updated, and always accurate!
http://caniuse.com/css-animation
They were implemented on these dates:
Safari 4.0: 11/06/2008
Chrome 1.0: 02/09/2008
Firefox 5: 20/04/2011
IE 10: 09/2011
They became part of the spec in 2009: http://www.w3.org/TR/css3-animations/
For more info, checkout http://css3.bradshawenterprises.com/support/ and http://css3.bradshawenterprises.com/animations/
I'm going this way. Instead of looking for the browser, I'm looking at feature detection. This nifty write-up will save me some work. So, I'm copying the code, you figure out what it all means :-).
/* Check if the Animation feature exists */
if(hasAnimation())
{
alert("Has!");
return;
}
function hasAnimation()
{
var elm = document.getElementById( 'imgDiv' )
animationstring = 'animation',
keyframeprefix = '',
domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
pfx = '';
if( elm.style.animationName === undefined )
{
var animation = false;
for( var i = 0; i < domPrefixes.length; i++ )
{
if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined )
{
pfx = domPrefixes[ i ];
animationstring = pfx + 'Animation';
keyframeprefix = '-' + pfx.toLowerCase() + '-';
animation = true;
break;
}
}
if( animation === false ) // animate in JavaScript fallback
return false;
}
/* Create animationstring */
elm.style[ animationstring ] = 'rotate 1s linear infinite';
var keyframes = '#' + keyframeprefix + 'keyframes rotate { '+
'from {' + keyframeprefix + 'transform:rotate( 0deg ) }'+
'to {' + keyframeprefix + 'transform:rotate( 360deg ) }'+
'}';
/* Add rule to stylesheet */
if( document.styleSheets && document.styleSheets.length )
{
document.styleSheets[0].insertRule( keyframes, 0 );
return true;
}
/* If there is no stylesheet, add rule to header */
var s = document.createElement( 'style' );
s.innerHTML = keyframes;
document.getElementsByTagName( 'head' )[ 0 ].appendChild( s );
return true;
}
Update: I've rewritten the code for clarity. Also the 'elm' element wasn't defined. The original demo code is here.
EDIT: I apologize to everyone for recommending a W3Schools link, I will NEVER do it again.
W3Schools usually has these types of table and information, check out this link.
It looks like as of now, the following browsers support CSS animations:
Firefox
Chrome
Safari
And, the ones left, which don't currently support it are:
IE
Opera