Friday, April 29, 2016

Automating maintenance of i18n files

Have you ever wished in Backbone or Angular or Handlebars you didn't have to change your template and then go and update the i18n file as well?

Try this Nodejs code. It picks up the strings from your template files and builds a new i18n file each time you build from them for you to use:

var newKeyFile='var __ = {';

filenames.forEach(function(filename) {
if(filename.indexOf(".svn") == -1){/*if it is not the subversion file, parse the contents*/
var content = fs.readFileSync('templates/' + filename, 'utf-8');
while(content.length&&content.indexOf('{{_')!=-1){ /*while engliish strings remain to be extracted*/
content = content.substring(content.indexOf('{{_')); /*trim content*/
var stringToAdd = content.substring(5,content.indexOf('"}}'));
content = content.substring(content.indexOf('"}}')+3);
newKeyFile+='"'+stringToAdd+'":"'+stringToAdd+'",\n';
}
}
});

newKeyFile+='};';

/*write master english key file so we don't have to manually maintain it*/
var lang = fs.writeFileSync("lang/"+locale+"_buildtime.js",newKeyFile,"utf-8");
eval(newKeyFile);

Monday, July 23, 2012

How to really get the right version of Internet Explorer in JavaScript



This is a simple function to really return the right version of Internet Explorer. Pieces are cobbled together from my old work and dojo's inner libraries too.

function getInternetExplorerVersion()
// Returns the version of Internet Explorer or a -1
// (indicating the use of another browser).
{
  var rv = -1; // Return value assumes failure.
  if (navigator.appName == 'Microsoft Internet Explorer')
  {
    var ua = navigator.userAgent;
    var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
    if (re.exec(ua) != null)
      rv = parseFloat( RegExp.$1 );
//In cases where the page has an HTTP header or META tag with
//X-UA-Compatible, then it is in emulation mode.
//Make sure isIE reflects the desired version.
//document.documentMode of 5 means quirks mode.
//Only switch the value if documentMode's major version
//is different from isIE's major version.
var mode = document.documentMode;
if(mode && mode != 5 && Math.floor(rv) != mode){
rv = mode;
}
  }
  return rv;
}

Wednesday, July 18, 2012

TimeTextBox in Dojo


//I wrote this to overcome a limitation in dojo. I created a combined Date Time control
// and wrote this to enable the time control part to have a start and end time set on it


dojo.declare("com.kana.base.widget.field.TimeTextBox", dijit.form.TimeTextBox, {
rangeCheck: function(/*Date*/date, constraints) {
// summary:
// disables dates outside of allowedDates, or if there are no allowedDates,
//  outside of the min/max of the _DateTimeTextBox
if(this.selector == "time") {
date = dojo.date.locale.format(date, {
selector: "time",
timePattern: "HH:mm:ss"
});
date = date.split(":");
date = parseFloat(date[0] + ":" + date[1]);

if(constraints.max) {
var max = constraints.max.split(":");
max = parseFloat(max[0] + "." + max[1]);
}

if(constraints.min) {//if it is less than the max and greater than the min
var min = constraints.min.split(":");
min = parseFloat(min[0] + '.' + min[1]);
}
if(max && min) {
return (max >= date) && (date >= min);
}
else if(max)
return (max >= date);
else if(min)
return (date >= min);
}
return this.inherited(arguments);
},
setShowing: function(isShowing) {
if(this.showing != isShowing) {
this.showing = isShowing;
this.domNode.style.display = isShowing ? '' : 'none';
}
},
_end: 0
});

// Prototype to get the readonly string for date.
com.kana.base.widget.field.DateTime.getReadOnlyString = function(dateTimeString, datePattern, timePattern, showDate, showTime) {

if(dateTimeString) {
var constr = {};
var dateString = "";
var timeString = "";
if(!(showDate === false)) {
if(datePattern) {
constr.datePattern = datePattern;
}
else {
constr.datePattern = "M/d/yyyy";
//default
}
constr.selector = "date";
dateString = dojo.date.locale.format(new Date(parseInt(dateTimeString)), constr) + " ";
}
if(!(showTime === false)) {
if(timePattern) {
constr.timePattern = timePattern;
}
else {
constr.timePattern = "h:mm a";
//default
}
constr.selector = "time";
timeString = dojo.date.locale.format(new Date(parseInt(dateTimeString)), constr);
}

return dateString + timeString;
}
return "";
//if passed null, give blank string
};

Friday, May 6, 2011

Making Events global instead of passing them in FF

Here's a good solution for an old old problem.

IE has always had window.event to allow you to grab an event from anywhere instead of passing it all over the place but Firefox and other 'standard compliant' browsers have been much less convenient. Well, here's the solution. Overwrite the window.event and its related properties. Here's a nice method to do it:


function mapEventToNS(e, win)
{
   if(!window.ActiveXObject){
win.event = e;
win.event.srcElement = e.target;
win.event.x = e.x;
win.event.y = e.y;
return true;
   }
}

Friday, June 11, 2010

Violation Table + Filter

At some point I was given the task to build a working filter for our Violations Tables and it had to work for Firefox as well as IE. The filter needs to transform before the main three tables because it determines what can be shown in them. I experienced a number of difficulties with synchronizing the different xml transforms since there are several going on on this page, and some needed to be done before others. I succeeded but my solution was not as nice (code wise) as I would have liked. Later on, Firefox finally started supporting asynchronous xml and xsl downloads so I could tell better when things would finish instead of polling the ready state. Click on the image to the right to see my end result better.



