ラベル Javascript の投稿を表示しています。 すべての投稿を表示
ラベル Javascript の投稿を表示しています。 すべての投稿を表示

2007/03/06

BloggerのLabel Feedでエラーが・・。

BetaというかNew Bloggerにはラベル機能があって整理・管理するのに便利なんですが、そのラベル毎にフィードがあるのはご存知でしょうか?

元ネタというか詳しい解説はいつもの如くクリボウさんのページを読んで頂ければと思うのですが、私のこのBlogではラベルフィード機能を使って、記事の下部に「関連のありそうな記事」とかってちょっと間の抜けたLinksを表示しています。

最初は調子良かったのですがレイアウトを修正する為にに何度か自分で試しているとエラーが出ている事がわかりました。


実際にはこの「関連のありそうな記事」は "Bloggerに「関連記事リスト」を。"に書いたように、記事のラベルをLabel FeedをJSONP形式で受け取りその中で日付順の上位5つを現在は表示しています。

Label FeedのURLに関しては上記のクリボウさんのページに"ラベルフィード URL 作成装置"とかも置いてありますのでそちらを参考にしていただくとして、例えばこのBlogで"Blogger"ってラベルのATOM1.0な要約(summary)されたフィードはブラウザにより表示の仕方は変わりますがFirefox2だとこんな感じになります。



上記画像はATOM1.0な形式のフィードに対してFirefoxがスタイル変更をして表示しいますが、ソースはXML形式ですので、これをAJAXな感じでXMLHttpRequestを使って取得して加工し表示って事もありかもしれませんが、フィードのURLが別サイト(www2.blogger.com)になってしまう為、クロスサイトスクリプティング (cross-site scripting) 的なセキュリティー上の問題があり、XMLHttpRequestでは取得する事が出来ません。

ですがBloggerのフィードはJSONそれもCallback指定が可能なJSONPが使えます。Callbackを指定したJSONPなURL<はalt=json-in-scriptとパラメータを指定し、Callbackしてもらう関数名として"callback=任意の関数名"をパラメーターとして指定する形になります。(Javascriptに対してネイティブな形で値を返してくれるので、一手間省けて逆に楽だったりします。)

そのようにして受け取った結果を、今はレイアウトを少し変更しましたので、こんな感じで表示されます。



ですが、これがこんな感じで表示される事があります。



実はこれはJSONPな呼び出しが非同期であり、エラーの検出も困難な為に事前にラベルを列挙して表示しているのです。つまりJSONPな呼び出しが失敗しているんです。

原因はなんだろうとフィードのURLをブラウザで直接開いて見ると、こんなエラー画面が・・・。



別のラベル名で呼び出すとエラーは出ませんが、何度かリロードしてると2~3回でエラーになります。このエラーは暫く時間をおかないと解除されないようで、もしかしたらBloggerの負荷制限なのかとも思っています。

そんな感じで、この件に関してはちょっと情報を漁りつつBloggerに質問してみようかと思います。

Windows VISTAの実環境で使い始めないといけないなぁと思いつつも、勇気と時間がとれなくていまだメインな環境にはインストール出来ない状況です。必要な時間というのは、インストールそのものに必要な時間よりも、その後の設定やトラブルに対処する時間の方です。トラブルってよりも操作方法なり設定が変わった為に出来なくなったり、不具合が出た事に足して対応する時間が惜しいって感じです。以前はそれそのものも楽しめたんですが・・・・・・・・・。

続きを読む・・

2007/03/01

Bloggerに「関連記事リスト」を。

Read Moreな機能は大体片付いたんですが、Documentationがまだ残ってます。やった事は記録に残そうとは心がけているのですが、次なる創作意欲、むしろ誘惑に負けて「関連記事リスト」を記事の後ろに挿入するコードを書いてみました。

この機能は既に稼動中なんですが、例によってデザインセンスが欠如してますから取り敢えず列挙しましたって感じです。ちなみに複数記事が表示されている時は動かないようにしてあります

何をもって関連がある記事とするのかって大きな問題があるのですが、とりあえず記事に設定されたラベルを元に、そのラベルの一致している数が多く、そして更新日時の新しい記事って順序で表示しています。

具体的にはBloggerのFeedをラベル別にGData APIを介して取り込み、それを上記の条件で並べ直して列挙しています。

詳細に関しては、もう少しデザインとか汎用性を高めてから書きたいと思いますが、気になる方はこのページなりJavascriptなファイルなりを参照して下さい。

