Show More
@@ -0,0 +1,7 b'' | |||||
|
1 | /* | |||
|
2 | * jQuery Form Plugin; v20131228 | |||
|
3 | * http://jquery.malsup.com/form/ | |||
|
4 | * Copyright (c) 2013 M. Alsup; Dual licensed: MIT/GPL | |||
|
5 | * https://github.com/malsup/form#copyright-and-license | |||
|
6 | */ | |||
|
7 | ;!function(a){"use strict";"function"==typeof define&&define.amd?define(["jquery"],a):a("undefined"!=typeof jQuery?jQuery:window.Zepto)}(function(a){"use strict";function b(b){var c=b.data;b.isDefaultPrevented()||(b.preventDefault(),a(b.target).ajaxSubmit(c))}function c(b){var c=b.target,d=a(c);if(!d.is("[type=submit],[type=image]")){var e=d.closest("[type=submit]");if(0===e.length)return;c=e[0]}var f=this;if(f.clk=c,"image"==c.type)if(void 0!==b.offsetX)f.clk_x=b.offsetX,f.clk_y=b.offsetY;else if("function"==typeof a.fn.offset){var g=d.offset();f.clk_x=b.pageX-g.left,f.clk_y=b.pageY-g.top}else f.clk_x=b.pageX-c.offsetLeft,f.clk_y=b.pageY-c.offsetTop;setTimeout(function(){f.clk=f.clk_x=f.clk_y=null},100)}function d(){if(a.fn.ajaxSubmit.debug){var b="[jquery.form] "+Array.prototype.join.call(arguments,"");window.console&&window.console.log?window.console.log(b):window.opera&&window.opera.postError&&window.opera.postError(b)}}var e={};e.fileapi=void 0!==a("<input type='file'/>").get(0).files,e.formdata=void 0!==window.FormData;var f=!!a.fn.prop;a.fn.attr2=function(){if(!f)return this.attr.apply(this,arguments);var a=this.prop.apply(this,arguments);return a&&a.jquery||"string"==typeof a?a:this.attr.apply(this,arguments)},a.fn.ajaxSubmit=function(b){function c(c){var d,e,f=a.param(c,b.traditional).split("&"),g=f.length,h=[];for(d=0;g>d;d++)f[d]=f[d].replace(/\+/g," "),e=f[d].split("="),h.push([decodeURIComponent(e[0]),decodeURIComponent(e[1])]);return h}function g(d){for(var e=new FormData,f=0;f<d.length;f++)e.append(d[f].name,d[f].value);if(b.extraData){var g=c(b.extraData);for(f=0;f<g.length;f++)g[f]&&e.append(g[f][0],g[f][1])}b.data=null;var h=a.extend(!0,{},a.ajaxSettings,b,{contentType:!1,processData:!1,cache:!1,type:i||"POST"});b.uploadProgress&&(h.xhr=function(){var c=a.ajaxSettings.xhr();return c.upload&&c.upload.addEventListener("progress",function(a){var c=0,d=a.loaded||a.position,e=a.total;a.lengthComputable&&(c=Math.ceil(d/e*100)),b.uploadProgress(a,d,e,c)},!1),c}),h.data=null;var j=h.beforeSend;return h.beforeSend=function(a,c){c.data=b.formData?b.formData:e,j&&j.call(this,a,c)},a.ajax(h)}function h(c){function e(a){var b=null;try{a.contentWindow&&(b=a.contentWindow.document)}catch(c){d("cannot get iframe.contentWindow document: "+c)}if(b)return b;try{b=a.contentDocument?a.contentDocument:a.document}catch(c){d("cannot get iframe.contentDocument: "+c),b=a.document}return b}function g(){function b(){try{var a=e(r).readyState;d("state = "+a),a&&"uninitialized"==a.toLowerCase()&&setTimeout(b,50)}catch(c){d("Server abort: ",c," (",c.name,")"),h(A),w&&clearTimeout(w),w=void 0}}var c=l.attr2("target"),f=l.attr2("action"),g="multipart/form-data",j=l.attr("enctype")||l.attr("encoding")||g;x.setAttribute("target",o),(!i||/post/i.test(i))&&x.setAttribute("method","POST"),f!=m.url&&x.setAttribute("action",m.url),m.skipEncodingOverride||i&&!/post/i.test(i)||l.attr({encoding:"multipart/form-data",enctype:"multipart/form-data"}),m.timeout&&(w=setTimeout(function(){v=!0,h(z)},m.timeout));var k=[];try{if(m.extraData)for(var n in m.extraData)m.extraData.hasOwnProperty(n)&&(a.isPlainObject(m.extraData[n])&&m.extraData[n].hasOwnProperty("name")&&m.extraData[n].hasOwnProperty("value")?k.push(a('<input type="hidden" name="'+m.extraData[n].name+'">').val(m.extraData[n].value).appendTo(x)[0]):k.push(a('<input type="hidden" name="'+n+'">').val(m.extraData[n]).appendTo(x)[0]));m.iframeTarget||q.appendTo("body"),r.attachEvent?r.attachEvent("onload",h):r.addEventListener("load",h,!1),setTimeout(b,15);try{x.submit()}catch(p){var s=document.createElement("form").submit;s.apply(x)}}finally{x.setAttribute("action",f),x.setAttribute("enctype",j),c?x.setAttribute("target",c):l.removeAttr("target"),a(k).remove()}}function h(b){if(!s.aborted&&!F){if(E=e(r),E||(d("cannot access response document"),b=A),b===z&&s)return s.abort("timeout"),y.reject(s,"timeout"),void 0;if(b==A&&s)return s.abort("server abort"),y.reject(s,"error","server abort"),void 0;if(E&&E.location.href!=m.iframeSrc||v){r.detachEvent?r.detachEvent("onload",h):r.removeEventListener("load",h,!1);var c,f="success";try{if(v)throw"timeout";var g="xml"==m.dataType||E.XMLDocument||a.isXMLDoc(E);if(d("isXml="+g),!g&&window.opera&&(null===E.body||!E.body.innerHTML)&&--G)return d("requeing onLoad callback, DOM not available"),setTimeout(h,250),void 0;var i=E.body?E.body:E.documentElement;s.responseText=i?i.innerHTML:null,s.responseXML=E.XMLDocument?E.XMLDocument:E,g&&(m.dataType="xml"),s.getResponseHeader=function(a){var b={"content-type":m.dataType};return b[a.toLowerCase()]},i&&(s.status=Number(i.getAttribute("status"))||s.status,s.statusText=i.getAttribute("statusText")||s.statusText);var j=(m.dataType||"").toLowerCase(),k=/(json|script|text)/.test(j);if(k||m.textarea){var l=E.getElementsByTagName("textarea")[0];if(l)s.responseText=l.value,s.status=Number(l.getAttribute("status"))||s.status,s.statusText=l.getAttribute("statusText")||s.statusText;else if(k){var o=E.getElementsByTagName("pre")[0],p=E.getElementsByTagName("body")[0];o?s.responseText=o.textContent?o.textContent:o.innerText:p&&(s.responseText=p.textContent?p.textContent:p.innerText)}}else"xml"==j&&!s.responseXML&&s.responseText&&(s.responseXML=H(s.responseText));try{D=J(s,j,m)}catch(t){f="parsererror",s.error=c=t||f}}catch(t){d("error caught: ",t),f="error",s.error=c=t||f}s.aborted&&(d("upload aborted"),f=null),s.status&&(f=s.status>=200&&s.status<300||304===s.status?"success":"error"),"success"===f?(m.success&&m.success.call(m.context,D,"success",s),y.resolve(s.responseText,"success",s),n&&a.event.trigger("ajaxSuccess",[s,m])):f&&(void 0===c&&(c=s.statusText),m.error&&m.error.call(m.context,s,f,c),y.reject(s,"error",c),n&&a.event.trigger("ajaxError",[s,m,c])),n&&a.event.trigger("ajaxComplete",[s,m]),n&&!--a.active&&a.event.trigger("ajaxStop"),m.complete&&m.complete.call(m.context,s,f),F=!0,m.timeout&&clearTimeout(w),setTimeout(function(){m.iframeTarget?q.attr("src",m.iframeSrc):q.remove(),s.responseXML=null},100)}}}var j,k,m,n,o,q,r,s,t,u,v,w,x=l[0],y=a.Deferred();if(y.abort=function(a){s.abort(a)},c)for(k=0;k<p.length;k++)j=a(p[k]),f?j.prop("disabled",!1):j.removeAttr("disabled");if(m=a.extend(!0,{},a.ajaxSettings,b),m.context=m.context||m,o="jqFormIO"+(new Date).getTime(),m.iframeTarget?(q=a(m.iframeTarget),u=q.attr2("name"),u?o=u:q.attr2("name",o)):(q=a('<iframe name="'+o+'" src="'+m.iframeSrc+'" />'),q.css({position:"absolute",top:"-1000px",left:"-1000px"})),r=q[0],s={aborted:0,responseText:null,responseXML:null,status:0,statusText:"n/a",getAllResponseHeaders:function(){},getResponseHeader:function(){},setRequestHeader:function(){},abort:function(b){var c="timeout"===b?"timeout":"aborted";d("aborting upload... "+c),this.aborted=1;try{r.contentWindow.document.execCommand&&r.contentWindow.document.execCommand("Stop")}catch(e){}q.attr("src",m.iframeSrc),s.error=c,m.error&&m.error.call(m.context,s,c,b),n&&a.event.trigger("ajaxError",[s,m,c]),m.complete&&m.complete.call(m.context,s,c)}},n=m.global,n&&0===a.active++&&a.event.trigger("ajaxStart"),n&&a.event.trigger("ajaxSend",[s,m]),m.beforeSend&&m.beforeSend.call(m.context,s,m)===!1)return m.global&&a.active--,y.reject(),y;if(s.aborted)return y.reject(),y;t=x.clk,t&&(u=t.name,u&&!t.disabled&&(m.extraData=m.extraData||{},m.extraData[u]=t.value,"image"==t.type&&(m.extraData[u+".x"]=x.clk_x,m.extraData[u+".y"]=x.clk_y)));var z=1,A=2,B=a("meta[name=csrf-token]").attr("content"),C=a("meta[name=csrf-param]").attr("content");C&&B&&(m.extraData=m.extraData||{},m.extraData[C]=B),m.forceSync?g():setTimeout(g,10);var D,E,F,G=50,H=a.parseXML||function(a,b){return window.ActiveXObject?(b=new ActiveXObject("Microsoft.XMLDOM"),b.async="false",b.loadXML(a)):b=(new DOMParser).parseFromString(a,"text/xml"),b&&b.documentElement&&"parsererror"!=b.documentElement.nodeName?b:null},I=a.parseJSON||function(a){return window.eval("("+a+")")},J=function(b,c,d){var e=b.getResponseHeader("content-type")||"",f="xml"===c||!c&&e.indexOf("xml")>=0,g=f?b.responseXML:b.responseText;return f&&"parsererror"===g.documentElement.nodeName&&a.error&&a.error("parsererror"),d&&d.dataFilter&&(g=d.dataFilter(g,c)),"string"==typeof g&&("json"===c||!c&&e.indexOf("json")>=0?g=I(g):("script"===c||!c&&e.indexOf("javascript")>=0)&&a.globalEval(g)),g};return y}if(!this.length)return d("ajaxSubmit: skipping submit process - no element selected"),this;var i,j,k,l=this;"function"==typeof b?b={success:b}:void 0===b&&(b={}),i=b.type||this.attr2("method"),j=b.url||this.attr2("action"),k="string"==typeof j?a.trim(j):"",k=k||window.location.href||"",k&&(k=(k.match(/^([^#]+)/)||[])[1]),b=a.extend(!0,{url:k,success:a.ajaxSettings.success,type:i||a.ajaxSettings.type,iframeSrc:/^https/i.test(window.location.href||"")?"javascript:false":"about:blank"},b);var m={};if(this.trigger("form-pre-serialize",[this,b,m]),m.veto)return d("ajaxSubmit: submit vetoed via form-pre-serialize trigger"),this;if(b.beforeSerialize&&b.beforeSerialize(this,b)===!1)return d("ajaxSubmit: submit aborted via beforeSerialize callback"),this;var n=b.traditional;void 0===n&&(n=a.ajaxSettings.traditional);var o,p=[],q=this.formToArray(b.semantic,p);if(b.data&&(b.extraData=b.data,o=a.param(b.data,n)),b.beforeSubmit&&b.beforeSubmit(q,this,b)===!1)return d("ajaxSubmit: submit aborted via beforeSubmit callback"),this;if(this.trigger("form-submit-validate",[q,this,b,m]),m.veto)return d("ajaxSubmit: submit vetoed via form-submit-validate trigger"),this;var r=a.param(q,n);o&&(r=r?r+"&"+o:o),"GET"==b.type.toUpperCase()?(b.url+=(b.url.indexOf("?")>=0?"&":"?")+r,b.data=null):b.data=r;var s=[];if(b.resetForm&&s.push(function(){l.resetForm()}),b.clearForm&&s.push(function(){l.clearForm(b.includeHidden)}),!b.dataType&&b.target){var t=b.success||function(){};s.push(function(c){var d=b.replaceTarget?"replaceWith":"html";a(b.target)[d](c).each(t,arguments)})}else b.success&&s.push(b.success);if(b.success=function(a,c,d){for(var e=b.context||this,f=0,g=s.length;g>f;f++)s[f].apply(e,[a,c,d||l,l])},b.error){var u=b.error;b.error=function(a,c,d){var e=b.context||this;u.apply(e,[a,c,d,l])}}if(b.complete){var v=b.complete;b.complete=function(a,c){var d=b.context||this;v.apply(d,[a,c,l])}}var w=a("input[type=file]:enabled",this).filter(function(){return""!==a(this).val()}),x=w.length>0,y="multipart/form-data",z=l.attr("enctype")==y||l.attr("encoding")==y,A=e.fileapi&&e.formdata;d("fileAPI :"+A);var B,C=(x||z)&&!A;b.iframe!==!1&&(b.iframe||C)?b.closeKeepAlive?a.get(b.closeKeepAlive,function(){B=h(q)}):B=h(q):B=(x||z)&&A?g(q):a.ajax(b),l.removeData("jqxhr").data("jqxhr",B);for(var D=0;D<p.length;D++)p[D]=null;return this.trigger("form-submit-notify",[this,b]),this},a.fn.ajaxForm=function(e){if(e=e||{},e.delegation=e.delegation&&a.isFunction(a.fn.on),!e.delegation&&0===this.length){var f={s:this.selector,c:this.context};return!a.isReady&&f.s?(d("DOM not ready, queuing ajaxForm"),a(function(){a(f.s,f.c).ajaxForm(e)}),this):(d("terminating; zero elements found by selector"+(a.isReady?"":" (DOM not ready)")),this)}return e.delegation?(a(document).off("submit.form-plugin",this.selector,b).off("click.form-plugin",this.selector,c).on("submit.form-plugin",this.selector,e,b).on("click.form-plugin",this.selector,e,c),this):this.ajaxFormUnbind().bind("submit.form-plugin",e,b).bind("click.form-plugin",e,c)},a.fn.ajaxFormUnbind=function(){return this.unbind("submit.form-plugin click.form-plugin")},a.fn.formToArray=function(b,c){var d=[];if(0===this.length)return d;var f,g=this[0],h=this.attr("id"),i=b?g.getElementsByTagName("*"):g.elements;if(i&&(i=a(i).get()),h&&(f=a(":input[form="+h+"]").get(),f.length&&(i=(i||[]).concat(f))),!i||!i.length)return d;var j,k,l,m,n,o,p;for(j=0,o=i.length;o>j;j++)if(n=i[j],l=n.name,l&&!n.disabled)if(b&&g.clk&&"image"==n.type)g.clk==n&&(d.push({name:l,value:a(n).val(),type:n.type}),d.push({name:l+".x",value:g.clk_x},{name:l+".y",value:g.clk_y}));else if(m=a.fieldValue(n,!0),m&&m.constructor==Array)for(c&&c.push(n),k=0,p=m.length;p>k;k++)d.push({name:l,value:m[k]});else if(e.fileapi&&"file"==n.type){c&&c.push(n);var q=n.files;if(q.length)for(k=0;k<q.length;k++)d.push({name:l,value:q[k],type:n.type});else d.push({name:l,value:"",type:n.type})}else null!==m&&"undefined"!=typeof m&&(c&&c.push(n),d.push({name:l,value:m,type:n.type,required:n.required}));if(!b&&g.clk){var r=a(g.clk),s=r[0];l=s.name,l&&!s.disabled&&"image"==s.type&&(d.push({name:l,value:r.val()}),d.push({name:l+".x",value:g.clk_x},{name:l+".y",value:g.clk_y}))}return d},a.fn.formSerialize=function(b){return a.param(this.formToArray(b))},a.fn.fieldSerialize=function(b){var c=[];return this.each(function(){var d=this.name;if(d){var e=a.fieldValue(this,b);if(e&&e.constructor==Array)for(var f=0,g=e.length;g>f;f++)c.push({name:d,value:e[f]});else null!==e&&"undefined"!=typeof e&&c.push({name:this.name,value:e})}}),a.param(c)},a.fn.fieldValue=function(b){for(var c=[],d=0,e=this.length;e>d;d++){var f=this[d],g=a.fieldValue(f,b);null===g||"undefined"==typeof g||g.constructor==Array&&!g.length||(g.constructor==Array?a.merge(c,g):c.push(g))}return c},a.fieldValue=function(b,c){var d=b.name,e=b.type,f=b.tagName.toLowerCase();if(void 0===c&&(c=!0),c&&(!d||b.disabled||"reset"==e||"button"==e||("checkbox"==e||"radio"==e)&&!b.checked||("submit"==e||"image"==e)&&b.form&&b.form.clk!=b||"select"==f&&-1==b.selectedIndex))return null;if("select"==f){var g=b.selectedIndex;if(0>g)return null;for(var h=[],i=b.options,j="select-one"==e,k=j?g+1:i.length,l=j?g:0;k>l;l++){var m=i[l];if(m.selected){var n=m.value;if(n||(n=m.attributes&&m.attributes.value&&!m.attributes.value.specified?m.text:m.value),j)return n;h.push(n)}}return h}return a(b).val()},a.fn.clearForm=function(b){return this.each(function(){a("input,select,textarea",this).clearFields(b)})},a.fn.clearFields=a.fn.clearInputs=function(b){var c=/^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i;return this.each(function(){var d=this.type,e=this.tagName.toLowerCase();c.test(d)||"textarea"==e?this.value="":"checkbox"==d||"radio"==d?this.checked=!1:"select"==e?this.selectedIndex=-1:"file"==d?/MSIE/.test(navigator.userAgent)?a(this).replaceWith(a(this).clone(!0)):a(this).val(""):b&&(b===!0&&/hidden/.test(d)||"string"==typeof b&&a(this).is(b))&&(this.value="")})},a.fn.resetForm=function(){return this.each(function(){("function"==typeof this.reset||"object"==typeof this.reset&&!this.reset.nodeType)&&this.reset()})},a.fn.enable=function(a){return void 0===a&&(a=!0),this.each(function(){this.disabled=!a})},a.fn.selected=function(b){return void 0===b&&(b=!0),this.each(function(){var c=this.type;if("checkbox"==c||"radio"==c)this.checked=b;else if("option"==this.tagName.toLowerCase()){var d=a(this).parent("select");b&&d[0]&&"select-one"==d[0].type&&d.find("option").selected(!1),this.selected=b}})},a.fn.ajaxSubmit.debug=!1}); No newline at end of file |
@@ -1,242 +1,241 b'' | |||||
1 | /* |
|
1 | /* | |
2 | @licstart The following is the entire license notice for the |
|
2 | @licstart The following is the entire license notice for the | |
3 | JavaScript code in this page. |
|
3 | JavaScript code in this page. | |
4 |
|
4 | |||
5 |
|
5 | |||
6 | Copyright (C) 2013 neko259 |
|
6 | Copyright (C) 2013 neko259 | |
7 |
|
7 | |||
8 | The JavaScript code in this page is free software: you can |
|
8 | The JavaScript code in this page is free software: you can | |
9 | redistribute it and/or modify it under the terms of the GNU |
|
9 | redistribute it and/or modify it under the terms of the GNU | |
10 | General Public License (GNU GPL) as published by the Free Software |
|
10 | General Public License (GNU GPL) as published by the Free Software | |
11 | Foundation, either version 3 of the License, or (at your option) |
|
11 | Foundation, either version 3 of the License, or (at your option) | |
12 | any later version. The code is distributed WITHOUT ANY WARRANTY; |
|
12 | any later version. The code is distributed WITHOUT ANY WARRANTY; | |
13 | without even the implied warranty of MERCHANTABILITY or FITNESS |
|
13 | without even the implied warranty of MERCHANTABILITY or FITNESS | |
14 | FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. |
|
14 | FOR A PARTICULAR PURPOSE. See the GNU GPL for more details. | |
15 |
|
15 | |||
16 | As additional permission under GNU GPL version 3 section 7, you |
|
16 | As additional permission under GNU GPL version 3 section 7, you | |
17 | may distribute non-source (e.g., minimized or compacted) forms of |
|
17 | may distribute non-source (e.g., minimized or compacted) forms of | |
18 | that code without the copy of the GNU GPL normally required by |
|
18 | that code without the copy of the GNU GPL normally required by | |
19 | section 4, provided you include this license notice and a URL |
|
19 | section 4, provided you include this license notice and a URL | |
20 | through which recipients can access the Corresponding Source. |
|
20 | through which recipients can access the Corresponding Source. | |
21 |
|
21 | |||
22 | @licend The above is the entire license notice |
|
22 | @licend The above is the entire license notice | |
23 | for the JavaScript code in this page. |
|
23 | for the JavaScript code in this page. | |
24 | */ |
|
24 | */ | |
25 |
|
25 | |||
26 | var THREAD_UPDATE_DELAY = 10000; |
|
26 | var THREAD_UPDATE_DELAY = 10000; | |
27 |
|
27 | |||
28 | var loading = false; |
|
28 | var loading = false; | |
29 | var lastUpdateTime = null; |
|
29 | var lastUpdateTime = null; | |
30 | var unreadPosts = 0 |
|
30 | var unreadPosts = 0 | |
31 |
|
31 | |||
32 | function blink(node) { |
|
32 | function blink(node) { | |
33 | var blinkCount = 2; |
|
33 | var blinkCount = 2; | |
34 |
|
34 | |||
35 | var nodeToAnimate = node; |
|
35 | var nodeToAnimate = node; | |
36 | for (var i = 0; i < blinkCount; i++) { |
|
36 | for (var i = 0; i < blinkCount; i++) { | |
37 | nodeToAnimate = nodeToAnimate.fadeTo('fast', 0.5).fadeTo('fast', 1.0); |
|
37 | nodeToAnimate = nodeToAnimate.fadeTo('fast', 0.5).fadeTo('fast', 1.0); | |
38 | } |
|
38 | } | |
39 | } |
|
39 | } | |
40 |
|
40 | |||
41 | function updateThread() { |
|
41 | function updateThread() { | |
42 | if (loading) { |
|
42 | if (loading) { | |
43 | return; |
|
43 | return; | |
44 | } |
|
44 | } | |
45 |
|
45 | |||
46 | loading = true; |
|
46 | loading = true; | |
47 |
|
47 | |||
48 | var threadPosts = $('div.thread').children('.post'); |
|
48 | var threadPosts = $('div.thread').children('.post'); | |
49 |
|
49 | |||
50 | var lastPost = threadPosts.last(); |
|
50 | var lastPost = threadPosts.last(); | |
51 | var threadId = threadPosts.first().attr('id'); |
|
51 | var threadId = threadPosts.first().attr('id'); | |
52 |
|
52 | |||
53 | var diffUrl = '/api/diff_thread/' + threadId + '/' + lastUpdateTime + '/'; |
|
53 | var diffUrl = '/api/diff_thread/' + threadId + '/' + lastUpdateTime + '/'; | |
54 | $.getJSON(diffUrl) |
|
54 | $.getJSON(diffUrl) | |
55 | .success(function(data) { |
|
55 | .success(function(data) { | |
56 | var bottom = isPageBottom(); |
|
56 | var bottom = isPageBottom(); | |
57 |
|
57 | |||
58 | var addedPosts = data.added; |
|
58 | var addedPosts = data.added; | |
59 | for (var i = 0; i < addedPosts.length; i++) { |
|
59 | for (var i = 0; i < addedPosts.length; i++) { | |
60 | var postText = addedPosts[i]; |
|
60 | var postText = addedPosts[i]; | |
61 |
|
61 | |||
62 | var post = $(postText); |
|
62 | var post = $(postText); | |
63 | post.appendTo(lastPost.parent()); |
|
63 | post.appendTo(lastPost.parent()); | |
64 | addRefLinkPreview(post[0]); |
|
64 | addRefLinkPreview(post[0]); | |
65 |
|
65 | |||
66 | lastPost = post; |
|
66 | lastPost = post; | |
67 | blink(post); |
|
67 | blink(post); | |
68 | } |
|
68 | } | |
69 |
|
69 | |||
70 | var updatedPosts = data.updated; |
|
70 | var updatedPosts = data.updated; | |
71 | for (var i = 0; i < updatedPosts.length; i++) { |
|
71 | for (var i = 0; i < updatedPosts.length; i++) { | |
72 | var postText = updatedPosts[i]; |
|
72 | var postText = updatedPosts[i]; | |
73 |
|
73 | |||
74 | var post = $(postText); |
|
74 | var post = $(postText); | |
75 | var postId = post.attr('id'); |
|
75 | var postId = post.attr('id'); | |
76 |
|
76 | |||
77 | var oldPost = $('div.thread').children('.post[id=' + postId + ']'); |
|
77 | var oldPost = $('div.thread').children('.post[id=' + postId + ']'); | |
78 |
|
78 | |||
79 | oldPost.replaceWith(post); |
|
79 | oldPost.replaceWith(post); | |
80 | addRefLinkPreview(post[0]); |
|
80 | addRefLinkPreview(post[0]); | |
81 |
|
81 | |||
82 | blink(post); |
|
82 | blink(post); | |
83 | } |
|
83 | } | |
84 |
|
84 | |||
85 | // TODO Process deleted posts |
|
85 | // TODO Process deleted posts | |
86 |
|
86 | |||
87 | lastUpdateTime = data.last_update; |
|
87 | lastUpdateTime = data.last_update; | |
88 | loading = false; |
|
88 | loading = false; | |
89 |
|
89 | |||
90 | if (bottom) { |
|
90 | if (bottom) { | |
91 | var $target = $('html,body'); |
|
91 | var $target = $('html,body'); | |
92 | $target.animate({scrollTop: $target.height()}, 1000); |
|
92 | $target.animate({scrollTop: $target.height()}, 1000); | |
93 | } |
|
93 | } | |
94 |
|
94 | |||
95 | $('#reply-count').text(getReplyCount()); |
|
95 | $('#reply-count').text(getReplyCount()); | |
96 | $('#image-count').text(getImageCount()); |
|
96 | $('#image-count').text(getImageCount()); | |
97 |
|
97 | |||
98 | updateBumplimitProgress(data.added.length); |
|
98 | updateBumplimitProgress(data.added.length); | |
99 | updatePostBumpableStatus(); |
|
99 | updatePostBumpableStatus(); | |
100 |
|
100 | |||
101 | if (data.added.length + data.updated.length > 0) { |
|
101 | if (data.added.length + data.updated.length > 0) { | |
102 | showNewPostsTitle(data.added.length); |
|
102 | showNewPostsTitle(data.added.length); | |
103 | } |
|
103 | } | |
104 | }) |
|
104 | }) | |
105 | .error(function(data) { |
|
105 | .error(function(data) { | |
106 | // TODO Show error message that server is unavailable? |
|
106 | // TODO Show error message that server is unavailable? | |
107 |
|
107 | |||
108 | loading = false; |
|
108 | loading = false; | |
109 | }); |
|
109 | }); | |
110 | } |
|
110 | } | |
111 |
|
111 | |||
112 | function isPageBottom() { |
|
112 | function isPageBottom() { | |
113 | var scroll = $(window).scrollTop() / ($(document).height() |
|
113 | var scroll = $(window).scrollTop() / ($(document).height() | |
114 | - $(window).height()) |
|
114 | - $(window).height()) | |
115 |
|
115 | |||
116 | return scroll == 1 |
|
116 | return scroll == 1 | |
117 | } |
|
117 | } | |
118 |
|
118 | |||
119 | function initAutoupdate() { |
|
119 | function initAutoupdate() { | |
120 | loading = false; |
|
120 | loading = false; | |
121 |
|
121 | |||
122 | lastUpdateTime = $('.metapanel').attr('data-last-update'); |
|
122 | lastUpdateTime = $('.metapanel').attr('data-last-update'); | |
123 |
|
123 | |||
124 | setInterval(updateThread, THREAD_UPDATE_DELAY); |
|
124 | setInterval(updateThread, THREAD_UPDATE_DELAY); | |
125 | } |
|
125 | } | |
126 |
|
126 | |||
127 | function getReplyCount() { |
|
127 | function getReplyCount() { | |
128 | return $('.thread').children('.post').length |
|
128 | return $('.thread').children('.post').length | |
129 | } |
|
129 | } | |
130 |
|
130 | |||
131 | function getImageCount() { |
|
131 | function getImageCount() { | |
132 | return $('.thread').find('img').length |
|
132 | return $('.thread').find('img').length | |
133 | } |
|
133 | } | |
134 |
|
134 | |||
135 | /** |
|
135 | /** | |
136 | * Update bumplimit progress bar |
|
136 | * Update bumplimit progress bar | |
137 | */ |
|
137 | */ | |
138 | function updateBumplimitProgress(postDelta) { |
|
138 | function updateBumplimitProgress(postDelta) { | |
139 | var progressBar = $('#bumplimit_progress'); |
|
139 | var progressBar = $('#bumplimit_progress'); | |
140 | if (progressBar) { |
|
140 | if (progressBar) { | |
141 | var postsToLimitElement = $('#left_to_limit'); |
|
141 | var postsToLimitElement = $('#left_to_limit'); | |
142 |
|
142 | |||
143 | var oldPostsToLimit = parseInt(postsToLimitElement.text()); |
|
143 | var oldPostsToLimit = parseInt(postsToLimitElement.text()); | |
144 | var postCount = getReplyCount(); |
|
144 | var postCount = getReplyCount(); | |
145 | var bumplimit = postCount - postDelta + oldPostsToLimit; |
|
145 | var bumplimit = postCount - postDelta + oldPostsToLimit; | |
146 |
|
146 | |||
147 | var newPostsToLimit = bumplimit - postCount; |
|
147 | var newPostsToLimit = bumplimit - postCount; | |
148 | if (newPostsToLimit <= 0) { |
|
148 | if (newPostsToLimit <= 0) { | |
149 | $('.bar-bg').remove(); |
|
149 | $('.bar-bg').remove(); | |
150 | } else { |
|
150 | } else { | |
151 | postsToLimitElement.text(newPostsToLimit); |
|
151 | postsToLimitElement.text(newPostsToLimit); | |
152 | progressBar.width((100 - postCount / bumplimit * 100.0) + '%'); |
|
152 | progressBar.width((100 - postCount / bumplimit * 100.0) + '%'); | |
153 | } |
|
153 | } | |
154 | } |
|
154 | } | |
155 | } |
|
155 | } | |
156 |
|
156 | |||
157 | /** |
|
157 | /** | |
158 | * If the bumplimit is reached, add dead_post class to all posts |
|
158 | * If the bumplimit is reached, add dead_post class to all posts | |
159 | */ |
|
159 | */ | |
160 | function updatePostBumpableStatus() { |
|
160 | function updatePostBumpableStatus() { | |
161 | var postCount = getReplyCount(); |
|
161 | var postCount = getReplyCount(); | |
162 | var postsToLimitElement = $('#left_to_limit'); |
|
162 | var postsToLimitElement = $('#left_to_limit'); | |
163 | var postsToLimit = parseInt(postsToLimitElement.text()); |
|
163 | var postsToLimit = parseInt(postsToLimitElement.text()); | |
164 |
|
164 | |||
165 | if (postsToLimit <= 0) { |
|
165 | if (postsToLimit <= 0) { | |
166 | $('.thread').find('.post').addClass('dead_post'); |
|
166 | $('.thread').find('.post').addClass('dead_post'); | |
167 | } |
|
167 | } | |
168 | } |
|
168 | } | |
169 |
|
169 | |||
170 | var documentOriginalTitle = ''; |
|
170 | var documentOriginalTitle = ''; | |
171 | /** |
|
171 | /** | |
172 | * Show 'new posts' text in the title if the document is not visible to a user |
|
172 | * Show 'new posts' text in the title if the document is not visible to a user | |
173 | */ |
|
173 | */ | |
174 | function showNewPostsTitle(newPostCount) { |
|
174 | function showNewPostsTitle(newPostCount) { | |
175 | if (document.hidden) { |
|
175 | if (document.hidden) { | |
176 | if (documentOriginalTitle === '') { |
|
176 | if (documentOriginalTitle === '') { | |
177 | documentOriginalTitle = document.title; |
|
177 | documentOriginalTitle = document.title; | |
178 | } |
|
178 | } | |
179 | unreadPosts = unreadPosts + newPostCount; |
|
179 | unreadPosts = unreadPosts + newPostCount; | |
180 | document.title = '[' + unreadPosts + '] ' + documentOriginalTitle; |
|
180 | document.title = '[' + unreadPosts + '] ' + documentOriginalTitle; | |
181 |
|
181 | |||
182 | document.addEventListener('visibilitychange', function() { |
|
182 | document.addEventListener('visibilitychange', function() { | |
183 | if (documentOriginalTitle !== '') { |
|
183 | if (documentOriginalTitle !== '') { | |
184 | document.title = documentOriginalTitle; |
|
184 | document.title = documentOriginalTitle; | |
185 | documentOriginalTitle = ''; |
|
185 | documentOriginalTitle = ''; | |
186 | unreadPosts = 0; |
|
186 | unreadPosts = 0; | |
187 | } |
|
187 | } | |
188 |
|
188 | |||
189 | document.removeEventListener('visibilitychange', null); |
|
189 | document.removeEventListener('visibilitychange', null); | |
190 | }); |
|
190 | }); | |
191 | } |
|
191 | } | |
192 | } |
|
192 | } | |
193 |
|
193 | |||
194 | /** |
|
194 | /** | |
195 | * Clear all entered values in the form fields |
|
195 | * Clear all entered values in the form fields | |
196 | */ |
|
196 | */ | |
197 | function resetForm(form) { |
|
197 | function resetForm(form) { | |
198 | form.find('input:text, input:password, input:file, select, textarea').val(''); |
|
198 | form.find('input:text, input:password, input:file, select, textarea').val(''); | |
199 | form.find('input:radio, input:checkbox') |
|
199 | form.find('input:radio, input:checkbox') | |
200 | .removeAttr('checked').removeAttr('selected'); |
|
200 | .removeAttr('checked').removeAttr('selected'); | |
201 | } |
|
201 | } | |
202 |
|
202 | |||
203 | // Post form data over AJAX |
|
|||
204 | $("form").submit(function(e){ |
|
|||
205 | var threadId = $('div.thread').children('.post').first().attr('id');; |
|
|||
206 |
|
||||
207 | var form = $(this); |
|
|||
208 | $.ajax({ |
|
|||
209 | url : '/api/add_post/' + threadId + '/', |
|
|||
210 | type : form.attr('method'), |
|
|||
211 | data : form.serialize(), |
|
|||
212 | success: function(response){ |
|
|||
213 | var json = $.parseJSON(response); |
|
|||
214 | var status = json.status; |
|
|||
215 |
|
||||
216 | var form = $('#form'); |
|
|||
217 | form.children('.form-errors').remove(); |
|
|||
218 |
|
||||
219 | if (status === 'ok') { |
|
|||
220 | resetForm(form); |
|
|||
221 | updateThread(); |
|
|||
222 | } else { |
|
|||
223 | var errors = json.errors; |
|
|||
224 | for (var i = 0; i < errors.length; i++) { |
|
|||
225 | var error = errors[i]; |
|
|||
226 |
|
||||
227 | var fieldName = error.field; |
|
|||
228 | var error = error.errors; |
|
|||
229 |
|
||||
230 | var errorList = $('<div class="form-errors">' + error |
|
|||
231 | + '<div>'); |
|
|||
232 | errorList.appendTo(form); |
|
|||
233 | } |
|
|||
234 | } |
|
|||
235 | } |
|
|||
236 | }); |
|
|||
237 | return false; |
|
|||
238 | }); |
|
|||
239 |
|
203 | |||
240 | $(document).ready(function(){ |
|
204 | $(document).ready(function(){ | |
241 | initAutoupdate(); |
|
205 | initAutoupdate(); | |
|
206 | ||||
|
207 | // Post form data over AJAX | |||
|
208 | var threadId = $('div.thread').children('.post').first().attr('id');; | |||
|
209 | ||||
|
210 | var form = $('#form'); | |||
|
211 | var options = { | |||
|
212 | success: updateOnPost, | |||
|
213 | url: '/api/add_post/' + threadId + '/', | |||
|
214 | }; | |||
|
215 | ||||
|
216 | form.ajaxForm(options); | |||
|
217 | ||||
|
218 | function updateOnPost(response, statusText, xhr, $form) { | |||
|
219 | var json = $.parseJSON(response); | |||
|
220 | var status = json.status; | |||
|
221 | ||||
|
222 | form.children('.form-errors').remove(); | |||
|
223 | ||||
|
224 | if (status === 'ok') { | |||
|
225 | resetForm(form); | |||
|
226 | updateThread(); | |||
|
227 | } else { | |||
|
228 | var errors = json.errors; | |||
|
229 | for (var i = 0; i < errors.length; i++) { | |||
|
230 | var error = errors[i]; | |||
|
231 | ||||
|
232 | var fieldName = error.field; | |||
|
233 | var error = error.errors; | |||
|
234 | ||||
|
235 | var errorList = $('<div class="form-errors">' + error | |||
|
236 | + '<div>'); | |||
|
237 | errorList.appendTo(form); | |||
|
238 | } | |||
|
239 | } | |||
|
240 | } | |||
242 | }); |
|
241 | }); |
@@ -1,144 +1,145 b'' | |||||
1 | {% extends "boards/base.html" %} |
|
1 | {% extends "boards/base.html" %} | |
2 |
|
2 | |||
3 | {% load i18n %} |
|
3 | {% load i18n %} | |
4 | {% load cache %} |
|
4 | {% load cache %} | |
5 | {% load static from staticfiles %} |
|
5 | {% load static from staticfiles %} | |
6 | {% load board %} |
|
6 | {% load board %} | |
7 |
|
7 | |||
8 | {% block head %} |
|
8 | {% block head %} | |
9 | <title>{{ thread.get_opening_post.get_title|striptags|truncatewords:10 }} - Neboard</title> |
|
9 | <title>{{ thread.get_opening_post.get_title|striptags|truncatewords:10 }} - Neboard</title> | |
10 | {% endblock %} |
|
10 | {% endblock %} | |
11 |
|
11 | |||
12 | {% block content %} |
|
12 | {% block content %} | |
13 | {% spaceless %} |
|
13 | {% spaceless %} | |
14 | {% get_current_language as LANGUAGE_CODE %} |
|
14 | {% get_current_language as LANGUAGE_CODE %} | |
15 |
|
15 | |||
16 | {% cache 600 thread_view thread.id thread.last_edit_time moderator LANGUAGE_CODE %} |
|
16 | {% cache 600 thread_view thread.id thread.last_edit_time moderator LANGUAGE_CODE %} | |
17 |
|
17 | |||
18 | <div class="image-mode-tab"> |
|
18 | <div class="image-mode-tab"> | |
19 | <a class="current_mode" href="{% url 'thread' thread.get_opening_post.id %}">{% trans 'Normal mode' %}</a>, |
|
19 | <a class="current_mode" href="{% url 'thread' thread.get_opening_post.id %}">{% trans 'Normal mode' %}</a>, | |
20 | <a href="{% url 'thread_mode' thread.get_opening_post.id 'gallery' %}">{% trans 'Gallery mode' %}</a> |
|
20 | <a href="{% url 'thread_mode' thread.get_opening_post.id 'gallery' %}">{% trans 'Gallery mode' %}</a> | |
21 | </div> |
|
21 | </div> | |
22 |
|
22 | |||
23 | {% if bumpable %} |
|
23 | {% if bumpable %} | |
24 | <div class="bar-bg"> |
|
24 | <div class="bar-bg"> | |
25 | <div class="bar-value" style="width:{{ bumplimit_progress }}%" id="bumplimit_progress"> |
|
25 | <div class="bar-value" style="width:{{ bumplimit_progress }}%" id="bumplimit_progress"> | |
26 | </div> |
|
26 | </div> | |
27 | <div class="bar-text"> |
|
27 | <div class="bar-text"> | |
28 | <span id="left_to_limit">{{ posts_left }}</span> {% trans 'posts to bumplimit' %} |
|
28 | <span id="left_to_limit">{{ posts_left }}</span> {% trans 'posts to bumplimit' %} | |
29 | </div> |
|
29 | </div> | |
30 | </div> |
|
30 | </div> | |
31 | {% endif %} |
|
31 | {% endif %} | |
32 | <div class="thread"> |
|
32 | <div class="thread"> | |
33 | {% for post in posts %} |
|
33 | {% for post in posts %} | |
34 | {% if bumpable %} |
|
34 | {% if bumpable %} | |
35 | <div class="post" id="{{ post.id }}"> |
|
35 | <div class="post" id="{{ post.id }}"> | |
36 | {% elif thread.archived %} |
|
36 | {% elif thread.archived %} | |
37 | <div class="post archive_post" id="{{ post.id }}"> |
|
37 | <div class="post archive_post" id="{{ post.id }}"> | |
38 | {% else %} |
|
38 | {% else %} | |
39 | <div class="post dead_post" id="{{ post.id }}"> |
|
39 | <div class="post dead_post" id="{{ post.id }}"> | |
40 | {% endif %} |
|
40 | {% endif %} | |
41 | {% if post.image %} |
|
41 | {% if post.image %} | |
42 | <div class="image"> |
|
42 | <div class="image"> | |
43 | <a |
|
43 | <a | |
44 | class="thumb" |
|
44 | class="thumb" | |
45 | href="{{ post.image.url }}"><img |
|
45 | href="{{ post.image.url }}"><img | |
46 | src="{{ post.image.url_200x150 }}" |
|
46 | src="{{ post.image.url_200x150 }}" | |
47 | alt="{{ post.id }}" |
|
47 | alt="{{ post.id }}" | |
48 | width="{{ post.image_pre_width }}" |
|
48 | width="{{ post.image_pre_width }}" | |
49 | height="{{ post.image_pre_height }}" |
|
49 | height="{{ post.image_pre_height }}" | |
50 | data-width="{{ post.image_width }}" |
|
50 | data-width="{{ post.image_width }}" | |
51 | data-height="{{ post.image_height }}"/> |
|
51 | data-height="{{ post.image_height }}"/> | |
52 | </a> |
|
52 | </a> | |
53 | </div> |
|
53 | </div> | |
54 | {% endif %} |
|
54 | {% endif %} | |
55 | <div class="message"> |
|
55 | <div class="message"> | |
56 | <div class="post-info"> |
|
56 | <div class="post-info"> | |
57 | <span class="title">{{ post.title }}</span> |
|
57 | <span class="title">{{ post.title }}</span> | |
58 | <a class="post_id" href="#{{ post.id }}"> |
|
58 | <a class="post_id" href="#{{ post.id }}"> | |
59 | ({{ post.id }})</a> |
|
59 | ({{ post.id }})</a> | |
60 | [{{ post.pub_time }}] |
|
60 | [{{ post.pub_time }}] | |
61 | {% if not thread.archived %} |
|
61 | {% if not thread.archived %} | |
62 | [<a href="#" onclick="javascript:addQuickReply('{{ post.id }}') |
|
62 | [<a href="#" onclick="javascript:addQuickReply('{{ post.id }}') | |
63 | ; return false;">>></a>] |
|
63 | ; return false;">>></a>] | |
64 | {% endif %} |
|
64 | {% endif %} | |
65 |
|
65 | |||
66 | {% if moderator %} |
|
66 | {% if moderator %} | |
67 | <span class="moderator_info"> |
|
67 | <span class="moderator_info"> | |
68 | [<a href="{% url 'delete' post_id=post.id %}" |
|
68 | [<a href="{% url 'delete' post_id=post.id %}" | |
69 | >{% trans 'Delete' %}</a>] |
|
69 | >{% trans 'Delete' %}</a>] | |
70 | ({{ post.poster_ip }}) |
|
70 | ({{ post.poster_ip }}) | |
71 | [<a href="{% url 'ban' post_id=post.id %}?next={{ request.path }}" |
|
71 | [<a href="{% url 'ban' post_id=post.id %}?next={{ request.path }}" | |
72 | >{% trans 'Ban IP' %}</a>] |
|
72 | >{% trans 'Ban IP' %}</a>] | |
73 | </span> |
|
73 | </span> | |
74 | {% endif %} |
|
74 | {% endif %} | |
75 | </div> |
|
75 | </div> | |
76 | {% autoescape off %} |
|
76 | {% autoescape off %} | |
77 | {{ post.text.rendered }} |
|
77 | {{ post.text.rendered }} | |
78 | {% endautoescape %} |
|
78 | {% endautoescape %} | |
79 | {% if post.is_referenced %} |
|
79 | {% if post.is_referenced %} | |
80 | <div class="refmap"> |
|
80 | <div class="refmap"> | |
81 | {% trans "Replies" %}: |
|
81 | {% trans "Replies" %}: | |
82 | {% for ref_post in post.get_sorted_referenced_posts %} |
|
82 | {% for ref_post in post.get_sorted_referenced_posts %} | |
83 | <a href="{% post_url ref_post.id %}">>>{{ ref_post.id }}</a |
|
83 | <a href="{% post_url ref_post.id %}">>>{{ ref_post.id }}</a | |
84 | >{% if not forloop.last %},{% endif %} |
|
84 | >{% if not forloop.last %},{% endif %} | |
85 | {% endfor %} |
|
85 | {% endfor %} | |
86 | </div> |
|
86 | </div> | |
87 | {% endif %} |
|
87 | {% endif %} | |
88 | </div> |
|
88 | </div> | |
89 | {% if forloop.first %} |
|
89 | {% if forloop.first %} | |
90 | <div class="metadata"> |
|
90 | <div class="metadata"> | |
91 | <span class="tags"> |
|
91 | <span class="tags"> | |
92 | {% for tag in thread.get_tags %} |
|
92 | {% for tag in thread.get_tags %} | |
93 | <a class="tag" href="{% url 'tag' tag.name %}"> |
|
93 | <a class="tag" href="{% url 'tag' tag.name %}"> | |
94 | #{{ tag.name }}</a |
|
94 | #{{ tag.name }}</a | |
95 | >{% if not forloop.last %},{% endif %} |
|
95 | >{% if not forloop.last %},{% endif %} | |
96 | {% endfor %} |
|
96 | {% endfor %} | |
97 | </span> |
|
97 | </span> | |
98 | </div> |
|
98 | </div> | |
99 | {% endif %} |
|
99 | {% endif %} | |
100 | </div> |
|
100 | </div> | |
101 | {% endfor %} |
|
101 | {% endfor %} | |
102 | </div> |
|
102 | </div> | |
103 | {% endcache %} |
|
103 | {% endcache %} | |
104 |
|
104 | |||
105 | {% if not thread.archived %} |
|
105 | {% if not thread.archived %} | |
106 |
|
106 | |||
107 | <div class="post-form-w"> |
|
107 | <div class="post-form-w"> | |
108 | <script src="{% static 'js/panel.js' %}"></script> |
|
108 | <script src="{% static 'js/panel.js' %}"></script> | |
109 | <div class="form-title">{% trans "Reply to thread" %} #{{ thread.get_opening_post.id }}</div> |
|
109 | <div class="form-title">{% trans "Reply to thread" %} #{{ thread.get_opening_post.id }}</div> | |
110 | <div class="post-form"> |
|
110 | <div class="post-form"> | |
111 | <form id="form" enctype="multipart/form-data" method="post" |
|
111 | <form id="form" enctype="multipart/form-data" method="post" | |
112 | >{% csrf_token %} |
|
112 | >{% csrf_token %} | |
113 | {{ form.as_div }} |
|
113 | {{ form.as_div }} | |
114 | <div class="form-submit"> |
|
114 | <div class="form-submit"> | |
115 | <input type="submit" value="{% trans "Post" %}"/> |
|
115 | <input type="submit" value="{% trans "Post" %}"/> | |
116 | </div> |
|
116 | </div> | |
117 | </form> |
|
117 | </form> | |
118 | <div><a href="{% url "staticpage" name="help" %}"> |
|
118 | <div><a href="{% url "staticpage" name="help" %}"> | |
119 | {% trans 'Text syntax' %}</a></div> |
|
119 | {% trans 'Text syntax' %}</a></div> | |
120 | </div> |
|
120 | </div> | |
121 | </div> |
|
121 | </div> | |
122 |
|
122 | |||
123 |
|
|
123 | <script src="{% static 'js/jquery.form.min.js' %}"></script> | |
|
124 | <script src="{% static 'js/thread_update.js' %}"></script> | |||
124 | {% endif %} |
|
125 | {% endif %} | |
125 |
|
126 | |||
126 | <script src="{% static 'js/thread.js' %}"></script> |
|
127 | <script src="{% static 'js/thread.js' %}"></script> | |
127 |
|
128 | |||
128 | {% endspaceless %} |
|
129 | {% endspaceless %} | |
129 | {% endblock %} |
|
130 | {% endblock %} | |
130 |
|
131 | |||
131 | {% block metapanel %} |
|
132 | {% block metapanel %} | |
132 |
|
133 | |||
133 | {% get_current_language as LANGUAGE_CODE %} |
|
134 | {% get_current_language as LANGUAGE_CODE %} | |
134 |
|
135 | |||
135 | <span class="metapanel" data-last-update="{{ last_update }}"> |
|
136 | <span class="metapanel" data-last-update="{{ last_update }}"> | |
136 | {% cache 600 thread_meta thread.last_edit_time moderator LANGUAGE_CODE %} |
|
137 | {% cache 600 thread_meta thread.last_edit_time moderator LANGUAGE_CODE %} | |
137 | <span id="reply-count">{{ thread.get_reply_count }}</span> {% trans 'replies' %}, |
|
138 | <span id="reply-count">{{ thread.get_reply_count }}</span> {% trans 'replies' %}, | |
138 | <span id="image-count">{{ thread.get_images_count }}</span> {% trans 'images' %}. |
|
139 | <span id="image-count">{{ thread.get_images_count }}</span> {% trans 'images' %}. | |
139 | {% trans 'Last update: ' %}{{ thread.last_edit_time }} |
|
140 | {% trans 'Last update: ' %}{{ thread.last_edit_time }} | |
140 | [<a href="rss/">RSS</a>] |
|
141 | [<a href="rss/">RSS</a>] | |
141 | {% endcache %} |
|
142 | {% endcache %} | |
142 | </span> |
|
143 | </span> | |
143 |
|
144 | |||
144 | {% endblock %} |
|
145 | {% endblock %} |
General Comments 0
You need to be logged in to leave comments.
Login now