Hackintosh + Carbon Copy Cloner = Hackintosh won’t boot

The boot hard drive in my Hackintosh was slowly failing (weird clicking noises, system freezes), so I immediately found another drive and cloned it, thinking I would just be able to swap them out and keep going. Not so. The bios was just stuck at the “Verifying DMI Pool Data……” (whatever that means). It would not boot, even though CCC usually makes bootable copies for normal OSX installs.

After a little searching, I found this forum post, and ignored it, because the guy who tried to help didn’t explain what the problem actually was, and was a bit rude about it.

Instead, (without fear of screwing it up, since it’s just a clone) I mounted the drive on another computer (you can leave it in the same computer and use iBoot if you want) and used MultiBeast to reinstall EasyBeast on the drive. My very limited understanding of how EasyBeast works is that it puts another partition on the drive with the hacked EFI stuff on it, and when I cloned it, that partition was ignored.

When I put it back in the Hackintosh, it booted right into OSX.

FYI, here’s my setup:

  • GA-G31M-ES2L v2.0 Motherboard
  • Intel Core 2 Duo 2.2ghz (overclocked to 2.6)
  • GeForce 8400GS
  • Atheros AR8131 Ethernet
  • Some generic power supply
  • 3TB worth of Sata hard drives (it is a media server after all)

And the steps I used to set it up:

  • Read this awesome blog post from TonyMacX86
  • Boot from burned CD with iBoot and MultiBeast
  • Install 10.6.0 retail
  • Update to 10.6.4, then without rebooting
  • Use MultiBeast to install EasyBeast, run MultiBeast’s permission fix scripts and reboot
  • Kext: VoodooHDA for audio (via MultiBeast)
  • Kext: NVEnabler for video (via MultiBeast)
  • Kext: AtherosL1cEthernet for ethernet (via KextHelper)

Notes:
Use System Utilities each and every time you use MultiBeast, it fixes permissions on the kexts.
I happen to have version 2.0 of the mobo, which has an Atheros ethernet chipset. Most of the others use a Realtec NIC, so don’t go nuts like me trying to make a Realtec NIC work if you don’t even have one.
I got a lot of help figuring out how to do this from InsanelyMac, the OSX86 Project, and their hardware compatability lists.

Use jQuery to attach an event to a key press

Keep in mind that some browsers don’t let jQuery know about certain key presses. For example, Chrome doesn’t send the event for keyCode 27 (escape), but Safari does.

$(document).keypress(function(e) {
	if (e.keyCode == 13) {
		alert("You pressed Enter!");
	}
});

And here’s a list of all the available keyCodes for you to use.

UPDATE: jQuery: Get all objects of selector, and then loop through them

In my original post I mentioned how one can use the get() function in jQuery to gather up all the selected DOM elements and put them in an Array, like so:

var stuffArray = $(".stuff").get();

Well here’s another way to do the same thing:

var stuffArray = $.makeArray($(".stuff"));

And then I showed how to loop through that new array and do something with each of the DOM elements like so:

for (x in stuffArray) {
	stuffArray[x].doSomethingHere();
}

Well there’s another way to do that too:

$.each(stuffArray, function(key, value) {
	value.doSomethingHere();
});

The two variables (key and value in the example) in the each callback function can be called whatever you want, but they represent 1) the array key, or if it’s a numerical array, the index of the entry in the array your each function is working on, and 2) the value at that key/index.

Using PHP to generate your CSS Stylesheets (or .JS files)

So maybe you want to just declare a variable once in PHP at the top of your stylesheet:

$theColor = "#363636";

And then when you need to refer to it a dozen times, spread throughout your stylesheet, you can, and you only have a single value to change if you want to change them all.

#myDiv {
	background-color: <?=$theColor;?>;
}
#myOtherDiv a:hover {
	color: <?=$theColor;?>;
}
#myList li {
	border: 1px solid <?=$theColor;?>;
}

The only problem with this is that the browser can see that it’s not a CSS file it’s getting, so you have to tell it with a header. To do this in PHP you use the header() function.

header('Content-type: text/css');