今一番不安なのは、苦労して車輪を再発明しまくってるだけじゃないかって事・・・・。

続きを読む・・

2007/02/28

Blogger Widgetで「続きを読む」を自動化。-- 2

本来であればBlogger Templateのマニュアルなりを読んでから取り掛かるべきなんでしょうが、いつもの如く現物合わせでやっています・・・。

Blogger TemplateStyle設定を書き加える事で指定したタグ範囲内を、単独で表示する時とその他の場合で表示/表示を切り替える事で実現するのが常道のようで、これは現在のBetaの取れた新しいBloggerの枠組になる以前に使われていた方法の転用的な物です。この辺りに関してはクリボウさんのページが時系列含めて分かりやすいかと思います。

ですが投稿された記事のURLを変数的な形で<A>タグの参照先として指定できないため、ルールを理解した上で記事のURLを推測するか、投稿後に確認したURLを再編集で書き込む必要があります。

そこで前回のPostではJavascriptを使い描画時に「続きを読む」リンクを動的に作成する機能をWidget内に組み込みました。


他に組み込んでいたScriptとの競合でイベントが無限ループに突入してStack over flowが発生というブラクラのような状態になってしまったりとかって問題もありましたが、現在私の環境(テンプレート)では稼動中です。

今は次の段階として他のテンプレートでの動作に関して検証しています。

基本的に私のテンプレートでのDOMは以下のように構成されています。

<DIV class=”post-body”>には記事本文が、続く<DIV class=”post-footer”>以下に記事へのURLとなるLink<a title=”permanent link” class=”timestamp-link”>で記述されています。

これにより現在のコードはこの”timestamp-link”というclass名を含む<a>タグを探してその内容を利用していますが、そもそもclass名は書式指定であり、これに頼る探索では汎用性に欠けるようです。

そこで他のサイトをInspectorで調べて回ったのですが、<a>タグのtitle=”permanent link” 指定はかなりの割合で設定されているようです。


上記のようにpost- body<div>タグに対してpost-footer<p>タグとなっていますが、記事へのリンクは要素 title=”permanent link”とされた<a>タグ内で記述されています。

つまりはpost-body (本文)のタグと同列のclass=”post-footer”で指定されたタグ内から要素 title=”permanent link”とされた<a>タグからURLを取得するようにすると、現状のかなりのテンプレートでも動作するかと思います

現在はこのような変更と合わせてLoad時間を短縮できるようにコードに手を入れています。またCurrentなソース(Javascipt)はここからダウンロードしてください。

続きを読む・・

2007/02/27

Blogger Widgetで「続きを読む」を自動化。

Bloggerでの「続きを読む」の方法ですが、アンカーの張り方(取得の仕方)がどうにも納得がいかない。

一度投稿してURLを見つけてから再度編集するって作業がどうにも面倒だったので、自動的にRead Moreなタグを挿入するWidgetを作ってみました。

本当はBloggerの機能自体でキレイにやる方法があるんじゃないかと思ったりもしてるんですが、どこを探してもその方法は見つからない。

基本的にはクリボウさんのページとか、Envyさんページを参考にはして、手書きで真面目にアンカー張れば動くようにはなったんですが、<div class="fullpost">は許せても、<div class="readmore">の書き方には納得がいかなくて。

そんな感じで、他の方法を検索したりするのが面倒になって作ったのがこのWidgetです。(導入済み)



Widget内でテンプレート的に設定できるようになっていますので、タグの文面の変更や画像を使う事も可能で、動作は InternetExplorer7 Firefox2.0 Opera9.10で確認しました。

強引なScriptですので制約があります。「続きを読む」機能は複数記事を表示している時に働いて欲しい機能ですが、その際に各記事の後ろに<span class="post-timestamp">で括られた記事単体を示すURLにAnchorを張った<a>タグが必要だという事です。


この制約は「続きを読む」で使うURLをその部分から取得しているからです。いくつのBloggerなサイトを見てみましたが、いくつかのサイトでは使われているようです。これは設定されているTemplateに依存するのですが、BloggerのTemplate書式・構造にそんなに詳しくないので未だ検討中ではあります。

と、ここまで書いて記事タイトルとかから取ってこようと変更中。

キーワードはpermanet link。これを<a>タグのTitle要素に入れているケースがかなり多いみたいのなので、そちらからURLを引っ張るように調整してみます。

