2007/05/08

How to write an plugin for IE7Pro


1. General infomation

All plugin file located in <IE7Pro Installation Directory>/plugins/<plugin name>/plugin.js .

We only support one javascript file now( all functions must be in this file).It must be named as "plugin.js".

for example:

c:\program files\ie7pro\plugins\serverinfo\plugin.js

And you need the next header for plugin.js

// ==UserScript==

// @name testplugin

// @namespace http://www.artefxdesign.com/greasemonkey

// @description Adds Netflix search links to IMDb pages

// @statussize 80

// ==/UserScript==

@name must be an unique id compare to other plugins.

@statussize is the width of status bar display area for this plugin.


2. Current Support APIs:

(1) PRO_setValue(name, value)

Allows user script authors to persist simple values locally.

(2) PRO_getValue(name, default)

Retrieve a value set with setValue. If the value is not found, default is returned instead.

(3) PRO_log(msg)

Output the debug message. you need install debugview to see the msg.

http://www.microsoft.com/technet/sysint … gview.mspx

(4) PRO_openInTab(url, flags)

Open an new tab.

flags:0=Current Tab, 1= New Tab Foreground, 2= New Tab Background

(5) PRO_addStyle(css)

Adds a string of CSS to the document.

(6) var httpreq = PRO_xmlhttpRequest();

Same as XMLHTTPRequest but can make an xmlhttp request to other domains.

http://msdn2.microsoft.com/en-us/library/ms535874.aspx

(7) var plugin = PRO_plugin(@name);


Methods:

1) registerContextMenu(name, func)

registerContextMenu("separator"); // add an separator for menu

function prototype: menuCommand(cookie, url)

2) setStatusInfo(imgurl, text, tip, cookie)

3) popupWindow(url, width, height, cookie)

URL support local path:ie7pro://pluginpath/foo.png


Properties:

1) onpagechange

fire when url change. state:1=page loading, 2= page loaded

function prototype: handlePageChange(cookie, url, state)

2) ontabcreate

fire when Tab created.

function prototype: handleTabCreate(cookie)

2) onpopupclose

fire when the window which opened by popupWindow closed.

function prototype: handlePopupClose(url)

3. User scripts

User scripts support all above APIs except PRO_plugin.

User scripts are executed after the DOM is fully loaded, but before onload occurs.

They are executed in an environment very much like regular DHTML scripts are, and executed completely in the content document.

4. Example : Alexa rank and Google Pagerank Plugin


// ==UserScript==

// @name Alexa rank/google pagerank

// @namespace http://www.alexa.com

// @description Display web site Alexa Rank & Google Rank(Thanks SearchStatus@Firefox)

// @statussize 160

// ==/UserScript==