EDIT: To give javascript files the same treatment, you have to send the Content-Type header “text/js“.

In CodeIgniter, you can make a CSS controller and route, and then you use the set_header() function in your controller:

$this->output->set_header("Content-type: text/css");

In Zend it would be

$this->getResponse()
	->setHeader('Content-type', 'text/css');

CodeIgniter Rejecting Ajax XMLHttpRequest from jQuery?

I have a javascript/jQuery ajax function that tries to post some data to a URL in my CodeIgniter installation, and it fails. Looking at the console it gives me this message

XMLHttpRequest cannot load http://www.DOMAIN.com/chris/calendar/async/update/assignment/325. Origin http://DOMAIN.com is not allowed by Access-Control-Allow-Origin.

The problem is in the headers that CodeIgniter is set up to send by default. The fix is to use CodeIgniter’s Output class to send the Access-Control-Allow-Origin header allowing everything, or *.

Convert Em size to Pixels with jQuery

I was trying to use jQuery-UI’s awesome resizable function on a new web app I’m developing, and it turns out that it doesn’t play nicely with ems. At least it’s grid options don’t. Anyway, I found the need to convert em values to pixel values on the fly. It has to be on-the-fly, because the whole point of using ems is that when the user scales text in the browser, everything em based scales too. So here’s a little javascript/jQuery function I wrote to do the conversion as needed.

function em(input) {
	var emSize = parseFloat($("body").css("font-size"));
	return (emSize * input);
}

parseFloat(), by the way, attempts to convert strings to numbers, even cutting the “px” off “16px” to make 16.

And how I used it:

$(".bar").resizable({ handles: 'e, w', grid: [em(2.5), em(2.5)]});

UPDATE:
And of course, the function to go the other way is:

function px(input) {
	var emSize = parseFloat($("body").css("font-size"));
	return (input / emSize);
}

AS3 Audio loops aren’t quite seamless

Well, actually they are. The problem (in my case) was that the software I used to make the MP3 I was trying to loop added a tiny bit of whitespace to the start of the audio. 83 milliseconds to be exact. It’s a messy workaround, but it seems to be working fine.

Instead of starting the sound over when the SoundChannel throws it’s SOUND_COMPLETE event, I set up a Timer for exactly 83 milliseconds less than the length of the audio, and have the Timer trigger the sound to start over.

function playMusic(e = null) {	
	var musicChannel:SoundChannel;
	
	var music = loadReferenceToMyMP3;
	musicChannel = music.play();
		
	var restartTimer:Timer = new Timer(music.length-83, 1);
	restartTimer.start();
	restartTimer.addEventListener(TimerEvent.TIMER_COMPLETE, playMusic);
}

UPDATE: It seems that different MP3 encoders make MP3s with different amounts of whitespace, but they all add some. To figure out what your number should be (on line 7), you’ll have to either measure the gap in some audio editing software, or just play with it until it sounds right.

jQuery: Get all objects of selector, and then loop through them

There’s a small update to this post here.

One of my favorite code snippets in jQuery is this one. It gathers up a bunch of elements (based on your jQuery selector) and puts them in an array for you to loop through. It’s great for repositioning lots of elements at once, like on a scroll event.

var stuffArray = $(".stuff").get();
for (x in stuffArray) {
	stuffArray[x].doSomethingHere();
}

My personal favorite uses for it is doing the same animation on a dozen objects, but with a slightly longer delay before each. Below, you can see that I’m looping through stuffArray, x is the array index, and the delay before animation is 100 milliseconds times x, so the first one is 0. Makes for a really cool effect on lists and stuff.

var stuffArray = $(".stuff").get();
for (x in stuffArray) {
	stuffArray[x].delay(100*x).animate({height: '100'}, 1000);
}

Detecting Flash Plugin with SWFObject

To detect whether a browser has the flash plugin, first load the SWFObject library, then:


If you don’t have flash, then swfobject.getFlashPlayerVersion().major will return 0, which in an if() statement turns into false.

swfobject.getFlashPlayerVersion().major is the major version
swfobject.getFlashPlayerVersion().minor is the point release
swfobject.getFlashPlayerVersion().release is the build number