Friday, 1 August 2014

More powerful Mustache template functions (lambdas)

The following insight allows the "helper" functions (lambdas) in Mustache to be more powerful by giving them access to much more data.

The standard shape of a Mustache template function is as follows:

{
"a":10,
"b":20,
"myfn": function(){
    return function(text, render){
        return "The cost is:" + render(text)
    }
},
"currency_symbol":"£"
}

The value of the parameter "text" will be the Mustache bracketed name of some part of the hash which was specified in the template ( e.g. "{{a}}" ). The purpose of the render function is to "lookup" the value of "a" in the hash and return 10 (in this case).

The insight recorded in this post is that any other simple value from the hash can be looked up and the value used in the function, for example...

return "The cost is: " + render("{{currency_symbol}}") + render(text)

Tuesday, 29 October 2013

Coping with Browser Cache in AJAX calls

When using jQuery to perform AJAX calls the following is typical

$.get("myScript.php",{'arg1':val1,'arg2':val2},function(json){
  ...
},'json')

I have found that the browser can supply an old result from its cache when I want a new result to be evaluated.

The solution is to add another argument to the cgi pack which contains a value which is guaranteed to be 'new'. This will stop the browser using a cached result. The value of the argument is conveniently supplied by the Javascript Date package. Of course myScript.php can just ignore the extra argument.

$.get("myScript.php",{'arg1':val1,'arg2':val2,'antiCache':antiCache()},function(json){
  ...
},'json')

function antiCache(){
return (new Date()).getTime();
}

[The getTime() method returns the number of milliseconds between midnight of January 1, 1970 and the specified date.]

Tuesday, 23 October 2012

EXTRACT-ing results from Pear DB into separate variables


I was used to writing this sort of code when using php_mysql

$result = $db->getRow($sql);
list($surname,$initials,$login,$email,$tutor,$prog)=$result;
//now got separate variables $surname, $initials, etc

Now that I am using PEAR DB, list(...) does not work, so I have found another 'trick' using the PHP function extract

extract($result,EXTR_PREFIX_ALL, "student");
//student is used as a prefix
//now got variables like $student_surname, $student_initials, etc

Note:
I am using 
$db->setFetchMode(DB_FETCHMODE_ASSOC);
so the alternative is to access the names as
$result['surname'], $result['initials']

Friday, 12 October 2012

Parsing the Search String/Query String (revised)

This version avoids using the eval() function and so is neater and safer.
[Compared with the version given in an earlier note in this blog]

var GLOBAL={}

location.search.replace(
  new RegExp("([^?=&]+)(=([^&]*))?", "g"),
  function($0, $1, $2, $3) {
    GLOBAL[$1]=$3;
  }
);

Monday, 9 July 2012

Using jQuery datepicker with html5 contenteditable


You are supposed to use jQuery datepicker with an input element.
Trying to attach it to a div gives a stay open calendar.
The trick here is to attach the datepicker to a hidden input element.

Use the "trigger by button" feature (hence little 'calendar' graphic)

When the datepicker closes (onClose) the new value can be planted (.html() )  in the visible contenteditable element.

If you are watching "on focus" & "on blur" of the contenteditable (to catch user editing) then these events can be simulated as the value is entered (.focus() - .blur() ) so that the change in date is dealt with as if the user entered it themselves.

HTML code:

<div>
<span class='date' contenteditable='false'>9/7/2012</span>
<input type='hidden' class='datepicker' />
</div>
Javascript code:

$(".datepicker").datepicker({
  dateFormat: 'dd/mm/yy',
  showOn: "button",
  buttonImage: "images/calendar.gif",
  buttonImageOnly: true,
  onClose: function(dateText, inst) {
  $(this).parent().find("[contenteditable=true]").focus().html(dateText).blur();
  }
});

Wednesday, 6 June 2012

Deleting HTML5 database tables in Safari

If you are developing using HTML5 databases in Safari (SQLite) you may need to delete tables. In OSX Safari you can use Develop|"Show Web Inspector", then Resources, Databases. There you will have a type in window where you can enter SQL statements like "DROP TABLE ".

In iOS you have to rely on Settings, Safari, "Clear Cookies & Data"

Thursday, 12 January 2012

Appleworks drawings after Lion

Appleworks drawings after Lion

Appleworks does not (& will not) run under Lion

There are many solutions to many of the document types but...
There are many postings saying that the only real solution for Appleworks drawings is to buy EazyDraw

I want to offer a possible workaround - using Keynote
(N.B. this relies on doing something BEFORE) you migrate to Lion

1) Using Appleworks, make a new presentation and paste some of your Appleworks drawings in, one drawing to a slide
2) Now save the presentation and then open it in Keynote

Hey Presto, your diagrams are all there and you can ungroup them and edit them (if you know how to use Keynote, that is)

Problems?

I found that Keynote undersizes the text boxes so they need stretching to the right to stop the word wrap

I found that my arcs (quarter circles for the most part) had gained "radii" making them look like segments of a circle. (Hence the previous post on how to draw arcs in Keynote)


How to draw a perfect arc in Keynote

To draw a perfect quarter circle in Keynote (the OSX presentation package)

1) Work at 400% (or whatever for greater accuracy) 
2) Draw square first
3) Choose Insert|Shape|Draw with pen (to start drawing a Bezier curve)
4) Click on first point (e.g. bottom left corner of square)
5) With mouse still down, drag the tangent upwards to next corner of square (e.g. top left)
6) Release mouse
[That's the first point done]
7) Click mouse at end point of arc (e.g. top, right corner of square), release. 
8) Press escape key

Hey presto, you should have a perfect quarter circle.

You can now delete your square
Then you can go on to treat your arc as a 'line' and adjust the thickness, colour, etc

