FireBreath -- Summary--方法 屬性 Attributes 事件和js的交互等

【方法】

JSAPI 對javascript暴露了四種基本類型的接口(Methods, Properties, Attributes, and Events),每一種接口都必須在JSAPI對象的構造函數中註冊(Attributes和Events除外)。

Attributes可以在任何一個除了析構函數的函數中註冊(registerAttribute(const std::string& str, const FB:variant& value, bool readOnly = false));


Events在1.5.0之後的版本中註冊是在類聲明中FB_JSAPI_EVENT(不帶on的函數名全小寫, 參數個數,  (參數類型列表)); 在cpp文件裏的函數中fire_funcName(參數s)即可。


Methods:方法如果沒有明確返回一個值則返回undefined,就像js函數。



如果想從js傳一個【字典】類型的參數,那麼形參可以用std::map(或者任何其他的STL字典類型,比如hash_map, multimap等),但鍵應該是std::string類型,值可以是任何JSAPIAuto支持的類型。

這是唯一值傳遞的情況,如果你需要用引用傳遞一個對象,那麼形參應該接受爲一個FB::JSObjectPtr類型,並且使用Invoke, GetProperty, SetProperty來操作它。




如果想從js傳一個【數組】類型的參數,那麼形參可以用std::vector(或者任何其他STL列表類型,比如list, set等),容器中的元素類型可以是任何JSAPI支持的類型。



JSAPIAuto類型支持 繼承自FB::variant所支持的類型。 當JSAPIAuto把一個參數轉換成你的JSAPI方法或屬性期望的類型時,它是通過使用FB::variant::convert_cast<type>來完成的。



FireBreath支持的類型:

數學類型:signed/unsigned int/long/short/char, float, double, size_t

布爾類型:true false

string: FireBreath支持std::string和std::wstring,並且會自動的在兩者之間進行轉換,需要注意的是:std::string表達式一直都是UTF-8編碼



char* 和 wchar_t*:只有作爲返回類型(或者assign to a FB::variant)你能使用char* wchar_t*,但是這些會在內部被轉換爲std::string和std::wstring。


二進制數據:如果你需要傳遞二進制數據給頁面,我們建議你要麼轉換成一個string(hex, base64等),要麼包裝成javascipt Array(比如std::vector<unsigned char>)。 傳遞行業內的數據作爲js數組不會特別有效率,但是插件接口不允許二進制數據。 所有的strings都假設瀏覽器爲UTF-8編碼,所以簡單的返回一個char*可能會產生不可預期的結果。

 


容器類型:FB支持所有的STL容器,並且是100%的兼容。 聯合類型可以作爲參數傳遞給JSAPI函數並且js對象會自動的轉換,反之,非聯合類型可以從js對象中保持數據。

 


方法的註冊:        registerMethod("mytestEvent", make_method(this, &cuihaoidentiferAPI::testEvent)); 


注意:需要在js中訪問的方法才需要註冊,否則可以不用註冊。 上例中mytestEvent爲暴露給js的函數名,make_method後爲真正的函數名。



【屬性】


屬性分爲只讀屬性和讀寫屬性,屬性也是靠函數實現的,即set和get,如下

registerProperty("mystr", make_property(this, &cuihaoidentiferAPI::get_myString, &cuihaoidentiferAPI::set_myString));

上例中是一個讀寫屬性,因爲有get和set,如果是隻讀屬性則只寫get即可,方法如下:

    std::string get_myString();

    void set_myString(const std::string& str);

這樣的方法不需要註冊,因爲不需要被js訪問。




【Attribute】

這個東西應該翻譯成什麼呢? Attribute和【屬性累死】,也分爲只讀和讀寫,但是區別是Attribute沒有複雜的代碼邏輯,只需要註冊一下即可,

void FB::JSAPIAuto::registerAttribute( const std::string &name, const FB::variant& value, bool readonly /*= false*/ ),

而這個註冊不需要在構造函數裏,在任何函數中註冊都可以,默認爲讀寫屬性,第三個參數爲true時即爲只讀,雖然叫做只讀的,但是僅僅是不可以在javascript中改變其值,在C++中還是可以改變其值的。

void cuihaoidentiferAPI::regAttriWR()             //對js提供的註冊Attribute的函數

{

    registerAttribute("first", 100); 

}


void cuihaoidentiferAPI::regAttriROnly()         //對js提供的註冊Attribute的函數

{

    registerAttribute("second", "cuihao", true);

}


可是,但是,可但是,請注意根據我自己的實驗發現:

1、當沒有調用註冊Attribute的函數registerAttribute時,得到的屬性值爲undefined(符合預期);

2、當在js中用代碼在沒有調用registerAttribute的情況下給Attribute賦值時卻可以賦值成功,並且就算是隻讀的也可以賦值成功,

這一點不太明白。

 



【Event】事件

由於瀏覽器的差異,強烈建議命名事件時遵循如下原則:

1、所有字母小寫

2、事件名字必須以"on"開頭


例如:

onload  onstart ondead  onsomethingelse ....


FB 1.5.0中的新特性

事件必須總是使用相同的參數個數和參數類型被觸發,最後我們在你的JSAPI類上增加了創建方法的宏,這樣就能在js中觸發事件。這是由你的JSAPI類中的FB_JSAPI_EVENT宏來完成的。 寫在class聲明中!

