[JavaScript] 15 Adobe XDのアイテムデータを取得するプラグイン作成 その3 テキスト出力

[M1 Mac, Monterey 12.6.3]

前回の続きです。

Pythonでは区切り文字付きテキストの方がリストのリテラル(機能のないただの文字列)より扱いやすいため、プラグインの内容を修正しました。

これでPythonスクリプトによりアイテムデータをリテラルのリストとして取得できます。あとは各要素から必要な数値を抽出してJSONに変換します。

JavaScriptの方は一応完成になります。

function myCommand(selection) {
    console.log(selection.items.length + " items are selected");

    let items_list = "";
    var num = 1;
    selection.items.forEach(function(value){
        // console.log(value);
        if (num < selection.items.length){
            items_list += value + ";";
        } else {
            items_list += value;
        }
        num += 1;
    });
    console.log(items_list);
}

module.exports = {
    commands: {
        GetItemXY: myCommand
    }
};
with open("items.txt", "r") as tf:
    items_list = tf.read().replace("\n","").split(';')
    
print(items_list)
print(len(items_list))

# ここからlistをJSONに変換する

[JavaScript] 14 Adobe XDのアイテムデータを取得するプラグイン作成 その2 リスト出力

[M1 Mac, Monterey 12.6.3]

Adobe XDのプラグインからアイテムデータをファイル出力するのは私の技量では難しいため早々にあきらめて、Python用のリストとして開発者コンソールに出力するようにしました。

これをPythonスクリプトにコピー&ペーストしてC++コードを書き換えようという算段です。

JavaScriptはローカル環境とのファイルのやり取りが不得手なところがあるので難しいことをやろうとせず、ここだけ手動でさっさとPythonに渡してしまうのが得策だと考えました。

アイテムデータをPython用リストとして出力
function myCommand(selection) {
    console.log(selection.items.length + " items are selected");

    let items_list = "";
    var num = 1;
    selection.items.forEach(function(value){
        // console.log(value);
        if (num == 1){
            items_list += "[\"" + value + "\",\n";
        } else if (num < selection.items.length){
            items_list += "\"" + value + "\",\n";
        } else {
            items_list += "\"" + value + "\"]\n";
        }
        num += 1;
    });
    console.log(items_list);
}

module.exports = {
    commands: {
        GetItemXY: myCommand
    }
};

[JavaScript] 13 Adobe XDのアイテムデータを取得するプラグイン作成 その1

[M1 Mac, Monterey 12.6.3]

ビデオ編集アプリのGUIデザインにはAdobe XDを使っています。

GUI内アイテムの座標と幅・高さをプラグインで取り出して、C++のコードを書き換えるところまで自動化しようとしています。

とりあえずAdobe XDのプラグイン開発環境を構築し、アイテムのデータ所在を確認するところまでは出来ました。スクリプト自体は簡単に書けたので拍子抜けでした。

これらをJSONファイルとして取り出し、PythonでJSON読込・コード書き換えができれば完成になります。

Adobe XD GUIデザイン
GUI内アイテムデータの出力
function myCommand(selection) {
    console.log(selection.items.length + " items are selected");

    selection.items.forEach(function(value){
        console.log(value);
    });
}

module.exports = {
    commands: {
        GetItemXY: myCommand
    }
};

[JavaScript] 12 submitボタンに動作を追加する

[M1 Mac, Big Sur 11.7.2]

検索ボタンを押すとMySQLへログインして検索するよう設定していますが、同時にストップウォッチが動作するようにしました。

<form method="post" name="formSearch">
    <input id="button2" type="submit" name="button2" value="検索"
    style="color:blue; width:80px; height:40px; font-size:18px; background-color:RGB(211,203,198);
    border:solid; border-color:RGB(30,144,255);">
</form>
<br>

<script language="javascript" type="text/javascript">
    const button2 = document.getElementById('button2');

    button2.addEventListener('click',(e) => {
        startWatch();
        document.cookie="watch=1;";
    });
</script>

<中略>

<span id="elapsedTime"></span>
<br>

