Friday, November 8, 2013

Adding Drupal CAPTCHAs in code

The Drupal CAPTCHA module provides a great configuration page for adding captchas to webforms and forms created with the Drupal form API (created in code).  I recently encountered a situation with a custom, multi-page form that needed a CAPTCHA.  The problem was that the CAPTCHA was showing up on the first page of the form, which seemed like a strange user experience.  Fortunately, it is possible to insert a CAPTCHA into a FAPI form in code as well.

The #captcha_type will define which style of CAPTCHA will be displayed. ( Image and reCAPTCHA require that those modules are enabled in addition to the regular CAPTCHA module )

  $form['captcha_fieldset'] = array(   // wrapping in a fieldset so it looks better
    '#type'           => 'fieldset',
    '#title'          => 'CAPTCHA',
    '#collapsible'    => FALSE,
    '#collapsed'      => FALSE,

    'my_form_captcha' => array(
      '#type' => 'captcha',
      '#captcha_type' => 'captcha/Math'  // displays the default math captcha
      // '#captcha_type' => 'recaptcha/reCAPTCHA'  // requires the reCAPTCHA module
      // '#captcha_type' => 'image_captcha/Image',  // requires image_captcha module (distributed with the captcha module)
    )
  );

Wednesday, October 30, 2013

PHP error reporting

Great for development:
<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
// probably more error reporting than you'll want
?>

Tuesday, October 8, 2013

Finally, a unicode lookup tool!

For whatever reason I always have trouble finding a resource this good for converting special symbols
http://unicodelookup.com

Tuesday, September 17, 2013

Online formatters & pretty printers

A few online resources that I use on a daily basis for formatting / pretty printing:

JSON Viewer:
Simple, straighforward, and FULL SCREEN!  ( I hate JSONLint because its window is so small )
There is also a 'View' mode that displays your JSON as an interactive (collapse/expand) list.
jsonviewer.stack.hu

