So the first thing I did was consider methods in which I can tell if javascript is turned off. I thought about embedding an image in the html "noscript" tags but then I wouldn't have any views to base it off of. I eventually decided to embed an image on a page, which upon loading, would activate some AJAX to record that javascript is turned on. This way, even if the javascript didn't load, I could still tell if someone visited the page. After that I questioned how many people actually had images turned on, so I ended up making that part of my analysis.
I'm not going to post the javascript, because it's just a simple AJAX function that sends the users IP to the PHP program which then checks it against the database.
More interestingly, this is what my HTML was:
Unfortunately, posting HTML doesn't provide any neat colorful syntax highlighting (it might if I used a different program). So in this I execute a function called "js_perc" when my image is finished loading. On the page, which is in PHP, I have add the users IP to the database if it doesn't already exist. Before my image can finish loading the PHP that generates the image finds that users IP to the database and logs him as having images on. Once the image loads it executes my javascript function which uses AJAX to contact the PHP script with the users IP and the PHP script logs that user as having Javascript enabled! Simple enough!
Truth be told most of the fun in this script is in the section that displays the statistics. I tried developing methods that would be able to compare multiple components at once. For example, say I wanted to compare people with images on, and people with images off. Now, out of those people with images on, I want to compare how many had JS on as well! This is a bad example because anyone with images off wouldn't be recorded as having javascript on as is the nature of the logging script. However, it gets more interesting when you factor in browers, operating systems, and pages visited.
This is my huge mess of a function that I didn't get around to optimizing:
// hs = haystack, ft = key value(s) to check, exp_val value(s) that ft is checked against,
rcount tells it whether to take count of values with the same key (that is all it will do),
$key = key to return;
function get_vals($hs, $ft = false, $exp_val = false, $rcount = true, $key = false){
$narr = array();
foreach($hs as $hsk => $v){
if(is_array($ft)){
for($n=0, $r=true; $n < count($ft); $n++){
if($v[$ft[$n]] != $exp_val[$n]){$r = false; break;}
else{ $r = true;}
}
}
elseif($v[$ft] == $exp_val){$r = true;}
elseif(!$ft && !$exp_val){$r = true;}
else{$r = false;}
if($key){$hsk = $v[$key];}
elseif($rcount && !is_array($v)){$hsk = $v;}
if($narr[$hsk] > 0 && $r && $rcount){$narr[$hsk]++;}
elseif($r && $rcount){$narr[$hsk] = 1;}
elseif($r){ $narr[] = $hsk; }
}
if($rcount){arsort($narr);}
return $narr;
}
Gah! How many lines of code did I just post? 24? Oh well, this function is recursive! So it would be much longer if I hadn't made it so. I haven't seen this function in well over a month, so dissecting it is only a little easier for me than it is for you. It can do multiple things, first it can aggregate data of the same type into one array key. That way I can get a sample of what the most blocked pages are and what not. The other thing it can do is take an array and isolate the keys you want, based on their values, into a new array. It can do this with multiple keys! It is amazing!
Using this I can do things like this! (where $vis is a huge array where every visitor has an array of their own and in that array is information collected on them)
$pages = get_vals($vis, array('js', 'img'), array(1,1), true, 'page');
echo "|h4>Most blocked pages - IMG on && JS off|/h4>";
echo "|ol>";
foreach($pages as $page => $num){
echo "|li>".$page." => ".$num."|/li>";
}
echo "|/ol>";
And get results like this!
Most blocked pages - IMG on && JS off
- /index.php => 1945
- /gallery/index.php => 668
- /404.php => 120
- /gallery/lb/index.php => 18
- /hire/index.php => 3
Check out more examples here: http://saurdo.com/js_perc_stats.php
That one function can provide me with any statistic I wish! What I was planning to develop from there was a way to send requests to the function without having to edit the PHP each time, in other words I wanted to make an HTML interface. I probably won't get around to that unless someone decides they really want it and are willing to pay for it.
Give it a click:
as dignissim, justo malesuada placerat porttitor, eros libero rutrum ante, eget faucibsequat. Fusce fermentum, nisi nec porttitor interdum, mauris ipsum porta diam, non tempor velit tellus vel ante. Aliquam felis diam, aliquet u
t vestibulum pharetra, suscipit ac velit. Ut vel lectus sem. Ut pulvinar, sem id luctus luctus, tellus I tried resizing live while you were dragging the image but as the image moved around as well as text that the image size affected it proved difficult to keep track of the size of the image. So I made it stationary! In my final version you can preserve the image's ratio With a press of the "Shift" key.
The ability to determine the proper height or width based on the distance of the mouse from the corner of the image took a bit of work because I did not want to resize the image to the right if it would create a horizontal scroll. So I had to find a way to resize the image while preserving the location of its right most corner.
What it would be originally:
mouseposY = ie ? (document.documentElement.scrollTop+e.clientY) : (window.pageYOffset+e.clientY);
mouseposX = ie ? (document.documentElement.scrollLeft+e.clientX) : (window.pageXOffset+e.clientX);
new_img.height = (mouseposY - rez_div.offsetTop);
new_img.width = (mouseposX - new_img.offsetLeft);
First I had to determine the mouse position and then just subtract the location of the image from that.
What resizing to the left looks like:
new_img.height = (mouseposY - rez_div.offsetTop);
// wherever the rezbox is plus its width gets the right corner of it minus the mouse position gets how far you are from that position
new_img.width = (rez_div.offsetLeft + mxwidth - mouseposX);
// manually setting the image location, rezbox plus its width minus however big the image already is
new_img.style.left = rez_div.offsetLeft + mxwidth - new_img.width+'px';
The height is the same because resizing to the left or right doesn't affect that. However, to resize to the left I first had to determine where the right corner of my resizing box was and then determine how far away my mouse was from that. Then, on top of all that, I had to shift my image so it wouldn't change position while resizing. To achieve this I took the location of my resizing box plus the width of the resizing box, to get the right corner, and then subtract however wide I just made the image.
One thing that really slowed me down is that offsetLeft doesn't really mean offsetLeft, it's in fact, meaningless. So I had to create my own function to find the offset of an object.
Finding the true offset function:
// ob is object to get offset of, type is top or left: left = 0 top = 1
function realOffset(ob, type){
if(type == 0){
offLeft = ob.offsetLeft;
//alert(ob.nodeName+' - '+ob.offsetLeft);
while(ob != document.body){
ob = ob.offsetParent;
offLeft += ob.offsetLeft;
//alert(ob.nodeName+' - '+ob.offsetLeft);
}
return offLeft;
}
else{
offTop = ob.offsetTop;
while(ob != document.body){
ob = ob.offsetParent;
offTop += ob.offsetTop
}
return offTop;
}
return false;
}
The type variable determines wether to find the offset left or offset top. To find the real offset you have to go through every parent object and find the offset of that. Luckily, there's something called "offsetParent" that makes this process a little less painful.
So, I got all that working. Last thing I need to do is stick it in the vbulletin plugin system and everything should work, right? Well, works in Chrome, Firefox, Opera, Safari, and every other browser. Excluding, of course IE. As unsurprising as this may be to some it came as a complete surprise to me. I tested this in IE 8-5 and it worked flawlessly. Somehow the act of putting it on a forum breaks it. The strange thing is that the thing that seems to break it is the fact that IE isn't returning an image width or height. No image width at all. So the only thing I could come up with is to see if the script was somehow executing before IE was able to determine its width or height. No luck, so I tried using some other attribute to determine its width and height. ClientWidth and ClientHeight perhaps? Nope. Nor did any of the other ones work. I spent a great deal of time on this. What was so special about VBulletin that it broke my script in IE and how can I simulate this?
After a while of tinkering with that I realized that I'd like this script on every website. I was tired of huge images I had to scroll past. So that was the answer to my IE problem. To forget about it completely and instead make a Chrome extension, which proved incredibly easy. Somehow Google made creating extensions in Chrome near effortless, an extension can be made entirely in javascript and to load it into chrome all you have to do is make a tiny little file that tells chrome what to do with it.
Here's my little file:
{
"name": " Resizer thing",
"version": "1.0",
"description": "The resizer thing I made.",
"content_scripts": [
{
"matches": ["http://*/*"],
"css": ["css.css"],
"js": ["rezbox.js"]
}
]
}
First couple of lines are pretty self explanatory. The whole "content scripts" thing is telling chrome where my files are and what I want to do with them. Basically, I tell it to match every possible url (starting with http) and then include a css style file and my javascript to resize images. To automatically resize images I wait until the page loads and then I run through every image on the page.
onload = function(){
for(i in document.images){
poo(document.images[i]);
}
}
mh = window.innerHeight;
mw = window.innerWidth;
I installed one such mod to test it out. The mod resized images to a size determined by a size set in the admin control panel. It then wrapped some tags around that image and made it into a highslide type link where you could view the full size in a highslide popup. The problem with this is that it not only destroyed any tags that were already surrounding it but it also destroyed the way images behave with text. For example, I could embed an image right here
and while it may exceed my line height it does not break the text onto new lines. This behavior and the use of any existing tags (such as anchors) is something I wanted to preserve.
I tried a number of different methods to create such a system. Perhaps my most successful one was a system where a double click would resize the image but a single click would follow any existing links. This worked for the most part but browsers kept blocking my links as popups because I had to set it on a timer and because I wanted them to open in a new window/tab. The images needed both a click and a double click event trigger but the click event trigger doesn't wait to see if the click is actually part of a double click. So you can imagine the kind of hackiness that was used in this method.
After that I moved onto some other project. I made the mod that resized the images, even implementing a method for users to set their own custom size, but they were not able to resize them back to their original size. Now, 4 months later, I came up with the idea to make a context menu for each image. That way a menu can popup and you can either choose to resize the image or follow the link. Then I made it!
and I have proof!
consectetur adipiscing elit. Quisque tincidunt sagittis mi
sit amet pellentesque. Nulla tristique ligula eget augue lobortis porttitoreget nec lacus. Etiam porta mauris sit amet felis suscipit eu mattis neque ullamcorper. Suspendisse ut enim vitae nisi gravida rhoncus. Sed at diam ut elit
molestie commodo.
Go on, click them! Neat huh? You can already guess what the "custom resize" button is for. I still have no idea how I am going to implement that. I already looked into the resize function that comes with jqeury but I found it to be extremely laggy when used on images, especially images with lots of pixels. I might either have to get inventive or go the simple route and just create a little popup where you can enter the dimensions yourself. One thing that really slowed me down was compatibility problems with both Firefox and IE. I pretty much developed the entire thing in Chrome. The Firefox bugs were fairly easy to flush out but getting the mouse position in IE took me about 15 more minutes than it should have!
The culprit:
// set menu position to where mouse is
div.style.top = /*@cc_on!@*/false ? (document.documentElement.scrollTop+e.clientY)+'px' : (window.pageYOffset+e.clientY)+'px';
div.style.left = /*@cc_on!@*/false ? (document.documentElement.scrollLeft+e.clientX + 15)+'px' : (window.pageXOffset+e.clientX + 15)+'px';
I realized that IE uses different functions to find the scroll position of the page, document.body.scrollTop, but what I did not realize is that they changed when you added a doctype. What is the reason for this?! Internet explorer was behaving up to this point. I finally found the answer on stack overflow, thankfully.
Once I figure out how to go about the custom resize thing I will try to put it on a live forum and then maybe release it as a mod for everyone else to use.