Underhill Labs

Election Badge Experiment

I’ve been experimenting with codepen a lot lately. There is something so cool about experimenting with some tricky javascript and sending a link to a code sandbox somewhere to someone and they fork it and say, “here’s the fix”. Or they take the idea a step further and say, “and what about this?”

Well, below is a ballot feature that I’d like to replicate with Drupal’s webform module. (well except for the tricksy voting feature.)

See the Pen Election Badge Experiment by Bart Lantz (@majorursa) on CodePen.

Adding a Group by Clause to a Drupal View

These are some quick notes on how I added a group by clause to a query for a view in Drupal 7.

I have a custom database query in a module that I wrote and one of the fields in it: video_id corresponds to a node nid. So I wanted to pull this database into a view. However there can be many rows in my database for each node and all I wanted for the view was to print one message Update answer key if there was one or more entries in the database and a different message Create answer key if there were no entries.

tl;dr this is what worked

Tag the query in hook_views_query_alter()

1
2
3
4
5
6
7
8
9
10
11

/**
 * Implements hook_views_query_alter().
 */
function my_mod_views_query_alter(&$view, &$query) {
  if($view->name == 'video_landing_page') {
    // add_groupby doesn't work
    //$query->add_groupby('node.nid');
    $query->add_tag('my_mod');
  }
}

Next implement hook_query_TAG_alter

1
2
3
4
5
6
/**
 * Implements hook_query_TAG_alter().
 */
function dance_code_query_my_mod_alter(QueryAlterableInterface $query){
  $query->groupBy('node.nid');
}

Full Story

This was simple to do with a raw sql statement by adding “group by node.nid”. So I first tried adding this group by with hook_views_query_alter().

1
2
3
4
5
function my_mod_views_query_alter(&$view, &$query) {
  if($view->name == 'video_landing_page') {
    $query->add_groupby('node.nid');
  }
}

This did not appear to work. I searched google and D.O. and none of the solutions worked. There was also a consensus that there was a bug in hook_views_query_alter() and that I should use hook_query_altar() instead.

So I worked on implementing hook_query_alter, unfortunately the first problem was knowing how to identify that I was altering the correct view.

Notes on Drupal Rules

These are notes for some of the trickier situations for writing Rules.

Trigger Rule when a Node field has changed

In order to get the node-unchanged selector, the only event must be “Before Saving Content”.

Event

  • Before Saving content

Conditions

  1. Set condition field exists
  2. Entities -> Entity has field (eg node:field-supervisor)
  3. Data Comparison
  4. equals (negated)
    • node-unchanged:field-supervisor
    • node.field-supervisor

Theme Hook Suggestions

Theme Hook Suggestion Patterns

Base Templates

The following base templates are part of Bartik: comment.tpl.php, comment-wrapper.tpl.php, maintenance-page.tpl.php, node.tpl.php, page.tpl.php. Additionally, the core taxonomy module defines the taxonomy-term.tpl.php template.

find all of the templates in your site install

from within your site’s root directory run one of the following commands and optionally redirect the output (it’s long) into a file. find . -name ‘*.tpl.php’ -print

or if you’re using zsh: ls */.tpl.php

Copy Base Template into your theme or module and customize it

Decide what template you’d like to override and copy it into your module or theme folder.

cp modules/taxonomy/taxonomy-term.tpl.php sites/all/modules/custom/amazing-mod/theme/taxonomy-term.tpl.php

Rename file to a specific taxonomy vocabulary or term id

The pattern for overriding a taxonomy template is taxonomy-term--[vocabulary-machine-name|tid].tpl.php. In our case we are going to override the template for the education_session, so we rename the template thus:

cd sites/all/modules/custom/amaaazing-mod/theme/ mv taxonomy-term.tpl.php taxonomy-term–education-session.tpl.php

Notice that we changed the underscores in the machine-name to dashes.

Additional Notes

Don’t Forget: replace _ with - in field and taxonomy-term machine names

For instance, the taxonomy term education_session would become education-session in the Theme Hook Suggestion: taxonomy-term--education-session.tpl.php

If you cannot see changes: clear caches

drush cc all

Create a template file for your module

Implement hook_theme()

Implement hook_theme() and define your template file.