興味のある方はどうぞご自由にお試しくださいというか、まて続報 !! (笑
※もっと簡単なやり方があるよとかって話が来そうで怖いですが・・・。

続きを読む・・

2007/02/26

Dojo -- JSONPに挑む。 【白帯編】

取り敢えずAjaxなライブラリとして使い始めたDojoですが、使い方というか流儀みたいなのがそれなりに理解出来たような気がするので、次の一歩としてJSON、それもCross Domainな呼び出しをする為にJSONPをと思っています。

JSONPServiceも他所様のサービスではなく自前で提供をと考えていますので、Server側のArchitectureも合わせて考慮する必要があり、PHPというのがPrivateな利用面ではMajorityなんでしょうが、個人的な好みからASP.NETで挑みます。

Sever側からはベタな手法としてRespone.Write()で手作りとかってのもあるんですが、ここはオシャレなLibraryを使ってみたいと思い、今回はJayrockを使ってみました。


JayrockLGPLでライセンスされており、単純な入出力のFormatter/Parserという面の他に、HTTP Handlerを利用したJSON-RPC的な実装も可能なかなり強力なLibraryです。

今回は取り敢えずJSONPな出力をするaspxなページを取り敢えず作ってみました。Jayrockのサンプルから引用したコードを新規のaspx.csに貼り付けた感じですが、JSONPの動作/雰囲気を掴むにはこんなもので十分かと。

using System;
using System.Data;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.IO;
using Jayrock.Json;
using Jayrock.Json.Conversion;

public partial class jsonpTest : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

        string callBackFunctionName = null;

        if (Request["callback"] != null)
        {
            callBackFunctionName = Request["callback"];
            Response.Write(callBackFunctionName + "(");
        }

        using (JsonWriter writer = CreateJsonWriter(Response.Output))
        {
            writer.WriteStartObject();              //  {
            writer.WriteMember("Name");             //      "Name" : 
            writer.WriteString("John Doe");         //          "John Doe",
            writer.WriteMember("PermissionToCall"); //      "PermissionToCall" :
            writer.WriteBoolean(true);              //          true,
            writer.WriteMember("PhoneNumbers");     //      "PhoneNumbers" :
            writer.WriteStartArray();               //          [ 
            WritePhoneNumber(writer,                //            { "Location": "Home",
                "Home""555-555-1234");            //              "Number": "555-555-1234" },
            WritePhoneNumber(writer,                //            { "Location": "Work",
                "Work""555-555-9999 Ext. 123");   //              "Number": "555-555-9999 Ext. 123" }
            writer.WriteEndArray();                 //          ]
            writer.WriteEndObject();                //  }
        }

        if (Request["callback"] != null)
            Response.Write(");");
    }

    private  void WritePhoneNumber(JsonWriter writer, string location, string number)
    {
        writer.WriteStartObject();      //  {
        writer.WriteMember("Location"); //      "Location" : 
        writer.WriteString(location);   //          "...", 
        writer.WriteMember("Number");   //      "Number" :
        writer.WriteString(number);     //          "..."
        writer.WriteEndObject();        //  }
    }

    private  JsonWriter CreateJsonWriter(TextWriter writer)
    {
        JsonTextWriter jsonWriter = new JsonTextWriter(writer);
        jsonWriter.PrettyPrint = true;
        return jsonWriter;
    }
}

ちなみにaspxファイルはこんな感じてデフォルトで作成された物から最初の一行以外は全部削ります。

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="jsonpTest.aspx.cs" Inherits="jsonpTest" %>

そしてクライアントになるhtmlファイルはこんな感じです。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
  <head>
    <script type="text/javascript" src="../dojo/dojo.js"></script>
    <script type="text/javascript">
        
        dojo.require("dojo.io");
        dojo.require("dojo.io.ScriptSrcIO");
        dojo.require("dojo.json");

        function testJSONP() {
        dojo.io.ScriptSrcTransport.bind({
          url: 'http://ilgvkteq.sv05.fsdotnet.net/ngm/jsonpTest.aspx'
          ,transport: "ScriptSrcTransport"
          ,jsonParamName: "callback"
          ,load: function(type, data, event, req) {
            showResult(data);
            }
        });
        }

        function showResult(result) {
            document.getElementById('output').innerHTML =dojo.json.serialize(result);
        }
    </script>
  </head>
  <body>

    <input type="button" onclick="testJSONP()" value="Test JSONP"/>
    <br /><br /><br />
    <div id="output"></div>

  </body>

