数学、電気の勉強始めました!プログラムにも挑戦しています!|ω・)ノ

ねごとめも背景

# ねごとめも

# カウンター

# プロフィール

negotoy

Author:negotoy
電気の勉強始めました!
テキストエディタを使ってプログラミングに挑戦中。
fc2 ブログに公開しているテンプレート等は、自由にカスタマイズして、ご活用ください。
プログラム実行の前に必ずコードの確認をお願いします。

# 最新記事

# カレンダー

02 | 2015/03 | 04
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 - - - -

# スポンサードリンク

{ <pre></pre> タグ版のテキストエディタ作成しました }

前回までの記事で作成したソースコードビューはソースコードに行番号を振り、
行をハイライトして、ソースコードを見やすく表示する。(1)
その javascript にソースコードコピーが簡単に出来るように
テキストエリアを表示させる機能を追加したもの。(2)

今回(3)は、それにクリップボードへコピーする機能を追加した。
最初、"クリップボードへのコピー"は javascript で簡単に実装できると思っていた。
軽い気持ちで作業に取りかかったけど結構、大変な作業だった。

まず、 javascript ではセキュリティー上の問題かなんなのかは知らないけど、
クリップボードへのコピーが出来ないらしい。

で、どんな方法でクリップボードにコピーしているの?を調べてみると、
flash の"クリップボード"の機能を利用できる事が分かった。

フリーソフトで flash の開発環境を構築する事が出来るか調べてみると、
なんとか行けそうな雰囲気がしたので挑戦。

ダウンロードしたソフトは以下の4つ。
FlashDevelop, java, flax, flashPlayer

Java は以前、少しだけかじった事があったけど HDD を SSD に換装した時にアンインストールしてた。

プログラムの流れは、
フラッシュ上でイベントが発火 →  HTML にアクセス → クリップボードにコピー → 
flash から javascript の関数を呼び出し、クリップボードにコピーの通知。

以下、今回作成したクリップボードに文字列を格納するソースコード。

今回作成した actionscript

package
{
	import flash.display.*;
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.display.Graphics;
	import flash.system.System;
	import flash.external.ExternalInterface;

	public class Main extends Sprite 
	{
		[Embed(source = "copy.png", mimeType="image/png")]
		private var ImageClass:Class;
		[SWF(width = "15px", height = "16px", backgroundColor = "0xffffff", frameRate = "16")]
		public function Main() 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		public function init(e:Event = null):void 
		{
			stage.scaleMode = StageScaleMode.NO_SCALE;
		var flashVars:Object = this.loaderInfo.parameters;
		var spr:Sprite = new Sprite();
		var g:Graphics = spr.graphics;
			g.lineStyle (1, 0x000000, 0);
			g.beginFill (0xFF0000, 0);
			g.drawRect  ( 0, 0 , 15 , 16);
		var bitmap:Bitmap = new ImageClass() as Bitmap;
			spr.addChild(bitmap);
			spr.buttonMode = true;
			spr.addEventListener(MouseEvent.CLICK, function(event:MouseEvent):void 
			{
				if (flashVars["code"])
				{
					System.setClipboard(flashVars["code"]);
					if (ExternalInterface.available)
					{
						ExternalInterface.call("copy","クリップボードにコピーしました。");
					}
				}
			}); 
			addChild(spr);
		}
	}
}


今回作成した javascript

function copy(args){alert(args);}