<script language="javascript" type="text/javascript">
    function getCookieValue(key) {
        const cookies = document.cookie.split(';');
        for (let cookie of cookies) {
            var cookiesArray = cookie.split('='); 
            if (cookiesArray[0].trim() == key.trim()) { 
                return cookiesArray[1];
            }
        }
        return '';
    }

    function showElapsedTime(time) {
        var now = new Date();
        const eTime = Math.floor((now - time)/1000);
        document.cookie="time=" + eTime + ";";

        var eTimeShow = "検索時間(秒) " + eTime;
        document.getElementById("elapsedTime").innerHTML = eTimeShow;

        return eTimeShow;
    }

    function startWatch(){
        var startTime = new Date();

        setInterval(
            function()
            {showElapsedTime(startTime);}
            ,1000 ) ;
    }

    var watchBool = getCookieValue("watch");
    if (watchBool == 1){
        let time = getCookieValue("time");
        var eTimeShow = "検索時間(秒) " + time;
        console.log(eTimeShow);
        document.getElementById("elapsedTime").innerHTML = eTimeShow;
    }
</script>

[JavaScript] 11 プログレスバー Fetch API

[M1 Mac, Big Sur 11.7.2]

懸案のプログレスバー表示ですが、PHPの簡易webサーバ側(PHPファイルと同じディレクトリ)にMySQL検索の進捗率を格納したテキストファイルを置いて定期的に読み込もうとしたもののデータを更新できず上手くいきませんでした。記録として残しておきます。

以前JavaScriptの学習を断念した原因であるHTTP通信に取り組まざるを得なくなりました。

様々な検証を通して、根本的にMySQL検索中は最新テキストファイルへのアクセスができないことが判明しました。

仕様なのかマシンスペックなのか何が原因なのかは良く分かりません。少なくとも今の環境ではどう手立てを施してもできないのかもしれません。

ここ数日かなりのめり込み愛着もわいてきましたのでJavaScriptと今後決別することはありませんが、この程度の動作も簡単には出来ないとなると使用頻度は低いままに終わりそうです。MySQL検索はターミナルでのPython実行で事足りますから。

直前試行の残データを読み込んだまま更新されない
<progress class="progress" value="0" id="pb">
</progress>
<div id="rate"></div>

<script type="text/javascript">
    async function showRate() {
        let response = await fetch("./files/rate.txt");
        var rateID = document.getElementById('rate')

        if (response.ok) {
            var rate = await response.text();
            rateID.textContent = rate;
            console.log("rate: %s", rate);
        }
        else {
            alert("HTTP-Error: " + response.status);
        }

        document.getElementById("pb").value = rate;
        
    };

    // Fetch APIの使用可否確認
    if(window.fetch ) {
	    console.log("fetch使用可能");
    } else {
	    console.log("fetch使用不可");
    }

    setInterval('showRate()', 1000);
</script>

[JavaScript] 10 cookieの使用 検索時間の記録

[M1 Mac, Big Sur 11.7.2]

MySQLアプリの検索時間をcookieに都度記録し、検索が完了してリロードされた時に最終記録を表示するようにしました。意味がないのですがプログレスバーはいきなり最後だけ100%で表示されます。

PHPもJavaScriptも初心者なので、HTMLを加えた3者が混在するPHPファイルを書くのは骨が折れます。どちらもそれなりに書けるようになるとスクリプト言語はPythonを合わせた3言語を学んだことになります。

Rubyも学んでみたいですが、それにしかできないことでもないと着手しそうにないですね。

MySQL検索終了時
<input id="checkBox" type="checkbox" name="checkBox" value="開始" onClick="startTimer()"/>

<span id="elapsedTime"></span>

<script language="javascript" type="text/javascript">

    function getCookieValue(key) {
        const cookies = document.cookie.split(';');
        for (let cookie of cookies) {
            var cookiesArray = cookie.split('='); 
            if (cookiesArray[0].trim() == key.trim()) { 
                return cookiesArray[1];
            }
        }
        return '';
    }

    function showElapsedTime(time) {
        var now = new Date();
        const eTime = Math.floor((now - time)/1000);
        document.cookie="time=" + eTime + ";";
        console.log(eTime);

        var eTimeShow = "検索時間(秒) " + eTime;
        console.log(eTimeShow);
        document.getElementById("elapsedTime").innerHTML = eTimeShow;

        return eTimeShow;
    }

    function startTimer(){
        var startTime = new Date();

        setInterval(
            function()
            {showElapsedTime(startTime);}
            ,1000 ) ;
    }

    try {
        let checkBox = document.getElementById('checkBox');
        console.log("checkBox: %b", checkBox.checked);

        if (checkBox.checked == false){
            var time = getCookieValue("time");
            var eTimeShow = "検索時間(秒) " + time;
            console.log(eTimeShow);
            document.getElementById("elapsedTime").innerHTML = eTimeShow;
        }
    }
    catch(e){
    }
</script>

[JavaScript] 09 cookieの使用

