SQLの窓

2016年05月31日


DB のデータを簡単に沢山作る方法は inner join

ページ処理のテストを行う為に、元を 7 件として、56 件のデータに増やす方法です。それぞれの SQL は、RDBMS 毎に動作するように書き換えれば実行可能です。

元のテーブル

既に 7 件のテストデータがあり、phpMyAdmin でエクスポートしています。phpMyAdmin はたいていのレンタルサーバで用意されていると思いますし、最新(4.6.2/php5.5以上)をダウンロードして解凍してアップロードするだけで動作します( PHP6 の場合は、最新の phpMyAdmin は動作しないようでした。Windows PC でも普通に動きます )
CREATE TABLE IF NOT EXISTS `board` (
  `row_no` serial,
  `body` varchar(1000),
  `subject` varchar(200),
  `from` varchar(20),
  `pdate` datetime,
  `cdate` datetime,
  primary key(`row_no`)
)

※ row_no は自動採番列です

データ

以下はエクスポートしたデータです。
-- phpMyAdmin SQL Dump
-- version 4.4.15.5
-- http://www.phpmyadmin.net
--
-- Host: localhost
-- Generation Time: 2016 年 5 月 28 日 13:26
-- サーバのバージョン: 5.6.17
-- PHP Version: 5.4.13

SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";


/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;

--
-- Database: `lightbox`
--

--
-- 挿入前にテーブルを空にする `board`
--

TRUNCATE TABLE `board`;
--
-- テーブルのデータのダンプ `board`
--

INSERT INTO `board` (`row_no`, `body`, `subject`, `from`, `pdate`, `cdate`) VALUES
(3, '「日本と米国が力を合わせて、世界の人々に希望を生み出すともしびとなる」。安倍晋三首相は27日、オバマ米大統領とともに訪れた広島市の平和記念公園で、強固な日米同盟をアピールした。昨年4月、米上下両院合同会議での演説で先の大戦への「痛切な反省」を表明した首相からは、今回のオバマ氏の広島訪問を、日米関係を新たな段階に進める節目にしたい思惑が透けて見える。', '<伊勢志摩サミット>閉幕 親密な日米 首相腐心', '毎日新聞', '2016-05-28 13:15:04', '2016-05-09 11:52:51'),
(10, '電子コミック販売サイト「漫画onWeb」や電子書籍取次サービス「電書バト」などを運営する漫画家の佐藤秀峰さんは、2月に伝書バトが実施した、電子コミック131冊を各11円で販売するセールの効果で、2月の売り上げ総額が3億円を超えたことを明らかにした。売り上げトップだった佐藤さん本人には、1億3000万円以上の印税が入ったという。', '電子コミック「11円」セールで売り上げ3億円超 トップ作家に印税1億3000万円 「常識打ち破る数字」', 'ITmedia ニュース', '2016-05-28 13:22:37', '2016-05-14 20:07:14'),
(11, 'タカタ製エアバッグの欠陥問題で、国土交通省は27日、火薬の劣化を防ぐ乾燥剤が入っていないエアバッグについて、新たに約700万台がリコール(回収・無償修理)対象になると明らかにした。\r\n\r\nメーカー各社に順次リコールを求め、2018年度末までに改修を済ませたいとしている。\r\n\r\n一連の問題では、国内で延べ約1259万台がリコールされており、対象は2000万台規模に達することになる。\r\n', 'リコール2000万台規模に=新たに700万台、タカタ製エアバッグ', '時事通信', '2016-05-28 13:18:36', '2016-05-14 20:08:07'),
(12, '酒の行き過ぎた安売りに待ったをかける規制は、大手スーパーやディスカウント店などの安値攻勢で経営が苦しくなった「町の酒屋さん」を救済する狙いがある。だが、厳しい罰則を恐れて、業者が萎縮し、健全な価格競争まで妨げてしまうリスクもはらんでいる。', '改正酒税法成立 量販店萎縮、価格形成ゆがみも', '産経新聞', '2016-05-28 13:17:26', '2016-05-14 20:08:11'),
(14, '広島の原爆資料館はオバマ米大統領が訪れた後の27日夜に記者会見し、オバマ氏が佐々木禎子さんの折り鶴や資料などを見て、自身も4羽の折り鶴を資料館に寄贈したと説明した。佐々木禎子さんは、原爆症で12歳で亡くなり、「原爆の子の像」のモデルとして知られている。政府関係者によると、大統領が自ら折ったもので、小中学生に手渡したという。志賀賢治館長は「感慨深げな表情で、岸田文雄外相の説明を聞いていた。視察時間は短く残念だったが、伝えたかったことを伝えられたのではないか」と語った。', '<米大統領広島訪問>オバマ氏、4羽の折り鶴 その思いは…', '毎日新聞', '2016-05-28 13:16:09', '2016-05-09 11:52:51'),
(21, '日立製作所は27日、中国・広州市の高層ビル「広州周大福金融中心」向けに受注したエレベーターが分速1200メートル(時速72キロ)を記録し、世界最高速度を達成したと発表した。14日に行った走行試験で世界最高速度を達成。今秋の稼働に向け、据え付けや調整作業を進めている。', '日立、エレベーターの最高速度達成', 'SankeiBiz', '2016-05-28 13:19:27', '2016-05-14 20:08:07'),
(22, 'レンタルビデオ店「TSUTAYA(ツタヤ)」を運営するカルチュア・コンビニエンス・クラブ(CCC)と民泊仲介サイト世界最大手の米Airbnb(エアビーアンドビー)が27日、事業提携を発表した。訪日観光客の増加で宿泊ニーズが高まる中、「ツタヤ」や「Tポイント」を展開するCCCのノウハウで日本市場を開拓し、一般住宅に有償で客を泊める民泊サービスの定着を目指す。', '米民泊サイト最大手が日本進出でツタヤと提携 外国人の訪日客に照準', '産経新聞', '2016-05-28 13:20:24', '2016-05-28 13:20:24');

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;


