So I am having an issue with my event handling in a script I am writing. The entire thing is working fine in chrome, and in safari even though it runs VERY slowly, it still works. In Firefox one of the events is not working at all.
Basically, on page load I am creating a bunch of event listeners:
canvasElem.addEventListener("mousedown",down,false);
canvasElem.addEventListener("mouseup",up,false);
canvasElem.addEventListener("mousemove",move,false);
These event listeners work, of that much I am sure, but one of the event listeners (that calls the down function) stops running part way through because of these two lines of code:
dXImgSpin=(centerXImgSpin-expansionOffsetXImgSpin)-(window.event.clientX);
dYImgSpin=(centerYImgSpin-expansionOffsetYImgSpin)-(window.event.clientY);
Now I understand (kind of understand, I am new to programming so it is still a bit over my head) That this won't work in firefox because I am using the IE DOM model rather then the W3C model, but in another part of the program that I was having issues with, /* event.pageX not working in firefox, but does in Chrome */ I fixed it by adding changing the way the event was handled(aka adding a canvasEleem.addEventListener), and then adding a line of code
event = event || window.event;
and changing the window.event.clientX to just event.clientX. However, when I try to do this in this different function, the above line of code won't even run.
Anything helps, and I am sorry if this question is not well phrased, But I have pretty much hit a wall in my current understanding of javascript, and can't understand how to get past it. If there is any more information that is required, don't hesitate to let me know!
Isaac
The full flow of code for when down is pressed:
canvasElem.addEventListener("mousedown",down,false);
function down(){
mouseDown=1;
getNewAngle();
angleMomentumImgSpin=.005;
}
The getNewAngle() function is the problem:
function getNewAngle(){
dX2ImgSpin=dX1ImgSpin;
dY2ImgSpin=dY1ImgSpin;
dX1ImgSpin=dXImgSpin;
dY1ImgSpin=dYImgSpin;
//THESE ARE THE PART THAT ARE CAUSING THE PROBLEM
dXImgSpin=(centerXImgSpin-expansionOffsetXImgSpin)-(window.event.clientX);
dYImgSpin=(centerYImgSpin-expansionOffsetYImgSpin)-(window.event.clientY);
//This if statement is to avoid the drawing from flipping when the mouse crosses the halfwaypoint
if (dXImgSpin>0){
angleImgSpin=(Math.atan((dYImgSpin/dXImgSpin))-angleStartImgSpin);
}else{angleImgSpin=(Math.atan((dYImgSpin/dXImgSpin))-angleStartImgSpin+(Math.PI))}
//alert(angle);
}
Related
I'm using Openlayers 2 and I'm creating a map app. I'm using apache cordova so it's just javascript/html/css.
It works fine for most cases but when I zoom in and out a bunch of times (with my fingers on a touchscreen) sometimes the scaleline stops updating. Moving the map around and zooming in/out some more usually get's it starting again.
My question is: Is there a way to force the ScaleLine control to redraw (other than moving around the screen and zoom in/out randomly). Like, is there a function I can run on, say, the click of a button to force redrawing?
I've tried
map.Control.Scaleline.update();
map.Control.Scaleline.draw();
But it doesn't work
Thanks!
PS:
I've tried opening the app from chrome on a desktop and since I don't have the touch screen capability there I can't reproduce the error
By looking at OpenLayers.debug.js I could see that scaleline is updated at "moveend" event which is only triggered when touch is completed (which it isn't if the user doesn't let the touch drag finish for example by zooming)
"move" always triggers, so I solved it by triggering "moveend" on "move" event.
map.events.on ({
"move": function () {
map.events.triggerEvent("moveend");
}
}
});
It removes the detail of adding certain events only on "moveend" but it solves the problem. Please comment if you have a better solution!
#atwinther was almost right. The solution is to watch for "touchend" and then send a moveend event. Only the latest browsers support this, however, so it might still be buggy for some people. At the least, according to Mozilla, this should work for the latest Firefox and Chrome: https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent
This is what I did that worked, with non-essential code ellided:
var SYP = {
init: function() {
this.map = new OpenLayers.Map("map");
// workaround for ol2 bug where touch events do not redraw the
// graticule or scaleline
this.map.events.on ({
"touchend": function () {
SYP.map.events.triggerEvent("moveend");
}
});
},
I'm writing a website with a canvas in it. The website has a script that runs successfully on every refresh except for a line at the end. When the script ends with:
document.body.onresize = function() {viewport.resizeCanvas()}
"document.body.onresize" is unchanged. (I double-checked in Chrome's javascript console: Entering "document.body.onresize" returns "undefined".)
However, when the script ends with:
document.body.onresize = function() {viewport.resizeCanvas()}
console.log(document.body.onresize)
"document.body.onresize" does change. The function works exactly as it should.
I can't explain why these two functionally identical pieces of code have different results. Can anyone help?
Edit: As far as I can tell, "document.body" is referring to the correct "document.body". When I call console.log(document.body) just before I assign document.body.onresize, the correct HTML is printed.
Edit 2: A solution (sort of)
When I substituted "window" for "document" the viewport's "resizeCanvas" function was called without fail every time I resized the window.
Why does "window" work while "document" only works if you call "console.log" first? Not a clue.
Resize events: no go
Most browsers don't support resize events on anything other than the window object. According to this page, only Opera supported detecting resizing documents. You can use the test page to quickly test it in multiple browsers. Another source that mentions a resize event on the body element specifically also notes that it doesn't work. If we look at these bug reports for Internet Explorer, we find out that having a resize event fire on arbitrary elements was an Internet Explorer-only feature, since removed.
Object.observe: maybe in the future
A more general method of figuring out changes to properties has been proposed and will most likely be implemented cross-browser: Object.observe(). You can observe any property for changes and run a function when that happens. This way, you can observe the element and when any property changes, such as clientWidth or clientHeight, you will get notified. It currently works only in Chrome with the experimental Javascript flag turned on. Plus, it is buggy. I could only get Chrome to notify me about properties that were changed inside Javascript, not properties that were changed by the browser. Experimental stuff; may or may not work in the future.
Current solution
Currently, you will have to do dirty checking: assign the value of the property that you want to watch to a variable and then check whether it has changed every 100 ms. For example, if you have the following HTML on a page:
<span id="editableSpan" contentEditable>Change me!</span>
And this script:
window.onload = function() {
function watch(obj, prop, func) {
var oldVal = null;
setInterval(function() {
var newVal = obj[prop];
if(oldVal != newVal) {
var oldValArg = oldVal;
oldVal = newVal;
func(newVal, oldValArg);
}
}, 100);
}
var span = document.querySelector('#editableSpan');
// add a watch on the offsetWidth property of the span element
watch(span, "offsetWidth", function(newVal, oldVal) {
console.log("width changed", oldVal, newVal);
});
}
This works similarly to Object.observe and for example the watch function in the AngularJS framework. It's not perfect, because with many such checks you will have a lot of code running every 100 ms. Additionally any action will be delayed 100 ms. You could possibly improve on this by using requestAnimationFrame instead of setInterval. That way, an update will be noticed whenever the browser redraws your webpage.
What you can do is that if you know for certain what particular action triggers a resize on your element that doesn't resize the full window you can trigger a resize event so your browser recalculate all of the divs (if by the case the browser is not triggering the event correctly).
With Jquery:
$(window).trigger('resize');
In the other hand, if you have an action that resizes an element you can always hold from that action to handle other following logic.
<script>
function body_OnResize() {
alert('resize');
}
</script>
<body onresize="body_OnResize()"></body>
I'm developing a plugin for a website building program, and am building the preview page for it. It's sort of a parallax scrolling plugin and the issue I'm having is that in Safari, when you scroll down to a certain point, it wont allow you to scroll any further. It's fine in firefox and chrome, but I saw the same issue in opera. I've managed to narrow it down to the function that's causing it, but I have no idea why or how to fix it.
When I comment out this function, the page scrolls fine, but it doesn't remove the empty divs like I need it to do:
function removeStuff() {
$('.conP').each(function(){
var divDad = $(this),
divses = $(this).children();
if (divses.hasClass('empty'))
divDad.remove();
});
}
here's the preview page where the issue can be observed:
http://reveriesrefined.com/myftp/dack_stev/
//////////EDIT:
I've simplified the code to this:
$('.conP_%id% > .empty').parent().remove();
however, it's still causing scrolling issues in safari and opera, but not the other browsers.
Any help is VERY VERY appreciated!
Actually, I found the issue already. Somehow even though commenting out the function mentioned above seemed to solve it, it was actually a line of code in another function.
I had this function:
function autoPlay() {
var backDiv = $('#outterLax div:first');
backDiv.hide();
$('.conP').hide();
backDiv.remove();
$('#outterLax').append(backDiv);
backDiv.show();
}
but the line:
$('.conP').hide();
was unnecessary as that was already being accomplished elsewhere in my code.
www.warhawkcomputers.com/Birenbaum
This site has various projects for my Computer class that I am in. A check is coming up and all programs will need to work in FF and IE.
My Bouncing Ball, Race Track, and Tanks projects under Third quarter as well as pong under Fourth Quarter work in IE when the objects need to be moved by a continuously adding variable performed in a javascript script, and it works perfectly fine in IE, but when viewed with Firefox 3, the moving objects no longer move and I have tested to find out it gets the variables but seems to only add it once and that the document.getElementById("objectname").style.left = "continuously adding variable" seems to not be executed despite being in a timer running every 10 milliseconds.
Also, none of my keypress code works in Firefox, but I believe that is because I use an outdated method of moving objects via keypress. This is largely due to my teacher's outdated methods.
Thanks for all of your guys's help.
You need to add a 'units' to your positions:
document.getElementById("ball").style.left = x + 'px';
document.getElementById("ball").style.top = y + 'px';
That will work in FF as well now.
Firefox does not use a global event object. They pass an event object into the handler. As a result, you need to modify your Move function:
function Move(e) {
/* snip */
var whichkey = window.event ? window.event.keyCode : e.keyCode;
/* ... */
Gerrat is absolutely correct about the other problem you asked about.
EDIT: this won't work with how you hooked your event handler in the body tag. You need to remove the onkeydown="Move()" attribute from the body tag and add the following code at the top of JavaScript.js:
document.body.onkeydown=Move;
If allowed to do so by your teacher, you would be MUCH better off using jQuery or some other framework.
I'm having problems with debugging DOM changes introduced by some JavaScript code I'm running. Somewhere in the code an element's class is changed, and I'm trying to pinpoint where exactly. Unfortunately, the new class name is so generic that searching through all the JS code gives too many results to be a viable option.
I've tried debugging a bit with Firebug, but despite the nice "Break on Attribute Change" feature, I can't get it to work in a way I would want. The Firebug demo works correctly, but it's a post load situation.
The problem seems to be that I want to watch for mutations before the page is fully loaded. I assume that the changes occur somewhere in $(document).ready(), so it's in the DOM, but I can't select elements for UI breakpoints as would be the case with the demo (after page load).
Is there some way to debug this kind of situation other than grepping/going through the code by hand?
I propose that you remove the target element where its classname is changed. With some luck, you may be able to generate an error in the JavaScript code, so you will find where is your problem.
Otherwise, if it's done by JQuery (addClass), you may want to modify the JQuery code itself just to figure out the callstack.
The code would look like this (make sure this code is the first code called after JQuery inclusion):
(function () {
var addClass = jQuery.fn.addClass;
jQuery.fn.addClass = function (value) {
for (var i = 0, l = this.length; i < l; i++) {
// Here you put your method to start the debugger if you get your right element
if (this[i].id === "abc") {
debugger;
}
}
addClass(value);
}
})();
Hope that helps.
This answer may sound pretty lame, but I honestly think the best solution for bugs like this is "deconstructing" your program. Just make a copy of the entire project, then rip it apart. Take out chunks of code one by one. Turn function calls into stub functions or whatever to keep things running. Find the minimal amount of code that triggers the bug. Then the solution should be obvious.
Have you considered adding a mutation event? The event I think you want, DOMAttrModified, is not supported in webkit, so you might have to test with Firefox or Opera. In fact it is deprecated in DOM level 3.
There are two jQuery plugins for mutation events here (documentation) and here but since you want to do this before page load they might not be the answer.
You are probably best writing your own JavaScript bind for this event - there is an example in the answer to is there an alternative to DOMAttrModified that will work in webkit
I hope this helps.
If you want to use the "Break on Attribute Change" feature to debug, you can do the following:
Comment out all JS in the page (which is hopefully all in the head) except for the base jQuery load.
Load the page and set your watch points.
Add a button, which fires the JS, to the HTML. Or, optionally fire it from the console.
Trigger the JS load/fire. Hopefully your watch and break points will fire as desired.
For example, suppose your page loads/has:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js" type="text/javascript"></script>
<script src="/Library_X.js" type="text/javascript"></script>
<script src="/MyJS.js" type="text/javascript"></script>
Then you could run this code in the console after setting the watch points:
function addJS_Node (text, s_URL)
{
var scriptNode = document.createElement ('script');
scriptNode.type = "text/javascript";
if (text) scriptNode.textContent = text;
if (s_URL) scriptNode.src = s_URL;
document.head.appendChild (scriptNode);
}
addJS_Node (null, '/Library_X.js');
//-- Possible pause here.
addJS_Node (null, '/MyJS.js');
// etc.
Or temporarily code a button that fires the same JS, into the page's HTML.