SQLの窓

2024年07月24日


JavaScript : window オブジェクトのプロパティとしてグローバル変数を定義する

実際は、右辺にオブジェクトをセットして専用の名前空間で参照できるライブラリのインスタンスとして利用します。

ルートで var で定義する変数と厳密には違うようですが、事実上同じと思っていいと思います。ですから、Fucntion 内でグルーバルな変数を利用したい場合は、window オブジェクトを使用すると良いでしょう
window.変数名 = "lightbox"

または

window["変数名"] = "lightbox"

例えば、ライブラリを簡単にまとめると以下のような定義のしかたになります。
(function(){

    S = {

        // いろいろな定義

        },

    // いろいろな定義
    ;

    window['MyLIB'] = S;

})();


(function(){})(); は、関数を定義して呼び出すのを一度に行う書き方で、無名関数を定義して () で実行しています
<script>

window["MyLIB"] = "lightbox";


(function(){

	alert(MyLIB);

})();

</script>



posted by lightbox at 2024-07-24 10:12 | JavaScript オブジェクト | このブログの読者になる | 更新情報をチェックする

2020年05月25日


ほぼ、Google Chrome 限定ですが Web Speech API の現時点での実装と問題点回避方法

※ 長い文章を試すと、安全なのは 70文字くらいでした。長すぎると壊れて、Google Chrome を再起動する必要がありました

Window.speechSynthesis

何故か最初のロードで speechSynthesis.getVoices() は一覧を取って来ません。この一覧でコンボボックスを作る必要があるので、とても回りくどい事をしています。

インターネットを調べましたが、過去のものは動かないものが多く、理由はこの Voice をセットしていない事が原因でした。



UI を jQuery で実装
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<textarea id="target_text" style='width:300px;height:60px;'>こんにちは</textarea><br>
<input type="button" id="speech_button" value="実行">
<select id="voice"></select>

<script>
var voice_types;

$(function(){

	if ( typeof SpeechSynthesisUtterance === 'undefined' ) {
		$('#target_text').val("Web Speech API は使えません");
	}

	// 初回ロード
	speechSynthesis.getVoices();
	// 詳細取得
	get_voice_type ();

	$("#speech_button").on("click", function() {
		// 念のために取り出す
		voice_types = speechSynthesis.getVoices();
		if ( voice_types.length == 0 ) {
			// 再取得で無かった場合、もう一度
			get_voice_type ();
			return;
		}

		var speech = new SpeechSynthesisUtterance($("#target_text").val());

		// 選択した言語を使う
		speech.voice = voice_types[ $('#voice > option:selected').val() ];

		speechSynthesis.speak(speech);

	});


});

function get_voice_type () {
		setTimeout(function(){
			voice_types = speechSynthesis.getVoices();
			$('#voice > option').remove();
			for( i = 0; i < voice_types.length; i++) {
				$('#voice').append($('<option>').text(voice_types[i].name).val(i));
			}
			$('#voice').prop("value",12);
		},100);
}

</script>

ここでは使っていませんが、pitch は声の高さを 0.1 づつで 1.6 ぐらいが限界みたいです(それ以上はかすれた変な声)。rate は速さで 0.1 づつ増やせますが、1.8 くらいで聞き取りは限界です。

関連する記事

Google Chrome での音声認識処理



posted by lightbox at 2020-05-25 14:57 | JavaScript オブジェクト | このブログの読者になる | 更新情報をチェックする

Google Chrome での音声認識処理






試したくて、マイクを見にヤマダ電機に言ったら、最低でも780円くらいしたのでやめて、古い WEBカメラを引っ張り出して使ったら使えました。

参考にしたのは、こちら

処理の中核を確認して、音声が途切れる毎に表示 DIV を追加する方式にして実装しました。イベントはたくさんありますが、直接必要なのは result イベントです。全く音声がない時間が5秒くらい? 続くと自動的に終わります。

Google Chrome の設定のプライバシーのコンテンツの設定でマイクを選びました。例外の管理では、一度ブロックしたサイトの削除して使えるようにできます。



ソースコード
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

<input id="st_btn" type="button" value="開始">
<input id="ed_btn" type="button" value="終了">
<div id="info"></div>
<div id="result">
	<div id="first_text"></div>