inner join で増殖して追加

inner join で条件を書かなければ、n 行あれば、n x n 行の結果を返します。その際、同じ表を a と b で別名定義して自己結合させます。

結果の行は、board の 定義に合わせて a 表のみから取得して、row_no は 自動採番なので null as row_no として先頭に作成します。

その結果をさらに board に insert する事によって、row_no は、新しく自動採番された行として挿入されます。その結果 a( 最初の行数 ) + n( 元の行数 ) * n( 元の行数 ) の行を登録する事になります。
insert into board
select
	null as row_no,a.body,a.subject,a.from,a.pdate,a.cdate
	from board a
inner join `board` b
もう一回すると 3192 件になるので、これ以上は注意して実行する必要があります。

乱数関数で日付データのみ、ばらつかせる

ここではさほど厳密にバラつかせる必要は無かったので、時間部分に適用しています。
※ PIPES_AS_CONCAT は、文字列結合に Oracle と同じ || を使用可能にする設定です。
SET sql_mode='PIPES_AS_CONCAT';

update board set pdate = cast('2016/05/28 0' || truncate(Rand()*10,0) || ':00' as datetime)



posted by lightbox at 2016-05-31 19:36 | Comment(0) | MySQL | このブログの読者になる | 更新情報をチェックする

Java、PHP、jQuery : 最近の記事と関連する記事のまとめ / インデックス

Java : WindowBuilder

HttpPost・JOption
Java WindowBuilder から超簡易掲示板(CSVタイプ)投稿

Google Gson・HttpGet・テーブル
WindowBuilder のテーブルコントロールにインターネットから JSON データを読み込んで処理するテンプレート

MySQL・テーブル
WindowBuilder テンプレートのテーブルコントロールに MySQL のデータを表示する

テンプレート・インポート
Eclipse 4.4 Pleiades + WindowBuilder テンプレート / アプリケーションウインドウとダイアログ / インポート手順



HttpGet クラス(ソースコード)
HttpPost クラス(ソースコード)


1からのプロジェクト作成方法


Java : Android Studio

<include>・HttpPost
tools.jar の callHttpGet のテストと include による画面再利用と HttpPost クラスで掲示板書き込み / Android Studio

コンボボックス・リスト処理
Android の Spinner に関するいろいろな実装と知識 / Android Studio


インターネット・画像
AsyncTask を継承して、Drawable を取得する専用クラスを作成する : Android Studio

ボタン
Android Studio でボタンの処理を追加する4つの方法 : Android Studio 2.0

第二画面
新しい Activity を追加して MainActivity より呼び出し、MainActivity に戻る処理

MessageBox
tools.jar を使用して MessageBox 処理

プロジェクト作成
tools.jar を使用して基本的なアクションを簡単に実装する


tools.jar ソースコード ( Tools.java, Tools2.java, TestArrayAdapter.java, AndroidTools.java )

NAVER
Android Studio : jar の作成と実行テスト
Android Studio の設定
Android Studio 予習開始!(良く使う機能・ショートカット・メニュー)


Java : コンソール

インターネット・アクセス
Java のコンソールで NAVER の RSS を取得して、title 部分を正規表現で加工して表示するサンプル

メール送信
java をコマンドプロンプトからビルドして実行するサンプル。( メール送信が初心者には楽しいはず )


PHP

DB・jQuery
PHP で 自家製 API を作成して jQuery の簡単なコードで更新処理を行うサンプル

掲示板・CSV・JSON
超簡易掲示板 : 保存タイプは CSV

掲示板・JSON
超簡易掲示板 ( JSON ) : PHP

キャラクタセット
PHP で HTML数値エンティティを、目的のキャラクタセットの文字列に変換する

trim・正規表現
PHP で漢字スペースと通常スペースのトリム


jQuery

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

ブックマークレット
ブックマークレット IFRAME ユニット作成ツール

ブックマークレット
イラストAC用、一括タグ転送ブックマークレット

音声認識
Google Chrome での音声認識処理

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

EASELJS
EASELJS を使用した画像の分割と分割されたエリア毎のアニメーション / createjs.Ticker の reset と init はうまく動きませんでした

EASELJS
EASELJS を使用した画像の縮小とトリミングと角丸マスク / 画像は new Image でイベント処理して画像サイズを取得します

一覧・Picasa API
jQuery Columns を使って、Picasa API より アルバム一覧を表示する

jquery.ajax-combobox
jquery.ajax-combobox(オートコンプリートとドロップダウンリストを組み合わせたコンボボックス) を使用して、入力可能なコンボックス( しかもリストはページャ付き )

jquery.ajax-combobox
jquery.ajax-combobox で JSON をデータに使う場合、複数項目を検索対象にする為の簡単な改造


Kintone

