A very confusing error just now:
error: aggregate ‘std::ofstream out’ has incomplete type and cannot be defined
from simple code:
std::ofstream out;
And the similar one:
error: variable ‘std::ofstream out’ has initialiser but incomplete type
from this code:
std::ofstream out(fname.c_str(),std::ios_base::app);
Using this didn't help:
#include <iostream>
Using this also didn't help:
#include <ofstream>
That was confusing me most, but now I see I've been getting "error: ofstream: No such file or directory" and I was missing it in the noise of other warnings and errors.
The solution was simple:
#include <fstream>
Yes, a very simple solution, but google wasn't helping. If it had been saying "ofstream is not a member of std" I'd have known I was missing a header file; a strange error message has you looking in other places. (I guess another std header file is doing a forward declaration for ofstream, which is why we get "incomplete type".)
Mumble, grumble, back to work.
Sunday, June 6, 2010
Monday, May 31, 2010
Rotating in jquery (firefox problems)
In my entry on rotating images in jquery/javascript I mentioned I'd not had the problem that the unofficial patch was supposed to fix. Well, now I've seen it even using that patch. The problem is this: if you try to rotate an image (in Firefox, at least) that hasn't fully loaded it all goes wrong.
When rotating in Firefox/Safari you are making a copy of the image; the jquery-rotate patch is to make sure your copy has been properly initialized before doing anything with it. My problem was similar: I was trying to rotate an image that hadn't loaded. (Curiously it didn't happen on a 106Kb image, but did consistently on a 69Kb image; the smaller image was in landscape, while the larger image was portrait, but I have no idea if that is related.)
My rotate call is in a function called init(). I first tried calling init() from the image's onLoad(), which worked most of the time. I also tried a more complex solution that involved not calling init() until both the image's onLoad() and JQuery's $(function(){...}); (what I personally like to call onDomLoaded) had both run. But still it happened on certain images, and I now feel that that level of complexity is not needed (also, onDomLoaded always seems to run before the image's onLoad triggers).
So, my solution is this:
Using a time-out of 25ms was not enough, but 40ms seems reliable. The downside is that the image flashes on screen briefly in the original orientation before rotate can kick in. We can fix that by having it invisible initially:
When rotating in Firefox/Safari you are making a copy of the image; the jquery-rotate patch is to make sure your copy has been properly initialized before doing anything with it. My problem was similar: I was trying to rotate an image that hadn't loaded. (Curiously it didn't happen on a 106Kb image, but did consistently on a 69Kb image; the smaller image was in landscape, while the larger image was portrait, but I have no idea if that is related.)
My rotate call is in a function called init(). I first tried calling init() from the image's onLoad(), which worked most of the time. I also tried a more complex solution that involved not calling init() until both the image's onLoad() and JQuery's $(function(){...}); (what I personally like to call onDomLoaded) had both run. But still it happened on certain images, and I now feel that that level of complexity is not needed (also, onDomLoaded always seems to run before the image's onLoad triggers).
So, my solution is this:
<img src="test.jpg" id="img"
onLoad="window.setTimeout('init()',40)">
Using a time-out of 25ms was not enough, but 40ms seems reliable. The downside is that the image flashes on screen briefly in the original orientation before rotate can kick in. We can fix that by having it invisible initially:
<img src="test.jpg" id="img" style="visibility:hidden" onLoad="window.setTimeout('init()',40)"> <script> function init(){ $('#img').rotate(90); $('#img').css('visibility','visible'); } </script>
Labels:
jquery,
web development
Monday, May 24, 2010
Rotating in jquery (and IE8 problems)
Rotating an image in jquery is harder than you might think. Harder than I had imagined it would be, at least. The first problem is that it is not part of either JQuery or JQueryUI, so you are out there in the wilderness where the 3rd party plugins live. And, trust me, it can get wild out there.
I first tried jqueryrotate. It is quite heavy, at around 10KB, but the main reason I abandoned it is that it didn't work properly for me (sorry, I cannot even remember why now).
Next I tried jquery-rotate and I soon got this working in Firefox 3. My code also worked in Safari and Firefox 3.6 first time. IE6/7/8 were the problem. Under the hood all these plugins use DXImageTransform.Microsoft.Matrix for the IE browsers (which works back to IE5 apparently), and Canvas for all other browsers (which works from at least Firefox 3). They even allow rotation of any angle, though I only needed to rotate in steps of 90 degrees.
(By the way jquery-rotate seems to be unmaintained, so I'm using this unofficial patch even though my testing didn't see the problems it fixes.)
Here is my code:
Then:
(To keep that code sample clearer I've hard-coded the sizes, to assume an image that has a 3:4 aspect ratio in its original position). The point of this code is to scale the image down to fit in the layout. This was where the first cross-browser problem appears. When Firefox/Safari rotate it they are creating a new object of the new dimensions. As far as I can tell when IE rotate it they are creating an optical illusion. It appears to have been rotated but when you read its width/height you get the numbers for the original position; and the same when you try to set them. (As an aside I tried a number of ideas to get around this underlying issue, but all ended in failure, so I guess it is just the way IE works.)
Tinaysh... Tenacish... Tenaciousness is my middle name, even if it is hard to spell. This code does the job:
OK, images rotate nicely in all browsers, on to the Next Problem.
I attach a draggable and resizable div (see the demos at http://dcook.org/software/jquery/magnifier/ to get an idea) to the image. I don't want it to leave the image so I use this:
mydiv.draggable({containment:img});
When rotation is 0 or 180 everything is fine, but rotations of 90 and 270 go wrong in IE6/IE7/IE8; it seems the different coordinate system confuse it and I can move mydiv outside the image. (Incidentally jquery's resizable containment is broken, so I had to hand-code that; my resizable containment code is not affected by this problem!)
But things get worse. In IE8 *only*, the rotated image overlaps the following page items; IE6/IE7 correctly push the page down when a landscape image gets rotated to become a portrait image. I could have lived with containment not working, but this one is a showstopper.
We can put the image in a named div, then alter the width/height of that div each time we rotate. So the code ends up as this:
IE8 is still less than ideal. Using #img_outer stops it overlapping with the following content, but it puts hard white space in the area where the image would be if height/width were reversed (and the draggable div can still be dragged into that area). For a landscape image that has been rotated that means whitespace to the right of the image, messing up multi-column table layouts. For a portrait image that has been rotated that means a lump of whitespace between the bottom of the image and the start of the next page content. Using overlap:hidden did not help.
This is very novel: a bug in IE8 that isn't in any other browser, not even IE6! I've not solved this, and welcome advice. Yes, okay, I could use absolute positioning to put a "Download Firefox" icon in that white area, but that isn't quite the advice I'm looking for...
I first tried jqueryrotate. It is quite heavy, at around 10KB, but the main reason I abandoned it is that it didn't work properly for me (sorry, I cannot even remember why now).
Next I tried jquery-rotate and I soon got this working in Firefox 3. My code also worked in Safari and Firefox 3.6 first time. IE6/7/8 were the problem. Under the hood all these plugins use DXImageTransform.Microsoft.Matrix for the IE browsers (which works back to IE5 apparently), and Canvas for all other browsers (which works from at least Firefox 3). They even allow rotation of any angle, though I only needed to rotate in steps of 90 degrees.
(By the way jquery-rotate seems to be unmaintained, so I'm using this unofficial patch even though my testing didn't see the problems it fixes.)
Here is my code:
$('#img').rotate(rotation,true);
Then:
if(rotation==90 || rotation==270){
$('#img').width(300);
$('#img').height(225);
}
else{
$('#img').width(300);
$('#img').height(400);
}
(To keep that code sample clearer I've hard-coded the sizes, to assume an image that has a 3:4 aspect ratio in its original position). The point of this code is to scale the image down to fit in the layout. This was where the first cross-browser problem appears. When Firefox/Safari rotate it they are creating a new object of the new dimensions. As far as I can tell when IE rotate it they are creating an optical illusion. It appears to have been rotated but when you read its width/height you get the numbers for the original position; and the same when you try to set them. (As an aside I tried a number of ideas to get around this underlying issue, but all ended in failure, so I guess it is just the way IE works.)
Tinaysh... Tenacish... Tenaciousness is my middle name, even if it is hard to spell. This code does the job:
if(rotation==90 || rotation==270){
if(document.all && !window.opera){ //IE-specific
$('#img').width(225);
$('#img').height(300);
}
else{
$('#img').width(300);
$('#img').height(225);
}
}
else{
$('#img').width(300);
$('#img').height(400);
}
OK, images rotate nicely in all browsers, on to the Next Problem.
I attach a draggable and resizable div (see the demos at http://dcook.org/software/jquery/magnifier/ to get an idea) to the image. I don't want it to leave the image so I use this:
mydiv.draggable({containment:img});
When rotation is 0 or 180 everything is fine, but rotations of 90 and 270 go wrong in IE6/IE7/IE8; it seems the different coordinate system confuse it and I can move mydiv outside the image. (Incidentally jquery's resizable containment is broken, so I had to hand-code that; my resizable containment code is not affected by this problem!)
But things get worse. In IE8 *only*, the rotated image overlaps the following page items; IE6/IE7 correctly push the page down when a landscape image gets rotated to become a portrait image. I could have lived with containment not working, but this one is a showstopper.
We can put the image in a named div, then alter the width/height of that div each time we rotate. So the code ends up as this:
if(rotation==90 || rotation==270){
if(document.all && !window.opera){ //IE-specific
$('#img').width(225);
$('#img').height(300);
$('#img_outer').width(300);
$('#img_outer').height(225);
}
else{
$('#img').width(300);
$('#img').height(225);
}
}
else{
$('#img').width(300);
$('#img').height(400);
if(document.all && !window.opera){ //IE-specific
$('#img_outer').width(300);
$('#img_outer').height(400);
}
}
You can also fix the other problem by using #img_outer as the containment div, instead of #img. That fixes all problems in IE6/IE7 (though be careful with margins, padding and borders; i.e. make sure #img_outer is exactly the same size as #img).IE8 is still less than ideal. Using #img_outer stops it overlapping with the following content, but it puts hard white space in the area where the image would be if height/width were reversed (and the draggable div can still be dragged into that area). For a landscape image that has been rotated that means whitespace to the right of the image, messing up multi-column table layouts. For a portrait image that has been rotated that means a lump of whitespace between the bottom of the image and the start of the next page content. Using overlap:hidden did not help.
This is very novel: a bug in IE8 that isn't in any other browser, not even IE6! I've not solved this, and welcome advice. Yes, okay, I could use absolute positioning to put a "Download Firefox" icon in that white area, but that isn't quite the advice I'm looking for...
Labels:
jquery,
web development
Thursday, April 29, 2010
Linux keyboard shortcuts
Have you ever gone to hit ctrl-tab (to switch tabs) or ctrl-w (to close current tab) in Firefox and suddenly all your Firefox windows (even the one playing radio on another desktop) disappear? (I'm using Ubuntu and Gnome, but I get the impression this problem affects all Linux distros and all window managers.)
It must be old age making my fingers clumsier but I didn't even know ctrl-q did that until a few weeks ago. Yet I've done it a couple of times by accident recently, and when I did it today I decided Something Has To Be Done.
The solution is not just joyously simple, but I also learnt another cool function while I was there. First the solution: System|Preferences|Keyboard Shortcuts. Assign ctrl-q to do something; then Firefox never gets to see it. I assigned it to the calculator app which is nicely harmless.
I learnt this trick here, which also mentions that the same idea works in XCFE (go to keyboard panel). I'm betting KDE has something similar.
And the cool function? Looking through the other keyboard shortcuts I saw Alt+Print takes a screenshot of just the current window! You have no idea how many times I've clicked Print, then opened up Gimp to crop the screenshot to show just the window of interest. I'm now alternating between feeling very foolish and feeling very empowered.
It must be old age making my fingers clumsier but I didn't even know ctrl-q did that until a few weeks ago. Yet I've done it a couple of times by accident recently, and when I did it today I decided Something Has To Be Done.
The solution is not just joyously simple, but I also learnt another cool function while I was there. First the solution: System|Preferences|Keyboard Shortcuts. Assign ctrl-q to do something; then Firefox never gets to see it. I assigned it to the calculator app which is nicely harmless.
I learnt this trick here, which also mentions that the same idea works in XCFE (go to keyboard panel). I'm betting KDE has something similar.
And the cool function? Looking through the other keyboard shortcuts I saw Alt+Print takes a screenshot of just the current window! You have no idea how many times I've clicked Print, then opened up Gimp to crop the screenshot to show just the window of interest. I'm now alternating between feeling very foolish and feeling very empowered.
Subscribe to:
Posts (Atom)