(function()

{

var plugin = PRO_plugin(@name);

plugin.onpagechange = handlePageChange;

plugin.registerContextMenu("Show Google results from this site", menuShowGoogleResult);

plugin.registerContextMenu("Show Google Related Site", menuShowGoogleRelated);

plugin.registerContextMenu("Show Alexa Overview", menuShowAlexaOverview);

plugin.registerContextMenu("Show Alexa Traffic Detail", menuShowAlexaTraffic);



var gCookie = "";

var gAlexaRank = "";

var gGoogleRank = "";



var reqObj = new Object();

reqObj.request = function(callback, cookie, url, userAgent, lastModify) {

var req;

req = PRO_xmlhttpRequest();

req.onreadystatechange = function() {

if (req.readyState == 4) {// completed

if (req.status < 400) {// only if "OK"

try {

callback(true, req, cookie);

} catch(err) {

}

} else {

// PRO_log("There was a problem loading data :\n" + req.status+ "/" + req.statusText);

callback(false, req, cookie);

}

setTimeout(function() {req.forceClean();req = null;}, 1000);

}

}

try {

req.open("GET", url);

req.setRequestHeader( "User-Agent", userAgent);

if(lastModify.length > 0)

req.setRequestHeader( "If-Modified-Since", lastModify);

req.send(null);



} catch(err){

}

return req;

}


// escape the url

function encodeURL(url)

{

return escape(url).replace(/\+/g, '%2B').replace(/\"/g, '%22').replace(/\'/g, '%27');

}



function menuShowGoogleResult(cookie,url) {

PRO_openInTab("http://google.com/search?&q=site:"+url,1);

}


function menuShowGoogleRelated(cookie,url) {

PRO_openInTab("http://www.google.com/search?q=related:"+url,1);

}


function menuShowAlexaOverview(cookie,url) {

var urlhost = url.split("/");

var qhost = urlhost[2];

PRO_openInTab("http://www.alexa.com/data/details/main?q=&url="+qhost,1);

}


function menuShowAlexaTraffic(cookie,url) {

var urlhost = url.split("/");

var qhost = urlhost[2];

PRO_openInTab("http://www.alexa.com/data/details/traffic_details?q=&url="+qhost,1);

}


function handlePageChange(cookie, url, state) {

if(state == 1) {// page loading

var re = /http:\/\/(.*)/i;

var urlhost = url.split("/");



var qhost = urlhost[2];

gCookie = cookie;

gAlexaRank = "";

gGoogleRank = "";

var encodeurl = encodeURL(qhost);

var queryurl = "http://xml.alexa.com/data?cli=10&dat=nsa&ver=quirk-searchstatus&uid=20060101000000&userip=126.12.3.4&amp;url=" + encodeurl;

reqObj.request(processAlexaData, cookie, queryurl, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; Alexa Toolbar)", "Thu, 26 Aug 2002 08:24:16 GMT");


var encodeurl2 = encodeURL(url);

var reqgr = "info:" + url;

var reqgre = "info:" + encodeurl2.replace( "_", "%5F" );

var gGoogleCHCalc = new googlechcalc();

var mGoogleCH = gGoogleCHCalc.googleCH( gGoogleCHCalc.strord( reqgr ) );

mGoogleCH = "6" + gGoogleCHCalc.googleNewCh( mGoogleCH );

queryurl = "http://toolbarqueries.google.com/search?client=navclient-auto&ch=" + mGoogleCH + "&ie=UTF-8&oe=UTF-8&features=Rank&amp;amp;q=" + reqgre;

PRO_log(queryurl);

reqObj.request(processGoogleData, cookie, queryurl, "User-Agent", "Mozilla/4.0 (compatible; GoogleToolbar 2.0.114-big; Windows XP 5.1)");


} else if(state == 2) {// page loaded

}

}


function processAlexaData(isOK, req, cookie) {

//PRO_log(req.responseText);

if(gCookie == cookie) {

if(isOK) {

var re = /TEXT=\"(\d+)\"\/\>/i;

var alexaRank = req.responseText.match(re);

if(alexaRank.length > 1)

gAlexaRank = alexaRank[1];

else

gAlexaRank = "0";

} else {

gAlexaRank = "0";

}

if(gGoogleRank.length > 0) {

processResult();

}

}

}


function processGoogleData(isOK, req, cookie) {

if(gCookie == cookie) {

if(isOK) {

var re = /Rank_.*?:.*?:(\d+)/i;

var googleRank = req.responseText.match(re);

if(googleRank.length > 1)

gGoogleRank = googleRank[1];

else

gGoogleRank = "0";

} else {

gGoogleRank = "0";

}

if(gAlexa.length > 0) {

processResult();

}

}

}


function processResult()

{

plugin.setStatusInfo("", "Alexa:"+FormatInteger(gAlexaRank)+" Google:"+gGoogleRank + "/10", "", gCookie);

}



function googlechcalc() {

return this;

}



googlechcalc.prototype =

{

googleNewCh: function( ch )

{

ch = ( ( ( ch / 7 ) << 2 ) ( ( this.myfmod( ch,13 ) ) & 7 ) );



prbuf = new Array();

prbuf[0] = ch;

for( i = 1; i < 20; i++ )

{

prbuf[i] = prbuf[i-1] - 9;

}

ch = this.googleCH( this.c32to8bit( prbuf ), 80 );



return ch;

},



googleCH: function( url )

{

var init = 0xE6359A60;



var length = url.length;



var a = 0x9E3779B9;

var b = 0x9E3779B9;

var c = 0xE6359A60;

var k = 0;

var len = length;

var mixo = new Array();



while( len >= 12 )

{

a += (url[k+0] +(url[k+1]<<8) +(url[k+2]<<16) +(url[k+3]<<24));

b += (url[k+4] +(url[k+5]<<8) +(url[k+6]<<16) +(url[k+7]<<24));

c += (url[k+8] +(url[k+9]<<8) +(url[k+10]<<16)+(url[k+11]<<24));

mixo = this.mix(a,b,c);

a = mixo[0]; b = mixo[1]; c = mixo[2];

k += 12;

len -= 12;

}



c += length;



switch( len )

{

case 11:

c += url[k+10]<<24;



case 10:

c+=url[k+9]<<16;



case 9 :

c+=url[k+8]<<8;



case 8 :

b+=(url[k+7]<<24);



case 7 :

b+=(url[k+6]<<16);



case 6 :

b+=(url[k+5]<<8);



case 5 :

b+=(url[k+4]);



case 4 :

a+=(url[k+3]<<24);



case 3 :

a+=(url[k+2]<<16);



case 2 :

a+=(url[k+1]<<8);



case 1 :

a+=(url[k+0]);

}



mixo = this.mix( a, b, c );



if( mixo[2] < 0 )

{

return ( 0x100000000 + mixo[2] );

}

else

{

return mixo[2];

}

},



hexdec: function( str )

{

return parseInt( str, 16 );

},



zeroFill: function( a, b )

{

var z = this.hexdec( 80000000 );



if( z & a )

{

a = a >> 1;

a &= ~z;

a = 0x40000000;

a = a >> ( b - 1 );

}

else

{

a = a >> b;

}



return (a);

},



mix: function( a, b, c )

{

a -= b; a -= c; a ^= ( this.zeroFill( c, 13 ) );

b -= c; b -= a; b ^= ( a << 8 );

c -= a; c -= b; c ^= ( this.zeroFill( b, 13 ) );

a -= b; a -= c; a ^= ( this.zeroFill( c, 12 ) );

b -= c; b -= a; b ^= ( a << 16);

c -= a; c -= b; c ^= ( this.zeroFill( b, 5 ) );

a -= b; a -= c; a ^= ( this.zeroFill( c, 3 ) );

b -= c; b -= a; b ^= ( a << 10);

c -= a; c -= b; c ^= ( this.zeroFill( b, 15 ) );



var ret = new Array( (a), (b), (c) );



return ret;

},



strord: function( string )

{

var result = new Array();



for( i = 0; i < string.length; i++ )

{

result[i] = string.charCodeAt( i);

}



return result;

},



c32to8bit: function( arr32 )

{

var arr8 = new Array();



for( i = 0; i < arr32.length; i++ )

{

for( bitOrder = i * 4; bitOrder <= i * 4 + 3; bitOrder++ )

{

arr8[bitOrder] = arr32[i] & 255;

arr32[i] = this.zeroFill( arr32[i], 8 );

}

}



return arr8;

},



myfmod: function( x, y )

{

var i = Math.floor( x / y );

return ( x - i * y );

}

};

function FormatInteger( integer )

{

var pattern = "###,###,###,###";

var result = '';



integerIndex = integer.length - 1;

patternIndex = pattern.length - 1;



while( ( integerIndex >= 0 ) && ( patternIndex >= 0 ) )

{

var digit = integer.charAt( integerIndex );

integerIndex--;



// Skip non-digits from the source integer (eradicate current formatting).

if( ( digit < '0' ) ( digit > '9') ) continue;



// Got a digit from the integer, now plug it into the pattern.

while( patternIndex >= 0 )

{

var patternChar = pattern.charAt( patternIndex );

patternIndex--;



// Substitute digits for '#' chars, treat other chars literally.

if( patternChar == '#' )

{

result = digit + result;

break;

}

else

{

result = patternChar + result;

}

}

}



return result;

}

}

)();




13 comments:

Anonymous said...

great tutorial, this is just the thing I was looking for. I want to create a plugin that allows you to find the cheapest Viagra Online and therefore save some money!

Generic Viagra Viagra

Dewaite Houwad said...

WOW Gold Tera Gold :Person programs service all above APIs except PRO_plugin.
Person programs are carried out after the DOM is absolutely packed, but before onload happens.
They are carried out in an atmosphere very much like common DHTML programs are, and carried out absolutely in the information report.

wowplay said...

This can be my own first time we go here. I ran across numerous entertaining stuff inside your website, specially their dialogue. Through the a lot of comments on your own content, I suppose That's not me on your own having every one of the leisure below! Keep up the great operate.
Buy RS Gold

Farrah Khan said...

Intimately, the post is actually the best on this laudable topic. I harmonize with your conclusions and will eagerly look forward to your future updates.
~^- organic supplements -^~

saim said...

Hey brilliant Blog, Thanks to a great effort in publishing your article
Great tips, I would like to join your blog anyway,




natural supplements

Farrah Khan said...

i have read your blog and find that your articles are amazing, i have added this into my bookmark. Thanks a lot.

find doctors list | doctor ratings

Fara Fae said...

Este es realmente mi primera vez aquí, el blog de gran apariencia. Descubrí tantas cosas interesantes dentro de tu blog en especial su discusión.


dietas online | dieta online

louisvuitton said...

Louis Vuitton Outlet In this economic crisis, Louis Vuitton Outlet is still a new store opened , Louis Vuitton Handbagswas talking to consumers, "it is big brand style," which is the brand in Qingdao, Louis Vuitton Outlet But so many consumers scratching their heads, even in Shanghai, the brand is huge, only one shop only. For the decision-making luxury goods new store openings, Louis Vuitton Outlet has a macro-interpretation, "China's luxury goods market in a very large domestic demand." Therefore, all the luxury brands must invest in the Chinese Louis Vuitton Bags market.According to industry sources,Louis Vuitton Outlet the cost of brand mall settled mainly by housing rents and sales of pumping into two parts, some of the newly opened, large shopping malls are not known, Louis Vuitton Outlet the rent is very cheap, and even some sales extracted part of the pumping only in accordance with percent. Therefore, some of the luxury goods store in the same city east of the closed shop,Louis Vuitton Outlet shop west of the phenomenon is not surprising.

Farrah Khan said...

I learned something today! Thanks! But I manage to include your blog among my reads every day because you have interesting,

natural sleep aid | energy supplements | fast energy

whatlivemom said...

Jav Japan Mediafire
western porn full movie
Porn Full Mediafire

Find Hospitals in your Area said...

This is my Good luck that I found your post which is according to my search and topic.
find a doctor in my area

Unknown said...

Hello, my friend! I mean this product is great, beautiful, and has written almost all the vital information. I would like to see more posts like this. chexsystem

nueva308 said...

I really enjoyed, I would like more information about this!


Read on: Buy complete link building service