</div>
<script>
var rec = null;
var target = $("#first_text");

$(function(){
	if ( typeof webkitSpeechRecognition === 'undefined' ) {
		$("#info").text("使用できません");
		$("#st_btn").prop("disabled", true);
		$("#ed_btn").prop("disabled", true);
	}
	else {
		// インスタンス作成
		rec = new webkitSpeechRecognition();
		// 初期設定
		rec.lang = "ja-JP";
		rec.interimResults = true;
		rec.continuous = true;
		// イベント登録
		rec.onerror = function(){
			$("#info").text("error");
		};
		rec.onnomatch = function(){
			$("#info").text("nomatch");
		};
		rec.onsoundstart = function(){
			$("#info").text("音検知");
		};
		rec.onsoundend = function(){
			$("#info").text("soundend");
		};
		rec.onspeechstart = function(){
			$("#info").text("スピーチ開始");
		};
		rec.onspeechend = function(){
			$("#info").text("スピーチ終了");
		};

		rec.onstart = function(){
			$("#info").text("開始");
		};
		rec.onend = function(){
			$("#info").text("終了");
		};
		// 結果テキストの作成
		rec.onresult = function(ev){
			var obj = ev.results;
			for (var i = ev.resultIndex; i < obj.length; i++ ) {
				if( obj[i].isFinal ) {
					target.text(obj[i][0].transcript);
					target = $("<div></div>");
					$("#result").append(target);
				}
				else {
					target.text(obj[i][0].transcript);
				}
			}
		};	

		// ボタンイベント
		$("#st_btn").on("click",function(){
			rec.start();
			$("#st_btn").prop("disabled",true);
		})
		$("#ed_btn").on("click",function(){
			rec.stop();
			$("#st_btn").prop("disabled",false);
		})
	}
	
});

</script>

関連する記事

ほぼ、Google Chrome 限定ですが Web Speech API の現時点での実装と問題点回避方法



posted by lightbox at 2020-05-25 02:08 | JavaScript オブジェクト | このブログの読者になる | 更新情報をチェックする

2019年01月17日


JavaScript でテーブル要素の td をクリックしてテキストを選択する / Range オブジェクト

Range オブジェクトを使用して td 内部を選択します。

$(function(){
	$("#copy-table-td-text td").each(function(){
		$(this).css({ "cursor" : "default" });
	});

	$("#copy-table-td-text td").on("click",function(){

		if( $(this).get(0).cellIndex > 0  ) {
			var range = document.createRange();
			range.selectNodeContents( $(this).get(0) );
	
			var selection = window.getSelection();
			selection.removeAllRanges();
			selection.addRange(range);
		}
	});
});

イベントと td でのカーソル形状の変更は jQuery でコードを作成しています。

$(this).get(0) で、jQuery より DOM オブジェクトを取得し、cellIndex プロパティを使用して『どの列をクリックしたか』を判定しています
▼ クリックするとテキストを選択します
ファイル名を指定して実行 コマンドプロンプト エクスプローラのアドレス
1 ms-settings:about start ms-settings:about ms-settings:about
2 ms-settings:windowsupdate start ms-settings:windowsupdate ms-settings:windowsupdate
3 shell:startup start shell:startup shell:startup
4 shell:sendto start shell:sendto sendto
5 control control control
6 shell:ControlPanelFolder start shell:ControlPanelFolder shell:ControlPanelFolder
7 mspaint mspaint mspaint
1 %TEMP% start %TEMP% %TEMP%