addEvent(window,"load",function()
{
var code_block=document.getElementsByTagName("code");
	for(i=0;i<code_block.length;i++)
	{
	var code=code_block[i].firstChild.data.split(/\r\n|\r|\n/);
	var div=document.createElement("div");
		div.style.overflow="auto";
		div.style.position="relative";
	var icon_box=document.createElement("div");
		icon_box.style.position="absolute";
		icon_box.style.top=10+"px";
		icon_box.style.right=10+"px";
		//icon_box.style.backgroundColor="red";
	var text=document.createElement("img");
		text.src="text.png";
		text.style.border=0+"px";
		text.style.marginRight=8+"px";
		text.style.cursor="pointer";
		text.parent=div;
		text.text=code_block[i].firstChild.data;
		text.flg="hide";
		text.tarea=null;
		
		addEvent(text,"click",function()
		{
			if(!this.tarea)
			{
			var tarea=this.tarea=document.createElement("textarea");
				tarea.style.width=90+"%";
				tarea.style.height=90+"%";
				tarea.style.fontSize=10+"px";
				tarea.style.fontFamily="Consolas";
				tarea.style.border="solid 3px #aaa";
				tarea.style.display="block";
				tarea.style.position="absolute";
				tarea.style.top=5+"%";
				tarea.style.left=6+"%";
				tarea.value=this.text;
				this.parent.appendChild(tarea);
				//tarea.focus();
				tarea.select();
			}
			else
			{
			var display=(this.tarea.style.display=="none")? "block" : "none";
				this.tarea.style.display=display;
				if(display=="block")
				{
					this.tarea.focus();
					this.tarea.select();
				}
			}
		});
	var flash=document.createElement("object");
		flash.style.display="inline-block";
		flash.setAttribute("data","Clipboard20150331f.swf")
		flash.setAttribute("id","Clipboard");
		flash.setAttribute("type","application/x-shockwave-flash");
		flash.setAttribute("height","16px");
		flash.setAttribute("width","15px");

		obj=document.createElement("param");
		obj.setAttribute("value","false");
		obj.setAttribute("name","menu");
		flash.appendChild(obj);

		obj=document.createElement("param");
		obj.setAttribute("value","noScale");
		obj.setAttribute("name","scale");
		flash.appendChild(obj);

		obj=document.createElement("param");
		obj.setAttribute("value","false");
		obj.setAttribute("name","allowFullscreen");
		flash.appendChild(obj);

		obj=document.createElement("param");
		obj.setAttribute("value","always");
		obj.setAttribute("name","allowScriptAccess");
		flash.appendChild(obj);

		obj=document.createElement("param");
		obj.setAttribute("value","#000");
		obj.setAttribute("name","bgcolor");
		flash.appendChild(obj);

		obj=document.createElement("param");
		obj.setAttribute("value","direct");
		obj.setAttribute("name","wmode");
		flash.appendChild(obj);

		obj=document.createElement("param");
		obj.setAttribute("value","transparent");
		obj.setAttribute("name","wmode");
		flash.appendChild(obj);
		
		obj=document.createElement("param");
		obj.setAttribute("value","code="+code_block[i].firstChild.data);
		obj.setAttribute("name","flashvars");
		flash.appendChild(obj);
		
		icon_box.appendChild(text);
		icon_box.appendChild(flash);
		div.appendChild(icon_box);
	var ol=document.createElement("ol");
		ol.style.marginLeft=50+"px";
		div.appendChild(ol);
		for(j=0;j<code.length;j++)
		{
			//if(code[j]==""){ continue; }
		var li=document.createElement("li");
		var pre=document.createElement("pre");
		var data=document.createTextNode(code[j].replace(/\t/g,"    "));
			pre.appendChild(data);
			li.appendChild(pre);
		var col=(j%2==1)? "#f0f0f0" : "#f8f8f8";
			li.style.backgroundColor=col;
			li.style.fontSize=12+"px";
			pre.style.fontFamily="Consolas";
			ol.appendChild(li);
		}
	var par=code_block[i].parentNode.parentNode;
		par.insertBefore(div,code_block[i].parentNode);
		code_block[i].parentNode.style.display="none";
	}
});


確認できた範囲では、上記のコードで、"クリップボードにコピーする" を
実装(最新のブラウザのIE,Firefox,Chrome)することはできたけど、すごく動作が重い。

前回作成したページ上のソースコードの行に行番号とハイライトをつけて
ソースコードを見やすく表示する javascript (ソースコードビュー)に
ソースコードをコピーしやすくする為の機能を追加した。

追加した機能はソースコードの右上にあるアイコンをクリックすると
テキストエリアが出現し、そのテキストエリア内にあるソースコードを
選択した状態で表示させるもの。

