[Koha-patches] [PATCH] Tags AJAX and JSON for OPAC side.
Joe Atzberger
joe.atzberger at liblime.com
Wed May 21 08:36:05 CEST 2008
Note, all Tags js will live under KOHA.Tags namespace.
See opac-tags.pl perldoc for AJAX/JSON examples. The capability is already
there to be very web-servicey, even moreso than the current OPAC implementation
will utilize.
---
.../opac-tmpl/prog/en/includes/doc-head-close.inc | 4 +-
koha-tmpl/opac-tmpl/prog/en/js/tags.js | 76 ++++++++++++++++
.../opac-tmpl/prog/en/modules/opac-results.tmpl | 5 +-
koha-tmpl/opac-tmpl/prog/en/modules/opac-tags.tmpl | 2 +-
opac/opac-tags.pl | 92 ++++++++++++++++++--
5 files changed, 166 insertions(+), 13 deletions(-)
create mode 100644 koha-tmpl/opac-tmpl/prog/en/js/tags.js
diff --git a/koha-tmpl/opac-tmpl/prog/en/includes/doc-head-close.inc b/koha-tmpl/opac-tmpl/prog/en/includes/doc-head-close.inc
index a7fc971..17186d2 100644
--- a/koha-tmpl/opac-tmpl/prog/en/includes/doc-head-close.inc
+++ b/koha-tmpl/opac-tmpl/prog/en/includes/doc-head-close.inc
@@ -16,7 +16,9 @@
<script type="text/javascript" src="<!-- TMPL_VAR name="themelang" -->/lib/jquery/plugins/ui.tabs.js"></script>
<!-- TMPL_IF NAME="AmazonContent" --><script type="text/javascript" language="javascript" src="<!-- TMPL_VAR NAME="themelang" -->/js/amazonimages.js"></script><!-- /TMPL_IF -->
<script type="text/javascript" language="javascript" src="<!-- TMPL_VAR NAME="themelang" -->/js/script.js"></script>
-<!-- TMPL_IF NAME="opacbookbag" --><script type="text/javascript" language="javascript" src="<!-- TMPL_VAR NAME="themelang" -->/js/basket.js"></script><!-- /TMPL_IF -->
+<script type="text/javascript" language="javascript"
+<!-- TMPL_IF NAME="opacbookbag" -->src="<!-- TMPL_VAR NAME="themelang" -->/js/basket.js"><!-- TMPL_ELSE -->>var readCookie;<!-- /TMPL_IF --></script>
+<!-- TMPL_IF NAME="TagsEnabled" --><script type="text/javascript" language="javascript" src="<!-- TMPL_VAR NAME="themelang" -->/js/tags.js"></script><!-- /TMPL_IF -->
<!-- TMPL_IF NAME="GoogleJackets" -->
<script type="text/javascript" language="javascript" src="<!-- TMPL_VAR NAME="themelang" -->/js/google-jackets.js"></script>
<!-- /TMPL_IF -->
diff --git a/koha-tmpl/opac-tmpl/prog/en/js/tags.js b/koha-tmpl/opac-tmpl/prog/en/js/tags.js
new file mode 100644
index 0000000..62c66b2
--- /dev/null
+++ b/koha-tmpl/opac-tmpl/prog/en/js/tags.js
@@ -0,0 +1,76 @@
+if (typeof KOHA == "undefined" || !KOHA) {
+ var KOHA = {};
+}
+
+/**
+* A namespace for Tags related functions.
+* readCookie is expected to already be declared. That's why the assignment below is unscoped.
+* readCookie should be from basket.js or undefined.
+
+$.ajaxSetup({
+ url: "/cgi-bin/koha/opac-tags.pl",
+ type: "POST",
+ dataType: "script"
+});
+*/
+if (typeof(readCookie) == "undefined") {
+ readCookie = function (name) { // from http://www.quirksmode.org/js/cookies.html
+ var nameEQ = name + "=";
+ var ca = document.cookie.split(';');
+ for(var i=0;i < ca.length;i++) {
+ var c = ca[i];
+ while (c.charAt(0)==' '){ c = c.substring(1,c.length); }
+ if (c.indexOf(nameEQ) == 0){ return c.substring(nameEQ.length,c.length); }
+ }
+ return null;
+ }
+}
+KOHA.Tags = {
+ add_tag_button: function(){
+ var mybibnum = $(this).attr("title");
+ var mynewtag = "newtag" + mybibnum;
+ var mytagid = "#" + mynewtag;
+ var mydata = {CGISESSID: readCookie('CGISESSID')}; // Someday this should be OPACSESSID
+ mydata[mynewtag] = $(mytagid).val(); // need [bracket] for variable property id
+ var response; // AJAX from server will assign value to response.
+ $.post(
+ "/cgi-bin/koha/opac-tags.pl",
+ mydata,
+ function(data){
+ // alert("AJAX Response: " + data);
+ eval(data);
+ // alert("counts: " + response["added"] + response["deleted"] + response["errors"]);
+ KOHA.Tags.set_tag_status(
+ mytagid + "_status",
+ KOHA.Tags.common_status(response["added"], response["deleted"], response["errors"])
+ );
+ if (response.alerts) {
+ alert(response.alerts.join("\n\n"));
+ }
+ },
+ 'script'
+ );
+ return false;
+ },
+ common_status : function(addcount, delcount, errcount) {
+ var cstat = "";
+ if (addcount && addcount > 0) {cstat += "Added " + addcount + (addcount==1 ? " tag" : " tags") + ". " ;}
+ if (delcount && delcount > 0) {cstat += "Deleted " + delcount + (delcount==1 ? " tag" : " tags") + ". " ;}
+ if (errcount && errcount > 0) {cstat += (errcount==1 ? "ERROR" : errcount + " ERRORS") + " during operation.";}
+ return cstat;
+ },
+ set_tag_status : function(tagid, newstatus) {
+ $(tagid).html(newstatus);
+ $(tagid).css({display:"inline"});
+ },
+
+ tag_message: {
+ tagsdisabled : function(arg) {return ("Sorry, tags are not enabled on this system.");},
+ scrubbed_all_bad : function(arg) {return ("Error! Your tag was entirely markup code. It was NOT added. Please try again with plain text.");},
+ badparam : function(arg) {return ("Error! Illegal parameter '" +arg+ "'.");},
+ scrubbed : function(arg) {return ("Note: your tag contained markup code that was removed. The tag was added as '" +arg+ "'.");},
+ failed_add_tag : function(arg) {return ("Error! The add_tag operation failed on '" +arg+ "'.");},
+ failed_delete : function(arg) {return ("Error! You cannot delete the tag '" +arg+ "'. Note: you can only delete your own tags.");},
+ },
+};
+
diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tmpl b/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tmpl
index 7200482..797240d 100644
--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tmpl
+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-results.tmpl
@@ -53,6 +53,7 @@ $(document).ready(function(){
$("#bookbag_form").unCheckCheckboxes();
return false;
});
+ <!-- TMPL_IF NAME="TagsEnabled" -->$(".tagbutton").click(KOHA.Tags.add_tag_button);<!-- /TMPL_IF -->
<!-- TMPL_IF NAME="GoogleJackets" -->KOHA.Google.GetCoverFromIsbn();<!-- /TMPL_IF -->
});
//]]>
@@ -257,9 +258,9 @@ $(document).ready(function(){
<form name="tagform<!-- TMPL_VAR NAME="biblionumber" -->" method="post" action="/cgi-bin/koha/opac-tags.pl">
<label for="newtag<!-- TMPL_VAR NAME="biblionumber" -->">New tag:</label>
<input name="newtag<!-- TMPL_VAR NAME="biblionumber" -->" id="newtag<!-- TMPL_VAR NAME="biblionumber" -->" maxlength="100" />
- <input name="tagbutton" class="tagbutton" type="submit" value="Add" />
+ <input name="tagbutton" class="tagbutton" title="<!-- TMPL_VAR NAME="biblionumber" -->" type="submit" value="Add" />
</form>
- <span id="tagstatus<!-- TMPL_VAR NAME="biblionumber" -->" class="tagstatus" style="display:none;">
+ <span id="newtag<!-- TMPL_VAR NAME="biblionumber" -->_status" class="tagstatus" style="display:none;">
Tag status here.
</span>
<!-- /TMPL_IF -->
diff --git a/koha-tmpl/opac-tmpl/prog/en/modules/opac-tags.tmpl b/koha-tmpl/opac-tmpl/prog/en/modules/opac-tags.tmpl
index 491f233..447bc5e 100644
--- a/koha-tmpl/opac-tmpl/prog/en/modules/opac-tags.tmpl
+++ b/koha-tmpl/opac-tmpl/prog/en/modules/opac-tags.tmpl
@@ -13,7 +13,7 @@
<!-- TMPL_LOOP NAME="ERRORS" -->
<div class="error">There was a problem with this operation:
<!-- TMPL_IF NAME="tagsdisabled" -->Sorry, tags are not enabled on this system.
- <!-- TMPL_ELSIF NAME="badparam" -->ERROR: illegal paramter <!-- TMPL_VAR NAME="badparam" -->
+ <!-- TMPL_ELSIF NAME="badparam" -->ERROR: illegal parameter <!-- TMPL_VAR NAME="badparam" -->
<!-- TMPL_ELSIF NAME="login" -->ERROR: You must log in to complete that action.
<!-- TMPL_ELSIF NAME="failed_delete" -->ERROR: You cannot delete the tag <!-- TMPL_VAR NAME="failed_delete" -->.
<br />Note: you can only delete your own tags.
diff --git a/opac/opac-tags.pl b/opac/opac-tags.pl
index 9d32fe0..d085003 100755
--- a/opac/opac-tags.pl
+++ b/opac/opac-tags.pl
@@ -31,7 +31,7 @@ use warnings;
use CGI;
use CGI::Cookie; # need to check cookies before having CGI parse the POST request
-use C4::Auth;
+use C4::Auth qw(:DEFAULT check_cookie_auth);
use C4::Context;
use C4::Debug;
use C4::Output 3.02 qw(:html :ajax pagination_bar);
@@ -45,14 +45,34 @@ my @deltags = ();
my %counts = ();
my @errors = ();
+sub ajax_auth_cgi ($) { # returns CGI object
+ my $needed_flags = shift;
+ my %cookies = fetch CGI::Cookie;
+ my $input = CGI->new;
+ my $sessid = $cookies{'CGISESSID'}->value || $input->param('CGISESSID');
+ my ($auth_status, $auth_sessid) = check_cookie_auth($sessid, $needed_flags);
+ $debug and
+ print STDERR "($auth_status, $auth_sessid) = check_cookie_auth($sessid," . Dumper($needed_flags) . ")\n";
+ if ($auth_status ne "ok") {
+ output_ajax_with_http_headers $input,
+ "window.alert('Your CGI session cookie ($sessid) is not current. " .
+ "Please refresh the page and try again.');\n";
+ exit 0;
+ }
+ $debug and print STDERR "AJAX request: " . Dumper($input),
+ "\n(\$auth_status,\$auth_sessid) = ($auth_status,$auth_sessid)\n";
+ return $input;
+}
+
# The trick here is to support multiple tags added to multiple bilbios in one POST.
# The HTML might not use this, but it makes it more web-servicey from the start.
# So the name of param has to have biblionumber built in.
# For lack of anything more compelling, we just use "newtag[biblionumber]"
# We split the value into tags at comma and semicolon
+my $is_ajax = is_ajax();
my $openadds = C4::Context->preference('TagsModeration') ? 0 : 1;
-my $query = new CGI;
+my $query = ($is_ajax) ? &ajax_auth_cgi({}) : CGI->new();
unless (C4::Context->preference('TagsEnabled')) {
push @errors, {+ tagsdisabled=>1 };
} else {
@@ -72,13 +92,19 @@ unless (C4::Context->preference('TagsEnabled')) {
}
my $add_op = (scalar(keys %newtags) + scalar(@deltags)) ? 1 : 0;
-my ($template, $loggedinuser, $cookie) = get_template_and_user({
- template_name => "opac-tags.tmpl",
- query => $query,
- type => "opac",
- authnotrequired => ($add_op ? 0 : 1), # auth required to add tags
- debug => 1,
-});
+my ($template, $loggedinuser, $cookie);
+if ($is_ajax) {
+ $loggedinuser = C4::Context->userenv->{'number'}; # must occur AFTER auth
+ $debug and print STDERR "op: $loggedinuser\n";
+} else {
+ ($template, $loggedinuser, $cookie) = get_template_and_user({
+ template_name => "opac-tags.tmpl",
+ query => $query,
+ type => "opac",
+ authnotrequired => ($add_op ? 0 : 1), # auth required to add tags
+ debug => 1,
+ });
+}
if ($add_op) {
unless ($loggedinuser) {
@@ -111,6 +137,7 @@ if (scalar @newtags_keys) {
if ($result) {
$counts{$biblionumber}++;
} else {
+ push @errors, {failed_add_tag=>$clean_tag};
warn "add_tag($biblionumber,$clean_tag,$loggedinuser...) returned bad result ($result)";
}
}
@@ -125,6 +152,23 @@ foreach (@deltags) {
}
}
+if ($is_ajax) {
+ my $sum = 0;
+ foreach (values %counts) {$sum += $_;}
+ my $js_reply = sprintf("response = {\n\tadded: %d,\n\tdeleted: %d,\n\terrors: %d,",$sum,$dels,scalar @errors);
+ my $err_string = '';
+ if (scalar @errors) {
+ $err_string = "\n\talerts: ["; # open response_function
+ foreach (@errors) {
+ my $key = (keys %$_)[0];
+ $err_string .= "\n\t\t KOHA.Tags.tag_message.$key(\"" . $_->{$key} . '"),';
+ }
+ $err_string .= "\n\t],\n"; # close response_function
+ }
+ output_ajax_with_http_headers($query, "$js_reply\n$err_string};");
+ exit;
+}
+
my $results = [];
my $my_tags = [];
@@ -172,4 +216,34 @@ if ($add_op) {
(scalar @$my_tags) and $template->param(MY_TAGS => $my_tags);
output_html_with_http_headers $query, $cookie, $template->output;
+__END__
+
+=head1 EXAMPLE AJAX POST PARAMETERS
+
+CGISESSID 7c6288263107beb320f70f78fd767f56
+newtag396 fire,+<a+href="foobar.html">foobar</a>,+<img+src="foo.jpg"+/>
+
+So this request is trying to add 3 tags to biblio #396. The CGISESSID is the same as that the browser would
+typically communicate using cookies. If it is valid, the server will split the value of "newtag396" and
+process the components for addition. In this case the intended tags are:
+ fire
+ <a+href="foobar.html">foobar</a>
+ <img src="foo.jpg" />
+
+The first tag is acceptable. The second will be scrubbed of markup, resulting in the tag "foobar".
+The third tag is all markup, and will be rejected.
+
+=head1 EXAMPLE AJAX JSON response
+
+response = {
+ added: 2,
+ deleted: 0,
+ errors: 2,
+ alerts: [
+ KOHA.Tags.tag_message.scrubbed("foobar"),
+ KOHA.Tags.tag_message.scrubbed_all_bad("1"),
+ ],
+};
+
+=cut
--
1.5.5.GIT
More information about the Koha-patches
mailing list