Browse Source
http://wiki.koha-community.org/wiki/Offline_circulation_firefox_plugin https://addons.mozilla.org/fr/firefox/addon/koct/origin
committed by
Paul Poulain
10 changed files with 390 additions and 2 deletions
@ -1,2 +1,10 @@ |
|||
This repository is for general contributions |
|||
to Koha. |
|||
This repository is for general contributions to Koha. |
|||
|
|||
- sandbox: |
|||
The sandbox system has been developed with the goal to lower the barrier for librarian to test patches and improvements of Koha. |
|||
http://wiki.koha-community.org/wiki/Sandboxes |
|||
|
|||
- koct: |
|||
Koha Offline Circulation Firefox addon |
|||
http://wiki.koha-community.org/wiki/Offline_circulation_firefox_plugin |
|||
https://addons.mozilla.org/fr/firefox/addon/koct/ |
|||
|
@ -0,0 +1,2 @@ |
|||
content koct chrome/content/ |
|||
overlay chrome://browser/content/browser.xul chrome://koct/content/koct.xul |
After Width: | Height: | Size: 577 B |
@ -0,0 +1,6 @@ |
|||
<?xml version="1.0"?> |
|||
<overlay id="koct" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> |
|||
<statusbar id="status-bar"> |
|||
<statusbarpanel image="chrome://koct/content/koct-window.png" class="statusbarpanel-iconic" onclick="window.open('chrome://koct/content/main.xul','main','centerscreen,chrome,resizable');"/> |
|||
</statusbar> |
|||
</overlay> |
@ -0,0 +1,84 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?> |
|||
<window |
|||
id="koct-window" |
|||
title="Koha Offline Circulation Tool" |
|||
persist="screenX screenY" |
|||
width="500" |
|||
height="400" |
|||
onload="onReady()" |
|||
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> |
|||
<script src="script.js" /> |
|||
<tabbox flex="1"> |
|||
<tabs> |
|||
<tab label="Check Out" accesskey="o" /> |
|||
<tab label="Check In" accesskey="i" /> |
|||
<tab label="Log" accesskey="l" onclick="updateTree()" /> |
|||
<tab label="Param" /> |
|||
</tabs> |
|||
<tabpanels flex="1"> |
|||
<tabpanel id="issuetab"> |
|||
<vbox flex="1"> |
|||
<hbox flex="1"> |
|||
<vbox flex="1"> |
|||
<label control="issuepatronbarcode" value="Patron Barcode:" /> |
|||
<textbox id="issuepatronbarcode" tabindex="1" onkeypress="checkReturn(event,'issueitembarcode', false)" /> |
|||
<label control="issueitembarcode" value="Item Barcode:" /> |
|||
<textbox id="issueitembarcode" tabindex="2" onkeypress="checkReturn(event,'issuesave', 'issue')" /> |
|||
</vbox> |
|||
<!--<vbox> |
|||
<label control="issuedate" value="Expected Return:" /> |
|||
<datepicker id="issuedate" type="grid" /> |
|||
</vbox>--> |
|||
</hbox> |
|||
<button id="issuesave" label="Save" tabindex="3" oncommand="save('issue')" /> |
|||
</vbox> |
|||
</tabpanel> |
|||
<tabpanel id="returntab"> |
|||
<vbox flex="1"> |
|||
<vbox flex="1"> |
|||
<label control="returnitembarcode" value="Item Barcode:" /> |
|||
<textbox id="returnitembarcode" tabindex="1" onkeypress="checkReturn(event,'returnsave', 'return')" /> |
|||
</vbox> |
|||
<button id="returnsave" tabindex="2" label="Save" oncommand="save('return')" /> |
|||
</vbox> |
|||
</tabpanel> |
|||
<tabpanel id="logtab"> |
|||
<vbox flex="1"> |
|||
<tree id="tree1" flex="1" hidecolumnpicker="true" seltype="single" onselect="setText('tree1','value1');" > |
|||
<treecols> |
|||
<treecol flex="1" label="Timestamp" /> |
|||
<treecol flex="1" label="Action" /> |
|||
<treecol flex="1" label="Card Number" /> |
|||
<treecol flex="1" label="Barcode" /> |
|||
<treecol flex="1" label="Status" /> |
|||
</treecols> |
|||
<treechildren id="treechildren"> |
|||
</treechildren> |
|||
</tree> |
|||
<hbox> |
|||
<button label="Commit to Koha" oncommand="commit(true)" /> |
|||
<button label="Apply directly" oncommand="commit(false)" /> |
|||
<button label="Clear" oncommand="clear()" /> |
|||
</hbox> |
|||
</vbox> |
|||
</tabpanel> |
|||
<tabpanel id="paramtab"> |
|||
<vbox onkeyup="savePreferences()" onchange="savePreferences()" oncommand="savePreferences()"> |
|||
<label control="server" value="Server:" /> |
|||
<textbox id="server" /> |
|||
<label control="branchcode" value="Branch Code:" /> |
|||
<textbox id="branchcode" /> |
|||
<label control="username" value="Username:" /> |
|||
<textbox id="username" /> |
|||
<label control="password" value="Password:" /> |
|||
<textbox id="password" type="password" /> |
|||
</vbox> |
|||
</tabpanel> |
|||
</tabpanels> |
|||
</tabbox> |
|||
<statusbar> |
|||
<statusbarpanel flex="1" /> |
|||
<statusbarpanel id="status" /> |
|||
</statusbar> |
|||
</window> |
After Width: | Height: | Size: 1.2 KiB |
@ -0,0 +1,187 @@ |
|||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; |
|||
var dbCon; |
|||
|
|||
var rowsadded; |
|||
|
|||
function onReady() { |
|||
rowsadded = 0; |
|||
|
|||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); |
|||
|
|||
restorePreferences(); |
|||
|
|||
var file = Components.classes["@mozilla.org/file/directory_service;1"] |
|||
.getService(Components.interfaces.nsIProperties) |
|||
.get("ProfD", Components.interfaces.nsIFile); |
|||
file.append("offlinecirc.sqlite"); |
|||
|
|||
var storageService = Components.classes["@mozilla.org/storage/service;1"] |
|||
.getService(Components.interfaces.mozIStorageService); |
|||
dbConn = storageService.openDatabase(file); |
|||
|
|||
dbConn.executeSimpleSQL("CREATE TABLE IF NOT EXISTS offlinecirc (timestamp TIMESTAMP, action VARCHAR, cardnumber VARCHAR, barcode VARCHAR, status VARCHAR)"); |
|||
|
|||
var statement = Components.classes['@mozilla.org/storage/statement-wrapper;1'].createInstance(Components.interfaces.mozIStorageStatementWrapper); |
|||
var query = dbConn.createStatement("SELECT COUNT(*) AS numrow FROM offlinecirc"); |
|||
statement.initialize(query); |
|||
statement.step(); |
|||
if(statement.row.numrow) { |
|||
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService); |
|||
var deleteRows = {value: null}; |
|||
if(prompts.confirmCheck(window, "WARNING", "The local database contains "+statement.row.numrow+" entrie(s), do you want to remove them ?", "I want to delete rows", deleteRows)){ |
|||
if (deleteRows.value){ |
|||
dbConn.executeSimpleSQL("DELETE FROM offlinecirc"); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
function updateTree() { |
|||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); |
|||
|
|||
var treechildren = document.getElementById("treechildren"); |
|||
while (treechildren.firstChild) { |
|||
treechildren.removeChild(treechildren.firstChild); |
|||
} |
|||
|
|||
var statement = Components.classes['@mozilla.org/storage/statement-wrapper;1'].createInstance(Components.interfaces.mozIStorageStatementWrapper); |
|||
var query = dbConn.createStatement("SELECT * FROM offlinecirc"); |
|||
statement.initialize(query); |
|||
while (statement.step()) { |
|||
var treeitem = document.createElementNS(XUL_NS, "treeitem"); |
|||
|
|||
var treerow = document.createElementNS(XUL_NS, "treerow"); |
|||
treeitem.appendChild(treerow); |
|||
|
|||
for each( column in ['timestamp','action','cardnumber','barcode','status'] ) { |
|||
var treecell = document.createElementNS(XUL_NS, "treecell"); |
|||
treecell.setAttribute("label", eval('statement.row.'+column)); |
|||
treerow.appendChild(treecell); |
|||
} |
|||
|
|||
treechildren.appendChild(treeitem); |
|||
} |
|||
} |
|||
|
|||
function save(attr) { |
|||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); |
|||
|
|||
switch(attr) { |
|||
case 'issue': |
|||
var patronbarcode = document.getElementById('issuepatronbarcode').value; |
|||
var itembarcode = document.getElementById('issueitembarcode').value; |
|||
dbConn.executeSimpleSQL("INSERT INTO offlinecirc VALUES(CURRENT_TIMESTAMP,'issue','"+patronbarcode+"','"+itembarcode+"','Local.')"); |
|||
rowsadded++; |
|||
document.getElementById('issuepatronbarcode').value = ''; |
|||
document.getElementById('issueitembarcode').value = ''; |
|||
document.getElementById('issuepatronbarcode').focus(); |
|||
document.getElementById('status').setAttribute("label",rowsadded+" Row(s) Added"); |
|||
break; |
|||
case 'return': |
|||
var itembarcode = document.getElementById('returnitembarcode').value; |
|||
dbConn.executeSimpleSQL("INSERT INTO offlinecirc VALUES(CURRENT_TIMESTAMP,'return',NULL,'"+itembarcode+"','Local.')"); |
|||
rowsadded++; |
|||
document.getElementById('returnitembarcode').value = ''; |
|||
document.getElementById('returnitembarcode').focus(); |
|||
document.getElementById('status').setAttribute("label",rowsadded+" Row(s) Added"); |
|||
break; |
|||
} |
|||
} |
|||
|
|||
function checkReturn(e, nextFieldName, attr) { |
|||
var event; |
|||
var key |
|||
var cChar |
|||
var retCheck = /\r/; |
|||
|
|||
if (window.event) { |
|||
event = window.event; |
|||
key = window.event.keyCode; |
|||
target = event.srcElement; |
|||
} else if (e) { |
|||
event = e; |
|||
key = event.which; |
|||
target = event.target; |
|||
} |
|||
|
|||
cChar= String.fromCharCode(key) |
|||
|
|||
if(retCheck.test(cChar)) { |
|||
document.getElementById(nextFieldName).focus(); |
|||
if(attr) { |
|||
save(attr); |
|||
} |
|||
} |
|||
} |
|||
|
|||
function restorePreferences() { |
|||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); |
|||
var prefs = Components.classes["@mozilla.org/preferences-service;1"] |
|||
.getService(Components.interfaces.nsIPrefService); |
|||
prefs = prefs.getBranch("extensions.koct."); |
|||
|
|||
for each( pref in ['server','branchcode','username','password'] ) { |
|||
document.getElementById(pref).value = prefs.getComplexValue("preference."+pref, |
|||
Components.interfaces.nsISupportsString).data; |
|||
} |
|||
} |
|||
|
|||
function savePreferences() { |
|||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); |
|||
var prefs = Components.classes["@mozilla.org/preferences-service;1"] |
|||
.getService(Components.interfaces.nsIPrefService); |
|||
prefs = prefs.getBranch("extensions.koct."); |
|||
var str = Components.classes["@mozilla.org/supports-string;1"] |
|||
.createInstance(Components.interfaces.nsISupportsString); |
|||
|
|||
for each( pref in ['server','branchcode','username','password'] ) { |
|||
str.data = document.getElementById(pref).value; |
|||
prefs.setComplexValue("preference."+pref, |
|||
Components.interfaces.nsISupportsString, str); |
|||
} |
|||
} |
|||
|
|||
function commit( pending ) { |
|||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); |
|||
|
|||
var statement = Components.classes['@mozilla.org/storage/statement-wrapper;1'].createInstance(Components.interfaces.mozIStorageStatementWrapper); |
|||
var query = dbConn.createStatement("SELECT * FROM offlinecirc WHERE status='Local.' OR status='Authentication failed.'"); |
|||
statement.initialize(query); |
|||
|
|||
var url = document.getElementById('server').value+"/cgi-bin/koha/offline_circ/service.pl"; |
|||
|
|||
while ( statement.step() ) { |
|||
|
|||
var params = "userid=" + document.getElementById('username').value; |
|||
params += "&password=" + document.getElementById('password').value; |
|||
params += "&branchcode=" + document.getElementById('branchcode').value; |
|||
params += "&pending=" + pending; |
|||
params += "&action=" + statement.row.action; |
|||
params += "×tamp=" + statement.row.timestamp; |
|||
params += statement.row.cardnumber ? "&cardnumber=" + statement.row.cardnumber : ""; |
|||
params += "&barcode=" + statement.row.barcode; |
|||
|
|||
var req = new XMLHttpRequest(); |
|||
req.open("POST", url, false); |
|||
req.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); |
|||
req.setRequestHeader("Content-length", params.length); |
|||
//req.setRequestHeader("Connection", "close");
|
|||
req.send(params); |
|||
|
|||
if ( req.status == 200 ) { |
|||
dbConn.executeSimpleSQL("UPDATE offlinecirc SET status='"+req.responseText+"' WHERE timestamp='"+statement.row.timestamp+"'"); |
|||
updateTree(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
function clear() { |
|||
netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect'); |
|||
|
|||
var statement = Components.classes['@mozilla.org/storage/statement-wrapper;1'].createInstance(Components.interfaces.mozIStorageStatementWrapper); |
|||
var query = dbConn.createStatement("SELECT * FROM offlinecirc"); |
|||
statement.initialize(query); |
|||
|
|||
dbConn.executeSimpleSQL("DELETE FROM offlinecirc"); |
|||
updateTree(); |
|||
} |
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,72 @@ |
|||
/* XPM */ |
|||
static char * koct_window_xpm[] = { |
|||
"16 16 53 1", |
|||
" c None", |
|||
". c #99CC33", |
|||
"+ c #92C825", |
|||
"@ c #92C826", |
|||
"# c #FFFFFF", |
|||
"$ c #DDDAE4", |
|||
"% c #9B98A2", |
|||
"& c #C7C4CD", |
|||
"* c #FEFEFE", |
|||
"= c #D4D4D4", |
|||
"- c #272727", |
|||
"; c #000000", |
|||
"> c #282828", |
|||
", c #F3F3F3", |
|||
"' c #FDFDFD", |
|||
") c #BDBDBD", |
|||
"! c #565656", |
|||
"~ c #DBDBDB", |
|||
"{ c #0C0C0C", |
|||
"] c #F2F2F2", |
|||
"^ c #2E2E2E", |
|||
"/ c #CECECE", |
|||
"( c #ACACAC", |
|||
"_ c #CACACA", |
|||
": c #414141", |
|||
"< c #F4F4F4", |
|||
"[ c #0F0F0F", |
|||
"} c #121212", |
|||
"| c #F6F6F6", |
|||
"1 c #D0D0D0", |
|||
"2 c #5A5A5A", |
|||
"3 c #BEBEBE", |
|||
"4 c #8D8D8D", |
|||
"5 c #060606", |
|||
"6 c #444444", |
|||
"7 c #C3C3C3", |
|||
"8 c #686868", |
|||
"9 c #CBCBCB", |
|||
"0 c #B1B1B1", |
|||
"a c #C5C5C5", |
|||
"b c #C9C9C9", |
|||
"c c #1A1A1A", |
|||
"d c #EBEBEB", |
|||
"e c #DDDDDD", |
|||
"f c #C8C8C8", |
|||
"g c #DCDCDC", |
|||
"h c #262626", |
|||
"i c #424242", |
|||
"j c #0B0B0B", |
|||
"k c #C7C7C7", |
|||
"l c #FFFEFF", |
|||
"m c #A7A4AD", |
|||
"n c #B7B4BE", |
|||
".+@@@@@@@@@@@@+.", |
|||
"+#######$%&####+", |
|||
"@##**#=-;;;>,'#@", |
|||
"@#**#);;;;;;!##@", |
|||
"@#**~;;;;;;;{]#@", |
|||
"@#*#^;;;;;;;;/#@", |
|||
"@##(;;;;;;;;;_#@", |
|||
"@##:;;;;;;;;;=#@", |
|||
"@#<[;;;;;;;;}|#@", |
|||
"@#1;23345;;;6##@", |
|||
"@#78#''#9;;;0##@", |
|||
"@#ab'***'c;-#'#@", |
|||
"@#dd*e##f;;~**#@", |
|||
"@#*'*ghi;jk#**#@", |
|||
"+#####lmn######+", |
|||
".+@@@@@@@@@@@@+."}; |
@ -0,0 +1,29 @@ |
|||
<?xml version="1.0"?> |
|||
|
|||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" |
|||
xmlns:em="http://www.mozilla.org/2004/em-rdf#"> |
|||
|
|||
<Description about="urn:mozilla:install-manifest"> |
|||
<em:id>koct@koha.fr</em:id> |
|||
<em:version>0.2.2</em:version> |
|||
<em:type>2</em:type> |
|||
|
|||
<!-- Target Application this extension can install into, |
|||
with minimum and maximum supported versions. --> |
|||
<em:targetApplication> |
|||
<Description> |
|||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> |
|||
<em:minVersion>1.5</em:minVersion> |
|||
<em:maxVersion>3.6.*</em:maxVersion> |
|||
</Description> |
|||
</em:targetApplication> |
|||
|
|||
<!-- Front End MetaData --> |
|||
<em:iconURL>chrome://koct/content/module-icon.png</em:iconURL> |
|||
<em:name>KOCT</em:name> |
|||
<em:description>Koha Offline Circulation Tool</em:description> |
|||
<em:creator>BibLibre</em:creator> |
|||
<em:developer>Jean-André Santoni; Claire Hernandez</em:developer> |
|||
<em:homepageURL>http://www.biblibre.com/</em:homepageURL> |
|||
</Description> |
|||
</RDF> |
Loading…
Reference in new issue