Added tagging, and a nice tag editor component.
This commit is contained in:
parent
d2907d72e8
commit
91338e7691
|
@ -31,7 +31,7 @@ beaker.session.secret = somesecret
|
|||
#beaker.session.data_dir = %(here)s/data/sessions
|
||||
|
||||
# SQLAlchemy database URL
|
||||
sqlalchemy.url = sqlite:///%(here)s/scribeengine.sqlite
|
||||
sqlalchemy.url = sqlite:///%(here)s/code365.sqlite
|
||||
|
||||
# Images directory
|
||||
paths.images = %(here)s/images
|
||||
|
@ -39,7 +39,7 @@ paths.images = %(here)s/images
|
|||
paths.themes = %(here)s/themes
|
||||
|
||||
# Security settings
|
||||
security.salt = secretsalt
|
||||
security.salt = xgH,{@1pgtU9,nLd
|
||||
|
||||
mail.on = false
|
||||
mail.manager = immediate
|
||||
|
|
|
@ -25,13 +25,18 @@ from datetime import datetime
|
|||
|
||||
from scribeengine.lib.base import *
|
||||
from scribeengine.lib import utils
|
||||
from scribeengine.model import Post
|
||||
from scribeengine.model import Post, Tag
|
||||
from scribeengine.model.meta import Session
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
class PostController(BaseController):
|
||||
|
||||
def __before__(self):
|
||||
BaseController.__before__(self)
|
||||
self._add_javascript(u'jquery.tag.editor.js')
|
||||
self._add_javascript(u'ScribeEngine.Post.js')
|
||||
|
||||
def index(self):
|
||||
h.redirect_to('/')
|
||||
|
||||
|
@ -61,6 +66,13 @@ class PostController(BaseController):
|
|||
post.body = c.form_values[u'body']
|
||||
post.status = u'published'
|
||||
post.url = url
|
||||
tags = c.form_values[u'tags']
|
||||
tag_list = [tag_name.strip() for tag_name in tags.split(u',')]
|
||||
for tag in post.tags:
|
||||
if tag.name in tag_list:
|
||||
del tag_list[tag.name]
|
||||
for tag in tag_list:
|
||||
post.tags.append(Tag(name=tag, url=utils.generate_url(tag)))
|
||||
Session.add(post)
|
||||
Session.commit()
|
||||
h.redirect_to(str('/archive/%s/%s' % (post.created.strftime('%Y/%m/%d'), post.url)))
|
||||
|
|
|
@ -63,8 +63,8 @@ class BaseController(WSGIController):
|
|||
self._add_javascript(u'jquery.js')
|
||||
if c.jsvalidation:
|
||||
self._add_javascript(u'jquery.validate.js')
|
||||
self._add_javascript(u'scribeengine.js')
|
||||
self._add_jsinit(u'init.js')
|
||||
self._add_javascript(u'ScribeEngine.js')
|
||||
self._add_jsinit(u'ScribeEngine.Init.js')
|
||||
|
||||
def __call__(self, environ, start_response):
|
||||
"""Invoke the Controller"""
|
||||
|
@ -178,14 +178,14 @@ class BaseController(WSGIController):
|
|||
return False, {u'values': params, u'errors': error_dict}
|
||||
return True, {u'values': values, u'errors': {}}
|
||||
|
||||
def _add_javascript(self, filename, subdir=u'global'):
|
||||
def _add_javascript(self, filename):
|
||||
"""
|
||||
This method dynamically adds javascript files to the <head> section
|
||||
of the template.
|
||||
"""
|
||||
if not getattr(c, u'scripts', None):
|
||||
c.scripts = []
|
||||
c.scripts.append((filename, subdir))
|
||||
c.scripts.append(filename)
|
||||
|
||||
def _add_jsinit(self, filename):
|
||||
"""
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 560 B |
|
@ -16,3 +16,11 @@
|
|||
* with this program; if not, write to the Free Software Foundation, Inc., *
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
|
||||
*****************************************************************************/
|
||||
|
||||
ScribeEngine.Namespace.create("ScribeEngine.Post", {
|
||||
|
||||
});
|
||||
|
||||
ScribeEngine.Events.load(function () {
|
||||
ScribeEngine.Widgets.tagEditor("#post-tags");
|
||||
});
|
||||
|
|
|
@ -90,7 +90,7 @@ ScribeEngine.Namespace.create("ScribeEngine.Events", {
|
|||
keypress: function (selector, func) {
|
||||
$(selector).bind("keypress", func);
|
||||
},
|
||||
get_element: function(event) {
|
||||
getElement: function(event) {
|
||||
var targ;
|
||||
if (!event) {
|
||||
var event = window.event;
|
||||
|
@ -122,6 +122,10 @@ ScribeEngine.Namespace.create("ScribeEngine.Widgets", {
|
|||
datepicker: function (selector)
|
||||
{
|
||||
$(selector).datepicker({showButtonPanel: true, dateFormat: "dd/mm/yy"});
|
||||
},
|
||||
tagEditor: function (selector)
|
||||
{
|
||||
$(selector).tagEditor({confirmRemoval: true, completeOnBlur: true, initialParse: true});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -226,12 +230,4 @@ ScribeEngine.Namespace.create("ScribeEngine.General", {
|
|||
* This function below will be executed on all page views.
|
||||
*/
|
||||
ScribeEngine.Events.load(function () {
|
||||
// Hide hidden elements
|
||||
ScribeEngine.General.hide_elements();
|
||||
// Initialise collapsible fieldsets
|
||||
ScribeEngine.General.init_fieldsets();
|
||||
// Initialise elastic textareas
|
||||
ScribeEngine.General.init_textareas();
|
||||
// Show any flash messages
|
||||
ScribeEngine.General.show_message();
|
||||
});
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
@author: Karl-Johan Sjögren / http://blog.crazybeavers.se/
|
||||
@url: http://blog.crazybeavers.se/wp-content/demos/jquery.tag.editor/
|
||||
@license: Creative Commons License - ShareAlike http://creativecommons.org/licenses/by-sa/3.0/
|
||||
@version: 1.1
|
||||
*/
|
||||
(function($) {
|
||||
$.fn.extend({
|
||||
tagEditor: function(options) {
|
||||
var defaults = {
|
||||
separator: ',',
|
||||
items: [],
|
||||
className: 'tagEditor',
|
||||
confirmRemoval: false,
|
||||
completeOnSeparator: false,
|
||||
completeOnBlur: false
|
||||
}
|
||||
|
||||
var options = $.extend(defaults, options);
|
||||
var listBase, textBase = this, hiddenText;
|
||||
var itemBase = [];
|
||||
|
||||
return this.each(function() {
|
||||
textBase.id = options.formField;
|
||||
|
||||
hiddenText = $(document.createElement('input'));
|
||||
hiddenText.attr('type', 'hidden');
|
||||
textBase.after(hiddenText);
|
||||
|
||||
listBase = $(document.createElement('ul'));
|
||||
listBase.attr('class', options.className);
|
||||
$(this).after(listBase);
|
||||
|
||||
for (var i = 0; i < options.items.length; i++) {
|
||||
addTag(jQuery.trim(options.items[i]));
|
||||
}
|
||||
|
||||
buildArray();
|
||||
$(this).keypress(handleKeys);
|
||||
$(this).blur(parse);
|
||||
|
||||
var form = $(this).parents("form");
|
||||
form.submit(function() {
|
||||
parse();
|
||||
hiddenText.val(itemBase.join(options.separator));
|
||||
hiddenText.attr("id", textBase.attr("id"));
|
||||
hiddenText.attr("name", textBase.attr("name"));
|
||||
textBase.attr("id", textBase.attr("id") + '_old');
|
||||
textBase.attr("name", textBase.attr("name") + '_old');
|
||||
});
|
||||
|
||||
function addTag(tag) {
|
||||
tag = jQuery.trim(tag);
|
||||
for (var i = 0; i < itemBase.length; i++) {
|
||||
if (itemBase[i].toLowerCase() == tag.toLowerCase())
|
||||
return;
|
||||
}
|
||||
|
||||
var item = $(document.createElement('li'));
|
||||
item.text(tag);
|
||||
item.attr('title', 'Remove tag');
|
||||
item.click(function() {
|
||||
if (options.confirmRemoval)
|
||||
if (!confirm("Do you really want to remove the tag?"))
|
||||
return;
|
||||
|
||||
item.remove();
|
||||
parse();
|
||||
});
|
||||
|
||||
listBase.append(item);
|
||||
}
|
||||
|
||||
function buildArray() {
|
||||
itemBase = [];
|
||||
var items = $("li", listBase);
|
||||
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
itemBase.push(jQuery.trim($(items[i]).text()));
|
||||
}
|
||||
}
|
||||
|
||||
function parse() {
|
||||
var items = textBase.val().split(options.separator);
|
||||
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
var trimmedItem = jQuery.trim(items[i]);
|
||||
if (trimmedItem.length > 0)
|
||||
addTag(trimmedItem);
|
||||
}
|
||||
textBase.val("");
|
||||
buildArray();
|
||||
}
|
||||
|
||||
function handleKeys(ev) {
|
||||
if (options.completeOnSeparator) {
|
||||
if (String.fromCharCode(ev.keyCode) == options.separator) {
|
||||
parse();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
switch (ev.keyCode) {
|
||||
case 13:
|
||||
{
|
||||
parse();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
File diff suppressed because one or more lines are too long
|
@ -404,6 +404,34 @@ fieldset {
|
|||
color: #fff;
|
||||
}
|
||||
|
||||
/* Tag Editor */
|
||||
|
||||
.tagEditor
|
||||
{
|
||||
margin: 4px 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.tagEditor li
|
||||
{
|
||||
display: inline;
|
||||
background-image: url(/images/minus_small.png);
|
||||
background-color: #454545;
|
||||
background-position: right center;
|
||||
background-repeat: no-repeat;
|
||||
list-style-type: none;
|
||||
padding: 2px 18px 2px 6px;
|
||||
margin: 0 4px;
|
||||
cursor: pointer;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
}
|
||||
|
||||
.tagEditor li:hover
|
||||
{
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
/* Miscellaneous Styles */
|
||||
|
||||
.hidden {
|
||||
|
|
|
@ -7,6 +7,15 @@
|
|||
<meta name="keywords" content="" />
|
||||
<meta name="description" content="" />
|
||||
<link href="${h.url_for('/styles/style.css')}" rel="stylesheet" type="text/css" media="screen" />
|
||||
% for script in c.scripts:
|
||||
<script src="/scripts/${script}" type="text/javascript"></script>
|
||||
% endfor
|
||||
% if c.jsvalidation:
|
||||
<script src="/scripts/${c.jsvalidation}" type="text/javascript"></script>
|
||||
% endif
|
||||
% if c.jsinit:
|
||||
<script src="/scripts/${c.jsinit}" type="text/javascript"></script>
|
||||
% endif
|
||||
</head>
|
||||
<body>
|
||||
<div id="header">
|
||||
|
|
|
@ -6,6 +6,11 @@
|
|||
<div class="entry">
|
||||
${h.literal(c.post.body)}
|
||||
</div>
|
||||
<div class="tags">
|
||||
% for tag in c.post.tags:
|
||||
<a href="/tag/${tag.url}">${tag.name}</a>
|
||||
% endfor
|
||||
</div>
|
||||
% if len(c.post.comments) == 0:
|
||||
<h3 id="comments">No Responses</h3>
|
||||
% elif len(c.post.comments) == 1:
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
<!-- <label for="post-body">Body:</label> -->
|
||||
<textarea name="body" id="post-body" class="form-textarea">${c.post.body}</textarea>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label for="post-tags">Tags:</label>
|
||||
<input type="text" name="tags" id="post-tags" class="form-text" value="${c.post.tags_list}" />
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<input type="submit" name="action" value="Save Draft"/>
|
||||
<input type="submit" name="action" value="Save & Publish"/>
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
<!-- <label for="post-body">Body:</label> -->
|
||||
<textarea name="body" id="post-body" class="form-textarea"></textarea>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label for="post-tags">Tags:</label>
|
||||
<input type="text" name="tags" id="post-tags" class="form-text" />
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<input type="submit" name="action" value="Save Draft" class="form-button"/>
|
||||
<input type="submit" name="action" value="Save & Publish" class="form-button"/>
|
||||
|
|
Loading…
Reference in New Issue