■ ソースコード表示、非表示切り替えボタン
ソースコード表示、非表示切り替えボタン

ソースコードが選択した状態で表示されるので右クリックからのコピーがやりやすくなっていると思う。

ソースコード上の右上にあるアイコンクリックでソースコードの表示、非表示の切り替えが出来ます。


addEvent(window,"load",function()
{
var code_block=document.getElementsByTagName("code");
	for(i=0;i<code_block.length;i++)
	{
	var code=code_block[i].firstChild.data.split(/\r\n|\r|\n/);
	var div=document.createElement("div");
		div.style.overflow="auto";
		div.style.position="relative";
	var icon=document.createElement("img");
		icon.src="text.png";
		icon.style.border=0+"px";
		icon.style.position="absolute";
		icon.style.top=10+"px";
		icon.style.right=10+"px";
		icon.style.cursor="pointer";
		icon.parent=div;
		icon.text=code_block[i].firstChild.data;
		icon.flg="hide";
		icon.tarea=null;
		
		addEvent(icon,"click",function()
		{
			if(!this.tarea)
			{
			var tarea=this.tarea=document.createElement("textarea");
				tarea.style.width=90+"%";
				tarea.style.height=90+"%";
				tarea.style.fontSize=11+"px";
				tarea.style.fontFamily="Consolas";
				tarea.style.border="solid 3px #aaa";
				tarea.style.display="block";
				tarea.style.position="absolute";
				tarea.style.top=5+"%";
				tarea.style.left=6+"%";
				tarea.value=this.text;
				this.parent.appendChild(tarea);
				//tarea.focus();
				tarea.select();
			}
			else
			{
			var display=(this.tarea.style.display=="none")? "block" : "none";
				this.tarea.style.display=display;
				if(display=="block")
				{
					//this.tarea.focus();
					this.tarea.select();
				}
			}
		});
		div.appendChild(icon);
	var ol=document.createElement("ol");
		ol.style.marginLeft=50+"px";
		div.appendChild(ol);
		for(j=0;j<code.length;j++)
		{
			//if(code[j]==""){ continue; }
		var li=document.createElement("li");
		var pre=document.createElement("pre");
		var data=document.createTextNode(code[j].replace(/\t/g,"    "));
			pre.appendChild(data);
			li.appendChild(pre);
		var col=(j%2==1)? "#f0f0f0" : "#f8f8f8";
			li.style.backgroundColor=col;
			li.style.fontSize=12+"px";
			pre.style.fontFamily="Consolas";
			ol.appendChild(li);
		}
	var par=code_block[i].parentNode.parentNode;
		par.insertBefore(div,code_block[i].parentNode);
		code_block[i].parentNode.style.display="none";
	}
});


ページ中に pre タグに囲まれた code タグがある場合、
ol タグの li ダグに振られる数字を利用して
ソースコードの行に番号をつけて出力(表示)する javascript を書いてみた。

要らなくなった pre タグを削除する javascript では
行番号付のソースコードを書きだした後、不必要になったコードを
削除すると pre タグ減り、行番号付のコードを書き出す際に pre タグが増えてしまう。
なので、 pre タグへの参照が面倒で、
pre タグを一旦、他の変数へ格納することで警告(エラー)を回避した。


■ ソースコードを行番号付きで出力(表示)後、不必要な pre タグを削除する javascript

addEvent(window,"load",function()
{
var pre_block=document.getElementsByTagName("pre");
var code_block=document.getElementsByTagName("code");
var target_pre=[];
var target_code=[];
	for(i=0;i<pre_block.length;i++)
	{
		target_pre[i]=pre_block[i];
		target_code[i]=code_block[i].firstChild.data;
	}
	for(i=0;i<target_pre.length;i++)
	{
	var code=target_code[i].split(/\r\n|\r|\n/);
	var div=document.createElement("div");
		div.style.overflow="auto";
	var ol=document.createElement("ol");
		ol.style.marginLeft=50+"px";
		div.appendChild(ol);
		for(j=0;j<code.length;j++)
		{
			//if(code[j]==""){ continue; }
		var li=document.createElement("li");
		var pre=document.createElement("pre");
		var data=document.createTextNode(code[j].replace(/\t/g,"    "));
			pre.appendChild(data);
			li.appendChild(pre);
		var col=(j%2==1)? "#f0f0f0" : "#f8f8f8";
			li.style.backgroundColor=col;
			li.style.fontSize=11+"px";
			pre.style.fontFamily="Consolas";
			ol.appendChild(li);
		}
	var par=target_pre[i].parentNode;
		par.insertBefore(div,target_pre[i]);
		par.removeChild(target_pre[i]);
	}
});


