Mozilla Firefox
 Extension Development
   Course 2: Advanced
           Littlebtc
OSSF Workshop / MozTW Acitivity

      T...
Review
• Do you remember…?
  – XUL and controls?
  – Some JavaScript technique?
  – install.rdf and chrome.manifest?
  – S...
Preference System
Make options for your extension
Why preferences?
• Provide options to user
  – Which can be set in an option window
  – Or in the program operation
• Reco...
about:config
Available types
• String
• Integer
• Boolean: true / false
Default Preferences
•   Can be included in the Extension Dir / XPI file
•   Will be loaded as default value of preferences...
Take an example
• See defaults/preferences/ tutorial.js

pref(quot;extensions.tutorial.option1quot;, false);
pref(quot;ext...
See about:config
Preference System:
             <prefwindow>
• Way to make a quot;option windowquot;
• It is XUL, again
• But it has a spe...
Set install.rdf, again
<em:optionsURL>chrome://tutorial/content/opt
  ions.xul</em:optionsURL>
• This will point the quot;...
<prefpane>
• Must be a child of <prefwindow>
• Reprensent a pane (tab) in the prefwindow
• Attributes:
  – label
  – image...
<preferences> <preference>
• <preferences>: Container
• <preference>: quot;Magic Attributequot; to hold the
  actual prefe...
Example: options.xul
<?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?>
<?xml-stylesheet href=quot;chrome://global/ski...
Example: panel2.xul
<?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?>

<overlay id=quot;Pane2Overlayquot;
    xmlns=q...
Result
Part 2: Read/Write in XPCOM
• XPCOM: nsIPrefService / nsIPrefBranch
• Changes Preferences in JavaScript
• First step: Read...
Part 2: Read/Write in XPCOM
• Then, read/write
• getBoolPref(), setBoolPref()
• getCharPref(), setCharPref()
  – BEWARE: N...
Part 2: Read/Write in XPCOM
Examples to run in JavaScript Shell:
// Get the quot;extensions.tutorial.quot; branch
var pref...
Part 2: Read/Write in XPCOM
• Read/Write Unicode Strings:
(from https://developer.mozilla.org/en/Code_snippets/Preferences...
When you should use XPCOM
• First run:
   – Make a default pref to detect first run
     (Change it after first run proces...
File Processing
Access local files
https://developer.mozilla.org/en/Code_snippets/File_I%2f%2fO
The nsIFile / nsILocalFile
• nsIFile: Cross-platform File I/O interface
• nsILocalFile: extends nsIFile, can access local
...
quot;Createquot; a nsILocalFile
• With a absolute path:
var file = Components.classes[quot;@mozilla.org/file/local;1quot;]...
quot;Createquot; nsIFile pointing to special
               folders
• Get an object located to Profile Directory:
// get p...
How to…
Assuming we have a nsIFile object file, how to
• Get the native path representation of a nsIFile?
   – file.path
•...
How to…
• Whether the path is
  readable/writable/executable/hidden?
  • Use file.isWritable() file.isReadable()
     file...
How to…
• quot;Open the filequot; by the OS?
  •   file.launch();

• Do something like quot;Open containing folderquot; in...
How to…
• Delete the path?
  – file.remove();
  – For folder, you can only remove empty folder
• Copy path?
  – file.copyT...
How to…
• How to quot;run the filequot; if it is a executable?
  – file.launch(); (Not recommended)
  – Use nsIProcess:
  ...
How to…
Assuming file is a nsIFile object refering to a folder path, how to:
• Access a file in this directory?
    – file...
File contents read/write
• https://developer.mozilla.org/en/Code_snippets/
  File_I%2f%2fO
• A little complex, why? When i...
File Picker / <filefield>
• File Open / File Save / Select Folder Dialog
• See
  https://developer.mozilla.org/en/nsIFileP...
File I/O demo 1
• A run dialog like Windows, use undocumented
  <filefield>
run.xul
<?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?>
<?xml-stylesheet href=quot;chrome://global/skinquot; type=q...
run.js (partial)
browse: function() {
   // Initialize file picker
   var fp = Cc[quot;@mozilla.org/filepicker;1quot;].cre...
run.js (partial 2)
go: function() {
    if (this.file && this.file.exists() &&
  this.file.isFile()) {
       this.file.la...
URI Problem
• In XPCOM, nsIURI is a common interface to represent
  an URI (It can handle all types of URI)
• nsIURI <-> S...
When you will need nsIURI / nsIFile
• Downloading files
  https://developer.mozilla.org/en/Code_snippets/
  Downloading_Fi...
Tree
A somehow complex XUL structure
What is a tree?
• A complex item lists
• An item may have some childs
Why is it so complex
•   There are A LOT OF way to implement
•   But none of them are NOT trivial 
•   Some is easier but...
The easiest: Content Tree
•   (Try XUL Editor!)
•   From https://developer.mozilla.org/En/XUL/Tree
<tree flex=quot;1quot; ...
The easiest: Content Tree
• <tree>: Sent a row number as rows attribute is
  recommended?
• <treecols>, <treecol>: Define ...
A tree with nested items
From https://developer.mozilla.org/En/XUL/Tree

<tree id=quot;myTreequot; flex=quot;1quot; hideco...
Wait, a lot of new thing…?
• <splitter>: Between columns, to make them
  resizable
• Nested items: <treechildren> under <t...
OK, now, what is wrong?
• Though we can multiply the tree with DOM,
  but it will the code will be somehow complex
  due t...
The most common:
               Custom TreeView
• Implements nsITreeView to create a tree
• Set custom tree view into view...
Tree Selection / Box Object
• Tree Selection: Get currently selected items
  https://developer.mozilla.org/en/XUL_Tutorial...
Take a break, there is a final boss: SQLite!

LUNCH TIME AGAIN!
Storage: SQLite
Great storage choice
What is SQLite?
• A lightweight relational database
  management system
• Its C/C++ library is very small (418KB in Firefo...
SQLite is in …
•   Firefox, Safari, Google Chrome
•   Google Gears
•   Photoshop lightroom, Adobe AIR
•   Skype, McAfee, S...
Now, make a new database!
Now, make a new database!
• Find your profile dir and copy the path Orz
Now, make a new database!
• Close SQLite manager and restart:
Create a table
Table is ready!
Add a record
Simple way to display SQLite DB
• Use template
  https://developer.mozilla.org/en/XUL/Templat
  e_Guide/SQLite_Templates
•...
students.xul
<tree flex=quot;1quot;>
 <treecols>
  <treecol id=quot;col-noquot; label=quot;Noquot; flex=quot;1quot;/>
  <t...
Explain
• <treechildren datasources=quot;profile:tutorial.sqlitequot;
  ref=quot;*quot; querytype=quot;storagequot;>
• Use...
mozStorage API
• Mozilla's way to multiply SQLite database
• So it is XPCOM again … 
• But it is not so difficult!

• I d...
Final Demo:
quot;Add a recordquot; function
A SQL preview
• INSERT INTO students (name, score) VALUES
  (quot;Littlebtcquot;, 30)
• Insert a data into students table
...
students.xul, again
<hbox>
<label value=quot;Student Name:quot; accesskey=quot;Nquot; control=quot;new_namequot; />
<textb...
student.js: student.add();
/* use nsIPromptService to alert */
    /*
   https://developer.mozilla.org/en/Code_snippets/Di...
…continued
   try { // try-catch exception handling

     /* We will see here later */
   } catch(e) { // There may be som...
Connect to DB
/* Find the tutorial.sqlite */
var file = Components.classes[quot;@mozilla.org/file/directory_service;1quot;...
Execute a quot;statementquot;
var sql = quot;INSERT INTO students (name, score) VALUES
  (?1, ?2)quot;;
var statement = db...
Finally…
• Don't forget to close your DB!

   db.close();
After try{…} catch{…}
• We should update the tree and show a
  message
/* Update the tree */
document.getElementById('stud...
Working Example
How to do for you later
• Understand how to CRUD (Create, Read,
  Update, Delete) in SQLite
  – SQL commands: INSERT, SELE...
This is the basic!
• Actually, SQLite storage access with <tree> is
  usually implemented in Custom Tree View way,
  both ...
It is 5:34am, I had finished my slide 

THANK YOU!
…….NOT YET!!!
Ext 0523
Upcoming SlideShare
Loading in …5
×

Ext 0523

0 views
1,540 views

Published on

Published in: Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
0
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
20
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Ext 0523

  1. 1. Mozilla Firefox Extension Development Course 2: Advanced Littlebtc OSSF Workshop / MozTW Acitivity The text of the slide is under CC-BY-SA-3.0. Most photos are under CC-BY-SA compatible license, while screenshots / logos are under Fair Use. Code is under MIT license.
  2. 2. Review • Do you remember…? – XUL and controls? – Some JavaScript technique? – install.rdf and chrome.manifest? – Some XPCOM introduction?
  3. 3. Preference System Make options for your extension
  4. 4. Why preferences? • Provide options to user – Which can be set in an option window – Or in the program operation • Record user's choice
  5. 5. about:config
  6. 6. Available types • String • Integer • Boolean: true / false
  7. 7. Default Preferences • Can be included in the Extension Dir / XPI file • Will be loaded as default value of preferences • Place .js files in [ext-dir]/defaults/preferences/ • Example of .js file content of default preferences : pref(quot;extensions.extensionname.preferencenamequot;, false); – Name: has a widely used naming convention – Value: Boolean / Integer / String
  8. 8. Take an example • See defaults/preferences/ tutorial.js pref(quot;extensions.tutorial.option1quot;, false); pref(quot;extensions.tutorial.option2quot;, quot;quot;); pref(quot;extensions.tutorial.option3quot;, 32); pref(quot;extensions.tutorial.default_editorquot;, quot;quot;);
  9. 9. See about:config
  10. 10. Preference System: <prefwindow> • Way to make a quot;option windowquot; • It is XUL, again • But it has a special system, in that system, you don't need to write too much JavaScript/XPCOM to support changing preferences.
  11. 11. Set install.rdf, again <em:optionsURL>chrome://tutorial/content/opt ions.xul</em:optionsURL> • This will point the quot;Optionsquot; button of your extension to the corresponding XUL pages:
  12. 12. <prefpane> • Must be a child of <prefwindow> • Reprensent a pane (tab) in the prefwindow • Attributes: – label – image – onpaneload: a onload-like on this panel – src: Content can be external XUL <prefpane id=quot;paneGeneralquot; label=quot;Generalquot; src=quot;chrome://path/to/paneOverlay.xulquot;/>
  13. 13. <preferences> <preference> • <preferences>: Container • <preference>: quot;Magic Attributequot; to hold the actual preference, attributes: – id – name: Corresponding preference name – type: bool/string/unichar/int/file • In controls, use preference=quot;idquot; to connect the magic!
  14. 14. Example: options.xul <?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?> <?xml-stylesheet href=quot;chrome://global/skin/quot; type=quot;text/cssquot;?> <?xml-stylesheet href=quot;chrome://mozapps/content/preferences/preferences.cssquot;?> <?xml-stylesheet href=quot;chrome://browser/skin/preferences/preferences.cssquot;?> <prefwindow xmlns=quot;http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xulquot;> <prefpane id=quot;panel1quot; label=quot;panel1quot;> <preferences> <preference name=quot;extensions.tutorial.option1quot; id=quot;extensions.tutorial.option1quot; type=quot;boolquot; /> <preference name=quot;extensions.tutorial.option2quot; id=quot;extensions.tutorial.option2quot; type=quot;unicharquot; /> </preferences> <checkbox id=quot;option1quot; preference=quot;extensions.tutorial.option1quot; label=quot;Check me!quot; /> <hbox> <label value=quot;Type Your Name:quot; accesskey=quot;Nquot; control=quot;option2quot; /> <textbox id=quot;option2quot; preference=quot;extensions.tutorial.option2quot; /> </hbox> </prefpane> <prefpane id=quot;panel2quot; label=quot;panel2quot; src=quot;chrome://tutorial/content/panel2.xulquot;/> </prefwindow>
  15. 15. Example: panel2.xul <?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?> <overlay id=quot;Pane2Overlayquot; xmlns=quot;http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xulquot;> <prefpane id=quot;panel2quot;> <preferences> <preference name=quot;extensions.tutorial.option3quot; id=quot;extensions.tutorial.option3quot; type=quot;intquot; /> </preferences> <hbox> <label value=quot;Type a Integer:quot; accesskey=quot;Iquot; control=quot;option3quot; /> <textbox id=quot;option3quot; preference=quot;extensions.tutorial.option3quot; type=quot;numberquot; /> </hbox> </prefpane> </overlay>
  16. 16. Result
  17. 17. Part 2: Read/Write in XPCOM • XPCOM: nsIPrefService / nsIPrefBranch • Changes Preferences in JavaScript • First step: Read branch // Get the root branch var prefs = Components.classes[quot;@mozilla.org/preferences-service;1quot;] .getService(Components.interfaces.nsIPrefBranch); // Get the quot;extensions.tutorial.quot; branch var prefs = Components.classes[quot;@mozilla.org/preferences-service;1quot;] .getService(Components.interfaces.nsIPrefService); prefs = prefs.getBranch(quot;extensions.tutorial.quot;);
  18. 18. Part 2: Read/Write in XPCOM • Then, read/write • getBoolPref(), setBoolPref() • getCharPref(), setCharPref() – BEWARE: Not Unicode Compatible! • getIntPref() and setIntPref()
  19. 19. Part 2: Read/Write in XPCOM Examples to run in JavaScript Shell: // Get the quot;extensions.tutorial.quot; branch var prefs = Components.classes[quot;@mozilla.org/preferences-service;1quot;] .getService(Components.interfaces.nsIPrefService); prefs = prefs.getBranch(quot;extensions.tutorial.quot;); // Get the value of option3 (a number) var option3 = prefs.getIntPref('option3'); alert(option3); // Set the value of option1 (a boolean) to true prefs.setBoolPref('option1', true); var option1 = prefs.getBoolPref('option1'); alert(option1);
  20. 20. Part 2: Read/Write in XPCOM • Read/Write Unicode Strings: (from https://developer.mozilla.org/en/Code_snippets/Preferences) // Example 1: getting Unicode value var option2 = prefs.getComplexValue(quot;option2quot;, Components.interfaces.nsISupportsString).data; alert(option2); // Example 2: setting Unicode value var str = Components.classes[quot;@mozilla.org/supports-string;1quot;] .createInstance(Components.interfaces.nsISupportsString); str.data = quot;火狐quot;; prefs.setComplexValue(quot;option2quot;, Components.interfaces.nsISupportsString, str);
  21. 21. When you should use XPCOM • First run: – Make a default pref to detect first run (Change it after first run processing is ended) • Dialog to remember something: – Like quot;Exit Firefoxquot;:
  22. 22. File Processing Access local files https://developer.mozilla.org/en/Code_snippets/File_I%2f%2fO
  23. 23. The nsIFile / nsILocalFile • nsIFile: Cross-platform File I/O interface • nsILocalFile: extends nsIFile, can access local filesystem • It is a quot;LOCATION INDICATORquot; • What can nsILocalFile object do? – Check whether the file exists – Copy / Delete / Move files – Create files / folders – Work as a parameter to a lot of function • Saving webpage into files, etc…
  24. 24. quot;Createquot; a nsILocalFile • With a absolute path: var file = Components.classes[quot;@mozilla.org/file/local;1quot;] .createInstance(Components.interfaces.nsILocalFile); file.initWithPath(quot;C:quot;); • quot;Pathquot; should be in a quot;nativequot; way like /home/littlebtc in Linux, C: in Windows • file:// URI? Explained later
  25. 25. quot;Createquot; nsIFile pointing to special folders • Get an object located to Profile Directory: // get profile directory var file = Components.classes[quot;@mozilla.org/file/directory_service;1quot;] .getService(Components.interfaces.nsIProperties) .get(quot;ProfDquot;, Components.interfaces.nsIFile); • You can replace the ProfD with: With… Where With… Where CurProcD (Firefox) Installation Desk Desktop Dir C:UsersLittlebtcDesktop Home User's Dir Progs quot;Programsquot; directory in C:UsersLittlebtc Windows Start Menu /home/littlebtc/ resource:app XULRunner App Directory
  26. 26. How to… Assuming we have a nsIFile object file, how to • Get the native path representation of a nsIFile? – file.path • Know whether the path refers to a existed thing? – file.exists() – Return true or false • Distinguish the path which this file object refers to from a folder, a file, or a link, or others? – Use file.isFile() file.isFolder() file.isSymlink() file.isSpecial()
  27. 27. How to… • Whether the path is readable/writable/executable/hidden? • Use file.isWritable() file.isReadable() file.isExecutable() file.isHidden() • Know the filesize (if it is a file)? – file.fileSize • The file name without path? – file.leafName • The parent of the path? – file.parent (It is a nsIFile object, and can be null!)
  28. 28. How to… • quot;Open the filequot; by the OS? • file.launch(); • Do something like quot;Open containing folderquot; in download manager? • file.reveal(); • Both of them are not work on Unix-like!
  29. 29. How to… • Delete the path? – file.remove(); – For folder, you can only remove empty folder • Copy path? – file.copyTo(file2, 'newname'); – file2 represents the parent path for the target item, if it is null, it will be copied to the same parent of file • Move path? – file.moveTo(file2, 'newname'); – file2 is the same as above – You can only move empty folder
  30. 30. How to… • How to quot;run the filequot; if it is a executable? – file.launch(); (Not recommended) – Use nsIProcess: https://developer.mozilla.org/En/Code_snippets/ Running_applications – nsIProcess cannot accept Unicode parameters on Windows… 
  31. 31. How to… Assuming file is a nsIFile object refering to a folder path, how to: • Access a file in this directory? – file.append('filename'); Then file will be changed, will refer to this file, not the original folder! • Access multiple files? Clone object, then append – var file1 = file.clone(); // Clone file object file1.append('filename'); • How to create a subfolder? – file.append(quot;DIRquot;); // Still, append first if( !file.exists() || !file.isDirectory() ) { // if it doesn't exist, create file.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0777); }
  32. 32. File contents read/write • https://developer.mozilla.org/en/Code_snippets/ File_I%2f%2fO • A little complex, why? When it comes to the encoding, it will be complex 
  33. 33. File Picker / <filefield> • File Open / File Save / Select Folder Dialog • See https://developer.mozilla.org/en/nsIFilePicker • <filefield> in the <prefwindow>, like Firefox options (UNDOCUMENTED): http://www.xuldev.org/blog/?p=142 • We will have a small demo!
  34. 34. File I/O demo 1 • A run dialog like Windows, use undocumented <filefield>
  35. 35. run.xul <?xml version=quot;1.0quot; encoding=quot;UTF-8quot;?> <?xml-stylesheet href=quot;chrome://global/skinquot; type=quot;text/cssquot;?> <dialog title=quot;Run applicationquot; buttons=quot;accept,cancelquot; ondialogaccept=quot;runApp.go();quot; xmlns=quot;http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xulquot;> <script type=quot;application/x-javascriptquot; src=quot;chrome://tutorial/content/run.jsquot;/> <hbox> <label value=quot;Select an file:quot; accesskey=quot;Fquot; /> <filefield id=quot;filequot; /> <button label=quot;Browse...quot; oncommand=quot;runApp.browse();quot; /> </hbox> <grid> <columns> <column flex=quot;1quot; /> <column flex=quot;2quot; /></columns> <rows> <row> <label value=quot;File name:quot; /><label value=quot;quot; id=quot;file_namequot; /> </row> <row> <label value=quot;File size:quot; /><label value=quot;quot; id=quot;file_sizequot; /> </row> </rows> </grid> </dialog>
  36. 36. run.js (partial) browse: function() { // Initialize file picker var fp = Cc[quot;@mozilla.org/filepicker;1quot;].createInstance(Ci.nsIFilePicker); fp.init(window, 'Select a file', Ci.nsIFilePicker.modeOpen); // Set Filter: file types fp.appendFilter('Windows executable', '*.exe'); fp.appendFilter('All Files', '*.*'); // Show the dialog var result = fp.show(); if (result == Ci.nsIFilePicker.returnOK) { this.file = fp.file; // This should not be happened, but this is a demo :P if (!this.file.exists() || !this.file.isFile()) { return; } // Include it into filefield document.getElementById('file').file = this.file; // Load file infos document.getElementById('file_name').value = this.file.leafName; document.getElementById('file_size').value = this.file.fileSize + ' bytes'; } },
  37. 37. run.js (partial 2) go: function() { if (this.file && this.file.exists() && this.file.isFile()) { this.file.launch(); } }
  38. 38. URI Problem • In XPCOM, nsIURI is a common interface to represent an URI (It can handle all types of URI) • nsIURI <-> String URL: Use nsIIOService – var uri = Components.classes[quot;@mozilla.org/network/io-service;1quot;] .getService(Components.interfaces.nsIIOService) .newURI('http://moztw.org/', null, null); – uri.spec will contain the string representation of the URI • nsIURI <-> nsIFile – var file_uri = Components.classes[quot;@mozilla.org/network/io-service;1quot;] .getService(Components.interfaces.nsIIOService) .newFileURI(file); // Assuming file is a nsIFIle – var file = file_uri.QueryInterface(Components.interfaces.nsIFileURL) .file;
  39. 39. When you will need nsIURI / nsIFile • Downloading files https://developer.mozilla.org/en/Code_snippets/ Downloading_Files (Basic) http://www.xuldev.org/blog/?p=163 (Advanced, by Gomita, a good intro to nsIWebBrowserPersist) • Use Places API (Bookmarks, Tags, History) https://developer.mozilla.org/en/Places • Progress listeners https://developer.mozilla.org/en/Code_snippets/ Progress_Listeners • And much more…
  40. 40. Tree A somehow complex XUL structure
  41. 41. What is a tree? • A complex item lists • An item may have some childs
  42. 42. Why is it so complex • There are A LOT OF way to implement • But none of them are NOT trivial  • Some is easier but not so easy to be extended • Some is harder, but fully functional
  43. 43. The easiest: Content Tree • (Try XUL Editor!) • From https://developer.mozilla.org/En/XUL/Tree <tree flex=quot;1quot; rows=quot;2quot;> <treecols> <treecol id=quot;senderquot; label=quot;Senderquot; flex=quot;1quot;/> <treecol id=quot;subjectquot; label=quot;Subjectquot; flex=quot;2quot;/> </treecols> <treechildren> <treeitem> <treerow> <treecell label=quot;joe@somewhere.comquot;/> <treecell label=quot;Top secret plansquot;/> </treerow> </treeitem> <treeitem> <treerow> <treecell label=quot;mel@whereever.comquot;/> <treecell label=quot;Let's do lunchquot;/> </treerow> </treeitem> </treechildren> </tree>
  44. 44. The easiest: Content Tree • <tree>: Sent a row number as rows attribute is recommended? • <treecols>, <treecol>: Define the columns – Use flex to modify column width in <treecol> – Use id to build an identifier of the column • <treeitem>, <treerow>: Represents a row • <treecell>: Represents a cell – Attribute: label
  45. 45. A tree with nested items From https://developer.mozilla.org/En/XUL/Tree <tree id=quot;myTreequot; flex=quot;1quot; hidecolumnpicker=quot;falsequot; seltype=quot;singlequot; class=quot;treequot; rows=quot;5quot;> <treecols id=quot;myTree2-treeColsquot;> <treecol id=quot;myTree2-treeCol0quot; primary=quot;truequot; flex=quot;2quot; label=quot;Column Aquot; persist=quot;widthquot; ordinal=quot;1quot;/> <splitter class=quot;tree-splitterquot; ordinal=quot;2quot;/> <treecol id=quot;myTree2-treeCol1quot; flex=quot;1quot; label=quot;Column Bquot; persist=quot;widthquot; ordinal=quot;3quot;/> </treecols> <treechildren> <treeitem> <treerow> <treecell label=quot;1quot;/> <treecell label=quot;aquot;/> </treerow> </treeitem> <!-- Make sure to set container=quot;truequot; --> <treeitem container=quot;truequot; open=quot;truequot;> <treerow> <treecell label=quot;2quot;/> <treecell label=quot;bquot;/> </treerow> <treechildren> <treeitem> <treerow> <treecell label=quot;2aquot;/> <treecell label=quot;baquot;/> </treerow> </treeitem> </treechildren> </treeitem> </treechildren> </tree>
  46. 46. Wait, a lot of new thing…? • <splitter>: Between columns, to make them resizable • Nested items: <treechildren> under <treeitem> • hidecolumnpicker=quot;falsequot; – Whether to hide the column picker on the right – seltype=quot;singlequot;: you can select only one item or seltype=quot;multiplequot; for multiple selection support • persist=quot;attributename1 attributename2quot; – Make Firefox quot;rememberquot; user's settings on specific attribute
  47. 47. OK, now, what is wrong? • Though we can multiply the tree with DOM, but it will the code will be somehow complex due to the bad XUL structure • So DOM way is not a popular way if it comes to dynamic content trees
  48. 48. The most common: Custom TreeView • Implements nsITreeView to create a tree • Set custom tree view into view property • It can be fully functional and dynamic – …But somehow hard: poorly documented and buggy if having bad implementation – You should check Firefox's code to understand  – It takes me almost 20 hours to make <tree> on NicoFox works and another 20 hours to fix bugs… • Are you ready? :D https://developer.mozilla.org/en/XUL_Tutorial/Custom_Tree_ Views http://www.xuldev.org/blog/?p=127 (Thank you again, Gomita!)
  49. 49. Tree Selection / Box Object • Tree Selection: Get currently selected items https://developer.mozilla.org/en/XUL_Tutorial/Tr ee_Selection – A little like text selection we had mentioned at the previous lecture (?) • Box Objects: Handle Tree's display Needed, for example, if you need to know the which cell the cursor is at https://developer.mozilla.org/en/XUL_Tutorial/Tr ee_Box_Objects
  50. 50. Take a break, there is a final boss: SQLite! LUNCH TIME AGAIN!
  51. 51. Storage: SQLite Great storage choice
  52. 52. What is SQLite? • A lightweight relational database management system • Its C/C++ library is very small (418KB in Firefox 3.5) and very easy-to-use • Can use most of the SQL command • Resulting database is a single file • PUBLIC DOMAIN!(No any copyright restriction) • Used by a lot of software / framework
  53. 53. SQLite is in … • Firefox, Safari, Google Chrome • Google Gears • Photoshop lightroom, Adobe AIR • Skype, McAfee, Songbird • PHP, Python… • iPhone, Symbian, Android… • Almost everywhere!!!!
  54. 54. Now, make a new database!
  55. 55. Now, make a new database! • Find your profile dir and copy the path Orz
  56. 56. Now, make a new database! • Close SQLite manager and restart:
  57. 57. Create a table
  58. 58. Table is ready!
  59. 59. Add a record
  60. 60. Simple way to display SQLite DB • Use template https://developer.mozilla.org/en/XUL/Templat e_Guide/SQLite_Templates • Simple, but useful for our demo! :D • We will use the template technique and <tree> in the following demo
  61. 61. students.xul <tree flex=quot;1quot;> <treecols> <treecol id=quot;col-noquot; label=quot;Noquot; flex=quot;1quot;/> <treecol id=quot;col-namequot; label=quot;Namequot; flex=quot;1quot;/> <treecol id=quot;col-scorequot; label=quot;Scorequot; flex=quot;1quot;/> </treecols> <treechildren datasources=quot;profile:tutorial.sqlitequot; ref=quot;*quot; querytype=quot;storagequot;> <template> <query> SELECT * FROM students ORDER BY score DESC </query> <action> <treeitem uri=quot;?quot;> <treerow> <treecell label=quot;?noquot;/> <treecell label=quot;?namequot;/> <treecell label=quot;?scorequot;/> </treerow> </treeitem> </action> </template> </treechildren> </tree>
  62. 62. Explain • <treechildren datasources=quot;profile:tutorial.sqlitequot; ref=quot;*quot; querytype=quot;storagequot;> • Use SQLite database as a template datasources • <template>: <query> and <action> – <query>: SQL command • SELECT * FROM students: Select all fields from students table • ORDER BY score DESC: Order by score field in descendant order – <action>: Applied template • uri=quot;?quot;: (?) • Read score field from ?score
  63. 63. mozStorage API • Mozilla's way to multiply SQLite database • So it is XPCOM again …  • But it is not so difficult! • I don't want to talk in detail, so go straight to examples!
  64. 64. Final Demo: quot;Add a recordquot; function
  65. 65. A SQL preview • INSERT INTO students (name, score) VALUES (quot;Littlebtcquot;, 30) • Insert a data into students table • Two fields: name and score • Their values: Littlebtc and 30
  66. 66. students.xul, again <hbox> <label value=quot;Student Name:quot; accesskey=quot;Nquot; control=quot;new_namequot; /> <textbox id=quot;new_namequot; style=quot;width: 8em;quot;/> <label value=quot;Score:quot; accesskey=quot;Squot; control=quot;new_scorequot; /> <textbox id=quot;new_scorequot; type=quot;numberquot; style=quot;width: 4em;quot; max=quot;100quot; min=quot;0quot;/> <button label=quot;Addquot; oncommand=quot;students.add();quot;/> </hbox>
  67. 67. student.js: student.add(); /* use nsIPromptService to alert */ /* https://developer.mozilla.org/en/Code_snippets/Dialogs_and_Prom pts */ var prompts = Cc[quot;@mozilla.org/embedcomp/prompt-service;1quot;] .getService(Ci.nsIPromptService); /* Record user's choice */ var name = document.getElementById('new-name').value; var score = document.getElementById('new-score').value; /* Required to enter a name */ if (!name) { prompts.alert(null, 'Error', 'Please Enter a Name.'); return; }
  68. 68. …continued try { // try-catch exception handling /* We will see here later */ } catch(e) { // There may be some error in XPCOM, we can handle it prompts.alert(null, 'Error', 'Database/XPCOM Error:' + e); } • XPCOM Will throw exception when error • So we need a good way to handle it • …Or it will be displayed in the error console
  69. 69. Connect to DB /* Find the tutorial.sqlite */ var file = Components.classes[quot;@mozilla.org/file/directory_service;1quot;] .getService(Components.interfaces.nsIProperties) .get(quot;ProfDquot;, Components.interfaces.nsIFile); file.append(quot;tutorial.sqlitequot;); /* Open database */ var storageService = Cc[quot;@mozilla.org/storage/service;1quot;] .getService(Ci.mozIStorageService); var db = storageService.openDatabase(file);
  70. 70. Execute a quot;statementquot; var sql = quot;INSERT INTO students (name, score) VALUES (?1, ?2)quot;; var statement = db.createStatement(sql); statement.bindUTF8StringParameter(0, name); statement.bindInt32Parameter(1, score); /* Execute the statement */ statement.execute(); /* Finallize */ statement.finalize(); • quot;Statementquot; is a SQL command in mozStorage • Why we should use the quot;bindingquot; way? Prevent SQL injection, make database safe • https://developer.mozilla.org/en/mozIStorageStatemen t#Binding_Functions
  71. 71. Finally… • Don't forget to close your DB! db.close();
  72. 72. After try{…} catch{…} • We should update the tree and show a message /* Update the tree */ document.getElementById('students-treechildren') .builder.rebuild(); /* Prompt the user */ prompts.alert(null, 'OK', 'Thank you!');
  73. 73. Working Example
  74. 74. How to do for you later • Understand how to CRUD (Create, Read, Update, Delete) in SQLite – SQL commands: INSERT, SELECT, UPDATE, DELETE • Remember: Always Binding, NEVER directly apply variables into SQL command strings – Google quot;SQL Injectionquot; for details • SQLite is simple but powerful – have fun!
  75. 75. This is the basic! • Actually, SQLite storage access with <tree> is usually implemented in Custom Tree View way, both in Firefox and NicoFox • That is another reason that I had spent 40 hours on a tree • Edit / Remove may be a very hard work
  76. 76. It is 5:34am, I had finished my slide  THANK YOU!
  77. 77. …….NOT YET!!!

×