<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
{% compressed_css 'catalogue' %}
<title>{% block title %}{% trans "Platforma Redakcyjna" %}{% endblock title %}</title>
+ {% block add_css %}{% endblock %}
</head>
<body>
</div>
-<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
+<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
{% compressed_js 'catalogue' %}
+{% block add_js %}{% endblock %}
{% block extrabody %}
{% endblock %}
</body>
{% if book.single %}
{% with book.0 as chunk %}
<tr>
+ <td><input type="checkbox" name="select_book" value="{{book.id}}"/></td>
<td><a href="{% url catalogue_book book.slug %}" title='{% trans "Book settings" %}'>[B]</a></td>
<td><a href="{% url catalogue_chunk_edit book.slug chunk.slug %}" title='{% trans "Chunk settings" %}'>[c]</a></td>
<td><a target="_blank"
{% endwith %}
{% else %}
<tr>
+ <td><input type="checkbox" name="select_book" value="{{book.id}}"/></td>
<td class='book-settings-link'><a href="{% url catalogue_book book.slug %}" title='{% trans "Book settings" %}'>[B]</a></td>
<td></td>
<td>{{ book.title }}</td>
<input type='hidden' name="status" value="{{ request.GET.status }}" />
</form>
+
<table id="file-list"{% if viewed_user %} class="book-list-user"{% endif %}>
<thead><tr>
+ <th></th>
<th></th>
<th>
<input class='check-filter' type='checkbox' name='all' title='{% trans "Show hidden books" %}'
{% if not books %}
<p>{% trans "No books found." %}</p>
{% endif %}
+
+<form name='chunk_mass_edit' action='{% url catalogue_chunk_mass_edit %}' class="hidden">
+{% csrf_token %}
+<input type="hidden" name="ids" />
+<input type="hidden" stage="stage" />
+</form>
{% load i18n %}
<tr>
+ <td><input type="checkbox" name="select_chunk" value="{{chunk.id}}" data-book-id="{{chunk.book.id}}" /></td>
<td class='book-settings-column'></td>
<td><a href="{% url catalogue_chunk_edit chunk.book.slug chunk.slug %}" title='{% trans "Chunk settings" %}'>[c]</a></td>
<td><a target="_blank" href="{{ chunk.get_absolute_url }}">
{% load i18n %}
{% load catalogue book_list %}
+{% load compressed %}
+{% block add_js %}
+{% compressed_js 'book_list' %}
+{% endblock %}
+
+{% block add_css %}
+{% compressed_css 'book_list' %}
+{% endblock %}
+
{% block content %}
{% book_list %}
{% endblock content %}
'chunk_edit', name="catalogue_chunk_edit"),
url(r'^book_append/(?P<slug>[^/]+)/$',
'book_append', name="catalogue_book_append"),
+ url(r'^chunk_mass_edit',
+ 'chunk_mass_edit', name='catalogue_chunk_mass_edit'),
url(r'^track/(?P<slug>[^/]*)/$', PublishTrackFeed()),
)
from django.contrib.auth.decorators import login_required, permission_required
from django.core.urlresolvers import reverse
from django.db.models import Count, Q
+from django.db import transaction
from django import http
from django.http import Http404, HttpResponse, HttpResponseForbidden
from django.shortcuts import get_object_or_404, render, render_to_response
})
+@transaction.commit_on_success
+def chunk_mass_edit(request):
+ if request.method == 'POST':
+ ids = map(int, request.POST.get('ids').split(','))
+ chunks = map(lambda i: Chunk.objects.get(id=i), ids)
+ try:
+ stage = Chunk.tag_model.objects.get(slug=request.POST.get('stage'))
+ for c in chunks: c.stage = stage
+ except KeyError: pass
+
+ try:
+ user = User.objects.get(username=request.POST.get('user'))
+ for c in chunks: c.user = user
+ except KeyError: pass
+
+ for c in chunks: c.save()
+ else:
+ raise Http404
+
+
@permission_required('catalogue.change_book')
def book_append(request, slug):
book = get_object_or_404(Book, slug=slug)
'css/book.css',
),
'output_filename': 'compressed/book_?.css',
- }
+ },
+ 'book_list': {
+ 'source_filenames': (
+ 'contextmenu/jquery.contextMenu.css',
+ ),
+ 'output_filename': 'compressed/book_list_?.css',
+ },
}
COMPRESS_JS = {
'js/book_text/book.js',
),
'output_filename': 'compressed/book_?.js',
- }
+ },
+ 'book_list': {
+ 'source_filenames': (
+ 'contextmenu/jquery.ui.position.js',
+ 'contextmenu/jquery.contextMenu.js',
+ 'js/catalogue/book_list.js',
+ ),
+ 'output_filename': 'compressed/book_list_?.js',
+ }
}
COMPRESS = True
--- /dev/null
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+\r
+<html xmlns="http://www.w3.org/1999/xhtml">\r
+\r
+ <head>\r
+ <title>jQuery Context Menu Plugin Demo</title>\r
+ <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />\r
+ \r
+ <style type="text/css">\r
+ BODY,\r
+ HTML {\r
+ padding: 0px;\r
+ margin: 0px;\r
+ }\r
+ BODY {\r
+ font-family: Verdana, Arial, Helvetica, sans-serif;\r
+ font-size: 11px;\r
+ background: #FFF;\r
+ padding: 15px;\r
+ }\r
+ \r
+ H1 {\r
+ font-family: Georgia, serif;\r
+ font-size: 20px;\r
+ font-weight: normal;\r
+ }\r
+ \r
+ H2 {\r
+ font-family: Georgia, serif;\r
+ font-size: 16px;\r
+ font-weight: normal;\r
+ margin: 0px 0px 10px 0px;\r
+ }\r
+ \r
+ #myDiv {\r
+ width: 150px;\r
+ border: solid 1px #2AA7DE;\r
+ background: #6CC8EF;\r
+ text-align: center;\r
+ padding: 4em .5em;\r
+ margin: 1em;\r
+ float: left;\r
+ }\r
+ \r
+ #myList {\r
+ margin: 1em;\r
+ float: left;\r
+ }\r
+ \r
+ #myList UL {\r
+ padding: 0px;\r
+ margin: 0em 1em;\r
+ }\r
+ \r
+ #myList LI {\r
+ width: 100px;\r
+ border: solid 1px #2AA7DE;\r
+ background: #6CC8EF;\r
+ padding: 5px 5px;\r
+ margin: 2px 0px;\r
+ list-style: none;\r
+ }\r
+ \r
+ #options {\r
+ clear: left;\r
+ }\r
+ \r
+ #options INPUT {\r
+ font-family: Verdana, Arial, Helvetica, sans-serif;\r
+ font-size: 11px;\r
+ width: 150px;\r
+ }\r
+ \r
+ </style> \r
+ \r
+ <script src="../js/lib/jquery-1.4.2.min.js" type="text/javascript"></script>\r
+ <script src="jquery.contextMenu.js" type="text/javascript"></script>\r
+ <link href="jquery.contextMenu.css" rel="stylesheet" type="text/css" />\r
+ \r
+ <script type="text/javascript">\r
+ \r
+ $(document).ready( function() {\r
+ \r
+ // Show menu when #myDiv is clicked\r
+ $("#myDiv").contextMenu({\r
+ menu: 'myMenu'\r
+ },\r
+ function(action, el, pos) {\r
+ alert(\r
+ 'Action: ' + action + '\n\n' +\r
+ 'Element ID: ' + $(el).attr('id') + '\n\n' + \r
+ 'X: ' + pos.x + ' Y: ' + pos.y + ' (relative to element)\n\n' + \r
+ 'X: ' + pos.docX + ' Y: ' + pos.docY+ ' (relative to document)'\r
+ );\r
+ });\r
+ \r
+ // Show menu when a list item is clicked\r
+ $("#myList UL LI").contextMenu({\r
+ menu: 'myMenu'\r
+ }, function(action, el, pos) {\r
+ alert(\r
+ 'Action: ' + action + '\n\n' +\r
+ 'Element text: ' + $(el).text() + '\n\n' + \r
+ 'X: ' + pos.x + ' Y: ' + pos.y + ' (relative to element)\n\n' + \r
+ 'X: ' + pos.docX + ' Y: ' + pos.docY+ ' (relative to document)'\r
+ );\r
+ });\r
+ \r
+ // Disable menus\r
+ $("#disableMenus").click( function() {\r
+ $('#myDiv, #myList UL LI').disableContextMenu();\r
+ $(this).attr('disabled', true);\r
+ $("#enableMenus").attr('disabled', false);\r
+ });\r
+ \r
+ // Enable menus\r
+ $("#enableMenus").click( function() {\r
+ $('#myDiv, #myList UL LI').enableContextMenu();\r
+ $(this).attr('disabled', true);\r
+ $("#disableMenus").attr('disabled', false);\r
+ });\r
+ \r
+ // Disable cut/copy\r
+ $("#disableItems").click( function() {\r
+ $('#myMenu').disableContextMenuItems('#cut,#copy');\r
+ $(this).attr('disabled', true);\r
+ $("#enableItems").attr('disabled', false);\r
+ });\r
+ \r
+ // Enable cut/copy\r
+ $("#enableItems").click( function() {\r
+ $('#myMenu').enableContextMenuItems('#cut,#copy');\r
+ $(this).attr('disabled', true);\r
+ $("#disableItems").attr('disabled', false);\r
+ }); \r
+ \r
+ });\r
+ \r
+ </script>\r
+ </head>\r
+ \r
+ <body>\r
+ \r
+ <h1>jQuery Context Menu Plugin Demo</h1>\r
+ <p>\r
+ This plugin lets you add context menu functionality to your web applications.\r
+ </p>\r
+ \r
+ <p>\r
+ <strong>Tip:</strong> Try using your keyboard to make a selection.\r
+ </p>\r
+ \r
+ <p>\r
+ <a href="http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/">Back to the project page</a>\r
+ </p>\r
+ \r
+ <h2>Demo</h2>\r
+ \r
+ <div id="myDiv">\r
+ Right click to view the context menu\r
+ </div>\r
+ \r
+ <div id="myList">\r
+ <ul>\r
+ <li>Item 1</li>\r
+ <li>Item 2</li>\r
+ <li>Item 3</li>\r
+ <li>Item 4</li>\r
+ <li>Item 5</li>\r
+ <li>Item 6</li>\r
+ </ul>\r
+ </div>\r
+ \r
+ <div id="options">\r
+ <p>\r
+ <input type="button" id="disableItems" value="Disable Cut/Copy" />\r
+ <input type="button" id="enableItems" value="Enable Cut/Copy" disabled="disabled" />\r
+ </p>\r
+ \r
+ <p>\r
+ <input type="button" id="disableMenus" value="Disable Context Menus" />\r
+ <input type="button" id="enableMenus" value="Enable Context Menus" disabled="disabled" />\r
+ </p>\r
+ </div>\r
+ \r
+ <ul id="myMenu" class="contextMenu">\r
+ <li class="edit"><a href="#edit">Edit</a></li>\r
+ <li class="cut separator"><a href="#cut">Cut</a>\r
+ <ul>\r
+ <li class="pe"><a href="#pe">Pe</a></li>\r
+ </ul>\r
+ </li>\r
+ <li class="copy"><a href="#copy">Copy</a></li>\r
+ <li class="paste"><a href="#paste">Paste</a></li>\r
+ <li class="delete"><a href="#delete">Delete</a></li>\r
+ <li class="quit separator"><a href="#quit">Quit</a></li>\r
+ </ul>\r
+ \r
+ </body>\r
+</html>\r
--- /dev/null
+/* Generic context menu styles */\r
+.contextMenu {\r
+ position: absolute;\r
+ width: 120px;\r
+ z-index: 99999;\r
+ border: solid 1px #CCC;\r
+ background: #EEE;\r
+ padding: 0px;\r
+ margin: 0px;\r
+ display: none;\r
+}\r
+\r
+.contextMenu LI {\r
+ list-style: none;\r
+ padding: 0px;\r
+ margin: 0px;\r
+}\r
+\r
+.contextMenu A {\r
+ color: #333;\r
+ text-decoration: none;\r
+ display: block;\r
+ line-height: 20px;\r
+ height: 20px;\r
+ background-position: 6px center;\r
+ background-repeat: no-repeat;\r
+ outline: none;\r
+ padding: 1px 5px;\r
+ padding-left: 28px;\r
+}\r
+\r
+.contextMenu LI.hover A {\r
+ color: #FFF;\r
+ background-color: #3399FF;\r
+}\r
+\r
+.contextMenu LI.disabled A {\r
+ color: #AAA;\r
+ cursor: default;\r
+}\r
+\r
+.contextMenu LI.hover.disabled A {\r
+ background-color: transparent;\r
+}\r
+\r
+.contextMenu LI.separator {\r
+ border-top: solid 1px #CCC;\r
+}\r
+\r
+/*\r
+ Adding Icons\r
+ \r
+ You can add icons to the context menu by adding\r
+ classes to the respective LI element(s)\r
+*/\r
+\r
+.contextMenu LI.edit A { background-image: url(images/page_white_edit.png); }\r
+.contextMenu LI.cut A { background-image: url(images/cut.png); }\r
+.contextMenu LI.copy A { background-image: url(images/page_white_copy.png); }\r
+.contextMenu LI.paste A { background-image: url(images/page_white_paste.png); }\r
+.contextMenu LI.delete A { background-image: url(images/page_white_delete.png); }\r
+.contextMenu LI.quit A { background-image: url(images/door.png); }\r
--- /dev/null
+// jQuery Context Menu Plugin\r
+//\r
+// Version 1.01\r
+//\r
+// Cory S.N. LaViska\r
+// A Beautiful Site (http://abeautifulsite.net/)\r
+//\r
+// More info: http://abeautifulsite.net/2008/09/jquery-context-menu-plugin/\r
+//\r
+// Terms of Use\r
+//\r
+// This plugin is dual-licensed under the GNU General Public License\r
+// and the MIT License and is copyright A Beautiful Site, LLC.\r
+//\r
+if(jQuery)( function() {\r
+ $.extend($.fn, {\r
+ \r
+ contextMenu: function(o, callback) {\r
+ // Defaults\r
+ if( o.menu == undefined ) return false;\r
+ if( o.inSpeed == undefined ) o.inSpeed = 150;\r
+ if( o.outSpeed == undefined ) o.outSpeed = 75;\r
+ // 0 needs to be -1 for expected results (no fade)\r
+ if( o.inSpeed == 0 ) o.inSpeed = -1;\r
+ if( o.outSpeed == 0 ) o.outSpeed = -1;\r
+ // Loop each context menu\r
+ $(this).each( function() {\r
+ var el = $(this);\r
+ var offset = $(el).offset();\r
+ // Add contextMenu class\r
+ $('#' + o.menu).addClass('contextMenu');\r
+ // Simulate a true right click\r
+ $(this).mousedown( function(e) {\r
+ var evt = e;\r
+ evt.stopPropagation();\r
+ $(this).mouseup( function(e) {\r
+ e.stopPropagation();\r
+ var srcElement = $(this);\r
+ $(this).unbind('mouseup');\r
+ if( evt.button == 2 ) {\r
+ // Hide context menus that may be showing\r
+ $(".contextMenu").hide();\r
+ // Get this context menu\r
+ var menu = $('#' + o.menu);\r
+ \r
+ if( $(el).hasClass('disabled') ) return false;\r
+ \r
+ // Detect mouse position\r
+ var d = {}, x, y;\r
+ if( self.innerHeight ) {\r
+ d.pageYOffset = self.pageYOffset;\r
+ d.pageXOffset = self.pageXOffset;\r
+ d.innerHeight = self.innerHeight;\r
+ d.innerWidth = self.innerWidth;\r
+ } else if( document.documentElement &&\r
+ document.documentElement.clientHeight ) {\r
+ d.pageYOffset = document.documentElement.scrollTop;\r
+ d.pageXOffset = document.documentElement.scrollLeft;\r
+ d.innerHeight = document.documentElement.clientHeight;\r
+ d.innerWidth = document.documentElement.clientWidth;\r
+ } else if( document.body ) {\r
+ d.pageYOffset = document.body.scrollTop;\r
+ d.pageXOffset = document.body.scrollLeft;\r
+ d.innerHeight = document.body.clientHeight;\r
+ d.innerWidth = document.body.clientWidth;\r
+ }\r
+ (e.pageX) ? x = e.pageX : x = e.clientX + d.scrollLeft;\r
+ (e.pageY) ? y = e.pageY : y = e.clientY + d.scrollTop;\r
+ \r
+ // Show the menu\r
+ $(document).unbind('click');\r
+ $(menu).css({ top: y, left: x }).fadeIn(o.inSpeed);\r
+ // Hover events\r
+ $(menu).find('A').mouseover( function() {\r
+ $(menu).find('LI.hover').removeClass('hover');\r
+ $(this).parent().addClass('hover');\r
+ }).mouseout( function() {\r
+ $(menu).find('LI.hover').removeClass('hover');\r
+ });\r
+ \r
+ // Keyboard\r
+ $(document).keypress( function(e) {\r
+ switch( e.keyCode ) {\r
+ case 38: // up\r
+ if( $(menu).find('LI.hover').size() == 0 ) {\r
+ $(menu).find('LI:last').addClass('hover');\r
+ } else {\r
+ $(menu).find('LI.hover').removeClass('hover').prevAll('LI:not(.disabled)').eq(0).addClass('hover');\r
+ if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:last').addClass('hover');\r
+ }\r
+ break;\r
+ case 40: // down\r
+ if( $(menu).find('LI.hover').size() == 0 ) {\r
+ $(menu).find('LI:first').addClass('hover');\r
+ } else {\r
+ $(menu).find('LI.hover').removeClass('hover').nextAll('LI:not(.disabled)').eq(0).addClass('hover');\r
+ if( $(menu).find('LI.hover').size() == 0 ) $(menu).find('LI:first').addClass('hover');\r
+ }\r
+ break;\r
+ case 13: // enter\r
+ $(menu).find('LI.hover A').trigger('click');\r
+ break;\r
+ case 27: // esc\r
+ $(document).trigger('click');\r
+ break\r
+ }\r
+ });\r
+ \r
+ // When items are selected\r
+ $('#' + o.menu).find('A').unbind('click');\r
+ $('#' + o.menu).find('LI:not(.disabled) A').click( function() {\r
+ $(document).unbind('click').unbind('keypress');\r
+ $(".contextMenu").hide();\r
+ // Callback\r
+ if( callback ) callback( $(this).attr('href').substr(1), $(srcElement), {x: x - offset.left, y: y - offset.top, docX: x, docY: y} );\r
+ return false;\r
+ });\r
+ \r
+ // Hide bindings\r
+ setTimeout( function() { // Delay for Mozilla\r
+ $(document).click( function() {\r
+ $(document).unbind('click').unbind('keypress');\r
+ $(menu).fadeOut(o.outSpeed);\r
+ return false;\r
+ });\r
+ }, 0);\r
+ }\r
+ });\r
+ });\r
+ \r
+ // Disable text selection\r
+ if( $.browser.mozilla ) {\r
+ $('#' + o.menu).each( function() { $(this).css({ 'MozUserSelect' : 'none' }); });\r
+ } else if( $.browser.msie ) {\r
+ $('#' + o.menu).each( function() { $(this).bind('selectstart.disableTextSelect', function() { return false; }); });\r
+ } else {\r
+ $('#' + o.menu).each(function() { $(this).bind('mousedown.disableTextSelect', function() { return false; }); });\r
+ }\r
+ // Disable browser context menu (requires both selectors to work in IE/Safari + FF/Chrome)\r
+ $(el).add($('UL.contextMenu')).bind('contextmenu', function() { return false; });\r
+ \r
+ });\r
+ return $(this);\r
+ },\r
+ \r
+ // Disable context menu items on the fly\r
+ disableContextMenuItems: function(o) {\r
+ if( o == undefined ) {\r
+ // Disable all\r
+ $(this).find('LI').addClass('disabled');\r
+ return( $(this) );\r
+ }\r
+ $(this).each( function() {\r
+ if( o != undefined ) {\r
+ var d = o.split(',');\r
+ for( var i = 0; i < d.length; i++ ) {\r
+ $(this).find('A[href="' + d[i] + '"]').parent().addClass('disabled');\r
+ \r
+ }\r
+ }\r
+ });\r
+ return( $(this) );\r
+ },\r
+ \r
+ // Enable context menu items on the fly\r
+ enableContextMenuItems: function(o) {\r
+ if( o == undefined ) {\r
+ // Enable all\r
+ $(this).find('LI.disabled').removeClass('disabled');\r
+ return( $(this) );\r
+ }\r
+ $(this).each( function() {\r
+ if( o != undefined ) {\r
+ var d = o.split(',');\r
+ for( var i = 0; i < d.length; i++ ) {\r
+ $(this).find('A[href="' + d[i] + '"]').parent().removeClass('disabled');\r
+ \r
+ }\r
+ }\r
+ });\r
+ return( $(this) );\r
+ },\r
+ \r
+ // Disable context menu(s)\r
+ disableContextMenu: function() {\r
+ $(this).each( function() {\r
+ $(this).addClass('disabled');\r
+ });\r
+ return( $(this) );\r
+ },\r
+ \r
+ // Enable context menu(s)\r
+ enableContextMenu: function() {\r
+ $(this).each( function() {\r
+ $(this).removeClass('disabled');\r
+ });\r
+ return( $(this) );\r
+ },\r
+ \r
+ // Destroy context menu(s)\r
+ destroyContextMenu: function() {\r
+ // Destroy specified context menus\r
+ $(this).each( function() {\r
+ // Disable action\r
+ $(this).unbind('mousedown').unbind('mouseup');\r
+ });\r
+ return( $(this) );\r
+ }\r
+ \r
+ });\r
+})(jQuery);
\ No newline at end of file
--- /dev/null
+(function($) {
+ $(function() {
+ // clicking on book checks chunks, too
+ $("input[name=select_book]").change(function(ev) {
+ $book = $(this);
+ $book.closest("table").find("input[name=select_chunk][data-book-id=" + $book.val() + "]").attr("checked", $book.is(':checked'));
+ });
+
+ // initialize context menu
+
+ var get_ids = function() {
+ return $.map($("input[name=select_chunk]:checked"), function(ele, idx) {
+ return ele.value;
+ }).join();
+ };
+
+ var set_stage = function(key, opt) {
+ var stage = $("select[name=stage] option[value!=]").eq(key).val();
+ $.post($('input[name=chunk_mass_edit_url]').val(),
+ {
+ ids: get_ids(),
+ stage: stage,
+ },
+ function(data, status) {
+ location.reload(true);
+ }
+ );
+ };
+
+ $.contextMenu({
+ selector: '#file-list',
+ items: {
+ "stage": {
+ name: "Set stage",
+ items: $.map($("select[name=stage] option[value!=]"),
+ function(ele, idx) {
+ return {
+ name: $(ele).text(),
+ callback: set_stage,
+ };
+ }),
+ },
+/* "user": {
+ name: "Set user",
+
+ },
+ "status": {
+ name: "Set status",
+ items:
+ },*/
+
+ },
+ });
+
+ });
+})(jQuery);