▲ それぞれ Windows10 で実行可能なコマンドですが、場所によって微妙に引き渡す文字列が違っています。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<style>
#lboxtable * {
	font-family: メイリオ,'MS Pゴシック';
	font-size: 12px;
}
#lboxtable table {
	border-collapse: collapse;
	border-style: solid;
	border-color: #000000;
	border-width: 1px;
	background-color: #FFFFFF;
}
#lboxtable td {
	padding: 5px;
	border-style: solid;
	border-color: #000000;
	border-width: 1px;
	/* white-space: nowrap; */
}
#lboxtable th {
	padding: 5px;
	border-style: solid;
	border-color: #000000;
	border-width: 1px;
	background-color: silver;
	/* white-space: nowrap; */
}
#lboxtable .header {
	padding: 5px;
	border-style: solid;
	border-color: #000000;
	border-width: 1px;
	background-color: silver;
	/* white-space: nowrap; */
}
</style>
<script>
$(function(){
	$("#copy-table-td-text td").each(function(){
		$(this).css({ "cursor" : "default" });
	});

	$("#copy-table-td-text td").on("click",function(){

		if( $(this).get(0).cellIndex > 0  ) {
			var range = document.createRange();
			range.selectNodeContents( $(this).get(0) );
	
			var selection = window.getSelection();
			selection.removeAllRanges();
			selection.addRange(range);
		}
	});
});
</script>
<div id="lboxtable">
<strong><span style="color:#3300cc;">▼ クリックするとテキストを選択します</span></strong>
<table id="copy-table-td-text">
<tr>
  <th></th>
  <th>ファイル名を指定して実行</th>
  <th>コマンドプロンプト</th>
  <th>エクスプローラのアドレス</th>
 </tr>
 <tr>
  <td>1</td>
  <td>ms-settings:about</td>
  <td>start ms-settings:about</td>
  <td>ms-settings:about</td>
 </tr>
 <tr>
  <td>2</td>
  <td>ms-settings:windowsupdate</td>
  <td>start ms-settings:windowsupdate</td>
  <td>ms-settings:windowsupdate</td>
 </tr>
 <tr>
  <td>3</td>
  <td>shell:startup</td>
  <td>start shell:startup</td>
  <td>shell:startup</td>
 </tr>
 <tr>
  <td>4</td>
  <td>shell:sendto</td>
  <td>start shell:sendto</td>
  <td>sendto</td>
 </tr>
 <tr>
  <td>5</td>
  <td>control</td>
  <td>control</td>
  <td>control</td>
 </tr>
 <tr>
  <td>6</td>
  <td>shell:ControlPanelFolder</td>
  <td>start shell:ControlPanelFolder</td>
  <td>shell:ControlPanelFolder</td>
 </tr>
 <tr>
  <td>7</td>
  <td>mspaint</td>
  <td>mspaint</td>
  <td>mspaint</td>
 </tr>
 <tr>
  <td>1</td>
  <td>%TEMP%</td>
  <td>start %TEMP%</td>
  <td>%TEMP%</td>
 </tr></tbody>
</table>
</div>




posted by lightbox at 2019-01-17 14:54 | JavaScript オブジェクト | このブログの読者になる | 更新情報をチェックする

2016年05月27日


Google Chrome で音声認識の結果をブログの投稿テキストエリアに転送するブックマークレット



この Seesaa ブログでもテストしました(リッチテキストは使用できません)。ブックマークレットを実行すると、ページの左上に IFRAME のウインドウを埋め込みます。その後、ページ内の対象のテキストエリアにカーソルを置くと開始ボタンが使えるようになるので『開始』をクリックします。

あとは、マイクで話すだけです。時々固まって動作しなくなる場合があるのでその場合は、『終了ボタン』を押すして再度開始ボタンを押して再開して下さい。

終了ボタンを押すと停止状態になり、テキストエリア内のテキストを編集しても結構です。最後に改行等を入れて開始ボタンで再開すると、最後の位置に追加して行きます。

長い時間何も音声入力が無いと自動的に終了します。

Google Chrome で音声認識の精度は想像以上に凄いです。学生がおもしろがって般若心経を朗読はじめたんですが、見事に認識されました(凄い)。

※ 前後にある文章や語句によって結果を変更して行くのがリアルタイムに見て取れる場合があります
▼ ブックマークレット登録用リンク
音声からテキスト

コードのメインは、Google Chrome での音声認識処理 を使用しています。但し、処理部分は私のサイトの recognition.js の中にあります。
parent.document.getElementById("if").style.position='absolute';
parent.document.getElementById("if").style.width='400px';
parent.document.getElementById("if").style.height='100px';
parent.document.getElementById("if").style.left='0px';
parent.document.getElementById("if").style.top='0px';
parent.document.getElementById("if").style.zIndex=0x7FFFFFFF;
parent.document.getElementById("if").style.borderColor='#000000';
parent.document.getElementById("if").style.borderWidth='1px';
parent.document.getElementById("if").style.borderStyle='solid';