</html>

このBloggerPost(記事)にはScriptを埋められないので、動作してる画面はこんな感じ。



ボタンを押すと、



かなり手抜きなテストですが、SeverからのResponseJavascriptObjectとして捕らえられている事とCallBackの指定の仕方が分かるので、白帯編としてはこれで十分かと。

この次は茶帯編として、JSONPで得た結果からGridの描画とかをと思っています。

続きを読む・・

2007/02/07

道場(Dojo)に入門!!

年始から有給使って旅行とか行ってましたが、このたびDojo に入門する事になりました。

AJAXなライブラリなんですが、PHPなりASP.Netを利用できない環境でCMS的な事をやってみようという事でDojoを使ってみる事にしました。

とりあえずフリーなWeb Spaceを借りて試したりしていたのですが、無条件でHTMLに広告を挿入してくるようなサイトなので、ContetnPaneで別ファイルをロードとかするときにちょっと不具合が出たりしています。

なので、Dojoのライブラリに手を入れてみたりしていますが、Dojoってどうやってデバッグとかしてるんだろうとか思いつつ、Alertとか使いながらなんとか必要な機能は追加できました。ContentPaneでLoadする際にはExecuteScriptというロードされる対象のスクリプトを実行する機能があるのですが、Scriptブロックに特定キーワードが含まれている時は、その実行を除外するような感じが出来ました。

本質的にはこんな機能を追加してるぐらいだったら、広告なしのサーバーを借りれば済むのですが、Dojo自体の実装とかを理解するには随分と役立ったかと思います。

コンテンツ自体は他の人との共同で作っていて、私はどっちかといえばフレームワークとか裏側のロジックを作ってる感じなんですが、もうちょっとしたら公開してみようかなとか思っています。

続きを読む・・

2006/12/24

You wanna change your behavior, don't you ?

Once upon a time, a company released a scheme for client side HTML which name was DHTML. They also proposed a forward-thinking scheme DHTML Behavior. I thought It was a quite good technical idea, but it has not got around enough.

最近Ajaxなコードを良く書くというか試すのですが、思い出すのはDHTML Behavior。MicrosoftがIE 5.0から組み込んだ機能なんですがあまり流行らずって感じです。今になってGoogleとかで検索しても個人の簡単なページしか見つからないし、MicrosoftのドキュメントもURLが変更になったのか探すのも面倒だったり。以前は日本語のHotWiredのWebMonkeyにも解説とかイカしたSampleとかあったんですが今は見れません。 本家WebMokey には記事がありますが、1998年だったんだと感慨深げに読んでいます。

当時DHTML BehaviorにXML+XSLそしてXMLHTTPRequestを使って業務系なVBで作られたDesktopアプリケーションをいくつかWebなApriに移行したりしてましたが、IE限定とはいえあれは画期的というか開発者というよりGeekなProgramerにはとても心地よいものでした。ページは全てXML記述。各コンポーネントは独自に制定したタグにより記述され、クライアントであるブラウザ(IE)はXMLページを開く事により連鎖的にXSL・CSSを取り込みブラウザ側でTransform。後は今で言うAjaxなアプリケーションとして動作するような仕組みでした。入力に対するValidationやフィールド移動なんかの機能も定義済みで、単一画面であり画面遷移なしで検索結果の表示なんかも当然XMLHTTPで。

そんな感じで個人的にはかなり気に入っていたんですが、予算を付けられずVisualなFormデザイナーとかを作ろうとしている段階でお蔵入りとなりしまた。

今思うと時代が早すぎたのかなぁと。XMLなんて理解する人が少なく、またXSLTによるTransformなんて想像の外だった時代ではありましたし、ブラウザがフロントエンドなアプリケーションの利便性に対する理解も少なかった時代でしたし。

今ならaddEventListenerとか、Prototype.jsのbindAsEventListenerでとかって話もあるんですが、css(Javascriptも埋め込んでしましたが)で定義出来てたDHTML behaviorの方がComponetの定義としてはイカしてたとたんじゃないかと。

でもまぁ時代も流れて技術のトレンドも変わるって事で、Prototype.jsを使いこなすが吉かなぁと思う今日この頃です。でもDHTMLって言葉なんか好きだったんだよね。

続きを読む・・

2006/12/22

Blogger Widget (3) for Amazaon Associates.

