diff --git a/Qalbum-thumbnailer.py b/Qalbum-thumbnailer.py new file mode 100755 index 0000000..fe1e2f4 --- /dev/null +++ b/Qalbum-thumbnailer.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python +# +# Copyright 2011 Ville Rantanen +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +import sys,os +import re +import shutil +import subprocess +from optparse import OptionParser +from math import ceil + +# (c) ville.rantanen@helsinki.fi + +webfilesearch=re.compile('.*index.html$|.*gallerystyle.css$|.*galleryscript.js$|.*descriptions.csv$',re.I) +imagesearch=re.compile('.*\.jpg$|.*\.jpeg$|.*\.gif$|.*\.png$|.*\.svg$|.*\.pdf$',re.I) +vectorsearch=re.compile('.*\.svg$|.*\.pdf$',re.I) +excludepaths=re.compile('_med|_tn|\..*') +doublequotes=re.compile('"') +singlequotes=re.compile("'") +stripquotes=re.compile('^"|"$') + +def getimagelist(path): + ''' Returns a list of images matching the regex ''' + list=os.listdir(path) + imgs=[] + for f in list: + if (imagesearch.match(os.path.join(path,f))) and (os.path.isfile(os.path.join(path,f))): + imgs.append(f) + return imgs + +def getnonimagelist(path): + ''' Returns a list of files not matching the image match regex ''' + list=os.listdir(path) + files=[] + for f in list: + if (not webfilesearch.match(os.path.join(path,f))) and (not imagesearch.match(os.path.join(path,f))) and (os.path.isfile(os.path.join(path,f))): + files.append(f) + files.sort() + return files + +def getpathlist(path): + ''' Returns a list of subfolders not matching the exclusion regex ''' + list=os.listdir(path) + paths=[] + for d in list: + if (not excludepaths.match(d)) and (os.path.isdir(os.path.join(path,d))): + paths.append(d) + return paths + +def createthumbs(path,list): + ''' Runs imagemagick Convert to create medium sized and thumbnail images ''' + if len(list)==0: + return + if not os.path.exists(os.path.join(path,'_tn')): + os.mkdir(os.path.join(path,'_tn')) + if not os.path.exists(os.path.join(path,'_med')): + os.mkdir(os.path.join(path,'_med')) + n=1 + nsum=len(list) + r=str(options.width) + res=r+'x'+r+'>' + for i in list: + if (vectorsearch.match(i)): + if (options.force) or (not os.path.exists(os.path.join(path,'_med','med_'+i+'.jpg'))): + print('Medium.. '+i+' '+str(n)+'/'+str(nsum)) + convargs=['convert','-density','300x300',os.path.join(path,i)+'[0]','-background','white','-flatten','-resize',res,'-quality','97',os.path.join(path,'_med','med_'+i+'.jpg')] + convp=subprocess.call(convargs) + if (options.force) or (not os.path.exists(os.path.join(path,'_tn','tn_'+i+'.jpg'))): + convargs=['convert','-density','300x300',os.path.join(path,'_med','med_'+i+'.jpg'),'-background','white','-flatten','-thumbnail','90x90^','-gravity','Center','-crop','90x90+0+0','+repage','-quality','75',os.path.join(path,'_tn','tn_'+i+'.jpg')] + convp=subprocess.call(convargs) + else: + if (options.force) or (not os.path.exists(os.path.join(path,'_med','med_'+i+'.jpg'))): + print('Medium.. '+i+' '+str(n)+'/'+str(nsum)) + convargs=['convert','-define','jpeg:size='+r+'x'+r,os.path.join(path,i)+'[0]','-background','white','-flatten','-resize',res,'-quality','85',os.path.join(path,'_med','med_'+i+'.jpg')] + convp=subprocess.call(convargs) + if (options.force) or (not os.path.exists(os.path.join(path,'_tn','tn_'+i+'.jpg'))): + convargs=['convert','-define','jpeg:size=300x300',os.path.join(path,'_med','med_'+i+'.jpg'),'-background','white','-flatten','-thumbnail','90x90^','-gravity','Center','-crop','90x90+0+0','+repage','-quality','75',os.path.join(path,'_tn','tn_'+i+'.jpg')] + convp=subprocess.call(convargs) + n+=1 + return + +def cleanthumbs(path): + ''' clears _med and _tn for unused thumbs ''' + print('clearing unused thumbs...') + if os.path.exists(os.path.join(path,'_tn')): + clearfolder(path,os.path.join(path,'_tn'),re.compile("(^tn_)(.*)(.jpg)")) + if os.path.exists(os.path.join(path,'_med')): + clearfolder(path,os.path.join(path,'_med'),re.compile("(^med_)(.*)(.jpg)")) + + return +def clearfolder(path,tnpath,regex): + ''' clears given folder ''' + list=getimagelist(tnpath) + for i in list: + f=regex.match(i) + try: + if not os.path.exists(os.path.join(path,f.group(2))): + print('removing '+i) + os.remove(os.path.join(tnpath,i)) + except: + continue + return + +def traverse(path): + ''' The recursive main function to create the thumbs and seek sub folders ''' + print(path) + pathlist=getpathlist(path) + imagelist=getimagelist(path) + print(str(len(pathlist))+' paths') + print(str(len(imagelist))+' images') + if options.clean: + cleanthumbs(path) + createthumbs(path,imagelist) + if options.recursive: + for p in pathlist: + traverse(os.path.join(path,p)) + return + +def execute(): + ''' Main execution ''' + usage='''Usage: %prog [options] folder +folder is the root folder of the image album.''' + parser=OptionParser(usage=usage) + parser.add_option("-f",action="store_true",dest="force",default=False, + help="Force regeneration of thumbnails") + parser.add_option("-c",action="store_true",dest="clean",default=False, + help="Clean unused thumbnails") + parser.add_option("-r",action="store_true",dest="recursive",default=False, + help="Recurse in to subfolders") + parser.add_option("-w",type="int",dest="width",default=850, + help="Medium image size") + global options + (options,args)=parser.parse_args() + if len(args) != 1: + parser.error("incorrect number of arguments") + startpath=os.path.abspath(args[0]) + traverse(startpath) + return + +execute() +sys.exit(0) + + diff --git a/Qalbum.py b/Qalbum.py new file mode 100755 index 0000000..f005845 --- /dev/null +++ b/Qalbum.py @@ -0,0 +1,448 @@ +#!/usr/bin/env python +# +# Copyright 2011 Ville Rantanen +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . + +import sys,os +import re +import urllib +import shutil +import csv +import subprocess +from math import ceil +from datetime import datetime + +# (c) ville.rantanen@helsinki.fi + +webfilesearch=re.compile('.*index.html$|.*gallerystyle.css$|.*galleryscript.js$|.*descriptions.csv$|\..*',re.I) +imagesearch=re.compile('.*\.jpg$|.*\.jpeg$|.*\.gif$|.*\.png$|.*\.svg$|.*\.pdf$',re.I) +vectorsearch=re.compile('.*\.svg$|.*\.pdf$',re.I) +#gifsearch=re.compile('.*gif$',re.I) +excludepaths=re.compile('_med|_tn|\..*') +doublequotes=re.compile('"') +singlequotes=re.compile("'") +stripquotes=re.compile('^"|"$') + +def getheader(path,parent,title=""): + if title=="": + title=unicode(os.path.basename(path),encoding="utf8").encode('ascii', 'xmlcharrefreplace') + return ''' + + +'''+title+''' + + + + + +''' + +def getimagelist(path): + ''' Returns a list of images matching the regex ''' + list=os.listdir(path) + imgs=[] + for f in list: + if (imagesearch.match(f)) and (os.path.isfile(os.path.join(path,f))): + imgs.append(f) + if options.timesort: + imgs.sort(key=lambda f: os.path.getmtime(os.path.join(path, f)),reverse=options.reverse) + else: + imgs.sort(reverse=options.reverse) + return imgs + +def getfiletimes(path,list): + ''' Returns a list of modification times ''' + times=[] + for p in list: + times.append(os.path.getmtime(os.path.join(path,p))) + return times + +def getnonimagelist(path): + ''' Returns a list of files not matching the image match regex ''' + list=os.listdir(path) + files=[] + if not options.attachments: + return files + for f in list: + if (not webfilesearch.match(f)) and (not imagesearch.match(f)) and (os.path.isfile(os.path.join(path,f))): + files.append(f) + if options.timesort: + files.sort(key=lambda f: os.path.getmtime(os.path.join(path, f)),reverse=options.reverse) + else: + files.sort(reverse=options.reverse) + return files + +def getpathlist(path): + ''' Returns a list of subfolders not matching the exclusion regex ''' + list=os.listdir(path) + paths=[] + for d in list: + if (not excludepaths.match(d)) and (os.path.isdir(os.path.join(path,d))): + paths.append(d) + if options.timesort: + paths.sort(key=lambda f: os.path.getmtime(f),reverse=options.reverse) + else: + paths.sort(reverse=options.reverse) + return paths + +def pathscript(path,list): + ''' Returns the javascript string of pathlist and pathimage arrays ''' + scrstr='' + return scrstr + +def pathlinks(path,list): + ''' Returns the HTML string of subfolders ''' + pathstr='
' + pathstr+='

