Showing posts with label Javascript. Show all posts

[JavaScript] Oracle JET 2.0.0: Now Available Open Source with New Data Visualization Features

原文はこちら。
https://blogs.oracle.com/data-visualizations/entry/oracle_jet_now_open_source

Oracle JET 2.0.0 (JavaScript Extension Toolkit) がオープンソースとしてリリースされました。ソースはGitHubで公開されています。
Oracle JET 2.0.0
http://www.oraclejet.org/oracle/oraclejet
https://github.com/oracle/oraclejet
JET 2.0.0には数多くのデータ可視化機能(Data Visualization)が含まれています。以下で一部をご紹介します。
What's New in Oracle JET 2.0.0
https://community.oracle.com/community/development_tools/oracle-jet/blog/2016/03/01/whats-new-in-oracle-jet-200

Picto Chart

新しいPictoChart可視化コンポーネントを使うと、数値データをイメージで可視化できます。Infographicでよく使われていますが、このコンポーネントを使うと、これまでの表やグラフよりもより興味深い、効果的な方法で数値情報を表現することができます。JETのPictoChartは選択、ハイライト、フィルタリングだけでなく、他の可視化機能と同様のアニメーションや対話機能をサポートしています。魅力的なダッシュボードを作成する上で不可欠な要素になると考えます。


For an in-depth look at PictoChartについての詳細は、以下のJETのブログエントリをご覧ください。
Introduction to PictoCharts
https://community.oracle.com/community/development_tools/oracle-jet/blog/2016/02/29/introduction-to-pictocharts

New Charting Features

