SharePointのウェブサービスを使ってブックマークレットでアイテム作成してみた

SharePointのウェブサービスを使ってブックマークレットでアイテム作成してみたをはてなブックマークに追加 SharePointのウェブサービスを使ってブックマークレットでアイテム作成してみたをdel.icio.usに追加 Yahoo!ブックマークに登録 SharePointのウェブサービスを使ってブックマークレットでアイテム作成してみたをGoogle Bookmarksに追加

「SharePointのウェブサービスを使ってブックマークレットでアイテム作成する」というのをやってみました。
SBMぽいことをさせたかったので、SharePointのドメイン内外からウェブサービスを呼ぶ必要があるということを意識しなければなりません。
SharePointサーバはhttp://mossというドメインで稼働していて、例えば、グーグル検索結果を参照している画面(http://google.co.jpドメイン)からブックマークレット(javascript)でなんとかしてSharePointのサービスを呼ばなければならないのですが、javascriptだとクロスドメインなのをどうにかする必要があります。なので、flashとcrossdomain.xmlの配置でサービスコールしてあげればよさそうなのでそうしました。動きの流れは以下のような感じになります。

ホッテントリ閲覧中にIEのブックマークレットをポチッと押す。
↓
javascriptでflashがエンベッドされる。
↓
flashのExternalInterface.callで、処理をjavascriptへ返す。
↓
javascriptでページタイトルの情報とかタグ入力とかURLを取得する。
↓
ExternalInterface.addCallbackで用意されているメソッドを呼ぶ
↓
flashでSharePointのウェブサービスをコールする。
↓
アイテムが投入される。

と、こんな感じ。ただ、これ作るのにIEの仕様にすげー振り回された。糞IEまじなくなってほしい。

とりあえず、ポイントを以下に列挙して行きます。

クロスドメインを解決するため、crossdomain.xmlを置く必要があります。

flash側はSecurity.loadPolicyFile(”/crossdomain.xml”)でこのcrossdomain.xmlを読み込んでおく必要があります。crossdomain.xmlを置くのはルート直下である必要はないようなのですが、loadPolicyFileで指定したパスのファイルを読み終わったあと、さらにルート直下のcrossdomain.xmlを読みに行く模様。loadPolicyFileで読めてれば大丈夫ぽい。

IEではスクリプトで<object>に<embed>をappendChild出来ない。

var obj = document.createElement( "object" );
var embed = document.createElement( "embed" );
obj.appendChild( embed ); // 出来ない。

理由はよくわからない。出来ないものは出来ないらしい。イラつく。

IEではスクリプトでobjectを動的出力する場合は処理の順番がある。

var obj = document.createElement('object');
// objectのアトリビュートを追加する前に親にappend
document.body.appendChild( obj );
var prm = document.createElement('param');
prm.setAttribute('name', 'movie');
prm.setAttribute('value', 'xxx.swf');
obj.appendChild( prm );
// objectにparamを突っ込んでから
// フラッシュのアトリビュートを追加する。
obj.setAttribute('data', 'xxx.swf');
obj.setAttribute('type', 'application/x-shockwave-flash');

理由はわからない。またもIEではまる。イラつく。

ExternalInterface.addCallback / call IEでの注意点。

貼付けたobjectのidは”externalなんちゃら”とかにしないと上手く動かない。

<object id="externalmoss" >

今回はexternalmossにした。ここらへんでIEを開くのも気持ち悪くなる。

ブックマークレット化のIE設定

ie.png

この情報バーがあがると上手く動かないので、IEにインターネットオプション→セキュリティ→レベルのカスタマイズ→スクリプト化されたウィンドウを使って情報の入力を求めることをWebサイトに許可する。を「有効にする」

ということで使い方。

iebkm1.png

ブックマークレットを押すとか後述のスクリプトをURL欄に入力するとプロンプトがあがるので、デリミタスペースでタグを入力します。

mossbkm.png

するとhogeというリストに参照ページのURLとタグが突っ込まれます。URLを見ると、ドメインをまたいでいる事がわかります。あ、ページタイトル入れるの忘れた。
まぁUIはこんなプロンプトじゃなくて、カッコいいやつをこさえれば良いし、SharePointのサービス呼べる事がわかったのでタグのサジェストも出そうと思えば出せますね。

bkm.js