クロスドメイン問題に行き詰っていたAmazon アフィリエイト向けのWidgetですが、専用の外部ファイルを必要としない形、つまりはWidget内完結型での最終形はこんな感じになりました。


<script type="text/javascript" language="javascript">
<!--
/* Script for Amazon Associates */

var MAX_ADS = 3;
var LABEL_WORD_FACTOR = 4;

cKeyWords=function(name,value){this.name=name;this.value=value};
cKeyWords.compare=function(a,b){return b.value-a.value};

var org=window["onload"];
window["onload"]=
(typeof org!="function"?
function(event){insertAds(document.body,'div','post-body')}:
function(event){insertAds(document.body,'div','post-body');org(event)});


function insertAds(elm,tagName,className){
var elms=elm.getElementsByTagName(tagName);

for(var i=0; i<elms.length;i++){
var e=elms[i];
if(e.getAttribute("className")==classNamee.getAttribute("class")==className){

var words = getKeywordsFromElement(e);
var labelWords = getLabelWords(e);

// Evaluate keywords by Label
for(var n=0;n<labelWords.length;n++)
if(words[labelWords[n]])
words[labelWords[n]]*=LABEL_WORD_FACTOR;

var wordList = sortKeywordsByPoint(words);


// for Debug...
for(var n=0,t="Keywords::Debug=";n<wordList.length;n++){
t=t+wordList[n].name+"["+wordList[n].value+"] ";
}
var eee=document.createElement("p");
eee.style.fontSize="75%";
eee.style.display="none";
eee.innerHTML=t;
e.appendChild(eee);

var eDiv = document.createElement("div");

for(var n=0;n<MAX_ADS&&n<wordList.length;n++){
var eSpan = document.createElement("span");
var eAd = document.createElement("iframe");
eAd.setAttribute("src"
, "http://rcm-jp.amazon.co.jp/e/cm?t=isawseash-22"
+ "&o=9&p=9&l=st1"
+ "&mode=books-jp"
+ "&search=" + encodeURI(wordList[n].name)
+ "&fc1=<1=&lc1=&bg1=&f=ifr");
eAd.setAttribute("scrolling","no");
eAd.setAttribute("frameborder","0");
eAd.setAttribute("border","0");
eAd.setAttribute("height","150");
eAd.setAttribute("width","180");
eAd.setAttribute("marginheight","0" );
eAd.setAttribute("marginwidth","0");

if (document.documentElement.getAttribute("style") == document.documentElement.style){
eAd.style.borderStyle ="none";
var s1 ="BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none"
var s2 = eAd.outerHTML;
s2 = s2.replace(s1,"border:none");
eSpan.innerHTML =s2;
}
else{
eAd.setAttribute("style","border:none;");
eAd = eSpan.appendChild(eAd);
}
eDiv.appendChild(eSpan);
}//__for(ads)
e.appendChild(eDiv);
}//__if
}//__for
}


function getKeywordsFromElement(elm){
var re = new RegExp;
re.compile("([A-Z]+[a-z0-9\.#\+-]+[ \.][A-Z0-9]+[a-z0-9\.#\+-]+)"
+"([A-Z]+[A-Za-z0-9\.\+#\-]+)([繧。-繝エ繝シ]+)","g");

var s = getPostDocumentText(elm,"(prescriptform)");

var token = s.match(re);
var rslt=new Array();

if(token){
for(var i=0;i<token.length;i++){
if( rslt[token[i]])
rslt[token[i]]++;
else
rslt[token[i]]=1;
}//__for
}//__if(token)

return rslt;
}//__function getKeyworksFromElement;

function getPostDocumentText(elm,exceptTagNames){
var sRslt="";
var re=new RegExp(exceptTagNames,"i");
for(var i=0;i<elm.childNodes.length;i++){
var e=elm.childNodes[i];
if(elm.childNodes[i].nodeType==1
&&!String(e.tagName).match(re)){
sRslt=sRslt+getPostDocumentText(e,exceptTagNames);
}
else if(e.nodeType==3){
sRslt=sRslt+e.nodeValue;
}
}//__for(childNodes)
return sRslt;
}

function sortKeywordsByPoint(keywords){
var wordList = new Array();
for( v in keywords)
if(typeof keywords[v]!="function")
wordList.push(new cKeyWords(v,keywords[v]));
wordList.sort(cKeyWords.compare);
return wordList;
}//__sortKeywordsByPoint