Subfolders

' + for p in list: + nice=nicestring(p) + imglist=getimagelist(os.path.join(path,p)) + nsum=str(len(imglist)) + imgstr="" + if len(imglist)>0: + imgstr='' + else: + imgstr='' + pathstr+=''+imgstr+''+unicode(nice,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+' ('+nsum+')'; + pathstr+='' + pathstr+='
' + return pathstr + +def imagescript(path,list): + ''' Returns the javascript string of imagelist and imagedesc ''' + strout='' + return strout + +def imagelinks(path,list): + ''' Returns the HTML string of images ''' + strout='
' + strout+='

Images

' + descriptions=getdescriptions(path,list) + n=0 + for i in list: + nice=nicestring(i) + desc=doublequotes.sub('',unicode(descriptions[n],encoding="utf8").encode('ascii', 'xmlcharrefreplace')) + strout+='
'+unicode(nice,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+'
' + n+=1 + strout+='
' + return strout + +def filescript(path,list): + ''' Returns the javascript string of filelist ''' + strout='' + return strout + +def filelinks(path,list): + ''' Returns the HTML string of non image files ''' + strout='
' + if len(list)>0: + strout+='

Attachments

' + n=0 + for i in list: + nice=nicestring(i) + size=sizestring(os.path.getsize(os.path.join(path,i))) + strout+=''+unicode(nice,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+' ['+size+']' + n+=1 + strout+='
' + return strout + +def createthumbs(path,list): + ''' Runs imagemagick Convert to create medium sized and thumbnail images ''' + if len(list)==0: + return + if not os.path.exists(os.path.join(path,'_tn')): + os.mkdir(os.path.join(path,'_tn')) + if not os.path.exists(os.path.join(path,'_med')): + os.mkdir(os.path.join(path,'_med')) + n=1 + nsum=len(list) + for i in list: + if (vectorsearch.match(i)): + if not os.path.exists(os.path.join(path,'_med','med_'+i+'.jpg')): + print('.. '+i+' '+str(n)+'/'+str(nsum)) + convargs=['convert','-density','300x300',os.path.join(path,i)+'[0]','-background','white','-flatten','-resize','1000x1000>','-quality','97',os.path.join(path,'_med','med_'+i+'.jpg')] + convp=subprocess.call(convargs) + if not os.path.exists(os.path.join(path,'_tn','tn_'+i+'.jpg')): + convargs=['convert','-density','300x300',os.path.join(path,'_med','med_'+i+'.jpg'),'-background','white','-flatten','-thumbnail','90x90^','-gravity','Center','-crop','90x90+0+0','+repage','-quality','75',os.path.join(path,'_tn','tn_'+i+'.jpg')] + convp=subprocess.call(convargs) + else: + if not os.path.exists(os.path.join(path,'_med','med_'+i+'.jpg')): + print('.. '+i+' '+str(n)+'/'+str(nsum)) + convargs=['convert','-define','jpeg:size=1200x1200',os.path.join(path,i)+'[0]','-background','white','-flatten','-resize','1000x1000>','-quality','85',os.path.join(path,'_med','med_'+i+'.jpg')] + convp=subprocess.call(convargs) + if not os.path.exists(os.path.join(path,'_tn','tn_'+i+'.jpg')): + convargs=['convert','-define','jpeg:size=300x300',os.path.join(path,'_med','med_'+i+'.jpg'),'-background','white','-flatten','-thumbnail','90x90^','-gravity','Center','-crop','90x90+0+0','+repage','-quality','75',os.path.join(path,'_tn','tn_'+i+'.jpg')] + convp=subprocess.call(convargs) + n+=1 + return + +def getdescriptions(path,list): + ''' Read descriptions.csv file and returns a list of descriptions. + Missing descriptions are replaced with the file name. ''' + if not os.path.exists(os.path.join(path,'descriptions.csv')): + return list + desc=[i for i in list] + reader = csv.reader(open(os.path.join(path,'descriptions.csv'),'rb'), + delimiter='\t', + doublequote=False, + escapechar='\\', + quoting=csv.QUOTE_NONE) + for row in reader: + if row[0] in list: + i=list.index(stripquotes.sub('',row[0])) + desc[i]=stripquotes.sub('',row[1]) + return desc + +def crumblinks(crumbs): + ''' Create the HTML string for crumb trails ''' + strout='
' + i=1 + for c in crumbs: + cname=os.path.basename(c) + if i==1: + cname="Home" + cdepth=len(crumbs)-i + clink="../"*cdepth + strout+=''+unicode(cname,encoding="utf8").encode('ascii', 'xmlcharrefreplace')+': ' + i+=1 + strout+='
' + return strout + +def nicestring(s): + ''' Returns a nice version of a long string ''' + if len(s)<20: + return s + s=s.replace("_"," ") + s=s.replace("-"," ") + if len(s)>30: + s=s[0:26]+".."+s[-3:] + return s + +def sizestring(size): + ''' Returns human readable file size string ''' + for x in ['b','kb','Mb','Gb','Tb']: + if size < 1024.0: + if (x=='b') | (x=='kb'): + return "%d%s" % (size, x) + else: + return "%3.1f%s" % (size, x) + size /= 1024.0 + +def traverse(path,crumbs): + ''' The recursive main function to create the index.html and seek sub folders ''' + print(path) + if len(crumbs)==1: + header=getheader(path,'../'*(len(crumbs)-1),inputs[0][1]) + else: + header=getheader(path,'../'*(len(crumbs)-1)) + print(len(crumbs)) + pathlist=getpathlist(path) + imagelist=getimagelist(path) + filelist=getnonimagelist(path) + print(str(len(pathlist))+' paths') + print(str(len(imagelist))+' images') + print(str(len(filelist))+' other files') + crumbstring=crumblinks(crumbs) + if len(pathlist)>0: + pathstring=pathlinks(path,pathlist) + pathjs=pathscript(path,pathlist) + else: + pathstring='
' + pathjs='' + filestring=filelinks(path,filelist) + filejs=filescript(path,filelist) + if len(imagelist)>0: + imagestring=imagelinks(path,imagelist) + imagejs=imagescript(path,imagelist) + else: + imagestring='
' + imagejs='' + + f=open(os.path.join(path,"index.html"),"w") + f.write(header) + f.write('
') + f.write(pathjs) + f.write(imagejs) + f.write(filejs) + f.write(crumbstring) + f.write(pathstring) + f.write('
') + f.write('
') + f.write(imagestring) + f.write(filestring) + f.write('
') + f.write(footer) + f.close() + createthumbs(path,imagelist) + for p in pathlist: + nextcrumbs=[i for i in crumbs] + nextcrumbs.append(os.path.join(path,p)) + traverse(os.path.join(path,p),nextcrumbs) + return + +class AndurilOptions: + '''Object featuring same variables as arguments from command line.''' + + def __init__(self, timesort, reverse): + '''Initializes the person's data.''' + self.timesort=timesort + self.reverse=reverse + self.attachments=True + +def execute(cf): + global footer + footer=''' + + + +''' + global inputs + global options + inputs=[] + inputs.append((cf.get_input('folderRoot'),'',cf.get_input('csvRoot'))) + for i in range(8): + inputs.append((cf.get_input('folder'+str(i+1)),cf.get_parameter('title'+str(i+1)),cf.get_input('csv'+str(i+1)))) + fileCol=cf.get_parameter('fileCol') + annotationCol=cf.get_parameter('annotationCol') + options=AndurilOptions(cf.get_parameter('sortTime','boolean'), + cf.get_parameter('sortReverse','boolean')) + outDir = cf.get_output('gallery') + # the folderRoot demands that the outDir is not created earlier. + if inputs[0][0]==None: + os.mkdir(outDir) + else: + shutil.copytree(inputs[0][0],os.path.join(outDir,inputs[0][1])) + + for d in inputs: + if (d[0]==None): + continue + if not os.path.exists(d[0]): + continue + print('Copying gallery '+d[1]) + cf.write_log('Copying gallery '+d[1]) + if not os.path.exists(os.path.join(outDir,d[1])): + shutil.copytree(d[0],os.path.join(outDir,d[1])) + # Find the annotations + if (d[2] is not None): + reader = csv.DictReader(open(d[2],'rb'), + delimiter='\t', + doublequote=False, + escapechar='\\', + quoting=csv.QUOTE_ALL) + for row in reader: + break + if (fileCol not in reader.fieldnames): + cf.write_error("Column \""+fileCol+"\" not found.") + exit() + if (annotationCol not in reader.fieldnames): + cf.write_error("Column \""+annotationCol+"\" not found.") + exit() + reader = csv.DictReader(open(d[2],'rb'), + delimiter='\t', + doublequote=False, + escapechar=None, + quotechar='"', + quoting=csv.QUOTE_NONE) + annotations=[] + header=['file','description'] + for row in reader: + annotations.append( (stripquotes.sub('',row.get('"'+fileCol+'"')), stripquotes.sub('',row.get('"'+annotationCol+'"')) ) ) + writefid=open(os.path.join(outDir,d[1],'descriptions.csv'),'wb') + writer = csv.writer(writefid, + delimiter='\t', + doublequote=False,escapechar='\\', + quotechar='"', + quoting=csv.QUOTE_NONE) + writer.writerow(header) + for r in annotations: + writer.writerow([r[0],r[1]]) + writefid.close() + # Copy all resources to target folder + shutil.copyfile('gallerystyle.css',os.path.join(outDir,'gallerystyle.css')) + shutil.copyfile('galleryscript.js',os.path.join(outDir,'galleryscript.js')) + inputs[0]=((cf.get_input('folderRoot'),cf.get_parameter('titleRoot'),cf.get_input('csvRoot'))) + startpath=os.path.abspath(outDir) + traverse(startpath,[startpath]) + return 0 + +def execute_plain(): + ''' Execute this if run outside anduril ''' + from optparse import OptionParser + usage='''Usage: %prog [options] folder +folder is the root folder of the image album.''' + parser=OptionParser(usage=usage) + parser.add_option("-r",action="store_true",dest="reverse",default=False, + help="Reverse sort orded") + parser.add_option("-t",action="store_true",dest="timesort",default=False, + help="Sort by file modification time") + parser.add_option("-a",action="store_false",dest="attachments",default=True, + help="Disable attachments") + global options + (options,args)=parser.parse_args() + if len(args) != 1: + #sys.exit(0) + startpath=os.path.abspath('.') + else: + startpath=os.path.abspath(args[0]) + pathname=os.path.dirname(os.path.realpath(sys.argv[0])) + fullpath=os.path.abspath(pathname) + # Copy all resources to target folder + shutil.copyfile(os.path.join(fullpath,'gallerystyle.css'),os.path.join(startpath,'gallerystyle.css')) + shutil.copyfile(os.path.join(fullpath,'galleryscript.js'),os.path.join(startpath,'galleryscript.js')) + global footer + footer=''' + + + +''' + global inputs + inputs=[] + inputs.append((None,'Gallery',None)) + + traverse(startpath,[startpath]) + return + +try: + import component_skeleton.main +except ImportError: + execute_plain() + sys.exit(0) + +component_skeleton.main.main(execute) + diff --git a/galleryscript.js b/galleryscript.js new file mode 100644 index 0000000..7a59fad --- /dev/null +++ b/galleryscript.js @@ -0,0 +1,455 @@ +/* +Copyright 2011 Ville Rantanen + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program. If not, see . +*/ +var maxThumb=10; +var uagent = navigator.userAgent.toLowerCase(); +var pathlist=[]; +var pathimage=[]; +var imagelist=[]; +var filelist=[]; +var imagedesc=[]; +var imagetime=[]; +var marklist=[] +var currentimage=-1; +var currentlist=-1; +var originals=false; + +function setup() { + // Setup run at the load of page. + if (notsupported()) { + return; + } + hidethumbs(); + document.onkeydown=keypressed; + var req=request(); + if (req!=-1) { + showimage(req); + } else { + thumblist(0,-1); + subfolderbiglist(); + } + return; +} + +function showimage(i) { + // Main function to show a single image + if (i>imagelist.length-1 || i<0) { return; } + thumblist(i,i); + showbigimage(i); + preload(i); + subfoldersmalllist(); + currentimage=i; + return; +} + +function showbigimage(i) { + // The medium version of image in the big image container + if (i==-1) { return; } + ob=document.getElementById('imagecontainer'); + width=document.body.clientWidth-30; + height=document.body.clientHeight-225; + if (originals) { mediumstr=encodeURIComponent(imagelist[i]); } + else { mediumstr='_med/med_'+encodeURIComponent(imagelist[i])+'.jpg'; } + ob.innerHTML='
'; + document.getElementById('imagesingle').style.maxWidth=width; + ob.style.height=height; + document.getElementById('imagesingle').style.maxHeight=height; + dc=document.getElementById('desccontainer'); + dc.innerHTML=currentlink(i)+imagedesc[i]; + dc.style.display='block'; + return; +} + +function currentlink(i) { + // gets the search term for this image + index = location.href.split("?"); + s='['+String(i+1)+'] '; + return s; +} + +function preload(i) { + // preloads left and right images + if (imagelist.length==0) { return; } + ob=document.getElementById('preloadcontainer'); + right=Math.max(0,i+1); + right=Math.min(right,imagelist.length-1); + left=Math.max(0,i-1); + left=Math.min(left,imagelist.length-1); + if (originals) { + prestr=''; + prestr+=''; + } else { + prestr=''; + prestr+=''; + } + ob.innerHTML=prestr; + return; +} + +function thumblist(n,curr) { + // creates the short thumbnail list + maxThumb=getmaxthumbs(); + if (imagelist.length==0) { return; } + ob=document.getElementById('thumbcontainer'); + ob.style.width=document.body.clientWidth-30; + startI=Math.max(0,n+1-Math.round((maxThumb/2))); + startI=Math.min(startI,imagelist.length-maxThumb); + startI=Math.max(0,startI); + endI=Math.min(startI+maxThumb,imagelist.length); + currentlist=endI; + nright=endI-Math.round((maxThumb/2))+maxThumb-1; + nleft=nright-maxThumb-maxThumb; + if (maxThumb%2==1) { nright+=1; nleft+=1; } + leftstr='
('+startI+')
'; + rightstr='
('+(imagelist.length-endI)+')
'; + menustr='all thumbnails'+ + 'Order:name/'+ + 'time/'+ + 'reverse'+ + 'Original:'+String(originals)+''; + thumbstr='
Images'+menustr+'
'+leftstr; + for (i=startI; i
'+nicestring((imagelist[i]))+''; + } + thumbstr+=rightstr+'
'; + ob.innerHTML=thumbstr; + if (curr>-1) { + c=document.getElementById('n'+curr); + if (c) {c.className="imagebox thumbbox rounded"; } + } + if (marklist.length>0) { + for (m in marklist) { + var mth=document.getElementById('n'+marklist[m]) + if (mth!=null) { + mth.className+=" marked"; + } + } + } + return; +} + +function allthumbs() { + // Shows all the thumbnails in the current folder + ob=document.getElementById('thumbcontainer'); + thumbstr='