kintone で画像を表示する / PC と スマホで少し違います。PC ではスペース項目、スマホでは、スマホ用ヘッダスペースを使用します

kintone JavaScript API で ルックアップ先が更新された場合の参照元を全て更新する

kintone API のトークンを使った PHP コードの注意点

kintone の開発者ライセンスを取得しました。一年有効で、見たところ4年ぐらい使えそうです


その他

A 要素と CSS だけでボタンを表現する 『BUTTONS』

BUTTON 要素と CSS だけでアイコンボタンを表現する 『BUTTONS』

utf8 文字ツール の 文字参照リンクの作成方法

レンタルサーバで PHP のバージョンを 5.4 から 5.6 に変更する時の注意事項

IFRAME 内に外部の javascript を読み込んで画面を作成する / document.write での構築



posted by lightbox at 2016-05-31 13:48 | Comment(0) | 記録 | このブログの読者になる | 更新情報をチェックする

Java のコンソールで NAVER の RSS を取得して、title 部分を正規表現で加工して表示するサンプル

java.util.regex.Matcher
java.util.regex.Pattern

groupCount で取得されるのは、部分一致した数なので、() を使用しなければ、戻り値は 0 となります。また、その場合は group() で取得できますし。group(0) でも取得できます。

なので、常に pattern に一致する文字列は group(0) です。group(n) で n が 1 以上は部分一致となります。
よって、部分一致のみのループは、for( int i = 1; i <= m.groupCount(); i++ ) となります。
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class Main {

	public static void main(String[] args) {
		
		Pattern p;
		Matcher m;
		int len;

		print("処理開始");

		// NAVER の RSS
		String str = httpGet("http://matome.naver.jp/feed/hot");

        // 部分一致の無い パターンを生成
        p = Pattern.compile("<title>.+?</title>");
        m = p.matcher(str);

        // 部分一致した数( 0 になります )
        len = m.groupCount();
        print( Integer.toString(len) );

        while(m.find()) {
        	// 部分一致は無いので、m.group() で パターン
        	// に対する全体一致を取得
       		System.out.println(m.group());
        }

		print("------------------------------------------");
        
        // 部分一致のあるパターンを生成
        p = Pattern.compile("<title>(.+?)</title>");
        m = p.matcher(str);

        // 部分一致した数 ( 1になります )
        len = m.groupCount();
        print( Integer.toString(len) );
        
        while(m.find()) {
        	// m.group(0) はパターンに対する全体一致なので
        	// 1 から始めて部分一致のみ表示
        	for( int i = 1; i < (len +1); i++) {
        		System.out.println(m.group(i));
        	}
        }
        
		print("------------------------------------------");
        
        // 部分一致のあるパターンを生成
        p = Pattern.compile("(<title>)(.+?)(</title>)");
        m = p.matcher(str);

        len = m.groupCount();
        print( Integer.toString(len) );

        String partsString;
        StringBuilder buffer;
        while(m.find()) {
    		buffer = new StringBuilder();
        	for( int i = 1; i < (len +1); i++) {

        		// title 開始タグ
        		if ( i == 1) {
        			buffer.append("『");
        		}
        		// title 内容
        		if ( i == 2) {
            		partsString = m.group(2);
            		// String クラスの正規表現置換
            		// 文の区切り的文字で改行
            		partsString = partsString.replaceAll("[。、.…!?]+", "\n");
        			buffer.append(partsString);
        		}
        		// title 終了タグ
        		if ( i == 3) {
        			buffer.append("』");
        		}
        	}
    		print(buffer.toString());
    		print("");
        }

	}
	
	// ********************************
	// データ表示用
	// ********************************
	public static void print( String s ) {
		System.out.println(s);
	}	

	// ********************************
	// static void main より呼び出す為の
	// static な インターネットアクセス関数 
	// ********************************
	public static String httpGet( String s ) {

		String result = "";

		try {
			URL url = new URL(s);

			HttpURLConnection http = (HttpURLConnection)url.openConnection();
			http.setRequestMethod("GET");
			http.connect();
			InputStream is = http.getInputStream();

			InputStreamReader isr = new InputStreamReader(is,"UTF8");
			BufferedReader br = new BufferedReader(isr);
			String line_buffer;
			StringBuilder sb = new StringBuilder();

			while(null != (line_buffer = br.readLine() )) {

				sb.append(String.format("%s\n",line_buffer));

			}

			br.close();
			isr.close();
			is.close();

			result = sb.toString();

		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;

	}	

}




posted by lightbox at 2016-05-31 12:00 | Comment(0) | Java | このブログの読者になる | 更新情報をチェックする

2016年05月30日


PHP で 自家製 API を作成して jQuery の簡単なコードで更新処理を行うサンプル

以下のような『社員マスタ』を使って、まず PHP のコードを用意します。
create table `社員マスタ` (
	`社員コード` varchar(4)
	,`氏名` varchar(50)
	,`フリガナ` varchar(50)
	,`所属` varchar(4)
	,`性別` int
	,`作成日` datetime
	,`更新日` datetime
	,`給与` int
	,`手当` int
	,`管理者` varchar(4)
	,`生年月日` datetime
	,primary key(`社員コード`)
)


全てのデータが空でも、SQL 的にはエラーは起こりません。但し、エラーが発生した場合は、kj にエラーメッセージをセットし、furi に 更新 SQL をセットします。

dbdata_update_json.php
<?php
header( "Content-Type: application/json; Charset=utf-8" );
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );
header( "Access-Control-Allow-Origin: *" );

