##// END OF EJS Templates
Merged with BB
Pavel Ryapolov -
r274:389d1321 merge default
parent child Browse files
Show More
@@ -0,0 +1,17 b''
1 from django.shortcuts import redirect
2 from boards import views, utils
3 from boards.models import Ban
4
5
6 class BanMiddleware:
7 """This is run before showing the thread. Banned users don't need to see
8 anything"""
9
10 def process_view(self, request, view_func, view_args, view_kwargs):
11
12 if view_func != views.you_are_banned:
13 ip = utils.get_client_ip(request)
14 is_banned = Ban.objects.filter(ip=ip).exists()
15
16 if is_banned:
17 return redirect(views.you_are_banned) No newline at end of file
@@ -0,0 +1,20 b''
1 .ui-button {
2 display: none;
3 }
4
5 .ui-dialog-content {
6 padding: 0;
7 min-height: 0;
8 }
9
10 .mark_btn {
11 cursor: pointer;
12 }
13
14 .img-full {
15 position: fixed;
16 z-index: 9999;
17 background-color: #CCC;
18 border: 1px solid #000;
19 cursor: pointer;
20 } No newline at end of file
@@ -0,0 +1,16 b''
1 @import url("../md/base_page.css");
2
3 .thread, .post-form-w, .image-mode-tab, .tag_info {
4 max-width: 1000px;
5 margin-left: auto;
6 margin-right: auto;
7 }
8
9 .thread {
10 border-left: solid 2px #888;
11 border-right: solid 2px #888;
12 }
13
14 .last-replies {
15 margin-right: 3ex;
16 }
@@ -0,0 +1,71 b''
1 function addImgPreview() {
2 var margin = 20; //..change
3
4 //keybind
5 $(document).on('keyup.removepic', function(e) {
6 if(e.which === 27) {
7 $('.img-full').remove();
8 }
9 });
10
11 $('body').on('click', '.thumb', function() {
12 var el = $(this);
13 var thumb_id = 'full' + el.find('img').attr('alt');
14
15 if(!$('#'+thumb_id).length) {
16 var img_w = el.find('img').attr('data-width');
17 var img_h = el.find('img').attr('data-height');
18
19 var win_w = $(window).width();
20 var win_h = $(window).height();
21 //new image size
22 if (img_w > win_w) {
23 img_h = img_h * (win_w/img_w) - margin;
24 img_w = win_w - margin;
25 }
26 if (img_h > win_h) {
27 img_w = img_w * (win_h/img_h) - margin;
28 img_h = win_h - margin;
29 }
30
31 var img_pv = new Image();
32 $(img_pv)
33 .addClass('img-full')
34 .attr('id', thumb_id)
35 .attr('src', $(el).attr('href'))
36 .appendTo($(el))
37 .css({
38 'width': img_w,
39 'height': img_h,
40 'left': (win_w - img_w) / 2,
41 'top': ((win_h - img_h) / 2)
42 })
43 //scaling preview
44 .mousewheel(function(event, delta) {
45 var cx = event.originalEvent.clientX,
46 cy = event.originalEvent.clientY,
47 i_w = parseFloat($(img_pv).width()),
48 i_h = parseFloat($(img_pv).height()),
49 newIW = i_w * (delta > 0 ? 1.25 : 0.8),
50 newIH = i_h * (delta > 0 ? 1.25 : 0.8);
51
52 $(img_pv).width(newIW);
53 $(img_pv).height(newIH);
54 //set position
55 $(img_pv)
56 .css({
57 left: parseInt(cx - (newIW/i_w) * (cx - parseInt($(img_pv).position().left, 10)), 10),
58 top: parseInt(cy - (newIH/i_h) * (cy - parseInt($(img_pv).position().top, 10)), 10)
59 });
60
61 return false;
62 }
63 ).draggable()
64 }
65 else {
66 $('#'+thumb_id).remove();
67 }
68 //prevent default
69 return false;
70 });
71 } No newline at end of file
@@ -0,0 +1,6 b''
1 /*! jQuery UI - v1.10.3 - 2013-09-21
2 * http://jqueryui.com
3 * Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.resizable.js, jquery.ui.button.js, jquery.ui.dialog.js
4 * Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */
5
6 (function(e,t){function i(t,i){var s,a,o,r=t.nodeName.toLowerCase();return"area"===r?(s=t.parentNode,a=s.name,t.href&&a&&"map"===s.nodeName.toLowerCase()?(o=e("img[usemap=#"+a+"]")[0],!!o&&n(o)):!1):(/input|select|textarea|button|object/.test(r)?!t.disabled:"a"===r?t.href||i:i)&&n(t)}function n(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var s=0,a=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.3",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,n){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),n&&n.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var n,s,a=e(this[0]);a.length&&a[0]!==document;){if(n=a.css("position"),("absolute"===n||"relative"===n||"fixed"===n)&&(s=parseInt(a.css("zIndex"),10),!isNaN(s)&&0!==s))return s;a=a.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++s)})},removeUniqueId:function(){return this.each(function(){a.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,n){return!!e.data(t,n[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),s=isNaN(n);return(s||n>=0)&&i(t,!s)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(i,n){function s(t,i,n,s){return e.each(a,function(){i-=parseFloat(e.css(t,"padding"+this))||0,n&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var a="Width"===n?["Left","Right"]:["Top","Bottom"],o=n.toLowerCase(),r={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+n]=function(i){return i===t?r["inner"+n].call(this):this.each(function(){e(this).css(o,s(this,i)+"px")})},e.fn["outer"+n]=function(t,i){return"number"!=typeof t?r["outer"+n].call(this,t):this.each(function(){e(this).css(o,s(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,n){var s,a=e.ui[t].prototype;for(s in n)a.plugins[s]=a.plugins[s]||[],a.plugins[s].push([i,n[s]])},call:function(e,t,i){var n,s=e.plugins[t];if(s&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(n=0;s.length>n;n++)e.options[s[n][0]]&&s[n][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var n=i&&"left"===i?"scrollLeft":"scrollTop",s=!1;return t[n]>0?!0:(t[n]=1,s=t[n]>0,t[n]=0,s)}})})(jQuery);(function(t,e){var i=0,s=Array.prototype.slice,n=t.cleanData;t.cleanData=function(e){for(var i,s=0;null!=(i=e[s]);s++)try{t(i).triggerHandler("remove")}catch(o){}n(e)},t.widget=function(i,s,n){var o,a,r,h,l={},c=i.split(".")[0];i=i.split(".")[1],o=c+"-"+i,n||(n=s,s=t.Widget),t.expr[":"][o.toLowerCase()]=function(e){return!!t.data(e,o)},t[c]=t[c]||{},a=t[c][i],r=t[c][i]=function(t,i){return this._createWidget?(arguments.length&&this._createWidget(t,i),e):new r(t,i)},t.extend(r,a,{version:n.version,_proto:t.extend({},n),_childConstructors:[]}),h=new s,h.options=t.widget.extend({},h.options),t.each(n,function(i,n){return t.isFunction(n)?(l[i]=function(){var t=function(){return s.prototype[i].apply(this,arguments)},e=function(t){return s.prototype[i].apply(this,t)};return function(){var i,s=this._super,o=this._superApply;return this._super=t,this._superApply=e,i=n.apply(this,arguments),this._super=s,this._superApply=o,i}}(),e):(l[i]=n,e)}),r.prototype=t.widget.extend(h,{widgetEventPrefix:a?h.widgetEventPrefix:i},l,{constructor:r,namespace:c,widgetName:i,widgetFullName:o}),a?(t.each(a._childConstructors,function(e,i){var s=i.prototype;t.widget(s.namespace+"."+s.widgetName,r,i._proto)}),delete a._childConstructors):s._childConstructors.push(r),t.widget.bridge(i,r)},t.widget.extend=function(i){for(var n,o,a=s.call(arguments,1),r=0,h=a.length;h>r;r++)for(n in a[r])o=a[r][n],a[r].hasOwnProperty(n)&&o!==e&&(i[n]=t.isPlainObject(o)?t.isPlainObject(i[n])?t.widget.extend({},i[n],o):t.widget.extend({},o):o);return i},t.widget.bridge=function(i,n){var o=n.prototype.widgetFullName||i;t.fn[i]=function(a){var r="string"==typeof a,h=s.call(arguments,1),l=this;return a=!r&&h.length?t.widget.extend.apply(null,[a].concat(h)):a,r?this.each(function(){var s,n=t.data(this,o);return n?t.isFunction(n[a])&&"_"!==a.charAt(0)?(s=n[a].apply(n,h),s!==n&&s!==e?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):e):t.error("no such method '"+a+"' for "+i+" widget instance"):t.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+a+"'")}):this.each(function(){var e=t.data(this,o);e?e.option(a||{})._init():t.data(this,o,new n(a,this))}),l}},t.Widget=function(){},t.Widget._childConstructors=[],t.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(e,s){s=t(s||this.defaultElement||this)[0],this.element=t(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=t.widget.extend({},this.options,this._getCreateOptions(),e),this.bindings=t(),this.hoverable=t(),this.focusable=t(),s!==this&&(t.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(t){t.target===s&&this.destroy()}}),this.document=t(s.style?s.ownerDocument:s.document||s),this.window=t(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:t.noop,_getCreateEventData:t.noop,_create:t.noop,_init:t.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(t.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:t.noop,widget:function(){return this.element},option:function(i,s){var n,o,a,r=i;if(0===arguments.length)return t.widget.extend({},this.options);if("string"==typeof i)if(r={},n=i.split("."),i=n.shift(),n.length){for(o=r[i]=t.widget.extend({},this.options[i]),a=0;n.length-1>a;a++)o[n[a]]=o[n[a]]||{},o=o[n[a]];if(i=n.pop(),s===e)return o[i]===e?null:o[i];o[i]=s}else{if(s===e)return this.options[i]===e?null:this.options[i];r[i]=s}return this._setOptions(r),this},_setOptions:function(t){var e;for(e in t)this._setOption(e,t[e]);return this},_setOption:function(t,e){return this.options[t]=e,"disabled"===t&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!e).attr("aria-disabled",e),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var o,a=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=o=t(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,o=this.widget()),t.each(n,function(n,r){function h(){return i||a.options.disabled!==!0&&!t(this).hasClass("ui-state-disabled")?("string"==typeof r?a[r]:r).apply(a,arguments):e}"string"!=typeof r&&(h.guid=r.guid=r.guid||h.guid||t.guid++);var l=n.match(/^(\w+)\s*(.*)$/),c=l[1]+a.eventNamespace,u=l[2];u?o.delegate(u,c,h):s.bind(c,h)})},_off:function(t,e){e=(e||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,t.unbind(e).undelegate(e)},_delay:function(t,e){function i(){return("string"==typeof t?s[t]:t).apply(s,arguments)}var s=this;return setTimeout(i,e||0)},_hoverable:function(e){this.hoverable=this.hoverable.add(e),this._on(e,{mouseenter:function(e){t(e.currentTarget).addClass("ui-state-hover")},mouseleave:function(e){t(e.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(e){this.focusable=this.focusable.add(e),this._on(e,{focusin:function(e){t(e.currentTarget).addClass("ui-state-focus")},focusout:function(e){t(e.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(e,i,s){var n,o,a=this.options[e];if(s=s||{},i=t.Event(i),i.type=(e===this.widgetEventPrefix?e:this.widgetEventPrefix+e).toLowerCase(),i.target=this.element[0],o=i.originalEvent)for(n in o)n in i||(i[n]=o[n]);return this.element.trigger(i,s),!(t.isFunction(a)&&a.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},t.each({show:"fadeIn",hide:"fadeOut"},function(e,i){t.Widget.prototype["_"+e]=function(s,n,o){"string"==typeof n&&(n={effect:n});var a,r=n?n===!0||"number"==typeof n?i:n.effect||i:e;n=n||{},"number"==typeof n&&(n={duration:n}),a=!t.isEmptyObject(n),n.complete=o,n.delay&&s.delay(n.delay),a&&t.effects&&t.effects.effect[r]?s[e](n):r!==e&&s[r]?s[r](n.duration,n.easing,o):s.queue(function(i){t(this)[e](),o&&o.call(s[0]),i()})}})})(jQuery);(function(t){var e=!1;t(document).mouseup(function(){e=!1}),t.widget("ui.mouse",{version:"1.10.3",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var e=this;this.element.bind("mousedown."+this.widgetName,function(t){return e._mouseDown(t)}).bind("click."+this.widgetName,function(i){return!0===t.data(i.target,e.widgetName+".preventClickEvent")?(t.removeData(i.target,e.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&t(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!e){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?t(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===t.data(i.target,this.widgetName+".preventClickEvent")&&t.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(t){return s._mouseMove(t)},this._mouseUpDelegate=function(t){return s._mouseUp(t)},t(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),e=!0,!0)):!0}},_mouseMove:function(e){return t.ui.ie&&(!document.documentMode||9>document.documentMode)&&!e.button?this._mouseUp(e):this._mouseStarted?(this._mouseDrag(e),e.preventDefault()):(this._mouseDistanceMet(e)&&this._mouseDelayMet(e)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,e)!==!1,this._mouseStarted?this._mouseDrag(e):this._mouseUp(e)),!this._mouseStarted)},_mouseUp:function(e){return t(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,e.target===this._mouseDownEvent.target&&t.data(e.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(e)),!1},_mouseDistanceMet:function(t){return Math.max(Math.abs(this._mouseDownEvent.pageX-t.pageX),Math.abs(this._mouseDownEvent.pageY-t.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(t,e){function i(t,e,i){return[parseFloat(t[0])*(p.test(t[0])?e/100:1),parseFloat(t[1])*(p.test(t[1])?i/100:1)]}function s(e,i){return parseInt(t.css(e,i),10)||0}function n(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}t.ui=t.ui||{};var a,o=Math.max,r=Math.abs,l=Math.round,h=/left|center|right/,c=/top|center|bottom/,u=/[\+\-]\d+(\.[\d]+)?%?/,d=/^\w+/,p=/%$/,f=t.fn.position;t.position={scrollbarWidth:function(){if(a!==e)return a;var i,s,n=t("<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=n.children()[0];return t("body").append(n),i=o.offsetWidth,n.css("overflow","scroll"),s=o.offsetWidth,i===s&&(s=n[0].clientWidth),n.remove(),a=i-s},getScrollInfo:function(e){var i=e.isWindow?"":e.element.css("overflow-x"),s=e.isWindow?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.width<e.element[0].scrollWidth,a="scroll"===s||"auto"===s&&e.height<e.element[0].scrollHeight;return{width:a?t.position.scrollbarWidth():0,height:n?t.position.scrollbarWidth():0}},getWithinInfo:function(e){var i=t(e||window),s=t.isWindow(i[0]);return{element:i,isWindow:s,offset:i.offset()||{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:s?i.width():i.outerWidth(),height:s?i.height():i.outerHeight()}}},t.fn.position=function(e){if(!e||!e.of)return f.apply(this,arguments);e=t.extend({},e);var a,p,g,m,v,_,b=t(e.of),y=t.position.getWithinInfo(e.within),k=t.position.getScrollInfo(y),w=(e.collision||"flip").split(" "),D={};return _=n(b),b[0].preventDefault&&(e.at="left top"),p=_.width,g=_.height,m=_.offset,v=t.extend({},m),t.each(["my","at"],function(){var t,i,s=(e[this]||"").split(" ");1===s.length&&(s=h.test(s[0])?s.concat(["center"]):c.test(s[0])?["center"].concat(s):["center","center"]),s[0]=h.test(s[0])?s[0]:"center",s[1]=c.test(s[1])?s[1]:"center",t=u.exec(s[0]),i=u.exec(s[1]),D[this]=[t?t[0]:0,i?i[0]:0],e[this]=[d.exec(s[0])[0],d.exec(s[1])[0]]}),1===w.length&&(w[1]=w[0]),"right"===e.at[0]?v.left+=p:"center"===e.at[0]&&(v.left+=p/2),"bottom"===e.at[1]?v.top+=g:"center"===e.at[1]&&(v.top+=g/2),a=i(D.at,p,g),v.left+=a[0],v.top+=a[1],this.each(function(){var n,h,c=t(this),u=c.outerWidth(),d=c.outerHeight(),f=s(this,"marginLeft"),_=s(this,"marginTop"),x=u+f+s(this,"marginRight")+k.width,C=d+_+s(this,"marginBottom")+k.height,M=t.extend({},v),T=i(D.my,c.outerWidth(),c.outerHeight());"right"===e.my[0]?M.left-=u:"center"===e.my[0]&&(M.left-=u/2),"bottom"===e.my[1]?M.top-=d:"center"===e.my[1]&&(M.top-=d/2),M.left+=T[0],M.top+=T[1],t.support.offsetFractions||(M.left=l(M.left),M.top=l(M.top)),n={marginLeft:f,marginTop:_},t.each(["left","top"],function(i,s){t.ui.position[w[i]]&&t.ui.position[w[i]][s](M,{targetWidth:p,targetHeight:g,elemWidth:u,elemHeight:d,collisionPosition:n,collisionWidth:x,collisionHeight:C,offset:[a[0]+T[0],a[1]+T[1]],my:e.my,at:e.at,within:y,elem:c})}),e.using&&(h=function(t){var i=m.left-M.left,s=i+p-u,n=m.top-M.top,a=n+g-d,l={target:{element:b,left:m.left,top:m.top,width:p,height:g},element:{element:c,left:M.left,top:M.top,width:u,height:d},horizontal:0>s?"left":i>0?"right":"center",vertical:0>a?"top":n>0?"bottom":"middle"};u>p&&p>r(i+s)&&(l.horizontal="center"),d>g&&g>r(n+a)&&(l.vertical="middle"),l.important=o(r(i),r(s))>o(r(n),r(a))?"horizontal":"vertical",e.using.call(this,t,l)}),c.offset(t.extend(M,{using:h}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,l=n-r,h=r+e.collisionWidth-a-n;e.collisionWidth>a?l>0&&0>=h?(i=t.left+l+e.collisionWidth-a-n,t.left+=l-i):t.left=h>0&&0>=l?n:l>h?n+a-e.collisionWidth:n:l>0?t.left+=l:h>0?t.left-=h:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,l=n-r,h=r+e.collisionHeight-a-n;e.collisionHeight>a?l>0&&0>=h?(i=t.top+l+e.collisionHeight-a-n,t.top+=l-i):t.top=h>0&&0>=l?n:l>h?n+a-e.collisionHeight:n:l>0?t.top+=l:h>0?t.top-=h:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,a=n.offset.left+n.scrollLeft,o=n.width,l=n.isWindow?n.scrollLeft:n.offset.left,h=t.left-e.collisionPosition.marginLeft,c=h-l,u=h+e.collisionWidth-o-l,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-o-a,(0>i||r(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-l,(s>0||u>r(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,a=n.offset.top+n.scrollTop,o=n.height,l=n.isWindow?n.scrollTop:n.offset.top,h=t.top-e.collisionPosition.marginTop,c=h-l,u=h+e.collisionHeight-o-l,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,g=-2*e.offset[1];0>c?(s=t.top+p+f+g+e.collisionHeight-o-a,t.top+p+f+g>c&&(0>s||r(c)>s)&&(t.top+=p+f+g)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+g-l,t.top+p+f+g>u&&(i>0||u>r(i))&&(t.top+=p+f+g))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}},function(){var e,i,s,n,a,o=document.getElementsByTagName("body")[0],r=document.createElement("div");e=document.createElement(o?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&t.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(a in s)e.style[a]=s[a];e.appendChild(r),i=o||document.documentElement,i.insertBefore(e,i.firstChild),r.style.cssText="position: absolute; left: 10.7432222px;",n=t(r).offset().left,t.support.offsetFractions=n>10&&11>n,e.innerHTML="",i.removeChild(e)}()})(jQuery);(function(t){t.widget("ui.draggable",t.ui.mouse,{version:"1.10.3",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"!==this.options.helper||/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(e){var i=this.options;return this.helper||i.disabled||t(e.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(e),this.handle?(t(i.iframeFix===!0?"iframe":i.iframeFix).each(function(){t("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(t(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(e){var i=this.options;return this.helper=this._createHelper(e),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),t.ui.ddmanager&&(t.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offsetParent=this.helper.offsetParent(),this.offsetParentCssPosition=this.offsetParent.css("position"),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},this.offset.scroll=!1,t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",e)===!1?(this._clear(),!1):(this._cacheHelperProportions(),t.ui.ddmanager&&!i.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this._mouseDrag(e,!0),t.ui.ddmanager&&t.ui.ddmanager.dragStart(this,e),!0)},_mouseDrag:function(e,i){if("fixed"===this.offsetParentCssPosition&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",e,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),!1},_mouseStop:function(e){var i=this,s=!1;return t.ui.ddmanager&&!this.options.dropBehaviour&&(s=t.ui.ddmanager.drop(this,e)),this.dropped&&(s=this.dropped,this.dropped=!1),"original"!==this.options.helper||t.contains(this.element[0].ownerDocument,this.element[0])?("invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||t.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?t(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",e)!==!1&&i._clear()}):this._trigger("stop",e)!==!1&&this._clear(),!1):!1},_mouseUp:function(e){return t("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),t.ui.ddmanager&&t.ui.ddmanager.dragStop(this,e),t.ui.mouse.prototype._mouseUp.call(this,e)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(e){return this.options.handle?!!t(e.target).closest(this.element.find(this.options.handle)).length:!0},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return s.parents("body").length||s.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s[0]===this.element[0]||/(fixed|absolute)/.test(s.css("position"))||s.css("position","absolute"),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.element.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;return n.containment?"window"===n.containment?(this.containment=[t(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,t(window).scrollLeft()+t(window).width()-this.helperProportions.width-this.margins.left,t(window).scrollTop()+(t(window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):"document"===n.containment?(this.containment=[0,0,t(document).width()-this.helperProportions.width-this.margins.left,(t(document).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):n.containment.constructor===Array?(this.containment=n.containment,undefined):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=t(n.containment),s=i[0],s&&(e="hidden"!==i.css("overflow"),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(e?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(e?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=i),undefined):(this.containment=null,undefined)},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent;return this.offset.scroll||(this.offset.scroll={top:n.scrollTop(),left:n.scrollLeft()}),{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top)*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)*s}},_generatePosition:function(e){var i,s,n,a,o=this.options,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,l=e.pageX,h=e.pageY;return this.offset.scroll||(this.offset.scroll={top:r.scrollTop(),left:r.scrollLeft()}),this.originalPosition&&(this.containment&&(this.relative_container?(s=this.relative_container.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,e.pageX-this.offset.click.left<i[0]&&(l=i[0]+this.offset.click.left),e.pageY-this.offset.click.top<i[1]&&(h=i[1]+this.offset.click.top),e.pageX-this.offset.click.left>i[2]&&(l=i[2]+this.offset.click.left),e.pageY-this.offset.click.top>i[3]&&(h=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((h-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,h=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((l-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,l=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a)),{top:h-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top),left:l-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(e,i,s){return s=s||this._uiHash(),t.ui.plugin.call(this,e,[i,s]),"drag"===e&&(this.positionAbs=this._convertPositionTo("absolute")),t.Widget.prototype._trigger.call(this,e,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),t.ui.plugin.add("draggable","connectToSortable",{start:function(e,i){var s=t(this).data("ui-draggable"),n=s.options,a=t.extend({},i,{item:s.element});s.sortables=[],t(n.connectToSortable).each(function(){var i=t.data(this,"ui-sortable");i&&!i.options.disabled&&(s.sortables.push({instance:i,shouldRevert:i.options.revert}),i.refreshPositions(),i._trigger("activate",e,a))})},stop:function(e,i){var s=t(this).data("ui-draggable"),n=t.extend({},i,{item:s.element});t.each(s.sortables,function(){this.instance.isOver?(this.instance.isOver=0,s.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=this.shouldRevert),this.instance._mouseStop(e),this.instance.options.helper=this.instance.options._helper,"original"===s.options.helper&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",e,n))})},drag:function(e,i){var s=t(this).data("ui-draggable"),n=this;t.each(s.sortables,function(){var a=!1,o=this;this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(a=!0,t.each(s.sortables,function(){return this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this!==o&&this.instance._intersectsWith(this.instance.containerCache)&&t.contains(o.instance.element[0],this.instance.element[0])&&(a=!1),a})),a?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=t(n).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return i.helper[0]},e.target=this.instance.currentItem[0],this.instance._mouseCapture(e,!0),this.instance._mouseStart(e,!0,!0),this.instance.offset.click.top=s.offset.click.top,this.instance.offset.click.left=s.offset.click.left,this.instance.offset.parent.left-=s.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=s.offset.parent.top-this.instance.offset.parent.top,s._trigger("toSortable",e),s.dropped=this.instance.element,s.currentItem=s.element,this.instance.fromOutside=s),this.instance.currentItem&&this.instance._mouseDrag(e)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",e,this.instance._uiHash(this.instance)),this.instance._mouseStop(e,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),s._trigger("fromSortable",e),s.dropped=!1)})}}),t.ui.plugin.add("draggable","cursor",{start:function(){var e=t("body"),i=t(this).data("ui-draggable").options;e.css("cursor")&&(i._cursor=e.css("cursor")),e.css("cursor",i.cursor)},stop:function(){var e=t(this).data("ui-draggable").options;e._cursor&&t("body").css("cursor",e._cursor)}}),t.ui.plugin.add("draggable","opacity",{start:function(e,i){var s=t(i.helper),n=t(this).data("ui-draggable").options;s.css("opacity")&&(n._opacity=s.css("opacity")),s.css("opacity",n.opacity)},stop:function(e,i){var s=t(this).data("ui-draggable").options;s._opacity&&t(i.helper).css("opacity",s._opacity)}}),t.ui.plugin.add("draggable","scroll",{start:function(){var e=t(this).data("ui-draggable");e.scrollParent[0]!==document&&"HTML"!==e.scrollParent[0].tagName&&(e.overflowOffset=e.scrollParent.offset())},drag:function(e){var i=t(this).data("ui-draggable"),s=i.options,n=!1;i.scrollParent[0]!==document&&"HTML"!==i.scrollParent[0].tagName?(s.axis&&"x"===s.axis||(i.overflowOffset.top+i.scrollParent[0].offsetHeight-e.pageY<s.scrollSensitivity?i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop+s.scrollSpeed:e.pageY-i.overflowOffset.top<s.scrollSensitivity&&(i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop-s.scrollSpeed)),s.axis&&"y"===s.axis||(i.overflowOffset.left+i.scrollParent[0].offsetWidth-e.pageX<s.scrollSensitivity?i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft+s.scrollSpeed:e.pageX-i.overflowOffset.left<s.scrollSensitivity&&(i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft-s.scrollSpeed))):(s.axis&&"x"===s.axis||(e.pageY-t(document).scrollTop()<s.scrollSensitivity?n=t(document).scrollTop(t(document).scrollTop()-s.scrollSpeed):t(window).height()-(e.pageY-t(document).scrollTop())<s.scrollSensitivity&&(n=t(document).scrollTop(t(document).scrollTop()+s.scrollSpeed))),s.axis&&"y"===s.axis||(e.pageX-t(document).scrollLeft()<s.scrollSensitivity?n=t(document).scrollLeft(t(document).scrollLeft()-s.scrollSpeed):t(window).width()-(e.pageX-t(document).scrollLeft())<s.scrollSensitivity&&(n=t(document).scrollLeft(t(document).scrollLeft()+s.scrollSpeed)))),n!==!1&&t.ui.ddmanager&&!s.dropBehaviour&&t.ui.ddmanager.prepareOffsets(i,e)}}),t.ui.plugin.add("draggable","snap",{start:function(){var e=t(this).data("ui-draggable"),i=e.options;e.snapElements=[],t(i.snap.constructor!==String?i.snap.items||":data(ui-draggable)":i.snap).each(function(){var i=t(this),s=i.offset();this!==e.element[0]&&e.snapElements.push({item:this,width:i.outerWidth(),height:i.outerHeight(),top:s.top,left:s.left})})},drag:function(e,i){var s,n,a,o,r,l,h,c,u,d,p=t(this).data("ui-draggable"),g=p.options,f=g.snapTolerance,m=i.offset.left,_=m+p.helperProportions.width,v=i.offset.top,b=v+p.helperProportions.height;for(u=p.snapElements.length-1;u>=0;u--)r=p.snapElements[u].left,l=r+p.snapElements[u].width,h=p.snapElements[u].top,c=h+p.snapElements[u].height,r-f>_||m>l+f||h-f>b||v>c+f||!t.contains(p.snapElements[u].item.ownerDocument,p.snapElements[u].item)?(p.snapElements[u].snapping&&p.options.snap.release&&p.options.snap.release.call(p.element,e,t.extend(p._uiHash(),{snapItem:p.snapElements[u].item})),p.snapElements[u].snapping=!1):("inner"!==g.snapMode&&(s=f>=Math.abs(h-b),n=f>=Math.abs(c-v),a=f>=Math.abs(r-_),o=f>=Math.abs(l-m),s&&(i.position.top=p._convertPositionTo("relative",{top:h-p.helperProportions.height,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:c,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r-p.helperProportions.width}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:l}).left-p.margins.left)),d=s||n||a||o,"outer"!==g.snapMode&&(s=f>=Math.abs(h-v),n=f>=Math.abs(c-b),a=f>=Math.abs(r-m),o=f>=Math.abs(l-_),s&&(i.position.top=p._convertPositionTo("relative",{top:h,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:c-p.helperProportions.height,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:l-p.helperProportions.width}).left-p.margins.left)),!p.snapElements[u].snapping&&(s||n||a||o||d)&&p.options.snap.snap&&p.options.snap.snap.call(p.element,e,t.extend(p._uiHash(),{snapItem:p.snapElements[u].item})),p.snapElements[u].snapping=s||n||a||o||d)}}),t.ui.plugin.add("draggable","stack",{start:function(){var e,i=this.data("ui-draggable").options,s=t.makeArray(t(i.stack)).sort(function(e,i){return(parseInt(t(e).css("zIndex"),10)||0)-(parseInt(t(i).css("zIndex"),10)||0)});s.length&&(e=parseInt(t(s[0]).css("zIndex"),10)||0,t(s).each(function(i){t(this).css("zIndex",e+i)}),this.css("zIndex",e+s.length))}}),t.ui.plugin.add("draggable","zIndex",{start:function(e,i){var s=t(i.helper),n=t(this).data("ui-draggable").options;s.css("zIndex")&&(n._zIndex=s.css("zIndex")),s.css("zIndex",n.zIndex)},stop:function(e,i){var s=t(this).data("ui-draggable").options;s._zIndex&&t(i.helper).css("zIndex",s._zIndex)}})})(jQuery);(function(t){function e(t){return parseInt(t,10)||0}function i(t){return!isNaN(parseInt(t,10))}t.widget("ui.resizable",t.ui.mouse,{version:"1.10.3",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var e,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),t.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(t("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(t(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),e=this.handles.split(","),this.handles={},i=0;e.length>i;i++)s=t.trim(e[i]),a="ui-resizable-"+s,n=t("<div class='ui-resizable-handle "+a+"'></div>"),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(e){var i,s,n,a;e=e||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=t(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=t(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),e.css(n,a),this._proportionallyResize()),t(this.handles[i]).length},this._renderAxis(this.element),this._handles=t(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),t(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(t(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(t(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var e,i=function(e){t(e).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),e=this.element,this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")}).insertAfter(e),e.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(e){var i,s,n=!1;for(i in this.handles)s=t(this.handles[i])[0],(s===e.target||t.contains(s,e.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=e(this.helper.css("left")),n=e(this.helper.css("top")),o.containment&&(s+=t(o.containment).scrollLeft()||0,n+=t(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=t(".ui-resizable-"+this.axis).css("cursor"),t("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(e){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,c=this.size.height,u=e.pageX-a.left||0,d=e.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[e,u,d]),this._updateVirtualBoundaries(e.shiftKey),(this._aspectRatio||e.shiftKey)&&(i=this._updateRatio(i,e)),i=this._respectSize(i,e),this._updateCache(i),this._propagate("resize",e),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==c&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),t.isEmptyObject(n)||this._trigger("resize",e,this.ui()),!1):!1},_mouseStop:function(e){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,c=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&t.ui.hasScroll(i[0],"left")?0:c.sizeDiff.height,a=s?0:c.sizeDiff.width,o={width:c.helper.width()-a,height:c.helper.height()-n},r=parseInt(c.element.css("left"),10)+(c.position.left-c.originalPosition.left)||null,h=parseInt(c.element.css("top"),10)+(c.position.top-c.originalPosition.top)||null,l.animate||this.element.css(t.extend(o,{top:h,left:r})),c.helper.height(c.size.height),c.helper.width(c.size.width),this._helper&&!l.animate&&this._proportionallyResize()),t("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",e),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(t){var e,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||t)&&(e=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,e>o.minWidth&&(o.minWidth=e),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(t){this.offset=this.helper.offset(),i(t.left)&&(this.position.left=t.left),i(t.top)&&(this.position.top=t.top),i(t.height)&&(this.size.height=t.height),i(t.width)&&(this.size.width=t.width)},_updateRatio:function(t){var e=this.position,s=this.size,n=this.axis;return i(t.height)?t.width=t.height*this.aspectRatio:i(t.width)&&(t.height=t.width/this.aspectRatio),"sw"===n&&(t.left=e.left+(s.width-t.width),t.top=null),"nw"===n&&(t.top=e.top+(s.height-t.height),t.left=e.left+(s.width-t.width)),t},_respectSize:function(t){var e=this._vBoundaries,s=this.axis,n=i(t.width)&&e.maxWidth&&e.maxWidth<t.width,a=i(t.height)&&e.maxHeight&&e.maxHeight<t.height,o=i(t.width)&&e.minWidth&&e.minWidth>t.width,r=i(t.height)&&e.minHeight&&e.minHeight>t.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,c=/sw|nw|w/.test(s),u=/nw|ne|n/.test(s);return o&&(t.width=e.minWidth),r&&(t.height=e.minHeight),n&&(t.width=e.maxWidth),a&&(t.height=e.maxHeight),o&&c&&(t.left=h-e.minWidth),n&&c&&(t.left=h-e.maxWidth),r&&u&&(t.top=l-e.minHeight),a&&u&&(t.top=l-e.maxHeight),t.width||t.height||t.left||!t.top?t.width||t.height||t.top||!t.left||(t.left=null):t.top=null,t},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var t,e,i,s,n,a=this.helper||this.element;for(t=0;this._proportionallyResizeElements.length>t;t++){if(n=this._proportionallyResizeElements[t],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],e=0;i.length>e;e++)this.borderDif[e]=(parseInt(i[e],10)||0)+(parseInt(s[e],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var e=this.element,i=this.options;this.elementOffset=e.offset(),this._helper?(this.helper=this.helper||t("<div style='overflow:hidden;'></div>"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(t,e){return{width:this.originalSize.width+e}},w:function(t,e){var i=this.originalSize,s=this.originalPosition;return{left:s.left+e,width:i.width-e}},n:function(t,e,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(t,e,i){return{height:this.originalSize.height+i}},se:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},sw:function(e,i,s){return t.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[e,i,s]))},ne:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[e,i,s]))},nw:function(e,i,s){return t.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[e,i,s]))}},_propagate:function(e,i){t.ui.plugin.call(this,e,[i,this.ui()]),"resize"!==e&&this._trigger(e,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),t.ui.plugin.add("resizable","animate",{stop:function(e){var i=t(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&t.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,c=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(t.extend(h,c&&l?{top:c,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&t(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",e)}})}}),t.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=t(this).data("ui-resizable"),c=l.options,u=l.element,d=c.containment,p=d instanceof t?d.get(0):/parent/.test(d)?u.parent().get(0):d;p&&(l.containerElement=t(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:t(document),left:0,top:0,width:t(document).width(),height:t(document).height()||document.body.parentNode.scrollHeight}):(i=t(p),s=[],t(["Top","Right","Left","Bottom"]).each(function(t,n){s[t]=e(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=t.ui.hasScroll(p,"left")?p.scrollWidth:o,h=t.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(e){var i,s,n,a,o=t(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,c=o._aspectRatio||e.shiftKey,u={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(u=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-u.left),c&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),c&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-u.left:o.offset.left-u.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-u.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=o.parentData.left),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,c&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,c&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.containerOffset,n=e.containerPosition,a=e.containerElement,o=t(e.helper),r=o.offset(),h=o.outerWidth()-e.sizeDiff.width,l=o.outerHeight()-e.sizeDiff.height;e._helper&&!i.animate&&/relative/.test(a.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l}),e._helper&&!i.animate&&/static/.test(a.css("position"))&&t(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),t.ui.plugin.add("resizable","alsoResize",{start:function(){var e=t(this).data("ui-resizable"),i=e.options,s=function(e){t(e).each(function(){var e=t(this);e.data("ui-resizable-alsoresize",{width:parseInt(e.width(),10),height:parseInt(e.height(),10),left:parseInt(e.css("left"),10),top:parseInt(e.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):t.each(i.alsoResize,function(t){s(t)})},resize:function(e,i){var s=t(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(e,s){t(e).each(function(){var e=t(this),n=t(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:e.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];t.each(o,function(t,e){var i=(n[e]||0)+(r[e]||0);i&&i>=0&&(a[e]=i||null)}),e.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):t.each(n.alsoResize,function(t,e){h(t,e)})},stop:function(){t(this).removeData("resizable-alsoresize")}}),t.ui.plugin.add("resizable","ghost",{start:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.size;e.ghost=e.originalElement.clone(),e.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),e.ghost.appendTo(e.helper)},resize:function(){var e=t(this).data("ui-resizable");e.ghost&&e.ghost.css({position:"relative",height:e.size.height,width:e.size.width})},stop:function(){var e=t(this).data("ui-resizable");e.ghost&&e.helper&&e.helper.get(0).removeChild(e.ghost.get(0))}}),t.ui.plugin.add("resizable","grid",{resize:function(){var e=t(this).data("ui-resizable"),i=e.options,s=e.size,n=e.originalSize,a=e.originalPosition,o=e.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,c=Math.round((s.width-n.width)/h)*h,u=Math.round((s.height-n.height)/l)*l,d=n.width+c,p=n.height+u,f=i.maxWidth&&d>i.maxWidth,g=i.maxHeight&&p>i.maxHeight,m=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,m&&(d+=h),v&&(p+=l),f&&(d-=h),g&&(p-=l),/^(se|s|e)$/.test(o)?(e.size.width=d,e.size.height=p):/^(ne)$/.test(o)?(e.size.width=d,e.size.height=p,e.position.top=a.top-u):/^(sw)$/.test(o)?(e.size.width=d,e.size.height=p,e.position.left=a.left-c):(e.size.width=d,e.size.height=p,e.position.top=a.top-u,e.position.left=a.left-c)}})})(jQuery);(function(e){var t,i,n,s,a="ui-button ui-widget ui-state-default ui-corner-all",o="ui-state-hover ui-state-active ",r="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",h=function(){var t=e(this);setTimeout(function(){t.find(":ui-button").button("refresh")},1)},u=function(t){var i=t.name,n=t.form,s=e([]);return i&&(i=i.replace(/'/g,"\\'"),s=n?e(n).find("[name='"+i+"']"):e("[name='"+i+"']",t.ownerDocument).filter(function(){return!this.form})),s};e.widget("ui.button",{version:"1.10.3",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,h),"boolean"!=typeof this.options.disabled?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var o=this,r=this.options,l="checkbox"===this.type||"radio"===this.type,c=l?"":"ui-state-active",d="ui-state-focus";null===r.label&&(r.label="input"===this.type?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(a).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){r.disabled||this===t&&e(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){r.disabled||e(this).removeClass(c)}).bind("click"+this.eventNamespace,function(e){r.disabled&&(e.preventDefault(),e.stopImmediatePropagation())}),this.element.bind("focus"+this.eventNamespace,function(){o.buttonElement.addClass(d)}).bind("blur"+this.eventNamespace,function(){o.buttonElement.removeClass(d)}),l&&(this.element.bind("change"+this.eventNamespace,function(){s||o.refresh()}),this.buttonElement.bind("mousedown"+this.eventNamespace,function(e){r.disabled||(s=!1,i=e.pageX,n=e.pageY)}).bind("mouseup"+this.eventNamespace,function(e){r.disabled||(i!==e.pageX||n!==e.pageY)&&(s=!0)})),"checkbox"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){return r.disabled||s?!1:undefined}):"radio"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){if(r.disabled||s)return!1;e(this).addClass("ui-state-active"),o.buttonElement.attr("aria-pressed","true");var t=o.element[0];u(t).not(t).map(function(){return e(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){return r.disabled?!1:(e(this).addClass("ui-state-active"),t=this,o.document.one("mouseup",function(){t=null}),undefined)}).bind("mouseup"+this.eventNamespace,function(){return r.disabled?!1:(e(this).removeClass("ui-state-active"),undefined)}).bind("keydown"+this.eventNamespace,function(t){return r.disabled?!1:((t.keyCode===e.ui.keyCode.SPACE||t.keyCode===e.ui.keyCode.ENTER)&&e(this).addClass("ui-state-active"),undefined)}).bind("keyup"+this.eventNamespace+" blur"+this.eventNamespace,function(){e(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(t){t.keyCode===e.ui.keyCode.SPACE&&e(this).click()})),this._setOption("disabled",r.disabled),this._resetButton()},_determineButtonType:function(){var e,t,i;this.type=this.element.is("[type=checkbox]")?"checkbox":this.element.is("[type=radio]")?"radio":this.element.is("input")?"input":"button","checkbox"===this.type||"radio"===this.type?(e=this.element.parents().last(),t="label[for='"+this.element.attr("id")+"']",this.buttonElement=e.find(t),this.buttonElement.length||(e=e.length?e.siblings():this.element.siblings(),this.buttonElement=e.filter(t),this.buttonElement.length||(this.buttonElement=e.find(t))),this.element.addClass("ui-helper-hidden-accessible"),i=this.element.is(":checked"),i&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",i)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(a+" "+o+" "+r).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(e,t){return this._super(e,t),"disabled"===e?(t?this.element.prop("disabled",!0):this.element.prop("disabled",!1),undefined):(this._resetButton(),undefined)},refresh:function(){var t=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOption("disabled",t),"radio"===this.type?u(this.element[0]).each(function(){e(this).is(":checked")?e(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):e(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):"checkbox"===this.type&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if("input"===this.type)return this.options.label&&this.element.val(this.options.label),undefined;var t=this.buttonElement.removeClass(r),i=e("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(t.empty()).text(),n=this.options.icons,s=n.primary&&n.secondary,a=[];n.primary||n.secondary?(this.options.text&&a.push("ui-button-text-icon"+(s?"s":n.primary?"-primary":"-secondary")),n.primary&&t.prepend("<span class='ui-button-icon-primary ui-icon "+n.primary+"'></span>"),n.secondary&&t.append("<span class='ui-button-icon-secondary ui-icon "+n.secondary+"'></span>"),this.options.text||(a.push(s?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||t.attr("title",e.trim(i)))):a.push("ui-button-text-only"),t.addClass(a.join(" "))}}),e.widget("ui.buttonset",{version:"1.10.3",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(e,t){"disabled"===e&&this.buttons.button("option",e,t),this._super(e,t)},refresh:function(){var t="rtl"===this.element.css("direction");this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(t?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(t?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function(e){var t={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};e.widget("ui.dialog",{version:"1.10.3",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var i=e(this).css(t).offset().top;0>i&&e(this).css("top",t.top-i)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&e.fn.draggable&&this._makeDraggable(),this.options.resizable&&e.fn.resizable&&this._makeResizable(),this._isOpen=!1},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var t=this.options.appendTo;return t&&(t.jquery||t.nodeType)?e(t):this.document.find(t||"body").eq(0)},_destroy:function(){var e,t=this.originalPosition;this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},disable:e.noop,enable:e.noop,close:function(t){var i=this;this._isOpen&&this._trigger("beforeClose",t)!==!1&&(this._isOpen=!1,this._destroyOverlay(),this.opener.filter(":focusable").focus().length||e(this.document[0].activeElement).blur(),this._hide(this.uiDialog,this.options.hide,function(){i._trigger("close",t)}))},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(e,t){var i=!!this.uiDialog.nextAll(":visible").insertBefore(this.uiDialog).length;return i&&!t&&this._trigger("focus",e),i},open:function(){var t=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),undefined):(this._isOpen=!0,this.opener=e(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this._show(this.uiDialog,this.options.show,function(){t._focusTabbable(),t._trigger("focus")}),this._trigger("open"),undefined)},_focusTabbable:function(){var e=this.element.find("[autofocus]");e.length||(e=this.element.find(":tabbable")),e.length||(e=this.uiDialogButtonPane.find(":tabbable")),e.length||(e=this.uiDialogTitlebarClose.filter(":tabbable")),e.length||(e=this.uiDialog),e.eq(0).focus()},_keepFocus:function(t){function i(){var t=this.document[0].activeElement,i=this.uiDialog[0]===t||e.contains(this.uiDialog[0],t);i||this._focusTabbable()}t.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=e("<div>").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front "+this.options.dialogClass).hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(t){if(this.options.closeOnEscape&&!t.isDefaultPrevented()&&t.keyCode&&t.keyCode===e.ui.keyCode.ESCAPE)return t.preventDefault(),this.close(t),undefined;if(t.keyCode===e.ui.keyCode.TAB){var i=this.uiDialog.find(":tabbable"),a=i.filter(":first"),s=i.filter(":last");t.target!==s[0]&&t.target!==this.uiDialog[0]||t.shiftKey?t.target!==a[0]&&t.target!==this.uiDialog[0]||!t.shiftKey||(s.focus(1),t.preventDefault()):(a.focus(1),t.preventDefault())}},mousedown:function(e){this._moveToTop(e)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var t;this.uiDialogTitlebar=e("<div>").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(t){e(t.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=e("<button></button>").button({label:this.options.closeText,icons:{primary:"ui-icon-closethick"},text:!1}).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(e){e.preventDefault(),this.close(e)}}),t=e("<span>").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar),this._title(t),this.uiDialog.attr({"aria-labelledby":t.attr("id")})},_title:function(e){this.options.title||e.html("&#160;"),e.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=e("<div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),this.uiButtonSet=e("<div>").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var t=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),e.isEmptyObject(i)||e.isArray(i)&&!i.length?(this.uiDialog.removeClass("ui-dialog-buttons"),undefined):(e.each(i,function(i,a){var s,n;a=e.isFunction(a)?{click:a,text:i}:a,a=e.extend({type:"button"},a),s=a.click,a.click=function(){s.apply(t.element[0],arguments)},n={icons:a.icons,text:a.showText},delete a.icons,delete a.showText,e("<button></button>",a).button(n).appendTo(t.uiButtonSet)}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),undefined)},_makeDraggable:function(){function t(e){return{position:e.position,offset:e.offset}}var i=this,a=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(a,s){e(this).addClass("ui-dialog-dragging"),i._blockFrames(),i._trigger("dragStart",a,t(s))},drag:function(e,a){i._trigger("drag",e,t(a))},stop:function(s,n){a.position=[n.position.left-i.document.scrollLeft(),n.position.top-i.document.scrollTop()],e(this).removeClass("ui-dialog-dragging"),i._unblockFrames(),i._trigger("dragStop",s,t(n))}})},_makeResizable:function(){function t(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}var i=this,a=this.options,s=a.resizable,n=this.uiDialog.css("position"),r="string"==typeof s?s:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:a.maxWidth,maxHeight:a.maxHeight,minWidth:a.minWidth,minHeight:this._minHeight(),handles:r,start:function(a,s){e(this).addClass("ui-dialog-resizing"),i._blockFrames(),i._trigger("resizeStart",a,t(s))},resize:function(e,a){i._trigger("resize",e,t(a))},stop:function(s,n){a.height=e(this).height(),a.width=e(this).width(),e(this).removeClass("ui-dialog-resizing"),i._unblockFrames(),i._trigger("resizeStop",s,t(n))}}).css("position",n)},_minHeight:function(){var e=this.options;return"auto"===e.height?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(){var e=this.uiDialog.is(":visible");e||this.uiDialog.show(),this.uiDialog.position(this.options.position),e||this.uiDialog.hide()},_setOptions:function(a){var s=this,n=!1,r={};e.each(a,function(e,a){s._setOption(e,a),e in t&&(n=!0),e in i&&(r[e]=a)}),n&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",r)},_setOption:function(e,t){var i,a,s=this.uiDialog;"dialogClass"===e&&s.removeClass(this.options.dialogClass).addClass(t),"disabled"!==e&&(this._super(e,t),"appendTo"===e&&this.uiDialog.appendTo(this._appendTo()),"buttons"===e&&this._createButtons(),"closeText"===e&&this.uiDialogTitlebarClose.button({label:""+t}),"draggable"===e&&(i=s.is(":data(ui-draggable)"),i&&!t&&s.draggable("destroy"),!i&&t&&this._makeDraggable()),"position"===e&&this._position(),"resizable"===e&&(a=s.is(":data(ui-resizable)"),a&&!t&&s.resizable("destroy"),a&&"string"==typeof t&&s.resizable("option","handles",t),a||t===!1||this._makeResizable()),"title"===e&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var e,t,i,a=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),a.minWidth>a.width&&(a.width=a.minWidth),e=this.uiDialog.css({height:"auto",width:a.width}).outerHeight(),t=Math.max(0,a.minHeight-e),i="number"==typeof a.maxHeight?Math.max(0,a.maxHeight-e):"none","auto"===a.height?this.element.css({minHeight:t,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,a.height-e)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var t=e(this);return e("<div>").css({position:"absolute",width:t.outerWidth(),height:t.outerHeight()}).appendTo(t.parent()).offset(t.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(t){return e(t.target).closest(".ui-dialog").length?!0:!!e(t.target).closest(".ui-datepicker").length},_createOverlay:function(){if(this.options.modal){var t=this,i=this.widgetFullName;e.ui.dialog.overlayInstances||this._delay(function(){e.ui.dialog.overlayInstances&&this.document.bind("focusin.dialog",function(a){t._allowInteraction(a)||(a.preventDefault(),e(".ui-dialog:visible:last .ui-dialog-content").data(i)._focusTabbable())})}),this.overlay=e("<div>").addClass("ui-widget-overlay ui-front").appendTo(this._appendTo()),this._on(this.overlay,{mousedown:"_keepFocus"}),e.ui.dialog.overlayInstances++}},_destroyOverlay:function(){this.options.modal&&this.overlay&&(e.ui.dialog.overlayInstances--,e.ui.dialog.overlayInstances||this.document.unbind("focusin.dialog"),this.overlay.remove(),this.overlay=null)}}),e.ui.dialog.overlayInstances=0,e.uiBackCompat!==!1&&e.widget("ui.dialog",e.ui.dialog,{_position:function(){var t,i=this.options.position,a=[],s=[0,0];i?(("string"==typeof i||"object"==typeof i&&"0"in i)&&(a=i.split?i.split(" "):[i[0],i[1]],1===a.length&&(a[1]=a[0]),e.each(["left","top"],function(e,t){+a[e]===a[e]&&(s[e]=a[e],a[e]=t)}),i={my:a[0]+(0>s[0]?s[0]:"+"+s[0])+" "+a[1]+(0>s[1]?s[1]:"+"+s[1]),at:a.join(" ")}),i=e.extend({},e.ui.dialog.prototype.options.position,i)):i=e.ui.dialog.prototype.options.position,t=this.uiDialog.is(":visible"),t||this.uiDialog.show(),this.uiDialog.position(i),t||this.uiDialog.hide()}})})(jQuery); No newline at end of file
@@ -0,0 +1,117 b''
1 /*! Copyright (c) 2013 Brandon Aaron (http://brandonaaron.net)
2 * Licensed under the MIT License (LICENSE.txt).
3 *
4 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
5 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
6 * Thanks to: Seamus Leahy for adding deltaX and deltaY
7 *
8 * Version: 3.1.3
9 *
10 * Requires: 1.2.2+
11 */
12
13 (function (factory) {
14 if ( typeof define === 'function' && define.amd ) {
15 // AMD. Register as an anonymous module.
16 define(['jquery'], factory);
17 } else if (typeof exports === 'object') {
18 // Node/CommonJS style for Browserify
19 module.exports = factory;
20 } else {
21 // Browser globals
22 factory(jQuery);
23 }
24 }(function ($) {
25
26 var toFix = ['wheel', 'mousewheel', 'DOMMouseScroll', 'MozMousePixelScroll'];
27 var toBind = 'onwheel' in document || document.documentMode >= 9 ? ['wheel'] : ['mousewheel', 'DomMouseScroll', 'MozMousePixelScroll'];
28 var lowestDelta, lowestDeltaXY;
29
30 if ( $.event.fixHooks ) {
31 for ( var i = toFix.length; i; ) {
32 $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;
33 }
34 }
35
36 $.event.special.mousewheel = {
37 setup: function() {
38 if ( this.addEventListener ) {
39 for ( var i = toBind.length; i; ) {
40 this.addEventListener( toBind[--i], handler, false );
41 }
42 } else {
43 this.onmousewheel = handler;
44 }
45 },
46
47 teardown: function() {
48 if ( this.removeEventListener ) {
49 for ( var i = toBind.length; i; ) {
50 this.removeEventListener( toBind[--i], handler, false );
51 }
52 } else {
53 this.onmousewheel = null;
54 }
55 }
56 };
57
58 $.fn.extend({
59 mousewheel: function(fn) {
60 return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
61 },
62
63 unmousewheel: function(fn) {
64 return this.unbind("mousewheel", fn);
65 }
66 });
67
68
69 function handler(event) {
70 var orgEvent = event || window.event,
71 args = [].slice.call(arguments, 1),
72 delta = 0,
73 deltaX = 0,
74 deltaY = 0,
75 absDelta = 0,
76 absDeltaXY = 0,
77 fn;
78 event = $.event.fix(orgEvent);
79 event.type = "mousewheel";
80
81 // Old school scrollwheel delta
82 if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }
83 if ( orgEvent.detail ) { delta = orgEvent.detail * -1; }
84
85 // New school wheel delta (wheel event)
86 if ( orgEvent.deltaY ) {
87 deltaY = orgEvent.deltaY * -1;
88 delta = deltaY;
89 }
90 if ( orgEvent.deltaX ) {
91 deltaX = orgEvent.deltaX;
92 delta = deltaX * -1;
93 }
94
95 // Webkit
96 if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }
97 if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX * -1; }
98
99 // Look for lowest delta to normalize the delta values
100 absDelta = Math.abs(delta);
101 if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }
102 absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));
103 if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }
104
105 // Get a whole value for the deltas
106 fn = delta > 0 ? 'floor' : 'ceil';
107 delta = Math[fn](delta / lowestDelta);
108 deltaX = Math[fn](deltaX / lowestDeltaXY);
109 deltaY = Math[fn](deltaY / lowestDeltaXY);
110
111 // Add event and delta to the front of the arguments
112 args.unshift(event, delta, deltaX, deltaY);
113
114 return ($.event.dispatch || $.event.handle).apply(this, args);
115 }
116
117 }));
@@ -0,0 +1,34 b''
1 function addMarkToMsg(start, end) {
2 var textarea = document.getElementById('id_text');
3 if(!textarea) return;
4 if( document.selection ) {
5 textarea.focus();
6 sel = document.selection.createRange();
7 sel.text = start + sel.text + end;
8 } else if(textarea.selectionStart || textarea.selectionStart == '0') {
9 textarea.focus();
10 var startPos = textarea.selectionStart;
11 var endPos = textarea.selectionEnd;
12 textarea.value = textarea.value.substring(0, startPos) + start + textarea.value.substring(startPos, endPos) + end + textarea.value.substring( endPos, textarea.value.length );
13 } else {
14 textarea.value += start + end;
15 }
16 return false;
17 }
18
19 function addMarkPanel() {
20 $('.mark_btn').on('click', function() {
21 switch($(this).attr('id')) {
22 case "italic":
23 return addMarkToMsg('_', '_');
24 case "bold":
25 return addMarkToMsg('__', '__');
26 case "spoiler":
27 return addMarkToMsg('%%', '%%');
28 case "comment":
29 return addMarkToMsg('//', '');
30 case "quote":
31 return addMarkToMsg('>', '');
32 }
33 });
34 }
@@ -0,0 +1,44 b''
1 /**
2 * Created with IntelliJ IDEA.
3 * User: vurdalak
4 * Date: 21.09.13
5 * Time: 15:21
6 * To change this template use File | Settings | File Templates.
7 */
8
9 function addPopups() {
10
11 $('a').each(function() {
12 if($(this).text().indexOf('>>') == 0) {
13 var refNum = $(this).text().match(/\d+/);
14
15 if (refNum != null) {
16 var self = $(this);
17
18 $(this).mouseenter(function() {
19 $.get('/get_post/' + refNum, function(data) {
20 var popup = $('<div/>').html(data)
21
22 popup.dialog({
23 modal: false,
24 minHeight: 0,
25 });
26
27 popup.position({
28 my: "left+20 top+20",
29 at: "right bottom",
30 of: self
31 })
32
33 self.mouseleave(function() {
34 if (popup != null) {
35 popup.remove();
36 }
37 });
38 })
39 });
40 }
41 }
42 });
43
44 }
@@ -0,0 +1,47 b''
1 {% load i18n %}
2
3 <div class="post" id="{{ post.id }}">
4 {% if post.image %}
5 <div class="image">
6 <a
7 class="thumb"
8 href="{{ post.image.url }}"><img
9 src="{{ post.image.url_200x150 }}"
10 alt="{% trans 'Post image' %}"v
11 data-width="{{ post.image_width }}"
12 data-height="{{ post.image_height }}"/>
13 </a>
14 </div>
15 {% endif %}
16 <div class="message">
17 <div class="post-info">
18 <span class="title">{{ post.title }}</span>
19 <a class="post_id" href="#{{ post.id }}">
20 (#{{ post.id }})</a>
21 [{{ post.pub_time }}]
22
23 {% if moderator %}
24 <span class="moderator_info">
25 [<a href="{% url 'delete' post_id=post.id %}"
26 >{% trans 'Delete' %}</a>]
27 ({{ post.poster_ip }})
28 [<a href="{% url 'ban' post_id=post.id %}?next={{ request.path }}"
29 >{% trans 'Ban IP' %}</a>]
30 </span>
31 {% endif %}
32 </div>
33 {% autoescape off %}
34 {{ post.text.rendered }}
35 {% endautoescape %}
36 </div>
37 {% if post.tags.exists %}
38 <div class="metadata">
39 <span class="tags">{% trans 'Tags' %}:
40 {% for tag in post.tags.all %}
41 <a class="tag" href="{% url 'tag' tag.name %}">
42 {{ tag.name }}</a>
43 {% endfor %}
44 </span>
45 </div>
46 {% endif %}
47 </div> No newline at end of file
@@ -1,2 +1,3 b''
1 bc8fce57a613175450b8b6d933cdd85f22c04658 1.1
1 bc8fce57a613175450b8b6d933cdd85f22c04658 1.1
2 784258eb652c563c288ca7652c33f52cd4733d83 1.1-stable
2 784258eb652c563c288ca7652c33f52cd4733d83 1.1-stable
3 1b53a22467a8fccc798935d7a26efe78e4bc7b25 1.2-stable
@@ -1,24 +1,31 b''
1 from django.utils.translation import ugettext_lazy as _
2
1 __author__ = 'neko259'
3 __author__ = 'neko259'
2
4
5 ROLE_AUTHOR = _('author')
6 ROLE_DEVELOPER = _('developer')
7 ROLE_JS_DEV = _('javascript developer')
8 ROLE_DESIGNER = _('designer')
9
3 authors = {
10 authors = {
4 'neko259': {
11 'neko259': {
5 'name': 'Pavel Ryapolov',
12 'name': 'Pavel Ryapolov',
6 'contacts': ['neko259@gmail.com'],
13 'contacts': ['neko259@gmail.com'],
7 'roles': ['author', 'developer'],
14 'roles': [ROLE_AUTHOR, ROLE_DEVELOPER],
8 },
15 },
9 'ilyas': {
16 'ilyas': {
10 'name': 'Ilyas Babayev',
17 'name': 'Ilyas Babayev',
11 'contacts': ['zamesilyasa@gmail.com'],
18 'contacts': ['zamesilyasa@gmail.com'],
12 'roles': ['author', 'developer'],
19 'roles': [ROLE_AUTHOR, ROLE_DEVELOPER],
13 },
20 },
14 'ritsufag': {
21 'ritsufag': {
15 'name': 'Aiko Kirino',
22 'name': 'Aiko Kirino',
16 'contacts': ['ritsufag@gmail.com'],
23 'contacts': ['ritsufag@gmail.com'],
17 'roles': ['javascript developer', 'designer'],
24 'roles': [ROLE_JS_DEV, ROLE_DESIGNER],
18 },
25 },
19 'Tenno Seremel': {
26 'Tenno Seremel': {
20 'name': 'anonymous',
27 'name': 'anonymous',
21 'contacts': ['html@serenareem.net'],
28 'contacts': ['html@serenareem.net'],
22 'roles': ['javascript developer', 'designer'],
29 'roles': [ROLE_JS_DEV, ROLE_DESIGNER],
23 },
30 },
24 } No newline at end of file
31 }
@@ -9,6 +9,12 b' from neboard import settings'
9 from boards import utils
9 from boards import utils
10
10
11 LAST_POST_TIME = "last_post_time"
11 LAST_POST_TIME = "last_post_time"
12 LAST_LOGIN_TIME = "last_login_time"
13
14 LOGIN_DELAY = 60 * 60
15
16 MAX_TEXT_LENGTH = 30000
17 MAX_IMAGE_SIZE = 8 * 1024 * 1024
12
18
13
19
14 class PlainErrorList(ErrorList):
20 class PlainErrorList(ErrorList):
@@ -41,45 +47,56 b' class NeboardForm(forms.Form):'
41
47
42 class PostForm(NeboardForm):
48 class PostForm(NeboardForm):
43
49
44 MAX_TEXT_LENGTH = 30000
50 title = forms.CharField(max_length=TITLE_MAX_LENGTH, required=False,
45 MAX_IMAGE_SIZE = 8 * 1024 * 1024
51 label=_('Title'))
52 text = forms.CharField(widget=forms.Textarea, required=False,
53 label=_('Text'))
54 image = forms.ImageField(required=False, label=_('Image'))
46
55
47 title = forms.CharField(max_length=TITLE_MAX_LENGTH, required=False)
56 # This field is for spam prevention only
48 text = forms.CharField(widget=forms.Textarea, required=False)
57 email = forms.CharField(max_length=100, required=False, label=_('e-mail'),
49 image = forms.ImageField(required=False)
58 widget=forms.TextInput(attrs={
59 'class': 'form-email'}))
50
60
51 session = None
61 session = None
62 need_to_ban = False
52
63
53 def clean_title(self):
64 def clean_title(self):
54 title = self.cleaned_data['title']
65 title = self.cleaned_data['title']
55 if title:
66 if title:
56 if len(title) > TITLE_MAX_LENGTH:
67 if len(title) > TITLE_MAX_LENGTH:
57 raise forms.ValidationError('Title must have less than' +
68 raise forms.ValidationError(_('Title must have less than %s '
58 str(TITLE_MAX_LENGTH) +
69 'characters') %
59 ' characters.')
70 str(TITLE_MAX_LENGTH))
60 return title
71 return title
61
72
62 def clean_text(self):
73 def clean_text(self):
63 text = self.cleaned_data['text']
74 text = self.cleaned_data['text']
64 if text:
75 if text:
65 if len(text) > self.MAX_TEXT_LENGTH:
76 if len(text) > MAX_TEXT_LENGTH:
66 raise forms.ValidationError('Text must have less than ' +
77 raise forms.ValidationError(_('Text must have less than %s '
67 str(self.MAX_TEXT_LENGTH) +
78 'characters') %
68 ' characters.')
79 str(MAX_TEXT_LENGTH))
69 return text
80 return text
70
81
71 def clean_image(self):
82 def clean_image(self):
72 image = self.cleaned_data['image']
83 image = self.cleaned_data['image']
73 if image:
84 if image:
74 if image._size > self.MAX_IMAGE_SIZE:
85 if image._size > MAX_IMAGE_SIZE:
75 raise forms.ValidationError('Image must be less than ' +
86 raise forms.ValidationError(_('Image must be less than %s '
76 str(self.MAX_IMAGE_SIZE) +
87 'bytes') % str(MAX_IMAGE_SIZE))
77 ' bytes.')
78 return image
88 return image
79
89
80 def clean(self):
90 def clean(self):
81 cleaned_data = super(PostForm, self).clean()
91 cleaned_data = super(PostForm, self).clean()
82
92
93 if not self.session:
94 raise forms.ValidationError('Humans have sessions')
95
96 if cleaned_data['email']:
97 self.need_to_ban = True
98 raise forms.ValidationError('A human cannot enter a hidden field')
99
83 if not self.errors:
100 if not self.errors:
84 self._clean_text_image()
101 self._clean_text_image()
85
102
@@ -106,9 +123,8 b' class PostForm(NeboardForm):'
106 current_delay = int(now - last_post_time)
123 current_delay = int(now - last_post_time)
107
124
108 if current_delay < settings.POSTING_DELAY:
125 if current_delay < settings.POSTING_DELAY:
109 error_message = 'Wait ' + str(settings.POSTING_DELAY -
126 error_message = _('Wait %s seconds after last posting') % str(
110 current_delay)\
127 settings.POSTING_DELAY - current_delay)
111 + ' seconds after last posting'
112 self._errors['text'] = self.error_class([error_message])
128 self._errors['text'] = self.error_class([error_message])
113
129
114 can_post = False
130 can_post = False
@@ -118,8 +134,10 b' class PostForm(NeboardForm):'
118
134
119
135
120 class ThreadForm(PostForm):
136 class ThreadForm(PostForm):
137
121 regex_tags = re.compile(ur'^[\w\s\d]+$', re.UNICODE)
138 regex_tags = re.compile(ur'^[\w\s\d]+$', re.UNICODE)
122 tags = forms.CharField(max_length=100)
139
140 tags = forms.CharField(max_length=100, label=_('Tags'))
123
141
124 def clean_tags(self):
142 def clean_tags(self):
125 tags = self.cleaned_data['tags']
143 tags = self.cleaned_data['tags']
@@ -192,8 +210,11 b' class ModeratorSettingsForm(SettingsForm'
192
210
193
211
194 class LoginForm(NeboardForm):
212 class LoginForm(NeboardForm):
213
195 user_id = forms.CharField()
214 user_id = forms.CharField()
196
215
216 session = None
217
197 def clean_user_id(self):
218 def clean_user_id(self):
198 user_id = self.cleaned_data['user_id']
219 user_id = self.cleaned_data['user_id']
199 if user_id:
220 if user_id:
@@ -203,7 +224,31 b' class LoginForm(NeboardForm):'
203
224
204 return user_id
225 return user_id
205
226
227 def _validate_login_speed(self):
228 can_post = True
229
230 if LAST_LOGIN_TIME in self.session:
231 now = time.time()
232 last_login_time = self.session[LAST_LOGIN_TIME]
233
234 current_delay = int(now - last_login_time)
235
236 if current_delay < LOGIN_DELAY:
237 error_message = _('Wait %s minutes after last login') % str(
238 (LOGIN_DELAY - current_delay) / 60)
239 self._errors['user_id'] = self.error_class([error_message])
240
241 can_post = False
242
243 if can_post:
244 self.session[LAST_LOGIN_TIME] = time.time()
245
206 def clean(self):
246 def clean(self):
247 if not self.session:
248 raise forms.ValidationError('Humans have sessions')
249
250 self._validate_login_speed()
251
207 cleaned_data = super(LoginForm, self).clean()
252 cleaned_data = super(LoginForm, self).clean()
208
253
209 return cleaned_data No newline at end of file
254 return cleaned_data
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
@@ -7,7 +7,7 b' msgid ""'
7 msgstr ""
7 msgstr ""
8 "Project-Id-Version: PACKAGE VERSION\n"
8 "Project-Id-Version: PACKAGE VERSION\n"
9 "Report-Msgid-Bugs-To: \n"
9 "Report-Msgid-Bugs-To: \n"
10 "POT-Creation-Date: 2013-09-17 21:58+0300\n"
10 "POT-Creation-Date: 2013-09-22 21:35+0300\n"
11 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
11 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
12 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13 "Language-Team: LANGUAGE <LL@li.org>\n"
13 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,30 +18,97 b' msgstr ""'
18 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
18 "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
19 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
19 "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
20
20
21 #: forms.py:96
21 #: authors.py:5
22 msgid "author"
23 msgstr "автор"
24
25 #: authors.py:6
26 msgid "developer"
27 msgstr "разработчик"
28
29 #: authors.py:7
30 msgid "javascript developer"
31 msgstr "разработчик javascript"
32
33 #: authors.py:8
34 msgid "designer"
35 msgstr "дизайнер"
36
37 #: forms.py:51 templates/boards/posting_general.html:135
38 #: templates/boards/thread.html:82
39 msgid "Title"
40 msgstr "Заголовок"
41
42 #: forms.py:53 templates/boards/posting_general.html:150
43 #: templates/boards/thread.html:97
44 msgid "Text"
45 msgstr "Текст"
46
47 #: forms.py:54 templates/boards/posting_general.html:155
48 #: templates/boards/thread.html:102
49 msgid "Image"
50 msgstr "Изображение"
51
52 #: forms.py:57 templates/boards/posting_general.html:165
53 #: templates/boards/thread.html:107
54 msgid "e-mail"
55 msgstr ""
56
57 #: forms.py:67
58 #, python-format
59 msgid "Title must have less than %s characters"
60 msgstr "Заголовок должен иметь меньше %s символов"
61
62 #: forms.py:76
63 #, python-format
64 msgid "Text must have less than %s characters"
65 msgstr "Текст должен быть короче %s символов"
66
67 #: forms.py:85
68 #, python-format
69 msgid "Image must be less than %s bytes"
70 msgstr "Изображение должно быть менее %s байт"
71
72 #: forms.py:111
22 msgid "Either text or image must be entered."
73 msgid "Either text or image must be entered."
23 msgstr "Текст или картинка должны быть введены."
74 msgstr "Текст или картинка должны быть введены."
24
75
25 #: forms.py:130
76 #: forms.py:124
77 #, python-format
78 msgid "Wait %s seconds after last posting"
79 msgstr "Подождите %s секунд после последнего постинга"
80
81 #: forms.py:138 templates/boards/post.html:39
82 #: templates/boards/posting_general.html:77
83 #: templates/boards/posting_general.html:160 templates/boards/tags.html:7
84 #: templates/boards/thread.html:62 templates/boards/rss/post.html:10
85 msgid "Tags"
86 msgstr "Теги"
87
88 #: forms.py:146
26 msgid "Inappropriate characters in tags."
89 msgid "Inappropriate characters in tags."
27 msgstr "Недопустимые символы в тегах."
90 msgstr "Недопустимые символы в тегах."
28
91
29 #: forms.py:158 forms.py:179
92 #: forms.py:174 forms.py:195
30 msgid "Captcha validation failed"
93 msgid "Captcha validation failed"
31 msgstr "Проверка капчи провалена"
94 msgstr "Проверка капчи провалена"
32
95
33 #: forms.py:185
96 #: forms.py:201
34 msgid "Theme"
97 msgid "Theme"
35 msgstr "Тема"
98 msgstr "Тема"
36
99
37 #: forms.py:190
100 #: forms.py:206
38 msgid "Enable moderation panel"
101 msgid "Enable moderation panel"
39 msgstr "Включить панель модерации"
102 msgstr "Включить панель модерации"
40
103
41 #: forms.py:202
104 #: forms.py:221
42 #, fuzzy
43 msgid "No such user found"
105 msgid "No such user found"
44 msgstr "Теги не найдены."
106 msgstr "Данный пользователь не найден"
107
108 #: forms.py:235
109 #, python-format
110 msgid "Wait %s minutes after last login"
111 msgstr "Подождите %s минут после последнего входа"
45
112
46 #: templates/boards/404.html:6
113 #: templates/boards/404.html:6
47 msgid "Not found"
114 msgid "Not found"
@@ -71,24 +138,24 b' msgstr "\xd0\xa0\xd0\xb5\xd0\xbf\xd0\xbe\xd0\xb7\xd0\xb8\xd1\x82\xd0\xbe\xd1\x80\xd0\xb8\xd0\xb9"'
71 msgid "Feed"
138 msgid "Feed"
72 msgstr "Лента"
139 msgstr "Лента"
73
140
74 #: templates/boards/base.html:29
141 #: templates/boards/base.html:33
75 msgid "All threads"
142 msgid "All threads"
76 msgstr "Все темы"
143 msgstr "Все темы"
77
144
78 #: templates/boards/base.html:34
145 #: templates/boards/base.html:38
79 msgid "Tag management"
146 msgid "Tag management"
80 msgstr "Управление тегами"
147 msgstr "Управление тегами"
81
148
82 #: templates/boards/base.html:36
149 #: templates/boards/base.html:40
83 msgid "Settings"
150 msgid "Settings"
84 msgstr "Настройки"
151 msgstr "Настройки"
85
152
86 #: templates/boards/base.html:43 templates/boards/login.html:6
153 #: templates/boards/base.html:47 templates/boards/login.html:6
87 #: templates/boards/login.html.py:21
154 #: templates/boards/login.html.py:21
88 msgid "Login"
155 msgid "Login"
89 msgstr "Вход"
156 msgstr "Вход"
90
157
91 #: templates/boards/base.html:44
158 #: templates/boards/base.html:48
92 msgid "Up"
159 msgid "Up"
93 msgstr "Вверх"
160 msgstr "Вверх"
94
161
@@ -100,42 +167,38 b' msgstr "ID \xd0\xbf\xd0\xbe\xd0\xbb\xd1\x8c\xd0\xb7\xd0\xbe\xd0\xb2\xd0\xb0\xd1\x82\xd0\xb5\xd0\xbb\xd1\x8f"'
100 msgid "Insert your user id above"
167 msgid "Insert your user id above"
101 msgstr "Вставьте свой ID пользователя выше"
168 msgstr "Вставьте свой ID пользователя выше"
102
169
170 #: templates/boards/post.html:10 templates/boards/posting_general.html:44
171 #: templates/boards/posting_general.html:100 templates/boards/thread.html:31
172 #: templates/boards/rss/post.html:5
173 msgid "Post image"
174 msgstr "Изображение сообщения"
175
176 #: templates/boards/post.html:26 templates/boards/posting_general.html:62
177 #: templates/boards/thread.html:49
178 msgid "Delete"
179 msgstr "Удалить"
180
181 #: templates/boards/post.html:29 templates/boards/posting_general.html:65
182 #: templates/boards/thread.html:52
183 msgid "Ban IP"
184 msgstr "Заблокировать IP"
185
103 #: templates/boards/posting_general.html:19
186 #: templates/boards/posting_general.html:19
104 msgid "Tag: "
187 msgid "Tag: "
105 msgstr "Тег: "
188 msgstr "Тег: "
106
189
107 #: templates/boards/posting_general.html:44
108 #: templates/boards/posting_general.html:100 templates/boards/thread.html:29
109 #: templates/boards/rss/post.html:5
110 msgid "Post image"
111 msgstr "Изображение сообщения"
112
113 #: templates/boards/posting_general.html:57
190 #: templates/boards/posting_general.html:57
114 msgid "Reply"
191 msgid "Reply"
115 msgstr "Ответ"
192 msgstr "Ответ"
116
193
117 #: templates/boards/posting_general.html:62 templates/boards/thread.html:47
194 #: templates/boards/posting_general.html:74 templates/boards/thread.html:135
118 msgid "Delete"
119 msgstr "Удалить"
120
121 #: templates/boards/posting_general.html:65 templates/boards/thread.html:50
122 msgid "Ban IP"
123 msgstr "Заблокировать IP"
124
125 #: templates/boards/posting_general.html:74 templates/boards/thread.html:116
126 msgid "replies"
195 msgid "replies"
127 msgstr "ответов"
196 msgstr "ответов"
128
197
129 #: templates/boards/posting_general.html:75 templates/boards/thread.html:117
198 #: templates/boards/posting_general.html:75 templates/boards/thread.html:136
130 msgid "images"
199 msgid "images"
131 msgstr "изображений"
200 msgstr "изображений"
132
201
133 #: templates/boards/posting_general.html:77
134 #: templates/boards/posting_general.html:150 templates/boards/tags.html:7
135 #: templates/boards/thread.html:60 templates/boards/rss/post.html:10
136 msgid "Tags"
137 msgstr "Теги"
138
139 #: templates/boards/posting_general.html:126
202 #: templates/boards/posting_general.html:126
140 msgid "No threads exist. Create the first one!"
203 msgid "No threads exist. Create the first one!"
141 msgstr "Нет тем. Создайте первую!"
204 msgstr "Нет тем. Создайте первую!"
@@ -144,32 +207,44 b' msgstr "\xd0\x9d\xd0\xb5\xd1\x82 \xd1\x82\xd0\xb5\xd0\xbc. \xd0\xa1\xd0\xbe\xd0\xb7\xd0\xb4\xd0\xb0\xd0\xb9\xd1\x82\xd0\xb5 \xd0\xbf\xd0\xb5\xd1\x80\xd0\xb2\xd1\x83\xd1\x8e!"'
144 msgid "Create new thread"
207 msgid "Create new thread"
145 msgstr "Создать новую тему"
208 msgstr "Создать новую тему"
146
209
147 #: templates/boards/posting_general.html:135 templates/boards/thread.html:80
210 #: templates/boards/posting_general.html:140 templates/boards/thread.html:87
148 msgid "Title"
211 msgid "Formatting"
149 msgstr "Заголовок"
212 msgstr "Форматирование"
213
214 #: templates/boards/posting_general.html:142 templates/boards/thread.html:89
215 msgid "quote"
216 msgstr "цитата"
217
218 #: templates/boards/posting_general.html:143 templates/boards/thread.html:90
219 msgid "italic"
220 msgstr "курсив"
150
221
151 #: templates/boards/posting_general.html:140 templates/boards/thread.html:85
222 #: templates/boards/posting_general.html:144 templates/boards/thread.html:91
152 msgid "Text"
223 msgid "bold"
153 msgstr "Текст"
224 msgstr "полужирный"
154
225
155 #: templates/boards/posting_general.html:145 templates/boards/thread.html:90
226 #: templates/boards/posting_general.html:145 templates/boards/thread.html:92
156 msgid "Image"
227 msgid "spoiler"
157 msgstr "Изображение"
228 msgstr "спойлер"
158
229
159 #: templates/boards/posting_general.html:163 templates/boards/thread.html:104
230 #: templates/boards/posting_general.html:146 templates/boards/thread.html:93
231 msgid "comment"
232 msgstr "комментарий"
233
234 #: templates/boards/posting_general.html:178 templates/boards/thread.html:121
160 msgid "Post"
235 msgid "Post"
161 msgstr "Отправить"
236 msgstr "Отправить"
162
237
163 #: templates/boards/posting_general.html:165
238 #: templates/boards/posting_general.html:180
164 msgid "Tags must be delimited by spaces. Text or image is required."
239 msgid "Tags must be delimited by spaces. Text or image is required."
165 msgstr ""
240 msgstr ""
166 "Теги должны быть разделены пробелами. Текст или изображение обязательны."
241 "Теги должны быть разделены пробелами. Текст или изображение обязательны."
167
242
168 #: templates/boards/posting_general.html:168 templates/boards/thread.html:106
243 #: templates/boards/posting_general.html:183 templates/boards/thread.html:123
169 msgid "Text syntax"
244 msgid "Text syntax"
170 msgstr "Синтаксис текста"
245 msgstr "Синтаксис текста"
171
246
172 #: templates/boards/posting_general.html:178
247 #: templates/boards/posting_general.html:193
173 msgid "Pages:"
248 msgid "Pages:"
174 msgstr "Страницы: "
249 msgstr "Страницы: "
175
250
@@ -205,11 +280,11 b' msgstr "\xd1\x82\xd0\xb5\xd0\xbc"'
205 msgid "No tags found."
280 msgid "No tags found."
206 msgstr "Теги не найдены."
281 msgstr "Теги не найдены."
207
282
208 #: templates/boards/thread.html:77
283 #: templates/boards/thread.html:79
209 msgid "Reply to thread"
284 msgid "Reply to thread"
210 msgstr "Ответить в тему"
285 msgstr "Ответить в тему"
211
286
212 #: templates/boards/thread.html:118
287 #: templates/boards/thread.html:137
213 msgid "Last update: "
288 msgid "Last update: "
214 msgstr "Последнее обновление: "
289 msgstr "Последнее обновление: "
215
290
@@ -266,12 +341,6 b' msgstr "\xd0\xa1\xd1\x81\xd1\x8b\xd0\xbb\xd0\xba\xd0\xb0 \xd0\xbd\xd0\xb0 \xd1\x81\xd0\xbe\xd0\xbe\xd0\xb1\xd1\x89\xd0\xb5\xd0\xbd\xd0\xb8\xd0\xb5"'
266 #~ msgid "Example: "
341 #~ msgid "Example: "
267 #~ msgstr "Пример: "
342 #~ msgstr "Пример: "
268
343
269 #~ msgid "italic"
270 #~ msgstr "курсив"
271
272 #~ msgid "bold"
273 #~ msgstr "полужирный"
274
275 #~ msgid "tags"
344 #~ msgid "tags"
276 #~ msgstr "тегов"
345 #~ msgstr "тегов"
277
346
@@ -283,15 +352,3 b' msgstr "\xd0\xa1\xd1\x81\xd1\x8b\xd0\xbb\xd0\xba\xd0\xb0 \xd0\xbd\xd0\xb0 \xd1\x81\xd0\xbe\xd0\xbe\xd0\xb1\xd1\x89\xd0\xb5\xd0\xbd\xd0\xb8\xd0\xb5"'
283
352
284 #~ msgid "gets"
353 #~ msgid "gets"
285 #~ msgstr "гетов"
354 #~ msgstr "гетов"
286
287 #~ msgid "author"
288 #~ msgstr "автор"
289
290 #~ msgid "developer"
291 #~ msgstr "разработчик"
292
293 #~ msgid "javascript developer"
294 #~ msgstr "разработчик javascript"
295
296 #~ msgid "designer"
297 #~ msgstr "дизайнер"
@@ -110,7 +110,7 b' class PostManager(models.Manager):'
110
110
111 if opening_post.replies:
111 if opening_post.replies:
112 thread = [opening_post]
112 thread = [opening_post]
113 thread.extend(opening_post.replies.all())
113 thread.extend(opening_post.replies.all().order_by('pub_time'))
114
114
115 return thread
115 return thread
116
116
@@ -139,7 +139,7 b' class PostManager(models.Manager):'
139 # must not be shown and be able for replying.
139 # must not be shown and be able for replying.
140
140
141 threads = self.get_threads()
141 threads = self.get_threads()
142 thread_count = len(threads)
142 thread_count = threads.count()
143
143
144 if thread_count > settings.MAX_THREAD_COUNT:
144 if thread_count > settings.MAX_THREAD_COUNT:
145 num_threads_to_delete = thread_count - settings.MAX_THREAD_COUNT
145 num_threads_to_delete = thread_count - settings.MAX_THREAD_COUNT
@@ -269,7 +269,7 b' class Post(models.Model):'
269 if reply_count > 0:
269 if reply_count > 0:
270 reply_count_to_show = min(settings.LAST_REPLIES_COUNT,
270 reply_count_to_show = min(settings.LAST_REPLIES_COUNT,
271 reply_count)
271 reply_count)
272 last_replies = self.replies.all()[reply_count -
272 last_replies = self.replies.all().order_by('pub_time')[reply_count -
273 reply_count_to_show:]
273 reply_count_to_show:]
274
274
275 return last_replies
275 return last_replies
@@ -6,8 +6,6 b' from neboard import settings'
6
6
7 __author__ = 'neko259'
7 __author__ = 'neko259'
8
8
9 MAX_ITEMS = 20
10
11 # TODO Make tests for all of these
9 # TODO Make tests for all of these
12 class AllThreadsFeed(Feed):
10 class AllThreadsFeed(Feed):
13
11
@@ -16,7 +14,7 b' class AllThreadsFeed(Feed):'
16 description_template = 'boards/rss/post.html'
14 description_template = 'boards/rss/post.html'
17
15
18 def items(self):
16 def items(self):
19 return Post.objects.get_threads(order_by='-pub_time')[:MAX_ITEMS]
17 return Post.objects.get_threads(order_by='-pub_time')
20
18
21 def item_title(self, item):
19 def item_title(self, item):
22 return item.title
20 return item.title
@@ -35,7 +33,7 b' class TagThreadsFeed(Feed):'
35
33
36 def items(self, obj):
34 def items(self, obj):
37 return Post.objects.get_threads(tag=obj,
35 return Post.objects.get_threads(tag=obj,
38 order_by='-pub_time')[:MAX_ITEMS]
36 order_by='-pub_time')
39
37
40 def get_object(self, request, tag_name):
38 def get_object(self, request, tag_name):
41 return get_object_or_404(Tag, name=tag_name)
39 return get_object_or_404(Tag, name=tag_name)
@@ -59,7 +57,7 b' class ThreadPostsFeed(Feed):'
59 description_template = 'boards/rss/post.html'
57 description_template = 'boards/rss/post.html'
60
58
61 def items(self, obj):
59 def items(self, obj):
62 return Post.objects.get_thread(opening_post_id=obj)[:MAX_ITEMS]
60 return Post.objects.get_thread(opening_post_id=obj)
63
61
64 def get_object(self, request, post_id):
62 def get_object(self, request, post_id):
65 return post_id
63 return post_id
@@ -69,7 +67,7 b' class ThreadPostsFeed(Feed):'
69
67
70 def item_link(self, item):
68 def item_link(self, item):
71 if item.thread:
69 if item.thread:
72 return reverse('thread', args={item.parent}) + "#" + str(item.id)
70 return reverse('thread', args={item.thread.id}) + "#" + str(item.id)
73 else:
71 else:
74 return reverse('thread', args={item.id})
72 return reverse('thread', args={item.id})
75
73
@@ -77,4 +75,4 b' class ThreadPostsFeed(Feed):'
77 return item.pub_time
75 return item.pub_time
78
76
79 def title(self, obj):
77 def title(self, obj):
80 return get_object_or_404(Post, id=obj).title No newline at end of file
78 return get_object_or_404(Post, id=obj).title
@@ -189,6 +189,15 b' blockquote {'
189 background-color: #442222;
189 background-color: #442222;
190 }
190 }
191
191
192 .mark_btn {
193 padding: 2px 4px;
194 border: 1px solid;
195 }
196
197 .mark_btn:hover {
198 background: #555;
199 }
200
192 .quote {
201 .quote {
193 color: #92cf38;
202 color: #92cf38;
194 font-style: italic;
203 font-style: italic;
@@ -293,7 +302,6 b' input[type="submit"]:hover {'
293 background: #555;
302 background: #555;
294 }
303 }
295
304
296
297 .fav {
305 .fav {
298 color: yellow;
306 color: yellow;
299 }
307 }
@@ -304,4 +312,12 b' input[type="submit"]:hover {'
304
312
305 .role {
313 .role {
306 text-decoration: underline;
314 text-decoration: underline;
307 } No newline at end of file
315 }
316
317 .form-email {
318 display: none;
319 }
320
321 .footer {
322 margin: 5px;
323 }
@@ -301,4 +301,17 b' input[type="submit"]:hover {'
301
301
302 .role {
302 .role {
303 text-decoration: underline;
303 text-decoration: underline;
304 }
305
306 .form-email {
307 display: none;
308 }
309
310 .mark_btn {
311 padding: 2px 4px;
312 border: 1px solid;
313 }
314
315 .mark_btn:hover {
316 background: #ccc;
304 } No newline at end of file
317 }
@@ -148,11 +148,12 b' li {'
148 margin: 0 1ex 1em 1ex;
148 margin: 0 1ex 1em 1ex;
149 overflow-x: auto;
149 overflow-x: auto;
150 word-wrap: break-word;
150 word-wrap: break-word;
151 background: #FFF;
152 padding: 1ex;
153 border: 1px solid #666;
154 box-shadow: 1px 1px 2px 1px #666;
151 }
155 }
152 .last-replies > .post, #posts > .post {
156
153 border-bottom: 1px solid #182F6F;
154 padding-bottom: 1em;
155 }
156 #posts > .post:last-child {
157 #posts > .post:last-child {
157 border-bottom: none;
158 border-bottom: none;
158 padding-bottom: 0;
159 padding-bottom: 0;
@@ -223,15 +224,10 b' li {'
223 }
224 }
224
225
225 .thread > .post > .message > .post-info {
226 .thread > .post > .message > .post-info {
226 border-bottom: 2px solid #182F6F;
227 border-bottom: 1px solid #ccc;
227 padding-bottom: .5em;
228 padding-bottom: .5em;
228 }
229 }
229
230
230 .last-replies > .post:last-child {
231 border-bottom: none;
232 padding-bottom: 0;
233 }
234
235 :target .post_id {
231 :target .post_id {
236 background: #182F6F;
232 background: #182F6F;
237 color: #FFF;
233 color: #FFF;
@@ -284,4 +280,8 b' li {'
284
280
285 .role {
281 .role {
286 text-decoration: underline;
282 text-decoration: underline;
287 } No newline at end of file
283 }
284
285 .form-email {
286 display: none;
287 }
@@ -4,13 +4,10 b''
4 return false;
4 return false;
5 });
5 });
6
6
7 $(".fancy").fancybox({
7 addImgPreview();
8 closeBtn: false,
8 addRefLinkMap();
9 closeClick: true,
10 padding: 0,
11 openEffect: 'none',
12 closeEffect: 'none'
13 });
14
9
15 addRefLinkMap();
10 // TODO Rewrite popups module and reenable it
16 })
11 //addPopups();
12 addMarkPanel();
13 });
@@ -30,9 +30,10 b' function addRefLinkMap() {'
30 if(typeof refMap[pNum] === 'object') {
30 if(typeof refMap[pNum] === 'object') {
31 //append refmap panel
31 //append refmap panel
32 if(!$("#refmap_"+pNum).length) {
32 if(!$("#refmap_"+pNum).length) {
33 var data = label_replies + refMap[pNum].toString().replace(/(\d+)/g, ' <a href="/jump/$1/">>>$1</a>');
33 $('#'+pNum+'').find('.message').after(
34 $('#'+pNum+'').find('.message').after($('<div class="refmap" id="refmap_'+pNum+'">'+data+'</div>'));
34 $('<div class="refmap" id="refmap_'+pNum+'">'+label_replies + refMap[pNum].toString().replace(/(\d+)/g, ' <a href="/jump/$1/">>>$1</a>')+'</div>')
35 );
35 }
36 }
36 }
37 }
37 }
38 }
38 }
39 } No newline at end of file
@@ -1,75 +1,28 b''
1 var image_mode = 0;
1 function addGalleryPanel() {
2 var normal_dom, table_dom;
2 var gallery = $('a[class="thumb"]').clone(true),
3
3 normal = $('.post').clone(true);
4 function add_panel(after)
5 {
6 var nav_top = $(after);
7 if (nav_top.length === 0) return;
8 nav_top = nav_top[0];
9
10 var tab_bar = $('<div class="image-mode-tab" role="radiogroup" aria-label="Image mode"></div>');
11
12 var tab;
13
14 tab = $('<input type="radio" class="image-mode-normal" name="image-mode" value="0" checked="checked"/>');
15 tab.on("change", tab_handler);
16
17 var label_normal = gettext('Normal');
18 tab = $('<label>' + label_normal + '</label>').prepend(tab);
19 tab_bar.append(tab);
20
21 tab = $('<input type="radio" class="image-mode-table" name="image-mode" value="1"/>');
22 tab.on("change", tab_handler);
23
24 var label_gallery = gettext('Gallery');
25 tab = $('<label>' + label_gallery + '</label>').prepend(tab);
26 tab_bar.append(tab);
27
28 tab_bar.insertAfter(nav_top);
29 }
30
31 function tab_handler(ev)
32 {
33 var current_el = $(this);
34
4
35 if (!current_el.prop('checked')) return;
5 $('.navigation_panel').filter(':first').after(
36
6 '<div class="image-mode-tab" role="radiogroup" aria-label="Image mode2">' +
37 var new_mode = parseInt(current_el.val(), 10);
7 '<label><input type="radio" class="image-mode-normal" name="image-mode" value="0" checked="checked"/>'+ gettext('Normal') +'</label>' +
38 if (new_mode === image_mode) return;
8 '<label><input type="radio" class="image-mode-table" name="image-mode" value="1"/>'+ gettext('Gallery') +'</label>' +
39 image_mode = new_mode;
9 '</div>'
40
10 );
41 make_normal_dom();
42 make_table_dom();
43
11
44 switch(new_mode) {
12 $('input[name="image-mode"]').change(function() {
45 case 0:
13 //gallery mode
46 $('#posts-table').replaceWith(normal_dom);
14 if($(this).val() === '1') {
47 break;
15 $('.thread').replaceWith(
48 case 1:
16 $('<div id="posts-table"></div>').append(gallery)
49 $('#posts').replaceWith(table_dom);
50 break;
51 }
52 }
53
54 function make_normal_dom()
55 {
56 if (typeof normal_dom === 'undefined') {
57 normal_dom = $('#posts').clone(true);
58 }
59 }
60
61 function make_table_dom()
62 {
63 if (typeof table_dom !== 'undefined') return;
64
65 table_dom = $('<div id="posts-table"></div>');
66 $('#posts > .post > .image > a').each(
67 function(){
68 table_dom.append(
69 $(this).clone().attr('target', '_blank')
70 );
17 );
71 }
18 }
72 );
19 //normal mode
20 else {
21 $('#posts-table').replaceWith(
22 $('<div class="thread"></div>').append(normal)
23 );
24 }
25 });
73 }
26 }
74
27
75 function moveCaretToEnd(el) {
28 function moveCaretToEnd(el) {
@@ -98,6 +51,6 b' function addQuickReply(postId) {'
98
51
99
52
100 $(document).ready(function(){
53 $(document).ready(function(){
101 add_panel('.navigation_panel');
54 addGalleryPanel();
102 addRefLinkMap();
55 addRefLinkMap();
103 });
56 });
@@ -1,29 +1,35 b''
1 {% load staticfiles %}
1 {% load staticfiles %}
2 {% load i18n %}
2 {% load i18n %}
3 {% load static from staticfiles %}
3
4
4 <!DOCTYPE html>
5 <!DOCTYPE html>
5 <html>
6 <html>
6 <head>
7 <head>
7 <link rel="stylesheet" type="text/css"
8 <link rel="stylesheet" type="text/css"
8 href="{{ STATIC_URL }}css/jquery.fancybox.css" media="all"/>
9 href="{% static 'css/base.css' %}" media="all"/>
9 <link rel="stylesheet" type="text/css"
10 <link rel="stylesheet" type="text/css"
10 href="{{ STATIC_URL }}css/{{ theme }}/base_page.css?3" media="all"/>
11 href="{% static theme_css %}" media="all"/>
11 <link rel="alternate" type="application/rss+xml" href="rss/" title="
12 <link rel="alternate" type="application/rss+xml" href="rss/" title=
12 {% trans 'Feed' %}"/>
13 "{% trans 'Feed' %}"/>
13
14
14 <link rel="icon" type="image/png"
15 <link rel="icon" type="image/png"
15 href="{{ STATIC_URL }}favicon.png">
16 href="{% static 'favicon.png' %}">
16
17
17 <meta name="viewport" content="width=device-width, initial-scale=1"/>
18 <meta name="viewport" content="width=device-width, initial-scale=1"/>
18 <meta charset="utf-8"/>
19 <meta charset="utf-8"/>
20
19 {% block head %}{% endblock %}
21 {% block head %}{% endblock %}
20 </head>
22 </head>
21 <body>
23 <body>
22 <script src="{{ STATIC_URL }}js/jquery-2.0.1.min.js"></script>
24 <script src="{% static 'js/jquery-2.0.1.min.js' %}"></script>
23 <script src="{{ STATIC_URL }}js/jquery.fancybox.pack.js"></script>
25 <script src="{% static 'js/jquery-ui-1.10.3.custom.min.js' %}"></script>
26 <script src="{% static 'js/jquery.mousewheel.js' %}"></script>
24 <script src="{% url 'django.views.i18n.javascript_catalog' %}"></script>
27 <script src="{% url 'django.views.i18n.javascript_catalog' %}"></script>
25 <script src="{{ STATIC_URL }}js/refmaps.js"></script>
28 <script src="{% static 'js/refmaps.js' %}"></script>
26 <script src="{{ STATIC_URL }}js/main.js"></script>
29 <script src="{% static 'js/panel.js' %}"></script>
30 <script src="{% static 'js/popup.js' %}"></script>
31 <script src="{% static 'js/image.js' %}"></script>
32 <script src="{% static 'js/main.js' %}"></script>
27
33
28 <div class="navigation_panel">
34 <div class="navigation_panel">
29 <a class="link" href="{% url 'index' %}">{% trans "All threads" %}</a>
35 <a class="link" href="{% url 'index' %}">{% trans "All threads" %}</a>
@@ -31,7 +37,7 b''
31 <a class="tag" href="{% url 'tag' tag_name=tag.name %}"
37 <a class="tag" href="{% url 'tag' tag_name=tag.name %}"
32 >{{ tag.name }}</a>
38 >{{ tag.name }}</a>
33 {% endfor %}
39 {% endfor %}
34 <a class="tag" href="{% url 'tags' %}" alt="{% trans 'Tag management' %}"
40 <a class="tag" href="{% url 'tags' %}" title="{% trans 'Tag management' %}"
35 >[...]</a>
41 >[...]</a>
36 <a class="link" href="{% url 'settings' %}">{% trans 'Settings' %}</a>
42 <a class="link" href="{% url 'settings' %}">{% trans 'Settings' %}</a>
37 </div>
43 </div>
@@ -38,10 +38,10 b''
38 {% endif %}
38 {% endif %}
39 {% if thread.thread.image %}
39 {% if thread.thread.image %}
40 <div class="image">
40 <div class="image">
41 <a class="fancy"
41 <a class="thumb"
42 href="{{ thread.thread.image.url }}"><img
42 href="{{ thread.thread.image.url }}"><img
43 src="{{ thread.thread.image.url_200x150 }}"
43 src="{{ thread.thread.image.url_200x150 }}"
44 alt="{% trans 'Post image' %}"
44 alt="{{ thread.thread.id }}"
45 data-width="{{ thread.thread.image_width }}"
45 data-width="{{ thread.thread.image_width }}"
46 data-height="{{ thread.thread.image_height }}" />
46 data-height="{{ thread.thread.image_height }}" />
47 </a>
47 </a>
@@ -94,10 +94,10 b''
94 {% endif %}
94 {% endif %}
95 {% if post.image %}
95 {% if post.image %}
96 <div class="image">
96 <div class="image">
97 <a class="fancy"
97 <a class="thumb"
98 href="{{ post.image.url }}"><img
98 href="{{ post.image.url }}"><img
99 src=" {{ post.image.url_200x150 }}"
99 src=" {{ post.image.url_200x150 }}"
100 alt="{% trans 'Post image' %}"
100 alt="{{ post.id }}"
101 data-width="{{ post.image_width }}"
101 data-width="{{ post.image_width }}"
102 data-height="{{ post.image_height }}"/>
102 data-height="{{ post.image_height }}"/>
103 </a>
103 </a>
@@ -137,6 +137,16 b''
137 <div class="form-errors">{{ form.title.errors }}</div>
137 <div class="form-errors">{{ form.title.errors }}</div>
138 </div>
138 </div>
139 <div class="form-row">
139 <div class="form-row">
140 <div class="form-label">{% trans 'Formatting' %}</div>
141 <div class="form-input" id="mark_panel">
142 <span class="mark_btn" id="quote"><span class="quote">&gt;{% trans 'quote' %}</span></span>
143 <span class="mark_btn" id="italic"><i>{% trans 'italic' %}</i></span>
144 <span class="mark_btn" id="bold"><b>{% trans 'bold' %}</b></span>
145 <span class="mark_btn" id="spoiler"><span class="spoiler">{% trans 'spoiler' %}</span></span>
146 <span class="mark_btn" id="comment"><span class="comment">// {% trans 'comment' %}</span></span>
147 </div>
148 </div>
149 <div class="form-row">
140 <div class="form-label">{% trans 'Text' %}</div>
150 <div class="form-label">{% trans 'Text' %}</div>
141 <div class="form-input">{{ form.text }}</div>
151 <div class="form-input">{{ form.text }}</div>
142 <div class="form-errors">{{ form.text.errors }}</div>
152 <div class="form-errors">{{ form.text.errors }}</div>
@@ -151,6 +161,11 b''
151 <div class="form-input">{{ form.tags }}</div>
161 <div class="form-input">{{ form.tags }}</div>
152 <div class="form-errors">{{ form.tags.errors }}</div>
162 <div class="form-errors">{{ form.tags.errors }}</div>
153 </div>
163 </div>
164 <div class="form-row form-email">
165 <div class="form-label">{% trans 'e-mail' %}</div>
166 <div class="form-input">{{ form.email }}</div>
167 <div class="form-errors">{{ form.email.errors }}</div>
168 </div>
154 <div class="form-row">
169 <div class="form-row">
155 {{ form.captcha }}
170 {{ form.captcha }}
156 <div class="form-errors">{{ form.captcha.errors }}</div>
171 <div class="form-errors">{{ form.captcha.errors }}</div>
@@ -174,7 +189,7 b''
174 {% block metapanel %}
189 {% block metapanel %}
175
190
176 <span class="metapanel">
191 <span class="metapanel">
177 <b><a href="{% url "authors" %}">Neboard</a> 1.1</b>
192 <b><a href="{% url "authors" %}">Neboard</a> 1.2</b>
178 {% trans "Pages:" %}
193 {% trans "Pages:" %}
179 {% for page in pages %}
194 {% for page in pages %}
180 [<a href="
195 [<a href="
@@ -32,4 +32,4 b''
32 </div>
32 </div>
33 </div>
33 </div>
34
34
35 {% endblock %} No newline at end of file
35 {% endblock %}
@@ -3,18 +3,21 b''
3 {% load i18n %}
3 {% load i18n %}
4 {% load markup %}
4 {% load markup %}
5 {% load cache %}
5 {% load cache %}
6 {% load static from staticfiles %}
6
7
7 {% block head %}
8 {% block head %}
8 <title>Neboard - {{ posts.0.get_title }}</title>
9 <title>Neboard - {{ posts.0.get_title }}</title>
9 {% endblock %}
10 {% endblock %}
10
11
11 {% block content %}
12 {% block content %}
12 <script src="{{ STATIC_URL }}js/thread.js"></script>
13 {% get_current_language as LANGUAGE_CODE %}
14
15 <script src="{% static 'js/thread.js' %}"></script>
13
16
14 {% if posts %}
17 {% if posts %}
15 {% cache 600 thread_view posts.0.last_edit_time moderator %}
18 {% cache 600 thread_view posts.0.last_edit_time moderator LANGUAGE_CODE %}
16 <div id="posts">
19 <div class="thread">
17 {% for post in posts %}
20 {% for post in posts %}
18 {% if bumpable %}
21 {% if bumpable %}
19 <div class="post" id="{{ post.id }}">
22 <div class="post" id="{{ post.id }}">
20 {% else %}
23 {% else %}
@@ -23,10 +26,10 b''
23 {% if post.image %}
26 {% if post.image %}
24 <div class="image">
27 <div class="image">
25 <a
28 <a
26 class="fancy"
29 class="thumb"
27 href="{{ post.image.url }}"><img
30 href="{{ post.image.url }}"><img
28 src="{{ post.image.url_200x150 }}"
31 src="{{ post.image.url_200x150 }}"
29 alt="{% trans 'Post image' %}"v
32 alt="{{ post.id }}"
30 data-width="{{ post.image_width }}"
33 data-width="{{ post.image_width }}"
31 data-height="{{ post.image_height }}"/>
34 data-height="{{ post.image_height }}"/>
32 </a>
35 </a>
@@ -82,6 +85,16 b''
82 <div class="form-errors">{{ form.title.errors }}</div>
85 <div class="form-errors">{{ form.title.errors }}</div>
83 </div>
86 </div>
84 <div class="form-row">
87 <div class="form-row">
88 <div class="form-label">{% trans 'Formatting' %}</div>
89 <div class="form-input" id="mark_panel">
90 <span class="mark_btn" id="quote"><span class="quote">&gt;{% trans 'quote' %}</span></span>
91 <span class="mark_btn" id="italic"><i>{% trans 'italic' %}</i></span>
92 <span class="mark_btn" id="bold"><b>{% trans 'bold' %}</b></span>
93 <span class="mark_btn" id="spoiler"><span class="spoiler">{% trans 'spoiler' %}</span></span>
94 <span class="mark_btn" id="comment"><span class="comment">// {% trans 'comment' %}</span></span>
95 </div>
96 </div>
97 <div class="form-row">
85 <div class="form-label">{% trans 'Text' %}</div>
98 <div class="form-label">{% trans 'Text' %}</div>
86 <div class="form-input">{{ form.text }}</div>
99 <div class="form-input">{{ form.text }}</div>
87 <div class="form-errors">{{ form.text.errors }}</div>
100 <div class="form-errors">{{ form.text.errors }}</div>
@@ -91,6 +104,11 b''
91 <div class="form-input">{{ form.image }}</div>
104 <div class="form-input">{{ form.image }}</div>
92 <div class="form-errors">{{ form.image.errors }}</div>
105 <div class="form-errors">{{ form.image.errors }}</div>
93 </div>
106 </div>
107 <div class="form-row form-email">
108 <div class="form-label">{% trans 'e-mail' %}</div>
109 <div class="form-input">{{ form.email }}</div>
110 <div class="form-errors">{{ form.email.errors }}</div>
111 </div>
94 <div class="form-row">
112 <div class="form-row">
95 {{ form.captcha }}
113 {{ form.captcha }}
96 <div class="form-errors">{{ form.captcha.errors }}</div>
114 <div class="form-errors">{{ form.captcha.errors }}</div>
@@ -111,8 +129,10 b''
111
129
112 {% block metapanel %}
130 {% block metapanel %}
113
131
132 {% get_current_language as LANGUAGE_CODE %}
133
114 <span class="metapanel">
134 <span class="metapanel">
115 {% cache 600 thread_meta posts.0.last_edit_time moderator %}
135 {% cache 600 thread_meta posts.0.last_edit_time moderator LANGUAGE_CODE %}
116 {{ posts.0.get_reply_count }} {% trans 'replies' %},
136 {{ posts.0.get_reply_count }} {% trans 'replies' %},
117 {{ posts.0.get_images_count }} {% trans 'images' %}.
137 {{ posts.0.get_images_count }} {% trans 'images' %}.
118 {% trans 'Last update: ' %}{{ posts.0.last_edit_time }}
138 {% trans 'Last update: ' %}{{ posts.0.last_edit_time }}
@@ -30,7 +30,6 b" urlpatterns = patterns('',"
30
30
31 # /boards/thread/
31 # /boards/thread/
32 url(r'^thread/(?P<post_id>\w+)/$', views.thread, name='thread'),
32 url(r'^thread/(?P<post_id>\w+)/$', views.thread, name='thread'),
33 # /boards/theme/theme_name/
34 url(r'^settings/$', views.settings, name='settings'),
33 url(r'^settings/$', views.settings, name='settings'),
35 url(r'^tags/$', views.all_tags, name='tags'),
34 url(r'^tags/$', views.all_tags, name='tags'),
36 url(r'^captcha/', include('captcha.urls')),
35 url(r'^captcha/', include('captcha.urls')),
@@ -49,5 +48,9 b" urlpatterns = patterns('',"
49 url(r'^tag/(?P<tag_name>\w+)/page/(?P<page>\w+)/rss/$', TagThreadsFeed()),
48 url(r'^tag/(?P<tag_name>\w+)/page/(?P<page>\w+)/rss/$', TagThreadsFeed()),
50 url(r'^thread/(?P<post_id>\w+)/rss/$', ThreadPostsFeed()),
49 url(r'^thread/(?P<post_id>\w+)/rss/$', ThreadPostsFeed()),
51
50
51 # i18n
52 url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
52 url(r'^jsi18n/$', 'django.views.i18n.javascript_catalog', js_info_dict),
53
54 # API
55 url(r'^get_post/(?P<post_id>\w+)/$', views.get_post, name="get_post"),
53 )
56 )
@@ -62,3 +62,12 b' def update_captcha_access(request, passe'
62
62
63 session[KEY_CAPTCHA_LAST_ACTIVITY] = int(time.time())
63 session[KEY_CAPTCHA_LAST_ACTIVITY] = int(time.time())
64 session[KEY_CAPTCHA_DELAY_TIME] = delay_time
64 session[KEY_CAPTCHA_DELAY_TIME] = delay_time
65
66
67 def get_client_ip(request):
68 x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
69 if x_forwarded_for:
70 ip = x_forwarded_for.split(',')[-1].strip()
71 else:
72 ip = request.META.get('REMOTE_ADDR')
73 return ip No newline at end of file
@@ -1,7 +1,9 b''
1 import hashlib
1 import hashlib
2 import string
2 import string
3 from django.core import serializers
3 from django.core.urlresolvers import reverse
4 from django.core.urlresolvers import reverse
4 from django.http import HttpResponseRedirect
5 from django.http import HttpResponseRedirect
6 from django.http.response import HttpResponse
5 from django.template import RequestContext
7 from django.template import RequestContext
6 from django.shortcuts import render, redirect, get_object_or_404
8 from django.shortcuts import render, redirect, get_object_or_404
7 from django.utils import timezone
9 from django.utils import timezone
@@ -14,6 +16,7 b' from boards.forms import ThreadForm, Pos'
14
16
15 from boards.models import Post, Tag, Ban, User, RANK_USER, SETTING_MODERATE
17 from boards.models import Post, Tag, Ban, User, RANK_USER, SETTING_MODERATE
16 from boards import authors
18 from boards import authors
19 from boards.utils import get_client_ip
17 import neboard
20 import neboard
18
21
19
22
@@ -34,6 +37,9 b' def index(request, page=0):'
34
37
35 if form.is_valid():
38 if form.is_valid():
36 return _new_post(request, form)
39 return _new_post(request, form)
40 if form.need_to_ban:
41 # Ban user because he is suspected to be a bot
42 _ban_current_user(request)
37 else:
43 else:
38 form = threadFormClass(error_class=PlainErrorList, **kwargs)
44 form = threadFormClass(error_class=PlainErrorList, **kwargs)
39
45
@@ -53,8 +59,8 b' def index(request, page=0):'
53 def _new_post(request, form, thread_id=boards.models.NO_PARENT):
59 def _new_post(request, form, thread_id=boards.models.NO_PARENT):
54 """Add a new post (in thread or as a reply)."""
60 """Add a new post (in thread or as a reply)."""
55
61
56 ip = _get_client_ip(request)
62 ip = get_client_ip(request)
57 is_banned = Ban.objects.filter(ip=ip).count() > 0
63 is_banned = Ban.objects.filter(ip=ip).exists()
58
64
59 if is_banned:
65 if is_banned:
60 return redirect(you_are_banned)
66 return redirect(you_are_banned)
@@ -99,7 +105,10 b' def _new_post(request, form, thread_id=b'
99
105
100
106
101 def tag(request, tag_name, page=0):
107 def tag(request, tag_name, page=0):
102 """Get all tag threads (posts without a parent)."""
108 """
109 Get all tag threads. Threads are split in pages, so some page is
110 requested. Default page is 0.
111 """
103
112
104 tag = get_object_or_404(Tag, name=tag_name)
113 tag = get_object_or_404(Tag, name=tag_name)
105 threads = []
114 threads = []
@@ -112,6 +121,9 b' def tag(request, tag_name, page=0):'
112 error_class=PlainErrorList)
121 error_class=PlainErrorList)
113 if form.is_valid():
122 if form.is_valid():
114 return _new_post(request, form)
123 return _new_post(request, form)
124 if form.need_to_ban:
125 # Ban user because he is suspected to be a bot
126 _ban_current_user(request)
115 else:
127 else:
116 form = forms.ThreadForm(initial={'tags': tag_name},
128 form = forms.ThreadForm(initial={'tags': tag_name},
117 error_class=PlainErrorList)
129 error_class=PlainErrorList)
@@ -144,6 +156,9 b' def thread(request, post_id):'
144
156
145 if form.is_valid():
157 if form.is_valid():
146 return _new_post(request, form, post_id)
158 return _new_post(request, form, post_id)
159 if form.need_to_ban:
160 # Ban user because he is suspected to be a bot
161 _ban_current_user(request)
147 else:
162 else:
148 form = postFormClass(error_class=PlainErrorList, **kwargs)
163 form = postFormClass(error_class=PlainErrorList, **kwargs)
149
164
@@ -166,6 +181,8 b' def login(request):'
166 if request.method == 'POST':
181 if request.method == 'POST':
167 form = LoginForm(request.POST, request.FILES,
182 form = LoginForm(request.POST, request.FILES,
168 error_class=PlainErrorList)
183 error_class=PlainErrorList)
184 form.session = request.session
185
169 if form.is_valid():
186 if form.is_valid():
170 user = User.objects.get(user_id=form.cleaned_data['user_id'])
187 user = User.objects.get(user_id=form.cleaned_data['user_id'])
171 request.session['user_id'] = user.id
188 request.session['user_id'] = user.id
@@ -241,6 +258,8 b' def jump_to_post(request, post_id):'
241
258
242
259
243 def authors(request):
260 def authors(request):
261 """Show authors list"""
262
244 context = _init_default_context(request)
263 context = _init_default_context(request)
245 context['authors'] = boards.authors.authors
264 context['authors'] = boards.authors.authors
246
265
@@ -248,6 +267,8 b' def authors(request):'
248
267
249
268
250 def delete(request, post_id):
269 def delete(request, post_id):
270 """Delete post"""
271
251 user = _get_user(request)
272 user = _get_user(request)
252 post = get_object_or_404(Post, id=post_id)
273 post = get_object_or_404(Post, id=post_id)
253
274
@@ -262,6 +283,8 b' def delete(request, post_id):'
262
283
263
284
264 def ban(request, post_id):
285 def ban(request, post_id):
286 """Ban user"""
287
265 user = _get_user(request)
288 user = _get_user(request)
266 post = get_object_or_404(Post, id=post_id)
289 post = get_object_or_404(Post, id=post_id)
267
290
@@ -273,16 +296,22 b' def ban(request, post_id):'
273
296
274
297
275 def you_are_banned(request):
298 def you_are_banned(request):
299 """Show the page that notifies that user is banned"""
300
276 context = _init_default_context(request)
301 context = _init_default_context(request)
277 return render(request, 'boards/staticpages/banned.html', context)
302 return render(request, 'boards/staticpages/banned.html', context)
278
303
279
304
280 def page_404(request):
305 def page_404(request):
306 """Show page 404 (not found error)"""
307
281 context = _init_default_context(request)
308 context = _init_default_context(request)
282 return render(request, 'boards/404.html', context)
309 return render(request, 'boards/404.html', context)
283
310
284
311
285 def tag_subscribe(request, tag_name):
312 def tag_subscribe(request, tag_name):
313 """Add tag to favorites"""
314
286 user = _get_user(request)
315 user = _get_user(request)
287 tag = get_object_or_404(Tag, name=tag_name)
316 tag = get_object_or_404(Tag, name=tag_name)
288
317
@@ -293,6 +322,8 b' def tag_subscribe(request, tag_name):'
293
322
294
323
295 def tag_unsubscribe(request, tag_name):
324 def tag_unsubscribe(request, tag_name):
325 """Remove tag from favorites"""
326
296 user = _get_user(request)
327 user = _get_user(request)
297 tag = get_object_or_404(Tag, name=tag_name)
328 tag = get_object_or_404(Tag, name=tag_name)
298
329
@@ -303,10 +334,39 b' def tag_unsubscribe(request, tag_name):'
303
334
304
335
305 def static_page(request, name):
336 def static_page(request, name):
337 """Show a static page that needs only tags list and a CSS"""
338
306 context = _init_default_context(request)
339 context = _init_default_context(request)
307 return render(request, 'boards/staticpages/' + name + '.html', context)
340 return render(request, 'boards/staticpages/' + name + '.html', context)
308
341
309
342
343 def api_get_post(request, post_id):
344 """
345 Get the JSON of a post. This can be
346 used as and API for external clients.
347 """
348
349 post = get_object_or_404(Post, id=post_id)
350
351 json = serializers.serialize("json", [post], fields=(
352 "pub_time", "_text_rendered", "title", "text", "image",
353 "image_width", "image_height", "replies", "tags"
354 ))
355
356 return HttpResponse(content=json)
357
358
359 def get_post(request, post_id):
360 """Get the html of a post. Used for popups."""
361
362 post = get_object_or_404(Post, id=post_id)
363
364 context = RequestContext(request)
365 context["post"] = post
366
367 return render(request, 'boards/post.html', context)
368
369
310 def _get_theme(request, user=None):
370 def _get_theme(request, user=None):
311 """Get user's CSS theme"""
371 """Get user's CSS theme"""
312
372
@@ -319,15 +379,6 b' def _get_theme(request, user=None):'
319 return theme
379 return theme
320
380
321
381
322 def _get_client_ip(request):
323 x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
324 if x_forwarded_for:
325 ip = x_forwarded_for.split(',')[-1].strip()
326 else:
327 ip = request.META.get('REMOTE_ADDR')
328 return ip
329
330
331 def _init_default_context(request):
382 def _init_default_context(request):
332 """Create context with default values that are used in most views"""
383 """Create context with default values that are used in most views"""
333
384
@@ -336,8 +387,12 b' def _init_default_context(request):'
336 user = _get_user(request)
387 user = _get_user(request)
337 context['user'] = user
388 context['user'] = user
338 context['tags'] = user.get_sorted_fav_tags()
389 context['tags'] = user.get_sorted_fav_tags()
339 context['theme'] = _get_theme(request, user)
340
390
391 theme = _get_theme(request, user)
392 context['theme'] = theme
393 context['theme_css'] = 'css/' + theme + '/base_page.css'
394
395 # This shows the moderator panel
341 moderate = user.get_setting(SETTING_MODERATE)
396 moderate = user.get_setting(SETTING_MODERATE)
342 if moderate == 'True':
397 if moderate == 'True':
343 context['moderator'] = user.is_moderator()
398 context['moderator'] = user.is_moderator()
@@ -348,7 +403,10 b' def _init_default_context(request):'
348
403
349
404
350 def _get_user(request):
405 def _get_user(request):
351 """Get current user from the session"""
406 """
407 Get current user from the session. If the user does not exist, create
408 a new one.
409 """
352
410
353 session = request.session
411 session = request.session
354 if not 'user_id' in session:
412 if not 'user_id' in session:
@@ -370,8 +428,21 b' def _get_user(request):'
370
428
371
429
372 def _redirect_to_next(request):
430 def _redirect_to_next(request):
431 """
432 If a 'next' parameter was specified, redirect to the next page. This is
433 used when the user is required to return to some page after the current
434 view has finished its work.
435 """
436
373 if 'next' in request.GET:
437 if 'next' in request.GET:
374 next_page = request.GET['next']
438 next_page = request.GET['next']
375 return HttpResponseRedirect(next_page)
439 return HttpResponseRedirect(next_page)
376 else:
440 else:
377 return redirect(index)
441 return redirect(index)
442
443
444 def _ban_current_user(request):
445 """Add current user to the IP ban list"""
446
447 ip = utils.get_client_ip(request)
448 Ban.objects.get_or_create(ip=ip)
@@ -24,13 +24,6 b' DATABASES = {'
24 }
24 }
25 }
25 }
26
26
27 CACHES = {
28 'default': {
29 'BACKEND': 'django.core.cache.backends.db.DatabaseCache',
30 'LOCATION': 'neboard_cache',
31 }
32 }
33
34 # Local time zone for this installation. Choices can be found here:
27 # Local time zone for this installation. Choices can be found here:
35 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
28 # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
36 # although not all choices may be available on all operating systems.
29 # although not all choices may be available on all operating systems.
@@ -92,6 +85,8 b' STATICFILES_FINDERS = ('
92 # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
85 # 'django.contrib.staticfiles.finders.DefaultStorageFinder',
93 )
86 )
94
87
88 STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.CachedStaticFilesStorage'
89
95 # Make this unique, and don't share it with anybody.
90 # Make this unique, and don't share it with anybody.
96 SECRET_KEY = '@1rc$o(7=tt#kd+4s$u6wchm**z^)4x90)7f6z(i&amp;55@o11*8o'
91 SECRET_KEY = '@1rc$o(7=tt#kd+4s$u6wchm**z^)4x90)7f6z(i&amp;55@o11*8o'
97
92
@@ -117,7 +112,8 b' MIDDLEWARE_CLASSES = ('
117 'django.contrib.auth.middleware.AuthenticationMiddleware',
112 'django.contrib.auth.middleware.AuthenticationMiddleware',
118 'django.contrib.messages.middleware.MessageMiddleware',
113 'django.contrib.messages.middleware.MessageMiddleware',
119 # Uncomment the next line for simple clickjacking protection:
114 # Uncomment the next line for simple clickjacking protection:
120 # 'django.middleware.clickjacking.XFrameOptionsMiddleware',
115 # 'django.middleware.clickjacking.XFrameOptionsMiddleware'
116 'boards.middlewares.BanMiddleware',
121 )
117 )
122
118
123 ROOT_URLCONF = 'neboard.urls'
119 ROOT_URLCONF = 'neboard.urls'
@@ -195,6 +191,7 b" SITE_NAME = 'Neboard'"
195
191
196 THEMES = [
192 THEMES = [
197 ('md', 'Mystic Dark'),
193 ('md', 'Mystic Dark'),
194 ('md_centered', 'Mystic Dark (centered)'),
198 ('sw', 'Snow White'),
195 ('sw', 'Snow White'),
199 ('pg', 'Photon Gray'),
196 ('pg', 'Photon Gray'),
200 ]
197 ]
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed, binary diff hidden
NO CONTENT: file was removed, binary diff hidden
1 NO CONTENT: file was removed
NO CONTENT: file was removed
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now