要らなくなった pre タグを非表示にする javascript では参照する値が
一定なので、問題なくソースコードを行番号付きで出力(表示)することが出来た。


■ ソースコードを行番号付きで出力後、不必要な pre タグを非表示にする javascript

addEvent(window,"load",function()
{
var code_block=document.getElementsByTagName("code");
	for(i=0;i<code_block.length;i++)
	{
	var code=code_block[i].firstChild.data.split(/\r\n|\r|\n/);
	var div=document.createElement("div");
		div.style.overflow="auto";
	var ol=document.createElement("ol");
		ol.style.marginLeft=50+"px";
		div.appendChild(ol);
		for(j=0;j<code.length;j++)
		{
			//if(code[j]==""){ continue; }
		var li=document.createElement("li");
		var pre=document.createElement("pre");
		var data=document.createTextNode(code[j].replace(/\t/g,"    "));
			pre.appendChild(data);
			li.appendChild(pre);
		var col=(j%2==1)? "#f0f0f0" : "#f8f8f8";
			li.style.backgroundColor=col;
			li.style.fontSize=12+"px";
			pre.style.fontFamily="Consolas";
			ol.appendChild(li);
		}
	var par=code_block[i].parentNode.parentNode;
		par.insertBefore(div,code_block[i].parentNode);
		code_block[i].parentNode.style.display="none";
	}
});

windows update の3月の更新プログラムインストール後、
タスクバー上でのイベントが停滞したり、異常終了する
状態が続いていた。


その原因の更新プログラム、「KB3033889」の修正版が公開された。

更新プログラム「KB3033889」の修正版の紹介記事はこちら → 窓の杜の記事

修正版はマイクロソフトのサポートページの手順に沿ってインストール → マイクロソフトサポートページ

ちょっと不安だったけど、この記事を見つけて即、手順にそって修正版をインストールしてみた。

「KB3033889」の修正版「KB3048778」
「KB3033889」の修正版「KB3048778」

更新プログラムインストール後、それまでの症状は改善された模様。

今現在までの使用で以前のような症状は発症していない。

前回の記事で書いた、"ページトップへ戻る" ボタンを設置した
テンプレートで発症していた症状はなんとか改善することができました。

前回の記事は → こちら

a タグを利用したトップへ戻るボタンを設置している
テンプレートにFC2のアクセス解析のコードを貼り付けると、
ページのスクロールの動きが一瞬、止まってしまう現象です。

原因は a タグの href 属性のようです。
以前のテンプレートでは、この href に属性値を設定した状態で
a タグに javascript でイベント登録していましたが、
今回、手直しをしたテンプレートでは、
この a タグの href 属性を削除して javascript でイベント登録をしています。

html ファイル修正前
html ファイル修正前

html ファイル修正後
html ファイル修正後

js ファイル修正前
js ファイル修正前

js ファイル修正後
js ファイル修正後

詳しくは分かりませんが、FC2解析のスクリプトが
a タグの href 属性上で発火するイベントを監視しているようです。

そのため、"ページトップへ戻る" ボタンを押した時に実行されるスクリプトと
アクセス解析用のスクリプトが同時に実行され、処理が遅れているような印象をもちました。

a タグを span タグに変えたり、イベントハンドラを他のものにしたりと、
あれこれ試しましたが、 a タグの href 属性削除に落ち着きました。

href 属性を指定した a タグに javascript でイベントを登録する場合と
FC2のアクセス解析のスクリプトを同時に使用する場合、注意する必要があるのかもしれません。

# スポンサードリンク