function getLabelWords(ePost){
var arRslt = new Array();

for(var eNext = ePost.nextSibling;eNext.nodeType!=1;eNext=eNext.nextSibling);
var eSpans = eNext.getElementsByTagName("span"); //Lable is in Span Elemnet.

for(var i=0; i<eSpans.length;i++){
var e=eSpans[i];
if(e.getAttribute("className")=="post-labels"e.getAttribute("class")=="post-labels"){
var eKeywords= e.getElementsByTagName("a");
for(var l=0;l<eKeywords.length;l++){
arRslt.push(eKeywords[l].innerHTML);
}
break;
}//__if
}//__for

return arRslt;
}//__getSearchKeyword
-->
</script>

そんなに特殊な事をしてるわけではなくて、ベタにキーワードを抽出というか、英単語とカタカナの単語を抜き出して出現回数で順位付け、それらの単語がLabelで使われている場合は倍率ドンって感じにして、上位から順にAmazon用のタグを作成して並べるって感じです。

例によって該当しないキーワードの場合は売れ筋商品が表示されたり、Books-jp指定しているだけなので、キーワードによっては不思議な書籍が表示されますが、それはそれで楽しめないようではダメですな。

BlogのPost(記事)に直接アフィリエイトなiframeとか埋めてしまうと、後で消すとか変更とか出来ませんが、Widgetにした事で動的な後付ですから変更が容易になるあたりが利点ではありますが、意図しない物が選択・表示されてしまう悲哀を背負っていますので、その辺りの改善は外部ファイル連携バージョンで対応する予定です。

外部に置くのはxslファイルにするか、それともRESTでJSONPな感じなAPIを用意するかは、まだ考え中ですが、最近のテーマは「素敵なGoogle生活」だったりするんで、場所もGoogle関係とするとGoogle Page Createtorとかになってしまうんで、Javascriptファイルやxslファイルは置けてもAPIの実装は無理だしとか。

続きを読む・・

2006/12/21

A Problem of Cross Domain.

投稿されたPostからKeywordを抜き出して、Amazon Web Service(AWS)使って広告を表示するWidgetをと考えてたんだけど、やっぱCross Domainの問題がネックになってWidget内だけでは完結しそうにないです。

JSONPとかってやるにしてもAWSではxslファイルは指定しないと駄目なんで。結局のところScript FileなりXSL TemplateをBloggerには置けないので、どこか外に置く必要があります。BlogSpotではなくFTP Publishingであればそれも出来るかと思うんですが、それだと趣旨がちょっと変わってしまうんだなとか思ってちょっと落ち込んでます。

Keywordの抽出に関してはカタカナと英単語と抜き出して出現回数上位をとかってとこまでは書いたんで、とりあえずこのLogicでAmazonライブリンク を呼ぶように変更する予定ではあります。

ちなみに色々な制限の中でCode書いてWidget書くことと、表示される広告内容に興味があるだけてAffiliate収入なんかはどうでもいいんですが、レポートのページとかは面白いなと思う今日この頃であったりして自分で買う時にわざわざ使ったりしてみたりとか思うんですが、海外発送は書籍ぐらいなんだよな・・。


続きを読む・・

2006/12/19

Extract Keywords.

Blogに投稿された記事から、キーワードを抽出してそれを元にAmazonの広告を作成とかって流れを夢想中。もちろんBloggerというかWidgetというルールで。

まずは形態素解析が必要になるんですが、「すべての漢字を取り出す正規表現」をPHPで試す って記事と、それをJavaScriptに応用した記事 を発見。 こちらの方はKOSHIAN API という文章からキーワードを使うAPIを実験的に公開もされています。

KOSHIANでバッチリじゃないとか思ったりもするんですが、実験的に公開されているAPIをガシガシ叩くわけにもいないので、

var res = str.match(/[一-龠]{2,}[ァ-ヴー]{2,}[a-zA-Z.]{2,}[a-zA-Z]{2,}/g);

ってのを拝借する事にします。

Keywordsが抽出できた所でこれに順位づけをしてやる必要があるんですが、これにはGoogle Suggestとはてなブックマーク件数取得APIとかを使って見ようかと。 本筋としてはAmazon ECS4.0のAPIをうまく使うべきかと思いますが、ちょっと寄り道も楽しいかと。

続きを読む・・

2006/12/18

Blogger Widget (2)

Widgetは作って見たいものの、何かネタは無いものかと思いながら唸ってばかりですが、もう1ネタ起こしてみました。