// ***********************************************
// 初期設定
// ***********************************************
if ( $_GET["sdata"] == "" ) {
	$_GET["sdata"] = "{}";
}
$data = json_decode($_GET["sdata"]);
$data->type = "UPDATE";

// ***********************************************
// 利用変数設定
// ***********************************************
$json_type =  JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT;
$db_data_type = MYSQLI_ASSOC;
$_GET["sdata"] = str_replace("'","''",$_GET["sdata"]);
// -----------------------------------------------


// ***********************************************
// 接続情報
// ***********************************************
$server = 'localhost';
$db_name = 'lightbox';
$user = 'root';
$password = 'trustno1';
// -----------------------------------------------


// ***********************************************
// 接続
// ***********************************************
$connect = @ new mysqli($server, $user, $password, $db_name);
if ($connect->connect_error) {
	$data->status = "ERROR";
	$data->kj = "接続エラーです";
	print json_encode($data,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
	exit();
}
$connect->set_charset("utf8"); 
// -----------------------------------------------


// ***********************************************
// NULL 項目の対応
// ***********************************************
if ($data->kyuyo == '') {
	$data->kyuyo = "null";
}
if ($data->teate == '') {
	$data->teate = "null";
}
if ($data->seibetu == '') {
	$data->seibetu = "0";
}
if ($data->birth == '') {
	$data->birth = "null";
}
else {
	$data->birth = "'{$data->birth}'";
}
// -----------------------------------------------


// ***********************************************
// 更新 SQL
// ***********************************************
$query = <<< QUERY
update `社員マスタ` set 
	`氏名` = '{$data->kj}'
	,`フリガナ` = '{$data->furi}'
	,`性別` = {$data->seibetu}
	,`給与` = {$data->kyuyo}
	,`手当` = {$data->teate}
	,`所属` = '{$data->syozoku}'
	,`管理者` = '{$data->kanri}'
	,`生年月日` = $data->birth
 where
 `社員コード` = '{$data->scode}'
QUERY;
// -----------------------------------------------


// ***********************************************
// クエリ実行
// ***********************************************
$result = $connect->query($query); 
if ( !$result ) {
	$data->status = "ERROR";
	$data->kj = "クエリに誤りがあります";
	$data->furi = $query;
	print json_encode( $data, $json_type );
	exit();
}
else {
	$data->status = "SUCCESS";
}
// -----------------------------------------------


// ***********************************************
// 接続解除
// ***********************************************
$connect->close();
// -----------------------------------------------


// ***********************************************
// 結果
// ***********************************************
print json_encode($data,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);

// -----------------------------------------------

?>


PHP で Access-Control-Allow-Origin: * をセットしているので、どこに置いても JavaScript から呼び出し可能です。

以下のような簡単なコードで更新のテストが可能です。
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>
<script>
$(function(){
	var sdata = {};
	$("#build").on("click", function(){
		$(".entry").find("input").each(function(idx){
			sdata[$(this).prop("id")] = $(this).val();
		});
		$("#result").text( JSON.stringify(sdata,null,"    ") );
	});
	$("#send").on("click", function(){
		var sdata = encodeURIComponent( $("#result").text() );
		$.get("http://localhost/log/easy_board/dbdata_update_json.php?sdata="+sdata ,function(data){
			console.dir(data);
		});
	});
});
</script>
<input id="build" type="button" value="JSON 文字列作成">
<input id="send" type="button" value="サーバ送信">
<pre class="entry">
<input id="scode"> scode
<input id="kj"> kj
<input id="furi"> furi
<input id="seibetu"> seibetu
<input id="kyuyo"> kyuyo
<input id="teate"> teate
<input id="syozoku"> syozoku
<input id="kanri"> kanri
<input id="birth"> birth
</pre>
<pre id="result">
</pre>



posted by lightbox at 2016-05-30 21:17 | Comment(0) | PHP + データベース | このブログの読者になる | 更新情報をチェックする

tools.jar の callHttpGet のテストと include による画面再利用と HttpPost クラスで掲示板書き込み / Android Studio

tools.jar

libs フォルダに保存して、右クリックから Add as Library を実行すると参照可能になります。

▼ ソースコード
Tools, Tools2, TestArrayAdapter, AndroidTools.java )

tools.jar は、気軽にアンドロイドのアプリケーションのテストができるように作成したライブラリです。Android の動作テストはとても時間がかかり、結構デリケートな部分が多いので、できればこのライブラリの中にあるような内容は適当にしたい事が多くあります。特に、商品では無く他人への説明や他の機能の習熟目的で使用し、自分自身は学生をターゲットにしており、授業で使用しています。

それらの中でも、特に面倒くさいのがインターネットに対するアクセスです。tools.jar では、GET アクセスは実装していますが、POST アクセスは実装していません。POST には POST するだけの意味がある時にしか利用されないので、ここで HttpPost クラスをソースで実装して 超簡易掲示板(CSV) を使って投稿するテストをしています。



画面を二つ使い、include でボタン3つの定義を両方で利用しています。
(Android Studio では、新しいアクティビティを作成すると、AndroidManifest も自動的に書き換えられます。)
※ 具体的なタイムアウト時の処理は行っていません(何も起きません)

 