Here's a snippet of my filter code so you'll be able to do that same: (new way)

function setXML(sourceURL) {
          this.xmlSource = sourceURL;
          if(window.ActiveXObject)
          {
            treeXml = new ActiveXObject('Microsoft.XMLDOM');
            treeXml.async = false;
            treeXml.load(sourceURL);
            this.XML = treeXml;

          }else{
            xmlhttp=new XMLHttpRequest();
            //xmlhttp.onreadystatechange=xml_Change;old way
            xmlhttp.open("GET",this.xmlSource,true);//"sourceURL"
            xmlhttp.overrideMimeType("text/xml");
            xmlhttp.send(null);

            setXML();//new way
          }
      }
      ViolationsFilterTable.prototype.setXML = setXML;

function setXML(){
      var xmlTree = xmlhttp.responseXML;
      lookupObject('filterTable').setMyXML(xmlTree);
      lookupObject('filterTable').setXmlLoaded(true);
      lookupObject('filterTable').initFilterTableFinal();//now transform in Firefox
call loadXSL(); (now with less waiting and polling) }


(old way) function xml_Change()//function for finished loading XSL
        {
            if (xmlhttp.readyState==4)//loaded = 4
            {
                if (xmlhttp.status==200)//status ok = 200
                {
                    var xmlTree = xmlhttp.responseXML;
                    lookupObject('filterTable').setMyXML(xmlTree);
                    lookupObject('filterTable').setXmlLoaded(true);
                    lookupObject('filterTable').initFilterTableFinal();//now transform in Firefox

//call loadXSL(); (old way)
                }
            }
        }

Thursday, June 10, 2010

Tutorial: Special Concerns With CSS and JavaScript

If you want to edit existing CSS and JavaScript, I wish you the best. Here are some guidelines I have come up with for myself to try and minimize collateral damage. You see every css entry or JavaScript class might only be used in one place or it could be used in a thousand places. Sometimes if you change the padding or the position the tiniest bit it will throw something off someplace else.

My best suggestion is to build a class that will stand the test of time and then don't touch it. sometimes its even better to make a new specialized class rather than alter existing ones that could break countless pages. Also feel free to comment in the css if you need to to remember which class that is or which classes it goes with to match baselines.

If it is impossible to avoid editing your existing CSS or JavaScript classes, due to one reason or another(as is too frequently the case), I recommend doing a search over the app to see where it is used. If possible, test each and every one of the unique looking cases after you change whatever it is you need to change.

Some of the more benign (meaning they usually don't mess up where things are) things to change are:
background styles
color
cursor
font-family, font-size, other font-stuff
text-shadow
most white-space ones overflow:hidden

The moderately powerful (or dangerous) ones are:
border(border affects the width in Firefox)
left
text-align
text-indent
overflow:visible
padding
position:relative
top
white-space:nowrap(this can cause it to overflow

The very powerful ones are:
display:block,table-row, or none
float(necessary to line up divs or give spans widths in Firefox)
height
line-height
margin(in IE it can cascade)
position:absolute
width
vertical-align


Internet Explorer does not interpret everything in JavaScript the same way as other browsers. It has unique methods that the others do not have, and it lacks some things that the others DO have. Most of the time, you can fortunately put code in just two groups: IE and non IE.
In order to specify that you want code to execute in IE only or not there is an easy shortcut.
We just attempt to make a proprietary IE JavaScript object, also known as an ActiveXObject?
if(window.ActiveXObject)//IE code
{

}else{//Other browsers code

}

Now you might be wondering which things are IE only and which are Firefox. Most normal methods are supported in both. But here's a link to a nice list of the DOM methods
If you stick to the the DOM to do your work you should be ok in most cases but the following are some incompatible differences between browsers.

  1. myObject.getAttribute("className"); for IE, myObject.getAttribute("class"); for Firefox
  2. Getting the Size of the Viewport, or Browser Window: document.documentElement.clientWidth;(or Height) for IE, window.innerWidth; for Firefox
  3. Event codes! All event codes are differently handled and event is global automatically in IE and not in any other browsers. event.srcElement versus event.target for Firefox to get the thing that started the event. In order to pass event along for firefox to use you must include it in the root method. I.e.


    Run like the Wind
  4. To get keyCodes from events use our allEve(event).key; method in Utils.js which works in all browsers
  5. After you do a var someNodes = selectNodes(yourXML or XSL) you must use someNodes.item(x); for IE and someNodes[x] for Firefox
  6. When you create a DOM element Firefox now requires you to declare its name-space: document.createElementNS("",'div'); but no other browser supports this.(yet) use document.createElement("div"); for most
  7. In IE you can easily make a node from a String like this openNode = 'false'; using our handy dandy createNewXmlNode(openNode) function. In Firefox you must build it from scratch with lots more code.
  8. instead of using .text .innerText, or .textcontent, instead use .firstChild.nodeValue which will work for both browsers
  9. appendchild works in both but it will not overwrite things so you must remove child first
  10. Using appendChild in Firefox on data that has been inserted via innerHTML will give you dead HTML that you cannot interact with. Use a floating/modal div to display form inputs instead if you can.
  11. font webdings only works in IE. The chars for arrows are 4 and 6. For Firefox you must use the actual HTML char values: '►' and '▼'

Flash Website

I'm currently working on the following flash/php website. It is under construction but it demonstrates some of the things I can do for employers http://graphix.bizland.com/ 
If you wish to stick to the flash parts of the website, click on the left button "browse logos" Otherwise feel free to play around with whatever works.