今回のは、各Postの下にAmazon Associatesな広告を自動的に挿入・表示する物です。

対象としたのはAmazonライブリンクです。これは通常キーワード・ジャンルを指定してiframeなタグ作ってから埋め込むんですが、今回のWidgetは、Postに付けられたTagをキーワードにiframeなタグを生成して、Postの本文の直後にねじ込み表示します。

複数個のTagが指定されていた場合は常に最初のTagをキーワードとします。BloggerのTagはPost・Edit時に指定した順序ではなくて、Alphabetical orderで表示されてしまうので、なんか台無しな感じですが・・・。ちなみにタグを設定してない投稿の後には売れ筋がでるんで、主に漫画とかが表示されてちょっと嫌。

それと動的にiframeタグを生成しているのですが、その際のstyle attributeの指定がどうもうまくいってません。Internet Explorer (IE)で見るとIFrameのBorderが残っちゃってます。IEの問題点として、setAttributeでstyleを指定できないので、style.cssTextでアクセスするのは知っていたつもりなんでが、何故か未だにBorderが消えてくれないです。それ以外は IE7 Firefox2 ともに大丈夫みたいです。(OperaとかIE6とかはまったく気にしてませんけど。)

こんな感じで納得いってないのですが、商品の選択され具合が興味深いので暫く動かしてみようかと思います。


ちかみにWidgetに書いてるコードはこんな感じです。(汎用的に書き初めたけど破綻してるのが物悲しい・・)


<script type="text/javascript" language="javascript">
/* Script for Amazon Associates */

var org=window["onload"];
window["onload"]=
(typeof org!="function"?
function(event){insertAds(document.body,'div','post-body')}:
function(event){insertAds(document.body,'div','post-body');org(event)});

function insertAds(elm,tagName,className){
var elms=elm.getElementsByTagName(tagName);

for(var i=0; i!=elms.length;i++){
var e=elms[i];
if(e.getAttribute("className")==classNamee.getAttribute("class")==className){
var eDiv = document.createElement(tagName.toLowerCase()=="div"?"span":"div");
var eAd = document.createElement("iframe");
eAd.setAttribute("src"
, "http://rcm-jp.amazon.co.jp/e/cm?t=isawseash-22"
+ "&o=9&p=48&l=st1"
+ "&mode=books-jp"
+ "&search=" + encodeURI(getSearchKeyword(e))
+ "&fc1=1=&lc1=&bg1=&f=ifr");

if (document.documentElement.getAttribute("style")
== document.documentElement.style)
eAd.style.borderStyle ="none";
else
eAd.setAttribute("style","border:none;");

eAd.setAttribute("scrolling","no");
eAd.setAttribute("frameborder","0");
eAd.setAttribute("border","0");
eAd.setAttribute("height","90");
eAd.setAttribute("width","728");
eAd.setAttribute("marginheight","0" );
eAd.setAttribute("marginwidth","0");

eAd = eDiv.appendChild(eAd);
e.appendChild(eDiv);
}//__if
}//__for
}

function getSearchKeyword(ePost){
var ret = null;

for(var eNext = ePost.nextSibling;eNext.nodeType!=1;eNext=eNext.nextSibling);
var eSpans = eNext.getElementsByTagName("span");

for(var i=0; i!=eSpans.length;i++){
var e=eSpans[i];
if(e.getAttribute("className")=="post-labels"e.getAttribute("class")=="post-labels"){
var eKeywords= e.getElementsByTagName("a");
if(eKeywords.length){
ret = eKeywords[0].innerHTML;
break;
}
else {break;}
}//__if
}//__for

return ret;
}
</script>


私はAffiliateとかそんなに詳しくないのですが、Amazonだと今時はREST経由で取得したXMLをXSLTで整形してとかがオシャレらしいんで、次回はそれをとか思ってます。

ちなみに当初はAmazonおまかせリンク(TM) ベータ版 とかってのを試したんてすが、load後だとなにやってもまともに動かなかったのと、Google Adsenseとは比較にならないほどのキーワード抽出というか選択の間抜けさだったりしたので止めました。

この辺り、キーワード抽出・選択あたりをPostされた記事の中から適切に出来たりしたら素敵だなぁ・・・。

続きを読む・・

2006/12/17

Open Link as New Window

なんとなくWidgetを作ってみたくて、投稿内のリンクを別窓で開くWidgetを作ってみました。