MainActivity.java

次画面2ボタンでインターネットよりテキストデータを取得し(tools.jar の callHttpGet)、次画面に引き渡してテキストエリアに表示します。そこで投稿ボタンで実際の WEB に対する投稿(HttpPost) となります。
package lightbox.may.toolstest;

import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import jp.android.work.Tools;

public class MainActivity extends AppCompatActivity {

	// テキストビュー( 表示用 )
	private TextView tv;

	// *****************************************
	// 初期画面構築
	// *****************************************
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		// 表示部分のインスタンスの取得
		tv = (TextView) MainActivity.this.findViewById(R.id.textView);

		// *****************************************
		// ボタン1 の設定
		// *****************************************
		Button btn1 = (Button)MainActivity.this.findViewById(R.id.button);
		btn1.setText("次画面");
		MainActivity.this.findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

			// 呼び出し番号 (1)
			Tools.callActivity(MainActivity.this,Main2Activity.class, 1);

			}

		});

		// *****************************************
		// ボタン2 の設定
		// インターネットのデータを次画面に引き渡す
		// *****************************************
		Button btn2 = (Button)MainActivity.this.findViewById(R.id.button2);
		btn2.setText("次画面2");
		btn2.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

				Tools.callHttpGet(
					"http://toolbox.winofsql.jp/kumonoito.txt",
					"utf-8",
					new Tools.OnAsyncTaskListener() {
						@Override
						public void onAsyncTaskListener(String s) {
							Intent intent = new Intent(MainActivity.this, Main2Activity.class);
							intent.putExtra("requestCode",2);
							intent.putExtra("text",s);
							startActivityForResult(intent, 2);
						}
					});

			}

		});

		// *****************************************
		// ボタン3 の設定
		// ブラウザ呼び出し
		// *****************************************
		Button btn3 = (Button)MainActivity.this.findViewById(R.id.button3);
		btn3.setText("ブラウザ");
		btn3.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

				Tools.callBrowser(MainActivity.this,"http://weather.yahoo.co.jp/weather/jp/27/6200.html");

			}

		});

	}

	// *****************************************
	// 第二画面から戻って来た時の処理
	// onActivityResult
	// *****************************************
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);

		Log.i("lightbox", String.format("呼び出し番号 : %d", requestCode)  );
		Log.i("lightbox", String.format("戻り番号 : %d", resultCode)  );

		if ( data != null ) {
			// 戻りデータの取得
			String returnData = data.getStringExtra("returnData");
			if (returnData != null) {
				// テキストビューに表示
				tv.setText(returnData);
			}
		}

	}
}


Main2Activity.java
package lightbox.may.toolstest;

import android.content.Intent;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class Main2Activity extends AppCompatActivity {

	// 呼び出し番号
	private int requestCode;
	// テキストエリア
	private EditText et;

	// *****************************************
	// 初期画面構築
	// *****************************************
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main2);

		// 入力部分のインスタンスの取得
		et = (EditText) Main2Activity.this.findViewById(R.id.editText);

		// *****************************************
		// 前の画面から送られたデータの取得
		// *****************************************
		Intent intent = getIntent();

		// 1) テキストデータ
		String text = intent.getStringExtra("text");
		if ( text != null ) {
			et.setText(text);
		}
		// 2) 整数データ
		requestCode = intent.getIntExtra("requestCode", 0);
		if ( requestCode != 0 ) {
			Log.i("lightbox", String.format("呼び出し番号 : %d", requestCode));
		}

		// *****************************************
		// ボタン1 の設定
		// 整数のみを戻す
		// *****************************************
		Button btn1 = (Button)Main2Activity.this.findViewById(R.id.button);
		btn1.setText("戻る");
		btn1.setTextColor(Color.parseColor("#f84848"));
		btn1.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

				// 戻り値のみ返す
				setResult(100);

				// 第二画面を終了して初期画面に戻る
				finish();

			}

		});

		// *****************************************
		// ボタン2 の設定
		// *****************************************
		Button btn2 = (Button)Main2Activity.this.findViewById(R.id.button2);
		btn2.setText("投稿");
		btn2.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

				Intent intent = new Intent();
				setResult(200,intent);

				// エミュレータから PC の WEBサーバへアクセスする場合
//				String url = "http://10.0.2.2/log/easy_board/csvtype/board.php";

				// 実機を PC につないで、WiFi 接続を可能にした場合
				// 192.168.1.2 は PC の IPアドレス
				String url = "http://192.168.1.2/log/easy_board/csvtype/board.php";

				Map<String,String> url_param = new HashMap<String,String>();
				url_param.put("url", url);

				Map<String,String> param = new HashMap<String,String>();
				param.put("send", "send");
				param.put("subject", "テスト投稿");
				param.put("name", "ウインドウビルダー");
				param.put("text", et.getText().toString());
				SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
				param.put("datetime", sdf.format(new Date()));

				new AsyncTask<Map,Void,String>(){
					@Override
					protected String doInBackground(Map... params) {

						// 引数より URL 部分を取得
						String url = params[1].get("url").toString();

						Log.i("lightbox",url);

						// インターネットアクセス
						return HttpPost.execute(url, params[0], "utf-8");

					}

					@Override
					protected void onPostExecute(String s) {
						Log.i("lightbox",s);
						finish();

					}
				}.execute(param,url_param);



			}

		});

		// *****************************************
		// ボタン3 の設定
		// 整数と文字列を戻す
		// *****************************************
		Button btn3 = (Button)Main2Activity.this.findViewById(R.id.button3);
		btn3.setText("戻る+データ");
		btn3.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {

				// 渡す値
				Intent intent = new Intent();
				intent.putExtra("returnData", et.getText().toString());
				// 戻り値と値を返す
				setResult(300, intent);

				finish();

			}

		});

	}

}