語法個數如下:

FB_JSAPI_EVENT({事件名(不帶on)}, {參數個數}, {參數類型列表})


eg.

/////////////////////////////

class ClassName

{

public:

FB_JSAPI_EVENT(load, 0, ())  //名字爲load,參數個數爲0,沒有參數類型

FB_JSAPI_EVENT(update, 1, (int)) // 名字爲update, 一個參數, 類型爲int

FB_JSAPI_EVENT(rename, 2, (const std::string& old, const std::string& new))  //名字爲rename,參數爲2個,    ///////////////////////////////////                                           //類型爲const std::string

}

///////////////////////////////////////////////////


觸發事件:

void ClassName::fireAllEvents()

{

fire_load();

fire_update(10);

fire("old name", "new name"); 


}

///////////////////////////////////////////////////


注意:永遠不要在析構函數中觸發事件(fire event),這樣會導致未定義的行爲,也許會使得頁面重新加載的時候插件崩潰!



在js中使用events:爲了在js中處理你的插件中的事件,你需要在插件對象中listen for it。

在所有的IE版本尤其是IE9中, 必須使用attachEvent函數來添加事件,儘管addEventListener在IE9中也是可用的,但是IE從來不會把事件句柄傳遞給插件,所以如果你不使用attachEvent這樣可能會導致失敗!

注意:調用attchEvent函數添加事件的時候必須加上“on”!  另外有用戶反映在IE中的embed標籤中使用插件可能會導致事件不能正常工作,所以請你在OBJECT標籤中使用。 


function onPluginLoad()        //對應load事件,無參數

{

   alert("I am  loadding!");

}


function onPluginUpdate(num)   //對應update事件,參數爲一個int類型

{

alert("number is " + num);

}


function onPluginRename(old, new)

{

alert(old + "  " + new);

}



function testEvent()

{

var plugin = document.getElementById("pluginID");

plugin.attachEvent("on" + "load", onPluginLoad);

plugin.attachEvent("on" + "update", );

plugin.attachEvent("on" + "rename", onPluginRename);

}


///////////////////////////////////////////////////////////////////////////////////////////////////////////


在其他瀏覽器中使用(except IE):使用addEventListener函數來添加事件,而用這個函數添加事件則不需要在事件名前手動加"on",會自動添加"on"。


function onPluginLoad()

{

alert("I ma loadding!");

}


function onPluginUpdate(num)

{

alert("number is " + num);

}


function testEvent()

{

var plugin = document.getElementById("pluginID");

plugin.addEventListener("load", onPluginLoad, false);      //addEventListener有三個參數

plugin.addEventListener("update", onPluginUpdate, false);  //addEventListener有三個參數

}



///////自適應不同瀏覽器///////

function testEvent()

{

var plugin = document.getElementById("pluginID");

if(plugin.attachEvent)                             //IE, 或者是判斷瀏覽器內核

{

plugin.attachEvent("on" + "load", onPluginLoad);

}

else

{

plugin.addEventListener("load", onPluginLoad, false);

}

}


注意:FB不支持"useCapture"參數,即addEventListener的第三個參數,忽略,寫false爲保持語法正確,true也可。


卸載事件:IE;detachEvent(),  非IE:removeEventListener()。


/////////////////////////////////////////////////////////////////////////////////



在FB 1.5.0 之前的版本中:

註冊事件(在構造函數中):

class ClassName

{

public:

registerEvent("onload");

registerEvent("onupdate");

}

///...................


觸發事件:

void ClassName::FireEvents()

{

//this->FireEvent("event name", params);  //event name包括"on", 

//params是一個FB::VariantList(std::vector<FB::variant>)。

this->FireEvent("onload", FB::variant_list_of());

this->FireEvent("onupdate", FB::variant_list_of(10));

}





//////////////////////////////////////////////////////////////////////////////////

再談實參 形參

js傳一個數組參數給插件的方法:在插件的方法中可以使用FB:VariantList做形參或者是任何一個適應實參的STL容器類型。

eg.

plugin.func(new Array(1, "2", 3.0));


//FB::VariantList做形參

bool func(FB::VariantList& array);


//STL做形參

bool func(std::vector<std::string>& array);



如果實參是一個js對象,那麼形參可以是一個FB::JSObjectPtr& obj類型。

如果實參是一個js函數,js函數同樣也是對象,也可以使用FB::JSObjectPtr& func類型。



如果實參是一組可變參數,那麼形參可以使用FB::CatchAll& args,比如:

//js

plugin.add('my stuff', 1, "2", 3.0)'


//.cpp

bool MyAPI::add(const FB::CatchAll& args)

{

const FB::VariantList& values = args.value;

std::string a = values[0].convert_cast<std::string>();

int         b = values[1].convert_case<int>();

//....


return true;

}


//////////////////////////////////////////////////////////////

返回基本類型

所有被FB::variant支持的簡單類型都可以直接返回。


返回容器

可以直接返回FB::VariantList 和 FB::VariantMap類型

return FB::variant_list_of(1)(2)(3);

return FB::variant_map_of(1, 2)(3, 4)(5, 6);



返回對象

返回的對象畢竟已經實現了FB::JSAPI,並且FB:JSAPIPtr應該作爲返回類型。

return boost::make_shared<SomeObject>(m_browserHost),

其中SomeObject必須已經實現了JSAPI。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章