|
Lines 1-311
Link Here
|
|
|
1 |
[% SET footerjs = 1 %] |
| 1 |
[% INCLUDE 'doc-head-open.inc' %] |
2 |
[% INCLUDE 'doc-head-open.inc' %] |
| 2 |
<title>Koha › Tools › Quote uploader</title> |
3 |
<title>Koha › Tools › Quote uploader</title> |
| 3 |
[% INCLUDE 'doc-head-close.inc' %] |
4 |
[% INCLUDE 'doc-head-close.inc' %] |
| 4 |
<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/css/uploader.css" /> |
5 |
<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/css/uploader.css" /> |
| 5 |
<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/css/quotes.css" /> |
6 |
<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/css/quotes.css" /> |
| 6 |
<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/css/datatables.css" /> |
7 |
<link rel="stylesheet" type="text/css" href="[% interface %]/[% theme %]/css/datatables.css" /> |
| 7 |
[% INCLUDE 'datatables.inc' %] |
|
|
| 8 |
<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.jeditable.mini.js"></script> |
| 9 |
<script type="text/javascript"> |
| 10 |
//<![CDATA[ |
| 11 |
var oTable; //DataTable object |
| 12 |
$(document).ready(function() { |
| 13 |
|
| 14 |
$("#cancel_upload").on("click",function(e){ |
| 15 |
e.preventDefault(); |
| 16 |
fnAbortRead(); |
| 17 |
}); |
| 18 |
$("#cancel_quotes").on("click",function(){ |
| 19 |
return confirm( _("Are you sure you want to cancel this import?") ); |
| 20 |
}); |
| 21 |
|
| 22 |
// Credits: |
| 23 |
// FileReader() code copied and hacked from: |
| 24 |
// http://www.html5rocks.com/en/tutorials/file/dndfiles/ |
| 25 |
// fnCSVToArray() gratefully borrowed from: |
| 26 |
// http://www.bennadel.com/blog/1504-Ask-Ben-Parsing-CSV-Strings-With-Javascript-Exec-Regular-Expression-Command.htm |
| 27 |
|
| 28 |
var reader; |
| 29 |
var progress = document.querySelector('.percent'); |
| 30 |
$("#server_response").hide(); |
| 31 |
|
| 32 |
function yuiGetData() { |
| 33 |
fnGetData(document.getElementById('quotes_editor')); |
| 34 |
} |
| 35 |
|
| 36 |
function fnAbortRead() { |
| 37 |
reader.abort(); |
| 38 |
} |
| 39 |
|
| 40 |
function fnErrorHandler(evt) { |
| 41 |
switch(evt.target.error.code) { |
| 42 |
case evt.target.error.NOT_FOUND_ERR: |
| 43 |
alert('File Not Found!'); |
| 44 |
break; |
| 45 |
case evt.target.error.NOT_READABLE_ERR: |
| 46 |
alert('File is not readable'); |
| 47 |
break; |
| 48 |
case evt.target.error.ABORT_ERR: |
| 49 |
break; // noop |
| 50 |
default: |
| 51 |
alert('An error occurred reading this file.'); |
| 52 |
}; |
| 53 |
} |
| 54 |
|
| 55 |
function fnUpdateProgress(evt) { |
| 56 |
// evt is an ProgressEvent. |
| 57 |
if (evt.lengthComputable) { |
| 58 |
var percentLoaded = Math.round((evt.loaded / evt.total) * 100); |
| 59 |
// Increase the progress bar length. |
| 60 |
if (percentLoaded < 100) { |
| 61 |
progress.style.width = percentLoaded + '%'; |
| 62 |
progress.textContent = percentLoaded + '%'; |
| 63 |
} |
| 64 |
} |
| 65 |
} |
| 66 |
|
| 67 |
function fnCSVToArray( strData, strDelimiter ){ |
| 68 |
// This will parse a delimited string into an array of |
| 69 |
// arrays. The default delimiter is the comma, but this |
| 70 |
// can be overriden in the second argument. |
| 71 |
|
| 72 |
// Check to see if the delimiter is defined. If not, |
| 73 |
// then default to comma. |
| 74 |
strDelimiter = (strDelimiter || ","); |
| 75 |
|
| 76 |
// Create a regular expression to parse the CSV values. |
| 77 |
var objPattern = new RegExp( |
| 78 |
( |
| 79 |
// Delimiters. |
| 80 |
"(\\" + strDelimiter + "|\\r?\\n|\\r|^)" + |
| 81 |
// Quoted fields. |
| 82 |
"(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" + |
| 83 |
// Standard fields. |
| 84 |
"([^\"\\" + strDelimiter + "\\r\\n]*))" |
| 85 |
), |
| 86 |
"gi" |
| 87 |
); |
| 88 |
|
| 89 |
// Create an array to hold our data. Give the array |
| 90 |
// a default empty first row. |
| 91 |
var arrData = [[]]; |
| 92 |
|
| 93 |
// Create an array to hold our individual pattern |
| 94 |
// matching groups. |
| 95 |
var arrMatches = null; |
| 96 |
|
| 97 |
// Keep looping over the regular expression matches |
| 98 |
// until we can no longer find a match. |
| 99 |
while (arrMatches = objPattern.exec( strData )){ |
| 100 |
|
| 101 |
// Get the delimiter that was found. |
| 102 |
var strMatchedDelimiter = arrMatches[ 1 ]; |
| 103 |
|
| 104 |
// Check to see if the given delimiter has a length |
| 105 |
// (is not the start of string) and if it matches |
| 106 |
// field delimiter. If it does not, then we know |
| 107 |
// that this delimiter is a row delimiter. |
| 108 |
if ( strMatchedDelimiter.length && (strMatchedDelimiter != strDelimiter) ){ |
| 109 |
// Since we have reached a new row of data, |
| 110 |
// add an empty row to our data array. |
| 111 |
// Note: if there is not more data, we will have to remove this row later |
| 112 |
arrData.push( [] ); |
| 113 |
} |
| 114 |
|
| 115 |
// Now that we have our delimiter out of the way, |
| 116 |
// let's check to see which kind of value we |
| 117 |
// captured (quoted or unquoted). |
| 118 |
if (arrMatches[ 2 ]){ |
| 119 |
// We found a quoted value. When we capture |
| 120 |
// this value, unescape any double quotes. |
| 121 |
var strMatchedValue = arrMatches[ 2 ].replace( |
| 122 |
new RegExp( "\"\"", "g" ), |
| 123 |
"\"" |
| 124 |
); |
| 125 |
} else if (arrMatches[3]){ |
| 126 |
// We found a non-quoted value. |
| 127 |
var strMatchedValue = arrMatches[ 3 ]; |
| 128 |
} else { |
| 129 |
// There is no more valid data so remove the row we added earlier |
| 130 |
// Is there a better way? Perhaps a look-ahead regexp? |
| 131 |
arrData.splice(arrData.length-1, 1); |
| 132 |
} |
| 133 |
|
| 134 |
// Now that we have our value string, let's add |
| 135 |
// it to the data array. |
| 136 |
arrData[ arrData.length - 1 ].push( strMatchedValue ); |
| 137 |
} |
| 138 |
|
| 139 |
// Return the parsed data. |
| 140 |
return( arrData ); |
| 141 |
} |
| 142 |
|
| 143 |
function fnDataTable(aaData) { |
| 144 |
for(var i=0; i<aaData.length; i++) { |
| 145 |
aaData[i].unshift(i+1); // Add a column w/quote number |
| 146 |
} |
| 147 |
|
| 148 |
|
| 149 |
/* Transition from the quote file uploader to the quote file editor interface */ |
| 150 |
$('#toolbar').css("visibility","visible"); |
| 151 |
$('#toolbar').css("position",""); |
| 152 |
$('#file_editor_inst').css("visibility", "visible"); |
| 153 |
$('#file_editor_inst').css("position", ""); |
| 154 |
$('#file_uploader_inst').css("visibility", "hidden"); |
| 155 |
$('#save_quotes').css("visibility","visible"); |
| 156 |
$('#file_uploader').css("visibility","hidden"); |
| 157 |
$('#file_uploader').css("position","absolute"); |
| 158 |
$('#file_uploader').css("top","-150px"); |
| 159 |
$('#quotes_editor').css("visibility","visible"); |
| 160 |
$("#save_quotes").on("click", yuiGetData); |
| 161 |
$("#delete_quote").on("click", fnClickDeleteRow); |
| 162 |
|
| 163 |
|
| 164 |
|
| 165 |
oTable = $('#quotes_editor').dataTable( { |
| 166 |
"bAutoWidth" : false, |
| 167 |
"bPaginate" : true, |
| 168 |
"bSort" : false, |
| 169 |
"sPaginationType" : "full_numbers", |
| 170 |
"sDom": '<"top pager"iflp>rt<"bottom pager"flp><"clear">', |
| 171 |
"aaData" : aaData, |
| 172 |
"aoColumns" : [ |
| 173 |
{ |
| 174 |
"sTitle" : "Number", |
| 175 |
"sWidth" : "2%", |
| 176 |
}, |
| 177 |
{ |
| 178 |
"sTitle" : "Source", |
| 179 |
"sWidth" : "15%", |
| 180 |
}, |
| 181 |
{ |
| 182 |
"sTitle" : "Quote", |
| 183 |
"sWidth" : "83%", |
| 184 |
}, |
| 185 |
], |
| 186 |
"fnPreDrawCallback": function(oSettings) { |
| 187 |
return true; |
| 188 |
}, |
| 189 |
"fnRowCallback": function( nRow, aData, iDisplayIndex ) { |
| 190 |
/* do foo on various cells in the current row */ |
| 191 |
var quoteNum = $('td', nRow)[0].innerHTML; |
| 192 |
$(nRow).attr("id", quoteNum); /* set row ids to quote number */ |
| 193 |
$('td:eq(0)', nRow).click(function() {$(this.parentNode).toggleClass('selected',this.clicked);}); /* add row selectors */ |
| 194 |
$('td:eq(0)', nRow).attr("title", _("Click ID to select/deselect quote")); |
| 195 |
/* apply no_edit id to noEditFields */ |
| 196 |
noEditFields = [0]; /* number */ |
| 197 |
for (i=0; i<noEditFields.length; i++) { |
| 198 |
$('td', nRow)[noEditFields[i]].setAttribute("id","no_edit"); |
| 199 |
} |
| 200 |
return nRow; |
| 201 |
}, |
| 202 |
"fnDrawCallback": function(oSettings) { |
| 203 |
/* Apply the jEditable handlers to the table on all fields w/o the no_edit id */ |
| 204 |
$('#quotes_editor tbody td[id!="no_edit"]').editable( function(value, settings) { |
| 205 |
var cellPosition = oTable.fnGetPosition( this ); |
| 206 |
oTable.fnUpdate(value, cellPosition[0], cellPosition[1], false, false); |
| 207 |
return(value); |
| 208 |
}, |
| 209 |
{ |
| 210 |
"callback" : function( sValue, y ) { |
| 211 |
oTable.fnDraw(false); /* no filter/sort or we lose our pagination */ |
| 212 |
}, |
| 213 |
"height" : "14px", |
| 214 |
}); |
| 215 |
}, |
| 216 |
}); |
| 217 |
$('#footer').css("visibility","visible"); |
| 218 |
} |
| 219 |
|
| 220 |
function fnHandleFileSelect(evt) { |
| 221 |
// Reset progress indicator on new file selection. |
| 222 |
progress.style.width = '0%'; |
| 223 |
progress.textContent = '0%'; |
| 224 |
|
| 225 |
reader = new FileReader(); |
| 226 |
reader.onerror = fnErrorHandler; |
| 227 |
reader.onprogress = fnUpdateProgress; |
| 228 |
reader.onabort = function(e) { |
| 229 |
alert('File read cancelled'); |
| 230 |
parent.location='quotes-upload.pl'; |
| 231 |
}; |
| 232 |
reader.onloadstart = function(e) { |
| 233 |
$('#cancel_upload').show(); |
| 234 |
$('#progress_bar').addClass("loading"); |
| 235 |
}; |
| 236 |
reader.onload = function(e) { |
| 237 |
// Ensure that the progress bar displays 100% at the end. |
| 238 |
progress.style.width = '100%'; |
| 239 |
progress.textContent = '100%'; |
| 240 |
$('#cancel_upload').hide(); |
| 241 |
quotes = fnCSVToArray(e.target.result, ','); |
| 242 |
fnDataTable(quotes); |
| 243 |
} |
| 244 |
|
| 245 |
// perform various sanity checks on the target file prior to uploading... |
| 246 |
var fileType = evt.target.files[0].type || 'unknown'; |
| 247 |
var fileSizeInK = Math.round(evt.target.files[0].size/1024); |
| 248 |
|
| 249 |
if (!fileType.match(/comma-separated-values|csv|excel|calc/i)) { |
| 250 |
alert(_("Uploads limited to csv. Incorrect filetype: %s").format(fileType)); |
| 251 |
parent.location='quotes-upload.pl'; |
| 252 |
return; |
| 253 |
} |
| 254 |
if (fileSizeInK > 512) { |
| 255 |
if (!confirm(_("%s %s KB Do you really want to upload this file?").format(evt.target.files[0].name, fileSizeInK))) { |
| 256 |
parent.location='quotes-upload.pl'; |
| 257 |
return; |
| 258 |
} |
| 259 |
} |
| 260 |
// Read in the image file as a text string. |
| 261 |
reader.readAsText(evt.target.files[0]); |
| 262 |
} |
| 263 |
|
| 264 |
$('#file_upload').one('change', fnHandleFileSelect); |
| 265 |
|
| 266 |
}); |
| 267 |
|
| 268 |
function fnGetData(element) { |
| 269 |
var jqXHR = $.ajax({ |
| 270 |
url : "/cgi-bin/koha/tools/quotes/quotes-upload_ajax.pl", |
| 271 |
type : "POST", |
| 272 |
contentType : "application/x-www-form-urlencoded", // we must claim this mimetype or CGI will not decode the URL encoding |
| 273 |
dataType : "json", |
| 274 |
data : { |
| 275 |
"quote" : encodeURI ( JSON.stringify(oTable.fnGetData()) ), |
| 276 |
"action" : "add", |
| 277 |
}, |
| 278 |
success : function(){ |
| 279 |
var response = JSON.parse(jqXHR.responseText); |
| 280 |
if (response.success) { |
| 281 |
alert(_("%s quotes saved.").format(response.records)); |
| 282 |
window.location.reload(true); // is this the best route? |
| 283 |
} |
| 284 |
else { |
| 285 |
alert(_("%s quotes saved, but an error has occurred. Please ask your administrator to check the server log for more details.").format(response.records)); |
| 286 |
window.location.reload(true); // is this the best route? |
| 287 |
} |
| 288 |
}, |
| 289 |
}); |
| 290 |
} |
| 291 |
|
| 292 |
function fnClickDeleteRow() { |
| 293 |
var idsToDelete = oTable.$('.selected').map(function() { |
| 294 |
return this.id; |
| 295 |
}).get().join(', '); |
| 296 |
if (!idsToDelete) { |
| 297 |
alert(_("Please select a quote(s) by clicking the quote id(s) you desire to delete.")); |
| 298 |
} |
| 299 |
else if (confirm(_("Are you sure you wish to delete quote(s) %s?").format(idsToDelete))) { |
| 300 |
oTable.$('.selected').each(function(){ |
| 301 |
oTable.fnDeleteRow(this); |
| 302 |
}); |
| 303 |
} |
| 304 |
} |
| 305 |
|
| 306 |
//]]> |
| 307 |
</script> |
| 308 |
</head> |
8 |
</head> |
|
|
9 |
|
| 309 |
<body id="tools_quotes" class="tools"> |
10 |
<body id="tools_quotes" class="tools"> |
| 310 |
[% INCLUDE 'header.inc' %] |
11 |
[% INCLUDE 'header.inc' %] |
| 311 |
[% INCLUDE 'cat-search.inc' %] |
12 |
[% INCLUDE 'cat-search.inc' %] |
|
Lines 370-373
Link Here
|
| 370 |
[% INCLUDE 'tools-menu.inc' %] |
71 |
[% INCLUDE 'tools-menu.inc' %] |
| 371 |
</div> |
72 |
</div> |
| 372 |
</div> |
73 |
</div> |
|
|
74 |
|
| 75 |
[% MACRO jsinclude BLOCK %] |
| 76 |
<script type="text/javascript" src="[% interface %]/[% theme %]/js/tools-menu.js"></script> |
| 77 |
[% INCLUDE 'datatables.inc' %] |
| 78 |
<script type="text/javascript" src="[% interface %]/lib/jquery/plugins/jquery.jeditable.mini.js"></script> |
| 79 |
<script type="text/javascript"> |
| 80 |
var oTable; //DataTable object |
| 81 |
$(document).ready(function() { |
| 82 |
|
| 83 |
$("#cancel_upload").on("click",function(e){ |
| 84 |
e.preventDefault(); |
| 85 |
fnAbortRead(); |
| 86 |
}); |
| 87 |
$("#cancel_quotes").on("click",function(){ |
| 88 |
return confirm( _("Are you sure you want to cancel this import?") ); |
| 89 |
}); |
| 90 |
|
| 91 |
// Credits: |
| 92 |
// FileReader() code copied and hacked from: |
| 93 |
// http://www.html5rocks.com/en/tutorials/file/dndfiles/ |
| 94 |
// fnCSVToArray() gratefully borrowed from: |
| 95 |
// http://www.bennadel.com/blog/1504-Ask-Ben-Parsing-CSV-Strings-With-Javascript-Exec-Regular-Expression-Command.htm |
| 96 |
|
| 97 |
var reader; |
| 98 |
var progress = document.querySelector('.percent'); |
| 99 |
$("#server_response").hide(); |
| 100 |
|
| 101 |
function yuiGetData() { |
| 102 |
fnGetData(document.getElementById('quotes_editor')); |
| 103 |
} |
| 104 |
|
| 105 |
function fnAbortRead() { |
| 106 |
reader.abort(); |
| 107 |
} |
| 108 |
|
| 109 |
function fnErrorHandler(evt) { |
| 110 |
switch(evt.target.error.code) { |
| 111 |
case evt.target.error.NOT_FOUND_ERR: |
| 112 |
alert('File Not Found!'); |
| 113 |
break; |
| 114 |
case evt.target.error.NOT_READABLE_ERR: |
| 115 |
alert('File is not readable'); |
| 116 |
break; |
| 117 |
case evt.target.error.ABORT_ERR: |
| 118 |
break; // noop |
| 119 |
default: |
| 120 |
alert('An error occurred reading this file.'); |
| 121 |
}; |
| 122 |
} |
| 123 |
|
| 124 |
function fnUpdateProgress(evt) { |
| 125 |
// evt is an ProgressEvent. |
| 126 |
if (evt.lengthComputable) { |
| 127 |
var percentLoaded = Math.round((evt.loaded / evt.total) * 100); |
| 128 |
// Increase the progress bar length. |
| 129 |
if (percentLoaded < 100) { |
| 130 |
progress.style.width = percentLoaded + '%'; |
| 131 |
progress.textContent = percentLoaded + '%'; |
| 132 |
} |
| 133 |
} |
| 134 |
} |
| 135 |
|
| 136 |
function fnCSVToArray( strData, strDelimiter ){ |
| 137 |
// This will parse a delimited string into an array of |
| 138 |
// arrays. The default delimiter is the comma, but this |
| 139 |
// can be overriden in the second argument. |
| 140 |
|
| 141 |
// Check to see if the delimiter is defined. If not, |
| 142 |
// then default to comma. |
| 143 |
strDelimiter = (strDelimiter || ","); |
| 144 |
|
| 145 |
// Create a regular expression to parse the CSV values. |
| 146 |
var objPattern = new RegExp( |
| 147 |
( |
| 148 |
// Delimiters. |
| 149 |
"(\\" + strDelimiter + "|\\r?\\n|\\r|^)" + |
| 150 |
// Quoted fields. |
| 151 |
"(?:\"([^\"]*(?:\"\"[^\"]*)*)\"|" + |
| 152 |
// Standard fields. |
| 153 |
"([^\"\\" + strDelimiter + "\\r\\n]*))" |
| 154 |
), |
| 155 |
"gi" |
| 156 |
); |
| 157 |
|
| 158 |
// Create an array to hold our data. Give the array |
| 159 |
// a default empty first row. |
| 160 |
var arrData = [[]]; |
| 161 |
|
| 162 |
// Create an array to hold our individual pattern |
| 163 |
// matching groups. |
| 164 |
var arrMatches = null; |
| 165 |
|
| 166 |
// Keep looping over the regular expression matches |
| 167 |
// until we can no longer find a match. |
| 168 |
while (arrMatches = objPattern.exec( strData )){ |
| 169 |
|
| 170 |
// Get the delimiter that was found. |
| 171 |
var strMatchedDelimiter = arrMatches[ 1 ]; |
| 172 |
|
| 173 |
// Check to see if the given delimiter has a length |
| 174 |
// (is not the start of string) and if it matches |
| 175 |
// field delimiter. If it does not, then we know |
| 176 |
// that this delimiter is a row delimiter. |
| 177 |
if ( strMatchedDelimiter.length && (strMatchedDelimiter != strDelimiter) ){ |
| 178 |
// Since we have reached a new row of data, |
| 179 |
// add an empty row to our data array. |
| 180 |
// Note: if there is not more data, we will have to remove this row later |
| 181 |
arrData.push( [] ); |
| 182 |
} |
| 183 |
|
| 184 |
// Now that we have our delimiter out of the way, |
| 185 |
// let's check to see which kind of value we |
| 186 |
// captured (quoted or unquoted). |
| 187 |
if (arrMatches[ 2 ]){ |
| 188 |
// We found a quoted value. When we capture |
| 189 |
// this value, unescape any double quotes. |
| 190 |
var strMatchedValue = arrMatches[ 2 ].replace( |
| 191 |
new RegExp( "\"\"", "g" ), |
| 192 |
"\"" |
| 193 |
); |
| 194 |
} else if (arrMatches[3]){ |
| 195 |
// We found a non-quoted value. |
| 196 |
var strMatchedValue = arrMatches[ 3 ]; |
| 197 |
} else { |
| 198 |
// There is no more valid data so remove the row we added earlier |
| 199 |
// Is there a better way? Perhaps a look-ahead regexp? |
| 200 |
arrData.splice(arrData.length-1, 1); |
| 201 |
} |
| 202 |
|
| 203 |
// Now that we have our value string, let's add |
| 204 |
// it to the data array. |
| 205 |
arrData[ arrData.length - 1 ].push( strMatchedValue ); |
| 206 |
} |
| 207 |
|
| 208 |
// Return the parsed data. |
| 209 |
return( arrData ); |
| 210 |
} |
| 211 |
|
| 212 |
function fnDataTable(aaData) { |
| 213 |
for(var i=0; i<aaData.length; i++) { |
| 214 |
aaData[i].unshift(i+1); // Add a column w/quote number |
| 215 |
} |
| 216 |
|
| 217 |
/* Transition from the quote file uploader to the quote file editor interface */ |
| 218 |
$('#toolbar').css("visibility","visible"); |
| 219 |
$('#toolbar').css("position",""); |
| 220 |
$('#file_editor_inst').css("visibility", "visible"); |
| 221 |
$('#file_editor_inst').css("position", ""); |
| 222 |
$('#file_uploader_inst').css("visibility", "hidden"); |
| 223 |
$('#save_quotes').css("visibility","visible"); |
| 224 |
$('#file_uploader').css("visibility","hidden"); |
| 225 |
$('#file_uploader').css("position","absolute"); |
| 226 |
$('#file_uploader').css("top","-150px"); |
| 227 |
$('#quotes_editor').css("visibility","visible"); |
| 228 |
$("#save_quotes").on("click", yuiGetData); |
| 229 |
$("#delete_quote").on("click", fnClickDeleteRow); |
| 230 |
|
| 231 |
oTable = $('#quotes_editor').dataTable( { |
| 232 |
"bAutoWidth" : false, |
| 233 |
"bPaginate" : true, |
| 234 |
"bSort" : false, |
| 235 |
"sPaginationType" : "full_numbers", |
| 236 |
"sDom": '<"top pager"iflp>rt<"bottom pager"flp><"clear">', |
| 237 |
"aaData" : aaData, |
| 238 |
"aoColumns" : [ |
| 239 |
{ |
| 240 |
"sTitle" : "Number", |
| 241 |
"sWidth" : "2%", |
| 242 |
}, |
| 243 |
{ |
| 244 |
"sTitle" : "Source", |
| 245 |
"sWidth" : "15%", |
| 246 |
}, |
| 247 |
{ |
| 248 |
"sTitle" : "Quote", |
| 249 |
"sWidth" : "83%", |
| 250 |
}, |
| 251 |
], |
| 252 |
"fnPreDrawCallback": function(oSettings) { |
| 253 |
return true; |
| 254 |
}, |
| 255 |
"fnRowCallback": function( nRow, aData, iDisplayIndex ) { |
| 256 |
/* do foo on various cells in the current row */ |
| 257 |
var quoteNum = $('td', nRow)[0].innerHTML; |
| 258 |
$(nRow).attr("id", quoteNum); /* set row ids to quote number */ |
| 259 |
$('td:eq(0)', nRow).click(function() {$(this.parentNode).toggleClass('selected',this.clicked);}); /* add row selectors */ |
| 260 |
$('td:eq(0)', nRow).attr("title", _("Click ID to select/deselect quote")); |
| 261 |
/* apply no_edit id to noEditFields */ |
| 262 |
noEditFields = [0]; /* number */ |
| 263 |
for (i=0; i<noEditFields.length; i++) { |
| 264 |
$('td', nRow)[noEditFields[i]].setAttribute("id","no_edit"); |
| 265 |
} |
| 266 |
return nRow; |
| 267 |
}, |
| 268 |
"fnDrawCallback": function(oSettings) { |
| 269 |
/* Apply the jEditable handlers to the table on all fields w/o the no_edit id */ |
| 270 |
$('#quotes_editor tbody td[id!="no_edit"]').editable( function(value, settings) { |
| 271 |
var cellPosition = oTable.fnGetPosition( this ); |
| 272 |
oTable.fnUpdate(value, cellPosition[0], cellPosition[1], false, false); |
| 273 |
return(value); |
| 274 |
}, |
| 275 |
{ |
| 276 |
"callback" : function( sValue, y ) { |
| 277 |
oTable.fnDraw(false); /* no filter/sort or we lose our pagination */ |
| 278 |
}, |
| 279 |
"height" : "14px", |
| 280 |
}); |
| 281 |
}, |
| 282 |
}); |
| 283 |
$('#footer').css("visibility","visible"); |
| 284 |
} |
| 285 |
|
| 286 |
function fnHandleFileSelect(evt) { |
| 287 |
// Reset progress indicator on new file selection. |
| 288 |
progress.style.width = '0%'; |
| 289 |
progress.textContent = '0%'; |
| 290 |
|
| 291 |
reader = new FileReader(); |
| 292 |
reader.onerror = fnErrorHandler; |
| 293 |
reader.onprogress = fnUpdateProgress; |
| 294 |
reader.onabort = function(e) { |
| 295 |
alert('File read cancelled'); |
| 296 |
parent.location='quotes-upload.pl'; |
| 297 |
}; |
| 298 |
reader.onloadstart = function(e) { |
| 299 |
$('#cancel_upload').show(); |
| 300 |
$('#progress_bar').addClass("loading"); |
| 301 |
}; |
| 302 |
reader.onload = function(e) { |
| 303 |
// Ensure that the progress bar displays 100% at the end. |
| 304 |
progress.style.width = '100%'; |
| 305 |
progress.textContent = '100%'; |
| 306 |
$('#cancel_upload').hide(); |
| 307 |
quotes = fnCSVToArray(e.target.result, ','); |
| 308 |
fnDataTable(quotes); |
| 309 |
} |
| 310 |
|
| 311 |
// perform various sanity checks on the target file prior to uploading... |
| 312 |
var fileType = evt.target.files[0].type || 'unknown'; |
| 313 |
var fileSizeInK = Math.round(evt.target.files[0].size/1024); |
| 314 |
|
| 315 |
if (!fileType.match(/comma-separated-values|csv|excel|calc/i)) { |
| 316 |
alert(_("Uploads limited to csv. Incorrect filetype: %s").format(fileType)); |
| 317 |
parent.location='quotes-upload.pl'; |
| 318 |
return; |
| 319 |
} |
| 320 |
if (fileSizeInK > 512) { |
| 321 |
if (!confirm(_("%s %s KB Do you really want to upload this file?").format(evt.target.files[0].name, fileSizeInK))) { |
| 322 |
parent.location='quotes-upload.pl'; |
| 323 |
return; |
| 324 |
} |
| 325 |
} |
| 326 |
// Read in the image file as a text string. |
| 327 |
reader.readAsText(evt.target.files[0]); |
| 328 |
} |
| 329 |
|
| 330 |
$('#file_upload').one('change', fnHandleFileSelect); |
| 331 |
|
| 332 |
}); |
| 333 |
|
| 334 |
function fnGetData(element) { |
| 335 |
var jqXHR = $.ajax({ |
| 336 |
url : "/cgi-bin/koha/tools/quotes/quotes-upload_ajax.pl", |
| 337 |
type : "POST", |
| 338 |
contentType : "application/x-www-form-urlencoded", // we must claim this mimetype or CGI will not decode the URL encoding |
| 339 |
dataType : "json", |
| 340 |
data : { |
| 341 |
"quote" : encodeURI ( JSON.stringify(oTable.fnGetData()) ), |
| 342 |
"action" : "add", |
| 343 |
}, |
| 344 |
success : function(){ |
| 345 |
var response = JSON.parse(jqXHR.responseText); |
| 346 |
if (response.success) { |
| 347 |
alert(_("%s quotes saved.").format(response.records)); |
| 348 |
window.location.reload(true); // is this the best route? |
| 349 |
} else { |
| 350 |
alert(_("%s quotes saved, but an error has occurred. Please ask your administrator to check the server log for more details.").format(response.records)); |
| 351 |
window.location.reload(true); // is this the best route? |
| 352 |
} |
| 353 |
}, |
| 354 |
}); |
| 355 |
} |
| 356 |
|
| 357 |
function fnClickDeleteRow() { |
| 358 |
var idsToDelete = oTable.$('.selected').map(function() { |
| 359 |
return this.id; |
| 360 |
}).get().join(', '); |
| 361 |
if (!idsToDelete) { |
| 362 |
alert(_("Please select a quote(s) by clicking the quote id(s) you desire to delete.")); |
| 363 |
} |
| 364 |
else if (confirm(_("Are you sure you wish to delete quote(s) %s?").format(idsToDelete))) { |
| 365 |
oTable.$('.selected').each(function(){ |
| 366 |
oTable.fnDeleteRow(this); |
| 367 |
}); |
| 368 |
} |
| 369 |
} |
| 370 |
</script> |
| 371 |
[% END %] |
| 372 |
|
| 373 |
[% INCLUDE 'intranet-bottom.inc' %] |
373 |
[% INCLUDE 'intranet-bottom.inc' %] |