ボタン部分の画面パーツ( action_buttons.xml )



デザインタブから <include> を選択できます。クリックすると参照可能な画面一覧が表示されるので、選択するとカーソルがコントロールを選択した状態になり、デザイン画面やツリーにドロップ可能になります。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="horizontal"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button1"
        android:id="@+id/button"
        android:layout_weight="1"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button2"
        android:id="@+id/button2"
        android:layout_weight="1"
        />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button3"
        android:id="@+id/button3"
        android:layout_weight="1"
        />

</LinearLayout>

activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="lightbox.may.toolstest.MainActivity">


    <include
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        layout="@layout/action_buttons"
        android:id="@+id/include2"/>

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/scrollView"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/include2">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/textView"/>
    </ScrollView>
</RelativeLayout>


activity_main2.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="lightbox.may.toolstest.Main2Activity">

    <include
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        layout="@layout/action_buttons"
        android:id="@+id/include"/>

    <EditText
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:inputType="textMultiLine"
        android:ems="10"
        android:id="@+id/editText"
        android:textSize="20dp"
        android:layout_below="@+id/include"
        android:layout_alignParentStart="true"
        android:gravity="top|left"/>

</RelativeLayout>



posted by lightbox at 2016-05-30 18:56 | Comment(0) | Android Studio 2 | このブログの読者になる | 更新情報をチェックする

2016年05月29日


Java WindowBuilder から超簡易掲示板(CSVタイプ)投稿

HttpPost クラスのテストです。



超簡易掲示板(CSV)は以下からダウンロードできます。

超簡易掲示板 : 保存タイプは CSV

WindowBuilder 側では、複数行のテキストフィールドを使って単純投稿です。
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.swing.JOptionPane;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

import com.google.gson.Gson;


public class TopWindow extends ApplicationWindow {

	private int width = 600;
	private int height = 440;
	private Gson gson;
	private Text text;

	// *********************************
	// コンストラクタ
	// *********************************
	public TopWindow() {
		super(null);
	}

	// *********************************
	// コントロールの追加
	// ※ Design での変更が反映されます
	// *********************************
	@Override
	protected Control createContents(Composite parent) {
		Composite container = new Composite(parent, SWT.NONE);

		// ボタンの定義
		Button button = new Button(container, SWT.NONE);
		// ボタンのイベント
		button.addSelectionListener(new SelectionAdapter() {
			@Override
			public void widgetSelected(SelectionEvent e) {

				// プログラム開始時に実行すると、固まるので直前に
				try {
					UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
				} catch (ClassNotFoundException | InstantiationException
						| IllegalAccessException
						| UnsupportedLookAndFeelException e1) {
					e1.printStackTrace();
				}

				// 確認ダイアログ( OK_CANCEL )の表示
				int result = JOptionPane.showConfirmDialog(
						null,
						"データを POST しますか",
						"確認",
						JOptionPane.OK_CANCEL_OPTION,
						JOptionPane.QUESTION_MESSAGE);
				// OK を選択
				if ( result == JOptionPane.OK_OPTION ) {

					// POST データ
					Map<String,String> param = new HashMap<String,String>();
					param.put("send", "send");
					param.put("subject", "テスト投稿");
					param.put("name", "ウインドウビルダー");
					param.put("text", text.getText());
					SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
					param.put("datetime", sdf.format(new Date()));

					// インターネットアクセス
					String data = HttpPost.execute("http://localhost/log/easy_board/csvtype/board.php", param, "utf-8");
					// データを取得できた
					if ( !data.equals("") ) {
						// コンソールで確認
						System.out.println(data);
					}
				}
			}
		});
		button.setBounds(10, 10, 81, 28);
		button.setText("実行");
		
		text = new Text(container, SWT.BORDER | SWT.MULTI);
		text.setBounds(10, 44, 483, 341);


		return container;
	}

	// *********************************
	// アプリケーションの開始
	// *********************************
	public static void main(String args[]) {
		try {
			// 自分自身(TopWindow) の作成
			TopWindow window = new TopWindow();
			// open を実行したら、Window を閉じるまで次の行を実行しない
			window.setBlockOnOpen(true);
			window.open();
			// Window を閉じたら以下を実行してアプリケーションを終了する
			Display.getCurrent().dispose();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	// *********************************
	// Window の初期設定
	// *********************************
	@Override
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);

		// タイトルの設定
		newShell.setText("タイトル文字列");

	}

	// *********************************
	// Window サイズの初期設定
	// *********************************
	@Override
	protected Point getInitialSize() {
		// プライベート変数を使用してウインドウサイズを決定しています
		return new Point(width, height);
	}

}


プロジェクトを一から作る方法


posted by lightbox at 2016-05-29 22:48 | Comment(0) | java : WindowBuilder | このブログの読者になる | 更新情報をチェックする

超簡易掲示板 : 保存タイプは CSV





