PK @{Im$! # django-tabination-latest/.buildinfo# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config:
tags:
PK @{I0L $ django-tabination-latest/objects.inv# Sphinx inventory version 2
# Project: django-tabination
# Version: 0.4.0
# The remainder of this file is compressed using zlib.
xm
0Ew ]]蚭cB_Z F2&@7q9s,2'o~ Jc'8ieW"'EpssڬPO\LL%pqq^Y4_³PPK @{I|_'|
# django-tabination-latest/index.html
django-tabination is a library that enables you to easily build your own tab
navigation based on class based views.
The main idea behind this library is that the properties of the tabs are defined
inside the view and aren’t stored in the database. The database based approach
(which is used for example by django-sitetree or django-treenav, often
based on django-mptt) is great for CMS-like projects with users editing the
pages directly via the admin, but it causes many problems when the pages are
mainly coded directly in the views because the navigation is then not tracked by
your version control system and can be off-sync / inconsistent between different
versions or systems.
There are also projects that provide a set of template tags to mark a page as
active, which can then be used to render the navigation template accordingly
(e.g. django-tabs). But that solution is very limited and not as flexible as
django-tabination.
django-tabination allows you to create tabs directly in your class based views
by settings some specific attributes. This can be simplified even further by
creating a common base class for all your tab views that handles all the logic
necessary to build a dynamically configured tab navigation.
Features include conditional displaying/hiding of a tab, translation of the tab
labels, tab hierarchies to build multi-level navigations and more.
There are several ways to install django-tabination, either by using a
package manager like pip or by manually downloading and installing a
copy of the library.
The recommended way to install django-tabination is directly from pypi using
pip:
pip install django-tabination
If you prefer not to use an automated package installer, you can download a
copy of django-tabination and install it manually. To install it, navigate to
the directory containing setup.py on your console and type:
django-tabination is a library that enables you to easily build your
own tab navigation templates by extending the views.TabView base class.
The library is strongly based on the class based views that Django
has introduced with version 1.3. You cannot use this library if your
project is using function based views.
For a working custom tab view, the following things are requried:
You need to extend the views.TabView base class
You need to add the class attribute _is_tab=True to your view
You need to specify the tab_group.
Each tab needs a tab_id.
In order for the tab to be visible in your navigation, you need to
set a tab_label.
You need to define a template_name.
Note
The _is_tab attribute is needed for the class to be tracked by a
tracking metaclass. Therefore it needs to be present when the
classes are parsed by the Python interpreter and cannot be added
later, e.g. with a decorator.
Now your page will be rendered using the template tabs/spam_tab.html,
because views.TabView extends Django’s generic TemplateView.
If you want, you can also use other generic view mixins (or any other
custom mixins) to provide additional functionality. A good example would
be the SingleObjectMixin:
Now the SpamCan object with a primary key provided from your URL
definition will be passed on to your template as object (see
SingleObjectMixin documentation).
Warning
As of Django 1.4, above example does not work due to a bug in the
class based views implementation (get_context_data in the
generic mixins does not call super()). This is fixed in Django
1.5 (see Ticket #16074). If you’re still using Django 1.4 you can
either use generic mixins that don’t affect get_context_data,
manually call TabView.get_context_data(self,**kwargs) from your
tab code or create your own mixins. See the next section for an
example.
You can do everything with your TabView that you can do with normal
class based views. The only things that you need to bear in mind is that
views.TabView always needs to be the base class (on the right side of the
parentheses). It may be overloaded using mixins but cannot be combined
with other views that override get_context_data.
You can further customize your tab view by overloading the views.TabView‘s
class attributes with your own class- or instance attributes or
properties (if logic is required).
For available attributes, see views.TabView documentation. You can also
create your own attributes, as long as they’re used in your template.
Keep in mind that if the tab you’re working with is not the currently
loaded tab, it is just an instance of the tab that has not passed
through the dispatching functions. In case you need some variables that
you get only by dispatching the request (e.g. self.kwargs), you can
use the special attribute self.current_tab to gain access to the
currently loaded tab. See also section Accessing request data.
Here is an example of a more sophisticated tab view hierarchy:
fromdjango.contrib.auth.decoratorsimportlogin_requiredfromdjango.utilsimportdecoratorsfromdjango.utils.translationimportugettextas_fromtabination.viewsimportTabViewclassMainNavigationBaseTab(TabView):"""Base class for all main navigation tabs."""tab_group='main_navigation'tab_classes=['main-navigation-tab']defget_context_data(self,**kwargs):context=super(MainNavigationBaseTab,self).get_context_data(**kwargs)context['spam']='ham'returncontext@propertydeftab_classes(self):"""If user is logged in, set ``logged_in_only`` class."""classes=super(MainNavigationBaseTab,self).tab_classes[:]ifself.current_tab.request.user.is_authenticated():classes+=['logged_in_only']returnclassesclassSpamTab(MainNavigationBaseTab):"""A simple TabView."""_is_tab=Truetab_id='spam'tab_label=_('Spam')template_name='spam_tab.html'classHamTab(MainNavigationBaseTab):"""TabView is only visible after authentication."""_is_tab=Truetab_id='ham'tab_label=_('Ham')tab_rel='nofollow,noindex'template_name='ham_tab.html'@decorators.method_decorator(login_required)defdispatch(self,*args,**kwargs):"""Make sure only authenticated users can access this tab."""returnsuper(HamTab,self).dispatch(*args,**kwargs)@propertydeftab_visible(self):"""Show tab only if current user is logged in."""returnself.current_tab.request.user.is_authenticated()classHiddenTab(MainNavigationBaseTab):"""A hidden TabView."""_is_tab=Truetab_id='hidden'template_name='hidden_tab.html'
In this example, a base tab class was created. Because it does not
contain the _is_tab class attribute, it is not listed as a tab
itself (which wouldn’t be possible anyway, as it has no tab_id). The
three classes SpamTab, HamTab and HiddenTab
extend the MainNavigationBaseTab. The base class predefines a
tab group, so each extending tab doesn’t have to define it again,
therefore following the DRY principle. It also adds a new context
variable called spam to the context of each tab.
The second tab, HamTab, overrides some more attributes. In this
example, the tab is only visible in the template if the current user is
logged in. Additionally, if the user is logged in, a new CSS class
logged_in_only gets added to the tab_classes list, in order to be
able to show the user that this is a “secret” tab that guest users
aren’t able to see. A copy of the tab_classes list is used because
otherwise the CSS class would be added to all classes which extend
MainNavigationBaseTab.
The third tab, HiddenTab, doesn’t define a tab_label and is
therefore not shown at all (see default behavior of
views.TabView.tab_visible()).
Warning
Keep in mind that if you’re overriding get_context_data(self,**kwargs), you need to call the superclasses’ versions of the
method first (like in the example above). Otherwise, you’ll override
the tabs context variable.
If you want to access self.request in a function used to render the
tab item in your template, you may notice that it is not available. This
is because the tab instances other than your current tab don’t pass
through the request dispatching functions.
If you need access to your current request information, you can access
it via the self.current_tab attribute, e.g.:
In order to display the tabs in your templates, you need to create a tab
list using the {{tabs}} context variable. You can also use
{{current_tab_id}} to access the id of the currently active tab.
Here is an example template:
Each item in the {{tabs}} list is an instance of a tab in the same
tab group as the current tab. Therefore you can use all class- and
instance variables as well as all functions without arguments that are
defined in the views.TabView base class or in the extending class.
If you want to access the current tab instance, you can simply use the view
variable which is provided by Django’s ContextMixin.
It’s a good idea to put this template code in a file called e.g.
blocks/tabination.html and to include it everywhere you want
the navigation to be displayed:
django-tabination can also be used for multilevel navigation. You can
use the tab_parent attribute to connect two navigation levels. The
attribute is defined at the child base navigation class. The
following example has a tab called ParentTab which is at the first
navigation level. The base class of the second navigation level is
ChildNavigationBaseTab. This class defines the attribute
tab_parent to connect itself and all it’s siblings with the parent
navigation level.
fromtabination.viewsimportTabView# First navigation levelclassParentNavigationBaseTab(TabView):"""Base class for all parent navigation tabs."""tab_group='parent_navigation'tab_classes=['parent-navigation-tab']classParentTab(ParentNavigationBaseTab):_is_tab=Truetab_id='parent'tab_label='Parent'template_name='parent_tab.html'classEmptyTab(ParentNavigationBaseTab):_is_tab=Truetab_id='empty'tab_label='Empty'template_name='empty_tab.html'# Second navigation levelclassChildNavigationBaseTab(TabView):"""Base class for all child navigation tabs."""tab_group='child_navigation'tab_classes=['child-navigation-tab']tab_parent=ParentTabclassFirstChildTab(ChildNavigationBaseTab):_is_tab=Truetab_id='first_child'tab_label='First Child'template_name='first_child_tab.html'classSecondChildTab(ChildNavigationBaseTab):_is_tab=Truetab_id='second_child'tab_label='Second Child'template_name='second_child_tab.html'
If you use multilevel navigation new values are added to your template
context.
If the current tab has a parent tab the following values are added:
parent_tab_id
The tab_id of the parent tab.
parent_tabs
Instances of all tabs at the parent level.
The following variable is added to the template context if the current
tab is a parent tab and has one or more children:
child_tabs
A list of instances of all child tabs.
Because the {{current_tab}} and {{current_tab_id}} context
variables always refer to the globally current tab and not to the active
tab in the current tab group, you would have to write different
templates for the different levels of navigation to properly set an
active class on the tab item. To avoid this problem, you can use the
tab.group_current_tab attribute which is provided with every tab
object and refers to the active tab of the current tab group, no whether
where in the hierarchy the group is positioned.
If you didn’t quite understand the things above (it’s complicated I
know...), just take a look at the following example:
Tabs are sorted by their weight attribute automatically. Tabs with a
lower weight are sorted before tabs with a higher weight. The default
value of weight is 0. Negative values are also allowed and will be
sorted before postive values. If two tabs have the same weight the
natural order of the classes is used.
To set up a testing environment, you need to install Django and some additional
dependencies:
$ pip install Django
$ make install
To run the test suite, use
$ make test
If you want to generate a coverage report, use
$ make report
To see a HTML version of the coverage report, there’s
$ make report-html
Finally, to check conformance to the PEP8 coding standard, use
$ make flake8
Note
The flake8 configuration ignores E128 (continuation line under-indented for
visual indent) errors and allows a max line length of 99 characters per
line.
')
.appendTo($('#searchbox'));
}
},
/**
* init the domain index toggle buttons
*/
initIndexTable : function() {
var togglers = $('img.toggler').click(function() {
var src = $(this).attr('src');
var idnum = $(this).attr('id').substr(7);
$('tr.cg-' + idnum).toggle();
if (src.substr(-9) == 'minus.png')
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
else
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
}).css('display', '');
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
togglers.click();
}
},
/**
* helper function to hide the search marks again
*/
hideSearchWords : function() {
$('#searchbox .highlight-link').fadeOut(300);
$('span.highlighted').removeClass('highlighted');
},
/**
* make the url absolute
*/
makeURL : function(relativeURL) {
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
},
/**
* get the current relative url
*/
getCurrentURL : function() {
var path = document.location.pathname;
var parts = path.split(/\//);
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
if (this == '..')
parts.pop();
});
var url = parts.join('/');
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
}
};
// quick alias for translations
_ = Documentation.gettext;
$(document).ready(function() {
Documentation.init();
});
PK z@{I8c c . django-tabination-latest/_static/websupport.js/*
* websupport.js
* ~~~~~~~~~~~~~
*
* sphinx.websupport utilties for all documentation.
*
* :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
(function($) {
$.fn.autogrow = function() {
return this.each(function() {
var textarea = this;
$.fn.autogrow.resize(textarea);
$(textarea)
.focus(function() {
textarea.interval = setInterval(function() {
$.fn.autogrow.resize(textarea);
}, 500);
})
.blur(function() {
clearInterval(textarea.interval);
});
});
};
$.fn.autogrow.resize = function(textarea) {
var lineHeight = parseInt($(textarea).css('line-height'), 10);
var lines = textarea.value.split('\n');
var columns = textarea.cols;
var lineCount = 0;
$.each(lines, function() {
lineCount += Math.ceil(this.length / columns) || 1;
});
var height = lineHeight * (lineCount + 1);
$(textarea).css('height', height);
};
})(jQuery);
(function($) {
var comp, by;
function init() {
initEvents();
initComparator();
}
function initEvents() {
$(document).on("click", 'a.comment-close', function(event) {
event.preventDefault();
hide($(this).attr('id').substring(2));
});
$(document).on("click", 'a.vote', function(event) {
event.preventDefault();
handleVote($(this));
});
$(document).on("click", 'a.reply', function(event) {
event.preventDefault();
openReply($(this).attr('id').substring(2));
});
$(document).on("click", 'a.close-reply', function(event) {
event.preventDefault();
closeReply($(this).attr('id').substring(2));
});
$(document).on("click", 'a.sort-option', function(event) {
event.preventDefault();
handleReSort($(this));
});
$(document).on("click", 'a.show-proposal', function(event) {
event.preventDefault();
showProposal($(this).attr('id').substring(2));
});
$(document).on("click", 'a.hide-proposal', function(event) {
event.preventDefault();
hideProposal($(this).attr('id').substring(2));
});
$(document).on("click", 'a.show-propose-change', function(event) {
event.preventDefault();
showProposeChange($(this).attr('id').substring(2));
});
$(document).on("click", 'a.hide-propose-change', function(event) {
event.preventDefault();
hideProposeChange($(this).attr('id').substring(2));
});
$(document).on("click", 'a.accept-comment', function(event) {
event.preventDefault();
acceptComment($(this).attr('id').substring(2));
});
$(document).on("click", 'a.delete-comment', function(event) {
event.preventDefault();
deleteComment($(this).attr('id').substring(2));
});
$(document).on("click", 'a.comment-markup', function(event) {
event.preventDefault();
toggleCommentMarkupBox($(this).attr('id').substring(2));
});
}
/**
* Set comp, which is a comparator function used for sorting and
* inserting comments into the list.
*/
function setComparator() {
// If the first three letters are "asc", sort in ascending order
// and remove the prefix.
if (by.substring(0,3) == 'asc') {
var i = by.substring(3);
comp = function(a, b) { return a[i] - b[i]; };
} else {
// Otherwise sort in descending order.
comp = function(a, b) { return b[by] - a[by]; };
}
// Reset link styles and format the selected sort option.
$('a.sel').attr('href', '#').removeClass('sel');
$('a.by' + by).removeAttr('href').addClass('sel');
}
/**
* Create a comp function. If the user has preferences stored in
* the sortBy cookie, use those, otherwise use the default.
*/
function initComparator() {
by = 'rating'; // Default to sort by rating.
// If the sortBy cookie is set, use that instead.
if (document.cookie.length > 0) {
var start = document.cookie.indexOf('sortBy=');
if (start != -1) {
start = start + 7;
var end = document.cookie.indexOf(";", start);
if (end == -1) {
end = document.cookie.length;
by = unescape(document.cookie.substring(start, end));
}
}
}
setComparator();
}
/**
* Show a comment div.
*/
function show(id) {
$('#ao' + id).hide();
$('#ah' + id).show();
var context = $.extend({id: id}, opts);
var popup = $(renderTemplate(popupTemplate, context)).hide();
popup.find('textarea[name="proposal"]').hide();
popup.find('a.by' + by).addClass('sel');
var form = popup.find('#cf' + id);
form.submit(function(event) {
event.preventDefault();
addComment(form);
});
$('#s' + id).after(popup);
popup.slideDown('fast', function() {
getComments(id);
});
}
/**
* Hide a comment div.
*/
function hide(id) {
$('#ah' + id).hide();
$('#ao' + id).show();
var div = $('#sc' + id);
div.slideUp('fast', function() {
div.remove();
});
}
/**
* Perform an ajax request to get comments for a node
* and insert the comments into the comments tree.
*/
function getComments(id) {
$.ajax({
type: 'GET',
url: opts.getCommentsURL,
data: {node: id},
success: function(data, textStatus, request) {
var ul = $('#cl' + id);
var speed = 100;
$('#cf' + id)
.find('textarea[name="proposal"]')
.data('source', data.source);
if (data.comments.length === 0) {
ul.html('
No comments yet.
');
ul.data('empty', true);
} else {
// If there are comments, sort them and put them in the list.
var comments = sortComments(data.comments);
speed = data.comments.length * 100;
appendComments(comments, ul);
ul.data('empty', false);
}
$('#cn' + id).slideUp(speed + 200);
ul.slideDown(speed);
},
error: function(request, textStatus, error) {
showError('Oops, there was a problem retrieving the comments.');
},
dataType: 'json'
});
}
/**
* Add a comment via ajax and insert the comment into the comment tree.
*/
function addComment(form) {
var node_id = form.find('input[name="node"]').val();
var parent_id = form.find('input[name="parent"]').val();
var text = form.find('textarea[name="comment"]').val();
var proposal = form.find('textarea[name="proposal"]').val();
if (text == '') {
showError('Please enter a comment.');
return;
}
// Disable the form that is being submitted.
form.find('textarea,input').attr('disabled', 'disabled');
// Send the comment to the server.
$.ajax({
type: "POST",
url: opts.addCommentURL,
dataType: 'json',
data: {
node: node_id,
parent: parent_id,
text: text,
proposal: proposal
},
success: function(data, textStatus, error) {
// Reset the form.
if (node_id) {
hideProposeChange(node_id);
}
form.find('textarea')
.val('')
.add(form.find('input'))
.removeAttr('disabled');
var ul = $('#cl' + (node_id || parent_id));
if (ul.data('empty')) {
$(ul).empty();
ul.data('empty', false);
}
insertComment(data.comment);
var ao = $('#ao' + node_id);
ao.find('img').attr({'src': opts.commentBrightImage});
if (node_id) {
// if this was a "root" comment, remove the commenting box
// (the user can get it back by reopening the comment popup)
$('#ca' + node_id).slideUp();
}
},
error: function(request, textStatus, error) {
form.find('textarea,input').removeAttr('disabled');
showError('Oops, there was a problem adding the comment.');
}
});
}
/**
* Recursively append comments to the main comment list and children
* lists, creating the comment tree.
*/
function appendComments(comments, ul) {
$.each(comments, function() {
var div = createCommentDiv(this);
ul.append($(document.createElement('li')).html(div));
appendComments(this.children, div.find('ul.comment-children'));
// To avoid stagnating data, don't store the comments children in data.
this.children = null;
div.data('comment', this);
});
}
/**
* After adding a new comment, it must be inserted in the correct
* location in the comment tree.
*/
function insertComment(comment) {
var div = createCommentDiv(comment);
// To avoid stagnating data, don't store the comments children in data.
comment.children = null;
div.data('comment', comment);
var ul = $('#cl' + (comment.node || comment.parent));
var siblings = getChildren(ul);
var li = $(document.createElement('li'));
li.hide();
// Determine where in the parents children list to insert this comment.
for(i=0; i < siblings.length; i++) {
if (comp(comment, siblings[i]) <= 0) {
$('#cd' + siblings[i].id)
.parent()
.before(li.html(div));
li.slideDown('fast');
return;
}
}
// If we get here, this comment rates lower than all the others,
// or it is the only comment in the list.
ul.append(li.html(div));
li.slideDown('fast');
}
function acceptComment(id) {
$.ajax({
type: 'POST',
url: opts.acceptCommentURL,
data: {id: id},
success: function(data, textStatus, request) {
$('#cm' + id).fadeOut('fast');
$('#cd' + id).removeClass('moderate');
},
error: function(request, textStatus, error) {
showError('Oops, there was a problem accepting the comment.');
}
});
}
function deleteComment(id) {
$.ajax({
type: 'POST',
url: opts.deleteCommentURL,
data: {id: id},
success: function(data, textStatus, request) {
var div = $('#cd' + id);
if (data == 'delete') {
// Moderator mode: remove the comment and all children immediately
div.slideUp('fast', function() {
div.remove();
});
return;
}
// User mode: only mark the comment as deleted
div
.find('span.user-id:first')
.text('[deleted]').end()
.find('div.comment-text:first')
.text('[deleted]').end()
.find('#cm' + id + ', #dc' + id + ', #ac' + id + ', #rc' + id +
', #sp' + id + ', #hp' + id + ', #cr' + id + ', #rl' + id)
.remove();
var comment = div.data('comment');
comment.username = '[deleted]';
comment.text = '[deleted]';
div.data('comment', comment);
},
error: function(request, textStatus, error) {
showError('Oops, there was a problem deleting the comment.');
}
});
}
function showProposal(id) {
$('#sp' + id).hide();
$('#hp' + id).show();
$('#pr' + id).slideDown('fast');
}
function hideProposal(id) {
$('#hp' + id).hide();
$('#sp' + id).show();
$('#pr' + id).slideUp('fast');
}
function showProposeChange(id) {
$('#pc' + id).hide();
$('#hc' + id).show();
var textarea = $('#pt' + id);
textarea.val(textarea.data('source'));
$.fn.autogrow.resize(textarea[0]);
textarea.slideDown('fast');
}
function hideProposeChange(id) {
$('#hc' + id).hide();
$('#pc' + id).show();
var textarea = $('#pt' + id);
textarea.val('').removeAttr('disabled');
textarea.slideUp('fast');
}
function toggleCommentMarkupBox(id) {
$('#mb' + id).toggle();
}
/** Handle when the user clicks on a sort by link. */
function handleReSort(link) {
var classes = link.attr('class').split(/\s+/);
for (var i=0; iThank you! Your comment will show up '
+ 'once it is has been approved by a moderator.');
}
// Prettify the comment rating.
comment.pretty_rating = comment.rating + ' point' +
(comment.rating == 1 ? '' : 's');
// Make a class (for displaying not yet moderated comments differently)
comment.css_class = comment.displayed ? '' : ' moderate';
// Create a div for this comment.
var context = $.extend({}, opts, comment);
var div = $(renderTemplate(commentTemplate, context));
// If the user has voted on this comment, highlight the correct arrow.
if (comment.vote) {
var direction = (comment.vote == 1) ? 'u' : 'd';
div.find('#' + direction + 'v' + comment.id).hide();
div.find('#' + direction + 'u' + comment.id).show();
}
if (opts.moderator || comment.text != '[deleted]') {
div.find('a.reply').show();
if (comment.proposal_diff)
div.find('#sp' + comment.id).show();
if (opts.moderator && !comment.displayed)
div.find('#cm' + comment.id).show();
if (opts.moderator || (opts.username == comment.username))
div.find('#dc' + comment.id).show();
}
return div;
}
/**
* A simple template renderer. Placeholders such as <%id%> are replaced
* by context['id'] with items being escaped. Placeholders such as <#id#>
* are not escaped.
*/
function renderTemplate(template, context) {
var esc = $(document.createElement('div'));
function handle(ph, escape) {
var cur = context;
$.each(ph.split('.'), function() {
cur = cur[this];
});
return escape ? esc.text(cur || "").html() : cur;
}
return template.replace(/<([%#])([\w\.]*)\1>/g, function() {
return handle(arguments[2], arguments[1] == '%' ? true : false);
});
}
/** Flash an error message briefly. */
function showError(message) {
$(document.createElement('div')).attr({'class': 'popup-error'})
.append($(document.createElement('div'))
.attr({'class': 'error-message'}).text(message))
.appendTo('body')
.fadeIn("slow")
.delay(2000)
.fadeOut("slow");
}
/** Add a link the user uses to open the comments popup. */
$.fn.comment = function() {
return this.each(function() {
var id = $(this).attr('id').substring(1);
var count = COMMENT_METADATA[id];
var title = count + ' comment' + (count == 1 ? '' : 's');
var image = count > 0 ? opts.commentBrightImage : opts.commentImage;
var addcls = count == 0 ? ' nocomment' : '';
$(this)
.append(
$(document.createElement('a')).attr({
href: '#',
'class': 'sphinx-comment-open' + addcls,
id: 'ao' + id
})
.append($(document.createElement('img')).attr({
src: image,
alt: 'comment',
title: title
}))
.click(function(event) {
event.preventDefault();
show($(this).attr('id').substring(2));
})
)
.append(
$(document.createElement('a')).attr({
href: '#',
'class': 'sphinx-comment-close hidden',
id: 'ah' + id
})
.append($(document.createElement('img')).attr({
src: opts.closeCommentImage,
alt: 'close',
title: 'close'
}))
.click(function(event) {
event.preventDefault();
hide($(this).attr('id').substring(2));
})
);
});
};
var opts = {
processVoteURL: '/_process_vote',
addCommentURL: '/_add_comment',
getCommentsURL: '/_get_comments',
acceptCommentURL: '/_accept_comment',
deleteCommentURL: '/_delete_comment',
commentImage: '/static/_static/comment.png',
closeCommentImage: '/static/_static/comment-close.png',
loadingImage: '/static/_static/ajax-loader.gif',
commentBrightImage: '/static/_static/comment-bright.png',
upArrow: '/static/_static/up.png',
downArrow: '/static/_static/down.png',
upArrowPressed: '/static/_static/up-pressed.png',
downArrowPressed: '/static/_static/down-pressed.png',
voting: false,
moderator: false
};
if (typeof COMMENT_OPTIONS != "undefined") {
opts = jQuery.extend(opts, COMMENT_OPTIONS);
}
var popupTemplate = '\
\ Sort by:\ best rated\ newest\ oldest\
\\
Add a comment\ (markup):
\``code``
, \ code blocks:::
and an indented block after blank line