parent.window.ds = parent.document.createElement('div');
parent.window.ds.setAttribute('id','ds')
parent.document.body.appendChild(parent.window.ds);
parent.document.getElementById("ds").style.position='absolute';
parent.document.getElementById("ds").style.width='400px';
parent.document.getElementById("ds").style.height='100px';
parent.document.getElementById("ds").style.left='8px';
parent.document.getElementById("ds").style.top='8px';
parent.document.getElementById("ds").style.zIndex=0x7FFFFFFE;
parent.document.getElementById("ds").style.backgroundColor='#000000';

var userAgent = window.navigator.userAgent.toLowerCase();

if (userAgent.indexOf("msie") > -1) {
	parent.document.getElementById("ds").style.filter='alpha(opacity=18)';
}
else {
	parent.document.getElementById("ds").style.opacity=.18;
}


str="";
str+="<body style='margin:0;background-color:#ffffff;padding:15px;'> \n";
str+="<style> \n";
str+=" * { \n";
str+=" font-family:";
str+=" \"メイリオ\", Meiryo, \"MS Pゴシック\"; \n";
str+=" font-size:12px;";
str+="} \n";
str+="</style> \n";

str+="<"+"script src=\"//ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js\"></"+"script> \n";
str+="<div id=\"check\"></div> \n";
str+="<input id=\"st_btn\" type=\"button\" value=\"開始\" disabled> \n";
str+="<input id=\"ed_btn\" type=\"button\" value=\"終了\" disabled> \n";
str+="<div id=\"info\" style='display:inline-block;'></div> \n";
str+="<div id=\"result\"><div id=\"first_text\"></div></div> \n";

str+="<"+"script> \n";
str+="$( function(){ \n";
str+=" \n";
str+="	load_action(); \n";
str+=" \n";
str+="} ); \n";
str+="</"+"script> ";


str+="</body> \n";

document.write( str );
document.close();

parent.scroll(0,0);

var target_textarea;
var rec = null;
var target;
var back_text = "";

function load_action() {

	parent.focus();

	var iid = setInterval(function(){
		parent.focus();
		target_textarea = parent.document.activeElement;
		if ( (target_textarea.tagName).toLowerCase() == "textarea" ) {
			$("#check").text("textarea を取得しました");
			clearInterval(iid);
			$("#st_btn").prop("disabled", false);
			$("#ed_btn").prop("disabled", false);
		}
		else {
			$("#check").text("テキストエリアにカーソルを置いて下さい");
		}
	},500);

	if ( typeof webkitSpeechRecognition === 'undefined' ) {
		$("#info").text("使用できません");
		$("#st_btn").prop("disabled", true);
		$("#ed_btn").prop("disabled", true);
	}
	else {

		target = $("#first_text");

		// インスタンス作成
		rec = new webkitSpeechRecognition();
		// 初期設定
		rec.lang = "ja-JP";
		rec.interimResults = true;
		rec.continuous = true;
		// イベント登録
		rec.onerror = function(){
			$("#info").text("error");
		};
		rec.onnomatch = function(){
			$("#info").text("nomatch");
		};
		rec.onsoundstart = function(){
			$("#info").text("音検知");
		};
		rec.onsoundend = function(){
			$("#info").text("soundend");
		};
		rec.onspeechstart = function(){
			$("#info").text("スピーチ開始");
		};
		rec.onspeechend = function(){
			$("#info").text("スピーチ終了");
		};

		rec.onstart = function(){
			$("#info").text("開始");
		};
		rec.onend = function(){
			$("#info").text("終了");
		};
		// 結果テキストの作成
		rec.onresult = function(ev){
			var obj = ev.results;
			for (var i = ev.resultIndex; i < obj.length; i++ ) {
				if( obj[i].isFinal ) {
					target.text(obj[i][0].transcript);
					target = $("<div></div>");
					$("#result").append(target);
					target_textarea.value = back_text + $("#result").text();
				}
				else {
					target.text(obj[i][0].transcript);
				}
			}
		};	

		// ボタンイベント
		$("#st_btn").on("click",function(){

			back_text = target_textarea.value;

			rec.start();
			$("#st_btn").prop("disabled",true);
		})
		$("#ed_btn").on("click",function(){
			rec.stop();
			$("#st_btn").prop("disabled",false);
			$("#result").html("<div id=\"first_text\"></div>");
			target = $("#first_text");

		})
	}

}
途中、IE のチェックをしているところがありますが、汎用テンプレートを使用して作成しているからです。