board.php、model.php、view.php の 3 ファイルで動作します。json.php が同梱されていますが、出力ファイルである board.csv を JSON 形式で取得する為のコードです。( JavaScript からアクセスする場合は、header( "Access-Control-Allow-Origin: *" ); を追加して下さい )

他のアプリケーションからのアクセスを簡単にテストできる仕様になっています。

board.php
<?php
// **************************************
// php.ini の output_buffering をチェックして
// 有効になっていた場合は、header の前に出力可能です
// **************************************

// **************************************
// 通常の HTML として出力します
// **************************************
header( "Content-Type: text/html; Charset=utf-8" );

// **************************************
// キャッシュを無効にするヘッダ
// ※ いろいろあるのは念のため
// **************************************
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );

// **************************************
// 関数の定義を読み込みます
// **************************************
require_once("model.php");

// **************************************
// $_POST['send'] != "" は送信ボタンが
// クリックされた事を示します
// さらに、テキストエリアに何か入力され
// た場合に処理を行います
// **************************************
$_POST['text'] = preg_replace( "/^[ \s]+/u", "", $_POST['text'] );
$_POST['text'] = preg_replace( "/[ \s]+$/u", "", $_POST['text'] );
if ( $_POST['send'] != "" && $_POST['text'] != "" ) {

	// データの書き込み処理
	post_data();

}

// *************************************
// データの表示処理
// *************************************
disp_data();


// **************************************
// ▼ 以下は画面です。$log_text を
//    埋め込んでいます
// **************************************
require_once("view.php");
?>


model.php
<?php

// **************************************
// データの書き込み処理
// **************************************
function post_data() {

	// データを一括読み込み
	$log_text = @file_get_contents("board.csv");

	// **************************************
	// 本文中の改行コードを "\n" という
	// 文字列に変換しています
	// **************************************
	$_POST['text'] = str_replace("\r\n","\\n",$_POST['text']);
	$_POST['text'] = str_replace("\n","\\n", $_POST['text'] );
	$_POST['text'] = str_replace("\r","\\n", $_POST['text'] );

	// HTML 要素を無効にする
	$_POST['text'] = str_replace("<","&lt;",$_POST['text']);
	$_POST['text'] = str_replace(">","&gt;",$_POST['text']);

	// HTML 要素を無効にする
	$_POST['subject'] = str_replace("<","&lt;",$_POST['subject']);
	$_POST['subject'] = str_replace(">","&gt;",$_POST['subject']);
	$_POST['name'] = str_replace("<","&lt;",$_POST['name']);
	$_POST['name'] = str_replace(">","&gt;",$_POST['name']);

	// シングルクォートとダブルクォートとカンマ
	$_POST['text'] = str_replace("'","&#39;",$_POST['text']);
	$_POST['text'] = str_replace("\"","&#34;",$_POST['text']);
	$_POST['text'] = str_replace(",","&#44;",$_POST['text']);

	// シングルクォートとダブルクォートとカンマ
	$_POST['subject'] = str_replace("'","&#39;",$_POST['subject']);
	$_POST['subject'] = str_replace("\"","&#34;",$_POST['subject']);
	$_POST['subject'] = str_replace(",","&#44;",$_POST['subject']);
	$_POST['name'] = str_replace("'","&#39;",$_POST['name']);
	$_POST['name'] = str_replace("\"","&#34;",$_POST['name']);
	$_POST['name'] = str_replace(",","&#44;",$_POST['name']);

	$log_wk = "{$_POST['text']},{$_POST['subject']},{$_POST['name']},{$_POST['datetime']}";

	// **************************************
	// 前回データとの境界に改行コードを
	// 設定しています
	// **************************************
	$log_text = $log_wk . "\n" . $log_text;

	// 書き込み
	file_put_contents("./board.csv", $log_text );

	// GET メソッドで再表示します
	header( "Location: board.php" );
	exit();


}

// **************************************
// データの表示処理
// **************************************
function disp_data() {

	// 埋め込み用データを global 宣言
	global $log_text;

	// データを一括読み込み
	$rows = @file("./board.csv");
	// ファイルが存在しない場合
	if ( $rows === false ) {
		$log_text = "ここに投稿データが表示されます";
		return;
	}

	// 表示用の埋め込みに使用される文字列変数
	$log_text = "";
	foreach( $rows as $v ) {

		$data = explode(",", $v);

		// **************************************
		// 本文の改行は br 要素で表現します
		// **************************************
		$row = str_replace("\\n", "<br>\n", $data[0] );

		// **************************************
		// 行毎に表示 HTML を作成
		// **************************************
		$row = "<h3>{$data[1]}</h3>{$row}<br><span class='sb'>({$data[2]} : {$data[3]} )</span><br>";

		// **************************************
		// 記事の境界を hr 要素で表現します
		// **************************************
		$row .= "<hr>\n";

		// **************************************
		// 表示画面全体 を作成
		// **************************************
		$log_text .= $row;
	
	}


}

?>


行データの作成は、以下のように置き換えるとメンテナンスしやすくなります。また、この部分を別ファイルにして require するともっと使いやすくなるでしょう。
		// **************************************
		// 行毎に表示 HTML を作成
		// **************************************
		$row = <<<HTML
		<h3>{$data[1]}</h3>
		{$row}<br>
		<span class='sb'>({$data[2]} : {$data[3]} )</span><br>
HTML;


view.php
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script>