~~~ /* * Implements hook_theme(). / function amazing_mod_hook_theme() { return array(

'amazing-item' => array(
    'variables' => ('item' => NULL),
    'template' => 'amazing-item',
 ),

); } and create the file vim theme/amazing-item.tpl.php ~~~

References

Notes on Practical Vim

Chapter 3: Insert Mode

Make corrections without leaving Insert mode

  • c-w delete last word
  • c-u delete back to beginning of sentence.

Paste from register without leaving Inser mode

  • C-r{register} paste from register

So you can yank some text in Normal mode, type A to start in insert mode at the end of the line, and type C-r0 to paste what you just yanked.

Autocomplete

There is a later chapter that covers autocomplete goodness, but I should mention the simple form. - C-n autocomplete

this autocompletes from current buffer, all open buffers and CTAGS.

Jump to the end of the line

This is a new keymapping I thought of just now! - inoremap <C-e> <C-o>A

This remaps Ctrl-e to jump to end of the line, while you’re in insert mode. Granted, this is what is known as mixing metaphors, as C-e is an emacs shortcut. But it’s also one of my favorites.

1
inoremap <C-a> <C-o>I

Would add the opposite emacs shortcut to jump to the beginning of the line.

Notes on Vimscript

Vim variable prefixes

s: script level scope
g: global scope
a: function argument
l: local to function
b: buffer scope
w: window scope
t: tab scope
v: predefine by vim

Vim keyboard mapping

nmap normal mode keyboard mapping
imap insert mode keyboard mapping

Vim pseudovariables

&var vim option
&l:var vim local option
&g:var vim global option
@var vim register
$var environment variable

Vim idioms

Check if variable is defined before defining it

if !exists("g.my-flag")
  let g.my-flag = 1
  [ ... do more stuff here ... ]
endif

Define function with function! if it can be reloaded

function! s:myfunction() 
  ...
endfunction

Vim Plugins: Vim-surround

Contunuing my series of posts on awesome, indispensible Vim plugins, today let’s meet vim-surround! Vim-surround allows you to manipulate text/tags/quotes that surround a chuck of code.

Delete Surroundings with ds*

Delete the <h3> tag:

before:

1
<h3>Welcome to Snarnia!</h3>

command to run with cursor anywhere on the line (even in tag.)

Delete Surrounding Tag
1
dst

after:

1
Welcome to Snarnia!

Change Surroundings with cs*

Change "Hello, Bossy" to <q>Hello, Bossy</q> with:

Change Surrounding Quote
1
cs"<q>

Add Surrounding text with ys*

Adding text makes use of vim’s yanking word movements. Suppose you want to add, quotes around a sentence:

before:

1
2
3
I'm a monster, as well as a dwarf. You should charge me double.

--Tyrion Lannister

Command, on same line as quotation:

1
yss"

after:

1
2
3
"I'm a monster, as well as a dwarf." You should charge me double."

--Tyrion Lannister

I have found vim-surround especially helpful when editing html.

Manipulate outer tags

One more tip for manipulating outer tags: add a numeric argument to work on outer tags.

“example html”
1
2
3
4
5
6
7
<div>
<ul>
  <li>one</li>
  <li>more</li>
  <li>thing</li>
<ul>
</div>

In order to delete the <div> tag while in a list item in the code up above, type: ds3t and that will delete the tag 3 layers up.

Afterwards:

“example html”
1
2
3
4
5
<ul>
<li>one</li>
<li>more</li>
<li>thing</li>
<ul>

Vim and NERDTree Awesome-ness

I thought I’d write up a couple quick posts on vim commands that I have been using lately. This first post is on NERDTree.

NERDTree

Wow, this plugin is so amazing. It is a sideloaded file browser for vim. screenshot of NERDTree

Installing and setting up NERDTree

If you have pathogen installed, then installing it is as simple as:

1
2
cd ~/.vim/bundles/
git clone git://github.com/scrooloose/nerdtree.git

Next, I added the following to my ~/.vimrc

1
map <leader>nt :execute 'NERDTreeToggle ' . getcwd()<CR>

My leader key is comma, so once the previous code is added to my .vimrc, I can type ,nt in normal mode, and NERDTree’s file browser pops open on the side and displays the current working directory. Type C-w h (Control-w h) to send focus to the file browser and hit <enter> over a directory to expand it, or press <enter> over a file name to open it in the main window.

Next to close the file browser type ,nt again and it disappears.

Use NERDTree to rename and create new files.

I was satisfied with the above commands for awhile, it was very convenient, but then I watched screencasts of people creating files eaily in Sublime and Textmate and lo I was unsatisfied. But then one day as I was in the file browser I happened upon the “m” or menu command and it was a godsend! Typing m while on a file will bring up a menu of options:

1
2
3
4
5
6
NERDTree Menu. Use j/k/enter and the shortcuts indicated
==========================================================
> (a)dd a childnode
  (m)ove the current node
  (d)elete the current node
  (c)opy the current node

Move (or rename) a file

  1. move cursor to a filename in the file browser
  2. type m to bring up the menu
  3. type m again to rename the file
  4. type in it’s new name, press <enter> and the file is renamed.

Create a new file

  1. move cursor to a filename in the file browser
  2. press m while on a directory.
  3. type a for add a child node
  4. type in the new file’s name and press <enter>
  5. arrow down to the new file name and select it to start editing it.

Delete a file

  1. move cursor to a filename in the file browser
  2. press m to bring up the menu.
  3. press d to delete the file.

Opening file

By default NERDTree opens a file you select in the current window (the last window you hopped to the file browser from.) If you’d like to open it in a new horizontally split window, press i when cursor is on the file. To open it in a new vertical spit, type s.

NERDTree help

As mentioned earlier, you can type ? while in the file browser to bring up a help window. Type ? again to toggle the help window’s display.

XQuery Notes

This post continues my notes from Introduction to Databases, a MOOC taught by Stanford’s Jennifer Widom. The topic of this post is XQuery.

XQuery Defition

XQuery is a query and functional programming language that is designed to query collections of XML data.

from wikipedia,

XQuery Syntax: FLWOR

FLWOR Syntax
1
2
3
4
5
for $var in expr
let $var := expr
where expr
order by expr
return expr
  • All the statements are optional, but the return statement
  • The for and let statements may be used more than once to build up complex queries

XML for the Examples

countries.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<countries>
  <country name="Afghanistan" population="22664136" area="647500">
    <language percentage="11">Turkic</language>
    <language percentage="35">Pashtu</language>
    <language percentage="50">Afghan Persian</language>
  </country>
  <country name="Albania" population="3249136" area="28750"/>
  <country name="Algeria" population="29183032" area="2381740">
    <city>
      <name>Algiers</name>
      <population>1507241</population>
    </city>
  </country>
</countries>

List all Countries with population over 1,000,000,000

1
2
3
4
5
6
7
for $c in doc('countries.xml')/countries/country
where $c/@population > 1000000000
order by $c/@population
return
<big-countries>
 { $c/data(@name) }
</big-countries>

XPath Notes

This spring I took Introduction to Databases a MOOC (Massive Open Online Class) from Stanford’s Jennifer Widom. It was very interesting, I learned a great deal from it. And one of the sections of the class that I really enjoyed, even though it sounded like it was going to be pretty dry, was the section on XML. I took quite a few pages of notes on the different XMl tools, so I figured I might as well post them to my blog.

XPath Definition

XPath is a query language for selecting nodes from an XML document.

from Wikipedia

XML for the Examples

countries.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<countries>
  <country name="Afghanistan" population="22664136" area="647500">
    <language percentage="11">Turkic</language>
    <language percentage="35">Pashtu</language>
    <language percentage="50">Afghan Persian</language>
  </country>
  <country name="Albania" population="3249136" area="28750"/>
  <country name="Algeria" population="29183032" area="2381740">
    <city>
      <name>Algiers</name>
      <population>1507241</population>
    </city>
  </country>
</countries>

Basic Path

Selects all of countries from the country root node.

1
doc('countries.xml')/countries/country

Path with Alternation

This will select countries with populations that speak Pashtu or Swedish.

1
doc('countries.xml')/countries/country[language(Pashtu|Swedish)]

Attributes are prepended with “@”

This will select the names of all countries

1
doc('countries.xml')/countries/country/@name

Path with Conditional

Select the names of all countries that have a population of less than 1,000,000.

1
doc('countries.xml')/countries/country[@population < 1000000]/@name

Complex Conditional

Select all countries that have a population of less than 1,000,000.

1
doc('countries.xml')/countries/country[@population < 1000000 and city/population > 50000]

data() prints out just the text value.

1
doc('countries.xml')/countries/country[@population < 1000000]/data(@name)