Javascript: Why won’t my loop work? (i.e. using closures)

Take a simple example:

for (var i = 0; i < 3; i++) {
console.log("Hello: " + i);
}

This will output

Hello: 0
Hello: 1
Hello: 2

But what if you need to do something more complicated than one line of javascript?

var obj = {}
for (var i = 0; i < 3; i++) {
	obj[i] = function() {
		console.log('Hello' + i);
	}
}
for (var j = 0; j < 3; j++) {
	obj[j]();
}

This will output:

The current number
is 3
The current number
is 3
The current number
is 3

What’s happening?

What is happening is scope in javascript doesn’t work the way you think it works.

function() {
	a variable in this block {
		still applies inside of this inner block!
	}
}
for (var i = 0; i < 3; i++) {
	console.log("My value: " + i);
	for (var j = 0; j < 3; j++) {
		console.log("My value: " + i);
	}
}

The first four lines will give you

My value: 0
My value: 0
My value: 0
My value: 0

Meaning, the value of i is the same inside the brackets of the inner loop as “i” is in the outer loop.

When you write:

for (var i = 0; i < 3; i++) {
	obj[i] = function() {
		console.log('Hello' + i);
	}
}

obj[i] is first assigned 0.

Then obj[i] is assigned 1. Then obj[i] is assigned 2…

3 is the final value. Which gives you:

The current number
is 3

Instead, make your inner function return a function. The inner function will close over the value before returning it, in this example, the value of i:

var item = [];
function hello(i) {
	return function() { console.log('Hello' + i); }
}
for (var i = 0; i < 3; i++) {
	item[i] = hello(i);
}
for (var j = 0; j < 3; j++) {
	item[j]();
}

Reference: http://stackoverflow.com/questions/111102/how-do-javascript-closures-work

WordPress: removing menus in the Admin

Here is a way to remove menu items in the Admin side for users who aren’t administrators:

Using Compass

LESS is a great CSS preprocessor and I will probably keep using it with bootstrap (which, as you can tell, is what I am using for my current WordPress theme).

However, I have started using Compass and I realized it’s not as scary as it seems.

The Command Line

Yes, Compass is a gem but not to worry – it’s not like trying to install rails.

All you need to do is open terminal and type:

$ gem update --system
$ gem install compass

That’s it!

Make a site

Let’s say you want to make a site in your “Sites” folder called “example”.

Open Terminal.

Type the following

cd Sites
$ compass create example

Folder structure

Compass will create a few folders.

Sass

Compass .scss files go here

stylesheets

Regular .css style sheets go here. Compass will generate .css stylesheets based on the files in “Sass”.

.sass-cache

I have yet to go in and change anything in the .sass-cache folder.

Config.rb

If you don’t want to store your compass files in sass or your css files in stylesheets you can change your configuration here.

Using 960 with Compass

The 960 grid used to come prepackaged with Compass, but now Tim Riley keeps it on his github.

You can install it by opening Terminal and typing:

gem install compass-960-plugin

For the example above, if you want to create a site called example in your Sites folder:

cd Sites
compass create -r ninesixty example --using 960

 

Concrete5, placing editable blocks in a template

In Concrete5 you can create an editable area by adding this:

<?php
$a = new Area('My Area Name');
$a->display($c);
?>

The only problem is that areas in concrete5 can contain many blocks – as many blocks as the user likes.

If you only want the user to edit a particular block (and not add as many blocks as they would like, another method is to replace the area with a block.

Replace the area with an autonav block

<?php
$autonav = BlockType::getByHandle('autonav');
$autonav->controller->orderBy = 'display_asc';
$autonav->controller->displayPages = 'top';
$autonav->render('templates/my-custom-template');
?>

Replace the area with a content block

<?php
$content = BlockType::getByHandle('content');
$content->render('templates/my-custom-template');
?>

Replace the area with a Google Map block

<?php
$googlemap = BlockType::getByHandle('google_map');
$googlemap->render('view');
?>

Replace the area with an image

<?php
$image = BlockType::getByHandle('image');
$image->render('view');
?>

 

WordPress and Concrete5: themes, templates

Themes

WordPress and Concrete5 both have theme folders.

In WordPress, the folder structure looks like:

-public_html (or what your web folder is called)
--wp-content
----themes
--------my-special-theme

In Concrete5, there are two theme folders

-public_html (or what your web folder is called)
--themes
--concrete
----themes

The outer theme folder is where you put your custom themes.

The theme folder inside the folder marked concrete5 are where the default themes are placed.

As a general rule, do not put any of your own code inside of the concrete5 folder.

Templates

In WordPress, templates go inside of your theme folder.

Each template file begins with:

<?php
/**
* Template Name: Name of my template
*/

In Concrete5, template pages (and other pages) often begin with:

<?php defined('C5_EXECUTE') or die("Access Denied.");

In WordPress, content is placed into the template with template tags:

<h1><?php bloginfo('name'); ?></h1>

In Concrete5, instead of using tags for the title, content, pagination, and so on, instead you mark out areas of editable content:

<?php
$a = new Area('Main');
$a->display($c);
?>

In the example above, the area is called ‘Main’ but it can be other things too:

<?php
$a = new Area('Sidebar');
$a->display($c);
?>

Headers and Footers

WordPress and Concrete5 both need special header and footer code.

In WordPress, this places the header on a template page:

<?php get_header(); ?>

Also, you have to make sure to include this file in your header.php page before your </head> tag:

<?php wp_head(); ?>

Include the footer template by writing:

<?php get_footer( $name ); ?>

And you “hook” into the footer by including this in footer.php:

<?php wp_footer(); ?>

Without wp_head or wp_footer, you will break many of your WordPress plugins which rely on these hooks to add items to your header (for example, any plugin that needs to include custom css or javascript in the head of your HTML document.

In Concrete5, you include the header by replacing your <title></title> tags with

<?php  Loader::element('header_required'); ?>

And in the footer:

<?php Loader::element('footer_required'); ?>