<style>
* {
	font-family: "ヒラギノ角ゴPro W3","Hiragino Kaku Gothic Pro","メイリオ",Meiryo,"MS Pゴシック",Verdana,Arial,Helvetica,sans-serif;
}
body {
	margin: 5px;
}
form {
	padding-right: 5px;
}
.sb {
	font-size: 8px;
}
#text {
	height: 100px;
	width: 500px;
}
#subject,#name {
	width: 400px;
}

@media screen and (max-width:479px) {

	#text {
		width: 100%;
	}
	#subject,#name {
		width: 230px;
	}
	#line_control {
		display: none;
	}
}

</style>

<script>

$( function(){
	$("form").on("submit", function(){

		var dateNow = new Date();
		var dateString = 
			dateNow.getFullYear() + "/" + 
			("0"+(dateNow.getMonth()+1)).slice(-2)+ "/" + 
			("0"+(dateNow.getDate())).slice(-2);
		var timeString = 
			("0"+(dateNow.getHours())).slice(-2) + ":" + 
			("0"+(dateNow.getMinutes())).slice(-2) + ":" + 
			("0"+(dateNow.getSeconds())).slice(-2);

		$("#datetime").val( dateString + " " + timeString );

	});
});

</script>
</head>

<body>
<h3><a href="board.php" style="color:black;">超簡易掲示板 ( CSV )</a></h3>

<form method="POST">
	タイトル <input
		type="text"
		id ="subject"
		name="subject">
	<br>
	名  前 <input
		type="text"
		id ="name"
		name="name">
	<br>
	<textarea
		id ="text"
		name="text"></textarea>
	<input type="hidden"
		id="datetime"
		name="datetime">
	<br>
	<input
		type="submit"
		name="send"
		value="送信">
</form>
<br>

<?= $log_text ?>

</body>
</html>


json.php
<?php
// **************************************
// 通常の HTML として出力します
// **************************************
header( "Content-Type: application/json; charset=utf-8" );
header( "pragma: no-cache" );
header( "Expires: Wed, 31 May 2000 14:59:58 GMT" );
header( "Cache-control: no-cache" );

// データを一括読み込み
$rows = @file("./board.csv");
// ファイルが存在しない場合
if ( $rows === false || $rows[0] == "" ) {
	print '{ "error": "ファイルが存在しません" }';
	exit();
}

// 全ての行用の JSON 用クラス作成
$json = new stdClass;
// 行データを格納する配列を作成
$json->item = array();

foreach( $rows as $v ) {

	$data = explode(",", $v);

	// 新しい行用のクラス作成
	$board_data = new stdClass;

	// text プロパティに 本文をセット
	$board_data->text = $data[0];
	// subject プロパティに タイトルをセット
	$board_data->subject = $data[1];
	// name プロパティに 名前をセット
	$board_data->name = $data[2];
	// subject プロパティに タイトルをセット
	$board_data->datetime = $data[3];

	// 配列の最後に投稿データをセット
	array_push ($json->item, $board_data);


}

print json_encode($json, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);

?>



posted by lightbox at 2016-05-29 22:21 | Comment(0) | PHP + WEBアプリ | このブログの読者になる | 更新情報をチェックする

2016年05月28日


ブックマークレット IFRAME ユニット作成ツール

https では無いページ用です。実行したページに IFRAME のウインドウを埋め込むコードのセットを作成するツールです。URL には、js ファイルの URL を入力し、さらに IFRAME のサイズを入力して実行します。

一つ目の TEXTAREA には、ブクマークレットを登録する為のリンクの HTML コードが作成され、二つ目の TEXTAREA には、.js の中に書き込む基本コードが作成されます。( .js は UTF-8 で保存します )

js URL
IFRAME 幅 IFRAME 高さ


WEB サイトをお持ちで無い方は、Google ドライブを使用できます。

Google ドライブにWEBページを作成する方法

▼ サンプル
https://b3612ccaef41231d7e34cda5ea0b9ed5af2eb17d.googledrive.com/host/0B9Jymqpro6gSVlB5Wm52U29wTlE/bml.js



posted by lightbox at 2016-05-28 00:33 | Comment(0) | ブックマークレットコード | このブログの読者になる | 更新情報をチェックする

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 | Comment(0) | JavaScript オブジェクト | このブログの読者になる | 更新情報をチェックする

2016年05月24日


Google Chrome での音声認識処理






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

参考にしたのは、こちら。確認した仕様はこちら。

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

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



ソースコード
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.2.2/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 2016-05-24 02:08 | Comment(0) | JavaScript オブジェクト | このブログの読者になる | 更新情報をチェックする
Seesaa の各ページの表示について
Seesaa の 記事がたまに全く表示されない場合があります。その場合は、設定> 詳細設定> ブログ設定 で 最新の情報に更新の『実行ボタン』で記事やアーカイブが最新にビルドされます。

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

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

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

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


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

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

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

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

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


Windows
container 終わり

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

Android SDK ポケットリファレンス
改訂版 Webデザイナーのための jQuery入門
今すぐ使えるかんたん ホームページ HTML&CSS入門
CSS ドロップシャドウの参考デモ
PHP正規表現チェッカー
Google Hosted Libraries
cdnjs
BUTTONS (CSS でボタン)
イラストAC
ぱくたそ
写真素材 足成
フリーフォント一覧
utf8 文字ツール
右サイド 終わり
base 終わり