[M1 Mac, Big Sur 11.7.2]

publicな変数の扱い方が全く分からないので、苦肉の策としてcookieに変数を格納し共有することにしました。

PHP、JavaScript、HTMLが混在するスクリプト内、スクリプト間でどうやって変数の受け渡しをしているのでしょうか。この点においてはC++やJavaよりも難易度が相当高いように思います。

プログレスバーについてもcookieを使って何とかできないか探っていきます。

MySQL検索終了時
<html>
<?php
# MySQLにログイン
$conn = new mysqli('localhost', 'root', 'root');
if (!$conn){
	die("MySQL接続に失敗しました");
} else {
	// print 'MySQL接続に成功しました';
}

$dbs_query = $conn->query('show databases;');
$dbs = $dbs_query->fetch_all(MYSQLI_ASSOC);

$dbs_count = count($dbs);

?>
<head>
	<meta charset="utf-8"/>
	<title>MySQL SEARCHER</title>
	<link rel="shortcut icon" href="favicon.ico">
	
</head>
<body>
データベース、カラム名、検索語を入力してください
<form id="form_submit" action="output.php" method="post">
	<table border="1">
		<tr>
			<td>DB</td>
			<td><input id="input1" type="text" name="db"></td>
		</tr>
	</table>
	<tr>
	<?php
	$num = 0;
	foreach ($dbs as $db) {
		if ($num == 0){
			echo "DB : ";
		}
		echo implode($db);
		if ($num != $dbs_count - 1){
			echo ", ";
		}
		$num = $num + 1;
		
	}
	?>
	</tr>
	<table border="1">
		<tr>
			<td>COL</td>
			<td><input id="input2" type="text" name="col"></td>
		</tr>

	</table>
	<table border="1">
		<tr>
			<td><input id="input3" type="text" name="key"></td>
			<td colspan="2" align="center">
			<input id="button" type="submit" value="検索">
			</td>
		</tr>
	</table>
</form>

<progress class="progress" value="0" id="pb">
</progress>
<br>
<br>

<span id="elapsedTime"></span>
<br>

<span id="clockTime"></span>
<script type="text/javascript">
	function set2fig(num) {
		var ret;
		if( num < 10 ) { ret = "0" + num; }
		else { ret = num; }
	return ret;
	}

	function showTime() {
		var now = new Date();
		var nowhour = set2fig(now.getHours());
		var nowminutes = set2fig(now.getMinutes());
		var nowseconds = set2fig(now.getSeconds());
	
		var clockTime = "現在時刻 " + nowhour + ":" + nowminutes + ":" + nowseconds;
		console.log(clockTime);
		document.getElementById("clockTime").innerHTML = clockTime;
    
    	return clockTime;
  	}
	
	setInterval('showTime()', 1000);
</script>
<br>

<span id="loadCount"></span>
<script language="javascript" type="text/javascript">
	var cnt;        // 読込回数

	function getCookieValue(key) {
		const cookies = document.cookie.split(';');
		for (let cookie of cookies) {
			var cookiesArray = cookie.split('='); 
			if (cookiesArray[0].trim() == key.trim()) { 
				return cookiesArray[1];
			}
		}
		return '';
	}

	// cookie使用可否確認
	if (navigator.cookieEnabled){
		console.log("cookie使用可能");
		
		// 読込回数をHTMLに表示
		if (!document.cookie){
			document.getElementById("loadCount").innerHTML = "1回目の読込";
			document.cookie="counts=1;";  
		}
		else{
			try{
				const cnt_ck = getCookieValue("counts");
				// 読み込み回数をインクリメント
				cnt = parseInt(cnt_ck) + 1;
				document.getElementById("loadCount").innerHTML = cnt + "回目の読込";
				
				//cookieに読込回数書き込み
				document.cookie="counts=" + cnt + ";";
			}
			catch(e){
				document.write("読込回数の取得に失敗しました。");
			}
		}
	}
	else{
		document.write("cookieが使用できません。");
		console.log("cookie使用不可");
	}
		
	if (cnt != 2){
		var now = new Date();
		
		function showElapsedTime() {
			var now2 = new Date();
			const eTime = Math.floor((now2 - now)/1000);
			console.log(eTime);

			// cookieのmaxTimeを都度更新する
			let maxTimeStr = "maxTime=" + eTime + ";";
			document.cookie = maxTimeStr;  

			var eTimeShow = "経過時間(秒) " + eTime;
			console.log(eTimeShow);
			document.getElementById("elapsedTime").innerHTML = eTimeShow;

		return eTimeShow;
		}

		setInterval('showElapsedTime()', 1000);

	} else if (cnt = 2){
		let maxTime_ck = getCookieValue("maxTime");
		var eTimeShow = "経過時間(秒) " + maxTime_ck;
		console.log(eTimeShow);

		// 2回目の読込時は1回目の最大値で固定表示
		document.getElementById("elapsedTime").innerHTML = eTimeShow;
	}