Images

'; + for (i=0; i
'+nicestring(imagelist[i])+''; + } + thumbstr+='
'; + ob.innerHTML=thumbstr; + ic=document.getElementById('imagecontainer'); + ic.innerHTML=''; + ic.style.height=0; + dc=document.getElementById('desccontainer'); + dc.style.display='none'; + currentimage=-1; + return; +} + +function subfoldersmalllist() { + // Shows a small subfolder list + ob=document.getElementById('pathcontainer'); + pathstr='Subfolders: '; + for (p=0; p'+nicestring(pathlist[p][0])+'('+String(pathlist[p][1])+')/ '; + } + pathstr+=''; + if (pathlist.length==0) { + ob.innerHTML=''; + } else { ob.innerHTML=pathstr; } + return; +} +function subfolderbiglist() { + // Shows a subfolder list with thumbnails + ob=document.getElementById('pathcontainer'); + pathstr='

Subfolders:

'; + for (p=0; p0) { + imgstr=''; + } else { imgstr=''; } + pathstr+=''+imgstr+''+nicestring(pathlist[p][0])+' ('+String(pathlist[p][1])+')'; + } + if (pathlist.length==0) { + ob.innerHTML=''; + } else { ob.innerHTML=pathstr; } + return; +} +function sortlist(property) { + // sorts the image list based on time or name, or reverse sort + var templist=[] + var tempmark=[] + var tempcurrent=imagelist[currentimage]; + for (i in imagelist) { + templist.push({name:imagelist[i], time:imagetime[i], desc:imagedesc[i]}); + } + for (i in marklist) { + tempmark.push(imagelist[marklist[i]]); + } + if (property=='time') { + templist.sort(function(a,b) { + return a.time-b.time + }) + } + if (property=='alpha') { + templist.sort(function(a, b){ + if (a.name < b.name) + return -1 + if (a.name > b.name) + return 1 + return 0 + }) + } + if (property=='rev') { + templist.reverse(); + } + for (i in imagelist) { + imagelist[i]=templist[i].name; + imagetime[i]=templist[i].time; + imagedesc[i]=templist[i].desc; + if (imagelist[i] == tempcurrent) { + currentimage=i; + } + } + var markidx=0; + marklist=[]; + for (i in tempmark) { + markidx=imagelist.indexOf(tempmark[i]); + if (markidx!=-1) { + marklist.push(markidx); + } + } + thumblist(currentimage,currentimage); + return; +} + +function request() { + // Fetch ?q=search request and present first match. + var query = location.search.substr(1).split("="); + if ((query[0]=="q") && query.length>1 && query[1].length>0) { + for (imname in imagelist) { + if (imagelist[imname].indexOf(unescape(query[1])) != -1) { + return parseInt(imname); + break; + } + } + } + // Fetch ?p=position request and return the integer + if ((query[0]=="p") && query.length>1 && query[1].length>0) { + var retval=parseInt(query[1]); + if (isNaN(retval)) { return -1; } + retval=Math.max(1,retval); + retval=Math.min(retval,imagelist.length); + return retval-1; + } + + return -1; +} + +function markitem(i) { + // Adds an item in a list of selected images + if (imagelist.length==0) { return; } + if (i==-1) { return; } + var lel=document.getElementById('listcontainer'); + if (lel.innerHTML.length<4) { + lel.innerHTML='
Marked:'+ + 'edit'+ + 'copy'+ + '
'; + } + var existidx=marklist.indexOf(i); + if (existidx==-1) { + marklist.push(i); + } else { + marklist.splice(existidx,1); + } + marklisteditor(); + showimage(i); + return; +} + +function unmarkitem(i) { + // remove an item from selection list + marklist.splice(i,1); + marklisteditor(); + showimage(currentimage); + return; +} + +function marklisteditor() { + // print out an editor view of the selection list + var mel=document.getElementById('marklist'); + var liststr=''; + var dlstr='X
'+ + ''+imagelist[marklist[i]]+''; + dlstr+=imagelist[marklist[i]]+'%0A'; + } + dlstr+='">Download as file'; + liststr+='
'+ + 'delete list'+ + ''+ + ''+dlstr+''+ + '
'; + + + mel.innerHTML=liststr; + return; +} + +function marklisttable() { + // print out a copy-pastable text box of the selection list + var mel=document.getElementById('marklist'); + mel.innerHTML='
'; + var cel=document.getElementById('marktable'); + cel.onclick=marklistselect; + cel.onblur=marklistblur; + cel.cols=80; + cel.hasfocus=false; + for (i in marklist) { + cel.value=cel.value+'"'+imagelist[marklist[i]]+'"\r\n'; + } + var rows=cel.value.split(/\r?\n|\r/).length + 1; + cel.rows=rows; + marklistselect(); + return; +} + +function deletemarklist() { + // delete the selection list + var answer = confirm("Delete your selection list?") + if (answer) { + var lel=document.getElementById('listcontainer'); + lel.innerHTML=''; + marklist=[]; + showimage(currentimage); + } + return +} + +function marklistselect() { + // set focus to selection list text area + var cel=document.getElementById('marktable'); + cel.hasfocus=true; + cel.select(); +} + +function marklistblur() { + // set blur to selection list text area + var cel=document.getElementById('marktable'); + cel.hasfocus=false; +} + +function nicestring(s) { + // Return a nice version of a string + s=String(s); + if (s.length<20) { + return s; + } + s=s.replace(/_/g,' '); + s=s.replace(/-/g,' '); + if (s.length>30) { + s=s.substring(0,26)+'..'+s.substring(s.length-4); + } + return s; +} + +function titlestring(s) { + // Return a nice version of a string for title attribute + s=s.replace(/"/g,"""); + s=s.replace(/<\/?[^>]+(>|$)/g, ""); + return s; +} + +function fliporiginals() { + // Use original images / medium size jpegs + if (originals) + { originals=false; } + else + { originals=true; } + showimage(currentimage); +} + +function getmaxthumbs() { + return Math.floor((document.body.clientWidth-30)/100)-2; +} + +function hidethumbs() { + // hide all thumbnails + if (notsupported()) { + return; + } + for (n=0; n(imagelist.length-1)) { currentimage=0; } + showimage(currentimage); + } + if (unicode==39 && shift==1) { + currentimage+=maxThumb; + if (currentimage>(imagelist.length-1)) { currentimage=0; } + showimage(currentimage); + } + if (unicode==88) { + markitem(currentimage); + } + //Debug: + //alert(unicode); + + return; +} + +function notsupported() { + // not supported devices (i.e. the javascript doesnt work properly ) + if (uagent.search('series60')>-1) { + return true; + } + if (uagent.search('opera mobi')>-1) { + return true; + } + return false; +}