【保存版】スマートフォン制作でよく使うJavaScript まとめ
2013.10.21
この記事は最終更新日から1年以上が経過しています。
今回は、スマートフォンサイト、webビューApp(ハイブリッドApp)等HTML5、CSS3、JavaScript等を用いてコンテンツを制作する際によく使う(使うと便利)JavaScriptをまとめてみました。
ユーザーエージェント
スマートフォンサイトを制作する際に、ユーザーエージェントを取得し端末により表示や関数を実行したりすることが多々あります。
取得方法、振分け方等の詳細は当サイトやその他のweb情報サイトにも多々UPされているかと思いますのでそちらをご参照ください。
それではscript
var ua = navigator.userAgent, uaFunc = function(s,h) { return (h.indexOf(s) > -1)}; var userInfo = {}; if(uaFunc("iPhone", ua)) { userInfo.device = "iPhone"; } else if(uaFunc("iPad", ua)) { userInfo.device = "iPad"; } else if(uaFunc("Android", ua)) { userInfo.device = "Android"; } else { userInfo.device = "PC"; }
更に、OSのバージョンによって色々分岐させたい時も発生します。
iPhone、AndroidのOSのバージョンの取得方法は以下となります。
function uaGetVer(myKey,contextEnd) { var myStart = ua.indexOf(myKey) + myKey.length, myEnd = ua.indexOf(contextEnd, myStart); return "Ver." + ua.substring (myStart,myEnd); }
それぞれバージョンが記載されている文字列を検索し、取得する方法となります。
iPhoneに関しては5_0等、「_」が付く表記となりますので、置換処理等を行うと良いでしょう。
まとめたscriptはこちらとなります。
script
var ua = navigator.userAgent, uaFunc = function(s,h) { return (h.indexOf(s) > -1)}; var userInfo = {}; if(uaFunc("iPhone", ua)) { userInfo.device = "iPhone"; } else if(uaFunc("iPad", ua)) { userInfo.device = "iPad"; } else if(uaFunc("Android", ua)) { userInfo.device = "Android"; } else { userInfo.device = "PC"; } if(userInfo.device == "iPhone") { userInfo.ver = uaGetVer("iPhone OS", "like"); } else if(userInfo.device == "iPad") { userInfo.ver = uaGetVer("CPU OS", "like"); } else if(userInfo.device == "Android") { userInfo.ver = uaGetVer(userInfo.device, ";"); } else { userInfo.ver = null; } function uaGetVer(myKey,contextEnd) { var myStart = ua.indexOf(myKey) + myKey.length, myEnd = ua.indexOf(contextEnd, myStart); return "Ver." + ua.substring (myStart,myEnd); }
要素位置(座標)取得
特定の要素の座標を取得したい。と言ったとき、div.position 等で取得できそうでできないのがJavaScriptです。w
windowに対する座標を取得する方法は、特定の要素の親要素のoffsetTopを取得し、更にその親要素のoffsetTop..
とscriptの再帰を行い取得していくやり方となります。
var elm = document.getElementById("elm"); var getElmPosition = function(elm) { var left = 0, top = 0; while(elm.parentNode) { left += elm.offsetLeft; top += elm.offsetTop; elm = elm.parentNode; } return {"left" : left, "top" : top}; } var elmPos = getElmPosition(elm);
配列のクローン(ディープコピー)作成
ある配列をコピーしたい。と思い、
var defaultItem = [0,1,2,3,4,5,6,7]; cloneItem = defaultItem;
このように記述してもJavaScriptではオブジェクトを参照しているので途中コピー元の値が変更すると、
defaultItem[0] = 5;
コピー先の値も変更してしまう結果となります。
コピー先の値を変更しない様にするには、さらに配列に格納し再帰を行いコピーするやり方となります。
var cloneItem = new Array(); var defaultItem = [0,1,2,3,4,5,6,7]; //clone Array.prototype.clone = function() { if (this[0].constructor == Array ) { var ar, n; ar = new Array(this.length); for(n = 0; n < ar.length; n++) { ar[n] = this[n].clone(); } return ar; } return Array.apply(null, this); } for(var i = 0, il = defaultItem.length; i < il; i++) { cloneItem = defaultItem.clone(); } defaultItem[0] = 5;
translateプロパティ取得
現在適応されているCSS StyleをJavaScriptでstyleを取得する際、
getComputedStyle(Element, null);
等で取得することが可能となっております。
このように取得することができます。
更にこのようにCSSプロパティを指定することによって、各プロパティの値を取得することができます。
getComputedStyle(Element, null).getPropertyValue("cssプロパティ名");
web技術を用いて、よりリッチなコンテンツを作ろうとした際、CSS3 のtranslateやscale等のtransformプロパティを扱うことが多々あります。
そこでtranslateのプロパティを取得しようと、
window.getComputedStyle(elm, null).getPropertyValue("-webkit-transform");
としても
このような値で帰ってきて思ったように値が取れないかと思います。
これは、transformがmatarix値で設定されている為となります。
matarixはmatrix(a, b, c, d, e, f) との様に6つの値で要素を変化させることが可能です。
1番目の数値は、水平方向の縮尺(a)
2番目の数値は、垂直方向の傾斜率(b)
3番目の数値は、水平方向の傾斜率(c)
4番目の数値は、垂直方向の縮尺(d)
5番目の数値は、水平方向の移動距離(e)
6番目の数値は、垂直方向の移動距離(f)
デフォルトの値はmatrix(1, 0, 0, 1, 0, 0)となっています。
translateの場合だと、 5番目の水平方向の移動距離と、6番目の垂直方向の移動距離を変化します。
つまり、matrix(1, 0, 0, 1, 10, 10)はtranslate(10px,10px)と同じとなります。
このmatrix値を取得するscriptとなります。
var computedStyle,mat,a,b,c,d,e,f, reMat = /matrix\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\,\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\)/; computedStyle = window.getComputedStyle(elm, null); mat = computedStyle['-webkit-transform'].match(reMat).slice(1); a = parseFloat(mat[0], 10); b = parseFloat(mat[1], 10); c = parseFloat(mat[2], 10); d = parseFloat(mat[3], 10); e = parseFloat(mat[4], 10); f = parseFloat(mat[5], 10);
使用例:
HTML
<div id="result"></div> <div id="elm" style="margin:60px 0 0 80px; width:100px; height:100px; background:#f00; -webkit-transform:translate(20px,10px);"></div>
JavaScript
var div = document.getElementById("result"), elm = document.getElementById("elm"); var computedStyle,mat,a,b,c,d,e,f, reMat = /matrix\(\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\,\s*(-?\d+(?:\.\d+)?)\s*,\s*(-?\d+(?:\.\d+)?)\s*\)/; computedStyle = window.getComputedStyle(elm, null); mat = computedStyle['-webkit-transform'].match(reMat).slice(1); a = parseFloat(mat[0], 10); b = parseFloat(mat[1], 10); c = parseFloat(mat[2], 10); d = parseFloat(mat[3], 10); e = parseFloat(mat[4], 10); f = parseFloat(mat[5], 10); div.innerHTML = "mat:" + mat + "<br>" + "a:" + a + "<br>" + "b:" + b + "<br>" + "c:" + c + "<br>" + "d:" + d + "<br>" + "e:" + e + "<br>" + "f:" + f + "<br>";
二度押し防止
スマートフォンサイトを制作していると、ボタンを押して処理までに時間がかかり、
ユーザーが「押してない」と判断してしまいもう一度ボタンが押されて、二度アクセスが行ってしまいエラーが起きてしまった。
などのトラブルが起こりがちでありますので、コレを防止する処理となります。
最初のtouchendから一定時間経過しないともう一度実行できない様にするやり方となります。
function noDoubleTap(doubleTapElms) { var accessTime = 1500, doubleAccess = false, doubleTapElms = doubleTapElms; var doubleTapController = function() { var that = this; that.init = function() { for(var i = 0;i < doubleTapElms.length;i++) { doubleTapElms[i].addEventListener("click", function(e){that.doubleTapFunc(e);}, false); doubleTapElms[i].addEventListener("touchstart", function(e){that.doubleTapFunc(e);}, false); doubleTapElms[i].addEventListener("touchend", function(e){that.doubleTapFunc(e);}, false); } } }; doubleTapController.prototype = { doubleTapFunc: function(e){ if(e.type == "touchstart" || e.type == "click"){ return; } else{ if(doubleAccess == false){ doubleAccess = true; setTimeout(function(){ doubleAccess = false; },accessTime); } else{ e.preventDefault(); return; } } } } var doubleTapControll = newdoubleTapController(); doubleTapControll.init(); } document.addEventListener("DOMContentLoaded", function(){ var doubleTapElms, doubleTapClass =['.js_doubleTap']; for(var name in doubleTapClass) { if(doubleTapClass.hasOwnProperty(name)){ doubleTapElms = document.querySelectorAll(doubleTapClass[name]); noDoubleTap(doubleTapElms); } } }, false);
Ajax処理
最後にAjax処理となります。
それぞれ、エラーが発生した際、成功した際の処理を追加してください。
var AjaxTime = 10000; var AjaxPath = { requestFile: "ajaxPath" }; var AjaxController = function(){}; AjaxController.prototype ={ createHttpRequest: function() { try { return newXMLHttpRequest(); } catch(e){} }, ajaxError: function() { return; }, requestFile: function() { var that = this, httpObj = that.createHttpRequest(); var timeout = false, timer =setTimeout(function(){ timeout = true; httpObj.abort(); }, AjaxTime); httpObj.open("POST",AjaxPath.requestFile, true); httpObj.onreadystatechange = function() { if(httpObj.readyState !== 4){ return; } if(timeout) { that.ajaxError(); return; }; clearTimeout(timer); if(httpObj.status == 200){ } } httpObj.send(null); return; } }
ではではぁ