PrettyPrinter:
Excellent for PHP arrays. The list of options for fomatting can be a little overwhelming but very powerful. I generally click the first two boxes for "Add new lines after "{" and before "}" " and "Add new lines before "{" "
prettyprinter.de

Phillihp's PHP Pretty Printer:
Admittedly, this tool is down every once in awhile. It's a bummer because I haven't found a better one. This handles PHP Objects beautifully, and color codes them too.
http://phillihp.com/toolz/php-array-beautifier/

It is also worth noting that the Javascript method JSON.stringify() is capable of pretty-printing JSON objects.   JSON.stringify(JSON_object, null, 2);    ( I don't remember what the null is for but the 2 is the amount of indentation I believe )

Firebug and the Chrome Developers Console also have good methods for formatting debugging output:
https://getfirebug.com/wiki/index.php/Console_API
https://developers.google.com/chrome-developer-tools/docs/console

If you have a favorite, please leave a comment.

Monday, September 16, 2013

Formatting dynamically generated content in JQuery Mobile

I'm learning the basics of JQuery Mobile and so far have found it to have distinct advantages and disadvantages.

The most major roadblock I encountered ( and also had trouble finding a solution to ) was that when I added HTML markup to the page dynamically it wasn't being automatically themed in the JQM 'style'.  ( JQM adds a series of CSS classes that control the display of page elements )

Finally I found this blog entry which nicely describes the issues I needed solved:
http://www.gajotres.net/jquery-mobile-and-how-to-enhance-the-markup-of-dynamically-added-content/

Unfortunately there doesn't seem to be a single solution to this problem, almost every HTML element type has a different means of being 'reformatted'.   For example I added a SELECT menu dynamically. To have it appear styled with JQM styles I had to first append the menu to the DOM:

$("#select_container").html(select_markup);  // append the select_markup
$("select").select();  // call select() on all select menus to force / reset styling

Text inputs, checkboxes, tables, buttons and navigation all have their own methods...

More on JQM to follow...

Thursday, September 5, 2013

onmousemove event handling in Internet Explorer

IE was giving me trouble when assigning event handlers in my usual syntax:
document.getElementById("myDiv").onmousemove = function (e) {
    // code to execute
}

The general consensus around the internet is that IE doesn't bind onmousemove events to elements other than the 'document' element. Or something like that. We all know that IE sucks, so lets cut straight the workaround.

It seems it works much better when using addEventListener():
document.getElementById("myDiv").addEventListener("mousemove", function (e) {
    // code to execute
}

Note that in that syntax the event goes by the name 'mousemove' and not 'ONmousemove'

Wednesday, August 21, 2013

CSS ellipsis

I always have trouble remembering what CSS properties need to be set to get text-overflow: ellipsis to work.  These three seem to do the job:

text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;   

Wednesday, August 14, 2013

TouchPunch - drag and drop on mobile devices

I'm starting a project that is going to require drag and drop functionality on mobile devices.  I quickly learned that jQuery UI's wonderful .draggable() method only works with mouse events, making it useless on a tablet or phone.
As always I am not the first to have this problem, so some developers came up with TouchPunch, a small library that forwards mouse events to their touch counterparts. Simply including this library solved the problem without the need to write a single line of code. Booya.
http://touchpunch.furf.com/

Friday, June 28, 2013

Thursday, June 6, 2013

'Flick' scrolling on iPad & iPhone

'Flick scrolling', or kinetic scrolling, is when the user can scroll a menu with momentum.

While developing a user interface at work I discovered that 'flick scrolling' is not enabled by default in the mobile Safari browser.

Long story short, this webkit snippet will solve your problem:
-webkit-overflow-scrolling: touch;

Just put it in a css class and add it to anything that should have 'flick scrolling'.

Thursday, May 23, 2013

JSONP XMLHttp Requests








// define a 'success' callback to handle the results of the request
success = function () {
   // this is called on success
}

// add the callback function 'success' as the query parameter 'callback'
var url = "http://www.api.com/endpoint?callback=success";


// create a new SCRIPT tag, assign the url to the 'src' attribute and append to the HEAD tag
var s = document.createElement("script");
s.src = url;
document.getElementsByTagName("head")[0].appendChild(s);

// couldn't be easier

Wednesday, May 22, 2013

HTML5 File API resources

I'm starting a project using the HTML5 File API and I'm excited about what new things are possible. 
Javascript interacting with the local file system? Front-end nerds rejoyce.

Official W3C Spec:
http://www.w3.org/TR/file-upload/

A great set of examples on html5rocks.com :
http://www.html5rocks.com/en/tutorials/file/dndfiles/

Monday, May 20, 2013

Programatically triggering Rules in Drupal 6

Sometimes a rule needs to be triggered and there is no existing event that can be used to trigger it.  The good news is that you can trigger events programatically without much trouble.

In this example we'll create a rule that sends an email to all users with a certain role.  We'll be writing this as a module for Drupal 6.

The first step is creating the event with hook_rules_event_info():

function modulename_rules_event_info() {
  return array(
    'modulename_event' => array(
      'label' => t('Event Name'),
      'module' => 'modulename',
      'arguments' => array(
        'user' => array('type' => 'user', 'label' => t('User.')),
        'node' => array('type' => 'node', 'label' => t('Node.'))
      ),
    ),
  );
}

Clear your Drupal cache to ensure that Drupal knows about your new event.

Now, navigate to the 'Rules' section on the Drupal admin area and create a new rule.  You should notice that your event is listed near the bottom of the 'events' select menu, under a heading of 'modulename'.

Continue to create the rule by defining conditions and actions to be evaluated when the event is triggered.

Now, to trigger the event programatically... enter this method in your module code at the point when the event should be fired:

rules_invoke_event('modulename_event', $user, $node);

An easy test is to send yourself an email with the rule, or use drupal_set_message() to output some text to the screen.

For more info see:  http://drupalcontrib.org/api/drupal/contributions%21rules%21rules%21rules.api.php/function/hook_rules_event_info/6

Wednesday, May 8, 2013

Adding mysql to your Path environment variable


Environment Variables in Windows -> Edit.

Under system variables select the path variable and click the edit button.

Each path in this field must be separated by a semicolon ; with no spaces.

Example path:  C:\Program Files\MySQL\MySQL Server 5.1\bin

Tuesday, April 16, 2013

Min and Max sliders with HTML 'range' inputs

I wrote this for work the other day and it won't wind up being used, so here it is.  These two event listeners can be used on two HTML <range> inputs for a 'minimum and maximum' selection. The max cannot be set smaller than the min and the min cannot be more than the max.

The HTML:

    Minimum Font Size:
    <input id="font_min" type="range" min="10" max="80" step="1" value="12" />
    <span id="font_min_val"></span>

    Maximum Font Size:
    <input id="font_max" type="range" min="10" max="80" step="1" value="30" />
    <span id="font_max_val"></span>


The jQuery:

    $("#font_min").change(function () {
        $("#font_min_val").text($(this).val()+"px");
       
        if ($(this).val() >= $("#font_max").val()) {
            $("#font_max").val($(this).val());
            $("#font_max_val").text($("font_max").val()+"px");


        }
    });

    $("#font_max").change(function () {
        $("#font_max_val").text($(this).val()+"px");
       
        if ($(this).val() <= $("#font_min").val()) {
            $("#font_min").val($(this).val());
            $("#font_min_val").text($("font_min").val()+"px");

        }
    });

Thursday, April 4, 2013

Blender Hotkeys I will never remember

r - rotate current object. use x,y,z to contrain axis of rotation.
s - scale. use x,y,z
g - move - use x,y,z

z - toggle wireframe view

NumberPad keys control view angle.
NUM5 - toggle 3d / orthographic view

b - marquee / loop selection

SHIFT+R - initiate loop cut. Use mouse wheel to select the number of loops to cut

CTRL+D - duplicate an object. use x,y,z to constrain to one dimension for relocating the clone


Wednesday, March 27, 2013

jQuery autocomplete

Here is a simple way to implement an 'autocomplete' text field:

Define a function to use as a typewatch timer:

var typewatch = (function(){
  var timer = 0;
  return function(callback, ms){
    clearTimeout (timer);
    timer = setTimeout(callback, ms);
  }
})();

Then use the timer in a .keyup() jQuery event listener.

$('#text-field').keyup(function(e) {
    typewatch(function () {
        tmpLen = $('#text-field').val().length;
        if( tmpLen > 2 || tmpLen == 0 ) { // also searches when the field is cleared with backspace
              getAutoComplete();  // or any other action
        }
    }, 500);
});

The listener will trigger a call to getAutoComplete() when the length of the text in the field is greater than 2 characters, or 0 characters for when the field is cleared.

Adjusting the > 2 characters or 500ms timeout will fine tune the behavior.

Thursday, February 28, 2013

Preloading web fonts for use with html CANVAS

The problem:
Your application makes use of html <canvas> to draw some text to a canvas element when the page loads. You've picked out a cool web font to use but find that it isn't loading in time to be drawn onto the canvas. Unlike DOM elements that automatically update to the correct font when it becomes available ( FOUT ), the canvas is simply drawn with the incorrect font.  Refreshing the canvas or page will probably display the correct font because it has finished loading or has been cached.

There are several creative ways around this. The following one has not been extensively tested but is something I want to experiment with in the future.

I found that while using @font-face to declare fonts in CSS, there was no way to know when the resources requested ( font files ) were loaded. The 'onload' will fire because all of the scripts and stylesheets have loaded, but the files the stylesheets requested could still be in transit.

By embedding the font files in the CSS by base64-encoding them, I was able to verify that the stylesheet ( including the font ) was loaded when the onload event happens. Run this within the <head> tags.

        var fileref = document.createElement("link");
        fileref.setAttribute("rel", "stylesheet");
        fileref.setAttribute("type", "text/css");
        fileref.setAttribute("href", "PATH_TO_CSS_FILE");
        document.getElementsByTagName("head")[0].appendChild(fileref);

Here are some considerations:
This approach will increase the size of your font by 30-40%, but will spare a round trip to the server to fetch additional font files.
This will prevent the page from loading until your whole CSS/font file is loaded. This could be unacceptably long if using a large font, multiple fonts, or browsing on a mobile device.

Now here is something I'm working on that is very untested and crazy:

        var filename = "cssGen.php?font="+fontFile;
        var fileref = document.createElement("link");
        fileref.setAttribute("rel", "stylesheet");
        fileref.setAttribute("type", "text/css");
        fileref.setAttribute("href", filename);
        document.getElementsByTagName("head")[0].appendChild(fileref);

In this case the CSS file being added is actually a PHP script posing as CSS.  The name of the font file is passed into the css/php using the 'font' query parameter.  Then inside the css/php script:

***
<?php
    header("Content-type: text/css; charset: UTF-8");
   
    $font = explode(".",$_GET['font']);
    $fontData = file_get_contents("fonts/".$_GET['font']);
    $encoded = base64_encode($fontData);
?>
@font-face {
    font-family: '<?php print $font[0]; ?>';
    src: url(data:application/x-font-woff;charset=utf-8;base64,<?php print $encoded; ?>) format('woff');
    font-weight: normal;
    font-style: normal;
}

#myCanvas {
    border: 1px dashed #999;
}

body {
    font-family: '<?php print $font[0]; ?>';
}

***
The headers are set so the file is interpreted as text/css. The name of the font family is derived from the filename and the font file is base64 encoded on the fly.
Again, not tested much, but fun to play around with.  I thought the whole idea of executing php inside CSS was worth trying anyway.

Wednesday, February 20, 2013

Check a hex color code using a regular expression

This handy function uses a regular expression to check for a valid 6 or 3-digit hex code beginning with #.

function hexCheck (hex) {
    var re = /^\#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/;
    return re.test(hex); // returns true if this is a valid hex code
}

This can and should be elaborated into another method for regularizing hex codes. ( Adding #, etc )

Wednesday, February 13, 2013

PHP Control Structure Syntax

This syntax is particularly useful when writing template files. In a template, you may or may not be receiving a piece of data from your CMS, and have to adjust accordingly. If the content isn't there, you'll want to make sure that an ugly error message won't appear and that the template handles the omission gracefully.

The basic concept:
<?php (conditional php statement) : ?>
   <p>some html content</p>
<?php endConditional; ?>


In the example above the HTML markup will only be output to the browser if the conditional statement resolves to true. Below we'll check that the $data has a valid value ( not equal to "" ), before printing it to the screen.

<?php if($data->user != "") : ?>
   <p>Welcome, <?php print $data->user; ?>!</p>
<?php endif; ?>

If all goes well, the result will be:  Welcome, User!
If not, nothing is output.


Wednesday, January 30, 2013

Writing a custom Drupal 6 Views 2 filter - resources

This is not intended to be a full tutorial but resources and tips that I found helpful.

Drupal 6
Views 2

Helpful Tutorials:
http://www.hashbangcode.com/blog/creating-custom-views-filters-exposed-form-element-drupal-6-561.html

In summary the major steps are:

1. Within a custom module, define hook_views_api() to alert Drupal that the module is views enabled, api version 2, optional path index pointing to a directory that has additional files for the view.

2.  Use hook_views_handlers() to again point to the directory of files to include for the view, as well as the name of a custom handler to be used and the parent handler it will extend.  The custom name handler should be the same as the name of the .inc file which will contain a class, which again will have the same name.

3. Use hook_views_data() to define the name and group the filter will appear under in the Views UI. Again the name of the custom handler is included.

4. In the .inc file named after the handler, create a class (custom handler name) that extends the parent handler class.  This class will contain about two methods. The first value_form() will build and return the form to be used within the views UI. The second, query(), uses drupal methods to insert additional 'WHERE' or 'AND' clauses to the SQL query statement being built by the view.  (add_where())

One major roadblock I hit was attempting to reference a table other than the main one being used by the view. SQL was giving me errors about an 'unknown column'. The method add_table() allowed me to register other tables to be used within the query.

Drupal permissions and the node_access table - a hard learned lesson

While building a custom filter for Views 2 on a Drupal 6 site I leaned an important lesson about the way Drupal handles permissions.

I was trying to write a filter that would display a selected list of nodes to users with a certain role.  Sounds easy right?  It would be fairly logical to assume that Drupal would support filtering access to nodes based on role. If you want to restrict access to an entire content type by role, this is easy. The 'views' explanation would be something like: "Show me nodes of this type, only to users who have this role".

My situation was different because the content type is accessible to all authenticated users, I only want to show a small subset of those nodes to users with a specific role.  That subset of nodes has no distinguishing property to filter, leading me to believe that I would have to write my own.

Here is where the trouble starts.

I wanted the filter to do a join between the 'node' table and the 'node_access' table to see if a particular node id was listed in the node_access table with the role id ( 'gid' in the table ) of the role to which I wanted to display the nodes. I was surprised when my queries were coming back empty.

I noticed that nodes of this content type would be returned with my custom filter when I used a role id that had access to nodes not available to 'authenticated users'.  To test this discovery I removed node access for authenticated users to the nodes I wanted available to the new role, and suddenly they were being listed in 'node_access' with the new role's id.

In summary:  If a node is accessible by the role 'authenticated user', the node_access table will only contain records associated with that role id.  Other roles given the same access will not have a record in the node_access table. This is most likely intended to reduce redundancy in the table because any user with any custom role will already be authenticated.

This is probably why this filter is not included in Views by default.

Unfortunately this means my query is impossible ( at least the way I attempted it ), and there goes several hours of facemashing my keyboard.

Thursday, January 24, 2013

Javascript query parameter setup

Using a query parameter can often be more convenient than having to change a hardcoded value while testing a script. This allows you to pass a variable into the script without having to edit and re-save your script.

var query = window.location.search.substring(1);
var keyVal = query.split("=");
var value = keyVal[1];
if (!value) { value = 100; } // in case no query parameter is passed in, use a default

Wednesday, January 9, 2013

Assigning CSS float values in javascript

I have to give credit for this information to an anonymous poster on stack overflow:  http://stackoverflow.com/questions/606470/is-there-a-cross-browser-way-of-setting-style-float-in-javascript

While creating and adding styles to some DOM elements with javascript, I noticed that my IDE was unhappy with me using this syntax:

domElement.style.float = "right";

The trouble is that 'float' is a reserved keyword in javascript, and the above syntax will cause unexpected results which vary across browsers.  I learned that I should be using: domElement.style.styleFloat = "right"; but this was still not working Firefox.

The cross browser solution ( Chrome, IE, Firefox ) :
domElement.style.styleFloat = "right";
domElement.style.cssFloat = "right";

Now everyone is happy.