Tuesday, 3 January 2012

Repeating Labels - Printing multiple copies of 1 label in OSX AddressBook

Repeating Labels
Printing multiple copies of 1 label in OSX AddressBook


OSX AddressBook is great for printing Christmas Card labels etc (i.e. proper address labels) but it is not clear how to use it to print multiple copies of a single label as you would do for labels on Homemade jam or on "sent by" stickers for the back of an envelope.


I have found one way to do it as follows...


Create a text file with a header line and then n repeats of an address data line where n is the number of labels on your label stationery (I used tab delimiter)




Last                            Home Street Home Street 2   Home City     Home State    Home zip
(sent by) J Bloggs    My No/Street     My Town             My City      My County      My Postcode
(sent by) J Bloggs    My No/Street     My Town             My City      My County      My Postcode
etc.

In AddressBook make a new group and File|Import... your text file of address - you will have n identical addresses

Use the AddressBook Label to print the group in the normal way (either selecting the Avery labels that you are using or creating a custom template).

Hint: If you are using Photocopier labels with no margins, then make your own template - I was using 8x3 photocopy labels and my template was...
top:0
bottom:0
left 4.670
right 4.670
rows:8
columns:3
horizontal gutter: 2.54
vertical gutter: 0

Saturday, 21 May 2011

Parsing the query string in Javascript into a single GLOBAL object


Two useful ideas combined:

1. From the book "Javascript the good bits", comes the idea to put all your (Javascript) global variables as ?? of a single global object called GLOBAL like this

var GLOBAL={}
GLOBAL.v1="value1";
GLOBAL.v2=0xFF;

2. If the html document is called with a URL with a search string (file.htm?v1=value1&v2=0xFF) then using Javascript you can parse the query string in the following way...

// http://stevenbenner.com/2010/03/javascript-regex-trick-parse-a-query-string-into-an-object/
// load GLOBAL with properties from the querystring at the end of the URL
// e.g. "?session=2010_2011&mod_id=COA122" produces GLOBAL.session='2010_2011' & GLOBAL.mod_id='COA122'

var GLOBAL={}

location.search.replace(
  new RegExp("([^?=&]+)(=([^&]*))?", "g"),
  function($0, $1, $2, $3) {
    var e="GLOBAL."+$1+" = '"+$3+"'"; 
    //alert(e); 
    eval(e);
  }
);

Thursday, 12 May 2011

Removing rowspan from a table

I had written a data mining (scraping) script to obtain data from a table and it was working - until the table started having rowspan entries in it. I decided the easiest way to continue was to write a script to replace the rowspan entries with the requisite number of simple entries.

Here is the rowspan replacement script I used (it is written in Javascript and uses jQuery)
The reverse() bit is needed to preserve order - the script uses prepend to insert new elements so we have to start with the last element that needs work and finish with the first.


function replace_rowspan(section){
$.fn.reverse = [].reverse; //http://forum.jquery.com/topic/jquery-reverse-a-collection-of-jquery-elements
//script to process an array containing rowspan and re-write it without rowspan by putting in all the repeats
while($(section).find("td[rowspan]").length>0){ //are there any rowspans left
$(section).find("tr>td[rowspan]:first").each(function(i,tdi){ //find a row with a rowspan
var the_row=$(tdi).parents("tr");
$(the_row).find("td[rowspan]").reverse().each(function(j,tdj){
var c=$(tdj).clone();
var rs=$(tdj).attr("rowspan")-1;
var v=$(tdj).text();
$(tdj).removeAttr("rowspan");
if(rs>=2) //if the rowspan left is 2 or more, then leave the rowspan attribute in and let it be processed next time round
$(the_row).next().prepend($(c).attr("rowspan",rs).addClass("green") );
else if(rs==1) // otherwise this will be the last new entry and the rowspan attribute can be removed
$(the_row).next().prepend($(c).removeAttr("rowspan").addClass("red") );
})
})
}
}

Tuesday, 12 April 2011

Google Docs

iGoogle is http://www.google.com/ig
but the Lboro special one is http://partnerpage.google.com/lboro.ac.uk

If you want to write Gadgets you should add to iGoogle the following 2 gadgets: Google Gadget Editor (GGE) and the Gadget Checker

To use a DIY gadget on your own iGoogle, select publish on the GGE and IGNORE THE DIRE VALIDATION WARNINGS OF THINGS THAT NEED TO BE FIXED, then choose "Add to my iGoogle page"

If you want to have a Google Doc on view at iGoogle, use the gadget "Fetch the content of a Google document". Under "edit settings", make sure the URL you put is the "uploaded" URL of the document, not the editing URL - see Share|"Publish to the web..." from the document editor.

I have had trouble with Safari reporting Script TimeOut which may be related to multiple sign-in which I had turned on temporarily [Slow Script - Safari is no longer responding because of a script on the webpage “iGoogle” (http://partnerpage.google.com/lboro.ac.uk). Do you want to stop running the script, or let it continue?]

I get the same trouble with Firefox reporting "A script on this page may be busy, or it may have stopped responding. You can stop the script now, or you can continue to see if the script will complete. Script: https://docs.google.com/static/document/client/js/1254644934-kix_main_i18n_kix_core.js:115"

"User Preferences" and writing all the HTML content dynamically is dealt with at http://code.google.com/apis/gadgets/docs/basic.html.

"Saving state" is dealt with at http://code.google.com/apis/gadgets/docs/fundamentals.html.
Note especially the bit about saving into a json string.

When working with UserPrefs I thought that gadjets.json.parse(string) was not working - but I read somewhere that you have to put gadgets.json.parse(gadgets.util.unescapeString(string))

Monday, 10 August 2009

Kickoff

This will be used for personal and/or work related entries