from django.core.management.color import color_style
from django.core.files import File
from catalogue.utils import trim_query_log
-
+from librarian.picture import ImageStore
from wolnelektury_core.management.profile import profile
from catalogue.models import Book
print "Importing %s.%s" % (file_base, ebook_format)
book.save()
- def import_picture(self, file_path, options):
- picture = Picture.from_xml_file(file_path, overwrite=options.get('force'))
+ def import_picture(self, file_path, options, continue_on_error=True):
+ try:
+ image_store = ImageStore(os.path.dirname(file_path))
+ picture = Picture.from_xml_file(file_path, image_store=image_store, overwrite=options.get('force'))
+ except Exception, ex:
+ if continue_on_error:
+ print "%s: %s" % (file_path, ex)
+ return
+ else:
+ raise ex
return picture
# @profile
('theme', _('theme')),
('set', _('set')),
('book', _('book')),
+ ('thing', _('thing')), # things shown on pictures
)
--- /dev/null
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding model 'Picture'
+ db.create_table(u'picture_picture', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('title', self.gf('django.db.models.fields.CharField')(max_length=120)),
+ ('slug', self.gf('django.db.models.fields.SlugField')(unique=True, max_length=120)),
+ ('sort_key', self.gf('django.db.models.fields.CharField')(max_length=120, db_index=True)),
+ ('created_at', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, db_index=True, blank=True)),
+ ('changed_at', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, db_index=True, blank=True)),
+ ('xml_file', self.gf('django.db.models.fields.files.FileField')(max_length=100)),
+ ('image_file', self.gf('sorl.thumbnail.fields.ImageField')(max_length=100)),
+ ('html_file', self.gf('django.db.models.fields.files.FileField')(max_length=100)),
+ ))
+ db.send_create_signal(u'picture', ['Picture'])
+
+
+ def backwards(self, orm):
+ # Deleting model 'Picture'
+ db.delete_table(u'picture_picture')
+
+
+ models = {
+ u'picture.picture': {
+ 'Meta': {'ordering': "('sort_key',)", 'object_name': 'Picture'},
+ 'changed_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'html_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'image_file': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '120'}),
+ 'sort_key': ('django.db.models.fields.CharField', [], {'max_length': '120', 'db_index': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '120'}),
+ 'xml_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'})
+ }
+ }
+
+ complete_apps = ['picture']
\ No newline at end of file
--- /dev/null
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding field 'Picture.areas'
+ db.add_column(u'picture_picture', 'areas',
+ self.gf('jsonfield.fields.JSONField')(default='{}'),
+ keep_default=False)
+
+
+ def backwards(self, orm):
+ # Deleting field 'Picture.areas'
+ db.delete_column(u'picture_picture', 'areas')
+
+
+ models = {
+ u'picture.picture': {
+ 'Meta': {'ordering': "('sort_key',)", 'object_name': 'Picture'},
+ 'areas': ('jsonfield.fields.JSONField', [], {'default': "'{}'"}),
+ 'changed_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'created_at': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'db_index': 'True', 'blank': 'True'}),
+ 'html_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'image_file': ('sorl.thumbnail.fields.ImageField', [], {'max_length': '100'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'unique': 'True', 'max_length': '120'}),
+ 'sort_key': ('django.db.models.fields.CharField', [], {'max_length': '120', 'db_index': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '120'}),
+ 'xml_file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'})
+ }
+ }
+
+ complete_apps = ['picture']
\ No newline at end of file
-from django.db import models
+from django.db import models, transaction
import catalogue.models
from django.db.models import permalink
from sorl.thumbnail import ImageField
from catalogue.utils import split_tags
from django.utils.safestring import mark_safe
from fnpdjango.utils.text.slughifi import slughifi
+from picture import tasks
+from StringIO import StringIO
+import jsonfield
+import itertools
+
+from PIL import Image
from django.utils.translation import ugettext_lazy as _
from newtagging import managers
from os import path
-picture_storage = FileSystemStorage(location=path.join(settings.MEDIA_ROOT, 'pictures'), base_url=settings.MEDIA_URL + "pictures/")
+picture_storage = FileSystemStorage(location=path.join(
+ settings.MEDIA_ROOT, 'pictures'),
+ base_url=settings.MEDIA_URL + "pictures/")
class Picture(models.Model):
changed_at = models.DateTimeField(_('creation date'), auto_now=True, db_index=True)
xml_file = models.FileField('xml_file', upload_to="xml", storage=picture_storage)
image_file = ImageField(_('image_file'), upload_to="images", storage=picture_storage)
+ html_file = models.FileField('html_file', upload_to="html", storage=picture_storage)
+ areas = jsonfield.JSONField(_('picture areas'), default='{}', editable=False)
+
objects = models.Manager()
tagged = managers.ModelTaggedItemManager(catalogue.models.Tag)
tags = managers.TagDescriptor(catalogue.models.Tag)
return ('picture.views.picture_detail', [self.slug])
@classmethod
- def from_xml_file(cls, xml_file, image_file=None, overwrite=False):
+ def from_xml_file(cls, xml_file, image_file=None, image_store=None, overwrite=False):
"""
Import xml and it's accompanying image file.
If image file is missing, it will be fetched by librarian.picture.ImageStore
from librarian.picture import WLPicture, ImageStore
close_xml_file = False
close_image_file = False
- # class SimpleImageStore(object):
- # def path(self_, slug, mime_type):
- # """Returns the image file. Ignores slug ad mime_type."""
- # return image_file
+
if image_file is not None and not isinstance(image_file, File):
image_file = File(open(image_file))
if not isinstance(xml_file, File):
xml_file = File(open(xml_file))
close_xml_file = True
-
+
try:
# use librarian to parse meta-data
- picture_xml = WLPicture.from_file(xml_file,
- image_store=ImageStore(picture_storage.path('images')))
- # image_store=SimpleImageStore
+ if image_store is None:
+ image_store = ImageStore(picture_storage.path('images'))
+ picture_xml = WLPicture.from_file(xml_file, image_store=image_store)
picture, created = Picture.objects.get_or_create(slug=picture_xml.slug)
if not created and not overwrite:
picture.title = picture_xml.picture_info.title
motif_tags = set()
+ thing_tags = set()
+ area_data = {'themes':{}, 'things':{}}
+
for part in picture_xml.partiter():
- for motif in part['themes']:
- tag, created = catalogue.models.Tag.objects.get_or_create(slug=slughifi(motif), category='theme')
+ if picture_xml.frame:
+ c = picture_xml.frame[0]
+ part['coords'] = [[p[0] - c[0], p[1] - c[1]] for p in part['coords']]
+ if part.get('object', None) is not None:
+ objname = part['object']
+ tag, created = catalogue.models.Tag.objects.get_or_create(slug=slughifi(objname), category='thing')
if created:
- tag.name = motif
+ tag.name = objname
tag.sort_key = sortify(tag.name)
tag.save()
- motif_tags.add(tag)
+ thing_tags.add(tag)
+ area_data['things'][tag.slug] = {
+ 'object': part['object'],
+ 'coords': part['coords'],
+ }
+ else:
+ for motif in part['themes']:
+ tag, created = catalogue.models.Tag.objects.get_or_create(slug=slughifi(motif), category='theme')
+ if created:
+ tag.name = motif
+ tag.sort_key = sortify(tag.name)
+ tag.save()
+ motif_tags.add(tag)
+ area_data['themes'][tag.slug] = {
+ 'theme': motif,
+ 'coords': part['coords']
+ }
picture.tags = catalogue.models.Tag.tags_from_info(picture_xml.picture_info) + \
- list(motif_tags)
+ list(motif_tags) + list(thing_tags)
+ picture.areas = area_data
if image_file is not None:
img = image_file
else:
img = picture_xml.image_file()
- # FIXME: hardcoded extension
- picture.image_file.save(path.basename(picture_xml.image_path), File(img))
+ modified = cls.crop_to_frame(picture_xml, img)
+ # FIXME: hardcoded extension - detect from DC format or orginal filename
+ picture.image_file.save(path.basename(picture_xml.image_path), File(modified))
picture.xml_file.save("%s.xml" % picture.slug, File(xml_file))
picture.save()
+ tasks.generate_picture_html(picture.id)
+
+ except Exception, ex:
+ print "Rolling back a transaction"
+ transaction.rollback()
+ raise ex
+
finally:
if close_xml_file:
xml_file.close()
if close_image_file:
image_file.close()
+
+ transaction.commit()
+
return picture
+ @classmethod
+ def crop_to_frame(cls, wlpic, image_file):
+ if wlpic.frame is None:
+ return image_file
+ img = Image.open(image_file)
+ img = img.crop(itertools.chain(*wlpic.frame))
+ contents = StringIO()
+ img.save(contents, format='png', quality=95)
+ return contents
+
@classmethod
def picture_list(cls, filter=None):
"""Generates a hierarchical listing of all pictures
tags = self.tags.filter(category__in=('author', 'kind', 'epoch', 'genre'))
tags = split_tags(tags)
- short_html = unicode(render_to_string('picture/picture_short.html',
- {'picture': self, 'tags': tags}))
+ short_html = unicode(render_to_string(
+ 'picture/picture_short.html',
+ {'picture': self, 'tags': tags}))
if self.id:
get_cache('permanent').set(cache_key, short_html)
--- /dev/null
+# -*- coding: utf-8 -*-
+# This file is part of Wolnelektury, licensed under GNU Affero GPLv3 or later.
+# Copyright © Fundacja Nowoczesna Polska. See NOTICE for more information.
+#
+from datetime import datetime
+from traceback import print_exc
+from celery.task import task
+from django.conf import settings
+import picture.models
+from django.core.files.base import ContentFile
+from django.template.loader import render_to_string
+import librarian.picture
+
+
+@task
+def generate_picture_html(picture_id):
+ pic = picture.models.Picture.objects.get(pk=picture_id)
+
+
+ html_text = unicode(render_to_string('picture/picture_info.html', {
+ 'things': pic.areas['things'],
+ 'themes': pic.areas['themes'],
+ }))
+ pic.html_file.save("%s.html" % pic.slug, ContentFile(html_text))
+
{% load i18n %}
{% load static from staticfiles %}
{% load chunks compressed catalogue_tags %}
+{% load thumbnail %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<body>
<div id="menu">
<ul>
- <li><a class="menu" href="#themes">{% trans "Themes" %}</a></li>
- <li><a class="menu" href="#objects">{% trans "Objects" %}</a></li>
+<!-- <li><a class="menu" href="#themes">{% trans "Themes" %}</a></li>
+ <li><a class="menu" href="#objects">{% trans "Objects" %}</a></li>-->
<!-- XXX do we have this? -->
<li><a class="menu" href="#nota_red">{% trans "Edit. note" %}</a></li>
<li><a class="menu" href="#info">{% trans "Infobox" %}</a></li>
<div id="info">
{# book_info book #}
</div>
-<!-- do something with the logo <div id="header">
- <a href="/"><img src="{% static "img/logo-220.png" %}" alt="Wolne Lektury" /></a>
- </div>-->
+ {{ picture.html_file.read|safe }}
<!-- main picture view -->
<div id="picture-view">
<ul class="toolbar">
- <li class="button plus"><a href="#">➕<!-- heavy plus sign --></a></li>
- <li class="button minus"><a href="#">➖<!-- heavy minus sign --></a>
+ <li class="square button plus"><a href="#">➕<!-- heavy plus sign --></a></li>
+ <li class="square button minus"><a href="#">➖<!-- heavy minus sign --></a>
</li>
+ <li class="button"><a href="#picture-objects" class="dropdown">{% trans "Objects" %}</a></li>
+ <li class="button"><a href="#picture-themes" class="dropdown">{% trans "Themes" %}</a></li>
</ul>
- <div class="picture-wrap">
- <img class="canvas" src="{{ picture.image_file.url }}"/>
+ <div class="picture-wrap {% if picture.image_file|is_portrait %}portrait{% endif %}">
+ {% thumbnail picture.image_file "700x500" as pic %}
+ <img class="canvas initial" src="{{pic.url}}"/>
+ {% endthumbnail %}
+ <img class="canvas loading original" src="{{ picture.image_file.url }}"/>
</div>
</div>
{{ piwik_tag|safe }}
def picture_list(request, filter=None, template_name='catalogue/picture_list.html'):
""" generates a listing of all books, optionally filtered with a test function """
- pictures_by_author, orphans = Picture.picture_list()
+ pictures_by_author, orphans = Picture.picture_list(
+ filter={'image_file__isnull':False})
books_nav = SortedDict()
for tag in pictures_by_author:
if pictures_by_author[tag]:
def picture_list_thumb(request, filter=None, template_name='picture/picture_list_thumb.html'):
- picture_list = Picture.objects.all()
+ picture_list = Picture.objects.filter(image_file__isnull=False)
return render_to_response(template_name, locals(),
context_instance=RequestContext(request))
}
-#toc, #themes, #nota_red, #info {
+#toc, #themes, #nota_red, #info, #objects {
position: fixed;
left: 0em;
top: 1.5em;
z-index: 99;
}
-#toc ol, #themes ol {
+#toc ol, #themes ol, #objects ol {
list-style: none;
padding: 0;
margin: 0;
+
+#picture-view {
+ width: 100%;
+ position:absolute;
+ top: 0;
+ bottom: 0;
+}
-#picture-view img.canvas {
- width: 700px;
+#picture-view .picture-wrap {
margin: 3rem auto 1rem auto;
display: block;
-// position: fixed;
+// position: absolute;
+}
+
+#picture-view .picture-wrap {
+ width: 700px;
+}
+
+#picture-view .picture-wrap {
+ height: 500px;
}
-#picture-view .toolbar {
+
+.picture-wrap img.original {
+ width: 100%;
+}
+
+.picture-wrap img.loading {
+ margin-left: -10000px;
+}
+
+.picture-wrap .mark {
+ border: 2px solid rgba(200, 200, 200, 0.7);
+ position: absolute;
+ display: block;
+}
+
+.picture-wrap .mark .label {
+ position: absolute;
+ display: none; /*block;*/
+ color: rgba(200, 200, 200, 0.8);
+ font-size: 0.9rem;
+ bottom: -1.5em;
+}
+
+
+.toolbar {
position: fixed;
top: 1.5rem;
- right: 0rem;
- background: #333;
+ left: 0rem;
color: #FFF;
- opacity: 0.9;
z-index: 99;
list-style: none;
padding: 0;
margin: 0;
}
-#picture-view .toolbar .button a {
+.toolbar ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+ font-size: 0.8rem;
+ background-color: #222;
+}
+
+.toolbar .button a {
+ background: #333;
+ opacity: 0.9;
display: block;
height:1.5rem;
- width:1.5rem;
+
text-align: center;
color: #FFF;
padding: 0.2rem;
text-decoration: none;
}
+.toolbar .button .dropdown-body a {
+ height: 1.2rem;
+}
+
+#picture-view .toolbar .button.square a {
+ width:1.5rem;
+}
+
+li.button {
+ clear: both;
+}
+li.button.square {
+ clear: none;
+ float: left;
+}
+
#picture-view .toolbar .button a:link,
#picture-view .toolbar .button a:visited {
color: #FFF;
(function($) {
- $.widget('wl.pictureviewer', {
-
- options: {
- steps: 6, // steps of zoom
- max: 300, // max zoom in percent
- plus_button: undefined,
- minus_button: undefined
- },
-
- _create: function() {
- var self = this;
- self._zoom = 0;
- self.initial_size = [
- self.element.width(),
- self.element.height()
- ];
- self.initial_position = self.element.offset();
-
- self.element.css({
- 'margin': 0,
- 'position': 'absolute',
- });
- self.element.offset(self.initial_position);
-
- if (self.options.plus_button)
- self.options.plus_button.click(
- function(ev) { self.zoom(1); });
- if (self.options.minus_button)
- self.options.minus_button.click(
- function(ev) { self.zoom(-1); });
-
- function contain(event, ui) {
- var fix = self.allowedPosition(ui.position);
- console.log("fix: ", fix);
- if (fix !== undefined) {
- return false;
- };
- };
- self.element.draggable({drag: contain});
-
- return self;
- },
-
- zoom: function(steps) {
- var t = this._zoom + steps;
- return this.zoomTo(t);
- },
-
- zoomForStep: function(step) {
- // 0 => initial
- // max_step-1 => max %
- return 100 + (this.options.max - 100) / this.options.steps * step
- },
-
- zoomTo: function(level) {
- if (level < 0 || level > this.options.steps)
- return;
- var ratio = this.zoomForStep(level) / 100;
- var new_width = ratio * this.initial_size[0];
- var new_height = ratio * this.initial_size[1];
- var target = {
- 'width': new_width,
- 'left': this.initial_position.left - (new_width - this.initial_size[0])/2,
- 'top': this.initial_position.top - (new_height - this.initial_size[1])/2,
- };
- this._zoom = level;
- this.element.animate(target, 200); // default duration=400
- },
-
- allowedPosition: function(off) {
- var x = undefined, fix_x = undefined;
- var y = undefined, fix_y = undefined;
- var w = this.element.width();
- var h = this.element.height();
- var cw = $(window).width();
- var ch = $(window).height();
- var off = off || this.element.offset();
-
- if (w <= cw) {
- var x = off.left;
- if (x < 0)
- fix_x = 0;
- if (x + w > cw)
- fix_x = cw - w;
- } else {
- if (x > 0)
- fix_x = 0;
- if (x + w < cw)
- fix_x = cw - w;
- }
-
- if (h <= ch) {
- var y = off.top;
- if (y < 0)
- fix_y = 0;
- if (y + h > ch)
- fix_y = ch - h;
- } else {
- if (y > 0)
- fix_y = 0;
- if (y + h < ch)
- fix_y = ch - h;
- }
- if (fix_x !== undefined || fix_y !== undefined)
- return { top: fix_y, left: fix_x };
- return undefined;
-
- },
- });
+ $.widget('wl.pictureviewer', {
+
+ options: {
+ steps: 6, // steps of zoom
+ max: -1, // max zoom in percent
+ plus_button: undefined,
+ minus_button: undefined,
+ height: 500, // height to scale to initially
+ },
+
+
+ _create: function() {
+ var self = this;
+ /* Calibrate */
+ self._zoom = 0;
+
+ // the initial thumbnailed picture
+
+
+ var img = self.element.find('img.initial').get(0);
+
+ self.initial_size = [
+ img.naturalWidth,
+ img.naturalHeight
+ ];
+
+ self.element.width(self.initial_size[0]);
+ self.element.height(self.initial_size[1]);
+
+ self.initial_position = self.element.offset();
+
+ var original = self.element.find('img.original').get(0);
+ self._original = false;
+
+ if (self.options.max <= 0) {
+ self.options.max = original.naturalWidth
+ * 100 / self.initial_size[0];
+ }
+
+ self.element.css({
+ 'margin': 0,
+ });
+
+ self.element.offset(self.initial_position);
+ self.element.draggable({containment:"parent"});
+
+ if (self.options.plus_button)
+ self.options.plus_button.click(
+ function(ev) { self.zoom(1); });
+ if (self.options.minus_button)
+ self.options.minus_button.click(
+ function(ev) { self.zoom(-1); });
+
+ self.options.areas_links.hover(function() {
+ $this = $(this);
+ var coords = $this.data("coords");
+ this._picture_mark = self.createMark({
+ label: $this.text(),
+ coords: coords,
+ });
+ }, function() {
+ $(this._picture_mark).remove();
+ this._picture_mark = undefined;
+ });
+ return self;
+ },
+
+ natural_size: function() {
+ var img = this.element.find('img').get(0);
+ return [ img.naturalWidth, img.naturalHeight ]
+ },
+
+ currentZoom: function() { return this._zoom; },
+
+ initOriginal: function() {
+ if (!this._original) {
+ this.element.find("img.initial").remove();
+ this.element.find("img.loading").removeClass("loading");
+ this._original = true;
+ }
+
+ },
+
+ zoom: function(steps) {
+ this.initOriginal();
+ var t = this._zoom + steps;
+ return this.zoomTo(t);
+ },
+
+ zoomForStep: function(step) {
+ // 0 => initial
+ // max_step-1 => max %
+ return 100 + (this.options.max - 100) / this.options.steps * step
+ },
+
+ zoomTo: function(level) {
+ if (level < 0 || level > this.options.steps)
+ return;
+ var ratio = this.zoomForStep(level) / 100;
+ var new_width = ratio * this.initial_size[0];
+ var new_height = ratio * this.initial_size[1];
+ var target = {
+ 'width': new_width,
+ 'left': Math.max(0,
+ this.initial_position.left
+ - (new_width - this.initial_size[0])/2),
+ 'top': Math.max(0,
+ this.initial_position.top
+ - (new_height - this.initial_size[1])/2),
+ };
+
+ this._zoom = level;
+ this.element.animate(target, 200); // default duration=400
+ },
+
+ allowedPosition: function(off) {
+ var x = undefined, fix_x = undefined;
+ var y = undefined, fix_y = undefined;
+ var w = this.element.width();
+ var h = this.element.height();
+ var cw = $(window).width();
+ var ch = $(window).height();
+ var off = off || this.element.offset();
+
+ if (w <= cw) {
+ var x = off.left;
+ if (x < 0)
+ fix_x = 0;
+ if (x + w > cw)
+ fix_x = cw - w;
+ } else {
+ if (x > 0)
+ fix_x = 0;
+ if (x + w < cw)
+ fix_x = cw - w;
+ }
+
+ if (h <= ch) {
+ var y = off.top;
+ if (y < 0)
+ fix_y = 0;
+ if (y + h > ch)
+ fix_y = ch - h;
+ } else {
+ if (y > 0)
+ fix_y = 0;
+ if (y + h < ch)
+ fix_y = ch - h;
+ }
+ if (fix_x !== undefined || fix_y !== undefined)
+ return { top: fix_y, left: fix_x };
+ return undefined;
+
+ },
+
+ // mark
+ // {
+ // label: "...",
+ // coords: [x, y, w, h]
+ // }
+ createMark: function(mark) {
+ var $mark = $('<div class="mark"><div class="label">' +
+ mark.label + '</div></div>');
+ var ratio = this.zoomForStep(this.currentZoom()) *
+ this.initial_size[0] / (100 * this.natural_size()[0]);
+ var scale = function (v) {
+ return v * ratio;
+ }
+ if (mark.coords[1][0] < 0 || mark.coords[1][1] < 0) { // whole
+ var s = self.natural_size();
+ if (mark.coords[1][0] < 0) mark.coords[1][0] = s[0];
+ if (mark.coords[1][1] < 0) mark.coords[1][1] = s[1];
+ }
+
+ var coords = [[scale(mark.coords[0][0]), scale(mark.coords[0][1])],
+ [scale(mark.coords[1][0]), scale(mark.coords[1][1])]];
+ this.element.append($mark);
+ $mark.width(coords[1][0] - coords[0][0]);
+ $mark.height(coords[1][1] - coords[0][1]);
+ $mark.css({left: coords[0][0], top: coords[0][1]});
+ return $mark.get(0);
+ },
+ });
}(jQuery));
$(document).ready(function(){
- $("img.canvas").pictureviewer({
- plus_button: $(".toolbar .button.plus"),
- minus_button: $(".toolbar .button.minus")
- });
+ $(".picture-wrap").pictureviewer({
+ plus_button: $(".toolbar .button.plus"),
+ minus_button: $(".toolbar .button.minus"),
+ areas_links: $("#picture-objects a, #picture-themes a"),
+ });
+
+ $.highlightFade.defaults.speed = 3000;
+
+ $('.toolbar a.dropdown').each(function() {
+ $t = $(this);
+ $($t.attr('href')).hide().insertAfter(this);
+ });
+
+ $('.toolbar a.dropdown').toggle(function() {
+ $(this).addClass('selected');
+ $($(this).attr('href')).slideDown('fast');
+ }, function() {
+ $(this).removeClass('selected');
+ $($(this).attr('href')).slideUp('fast');
+ });
+
+
});
PIPELINE_COMPILERS = (
'pyscss_compiler.PySCSSCompiler',
)
-PIPELINE_PYSCSS_BINARY = '/usr/bin/env pyscss'
+PIPELINE_PYSCSS_BINARY = '/usr/bin/env /home/staging/wolnelektury.pl/ve/bin/pyscss'
PIPELINE_PYSCSS_ARGUMENTS = ''