var isIE = /*@cc_on!@*/0;
function buildQuery(){
var tags = prompt( "input tag", "" );
var tagList = [];
if( tags ){
tagList = tags.replace(/^[  ]*/gim, "").replace(/[  ]*$/gim, "").split( ' ' );
}
var method = '';
for( var idx = 0; idx < tagList.length; idx++ ){
method = method + '<Method ID="' + ( idx + 1 ) + '" Cmd="New"><Field Name="Title">' + tagList[ idx ] +'</Field><Field Name="url">' + location.href +'</Field></Method>';
}
if( tagList.length > 0 ){
if ( isIE ) {
window[ "externalmoss" ].execbkm( '<Batch>' + method + '</Batch>' );
}
else {
document[ "externalmoss" ].execbkm( '<Batch>' + method + '</Batch>' );
}
}
}
(function(){
if( isIE ){
var obj = document.createElement( "object" );
obj.setAttribute( "width", "1" );
obj.setAttribute( "height", "1");
document.body.appendChild( obj );
var prm = document.createElement( "param" );
prm.setAttribute( "name", "movie" );
prm.setAttribute( "value","http://moss/Documents/BKMForMOSS.swf" );
obj.appendChild( prm );
prm = document.createElement("param");
prm.setAttribute( "name", "allowScriptAccess" );
prm.setAttribute( "value", "always");
obj.appendChild( prm );
obj.setAttribute( "classid","clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" );
obj.setAttribute( "id", "externalmoss" );
obj.setAttribute( "name", "externalmoss" );
obj.setAttribute( "data", "http://moss/Documents/BKMForMOSS.swf" );
obj.setAttribute( "type", "application/x-shockwave-flash" );
}
else {
var obj = document.createElement( "object" );
obj.setAttribute( "classid","clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" );
obj.setAttribute( "width", "0" );
obj.setAttribute( "height", "0");
document.body.appendChild( obj );
var prm = document.createElement( "param" );
prm.setAttribute( "name", "movie" );
prm.setAttribute( "value","http://moss/Documents/BKMForMOSS.swf" );
obj.appendChild( prm );
prm = document.createElement("param");
prm.setAttribute( "name", "allowScriptAccess" );
prm.setAttribute( "value", "always");
obj.appendChild( prm );
var emb = document.createElement("embed");
emb.setAttribute( "src", "http://moss/Documents/BKMForMOSS.swf" );
emb.setAttribute( "width", "0" );
emb.setAttribute( "height", "0" );
emb.setAttribute( "name", "externalmoss" );
emb.setAttribute( "type", "application/x-shockwave-flash" );
emb.setAttribute( "pluginspage","http://www.macromedia.com/go/getflashplayer");
emb.setAttribute( "allowScriptAccess","always");
obj.appendChild( emb );
}
})();

BKMForMOSS.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="init()">
<mx:Script>
<![CDATA[
import flash.external.*;
import mx.rpc.events.ResultEvent;
import mx.rpc.events.FaultEvent;
import flash.system.Security;
public function init(): void {
ExternalInterface.addCallback( "execbkm", execbkm );
Security.loadPolicyFile("http://moss/Documents/crossdomain.xml");
Security.allowDomain("*");
ExternalInterface.call( "buildQuery" );
}
private function execbkm( query:String ):void {
var requestXML:XML = new XML('<UpdateListItems xmlns="http://schemas.microsoft.com/sharepoint/soap/"><listName>hoge</listName><updates>' + query + '</updates></UpdateListItems>');
mossService.UpdateListItems( requestXML );
ExternalInterface.call( "alert( 'ブクマしました' )" );
}
private function resultEvt(event:ResultEvent):void{
// result
}
private function faultEvt(event:FaultEvent):void{
// fault
}
]]>
</mx:Script>
<mx:WebService id="mossService" wsdl="http://moss/_vti_bin/Lists.asmx?wsdl" service="Lists">
<mx:operation name="UpdateListItems" fault="faultEvt(event)" result="resultEvt(event)"/>
</mx:WebService>
</mx:Application>

crossdomain.xml

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<site-control permitted-cross-domain-policies="all" />
<allow-access-from domain="*" />
<allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>

ブックマークレット

javascript:(function(){if(window.buildQuery){buildQuery();} else {var x=document.createElement('script');x.src='http://moss/Documents/bkm.js';x.type='text/javascript';x.charset='utf-8';document.body.appendChild(x);}})();

コメントをどうぞ