グラフにも新たな表現形式が追加されています。
  • 一方向のみでグラフのズーム&スクロールが可能になりました

  • 積み上げ棒グラフで棒の総数を表示できるようになりました

    • グラフの軸ラベルにラベルテキストをラップできるようになりました

    • ズーム&スクロールウィンドウで、異なるデータ系列や異なるグラフの種類を表示できるようになりました
    • 参照オブジェクトがデータ可視化コンポーネント間でハイライトやフィルタリングできるよう、参照オブジェクトでのカテゴリをサポートします。
    JET 2.0.0では新しいデータ可視化機能やフレームワーク機能がたくさん追加されています。新機能の完全なリストをご所望であれば、以下のエントリとリリースノートをご覧ください。
    What's New in Oracle JET 2.0.0
    https://community.oracle.com/community/development_tools/oracle-jet/blog/2016/03/01/whats-new-in-oracle-jet-200JET v2.0.0 Release Notes
    http://www.oracle.com/webfolder/technetwork/jet/releaseNotes.html
    JET Data Visualizationsに関する詳細を説明した一連のエントリは、以下のリンクからどうぞ。
    JET Data Visualizations: FAQ
    https://community.oracle.com/docs/DOC-993442

    [JavaScript] Oracle JETがオープンソース化されました

    本日から、Oracle JET(JavaScript Extension Toolkit)はオープンソースになりました。
    Oracle JET
    http://oraclejet.org
    ソースはGitHubに公開されています。現在のバージョンは2.0.0です。
    oracle/oraclejet
    https://github.com/oracle/oraclejet 
    早速jaxenterで記事になっていますね...と読んでみたら、執筆者は最近はJETに関するエントリをたくさん書いているNetBeansのEvangelist(Geertjan Wielenga)でした。
    Visualize data in the Cloud with enterprise JavaScript
    Open Sourced: Oracle JET, An Enterprise-Ready JavaScript Toolkit
    https://jaxenter.com/open-sourced-oracle-jet-124350.html

    [JavaScript, Database] Node-oracledb: Avoiding "ORA-01000: maximum open cursors exceeded"

    原文はこちら。
    https://blogs.oracle.com/opal/entry/node_oracledb_avoiding_ora_01000

    Nodeを始めた開発者は、もっとも予期しないタイミングでメソッドが呼び出されるように見えるという、異なるJavaScriptのプログラミングスタイルに直面する羽目になるでしょう。最初のnode-oracledbでハックするフェーズにいる間に、
    ORA-01000(maximum open cursors exceeded / 最大オープン・カーソル数を超えました
    というエラーに出くわすことがあるでしょう。カーソルとは「解析済みSQL分とその他の処理情報を保持するセッション固有のプライベートSQL領域へのハンドル」です。

    ORA-01000に出くわしたときに実施すべきことをまとめました。
    • 一度に大量の不完全に処理されたステートメントをオープンしない
      • 接続をリリースする前にResultSetをクローズする
      • PL/SQLブロック内でdbms_sql.open_cursor()を使ってカーソルをオープンする場合、REF CURSORSをnode-oracledbへ返す場合以外は、PL/SQLブロックから返る前にクローズする。(将来のnode-oracledbバージョンでOracle Database 12cのImplicit Result Setをサポートする場合、これらのカーソルもまたPL/SQLブロック内で閉じてはいけない)
      • アプリケーションが想定通りの順番で接続とステートメントを処理していることを確認する
    • 適切なステートメントキャッシュサイズ(Statement Cache size)を選択する。node-oracledbには接続ごとのステートメントキャッシュがある。node-oracledbが内部でステートメントをリリースすると、当該接続のステートメントキャッシュに入れられるが、ステートメントの再実行を非常に効率的にするため、カーソルは引き続きオープンしたままである。
      キャッシュサイズはstmtCacheSizeという属性で設定することができる。
      stmtCacheSize
      https://github.com/oracle/node-oracledb/blob/master/doc/api.md#propdbstmtcachesize
      適切なステートメントキャッシュサイズはステートメントの局所性に関する知識とアプリケーションで利用可能なリソースに依存する。ステートメントを再実行する場合、実行されていればキャッシュにステートメントが残っている。何個のステートメントをキャッシュに保持したいか、ステートメントを再実行しないとか、キャッシュにないというまれなケースでは、キャッシュを無効にして管理のオーバヘッドを排除することができる。
      誤ったステートメントキャッシュサイズを設定すると、アプリケーションの効率が低下する。幸いにしてOracle 12.1では、oraaccess.xmlファイルを使い、キャッシュを自動的にチューニングすることができる。
      External Configuration
      https://github.com/oracle/node-oracledb/blob/master/doc/api.md#oraaccess
      node-oracledbのステートメントキャッシュに関する詳細情報は以下のリンクに記載がある。
      Statement Caching
      https://github.com/oracle/node-oracledb/blob/master/doc/api.md#stmtcache
    • バインド変数を利用することを忘れないこと。使わない場合、ステートメントの各バリアントが独自のステートメントキャッシュエントリとカーソルを持つ。適切なバインディングを使えば、一個のエントリとカーソルだけですむ。
    • 適切にデータベースのopen_cursorsパラメータを設定する。このパラメータは各セッション(つまり、node-oracleの各接続)が利用可能なカーソルの最大個数を指定するもので、接続数がこの値を上回ると、ORA-01000がスローされる。以下のドキュメントにopen_cursorsの記載がある。
      Oracle® Databaseリファレンス 12cリリース1 (12.1)
      http://docs.oracle.com/cd/E57425_01/121/REFRN/GUID-FAFD1247-06E5-4E64-917F-AEBD4703CF40.htm
      Oracle® Database Reference 12c Release 1 (12.1)
      http://docs.oracle.com/database/121/REFRN/GUID-FAFD1247-06E5-4E64-917F-AEBD4703CF40.htm
      接続のステートメント・キャッシュ内のエントリごとのカーソルと一緒に、接続が現在実行している新しいステートメント、もしくはリリースされていないResultSetもまたカーソルを消費する(どちらの状況では、まだキャッシュされていない)。任意の接続が持つオープンされたカーソルの個数の最大値を収容できるよう、OPEN_CURSORSは十分に大きな数値になっていることを確認すること。必要な上限値は、stmtCacheSize + 接続中のステートメントの最大実行回数である。
      これは、すべての接続単位であることを忘れてはいけない。ステートメントが内部的にリリースされた場合も、キャッシュ管理が行われる。接続の大部分がOPEN_CURSORSで定義した個数よりも少ないカーソルを使用できるが、一つの接続でリミットに達して、新規のステートメントを実行しようとすると、その接続でORA-01000を取得することになる。

    [JavaScript, Java] Dynamic linker API for the Java platform (JEP 276)

    原文はこちら。
    https://blogs.oracle.com/sundararajan/entry/dynamic_linker_api_for_the


    JEP 276は、Javaのための動的リンカAPIを定義しています。
    JEP 276: Dynamic Linking of Language-Defined Object Models
    http://openjdk.java.net/jeps/276 
    このJEPでは、"プロパティを読み取り"、"プロパティの書き込み "、"callableオブジェクトの呼び出し"といった、invokedynamicのCallsitesと呼ばれる、オブジェクトへのハイレベルな操作をリンクするための機能」を提供します。こうしたプレーンなJavaオブジェクトに対するこうした操作の通常のセマンティクスのためのデフォルトリンカだけでなく、言語固有のリンカのインストールのためのファシリティも提供します。

    Nashorn JavaScriptエンジンではすでに、プロパティのリンク、インデックスによるアクセス、スクリプトオブジェクトだけでなく、「外部」「ホスト」Javaオブジェクト(POJOs)への呼び出しのためにdynalinkライブラリを使っています。JEP-276を使用し、"jdk,dynalink"と命名されたJava 9モジュールのパブリック(JDK固有の)APIとしてdynalinkを公開します。


    現在、"jdk9 sandbox"というOpenJDKリポジトリのJEP-276-branchという名前のブランチに、JEP-276のソースコードがあります。
    OpenJDK / jdk9 / sandbox
    http://hg.openjdk.java.net/jdk9/sandbox 
    これは、最終的にjdk9リポジトリに取り込まれます。dynalink" APIで遊んでみたい方は、このフォレストをチェックアウトし、"JEP-276-branch"をビルドすることができます。
    Java APIとともに使いたい場合には、最近jshellツールを使っています。
    JEP 222: jshell: The Java Shell (Read-Eval-Print Loop)
    http://openjdk.java.net/jeps/222 
    以下はdynalink APIをJavaコードから使うためのjshell REPLのサンプルです。
    import java.lang.invoke.*
    // dynalink API lives in these packages
    import jdk.dynalink.*
    import jdk.dynalink.support.*

    // dynamic 'operation' for a callsite. 'length' property
    Operation op = new NamedOperation(StandardOperation.GET_PROPERTY, "length")

    // method type of operation to be linked - length is 'int' value
    MethodType mt = MethodType.methodType(int.class, Object.class)

    // callsite descriptor
    CallSiteDescriptor desc = new CallSiteDescriptor(MethodHandles.publicLookup(),
    op, mt)

    // callsite
    SimpleRelinkableCallSite cs = new SimpleRelinkableCallSite(desc)

    // create a linker factory
    DynamicLinkerFactory fac = new DynamicLinkerFactory()
    // create dynalink linker
    DynamicLinker linker = fac.createLinker()

    // link the callsite
    linker.link(cs)

    // invoke it!
    printf("array size %d\n", (int)cs.getTarget().invoke(new String[10]))

    import java.util.ArrayList

    // make a list and populate two elements
    ArrayList<String> al = new ArrayList<>()
    al.add("hello")
    al.add("world")

    // get 'length' of array list - which is nothing but size
    printf("list size %d\n", (int)cs.getTarget().invoke(al))
    上記のREPLでは、"array size 10" と "list size 2" をそれぞれ表示します。(異なる"this"オブジェクトが渡された場合に)lengthプロパティは自動的に配列の長さに再リンクされ、ArrayListのsize になることに注意してください。Javaオブジェクトのリンク(および再リンク)はdynalink実装に付属する"java beans linker"によって処理されます。

    [Java, JavaScript] Fully Transparent Java Objects in Nashorn

    原文はこちら。
    https://blogs.oracle.com/nashorn/entry/fully_transparent_java_objects_in

    NashornのJSAdapterは、JavaオブジェクトをJavaScriptで取り扱うための強力なツールで、完全な透過性を有していますので、これを利用してJavaオブジェクトをラップし、新たなプロパティや挙動を追加することができます。
    JSAdapter constructor
    https://wiki.openjdk.java.net/display/Nashorn/Nashorn+extensions#Nashornextensions-JSAdapterconstructor
    例:
    var Date = Java.type('java.time.LocalDate')

    function wrapDate(d) {
    return new JSAdapter() {
    __get__: function(name) {
    if (name === 'yesterday') {
    return d.minusDays(1)
    }
    return d[name]
    }
    }
    }

    var now = wrapDate(Date.now())
    実行すると、このスクリプトは現在時刻を表す Date オブジェクトを JSAdapter でラップし、ラップされたオブジェクトの任意のプロパティに対するアクセスがあると、速やかに __get__ function が呼び出されます。プロパティ名がアダプタが理解しているもの(ここでは yesterday )であれば、適切な値を返します。
    jjs> load('yesterday.js')

    jjs> print(now.yesterday)

    2015-11-04
    その他のすべてのプロパティはラップされたオブジェクトから取得されます。
    しかし、これらの例を見ると、ラッピングが完全ではないことを示しています。
    jjs> print(now)

    <shell>:1 TypeError: [object JSAdapter] has no such function "toString"

    jjs> print(now.lengthOfMonth())

    <shell>:1 TypeError: [object JSAdapter] has no such function "lengthOfMonth"
    ラッパーは、転送するように指示されたラップされたオブジェクトにそれらの要求を転送するだけの、独立したオブジェクトです。

    ここでラッパーが完全に透過的でなければならないのは、デフォルトの場合です。ラッパーを完全に透過的にするためにここで必要なのは、あるプロパティを追加するような、すべてのメソッド呼び出しをラップされたJavaオブジェクトへ転送するデフォルトの場合です。このケースの場合、レシーバーと引数を正しく取り扱う必要があるため、プロパティの検索に比べていささか複雑です。受信機と引数を正しく処理する必要があるため場合は、プロパティの検索よりも少し複雑です。

    以下の例は、透過呼び出しの転送のために利用可能なイディオムです。
    function wrapDate(d) {
    return new JSAdapter() {
    __call__: function() {
    ...
    var args = [d].concat(Array.prototype.slice.call(arguments, 1))
    return Function.call.apply(d[arguments[0]], args)
    }
    }
    }
    非常に思慮深いJavaScript中のこの2行で、所望の機能を果たします。各JavaScript関数には、暗黙のローカル変数とargumentsがあり、これは現在起動中の関数に渡されるすべての引数を保持します。このarguments配列は2箇所で利用されています。

    最初の行で、実際の呼び出し引数を配列から抽出しています。argumentsの最初の配列要素は呼び出されたメソッド名であって、これは引数になくてもかまいません。しかしレシーバーにとってはこの引数は必要で、 concat を呼び出すことにより、その第1引数を引数の前に連結しています。

    2行目では、イディオムが実際に呼び出しを行う Function.call 関数を使っています。プロパティ検索を使って、呼び出されるメソッドを表すオブジェクトをラップされたオブジェクトから取り出します。ここで、arguments変数の最初の要素が呼び出されるメソッドの名前であることを思い出してください。レシーバーオブジェクトを含む引数は、すでに引数にargsに存在します。

    これで。ラッピングが透過的になっています。
    jjs> print(now)

    2015-11-05

    jjs> print(now.lengthOfMonth())

    30

    jjs> print(now.yesterday)

    2015-11-04
    transparent forwarding idiomを説明したサンプルはJDK 9のNashornのソース(samples/jsadapter-fallthrough.js)にあります。

    [訳注]
    JDK 9 Nashornのソースは、以下のURLにアクセスし、
    http://hg.openjdk.java.net/jdk9/jdk9/nashorn
    左側のメニューの[browse] をクリック > ディレクトリ samples をクリック > jsadapter-fallthrough.jsをクリックすると確認できます。

    [Cloud, WebCenter, JavaScript] Oracle Documents Cloud Service and Node.js

    原文はこちら。
    https://blogs.oracle.com/OracleCloud4Developers/entry/oracle_documents_cloud_service_and

    Oracle Documents Cloud Serviceでは、クラウドで直接REST APIを使ってファイルやフォルダ、ユーザーの管理ができる一連の機能を提供しています。
    Oracle Documents Cloud Service
    https://cloud.oracle.com/documents
    この記事ではAPIの利用例をご紹介します。今回は、Node.jsでの操作についてご紹介します。
    メインコンテナ、メインコンテナの子、特定のフォルダやファイルに関する情報にアクセスします。また、特定のファイルの内容を取得したり、アイテムを削除したり、項目の名前を変更したりします。これらはすべてNode.jsのExpressフレームワークを使用して構築したWebアプリケーションを介して実行します。

    今回の例を実施するにあたっての前提条件は以下の通りです。
    • Node.js
    • Expressフレームワーク
    • 結果表示のためのテンプレートエンジン
    • 開発環境に含まれる、Node.js用RESTクライアント
    • スクリプト記述用テキストエディタ
    • APIのエンドポイントURL
    • 認証のための資格証明(ユーザー名とパスワード)
    • サービスのメインコンテナに配置する2個のテキストファイル
    アプリケーションの全貌は下図をご覧ください。
    img1
    Node.js自身がHTTP Serverの機能を持っており、ルーティング、テンプレート化が簡単という理由から、Expressフレームワークを使うことにしました。

    HTTP Serverが受け取ったリクエストは、REST APIと対話する適切なスクリプトにルーティングされます。スクリプトがAPIからレスポンスを受け取ると、即座に描画テンプレートを使ってブラウザに対してレスポンスを描画します。

    テンプレートエンジンとしてEJSを、専用RESTクライアントとしてnode-rest-clientを選択しました。これらの2種類はExpressフレームワークとともに以下のコマンドを実行し、node package managerを使ってインストールすることができます。
    • npm install ejs
    • npm install node-rest-client
    • npm install express
    アプリケーションサーバは非常に基本的なものです。Expressフレームワークと、テンプレートエンジン、2個のルーティングを設定します。最初のルーティングはインデックスページ、もう一つはREST APIへのHTTPリクエストを処理するページです。サーバーはポート番号3000でリクエストを受け付けます。

    APIのエンドポイントURLを知るため、サービスのWebアプリケーションにログインします(cloud.oracle.comでデータセンターを選択、アイデンティティ・ドメイン、ユーザー名、パスワードを入力、Documentsクラウドサービスを選択して、サービスのコンソールを開きます)。

    Webアプリケーションにリダイレクトされると、/home/nameascを/apiで置き換えることでAPIのエンドポイントを取得できます。WebアプリケーションのURLは以下のような構成になっています。
    https://<account>-<identity domain>.documents.<datacenter>.oraclecloud.com/documents/home/nameasc
    例として、実際のURLが以下のようであれば
    https://foo-bar.documents.us.oraclecloud.com/documents/home/nameasc
    APIのエンドポイントURLは以下のようになります。
    https://foo-bar.documents.us.oraclecloud.com/documents/api
    今後、このドメインを例にして説明を進めます。
    APIの認証に使うユーザー名とパスワードはWebアプリケーションログイン時と同じものですが、この場合、アイデンティティ・ドメインは不要です。

    前提条件として記載したように、サービスのメインコンテナに2個のテキストファイルを配置することを忘れないでください。

    サービスのフォルダ構成を明確にするために、下図をご覧ください。
    img1
    実際のREST APIとの通信を司るスクリプトには2個のハンドラがあります。一つはGETリクエスト用、もう一つは自身へのPOSTリクエスト用です。

    GETリクエストの場合、ボタンを持つフォームを含むテンプレートをレンダリングしますが、POSTリクエストの場合、さらにJSON形式で認証のための資格証明を含むテキストファイルを開き、その内容を解析してオブジェクトに格納します。

    ファイルの中身は、次のような感じになります。
    {"user" : "john.doe@company.com", "password" : "supersecret"}
    続いて、基本認証を使ってAPIに対し認証するための組み込み機能を提供するnode-rest-clientが必要です。
    var RESTClient = require('node-rest-client').Client;
    restClient = new RESTClient({user : credentials.user, password : credentials.password});
    その後、ファイルはAPIのエンドポイントURLを設定します。
    var apiURL = "https://foo-bar.documents.us.oraclecloud.com/documents/api";
    最後に、実際のリクエストをREST APIに対して送信する機能が含まれています。
    //perform the api request
    restClient.get(apiURL, function(data, apiResponse){
    //set up params to be passed into the template
    var params = {
    respData: ((typeof data) == 'object') ? JSON.stringify(data) : data
    }
    //send HTTP response (render template)
    res.render('rest', params);
    });
    ここで説明したPOSTハンドラはHTMLフォームが発行されたタイミングで呼び出されます。

    REST APIへのリクエスト発行の最終ステップでNodeサーバーを起動しています。

    この例はローカルのUbuntu上にインストールされたNode.jsを使っています。開始する場合には、ターミナルを開き、以下のコマンドを実行します。
    sudo nodemon <path file.js="" server="" to="">
    個人的には、スクリプト変更時に自動的にサーバーを再起動してくれ、手作業による再起動が不要なため、nodemonを使っています。

    サーバーが起動したら、ブラウザでhttp://localhost:3000にアクセスすると、アプリケーションのインデックスページが開きます。これはこの記事の最初に説明した2個目のルートです。

    2個目のルートへアクセスすると、フォームを含むテンプレートを表示するGETハンドラを起動します。フォームをルートに送信すると、POSTハンドラが呼び出され、スクリプトがAPIにアクセスします。APIからレスポンスが返ると、フォームの同じテンプレートを使って結果を表示します。

    注意いただきたいのは、APIへの最初のリクエストはAPIの基本パスへのGETリクエストです。APIのデータフォーマットのデフォルトはJSONで、以下のような形式です。
    {items: [{"version": "1.0", "isLatest": false}, {"version": "1.0", "isLatest": true }]}
    メインコンテナに関する情報を入手するために、スクリプトを編集し、"/folders/self"を付加してapiURL変数を変更します。URLを以下のような感じに変更します。
    https://foo-bar.documents.us.oraclecloud.com/documents/api/folders/self
    上記URLへのGETリクエストを実行すると、APIはメインコンテナの情報をレスポンスとして返します。メインコンテナの子の情報を取得するには、エンドポイントURLの"/self"を"/items"に置き換えます。変更した結果、URLは以下のようになります。
    https://foo-bar.documents.us.oraclecloud.com/documents/api/folders/items
    上記URLへのGETリクエストを実行すると、APIはメインコンテナの子、つまりファイルやフォルダの情報をレスポンスとして返します。今回の場合、子は事前にメインコンテナにアップロードした2個のファイルです。

    [注意]
    "/folders/items"パスを使ってメインコンテナの子にアクセスします。メインコンテナに含まれるすべてのフォルダとファイルはおのおののIDを使ってアクセスします。

    続いて、ファイルの一つの情報を取得しましょう。このために、ファイルのIDが必要です。このファイルのIDは先ほどメインコンテナの子の問い合わせの際に入手しました。この操作で利用するエンドポイントURLは以下のようになります。
    https://https://foo-bar.documents.us.oraclecloud.com/documents/api/files/<file id>
    上記URLに対するGETリクエストを実行すると、APIはファイルに関する情報(作成日、ファイル名、IDなど)を返します。ファイルの中身を取得したい場合には、URLに"/data"を付加します。URLは以下のようになります。
    https://foo-bar.documents.us.oraclecloud.com/documents/api/files/<file id>/data
    [注意]
    ファイルの内容を問い合わせる際、APIの応答はJSON形式ではなく、ファイルの中身のみを含むプレーンテキスト形式です。

    上記のURLに対しGETリクエストを発行すると、APIはファイルの内容を返します。以下はその例です。
    "Hello Docs. This is file1's content"
    開発、テストフェーズにて、このWebアプリケーションを使ってAPIが返す情報を常にダブルチェックすることができます。

    ここまでで、APIを使って情報を取得しましたが、続いての例ではファイルを削除します。

    アイテムの削除はアイテムの情報を入手するのと同じぐらいシンプルで、単にAPIへのリクエストメソッドをDELETEに変更すればよいのです。URLはアイテムの情報を入手した際に使ったものと同じです(先ほど追加した"/data"のことは忘れています)。RESTクライアントを使って、この形式でDELETEリクエストを送信することができます。
    client.delete(requestPath, function(data, response){
    // do something with the response
    });
    これらの修正をスクリプトに対して実施し、リクエストをAPIに送信すると、操作結果を含むレスポンスが返ってきます。以下はその例です。
    { "errorCode" : "0" … }
    これはファイルの削除が成功したことを示しています。

    最後の例として、既存のリソースの名前を変更します。今回は、メインコンテナに残る別のファイルを対象にします。

    ファイル名を変更するには、PUTリクエストをファイルのパスに対し発行しますが、ファイルの新規名称を含む追加のパラメータを指定する必要があります。URLのパターンはファイル情報を入手したときと同じです。以下はコード例です。
    var args = {  parameters:{"name" : "changed-name.txt"} };
    client.put(requestPath, args, function(data, response){
    // do something with the response
    });
    PUTリクエストをこのファイルのURLパスに送信すると、APIはファイルの情報を返します。その情報には新しいファイル名が含まれています。

    先ほど実施したように、Webアプリケーションを使ってファイル名が正しく変更されていることを確認できます。

    REST APIの機能に関する詳細情報は、REST APIリファレンスをご覧ください。
    Developing for Oracle Documents Cloud Service
    Oracle Documents Cloud Service REST API Reference
    http://docs.oracle.com/cloud/latest/documentcs_welcome/WCCCD/GUID-205EBBB4-F8D5-4FD0-B82F-210960F5C6F7.htm#WCCCD3724

    [JavaScript, Database] Nashorn and Stored Procedures

    原文はこちら。
    https://blogs.oracle.com/java/entry/nashorn_and_stored_procedures

    JavaScriptは最も人気のある言語の一つで、JSONドキュメントを処理するための自然な選択です。数多くのJSONドキュメントを処理する場合、直接処理するか、それとも、データを中間層のエンジンへ運ぶか、どちらにされますか?

    次回のVTS(Virtual Technology Summit)では、Kuassi MensahがStored Procedureを使い、データ転送を避けつつデータベース内での処理が可能なことを説明します。中間層とデータベース間の可搬性のために、JavaScript Stored Procedureには標準的なデータベースアクセスのためのAPIが必要です。Java 8で導入されたNashorn JavaScriptエンジンを使うと、JavaScriptでJDBCの呼び出しが可能です。クラウド展開のために、Stored Procedureをクラウドデータサービスにすることで、JavaScript Stored ProcedureをRESTful Webサービスを通じて呼び出すことができます。

    VTSはHands-onセッションやプレゼンターが技術的な質問に答える、一連のインタラクティブなオンラインイベントです。
    Virtual Technology Summit
    http://www.oracle.com/technetwork/community/developer-day/index.html
    このイベントはOracle Technology Network(OTN)がスポンサーの無料イベントですが、登録が必要です。お近くのイベントにご参加ください。
    • Americas - 9月16日 9:30-12:30 (PDT) [日本時間9月17日 1:30-4:40]
      登録はこちら
    • EMEA - 9月23日 9:30-12:30 (BST) [日本時間 9月23日 17:30-20:30]
      登録はこちら
    • APAC - 9月30日15:00-18:30 (AU/SYD) [日本時間 9月30日14:00-17:30]
      登録はこちら

    [Java. JavaScript] Nashornの機能強化に伴うドキュメントへの追加・修正

    JDK 8u60がリリースされましたが、そのリリースノートの中で、Nashornの機能強化に伴うドキュメントの記載内容の変更が取り上げられています。
    8u60 Update Release Notes
    http://www.oracle.com/technetwork/java/javase/8u60-relnotes-2620227.html
    データ型のマッピングに対する機能強化で、ドキュメントへの追加が1件、修正が2件です。いずれも以下の箇所に関係します。
    Java Platform, Standard Edition Java Scripting Programmer's Guide
    3.10 Mapping Data Types
    http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/javascript.html#A1147390

    Oracle Java Platform, Standard Edition Javaスクリプト・プログラマーズ・ガイド
    3.10 データ型のマッピング
    http://docs.oracle.com/javase/jp/8/docs/technotes/guides/scripting/prog_guide/javascript.html#A1147390
    それでは見ていきましょう。

    • Addition:
      In the previous section, we mentioned that every JavaScript object when exposed to Java APIs implements the java.util.Map interface. This is true even for JavaScript arrays. However, this behavior is often not desired or expected when the Java code expects JSON-parsed objects. Java libraries that manipulate JSON-parsed objects usually expect arrays to expose the java.util.List interface instead. If you need to expose your JavaScript objects so that arrays are exposed as lists and not maps, you can use the Java.asJSONCompatible(obj) function, where obj is the root of your JSON object tree.

    • 追加
      前章(3.10 データ型のマッピング)で、「APIでマップを直接受け取ることができるように、すべてのJavaScriptオブジェクトがjava.util.Mapインターフェースを実装している」、と述べました。これはJavaScript配列に対しては今なお変わりません。
      しかし、JavaコードがJSONパース済みのオブジェクトを期待している場合、これは予期せぬ、期待されない挙動になることがあります。JSONパース済みのオブジェクトを操作するJavaライブラリは通常java.util.Listインターフェースで受け取ることのできる配列を期待しています。配列をマップではなくリストとして受け取るよう、JavaScriptオブジェクトを受け取る必要がある場合、Java.asJSONCompatible(obj) 関数を利用することができます。ここでobjはJSONオブジェクトツリーのルートです。

    • Correction:
      The caution mentioned at the end of Mapping Data Types section, is no longer applicable.
      Nashorn ensures that internal JavaScript strings are converted to java.lang.String when exposed externally.

    • 修正
      「データ型のマッピング」の最後に記載した注意点は、JDK 8u60以後考慮する必要はありません。
      内部文字列を取り出す場合、Nashornは内部JavaScript文字列をjava.lang.Stringに変換します。

    • Correction:
      The statement in the section Mapping Data Types, that mentions "For example, arrays must be explicitly converted,........." is not correct.
      Arrays are automatically converted to Java array types, such as java.util.List, java.util.Collection, java.util.Queue and java.util.Deque and so on.

    • 修正
      「データ型のマッピング」で述べている、「たとえば、配列は明示的に変換する必要があり…」の記述は間違っています。
      配列は自動的にJavaの配列型に変換されます。(例:java.util.Listjava.util.Collectionjava.util.Queuejava.util.Dequeなど)

    [Database, JavaScript] Node-oracledb goes 1.0: The Node.js add-on for Oracle Database

    原文はこちら。
    https://blogs.oracle.com/opal/entry/node_oracledb_goes_1_0

    Announcement

    本日Oracleはnode-oracledb 1.0をリリースしました。これは高性能のOracle Databaseアプリケーションを実現するためのNode.jsのAdd-onです。
    Node.js
    https://nodejs.org/
    Node-oracledbはnpmjs.comやGitHubからご利用いただけます。
    Oracle Database Driver by Oracle Corp. (npmjs.com)
    https://www.npmjs.com/package/oracledb
    Oracle Database driver for Node.js (GitHub)
    https://github.com/oracle/node-oracledb
    GitHubに今年頭に最初のコードをPushしてからほぼ毎月、新機能を加えながら、node-oracledbのアップデートをリリースしてきました。非常にエキサイティングなことに、すでに採用され、本番運用されている重要なアプリケーションで動作しているそうです。node-oracledbとしての8回目のリリースである今回のリリースは、これまでの中で最高のものであることをお約束します。

    node-oracledb 1.0 add-on for Node.jsでは、以下の標準機能や拡張機能をサポートしています。
    node-oracledbは、他のオープンソース言語用のOracle Database ドライバのように、Oracleがオープンソースチャネル(GitHub)を通じて機能強化、メンテナンス、サポートします。このAdd-onはApache 2.0ライセンスに基づきます。

    node-oracledbの入手方法

    Oracle Technology NetworkのNode.js Developer Centerにnode-oracledbを始めるにあたって必要なすべてのリンクや情報があります。
    Node.js Developer Center
    http://www.oracle.com/technetwork/database/database-technologies/node_js/index.html
    まずは、node-oracledbの手順に従ってスタートしてください。
    Installing node-oracledb
    https://github.com/oracle/node-oracledb/blob/master/INSTALL.md

    過去のリリースからの変更点

    大きな変更点は以下の通りです。
    • LOBに対するクエリ、インサート、PL/SQLでのLOBバインド変数のサポートを追加し、CLOB、BLOB型のStreamインターフェースを実装しました
      多くのレガシースキーマを取り扱う際に必要になっただけでなく、LOBのサポートもあって、アプリケーション開発者はOracle Database 12.1.0.2のJSONデータ型をVARCHAR2の最大長の制限を気にせずに利用できます。
      お客様からは、いつLOBがサポートされるのか、早期アクセスしたい、と毎日のようにコンタクトしてこられましたが、ようやく、サポートしました。引き続き負荷テストやベンチマークを実施して機能強化に努めていきます。
      LOBをnode-oracledbで利用する方法は、以下のドキュメントやサンプルをご覧ください。
      Working with CLOB and BLOB Data
      https://github.com/oracle/node-oracledb/blob/master/doc/api.md#lobhandling
      node-oracledbのサンプル
      https://github.com/oracle/node-oracledb/tree/master/examples
      Oracle DatabaseでのJSONサポートに関する一般的な情報は、以下のドキュメントもしくはJSONチームのブログエントリをご覧ください。
      JSON in Oracle Database
      http://docs.oracle.com/database/121/ADXDB/json.htm#CACGCBEG
      http://docs.oracle.com/cd/E57425_01/121/ADXDB/json.htm#CACGCBEG
      JSON in the Oracle database
      https://blogs.oracle.com/jsondb/
    • Oracledb.fetchAsStringexecute()の新たなfetchInfoプロパティを追加し、数字(number)、日付(date)、ROWIDを文字列としてフェッチできるようになりました。
      日付(date)と数字(number)はアプリケーションレベルで、日付と数字、ROWIDは文レベルで利用可能です。これらの機能を使うと、JavaScriptの表現や変換における制限を克服することができます。
    • DATE型としてのDATE、TIMESTAMP、ローカルタイムゾーン付きTIMESTAMPをDML RETURNING(RETURNING INTO)型にバインドできるようになりました。
      これらのデータ型を文字列としてバインドできます。
    • 内部Oracleクライアント文字セットが常にAL32UTF8に設定されるようになりました。
      これでもう外部でNLS_LANGを設定する必要はありません。ユーザーから報告された、マルチバイトデータに関連するバグは内部バッファの割り当てを正したことにより修正されました。NLSエクスペリエンスの一貫性が向上しました。
    • テストスィートの資格証明やサンプルデータベースの資格証明を環境変数から設定できるようになりました。
      自動的にプロビジョニングされた環境でのテストを支援するちょっとした変更です。テストスィートっはすでに大規模な件数をカバーしています。将来のリリースで機能強化を続けていきます。
    • node-oracledbのバグ修正。これらは変更履歴に列挙しています。
      Change Log
      https://github.com/oracle/node-oracledb/blob/master/CHANGELOG.md

    次は?

    ダイナミックに変化する環境におけるオープンソースプロジェクトゆえ、我々のStatement of Directionは、簡単かつ柔軟な目標としていました。積極的にOracle Databaseの機能のサポートやプロジェクトに関係するユーザーから機能要求に取り組んでいます。我々の優先順位リストは、それぞれのポイントリリースで再評価します。
    そして今、version 1.0に到達しました。では次は?ここからスタートです。数多くの重要で興味深いタスクが目の前にあります。開発プロセスから、ドライバの機能、配布に至るまでのプロジェクトのレビューからスタートします。このレビューで、次のタスクを決定します。ユーザーからのヒアリングは優先順位付けのために重要なので、躊躇せずにGitHubへのコメントをお願いします。
    oracle/node-oracledb : Issues
    https://github.com/oracle/node-oracledb/issues
    io.jsとの再マージやNode.js Foundationの構成など、Node.jsには大きな変化が起こっています。マージされたNode.jsのコードベースが安定し、Node.js FoundationのLTS(長期間サポート)の計画が固まると、node-oracledbのスケジュールの詳細について、より秩序だってお話することができるようになるでしょう。Node.jsやパートナーの皆様と一緒に最高のエクスペリエンスを提供するように取り組んでいます(テクニカルノートで、互換性レイヤNANのV2リリースは直近の数日間で行われたため、node-oracledb 1.0への取り込みには間に合いませんでした。そのため、最新、最先端のio.jsのサポートはnode-oracledbの将来バージョンにて実施する予定です)。
    成長しているnode-oracledbミュニティ、特にコードや提案、議論でnode-oracledbに貢献してくださった方々への感謝をもって、この発表の結びとします。

    [Database, JavaScript] node-oracledb 0.7.0 now supports Result Sets and REF CURSORS

    原文はこちら。
    https://blogs.oracle.com/opal/entry/node_oracledb_0_7_0

    Node.js driver for Oracle Databaseの新しいリリースがnpmjs.comやGitHubからご利用いただけるようになりました。
    node-oracledb (npm)
    https://www.npmjs.com/package/oracledb
    node-oracledb (GitHub)
    https://github.com/oracle/node-oracledb
    node-oracledb 0.7はNode.js 0.10、Node.js 0.12、io.jsからOracle Databaseに接続できます。数多くのプラットフォームで動作しますnode-oracledbに関する詳細は、GitHubページをご覧ください。
    0.7における変更点は以下の通りです。
    • 大きなデータセットの取得で結果セットが使えるようになりました。問い合わせ結果の行をResultsetクラスを使ってバッチで取得することができます。
      ResultSet class
      https://github.com/oracle/node-oracledb/blob/master/doc/api.md#resultsetclass
      これを使うことにより、大量の問い合わせ結果を一気に大量のメモリを使わず取得することができます。新たなgetRow()やgetRows()メソッドを繰り返し呼び出して問い合わせ結果をスクロールすることができます。
      getRow()
      https://github.com/oracle/node-oracledb/blob/master/doc/api.md#getrow
      getRows()
      https://github.com/oracle/node-oracledb/blob/master/doc/api.md#getrows
      一気にすべての行を返すというオリジナルのnode-oracledbの挙動は、デフォルトとして残っています。結果セットを返すには、新たなexecute()オプションである{ resultSet: true} を使う必要があります。以下はその例です。
    • //  (See the full code in examples/resultset2.js)

      . . .

      var numRows = 10; // number of rows to return from each call to getRows()

      connection.execute(
      "SELECT employee_id, last_name FROM employees ORDER BY employee_id",
      [], // no bind variables
      { resultSet: true }, // return a result set. Default is false
      function(err, result)
      {
      if (err) { . . . }
      fetchRowsFromRS(connection, result.resultSet, numRows);
      });
      });

      . . .

      function fetchRowsFromRS(connection, resultSet, numRows)
      {
      resultSet.getRows( // get numRows rows
      numRows,
      function (err, rows)
      {
      if (err) {
      . . . // close the result set and release the connection
      } else if (rows.length == 0) { // no rows, or no more rows
      . . . // close the result set and release the connection
      } else if (rows.length > 0) {
      console.log(rows);
      fetchRowsFromRS(connection, resultSet, numRows); // get next set of rows
      }
      });
      }
      もうデータがない、もしくはデータを使わなくなった場合には、新しい結果セットを閉じるclose()メソッドを使って結果セットを閉じることが重要です。
      close()
      https://github.com/oracle/node-oracledb/blob/master/doc/api.md#close
      Result Setsの詳細情報はマニュアルをご覧ください。
      Result Set Handling
      https://github.com/oracle/node-oracledb/blob/master/doc/api.md#resultsethandling
    • PL/SQLからの問い合わせ結果でREF CURSORが使えるようになりました。バインド変数を使ってREF CURSORの結果を返すPL/SQLコードは、新たなnode-oracledbの型であるOracledb.CURSORにバインドでき、新たなResultSetクラスを使って結果を取得することができます。
      //  (See the full code in examples/refcursor.js)

      var oracledb = require('oracledb');

      . . .

      var numRows = 10; // number of rows to return from each call to getRows()

      var bindvars = {
      sal: 6000,
      cursor: { type: oracledb.CURSOR, dir: oracledb.BIND_OUT }
      }

      connection.execute(
      "BEGIN get_emp_rs(:sal, :cursor); END;", // The PL/SQL has an OUT bind of type SYS_REFCURSOR
      bindvars,
      function(err, result)
      {
      if (err) { . . . }
      fetchRowsFromRS(connection, result.outBinds.cursor, numRows);
      });

      . . .

      function fetchRowsFromRS(connection, resultSet, numRows)
      {
      resultSet.getRows( // get numRows rows
      numRows,
      function (err, rows)
      {
      if (err) {
      . . . // close the result set and release the connection
      } else if (rows.length == 0) { // no rows, or no more rows
      . . . // close the result set and release the connection
      } else if (rows.length > 0) {
      console.log(rows);
      fetchRowsFromRS(connection, resultSet, numRows); // get next set of rows
      }
      });
      }
      REF CURSORの利用に関する詳細情報は以下のマニュアルをご覧ください。
      REF CURSOR Bind Parameters
      https://github.com/oracle/node-oracledb/blob/master/doc/api.md#refcursors
    • 行のプリフェッチができるようになりました。新しいResultSetクラスでは新たな属性 oracledb.prefetchRows と新たな execute() オプションである refetchRows を通じてサポートします。
      oracledb.prefetchRows
      https://github.com/oracle/node-oracledb/blob/master/doc/api.md#propdbprefetchrows
      sexecute(): Options
      https://github.com/oracle/node-oracledb/blob/master/doc/api.md#executeoptions
      アプリケーションがOracle DatabaseからのResultSetの問い合わせ結果の行やREF CURSORの行を取得する都度、プリフェッチによって下位のOracle Databaseのライブラリに別の行を転送させることができます。これは、データベースやネットワークリソースのより有効な利用を促し、パフォーマンスやスケーラビリティに寄与します。プリフェッチサイズにかかわらず、アプリケーションへ返す行数は変化しません。基盤のOracleクライアントライブラリがバッファリングを司ります。
    • プリフェッチサイズのデフォルト値は100です。アプリケーションは各々のexecute()で所望のパフォーマンスを出すため、不要なメモリの割り当てや初期化を避けるために、プリフェッチサイズを調整すべきです。いくつかのTipsがマニュアルに記載されています。
      node-oracledb: Documentation for the Oracle Database Node.js Driver
      https://github.com/oracle/node-oracledb/blob/master/doc/api.md
      node-oracledb 0.7.0では、非ResultSetクエリは現在プリフェッチサイズを固定値2でプリフェッチしています。これらのクエリで必要なラウンドトリップの回数を削減しています。
    • テストスィートを追加しました。ディレクトリのREADMEをご覧いただいて、テスト実行方法を確認してください。
      Testing node-oracledb
      https://github.com/oracle/node-oracledb/blob/master/test/README.md
      テストスィートを実行すると、各テストには識別が容易になるよう、固有の番号があることに気付くことでしょう。番号は連番とは限りません。
      Linux、Windowsでほとんどのテストをしています。環境やバージョンの違いに由来するテスト結果の差異を確認した場合は、OCAに署名し、修正とその修正が必要な理由とともに、pullリクエストを送ってください。詳細は以下のリンクをご覧ください。
      Contributing to node-oracledb
      https://github.com/oracle/node-oracledb/blob/master/CONTRIBUTING.md
      (OCAに署名後)新たなテストを提示する場合、各テストに対し、テスト済み領域に適用するドキュメント対象範囲のユニークな番号を割り当てます。
    • RETURNING INTOを使うSQL文のエラー処理を修正しました。同じエラーメッセージをレポートするDML RETURNING文を伴うすべてのエラーの発生原因であるバグを修正しました。
    • SQLにRETURNING INTO句がある場合の日付のINSERTを修正しました。INSERTを使ってdateやtimestampをインサートし、SQL句の文字もしくは数値列にRETURNING INTOが含まれる場合、エラーが出ていましたが、これを修正しました。
    • Renumbered the values used by the Oracledb Constantsが用いる値を再割り当てしました。アプリケーションがOracledb.OBJECTやOracledb.BIND_INOUTといった定数を使う場合、変更に気付かないかもしれませんが、何らかの理由で数値を例えば2のようにハードコーディングしている場合、この新しい数字を使って書き換える必要があります。詳細は以下のページをご覧ください。
      lib/oracledb.js
      https://github.com/oracle/node-oracledb/blob/master/lib/oracledb.js
      もしくは、よりよい方法としては、コードを定数を使って書き換えてください。

    Đếm lượt xem bài viết bằng cookie

    Đếm lượt xem bài viết là một thủ thuật khá cần thiết cho blogspot. Thông thường việc đếm lượt xem bài viết được thực hiện bằng ngôn ngữ php tuy nhiên nó yêu cầu sử dụng host, do đó dẫn đến việc đứt gánh giữa đường khi host không còn hoạt động. Ở đây mình hướng dẫn bạn cách đếm lượt xem bài viết sử dụng cookie. Bạn có thể xem DEMO bên dưới.


    Thông thường bộ đếm lượt truy cập bài viết được đặt ở cuối bài viết, do đó bạn có thể tìm trong Template ở chế độ mở rộng mẫu tiện ích đến một trong những dòng code sau:

    <div class='post-footer'>

    <div class='post-footer-line post-footer-line-1'>

    <div class='post-footer-line post-footer-line-2'>

    <div class='post-footer-line post-footer-line-3'>

    Rồi đặt trước hoặc sau nó bằng đoạn code bên dưới:

    <b:if cond='data:blog.pageType == &quot;item&quot;'>
    <script type='text/javascript'>
    //<![CDATA[
    function setC(visitors, value){
    var expireDate=new Date (2099, 12, 31);
    document.cookie = visitors + "=" + escape(value) + ((expireDate == null) ? "" : ("; expires=" +
    expireDate.toGMTString())) }
    function readC(visitors){
    var search = visitors + "=";
    var i, j;
    if (document.cookie.length > 0) {
    i = document.cookie.indexOf(search);
    if (i != -1) {
    i += search.length;
    j = document.cookie.indexOf(";", i);
    if (j == -1) j = document.cookie.length;
    return unescape(document.cookie.substring(i,j));
    } } }
    var num;
    num=readC("visitors");
    if (!num) num=0;
    num++;
    setC("visitors", num);
    document.write("<div class='visitors'>");
    document.write("<b>Bạn đã xem bài này "+num+" lần.<\/b>");
    document.write("<\/div>");
    //]]>
    </script>
    </b:if>

    Nếu muốn tùy biến CSS cho dòng thông báo thì bạn đặt CSS như thế này (trước dòng ]]></b:skin> trong Template):

    .visitors{
    … đặt các thuộc tính CSS ở đây nha ..
    }

    Hy vọng đoạn script này sẽ giúp ích cho blogspot của bạn, tránh đến việc sử dụng host để dành cho cả một thủ thuật nhỏ như thế này quả thật là bất tiện và phung phí.

    Hướng dẫn tạo list game flash cho Blogspot


    [ND] - Bạn thấy mình thật vất vả khi đi post từng bài trên blog của mình để chia sẻ các game flash mà mình yêu thích. Hay khi post xong rồi bạn thấy hệ thống game của mình hơi lộn xộn và khó quản lí ? Tôi sẽ có giải pháp cho bạn và tôi nghĩ đó là giải pháp tối ưu.

    Bạn xem thử nhé : Live demo

    Khi bạn tạo xong nó sẽ thế này :


    Chúng ta bắt đầu tạo cho mình một list game nào. Trước tiên bạn xem code của nó :
    <div class='widget-content'>
    <style type="text/css">
    #link-ex {
    font-weight:bold; text-color:#f00; padding: 0; height:200px; overflow: auto;}
    #link-ex p {padding:3px 0;border-bottom:1px dotted #234;
    }
    </style>
    <p>»  <a onclick="ND('http://media2.gamevui.com/images/Flash/gamethethao/tay-lai-dia-hinh_Secure.swf','700','620')" href="#ND">
    <font color="#347202">Tay lái địa hình</font></a><font color="#347202"><br /></font></p>
    <p>»  <a onclick="ND('http://media8.gamevui.com/images/Flash/ChienThuat/Age-of-war.swf','700','620')" href="#ND">
    <font color="#347202">Cuộc chiến thế kỉ</font></a><font color="#347202"><br /></font></p>

    </div>
    </div>
    <font color="#347202">
    <script type="text/javascript" language="javascript">   
        function MPAction(sAction) {
            if (sAction=='stop') {
                Player.controls.stop();
            } else if (sAction=='pause') {
                Player.controls.pause();
            } else {
                Player.controls.play();
            }
    }
    </script>
    <!--Code share by Nguyen Duc-->
    <script language="javascript"></script>
    <script language="JaVASCriPT">function ND(src,width,height){
        if(width>screen.width-100 || height>screen.height-100){
            SCwidth=screen.width-100;
            SCheight=screen.height-100;
            scrollbar="scrollbars=yes";
        }else{
            SCwidth=width;
            SCheight=height;
            scrollbar="scrollbars=no";
        }
        img_origin=window.open("","","width="+SCwidth+",height="+SCheight+",status=no,toolbar=no,"+scrollbar+",resizable=no");
        img_origin.document.write(""
    +"<HTML>"
    +"<HEAD>"
    +"<meta http-equiv='Content-Language' content='en-us'>"
    +"<TITLE>(Code By Nguyen Duc)</TITLE>"
    +"<META HTTP-EQUIV='Content-Type' CONTENT='text/html; charset=windows-1252'>"

    +"</HEAD>"
    +"<BODY BGCOLOR=#347202 topmargin=5>"

    +"<p align=center>"
    +"<table align=center border=0 cellpadding=6 cellspacing=1 class=tborder width=100%>"
    +"    <thead>"
    +"        <tr>"
    +"            <td class=tcat colspan=0>"
    +"            <span class=smallfont><center><strong>Chơi Game Online Miễn Phí</strong></center></span></td>"
    +"        </tr>"
    +"    </thead>"
    +"    <tbody id=collapseobj_module_4_5342>"
    +"    <tr>"
    +"    <td align=center class=alt1 valign=top height=350 background=bg.gif>"
    +"<p align=center><B>Chúc bạn chơi game vui vẻ</b></p>"
    +"<object classid=clsid:D27CDB6E-AE6D-11CF-96B8-444553540000 codebase=http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0 border=0 width=100% height=420 background=load_flash.gif>"
    +"<param name=movie value='"+src+"'>"
    +"<param name=quality value=High>"
    +"<embed src='"+src+"' pluginspage=http://www.macromedia.com/go/getflashplayer type=application/x-shockwave-flash name=obj2 width=100% height=420 quality=High wmode=transparent></object>"

    +"<br>"
    +"<a href='"+src+"' title='Nhấn chuột phải rồi chọn Save Target as để tải game!'><font style='font-family: Tahoma,Verdanda;font-size: 11px;'><b> <b>Nhấn vào đây để phóng to</b></font></a>"
    +"</td>"
    +"    </tr>"
    +"</tbody>"
    +"</table>"
    +"</p>"
    +"</BODY>"
    +"</HTML>"
    );
    }</script></font>
    <!--Code share by Nguyen Duc-->
    Bạn chỉ cần tạo một widget HTML/Javascript rồi thêm code đó vào là xong thôi.

    Hướng dẫn thêm game vào List:

    Ở code trên bạn chú ý phần code màu đỏ. Đó chính phần code game thêm vào. Mỗi game được thêm vào dưới dạng:
    <p>»  <a onclick="ND('http://media8.gamevui.com/images/Flash/ChienThuat/Age-of-war.swf','700','620')" href="#ND">
    <font color="#347202">Cuộc chiến thế kỉ</font></a><font color="#347202"><br /></font></p>
    Mô tả:
    Phần code màu hồng chính là link game flash mà bạn muốn thêm. Phần màu xanh là tên game. Phần màu tím bạn có thể thay đổi, nó đơn giản chỉ là khi mình nhấn vô game thì nó hiện như hình dưới ở thanh địa chỉ:


    Cứ mỗi game bạn đã có tên và thêm link vào thì bạn đặt ngay dưới phần code màu đỏ ở trên.

    Hướng dẫn lấy link game :

    - Hiện tại trên mạng có nhiều trang chơi game flash trực tuyến như Game Vui, Vương Quốc Game, Trò Chơi Việt, .....bạn vào một trang. Chọn lấy 1 game mình thích, bạn có thể thấy mỗi trang đều cho phép chèn game đó vào blog/web bằng cách copy lấy đoạn code của họ. Tuy nhiên, trường hợp này bạn chỉ lấy đường link game flash mà thôi. Nó tương tự như phần tôi bôi đen dưới đây :


    Nếu trang mà bạn muốn lấy game không cung cấp link flash bạn có thể dùng View Source thần chưởng vậy.

    - Giải pháp thứ 2 chúng ta có thể áp dụng đó là tải game về rồi up lên các host cho phép định  dạng swf lấy D-Link như : Photobucket, SwfCabin, SwfUpload,... rồi bạn lấy link game của mình và làm tương tự.

    Chú ý : Các bạn có thể áp dụng thụ thuật này để tạo danh sách video, nhạc, hay cái gì đó tương tự,.. tùy theo ý tưởng của bạn.

    Chúc các bạn vui vẻ !
    Bài này chỉ dành cho Newbie, mong các cao thủ đừng chê cười.

    Thủ thuật yêu cầu: Script liệt kê và gọi script

    Trong quá trình thiết kế weblog trên nền tảng Blogspot, hẳn bạn đã, đang và sẽ vọc rất nhiều script, dẫn đến thực tế là gắn nhiều script vào Template sẽ gây ảnh hưởng đến tốc độ load trang. Có một yêu cầu của bạn đọc về việc làm sao có script gọi được script, tức là gom các file script vào một chỗ rồi đến lúc nào cần script đó hoạt động thì mới gọi nó ra, chứ không cho nó load hết toàn bộ trong trang. Mình viết thủ thuật này theo yêu cầu của bạn MrWinni.

    Mình có thể mô tả thủ thuật này như sau: Trước hết mình tạo một tiện ích để chứa các file script và mình đặt tiện ích này lên trên tiện ích Header để dễ bề quản lý, sau đó mình dùng script liệt kê tất cả các file js cần dùng trong Template rồi đặt vào tiện ích này; mỗi khi cần bất kỳ một file js nào hoạt động thì chỉ cần dùng lệnh gọi script đó ra là được, như vậy sẽ không load tất cả các file js ra cùng một lúc. Nói như thế nghĩa là giả sử mình sử dụng đến 1000 file js trong Template song vẫn không hề ảnh hưởng đến tốc độ load trang của Template.

    Đến đây, mình tin rằng bạn sẽ cần đến thủ thuật này hơn bao giờ hết. Vậy thì hãy thực hiện như sau:

    Bước 1. Đăng nhập Blogger, vào Design >> Edit HTML, chọn Expand Widget Templates. Tìm sau thẻ <body> rồi đến thẻ <div id='header'> hoặc thẻ <div id='topnavbar'> (nếu Template của bạn có thanh menu đỉnh) và đặt trước thẻ đó bằng đoạn code bên dưới:
    <b:section class='scripcontainer' id='scriptcontainer'>
    <b:widget id='HTML100' locked='false' title='' type='HTML'>
    <b:includable id='main'>
    <!-- only display title if it's non-empty -->
    <b:if cond='data:title != &quot;&quot;'>
    <h2 class='title'><data:title/></h2>
    </b:if>
    <div class='widget-content'>
    <data:content/>
    </div>
    </b:includable>
    </b:widget>
    </b:section>
    Lưu Template.

    Bước 2. Vào Page Elements, kéo đến đầu Layout, sát trên phần Header, chọn Edit để chỉnh sửa tiện ích HTML/Javascript rồi đặt đoạn code như bên dưới vào đó:
    <script type="text/javascript">
    // ScriptListing&Reading Script by www.thuthuatblogger.info
    function readScript(index) {

    URLBase="http://tenban.googlecode.com/files/";
    scriptLIST=new Array(

    0,"",
    1,"code1.txt",
    2,"code2.txt",
    3,"code3.txt",
    4,"code4.txt",
    5,"code5.txt",
    6,"code6.txt",
    7,"code7.txt",
    8,"code8.txt",
    9,"code9.txt",
    10,"code10.txt",

    1000,""
    );

    regNum = index * 2 +1;
    document.write('<script src="' + URLBase + scriptLIST[regNum] + '"><\/script>');
    }
    </script>
    Trong trường hợp này, bạn upload các file js có đuôi .js hoặc .txt vào cùng một nguồn lưu trữ file (ví dụ googlecode hoặc host riêng của bạn), đặt URL ngồn (URLBase) cho script. Cứ mỗi lần dùng thêm file js thì bạn chỉ cần thêm số thứ tự theo định dạng như trên.

    Mỗi khi bạn muốn một script nào đó hoạt động tại vị trí theo ý bạn thì chỉ cần sử dụng lệnh gọi script như sau:

    <script>readScript(1);</script>

    Hoặc <script>readScript(2);</script>

    Hoặc <script>readScript(3);</script>

    Cứ như thế chỉ cần thay số thứ tự cho file js cần gọi ra là được.

    Nếu bạn upload các file js (lưu tên lộn xộn theo đuôi .js và .txt) lên các host khác nhau thì ở Bước 2, bạn sử dụng code như sau:
    <script type="text/javascript">
    // ScriptListing&Reading Script by www.thuthuatblogger.info
    function readScript(index) {
    scriptLIST=new Array(
    // Đây là danh sách các URL dẫn đến nguồn script
    0,"",
    1,"http://www.tenmien1.com/files/code1.js",
    2,"http://www.tenmien2.com/files/code2.txt",
    3,"http://www.tenmien3.com/files/code3.js",
    4,"http://www.tenmien4.com/files/code4.txt",
    5,"http://www.tenmien5.com/files/code5.js",
    6,"http://www.tenmien6.com/files/code6.txt",
    7,"http://www.tenmien7.com/files/code7.txt",
    8,"http://www.tenmien8.com/files/code8.js",
    9,"http://www.tenmien9.com/files/code9.txt",
    10,"http://www.tenmien10.com/files/code10.txt",

    1000,""
    );
    regNum = index * 2 +1;
    document.write('<script src="' + scriptLIST[regNum] + '"><\/script>');
    }
    </script>
    Tuy code này đơn giản song vẫn hy vọng rằng hiệu quả nó đem lại là vô cùng lớn đối với các bạn.

    Thủ thuật yêu cầu: Ẩn hiện tiện ích trên sidebar

    Thủ thuật này được viết theo yêu cầu của bạn Blue79blog, với ý tưởng tạo hiệu ứng ẩn hiện tiện ích trên phần sidebar của blogspot. Thủ thuật này lấy cảm hứng từ style ở trang cokhi-hui.net (xin lưu ý, ở đây chỉ lấy cảm hứng theo yêu cầu của bạn đọc chứ script không liên quan đến trang cokhi-hui.net).

    Xem Demo.

    Bây giờ chúng ta cùng bắt đầu thực hành nhé.

    Bước 1. Sử dụng javascript bên dưới để tạo hiệu ứng, đặt code trước thẻ </head>.
    <script type="text/javascript">
    //<![CDATA[
    // Hide and Show Toggle Effect Script. Please keep www.thuthuatblogger.info source for your using in any ways
    function toggle( targetId )
    {
    var state = 0;
    var blockname = "block" + targetId;
    var blockimage = "blockcollapse" + targetId;
    if ( document.getElementById ) {
    target = document.getElementById( blockname );
    if ( target.style.display == "none" ) {
    target.style.display = "";
    state = 1;
    }
    else {
    target.style.display = "none";
    state = 0;
    }
    document.getElementById( blockimage ).src = state ? "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4b4PC2GW7FZJWwwbFbNhISos9d5mKKEn3TXHlUM1gSdXkcaha-ZUGjoqGItmq0jWfESjU4KeuafiswPHGnH8NWoveBiTnkqw-mVNcN8skwdSF8JJTFj6bffu6lyViI4by6e_WdjBDURk_/s1600/minus.gif" : "https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR6zHO4Ajv7xxzbxhUjA2GxHVnJeBTzo8iGcfo54gre8svEDGEt6ED2h7OkEba2IW23PhJIb6dkiXPnFdrWUBXOfPiB4TOtw5HFO5_c0GoGgD0E-GTRaeSZqVg1zgOyS30LhCDF1yTsjMX/s1600/plus.gif";
    }
    }
    //]]>
    </script>

    Bước 2. Thiết lập cấu trúc HTML theo các trường hợp sau đây (áp dụng chung cho website và blogspot):

    Trường hợp 1: Nội dung được ẩn, nhấn nút show/hide để hiện nội dung, nút show/hide nằm nằm bên trái tiêu đề.
    <a href="javascript: void(0);" onclick="toggle(&quot;1&quot;); return false">
    <img border="0" id="blockcollapse1" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR6zHO4Ajv7xxzbxhUjA2GxHVnJeBTzo8iGcfo54gre8svEDGEt6ED2h7OkEba2IW23PhJIb6dkiXPnFdrWUBXOfPiB4TOtw5HFO5_c0GoGgD0E-GTRaeSZqVg1zgOyS30LhCDF1yTsjMX/s1600/plus.gif" style="margin-right: 5px;" />Đây là một tiêu đề</a>
    <div id="block1" style="display: none;">
    Đây là một đoạn văn bản hoặc một hình ảnh …
    </div>


    Đây là một tiêu đề


    Trường hợp 2: Nội dung được hiện, nhấn nút show/hide để ẩn nội dung, nút show/hide nằm bên trái tiêu đề
    <a href="javascript: void(0);" onclick="toggle(&quot;2&quot;); return false">
    <img border="0" id="blockcollapse2" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4b4PC2GW7FZJWwwbFbNhISos9d5mKKEn3TXHlUM1gSdXkcaha-ZUGjoqGItmq0jWfESjU4KeuafiswPHGnH8NWoveBiTnkqw-mVNcN8skwdSF8JJTFj6bffu6lyViI4by6e_WdjBDURk_/s1600/minus.gif" style="margin-right: 5px;" />Đây là một tiêu đề</a>
    <div id="block2">
    Đây là một đoạn văn bản hoặc một hình ảnh…
    </div>


    Đây là một tiêu đề

    Thủ thuật Blogger là nơi bạn vừa học tập vừa thực hành về thiết kế website/webblog. Chúng tôi hy vọng sẽ trở thành một ngôi trường nhỏ để bạn góm ghém hành trang bước vào những ngôi trường lớn hơn.

    Trường hợp 3. Nội dung được ẩn, nhấn nút show/hide để hiện nội dung, nút show/hide nằm bên phải tiêu đề.
    <a href="javascript: void(0);" onclick="toggle(&quot;3&quot;); return false">
    Đây là một tiêu đề<img border="0" id="blockcollapse3" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgR6zHO4Ajv7xxzbxhUjA2GxHVnJeBTzo8iGcfo54gre8svEDGEt6ED2h7OkEba2IW23PhJIb6dkiXPnFdrWUBXOfPiB4TOtw5HFO5_c0GoGgD0E-GTRaeSZqVg1zgOyS30LhCDF1yTsjMX/s1600/plus.gif" style="margin-left: 5px;" />
    </a>
    <div id="block3" style="display: none;">
    Đây là một đoạn văn bản hoặc một hình ảnh…
    </div>


    Đây là một tiêu đề


    Trường hợp 4. Nội dung được hiện, nhấn nút show/hide để ẩn nội dung, nút show/hide nằm bên phải tiêu đề.
    <a href="javascript: void(0);" onclick="toggle(&quot;4&quot;); return false">
    Đây là một tiêu đề<img border="0" id="blockcollapse4" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj4b4PC2GW7FZJWwwbFbNhISos9d5mKKEn3TXHlUM1gSdXkcaha-ZUGjoqGItmq0jWfESjU4KeuafiswPHGnH8NWoveBiTnkqw-mVNcN8skwdSF8JJTFj6bffu6lyViI4by6e_WdjBDURk_/s1600/minus.gif" style="margin-left: 5px;" />
    </a>
    <div id="block4">
    Đây là một đoạn văn bản hoặc một hình ảnh…
    </div>


    Đây là một tiêu đề

    Thủ thuật Blogger là nơi bạn vừa học tập vừa thực hành về thiết kế website/webblog. Chúng tôi hy vọng sẽ trở thành một ngôi trường nhỏ để bạn góm ghém hành trang bước vào những ngôi trường lớn hơn.

    Đến đây là phần quan trọng đối với blogspot, áp dụng để tạo hiệu ứng ẩn hiện đối với tiện ích trên blogspot. Đăng nhập Blogger, vào Design >> Edit HTML, chọn Expand Widget Templates (nhớ thực hiện Bước 1 xong). Xác định ID của một tiện ích và tìm đến đoạn code của nó, ví dụ đối với tiện ích có ID là HTML1:
    <b:widget id='HTML1' locked='false' title='Đây là tiêu đề tiện ích 1' type='HTML'>
    <b:includable id='main'>
    <!-- only display title if it's non-empty -->
    <b:if cond='data:title != &quot;&quot;'>
    <h2 class='title'><data:title/></h2>
    </b:if>
    <div class='widget-content'>
    <data:content/>
    </div>
    <b:include name='quickedit'/>
    </b:includable>
    </b:widget>
    Chỉnh code của tiện ích đó lại như bên dưới. Ở đây mình áp dụng cho trường hợp 1, các trường hợp còn lại bạn có thể tự thực hiện.
    <b:widget id='HTML1' locked='false' title='Đây là tiêu đề tiện ích 1' type='HTML'>
    <b:includable id='main'>
    <!-- only display title if it's non-empty -->
    <a href='javascript: void(0);' onclick='toggle(&quot;1&quot;); return false'>
    <b:if cond='data:title != &quot;&quot;'>
    <h2 class='title'><img border='0' id='blockcollapse1' src='https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEit1mpjQgjQTaiEJlsPLEfghzDHz30jEk3FpZ76W4wEobJ7m-7IdHpkodSB_1xHKycZj18RDVyn2QvE7wnJE2U87xfESYV72ImvP1qa4nTdDGPXSlZequHVDxpfyZ6VO7aDA1BgZD3QGygg/s1600/mas.gif' style='margin-right: 5px;'/><data:title/></h2>
    </b:if></a><div id='block1' style='display: none;'>
    <div class='widget-content'>
    <data:content/>
    </div> </div>
    </b:includable>
    </b:widget>
    Lưu Template là xong. Bạn có thể sử dụng cấu trúc tương tự như trên để vận dụng cho nhiều tiện ích khác nhau nhé.

    Tạo đoạn text hiển thị ngẫu nhiên và luân phiên

    Trên blogspot của bạn, đôi khi bạn thích hiển thị một số dòng text thông báo hoặc một vài câu danh ngôn mà bạn tâm đắc. Hiệu ứng tạo text hiển thị ngẫu nhiên hoặc luân phiên sẽ giúp cho trang web trở nên sinh động và bớt đơn điệu hơn. Qua bài viết này mình sẽ giới thiệu bạn cách tạo 2 kiểu text như thế.

    1. Hiển thị text ngẫu nhiên: Đặt đoạn code sau đây vào một tiện ích HTML/Javascript.

    <div style="width:500px;height:50px;background:#DDD;padding:5px 5px 5px 5px;margin:0px auto">
    <!-- RANDOM QUOTES -->
    <script type="text/javascript">
    quotes = new Array()
    quotes[0] = "Nội dung đoạn text 1"
    quotes[1] = "Nội dung đoạn text 2"
    quotes[2] = "Nội dung đoạn text 3"
    quotes[3] = "Nội dung đoạn text 4"
    quotes[4] = "Nội dung đoạn text 5"
    quotes[5] = "Nội dung đoạn text 6"

    randomquote = Math.random() * (quotes.length)
    randomquote = Math.floor(randomquote)
    document.write(quotes[randomquote])
    </script>
    <!-- RANDOM QUOTES -->
    </div>

    Lần lượt thay nội dung các đoạn text cần hiển thị ngẫu nhiên.


    2. Hiển thị text luân phiên: Đặt đoạn code sau đây vào một tiện ích HTML/Javascript.

    <!-- ROTATING QUOTES -->
    <script type="text/javascript">
    var index = 0;
    quotes = new Array();
    quotes[0] = "Nội dung đoạn Text 1";
    quotes[1] = "Nội dung đoạn Text 2";
    quotes[2] = "Nội dung đoạn Text 3";
    quotes[3] = "Nội dung đoạn Text 4";
    quotes[4] = "Nội dung đoạn Text 5";
    quotes[5] = "Nội dung đoạn Text 6";

    index = Math.random()*(quotes.length);
    index = Math.floor(index);

    function rotator() {
    if (index == quotes.length) {index = 0;}
    document.getElementById("rotation").innerHTML = quotes[index];
    index++;
    setTimeout("rotator();",5000);
    }
    </script>
    <!-- ROTATING QUOTES -->
    <div id="rotation" style="width:500px;height:50px;background:#DDD;padding:5px 5px 5px 5px;margin:0px auto"></div>
    <script type="text/javascript">rotator();</script>

    Lần lượt thay nội dung các đoạn text cần hiển thị luân phiên. Chú ý có thể thay đổi số 5000 tượng trưng cho 5 giây chỉ khoảng cách thời gian giữa các lần hiển thị text luân phiên.




    Ở 2 code trên, bạn có thể tùy biến thêm CSS để tạo bản sắc riêng khi áp dụng cho blogspot của bạn.

    Hiển thị thời gian ước tính để đọc bài viết

    Tính được thời gian ước tính để đọc một bài viết là một cách thú vị để cho người đọc phần nào hiểu sơ qua về độ dài của bài viết mà không cần phải đọc lướt qua. Người ta ước tính rằng con người chúng ta trung bình cứ mỗi một phút có thể đọc được 300 từ và cứ mỗi 2 giây là có thể xem một hình ảnh. Như vậy dựa vào căn cứ trung bình này, bằng một thuật toán tính đến số từ, các khoảng trắng và hình ảnh trong một bài viết, chúng ta có thể ước tính được thời gian cần để đọc toàn bộ một bài viết.

    Qua bài viết này, nhờ sử dụng javascript để tạo những thuật toán cơ bản, mình sẽ giúp bạn hiển thị được thời gian ước tính để đọc một bài viết dưới mỗi tiêu đề bài viết để người đọc bớt phần mệt nhọc đoán chừng độ dài bài viết của bạn.

    Để làm được như vậy, bạn hãy thực hiện theo các bước sau đây:

    Bước 1. Đăng nhập Blogger. Vào Design >> Edit HTML. Chọn Expand Widget Templates. Đặt đoạn code sau đây vào trước thẻ </head>.

    <script type='text/javascript'>
    //<![CDATA[
    // Estimate-time-to-read-blogspot-post Script by Huynh Nhat Ha
    var wordsperminute = 300;
    var imagesperminute = 30;

    function timeperpostreading(id) {
    var postcontent = document.getElementById(id);

    var img = postcontent.getElementsByTagName("img");
    var numimg = img.length;

    var strx = postcontent.innerHTML;
    if(strx.indexOf("<")!=-1) {
    var s = strx.split("<");
    for(var i=0;i<s.length;i++){
    if(s[i].indexOf(">")!=-1){
    s[i] = s[i].substring(s[i].indexOf(">")+1,s[i].length);
    }
    }
    strx = s.join("");
    }

    var blankfirst = /^ /;
    var blankfinal = / $/;
    var blanktotal = /[ ]+/g;
    strx = strx.replace(blanktotal," ");
    strx = strx.replace(blankfirst,"");
    strx = strx.replace(blankfinal,"");

    var words = strx.split(" ");
    var numwords = words.length;

    var minutes = parseInt((numwords/wordsperminute)+(numimg/imagesperminute));
    var seconds = parseInt((((numwords/wordsperminute)+(numimg/imagesperminute))-minutes)*60);
    minutes=("0" + minutes).slice (-1);
    seconds=("0" + seconds).slice (-2);

    var forreturn = "Thời gian ước tính để đọc bài viết này: "+minutes+":"+seconds;
    document.getElementById("timeperpost").innerHTML = forreturn;
    }
    //]]>
    </script>

    Bước 2. Tìm đến dòng <div class='post-header-line-1'/> và đặt trước nó bằng dòng code bên dưới.

    <p id='timeperpost'/>

    Tiếp tục tìm dòng <data:post.body/> (hoặc <p><data:post.body/></p>) rồi thay thế nó bằng đoạn code bên dưới.

    <div expr:id='data:post.id'>
    <p><data:post.body/></p>
    </div>
    <script type='text/javascript'>
    timeperpostreading(&quot;<data:post.id/>&quot;);
    </script>

    Lưu Template là OK. Hy vọng thủ thuật nhỏ này sẽ tạo thêm nét độc đáo cho blogspot của bạn.
    ài
    Copyright © 2013 TIẾNG NHẬT JP 日本語