Mind your JavaScript
Mario Peshev @no_fear_inc
WordPress Engineer #WCNorge
Mario Peshev @no_fear_inc
WordPress Engineer #WCNorge


Open Sourcerer
WordPress Engineer @ Placester
WP Head @ DevriX
Java/C#/Python background
Hundreds of crash & burn moments with JavaScript



Project started

3.toFixed(4) // SyntaxError: Unexpected token ILLEGAL (3).toFixed(4) // "3.0000" 3.14159265359.toFixed(4) // "3.1416" 3..toFixed(2) // "3.00" 3...toFixed(2) // SyntaxError: Unexpected token.
Funny thing:
0.1 + 0.2 // 0.30000000000000004
function explosion() {
for( var element in arguments ) { // where did that come from?
console.log( arguments[element] ); // element is index?
}
}
explosion(5, 4, 3, 2, 1, 'Kaboom!');
[nofearinc@nofearinc js-samples]$ node explosion.js
5
4
3
2
1
Kaboom!

Altering a function parameter actually affects the arguments as well…
function hello( what ) {
what = "world";
return "Hello, " + arguments[0] + "!";
}
hello("shazow"); // "Hello, world!"
Thanks to wtfjs.com
arguments is not even a real array, so we need to ‘turn’ it:
function injected() {
var arr = Array.prototype.slice.call(arguments);
arr.push(4);
return arr;
}
var result = injected(1,2,3); // [1, 2, 3, 4]
I won’t even go into prototypes and call, it’d get messy…
[1,2,3]; // 1, 2, 3 new Array(1,2,3); // 1, 2, 3 new Array(5); // 5 times undefined
therefore:
",,,," == new Array(5); // quite true
Array.prototype includes numerous handy functions. But…
([]+[]).length // 0 ([]+![]).length // 5
Two NaN are not siblings
Number('z') === Number('z') // false, NaN != NaN
Number('z') == Number('z') // false
So many equal comparisons
false == 0 // true null == undefined // true 0 == '' // true 0 == '0' // true
Compare by === to capture proper type as well

(function(b){var a={add:"ajaxAdd",del:"ajaxDel",dim:"ajaxDim",
process:"process",recolor:"recolor"}, c;c={settings:{url:ajaxurl,
type:"POST",response:"ajax-response",what:"",alt:"alternate",altOffset:0,
addColor:null,delColor:null, dimAddColor:null,dimDelColor:null,
confirm:null,addBefore:null, addAfter:null,delBefore:null,delAfter:null
, dimBefore:null,dimAfter:null},nonce:function(g,f){var d=wpAjax.
unserialize(g.attr("href"));return f.nonce||d._ajax_nonce
define('SCRIPT_DEBUG', true);
…makes the developer happy.
Adding script tags directly to header/footer?
Nah.
<?php
function correct_frontend_scripts() {
wp_enqueue_script( 'my-script-handle',
plugins_url( 'js/script-file.js', __FILE__ ),
array( 'jquery' ) );
}
add_action( 'wp_enqueue_scripts', 'correct_frontend_scripts' );
?>
Use get_template_directory_uri() or get_stylesheet_directory_uri() in themes
function load_admin_scripts( $hook ) {
// don't include on regular admin pages
if( $hook != 'edit.php' && $hook != 'post.php' &&
$hook != 'post-new.php' ) {
return;
}
wp_enqueue_script( 'my-own', plugins_url(
'js/my-own.js' , dirname(__FILE__) ) );
}
add_action('admin_enqueue_scripts', 'load_admin_scripts');
admin_init is not the right place to load your script.
Enqueue an admin script and register translation variables
function dx_admin_enqueue( $hook ) {
wp_enqueue_script('h2change', plugins_url('h2change.js', __FILE__));
wp_localize_script( 'h2change', 'translator', array(
'h2' => __('Title in English', 'domain')
));
}
In h2change.js, make use of translator object registered above:
jQuery(document).ready(function($) {
$('h2').html(translator.h2);
});
Register callback when executing AJAX call with autosave action
add_action( 'wp_ajax_autosave', 'inject_autosave_action', 9 );
function inject_autosave_action( ) {
if( ! empty ($_POST['post_id'] ) ) {
$autosaved = rand( 1, 1000 );
update_post_meta( $_POST['post_id'], 'autosaved', $autosaved );
}
die();
}
Returning AJAX data as XML
$x = new WP_Ajax_Response( array(
'what' => 'autosave',
'id' => $id,
'data' => $id ? $data : '',
'supplemental' => $supplemental
) );
$x->send();
source: wp-admin/includes/ajax-actions.php
var post_data = {
'post_id': post_id,
'action': 'autosave',
...
};
jQuery.ajax({
data: post_data,
type: "POST",
url: ajaxurl,
success: function( response ) {
// get the party started
}
});
<?php
add_action( 'wp_head', 'ajaxurl_injection' );
function ajaxurl_injection() {
?>
<script type="text/javascript">
var ajaxurl = '<?php echo admin_url('admin-ajax.php'); ?>';
</script>
<?php
}
var obj = new Object();
Every solider for himself.
Btw, var obj = {}; is the same.
And, seriously, that’s even not a pattern for new template-like objects. However,
var person = {
name: "John Smith",
age: 42
};
console.log( person.age ); // 42
Looping over that so called object (note: sluggish):
for( var key in person ) {
console.log( key + ' is ' + person[key] );
// name is John Smith \n age is 42
}
Useful for hashes & namespacing, like:
<script type="text/javascript">//<![CDATA[
var mpeshev = {
"ajaxurl": "<?php echo admin_url( 'admin-ajax.php' ); ?>"};
//]]>
</script>
console.log( mpeshev.ajaxurl ); // yep, yields to the admin url
The real class is actually a function, a “constructor” to be found as
function Person(name, age) {
this.name = name;
this.age = age;
this.get = function() {
return this.name + ' is ' + this.age;
}
}
john = new Person('John', 42);
peter = new Person('Peter', 31);
console.log(john.get()); // John is 42
console.log(peter.get()); // Peter is 31

Reduce direct DOM access, cache your variables
function classifyDivs() {
var divs = document.getElementsByTagName('div');
for (var i = 0, l = divs.length; i < l; i++) {
divs[i].className += ' checked';
}
}
Besides, i+=1 is faster than i++
Comments and long variable names take more time to interpret
WPORG plugin, slight name changes only
function updateSomeIds(ids) {
var x;
for (x in ids) {
jQuery('#someid table td').find(
':input[name^="somename['+x+']"]').each(function() {
jQuery(this).attr('name',
jQuery(this).attr('name').
replace("["+x+"]", "["+ids[x]+"]"));
});
}}
Note: Avoid context wild guesses, location.href is slower than window.location.href
$('#parent1 #child #inner') // usually not needed

Meet me after the track for any questions or contact me online:
Tweets as @no_fear_inc
Mario Peshev on LinkedIn
nofearinc on WordPress.org
GitHubering via mpeshev
DevWP.eu - blog