2 // copyright Sébastien Lucas
\r
3 // https://github.com/seblucas/cops
\r
5 var templatePage, templateBookDetail, templateMain, currentData, before, filterList;
\r
7 var cache = new LRUCache(30);
\r
10 var isPushStateEnabled = window.history && window.history.pushState && window.history.replaceState &&
\r
11 // pushState isn't reliable on iOS until 5.
\r
12 !navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/);
\r
14 function debug_log(text) {
\r
20 function updateCookie (id) {
\r
21 if($(id).prop('pattern') && !$(id).val().match(new RegExp ($(id).prop('pattern')))) {
\r
24 var name = $(id).attr('id');
\r
25 var value = $(id).val ();
\r
26 $.cookie(name, value, { expires: 365 });
\r
29 function updateCookieFromCheckbox (id) {
\r
30 var name = $(id).attr('id');
\r
31 if ((/^style/).test (name)) {
\r
34 if ($(id).is(":checked"))
\r
36 if ($(id).is(':radio')) {
\r
37 $.cookie(name, $(id).val (), { expires: 365 });
\r
39 $.cookie(name, '1', { expires: 365 });
\r
44 $.cookie(name, '0', { expires: 365 });
\r
48 function elapsed () {
\r
49 var elapsedTime = new Date () - before;
\r
50 return "Elapsed : " + elapsedTime;
\r
53 function retourMail(data, textStatus, jqXHR ) {
\r
54 $("#mailButton :first-child").removeClass ("icon-spinner icon-spin").addClass ("icon-envelope");
\r
58 function sendToMailAddress (component, dataid) {
\r
59 var email = $.cookie ('email');
\r
60 if (!$.cookie ('email')) {
\r
61 email = window.prompt (currentData.const.i18n.customizeEmail, "");
\r
62 $.cookie ('email', email, { expires: 365 });
\r
64 var url = 'sendtomail.php';
\r
65 $("#mailButton :first-child").removeClass ("icon-envelope").addClass ("icon-spinner icon-spin");
\r
66 $.ajax ({'url': url, 'type': 'post', 'data': { 'data': dataid, 'email': email }, 'success': retourMail});
\r
69 function strformat () {
\r
70 var s = arguments[0];
\r
71 for (var i = 0; i < arguments.length - 1; i++) {
\r
72 var reg = new RegExp("\\{" + i + "\\}", "gm");
\r
73 s = s.replace(reg, arguments[i + 1]);
\r
78 function isDefined(x) {
\r
80 return x !== undefinedVar;
\r
83 function getCurrentOption (option) {
\r
84 if (!$.cookie (option)) {
\r
85 if (currentData && currentData.const && currentData.const.config && currentData.const.config [option]) {
\r
86 return currentData.const.config [option];
\r
89 return $.cookie (option);
\r
92 function htmlEscape(str) {
\r
94 .replace(/&/g, '&')
\r
95 .replace('"', '"')
\r
96 .replace("'", ''')
\r
97 .replace(/</g, '<')
\r
98 .replace(/>/g, '>');
\r
101 /************************************************
\r
102 * All functions needed to filter the book list by tags
\r
103 ************************************************
\r
106 function getTagList () {
\r
108 $(".se").each (function(){
\r
109 if ($(this).parents (".filtered").length > 0) { return; }
\r
110 var taglist = $(this).text();
\r
112 var tagarray = taglist.split (",");
\r
113 for (var i in tagarray) {
\r
114 var tag = tagarray [i].replace(/^\s+/g,'').replace(/\s+$/g,'');
\r
121 function doFilter () {
\r
122 $(".books").removeClass("filtered");
\r
123 if (jQuery.isEmptyObject(filterList)) {
\r
128 $(".se").each (function(){
\r
129 var taglist = ", " + $(this).text() + ", ";
\r
130 var toBeFiltered = false;
\r
131 for (var filter in filterList) {
\r
132 var onlyThisTag = filterList [filter];
\r
133 filter = ', ' + filter + ', ';
\r
134 var myreg = new RegExp (filter);
\r
135 if (myreg.test (taglist)) {
\r
136 if (onlyThisTag === false) {
\r
137 toBeFiltered = true;
\r
140 if (onlyThisTag === true) {
\r
141 toBeFiltered = true;
\r
145 if (toBeFiltered) { $(this).parents (".books").addClass ("filtered"); }
\r
150 function updateFilters () {
\r
151 var tagList = getTagList ();
\r
153 // If there is already some filters then let's prepare to update the list
\r
154 $("#filter ul li").each (function () {
\r
155 var text = $(this).text ();
\r
156 if (isDefined (tagList [text]) || $(this).attr ('class')) {
\r
157 tagList [text] = 0;
\r
159 tagList [text] = -1;
\r
163 // Update the filter -1 to remove, 1 to add, 0 already there
\r
164 for (var tag in tagList) {
\r
165 var tagValue = tagList [tag];
\r
166 if (tagValue === -1) {
\r
167 $("#filter ul li:contains('" + tag + "')").remove();
\r
169 if (tagValue === 1) {
\r
170 $("#filter ul").append ("<li>" + tag + "</li>");
\r
174 $("#filter ul").append ("<li> СБРОСИТЬ </li>");
\r
176 // Sort the list alphabetically
\r
177 $('#filter ul li').sortElements(function(a, b){
\r
178 return $(a).text() > $(b).text() ? 1 : -1;
\r
182 function handleFilterEvents () {
\r
183 $("#filter ul").on ("click", "li", function(){
\r
184 var filter = $(this).text ();
\r
185 if (filter === " СБРОСИТЬ ") {
\r
187 $("#filter ul li").removeClass ("filter-exclude");
\r
188 $("#filter ul li").removeClass ("filter-include");
\r
192 switch ($(this).attr("class")) {
\r
193 case "filter-include" :
\r
194 $(this).attr("class", "filter-exclude");
\r
195 filterList [filter] = false;
\r
197 case "filter-exclude" :
\r
198 $(this).removeClass ("filter-exclude");
\r
199 delete filterList [filter];
\r
202 $(this).attr("class", "filter-include");
\r
203 filterList [filter] = true;
\r
210 /************************************************
\r
211 * Functions to handle Ajax navigation
\r
212 ************************************************
\r
215 function navigateTo (url) {
\r
216 before = new Date ();
\r
217 var jsonurl = url.replace ("index", "getJSON");
\r
218 var cachedData = cache.get (jsonurl);
\r
220 history.pushState(jsonurl, "", url);
\r
221 updatePage (cachedData);
\r
223 $.getJSON(jsonurl, function(data) {
\r
224 history.pushState(jsonurl, "", url);
\r
225 cache.put (jsonurl, data);
\r
231 function updatePage (data) {
\r
234 data ["const"] = currentData ["const"];
\r
235 if ($("section").length && currentData.isPaginated === 0 && data.isPaginated === 0) {
\r
236 // Partial update (for now disabled)
\r
237 debug_log ("Partial update");
\r
238 debug_log(templateMain);
\r
239 result = templateMain (data);
\r
240 debug_log ("Result: ");
\r
241 debug_log (result);
\r
242 $("h1").html (data.title);
\r
243 $("section").html (result);
\r
246 result = templatePage (data);
\r
247 $("body").html (result);
\r
249 document.title = data.title;
\r
250 currentData = data;
\r
252 debug_log (elapsed ());
\r
254 if ($.cookie('toolbar') === '1') { $("#tool").show (); }
\r
255 if (currentData.containsBook === 1) {
\r
256 $("#sortForm").show ();
\r
257 if (getCurrentOption ("html_tag_filter") === "1") {
\r
258 $("#filter ul").empty ();
\r
260 handleFilterEvents ();
\r
263 $("#sortForm").hide ();
\r
267 function handleLinks () {
\r
268 $("body").on ("click", "a[href^='index']", link_Clicked);
\r
269 $("body").on ("submit", "#searchForm", search_Submitted);
\r
270 $("body").on ("click", "#sort", function(){
\r
271 $('.books').sortElements(function(a, b){
\r
273 if ($("#sortorder").val() === "desc")
\r
277 return $(a).find ("." + $("#sortchoice").val()).text() > $(b).find ("." + $("#sortchoice").val()).text() ? test : -test;
\r
281 $("body").on ("click", ".headright", function(){
\r
282 if ($("#tool").is(":hidden")) {
\r
283 $("#tool").slideDown("slow");
\r
284 $.cookie('toolbar', '1', { expires: 365 });
\r
286 $("#tool").slideUp();
\r
287 $.removeCookie('toolbar');
\r
290 $("body").magnificPopup({
\r
291 delegate: '.fancycover', // child items selector, by clicking on it popup will open
\r
293 gallery:{enabled:true, preload: [0,2]},
\r
294 disableOn: function() {
\r
295 if( getCurrentOption ("use_fancyapps") === "1" ) {
\r
303 function link_Clicked (event) {
\r
304 var currentLink = $(this);
\r
305 debug_log("Link clicked");
\r
306 if (!isPushStateEnabled ||
\r
307 currentData.page === "OPTS") {
\r
310 event.preventDefault();
\r
311 var url = currentLink.attr('href');
\r
313 if ($(".mfp-ready").length)
\r
315 $.magnificPopup.close();
\r
318 // The bookdetail / about should be displayed in a lightbox
\r
319 if (getCurrentOption ("use_fancyapps") === "1" &&
\r
320 (currentLink.hasClass ("fancydetail") || currentLink.hasClass ("fancyabout"))) {
\r
321 debug_log('Lighhtbox mode on');
\r
322 before = new Date ();
\r
323 var jsonurl = url.replace ("index", "getJSON");
\r
324 $.getJSON(jsonurl, function(data) {
\r
325 data ["const"] = currentData ["const"];
\r
327 if (data.page === "ABOUT") {
\r
328 detail = data.fullhtml;
\r
330 detail = templateBookDetail (data);
\r
332 $.magnificPopup.open({
\r
338 debug_log (elapsed ());
\r
345 function search_Submitted (event) {
\r
346 if (!isPushStateEnabled ||
\r
347 currentData.page === "OPTS") {
\r
350 event.preventDefault();
\r
351 var url = strformat ("index.php?page=OPENQ¤t={0}&query={1}", currentData.page, $("input[name=query]").val ());
\r
355 window.onpopstate = function(event) {
\r
356 before = new Date ();
\r
357 var data = cache.get (event.state);
\r
361 $(document).keydown(function(e){
\r
362 if (e.keyCode === 37 && $("#prevLink").length > 0) {
\r
363 navigateTo ($("#prevLink").attr('href'));
\r
365 if (e.keyCode === 39 && $("#nextLink").length > 0) {
\r
366 navigateTo ($("#nextLink").attr('href'));
\r