ホーム » Javascript
「Javascript」カテゴリーアーカイブ
EventEmitterをちょっと改造
EventEmitterはDOMを使用せずにイベント機能をクラスに与えることが可能なとても便利なクラス。
但し最大の不満はListener登録時にListener内でのthisを指定できない点。
※バージョンは5.2.4
例)リスナーの登録
[code]
var eventEmitter = new EventEmitter();
・・・
eventEmitter.addListener(‘click’, this.on_clicked.bind(this));
[/code]
上記のようにListener登録してしまうとremoveListenerが正しく機能せずにListenerが残ってしまう。
例)リスナーの削除
[code]
eventEmitter.removeListener(‘click’, this.on_clicked.bind(this));
[/code]
これらの問題を対応するためにEventEmitterを以下に従って修正
addListenerの修正
変更前
[code]
proto.addListener = function addListener(evt, listener) {
if (!isValidListener(listener)) {
throw new TypeError(‘listener must be a function’);
}
var listeners = this.getListenersAsObject(evt);
var listenerIsWrapped = typeof listener === ‘object’;
var key;
for (key in listeners) {
if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
listeners[key].push(listenerIsWrapped ? listener : {
listener: listener,
once: false
});
}
}
return this;
};
[/code]
変更後
[code]
proto.addListener = function addListener(evt, listener) {
if (!isValidListener(listener)) {
throw new TypeError(‘listener must be a function’);
}
// tarumi custom
var bind_instance = null;
if(arguments.length > 2){
bind_instance = arguments[2];
}
// tarumi custom
var listeners = this.getListenersAsObject(evt);
var listenerIsWrapped = typeof listener === ‘object’;
var key;
for (key in listeners) {
if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) {
listeners[key].push(listenerIsWrapped ? listener : {
listener: listener,
// tarumi custom
instance: bind_instance,
// tarumi custom
once: false
});
}
}
return this;
};
[/code]
関数:emitEventの修正
変更前
[code]
proto.emitEvent = function emitEvent(evt, args) {
var listenersMap = this.getListenersAsObject(evt);
var listeners;
var listener;
var i;
var key;
var response;
for (key in listenersMap) {
if (listenersMap.hasOwnProperty(key)) {
listeners = listenersMap[key].slice(0);
for (i = 0; i < listeners.length; i++) {
// If the listener returns true then it shall be removed from the event
// The function is executed either with a basic call or an apply if there is an args array
listener = listeners[i];
if (listener.once === true) {
this.removeListener(evt, listener.listener);
}
response = listener.listener.apply(this, args || []);
if (response === this._getOnceReturnValue()) {
this.removeListener(evt, listener.listener);
}
}
}
}
return this;
};
[/code]
変更後
[code]
proto.emitEvent = function emitEvent(evt, args) {
var listenersMap = this.getListenersAsObject(evt);
var listeners;
var listener;
var i;
var key;
var response;
for (key in listenersMap) {
if (listenersMap.hasOwnProperty(key)) {
listeners = listenersMap[key].slice(0);
for (i = 0; i < listeners.length; i++) {
// If the listener returns true then it shall be removed from the event
// The function is executed either with a basic call or an apply if there is an args array
listener = listeners[i];
if (listener.once === true) {
this.removeListener(evt, listener.listener);
}
if(listener.instance===null || listener.instance === ‘null’ || listener.instance === ‘undefined’ || listener.instance === undefined){
response = listener.listener.apply(this, args || []);
}
else{
response = listener.listener.apply(listener.instance, args || []);
}
if (response === this._getOnceReturnValue()) {
this.removeListener(evt, listener.listener);
}
}
}
}
return this;
};
[/code]
リスナーの登録の変更
[code]
eventEmitter.addListener(‘click’, this.on_clicked,this);
[/code]
リスナーの削除の変更
[code]
eventEmitter.removeListener(‘click’, this.on_clicked);
[/code]
POSTでデータが転送できない
POSTでデータが転送されない
スマホ用のサイトを作成しログイン画面を作成。
しかし画面上で入力した値がPOSTでとれない。
今更・・・?
頭がおかしいのか?と思ったが・・・
jQuery Mobileを作成した時はFORM属性にdata-ajax=”false”をつけないといけないとは
jQuery Mobileの役立つサイトメモ
jQuery mobileのスタイルをあてたコントロールが表示されない
スクロールするDIVにjQuery Mobileのスタイルをあてたcheckboxを表示
最初は正しく表示されている
スクロールするとなぜか一番下が表示されない
再度一番上を確認すると表示されない
ちなみにjQuery Mobileのスタイルをあてないcheckboxは問題ない
再描画の問題なのか?DOMのキャッシュの問題なのか?
DIVのスタイルから以下を外すと表示されない問題は解決
[code]
-webkit-overflow-scrolling: touch
[/code]
iPhoneを回転するとzoomControlが隠れる
Leafletモバイルのサンプルページに従ってページを作成。
Leaflet on Mobile
iPhone SE iOSのバージョンは10.3.2
最初はzoomControlも正しい位置に表示されているが、回転するとzoomControlがアドレスバーに隠れてしまう。
HTMLとCSS
[code]
body {
padding: 0;
margin: 0;
}
html, body, #map {
height: 100vh;
width: 100vw;
}
[/code]
対応は回転のイベントで以下の処理を行う
[code]
$(window).bind("orientationchange",function(){
setTimeout(function(){
$(‘html,body’).animate({scrollTop: 0}, 500, ‘swing’);
map.invalidateSize()
}, 400);
})
[/code]
Javascriptでファイルダウンロード
JavaScript+WebAPIでシステム構築をしていると意外と悩むのがファイルダウンロード、アップロード。
多くの場合はWebAPIでダウンロードファイルの情報を照会して別途ダウンロードを行ったり
サーバー上にファイルをアップロードしてからWebAPIを呼び出して更新処理を行う方法が
一般的だったが、最近はWbAPIを使って直接ファイルのアップロード、ダウンロードを行うことができる。(疑似的だが)
■ダウンロード
[code]
var data = {
"layer_no": layer_no,
"point_no": point_no,
"crc": crc
};
m_web_service.call("exportPtaPolygon",
function (data, textStatus, xhr) {
if(!cmn_is_null(data.d)){
if(cmn_is_null(data.d.lats)){
m_common.MsgBox("エクスポート", "エクスポート対象のデータはありません", 0, 0);
m_window.Close("600");
return;
}
var csv = "";
for(var i = 0 ; i < data.d.lats.length ; i++){
csv = csv + data.d.lats[i] + "," + data.d.lons[i] + "\r\n";
}
let downloadData = new Blob([csv], {type: ‘text/csv’});
let filename = ‘PTA.csv’
if (window.navigator.msSaveBlob) {
window.navigator.msSaveBlob(downloadData, filename); // IE用
} else {
let downloadUrl = (window.URL || window.webkitURL).createObjectURL(downloadData);
let link = document.createElement(‘a’);
link.href = downloadUrl;
link.download = filename;
link.click();
(window.URL || window.webkitURL).revokeObjectURL(downloadUrl);
}
m_window.Close("600");
}
else{
}
},
m_common.dummy_function,
data);
[/code]
■アップロード
[code]
var fileref = document.getElementById(id);
var reader = new FileReader();
reader.onload = function(theFile){
var outhtml = theFile.target.result;
var recs = outhtml.split("\r\n");
if(recs.length < 4){
m_common.MsgBox("インポート", "正しいファイルを指定してください", 400, 200);
return;
}
var xs = [];
var ys = [];
for(var n = 0 ; n < recs.length ; n++){
let yx = recs[n].split(",");
if(yx.length == 2){
ys.push(parseFloat(yx[0]));
xs.push(parseFloat(yx[1]));
}
}
var data = {
"layer_no": layer_no,
"point_no": point_no,
"crc": crc,
"xs" : xs,
"ys" : ys,
"user_no" : String(m_master.user_no)
};
m_common.waitmsg_on();
m_web_service.call("importPtaPolygon",
function (data, textStatus, xhr) {
m_common.waitmsg_off();
if(data.d){
m_common.MsgBox("インポート", "インポートしました", 400, 200);
}
else{
m_common.MsgBox("インポート", "インポートできません", 400, 200);
}
m_window.Close("600");
},
m_common.dummy_function,
data);
}
reader.readAsText(fileref.files[0], "shift-jis");
[/code]