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

ねごとめも背景

# ねごとめも

# カウンター

# プロフィール

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 - - - -

# スポンサードリンク

前回までの記事で作成したソースコードビューはソースコードに行番号を振り、
行をハイライトして、ソースコードを見やすく表示する。(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のアクセス解析のスクリプトを同時に使用する場合、注意する必要があるのかもしれません。

# スポンサードリンク