ちょっと力業のコードですがFirefoxとInternetExplorerでの動作を確認しています。

コードはこのページのソースを参照して頂ければとか思うのですが、余白・改行を詰めてあるので見れたものではありませんので以下に。
var org=window["onload"];
window["onload"]=
(typeof org!="function"?
function(event){insertTargetAttribute(document.body,'post-body')}:
function(event){org(event);insertTargetAttribute(document.body,'post-body')});

function insertTargetAttribute(e,className){
for( var eChild=e.firstChild;eChild!=null;eChild=eChild.nextSibling){
if(eChild.nodeName=='A'&&eChild.nodeType==1&&hasClassName(eChild,className))
eChild.setAttribute("target","_blank");
insertTargetAttribute(eChild,className);
}
}

function hasClassName(elm,className){
if(elm==null)return false;
if(elm.nodeType==1)
if(elm.getAttribute("class")==className||elm.getAttribute("className")==className)
return true;
return hasClassName(elm.parentNode,className);
}


要するにclassがpost-bodyなタグ以下にあるAnchor TagにAttribute target="_blank"を追加しています。今風というかXHTML 1.1とかですとtarget="_blnak"なんて廃止されちゃってたり、そもそも嫌いな方もいらっしゃるのは承知の上ですが、BloggerのWidgetでこんな機能も付加できる例としてはアリじゃないかと。

普通に投稿するときにAnchor Tagにtarget="_blank"を追加して書いてれば、こんな物は必要ありません。 本題としてはBloggerのWidget機能に対する考察であったり、Postされた記事に対しての後加工みたいな感じです。Visual系(?)な人がネタさえ考えたらもっと素敵(≒馬鹿)な事が出来そうな予感もありますし。

ちなみにGoogleというかBloggerにRequestとして、追加したWidgetのタイトルを非表示に出来るようにしてくれって事があったりします。HTML/JavaScriptなPage Elementを複数追加してると混乱しませんか?

それからこのコードのhasClassName()なんて、もっとオシャレな書き方・処理があるんじゃないかと思うんですが、どなたかアドバイス頂けたら幸いです。ちなみにprototype.jsは無しの方向で。

この下のボタンでWidgetを追加できます。お好きな方はご活用ください。



気が向いたらjavascriptでOpen as New Windowするコードで書き換えてみたりするつもりです。

それから別途にSnap Preview Anywhereとかも設定してたりして、ちょっとウザい事になってますが、今回のWidgetとは関係ありませんというか、Inspireされてたりします。

それと某巨大掲示板からリンクされてたのがTriggerだったりします・・。

続きを読む・・

2006/09/13

AJAX, JAVA Applet, ActiveX

AjaxでサーバーからloadされるJavascriptが署名付きでクライアント側で評価出来るになれば良いのに。

これはHTTPSなり使ってればサーバー側の署名から評価はできるんだけど。

匿名の世界での安易にプログラム実行してしまう環境ってのはやっぱりイマイチな気がしないでもない。

いっそサイズとか非可読性を考慮して中間コードにして・・・・とか考えてたら、それってActiveX? Java Applet? とぐるっと思考が一周してしまいました。

ブラウザのみでOK、追加のコンポーネントは一切必要なしってのが、AJAXの良さなんだけどね。

でも何処のページみるのにもJavascript on とかって憂鬱な気が。

暫くはIntranet向けにしかコード書くつもりもないので、仕事的には気にならないが、技術の普及という面では気になる。イントラ向けならACTIVE Xでも JAVA Appletでも良いじゃんとか。まぁExtraに出すからとか、なんとか理由を考えつつ、自分を納得させる。

なんか自身が矛盾していると、内部でひたすらループ。

まぁ比較的に古くて枯れた技術というか手法の組み合わせなんで、あまり深く考えてはいけないでしょうね。

なんとなく、私なりに開発の本流にのせる為の条件を書いて見た。
これはライブラリを含む開発環境で網羅してもらいたい事。

・ブラウザ間の差異を吸収する事。
IEのみとかは無しの方向で。IE, Mozilaは当然として Operaぐらいはなんとかカバーしたい。

・サーバー側の動的なページ作成時における、デザインとコードの分離が可能である事。
デザインとコードの分離を進めてきたのに、ここで後戻りは・・・・・・・・。

・デバッグ機能がある事。
printf 的なのとか log出力なDebugしか出来ないのはもう嫌かも。

こんな感じです。

続きを読む・・