</script>
<br>
<br>

</body>
</html>

参考サイト

[JavaScript] 08 デジタル時計配置

[M1 Mac, Big Sur 11.7.2]

MySQLアプリにプログレスバーを実装するのに手間取っていて、解決への取っ掛かりとしてHTMLの正常動作を確認するためデジタル時計を配置しました。

setInterval関数の第1引数に繰り返し実行する関数を入れるのですが、なぜかシングルクオートで囲む仕様になっています。

インタプリタの観点からは関数が格納されているメモリアドレスにアクセスするという意味合いなのでしょうが、正直ユーザーフレンドリーではないですね。

#MySQLアプリ #PHP

<span id="clockTime"></span>
<script type="text/javascript">
	function set2fig(num) {
		var ret;
		if( num < 10 ) { ret = "0" + num; }
		else { ret = num; }
	return ret;
	}

	function showTime() {
		var now = new Date();
		var nowhour = set2fig(now.getHours());
		var nowminutes = set2fig(now.getMinutes());
		var nowseconds = set2fig(now.getSeconds());
	
		var clockTime = "現在時刻 " + nowhour + ":" + nowminutes + ":" + nowseconds;
		console.log(clockTime);
		document.getElementById("clockTime").innerHTML = clockTime;
    
    return clockTime;
  	}
	
	setInterval('showTime()', 1000);
</script>

参考サイト

[JXA] 04 ローマ字を漢字に変換 その2 クリップボード反映待ち

JXA : JavaScript for Automation
[M1 Mac, Ventura 13.0]

クリップボードへのコピーは即時ではないことが判明したため、do…while文でループさせました。これで動作の再現性がようやく確保できました。

Google Chrome, Safari, Microsoft Excelではこのスクリプトで問題なく変換しますが、肝心のVSCodeがどうしてもダメです。

もう少しなので何とかしたいところです。

function run(input, parameters) {
    var se = Application("System Events");
    se.includeStandardAdditions = true;
    var txt0 = se.theClipboard();

    se.keystroke("a", {using:"command down"});
    se.keystroke("c", {using:"command down"});

    do {
        var txt1 = se.theClipboard();
    } while (txt0 == txt1);

    // se.displayDialog(txt1);

    lib = Library('convertlib');
    var ret = lib.romaji_to_hiragana(txt1);

    se.setTheClipboardTo(ret);
    do {
        var txt2 = se.theClipboard();
    } while (txt1 == txt2);

    // se.displayDialog(txt2);
    
    se.keystroke("v", {using:"command down"});
    se.keystroke("a", {using:"command down"});

    // VSCodeを別扱いにしたいがうまくいかず
    // var curApp = Application.currentApplication();
    // var nameApp = curApp.name();
    // se.displayDialog(nameApp);

    se.keyCode(104);
    se.keyCode(104);
    // または
    // se.keystroke("r", {using:["control down", "shift down"]});
            
    return input;
}

[JXA] 03 ローマ字を漢字に変換 その1

JXA : JavaScript for Automation
[M1 Mac, Big Sur 11.6.8, Ventura 13.0]

JXAでアプリ上のローマ字をひらがなに変換し、さらに漢字に変換するスクリプトを書きました。

やはりAppleScriptと同様にVenturaではまともに動きませんでした。クリップボードをコントロールすることができなくなっています。

調べてみるとクリップボードへの反映にやや時間が掛かるとのことなので、もう少し検討を続けます。

function run(input, parameters) {
    var se = Application("System Events");
    se.includeStandardAdditions = true;

    se.keystroke("a", {using:"command down"});
    se.keystroke("c", {using:"command down"});

    var txt = se.theClipboard();

    lib = Library('convertlib');
    var ret = lib.romaji_to_hiragana(txt);

    se.setTheClipboardTo("");
    se.setTheClipboardTo(ret);

    se.keystroke("v", {using:"command down"});
    se.keystroke("a", {using:"command down"});

    se.keyCode(104);
    se.keyCode(104);
    // または
    // se.keystroke("r", {using:["control down", "shift down"]});
             
    return input;
}