改行を入れて読みやすくしたブックマークレットコード
javascript:
var%20wnd=document.createElement('iframe');
wnd.setAttribute('id','if');
wnd.frameBorder=0;
document.body.appendChild(wnd);
var%20url='';
if((location.href).substr(0,5)=='https'){
	url='https://lightbox.sakura.ne.jp/toolbox/recognition.js';
}else{
	url='http://toolbox.winofsql.jp/recognition.js';
}
wnd.contentWindow.document.write('<script src=\''+url+'\' charset=\'utf-8\'></script>')
最後の document.write は DOM でも書けますが、どうせ js のほうでは画面を作成するのに document.write を使用せざるを得ないので同じ事です。初期画面の HTML や JavaScript の文字列化はこちらから実行できます。
( プログラム用文字列 の JavaScript ボタン )


posted by lightbox at 2016-05-27 22:41 | JavaScript オブジェクト | このブログの読者になる | 更新情報をチェックする

2014年10月08日


JavaScript の String と Date オブシェクトに、9999/99/99 書式の文字列日付を取り出すメソッドを追加する

月と日が一桁の場合、前に "0" を付加する為に、String.prototype.right がある事が前提です。 

文字列からのアプローチは、年・月・日の区切り文字に対して sdate を実行します(引数に Date オブジェクト)。
Date オブジェクトからのアプローチは、日付オブジェクトに対して、sdate を実行して、引数には区切り文字を指定します 
<script type="text/javascript">
String.prototype.right = function(n){
	var str = this.valueOf();
	str = str.substr(str.length-n,n);
	return str;
}
String.prototype.sdate = function(dt){
	var str = this.valueOf();
	var today = dt.getFullYear() + str + ("0"+(dt.getMonth()+1)).right(2) + str + ("0"+dt.getDate()).right(2);
	return today;
}
Date.prototype.sdate = function(str){
	var today = this.getFullYear() + str + ("0"+(this.getMonth()+1)).right(2) + str + ("0"+this.getDate()).right(2);
	return today;
}

console.log( "-".sdate(new Date()) )
console.log( (new Date()).sdate("-") )
</script>



タグ:javascript
posted by lightbox at 2014-10-08 11:16 | JavaScript オブジェクト | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

Seesaa のページで、アーカイブとタグページは要注意です。タグページはコンテンツが全く無い状態になりますし、アーカイブページも歯抜けページはコンテンツが存在しないのにページが表示されてしまいます。

また、カテゴリページもそういう意味では完全ではありません。『カテゴリID-番号』というフォーマットで表示されるページですが、実際存在するより大きな番号でも表示されてしまいます。

※ インデックスページのみ、実際の記事数を超えたページを指定しても最後のページが表示されるようです

対処としては、このようなヘルプ的な情報を固定でページの最後に表示するようにするといいでしょう。具体的には、メインの記事コンテンツの下に『自由形式』を追加し、アーカイブとカテゴリページでのみ表示するように設定し、コンテンツを用意するといいと思います。


※ エキスパートモードで表示しています

アーカイブとカテゴリページはこのように簡単に設定できますが、タグページは HTML 設定を直接変更して、以下の『タグページでのみ表示される内容』の記述方法で設定する必要があります

<% if:page_name eq 'archive' -%>
アーカイブページでのみ表示される内容
<% /if %>

<% if:page_name eq 'category' -%>
カテゴリページでのみ表示される内容
<% /if %>

<% if:page_name eq 'tag' -%>
タグページでのみ表示される内容
<% /if %>
この記述は、以下の場所で使用します
container 終わり



フリーフォントで簡単ロゴ作成
フリーフォントでボタン素材作成
フリーフォントで吹き出し画像作成
フリーフォントではんこ画像作成
ほぼ自由に利用できるフリーフォント
フリーフォントの書体見本とサンプル
画像を大きく見る為のウインドウを開くボタンの作成

CSS ドロップシャドウの参考デモ
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり