mobile detection for coldfusion - mobile

Is there a way to detection if a user is on a mobile device using just coldfusion only?
I'm not doing a mobile redirect.
I am using CSS media queries to change the layout to fit screen width.
I just want to do a simple if mobile render this information else render this information instead to parts of the site not the whole thing. (ex: if mobile [show jquery animation] else show [link])
I don't want to waste time rendering both if only to do a display none to the info not going to be shown anyways.
No javascript mobile detection (people might have javascript off on their browsers)

I used the code up at http://detectmobilebrowsers.com/ to do this. They keep the regex pretty current. The about page there has details on tablets if you need that as well as mobile. Drop if in a UDF function in order to easily keep it up-to-date on further changes.
The CFM version:
<cfif reFindNoCase("android.+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino",CGI.HTTP_USER_AGENT) GT 0 OR reFindNoCase("1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|e\-|e\/|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\-|2|g)|yas\-|your|zeto|zte\-",Left(CGI.HTTP_USER_AGENT,4)) GT 0>
<cflocation url="http://mobile.yoururl.com">
</cfif>

I wrote a blog entry about this very thing!
http://www.mccran.co.uk/index.cfm/2010/6/4/Simple-Coldfusion-script-to-detect-if-a-user-is-on-a-Mobile-platform
<cfif findNoCase('Android', cgi.http_user_agent,1)>
<!--- relocate to Android version of the mobile site --->
<cflocation url="android/">
<cfelseif findNoCase('iPhone', cgi.http_user_agent,1)>
<!--- relocate to iphone version of the mobile site --->
<cflocation url="iphone/">
</cfif>
You can easily detect the browser from the user agent string. Tho as I've experienced recently browsers like chrome will allow you to change your user agent string:
http://www.mccran.co.uk/index.cfm/2011/9/25/Samsung-Galaxy-Tab-101-Switching-your-browser-from-mobile-view

Use CGI.HTTP_USER_AGENT:
<cfif (CGI.HTTP_USER_AGENT is "MobileAgentOne")>
replace MobileAgentOne with the browser you are looking for.
A quick google should provide you with an adequate list of Mobile agents currently in-use, such as: http://www.useragentstring.com/pages/Mobile%20Browserlist/
If you'd like to be a tad more robust, here's a way to provide partial matches, so you can look for families of mobile phones, rather than listing out one million different unique mobile agents:
<cfset agentList = "ASUS,AUDIOVOX,BenQ">
<cfloop list="#agentList#" index="thisAgent">
<cfif FindNoCase(thisAgent, CGI.HTTP_USER_AGENT)>
Found
</cfif>
</cfloop>

You can examine the value of CGI.HTTP_USER_AGENT and see if it indicates that the client is a mobile.
Here's a quick snippet based on some Python code I found but there may be more advanced checks you can do:
<cfif refindNoCase
( 'android|blackberry|iphone|ipod|mobile|palm|phone|windows\s+ce'
, CGI.HTTP_USER_AGENT
)>
probably mobile
</cfif>

