Mind your JavaScript

 

 

Mario Peshev @no_fear_inc

WordPress Engineer #WCNorge

Mind your Language

mind-your-language

Mario Peshev

trainer-speaker

Open Sourcerer

WordPress Engineer @ Placester

WP Head @ DevriX

Java/C#/Python background

Hundreds of crash & burn moments with JavaScript

project-manager

good_code

hironakamura

Project started

I’m a PHP developer and I know JavaScript inherently

php-developers

Number conversion

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

Mystic arguments

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!

woot

Arguments

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 a Hybrid

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…

Array management

[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

Type comparisons

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

Stewie_Griffin_The_Deuce

I’m a WP developer and I know how to use JS

(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.

wp_enqueue_scripts

 

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

admin_enqueue for a page

 

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.

wp_localize_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);
});

AJAX hook with function

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();
}

By the way…

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

AJAX JS part

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
	}
});

Add ajaxurl to frontend

<?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
}

I’m a OOP ninja

3d small people - ninja

Objectivism

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

Objectivism part 2

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 class

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

sonic-the-hedgehog

DOM Access

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

Real sample

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

time is up concept clock

Thank you!

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