(Apologies for making this an answer, but I'm unable to comment here.)
Testing for the string 'android' catches a bunch of tablets (motorola xoom, samsung galaxy tab, asus transformer, others from toshiba, sony, acer, etc.). Android is an OS, not a class of devices.
I'd say a realistic answer depends a lot on what you consider to be a "mobile" device. Arguably, many tablets do just fine with "normal" (non-mobile) sites, given their processing power and physical screen size, so lumping them in with much smaller and less capable mobile phones does those users a disservice.
Note that 'iPhone' is listed in several previous answers, but not 'iPad', so they implicitly exclude iOS tablets, which I believe is correct for android too.
An answer based on that approach is much less trivial, unfortunately. Various solutions are out there on the net, one basic version of which is to look for the word mobile and exclude some tablet-specific strings such as tablet, pad, xoom, eeepc, flyer, etc. However, new devices appear every week, and chasing even the most popular ones will be a challenge at best.

Does the detectmobilebrowsers.com solution go in the header? Is there any reason not to put the detection line before the header? I have a frameset (I know, not ideal...) and I think the frameset is getting detected first and loading my frames before running the detection script runs. (Is that possible?)
It works fine in the header with android, but not kindle, ipad or iphone (I added an ipad line).
Thanks for reading,
LPP

(Sorry for answering instead of commenting, I'm not able to comment or vote up)
I initially liked mujimu's solution. I put it on my site and it seemed to work well testing with my own iphone. However, I started testing with this http://www.mobilephoneemulator.com/ and it didn't work for a majority of devices.
Here's what I would do (and will do). Output something like this in a discreet location <cfoutput>#CGI.HTTP_USER_AGENT#</cfoutput>. Then test and record what the devices output.
Then, use something like this (thank you Peter Boughton) and in between the pipes, use a distinct keyword from the testing...
<cfif refindNoCase
( 'distinct_keyword|android|blackberry|iphone|ipod|mobile|palm|phone|windows\s+ce'
, CGI.HTTP_USER_AGENT
)>
probably mobile
</cfif>
After my initial testing here's the list I've come up with. Please let me know if you think this is accurate...
ARCELIK,Access,Acer,Ahong,Aiko,Airis,Airness,Alcatel,AlphaCell Wireless,Amazon,Amoi,Amoisonic,Android,AnexTek,Apple,Archos,Asmobile,Aspen,Asus,ASUSTeK COMPUTER INC.,Audiovox,Becker,BEKO,Bellawave,BellWave,BenQ,BenQSiemens,BenQ-Siemens,Bird,Bleu,Blue Coat,B-Mobile,Bolt,Bytemobile,Capitel,Casio,CDM,CECT,CheckCom,Cingular,Cking,Compal,Compaq,CoralWeb,Cricket,Dai Telecom,Dallab,Danger,Daxian,DBTEL,Dicam,Dmobo,DoCoMo,Dopod,Doris,DreamPhone,EDL,Elite,ELSON,Emblaze,Emobile,Enteos,Era,Ericsson,Ericy,ETEN,EZIO,EZZE,Fitel,Fly,Fujitsu,generic,generic web browser,Generic Windows,Generic Windows Mobile,GIGABYTE,Gionee,Google,Gradiente,Grundig,Haier,Handspring,Hedy,Hei,Helio,Hewlett-Packard,Hisense,Hitachi,HP,HTC,HTC Corporation,HTIL,HUAWEI,Hummer,IAC OKWAP,IAC OKWAP Mobile Communications,Idea,iKoMo,IM,Imate,i-mate,i-mobile,Infineon,InfoSonics,Innostream,INQ Mobile,Itelco,IXI,KCM,KDDI,KDDI - SonyEricsson,KDDI-Casio,KDDI-Hitachi,KDDI-Kiocera,KDDI-Kyocera,KDDI-Panasonic,KDDI-Pantech,KDDI-Sanyo,KDDI-Sharp,KDDI-SonyEriccson,KDDI-SonyEricsson,KDDI-Toshiba,Kejian,Kisen,Klondike,KONKA,Kozi,KPT,K-Touch,Kyocera,Kyocera Wireless Corp,LCT,Lenovo,Lenovo Mobile,Lexibook,Lexus,LG,LG Electronics,LGE,Lobster,Longcos,LT,LXE,M3 Gate,Malata,MAUI-based Generic,Maxon,Medion,MicroMax,Microsoft,MIO,Mio Technology,Miracle,MiTAC,Mitsubishi,Mobile Wireless Group,MOBISTEL,Modelabs,ModelLabs,Modottel,Modu,MOMO Design,Morange,Motorola,Myphone,NEC,Neonode,Newgen,Nexian,Nintendo,Nokia,Novarra,NTT DoCoMo,NTT DoCoMo FOMA 3G,O2,ONDA,Openwave,Opera,Optimay,Orange,Palm,PalmOne,Panasonic,Panda,Pantech,PCD,Philips,PhoneOne,Pirelli-Arcor,Porsche Design,Porshe,Poseidon,Psion,QCI,QMobile,Qtek,Raks,Reporo,Research In Motion Ltd.,RIM,Robot,Ron,Rover,RT,Sagem,SAMART,Samsung,Sanyo,SavaJe,SEC,Semc,Sendo,Sharp,Siemens,Skyfire,Skyspring,Skyspring Vitelcom,Skyworth,SKYZEN,SlobTrot Software,SmartTrust,Smile,SoftBank,Sonim,Sony,Sony Ericsson Mobile Communications,SonyEricsson,Spice,Sprint,SPV,Sunrise,TCL,Techfaith,Tel.Me.,Telecom Italia,Telit,TIANYU,T-Mobile,Toplux,Toshiba,Tranxcode,TTPCom,tvCompass,tvCompass DMR1500,Ubiquam,UCWEB,Uniscope,Unistar,Uriver,Usha Lexus,Utec,UTStarcom,V3m (Metro PCS),Vacom,Velocity Mobile,Venera,Verizon,Vertu,VeryKool,VERZIOWORLD,Vitelcom,VITELCOM for Telefonica Movistar,VK,VK Mobile,Vodafone,Vodafone ZTE,Voxtel,W3C,Wapamp,Wapsilon,WAPUniverse,WellcoM,WinWAP Technologies,Wonu,XDA,Yas,Yospace Ericsson,Yospace Motorola,Yospace Nokia,Yospace Sharp,Yospace Siemens,Yospace SonyEricsson,Yulong,Zonda,ZT,ZTE,.mobi

Per the following JavaScript answer, a better solution may now be to use something like the following, which avoids issues with changing user agents.
https://stackoverflow.com/a/24600597/1427373
Adapted for ColdFusion:
<cfset mobileDevice = false>
<!--- Detect if we are using a mobile device --->
<cfif reFindNoCase("Mobi|Android", CGI.HTTP_USER_AGENT) NEQ 0>
<cfset mobileDevice = true>
</cfif>

Related

Interpolating custom data onto a PDF

I am building an Angular test preparation app (with Laravel 5.1 API). One of the requirements is to allow the user to print a certificate of achievement.
The client wants the person's name and credentials interpolated into the document (e.g., highlighted below). Here is a snapshot of the PDF template they sent:
The way I'm handling PDF viewing is simply by storing the file on S3 and giving them a link to that file.
Interpolating information into a PDF doc doesn't seem trivial and I haven't found much information on programmatically allowing this, but there are tools like DocHub, that allow you do edit while viewing the PDF.
I'm interested in learning:
is doing this programmatically trivial?
are there 3rd party tools I'm unaware of?
would I even be able to send this information along to the S3 link to interpolate in the first place?
Using PDF as a format for editing is usually a bad choice. If you have a form with fixed fields, then it's easy. Create a PDF template with an interactive form. In this form, based on AcroForm technology, you'll define fields with fixed coordinates, and a fixed size. You can then add content to these fields.
One major disadvantage with this approach is the lack of flexibility. Did you notice that I used the word "fixed" three times in the previous paragraph? If text doesn't fit the predefined field, you're out of luck. If the field is overdimensioned, you'll end up with plenty of white space. This approach is great if you can predict what the data will be like. A typical use case is a ticket or a voucher. For instance: the empty form is a really nice page, with only a couple of fields where an automated system can put a name, a date, a time, and a seat number.
This isn't the best approach for the example you show in your screen shot. The position of every line of text, every word, every character is known in advance. If you want to replace a short word with a long word (or vice-versa), then all those positions (of each line, of the complete page, possibly of the complete document) need to be recalculated. That's madness. Only people with very poor design skills come up with such an idea.
A better idea, is to store the template as HTML. See for instance chapter 5 of iText's pdfHTML tutorial, where we have this snippet of HTML:
<html>
<head>
<title>Invitation to SXSW 2018</title>
</head>
<body>
<u><b>Re: Invitation</b></u>
<br>
<p>Dear <name>SXSW visitor</name>,
we hope you had a great SXSW film festival experience last year.
And we would like to invite you to the next edition of SXSW Film
that takes place from March 9 until March 17, 2018.</p>
<p>Sincerely,<br>
The SXSW crew<br>
<date>August 4, 2017</date></p>
</body>
</html>
Actually, it's not really HTML, because the <name> tag and the <date> tag don't exist in HTML. All HTML processors (browsers as well as pdfHTML) ignore those tags and treat their content as if the tag was a <span>:
It doesn't make much sense to have such tags in the context of pure HTML, but it does make a lot of sense in the case of pdfHTML. With pdfHTMLL, you can configure custom tags, and have a result that looks like the PDFs shown below:
Look at the document for "John Doe" and compare it with the document for "Bruno Lowagie". The name "John Doe" is much shorter than my name, hence more words fit on that first line. The text flows nicely (we could also have chosen to justify the text on both sides). This "flow" is impossible to achieve with your approach, because you will never get a PDF template to reflow nicely.
OK, I get it, you probably say, but what about the practical aspects? You talk about a Java / .Net library, but I am working with Laravel and Angular.js. First, let me tell you that I don't think you'll find any good PDF tools for Laravel or Angular.js, because of the nature of PDF and those development environments (in my opinion, those technologies don't play well together). Regardless of my opinion, this shouldn't be much of a problem for you because you work in an Amazon environment. AWS supports Java, and the Java code needed to get pdfHTML working is minimal. Most of the code samples I wrote for the pdfHTML tutorial are shorter than 15 lines. So why not try Java and pdfHTML?
If you're already using Amazon services, why not use an amazon lambda function, in combination with iText7 (java), to generate the pdf on demand?
That way, you are guaranteed that the pdf is correct, and has nice layout every time.
Generating the pdf can either be done by:
converting HTML,
programmatically creating your entire document,
filling and flattening an XFA form.
I think for your use-case, either option 1 or 2 are the most sustainable.

Phones dialing wrong number from tel-hyperlink

We received a complaint that some visitors to our website are dialing the wrong number to get in contact with us.
Our website has a hyperlink in the following form in the footer:
Call us at 12345678
Note that the "+47" (international code) is NOT displayed visually, it is only included in the hyperlink. But now it turns out a limited number of people (circa one a day) is actually calling a private local number at 47123456. Not many considering the size of our business, but still a major nuisance for the family receiving these calls.
The people calling say they just pressed the link to dial.
Has anybody else had these problems? Is anybody aware of mobile phones that do not properly support the tel hyperlink? Any suggestions for a solution? (Apart from changing our or their phone number, of course.)
There are different ways smart phones pick a telephone number.
some are reading the text of your website - some use the tag
on my first try: I would add the +47 to the displayed telephone number
on my second try (or both together): I would replace +47 with 0047 (its norway - or?)
and before posting i got a third idea: which encoding has the webserver and which encoding has the html / PHP page in sourcecode? Both UTF-8 or something else?
Maybe your server is sending it in a different way than the website is created and somehow some smartphones can't handle it correctly.
The problem here is pretty simple: this is the URL-Encoding.
The + char is an reserved character within the URL and represents an space.
To get an actual + sign replace it with the URL encoded version: %2B
See Links for details:
Wikipedia
W3Scools

Online Maps (google, nokia)

Is it possible to highlight a list of countries with a different colors?
I need to display some countries' statistics on the world map.
Now I use an image and fill a region with color (calculated for each country) by country's coordinates. It's a simple solution and it works well. But now I need to specify the countries' name too (and I think it's not the last customization).
There is a polygon solution, but it uses an array of coordinates. I don't think it's a suitable solution to highlight countries's territory.
I haven't found a solution yet. Any suggestions?
Thanks in advance.
Highlighting countries or regions to support statistics is known as Choropleth Mapping
, but unfortunately there usually isn't direct library support for Choropleth maps bundled into an online map API. This means you'll have to create your own framework, but fortunately it is possible to create one - I wrote an example using jQuery + HERE Maps to
answer the question here
Updated WKT solution now available
Access to KML shapes is no longer required, since the Geocoder API now offers an IncludeShapes attribute which returns the shape of a country in WKT format. A WKT parser can be found here.
A simple WKT choropleth example can be found here.
KML Base solution
For any framework you will need to have a file holding the boundaries of the countries or regions you need. The example uses a KML file, but you could also start with polygons if you had them. Country borders are a political minefield, which is the reason I guess most online mapping APIs steer clear of them. As a hint: try starting with something like http://geocommons.com/overlays/119819 and simplify it as much as possible to speed up the rendering- many small wiggles in the coast lines and small outlying islands are unnecessary.
Of course you could also try searching for "create choropleth map" from a search engine of your choice and use an tool to create a static image for your data (potentially at several zoom levels) and then use this as the basis of an map tile overlay. This requires a lot more work up front, but would push all the calculations server side and hence be faster to display.
Working example can be found on GitHub here
You could put the country's name into the image. It's not that difficult to place text into an image. The only tricky bit is if you are using tiles, you need to deal with names that cross tile boundaries by drawing the name once for each tile.

How (or should I) markup phone numbers in a website?

Im mobile optimising a website with media queries. Without any extra markup the phone numbers seems to be recognised and become 'clickable' on iphones and android, but my windows phone emulator only recognises the 2nd 1/2 of one the numbers.
This method doesnt work on opera mobile:
1234
http://developer.apple.com/library/safari/#codinghowtos/Mobile/UserExperience/_index.html
This method makes the link clickable in desktop browsers, even if the browser doesn't know how to handle the number:
<a href=”#” tel=”1234”>1234</a>
http://www.wpromote.com/blog/google/optimizing-your-web-site-for-mobile-3-easy-tips/
So whats the best solution or trade off for markup around phone numbers? Thanks
The first example (tel:) is an RFC standard: http://www.ietf.org/rfc/rfc3966.txt and, as far as I know, there is no "tel" attribute, so i would prefer the tel-URI.

Google Waves - basic structure

Is a wave limited to the sharing of textual information (HTML), or am I correct in assuming that a wave can contain arbitrary data (represented in XML), so long as it also contains the javascript necessary to render it in a meaningful way?
I ask because the collaborative document preparation demonstrated in the Google I/O video looks very powerful, but there are many other types of documents than simple rtf text. In my case I would be looking interactively to develop gantt charts.
There is a lot that can be done inside each Wave. They have not yet made all features available, but here is a link to some samples: http://wave-samples-gallery.appspot.com/ which includes my Slashdot Gadget:http://wave-samples-gallery.appspot.com/about_app?app_id=18006
The Slashdot Gadget actually takes the RSS feed for Slashdot and displays the latest headlines.
Here is the XML: http://www.m1cr0sux0r.com/slashdot.xml
alt text http://www.m1cr0sux0r.com/xml.jpg
I got access to Google Wave a few days ago, and here's what the raw data for their Sokoban game (which supports two players playing simultaneously on the same board) looks like, for example:
<blip>
<p _t="title">
</p>
<p>
<w:gadget author="blixt#wavesandbox.com" prefs="" state="" title="" url="http://sokoban-server.appspot.com/com.example.simplegadget.client.SokobanGadget.gadget.xml">
<w:pref name="playerAllocation" value="1 1,blixt">
</w:pref>
<w:pref name="totalMoves" value="8">
</w:pref>
<w:pref name="playerPositions" value="1 4,2">
</w:pref>
<w:pref name="rockPositions" value="6 2,2 3,2 14,2 15,2 16,2 4,3">
</w:pref>
</w:gadget>
</p>
</blip>
So yes, you can store any data you like in a single blip, with the possibility to go backwards in "time" to see older versions of the data etc.
By the way, if you're interested in seeing some code for a robot that sits in a wave and interacts with users, I made one for a game I'm developing: Google Code Project for multifarce (and the game in question, it's not really public yet and as such not particularly functional.) The bot source is here: multifarce Wave robot source
Basically, all you need to get a bot running are the 14 last lines in that code. I love it! =)

Resources