Merge branch 'develop' of git://github.com/shish/shimmie2

This commit is contained in:
jgen 2014-02-23 03:11:09 -05:00
commit cebc197fba
57 changed files with 744 additions and 1224 deletions

View File

@ -44,7 +44,6 @@ class BaseThemelet {
$h_thumb_link = $image->get_thumb_link(); $h_thumb_link = $image->get_thumb_link();
$h_tip = html_escape($image->get_tooltip()); $h_tip = html_escape($image->get_tooltip());
$h_tags = strtolower($image->get_tag_list()); $h_tags = strtolower($image->get_tag_list());
$base = get_base_href();
$ext = strtolower($image->ext); $ext = strtolower($image->ext);
// If the file doesn't support thumbnail generation, show it at max size. // If the file doesn't support thumbnail generation, show it at max size.
@ -55,7 +54,13 @@ class BaseThemelet {
$tsize = get_thumbnail_size($image->width, $image->height); $tsize = get_thumbnail_size($image->width, $image->height);
} }
return "<a href='$h_view_link' class='thumb shm-thumb shm-thumb-link' data-tags='$h_tags' data-post-id='$i_id'>". $custom_classes = "";
if(class_exists("Relationships")){
if($image->parent_id !== NULL){ $custom_classes .= "shm-thumb-has_parent "; }
if($image->has_children == TRUE){ $custom_classes .= "shm-thumb-has_child "; }
}
return "<a href='$h_view_link' class='thumb shm-thumb shm-thumb-link {$custom_classes}' data-tags='$h_tags' data-post-id='$i_id'>".
"<img id='thumb_$i_id' title='$h_tip' alt='$h_tip' height='{$tsize[1]}' width='{$tsize[0]}' src='$h_thumb_link'>". "<img id='thumb_$i_id' title='$h_tip' alt='$h_tip' height='{$tsize[1]}' width='{$tsize[0]}' src='$h_thumb_link'>".
"</a>\n"; "</a>\n";
} }
@ -86,7 +91,7 @@ class BaseThemelet {
private function build_paginator($current_page, $total_pages, $base_url, $query) { private function build_paginator($current_page, $total_pages, $base_url, $query) {
$next = $current_page + 1; $next = $current_page + 1;
$prev = $current_page - 1; $prev = $current_page - 1;
$rand = rand(1, $total_pages); $rand = mt_rand(1, $total_pages);
$at_start = ($current_page <= 1 || $total_pages <= 1); $at_start = ($current_page <= 1 || $total_pages <= 1);
$at_end = ($current_page >= $total_pages); $at_end = ($current_page >= $total_pages);

View File

@ -479,15 +479,9 @@ class Image {
$this->delete_tags_from_image(); $this->delete_tags_from_image();
// insert each new tags // insert each new tags
foreach($tags as $tag) { foreach($tags as $tag) {
if(preg_match("/^source[=|:](.*)$/i", $tag, $matches)) { $ttpe = new TagTermParseEvent($tag, $this->id);
$this->set_source($matches[1]); send_event($ttpe);
continue; if($ttpe->is_metatag()) {
}
if(preg_match("/^pool[=|:](.*)$/i", $tag, $matches)) {
if(class_exists("Pools")) {
$pls = new Pools();
$pls->add_post_from_tag($matches[1], $this->id);
}
continue; continue;
} }

View File

@ -36,7 +36,7 @@ _d("WH_SPLITS", 1); // int how many levels of subfolders to put in
_d("VERSION", 'trunk'); // string shimmie version _d("VERSION", 'trunk'); // string shimmie version
_d("TIMEZONE", null); // string timezone _d("TIMEZONE", null); // string timezone
_d("MIN_FREE_SPACE",100*1024*1024); // int disable uploading if there's less than MIN_FREE_SPACE bytes free space _d("MIN_FREE_SPACE",100*1024*1024); // int disable uploading if there's less than MIN_FREE_SPACE bytes free space
_d("CORE_EXTS", "bbcode,user,mail,upload,image,view,handle_pixel,ext_manager,setup,upgrade,handle_404,comment,tag_list,index,tag_edit,alias_editor,hellban"); // extensions to always enable _d("CORE_EXTS", "bbcode,user,mail,upload,image,view,handle_pixel,ext_manager,setup,upgrade,handle_404,comment,tag_list,index,tag_edit,alias_editor"); // extensions to always enable
_d("EXTRA_EXTS", ""); // optional extra extensions _d("EXTRA_EXTS", ""); // optional extra extensions

View File

@ -164,7 +164,7 @@ class AdminPage extends Extension {
global $page; global $page;
$matches = array(); $matches = array();
preg_match("#^(?P<proto>\w+)\:(?:user=(?P<user>\w+)(?:;|$)|password=(?P<password>\w+)(?:;|$)|host=(?P<host>[\w\.\-]+)(?:;|$)|dbname=(?P<dbname>[\w_]+)(?:;|$))+#", DATABASE_DSN, $matches); preg_match("#^(?P<proto>\w+)\:(?:user=(?P<user>\w+)(?:;|$)|password=(?P<password>\w*)(?:;|$)|host=(?P<host>[\w\.\-]+)(?:;|$)|dbname=(?P<dbname>[\w_]+)(?:;|$))+#", DATABASE_DSN, $matches);
$software = $matches['proto']; $software = $matches['proto'];
$username = $matches['user']; $username = $matches['user'];
$password = $matches['password']; $password = $matches['password'];
@ -184,6 +184,8 @@ class AdminPage extends Extension {
break; break;
} }
//FIXME: .SQL dump is empty if cmd doesn't exist
$page->set_mode("data"); $page->set_mode("data");
$page->set_type("application/x-unknown"); $page->set_type("application/x-unknown");
$page->set_filename('shimmie-'.date('Ymd').'.sql'); $page->set_filename('shimmie-'.date('Ymd').'.sql');
@ -195,67 +197,59 @@ class AdminPage extends Extension {
private function download_all_images() { private function download_all_images() {
global $database, $page; global $database, $page;
$zip = new ZipArchive; $images = $database->get_all("SELECT hash, ext FROM images");
$images = $database->get_all("SELECT * FROM images");
$filename = data_path('imgdump-'.date('Ymd').'.zip'); $filename = data_path('imgdump-'.date('Ymd').'.zip');
if($zip->open($filename, 1 ? ZIPARCHIVE::OVERWRITE:ZIPARCHIVE::CREATE) === TRUE){ $zip = new ZipArchive;
if($zip->open($filename, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) === TRUE){
foreach($images as $img){ foreach($images as $img){
$hash = $img["hash"]; $img_loc = warehouse_path("images", $img["hash"], FALSE);
preg_match("^[A-Za-z0-9]{2}^", $hash, $matches); $zip->addFile($img_loc, $img["hash"].".".$img["ext"]);
$img_loc = "images/".$matches[0]."/".$hash;
if(file_exists($img_loc)){
$zip->addFile($img_loc, $hash.".".$img["ext"]);
}
} }
$zip->close(); $zip->close();
} }
$page->set_mode("redirect"); $page->set_mode("redirect");
$page->set_redirect(make_link($filename)); //Fairly sure there is better way to do this.. $page->set_redirect(make_link($filename)); //TODO: Delete file after downloaded?
//TODO: Delete file after downloaded?
return false; // we do want a redirect, but a manual one return false; // we do want a redirect, but a manual one
} }
private function reset_image_ids() { private function reset_image_ids() {
global $database; global $database;
//This might be a bit laggy on boards with lots of images (?) //TODO: Make work with PostgreSQL + SQLite
//Seems to work fine with 1.2k~ images though. //TODO: Update score_log (Having an optional ID column for score_log would be nice..)
$i = 0; preg_match("#^(?P<proto>\w+)\:(?:user=(?P<user>\w+)(?:;|$)|password=(?P<password>\w*)(?:;|$)|host=(?P<host>[\w\.\-]+)(?:;|$)|dbname=(?P<dbname>[\w_]+)(?:;|$))+#", DATABASE_DSN, $matches);
$image = $database->get_all("SELECT * FROM images ORDER BY images.id ASC");
/*$score_log = $database->get_all("SELECT message FROM score_log");*/ if($matches['proto'] == "mysql"){
foreach($image as $img){ $tables = $database->get_col("SELECT TABLE_NAME
$xid = $img[0]; FROM information_schema.KEY_COLUMN_USAGE
$i = $i + 1; WHERE TABLE_SCHEMA = :db
$table = array( //Might be missing some tables? AND REFERENCED_COLUMN_NAME = 'id'
"image_tags", "tag_histories", "image_reports", "comments", "user_favorites", "tag_histories", AND REFERENCED_TABLE_NAME = 'images'", array("db" => $matches['dbname']));
"numeric_score_votes", "pool_images", "slext_progress_cache", "notes");
$i = 1;
$sql = $ids = $database->get_col("SELECT id FROM images ORDER BY images.id ASC");
"SET FOREIGN_KEY_CHECKS=0; foreach($ids as $id){
UPDATE images $sql = "SET FOREIGN_KEY_CHECKS=0;
SET id=".$i. UPDATE images SET id={$i} WHERE image_id={$id};";
" WHERE id=".$xid.";"; //id for images
foreach($tables as $table){
foreach($table as $tbl){ $sql .= "UPDATE {$table} SET image_id={$i} WHERE image_id={$id};";
$sql .= " }
UPDATE ".$tbl."
SET image_id=".$i." $sql .= " SET FOREIGN_KEY_CHECKS=1;";
WHERE image_id=".$xid.";"; $database->execute($sql);
}
$i++;
/*foreach($score_log as $sl){ }
//This seems like a bad idea. $database->execute("ALTER TABLE images AUTO_INCREMENT=".(count($ids) + 1));
//TODO: Might be better for log_info to have an $id option (which would then affix the id to the table?) }elseif($matches['proto'] == "pgsql"){
preg_replace(".Image \\#[0-9]+.", "Image #".$i, $sl); //TODO: Make this work with PostgreSQL
}*/ }elseif($matches['proto'] == "sqlite"){
$sql .= " SET FOREIGN_KEY_CHECKS=1;"; //TODO: Make this work with SQLite
$database->execute($sql); }
}
$count = (count($image)) + 1;
$database->execute("ALTER TABLE images AUTO_INCREMENT=".$count);
return true; return true;
} }
} }

View File

@ -38,8 +38,8 @@ class AdminPageTheme extends Themelet {
$html = ""; $html = "";
$html .= $this->button("All tags to lowercase", "lowercase_all_tags", true); $html .= $this->button("All tags to lowercase", "lowercase_all_tags", true);
$html .= $this->button("Recount tag use", "recount_tag_user", false); $html .= $this->button("Recount tag use", "recount_tag_use", false);
$html .= $this->button("Download all images", "image_dump", false); $html .= $this->button("Download all images", "download_all_images", false);
$html .= $this->button("Download database contents", "database_dump", false); $html .= $this->button("Download database contents", "database_dump", false);
if($database->get_driver_name() == "mysql") if($database->get_driver_name() == "mysql")
$html .= $this->button("Reset image IDs", "reset_image_ids", true); $html .= $this->button("Reset image IDs", "reset_image_ids", true);

View File

@ -8,82 +8,75 @@
* Documentation: * Documentation:
* Simply enable this extention in the extention manager to enable arrow key navigation. * Simply enable this extention in the extention manager to enable arrow key navigation.
*/ */
class ArrowkeyNavigation extends Extension { class ArrowkeyNavigation extends Extension {
# Adds functionality for post/view on images # Adds functionality for post/view on images
public function onDisplayingImage(DisplayingImageEvent $event) { public function onDisplayingImage(DisplayingImageEvent $event) {
$prev_url = make_http(make_link("post/prev/".$event->image->id)); $prev_url = make_http(make_link("post/prev/".$event->image->id));
$next_url = make_http(make_link("post/next/".$event->image->id)); $next_url = make_http(make_link("post/next/".$event->image->id));
$this->add_arrowkeys_code($prev_url, $next_url); $this->add_arrowkeys_code($prev_url, $next_url);
} }
# Adds functionality for post/list
public function onPageRequest(PageRequestEvent $event) {
if($event->page_matches("post/list")) {
$pageinfo = $this->get_list_pageinfo($event);
$prev_url = make_http(make_link("post/list/".$pageinfo["prev"]));
$next_url = make_http(make_link("post/list/".$pageinfo["next"]));
$this->add_arrowkeys_code($prev_url, $next_url);
}
}
# adds the javascript to the page with the given urls
private function add_arrowkeys_code($prev_url, $next_url) {
global $page;
$page->add_html_header("<script type=\"text/javascript\"> # Adds functionality for post/list
document.onkeyup=checkKeycode; public function onPageRequest(PageRequestEvent $event) {
function checkKeycode(e) if($event->page_matches("post/list")) {
{ $pageinfo = $this->get_list_pageinfo($event);
var keycode; $prev_url = make_http(make_link("post/list/".$pageinfo["prev"]));
if(window.event) keycode=window.event.keyCode; $next_url = make_http(make_link("post/list/".$pageinfo["next"]));
else if(e) keycode=e.which; $this->add_arrowkeys_code($prev_url, $next_url);
}
}
if (e.srcElement.tagName != \"INPUT\") # adds the javascript to the page with the given urls
{ private function add_arrowkeys_code($prev_url, $next_url) {
if(keycode==\"37\") window.location.href='$prev_url'; global $page;
else if(keycode==\"39\") window.location.href='$next_url';
} $page->add_html_header("<script type=\"text/javascript\">
} (function($){
</script>"); $(document).keyup(function(e) {
} if($(e.target).is('input', 'textarea')){ return; }
if (e.keyCode == 37) { window.location.href = '{$prev_url}'; }
# returns info about the current page number else if (e.keyCode == 39) { window.location.href = '{$next_url}'; }
private function get_list_pageinfo($event) { });
global $config, $database; })(jQuery);
</script>", 60);
// get the amount of images per page }
$images_per_page = $config->get_int('index_images');
# returns info about the current page number
// if there are no tags, use default private function get_list_pageinfo($event) {
if ($event->get_arg(1) == null){ global $config, $database;
$prefix = "";
$page_number = (int)$event->get_arg(0); // get the amount of images per page
$total_pages = ceil($database->get_one( $images_per_page = $config->get_int('index_images');
"SELECT COUNT(*) FROM images") / $images_per_page);
} // if there are no tags, use default
if ($event->get_arg(1) == null){
else { // if there are tags, use pages with tags $prefix = "";
$prefix = $event->get_arg(0)."/"; $page_number = (int)$event->get_arg(0);
$page_number = (int)$event->get_arg(1); $total_pages = ceil($database->get_one(
$total_pages = ceil($database->get_one( "SELECT COUNT(*) FROM images") / $images_per_page);
"SELECT count FROM tags WHERE tag=:tag", }
array("tag"=>$event->get_arg(0))) / $images_per_page); else { // if there are tags, use pages with tags
} $prefix = $event->get_arg(0)."/";
$page_number = (int)$event->get_arg(1);
// creates previous & next values $total_pages = ceil($database->get_one(
// When previous first page, go to last page "SELECT count FROM tags WHERE tag=:tag",
if ($page_number <= 1) $prev = $total_pages; array("tag"=>$event->get_arg(0))) / $images_per_page);
else $prev = $page_number-1; }
if ($page_number >= $total_pages) $next = 1;
else $next = $page_number+1; // creates previous & next values
// When previous first page, go to last page
// Create return array if ($page_number <= 1) $prev = $total_pages;
$pageinfo = array( else $prev = $page_number-1;
"prev" => $prefix.$prev, if ($page_number >= $total_pages) $next = 1;
"next" => $prefix.$next, else $next = $page_number+1;
);
// Create return array
return $pageinfo; $pageinfo = array(
} "prev" => $prefix.$prev,
"next" => $prefix.$next,
);
return $pageinfo;
}
} }
?> ?>

View File

@ -45,7 +45,7 @@ class Artists extends Extension {
public function onSearchTermParse(SearchTermParseEvent $event) { public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array(); $matches = array();
if(preg_match("/^author[=|:](.*)$/", $event->term, $matches)) { if(preg_match("/^author[=|:](.*)$/i", $event->term, $matches)) {
$char = $matches[1]; $char = $matches[1];
$event->add_querylet(new Querylet("Author = :author_char", array("author_char"=>$char))); $event->add_querylet(new Querylet("Author = :author_char", array("author_char"=>$char)));
} }

View File

@ -1,6 +1,6 @@
<?php <?php
/* /*
* Name: Bulk Remove (Beta) * Name: [Beta] Bulk Remove
* Author: Drudex Software <support@drudexsoftware.com> * Author: Drudex Software <support@drudexsoftware.com>
* Link: http://www.drudexsoftware.com/ * Link: http://www.drudexsoftware.com/
* License: GPLv2 * License: GPLv2

View File

@ -1,6 +1,6 @@
<?php <?php
/** /**
* Name: Chatbox (Beta) * Name: [Beta] Chatbox
* Author: Drudex Software <support@drudexsoftware.com> * Author: Drudex Software <support@drudexsoftware.com>
* Link: http://www.drudexsoftware.com * Link: http://www.drudexsoftware.com
* License: GPLv2 * License: GPLv2

View File

@ -262,7 +262,7 @@ class CommentList extends Extension {
public function onSearchTermParse(SearchTermParseEvent $event) { public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array(); $matches = array();
if(preg_match("/^comments([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/", $event->term, $matches)) { if(preg_match("/^comments([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) {
$cmp = ltrim($matches[1], ":") ?: "="; $cmp = ltrim($matches[1], ":") ?: "=";
$comments = $matches[2]; $comments = $matches[2];
$event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM comments GROUP BY image_id HAVING count(image_id) $cmp $comments)")); $event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM comments GROUP BY image_id HAVING count(image_id) $cmp $comments)"));

View File

@ -117,7 +117,7 @@ class Favorites extends Extension {
public function onSearchTermParse(SearchTermParseEvent $event) { public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array(); $matches = array();
if(preg_match("/^favorites([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/", $event->term, $matches)) { if(preg_match("/^favorites([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) {
$cmp = ltrim($matches[1], ":") ?: "="; $cmp = ltrim($matches[1], ":") ?: "=";
$favorites = $matches[2]; $favorites = $matches[2];
$event->add_querylet(new Querylet("images.id IN (SELECT id FROM images WHERE favorites $cmp $favorites)")); $event->add_querylet(new Querylet("images.id IN (SELECT id FROM images WHERE favorites $cmp $favorites)"));

View File

@ -1,4 +1,8 @@
<?php <?php
/*
* Name: [Beta] Hellban
*/
class HellBan extends Extension { class HellBan extends Extension {
public function onPageRequest(PageRequestEvent $event) { public function onPageRequest(PageRequestEvent $event) {
global $page, $user; global $page, $user;

View File

@ -109,6 +109,7 @@
* <li>downvoted_by=Username -- search for a user's dislikes * <li>downvoted_by=Username -- search for a user's dislikes
* <li>upvoted_by_id=UserID -- search for a user's likes by user ID * <li>upvoted_by_id=UserID -- search for a user's likes by user ID
* <li>downvoted_by_id=UserID -- search for a user's dislikes by user ID * <li>downvoted_by_id=UserID -- search for a user's dislikes by user ID
* <li>order=score_(ASC, DESC) -- find all images sorted from by score
* </ul> * </ul>
* <li>Image Rating * <li>Image Rating
* <ul> * <ul>
@ -141,6 +142,11 @@
* <li>pool=(PoolID, any, none) -- search for images in a pool by PoolID. * <li>pool=(PoolID, any, none) -- search for images in a pool by PoolID.
* <li>pool_by_name=PoolName -- search for images in a pool by PoolName. underscores are replaced with spaces * <li>pool_by_name=PoolName -- search for images in a pool by PoolName. underscores are replaced with spaces
* </ul> * </ul>
* <li>Post Relationships
* <ul>
* <li>parent=(parentID, any, none) -- search for images by parentID / if they have, do not have a parent
* <li>child=(any, none) -- search for images which have, or do not have children
* </ul>
* </ul> * </ul>
*/ */
@ -295,12 +301,12 @@ class Index extends Extension {
public function onSearchTermParse(SearchTermParseEvent $event) { public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array(); $matches = array();
// check for tags first as tag based searches are more common. // check for tags first as tag based searches are more common.
if(preg_match("/^tags([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/", $event->term, $matches)) { if(preg_match("/^tags([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) {
$cmp = ltrim($matches[1], ":") ?: "="; $cmp = ltrim($matches[1], ":") ?: "=";
$tags = $matches[2]; $tags = $matches[2];
$event->add_querylet(new Querylet('images.id IN (SELECT DISTINCT image_id FROM image_tags GROUP BY image_id HAVING count(image_id) '.$cmp.' '.$tags.')')); $event->add_querylet(new Querylet('images.id IN (SELECT DISTINCT image_id FROM image_tags GROUP BY image_id HAVING count(image_id) '.$cmp.' '.$tags.')'));
} }
else if(preg_match("/^ratio([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+):(\d+)$/", $event->term, $matches)) { else if(preg_match("/^ratio([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+):(\d+)$/i", $event->term, $matches)) {
$cmp = preg_replace('/^:/', '=', $matches[1]); $cmp = preg_replace('/^:/', '=', $matches[1]);
$args = array("width{$this->stpen}"=>int_escape($matches[2]), "height{$this->stpen}"=>int_escape($matches[3])); $args = array("width{$this->stpen}"=>int_escape($matches[2]), "height{$this->stpen}"=>int_escape($matches[3]));
$event->add_querylet(new Querylet("width / height $cmp :width{$this->stpen} / :height{$this->stpen}", $args)); $event->add_querylet(new Querylet("width / height $cmp :width{$this->stpen} / :height{$this->stpen}", $args));
@ -326,28 +332,28 @@ class Index extends Extension {
else if(preg_match("/^(source)[=|:](.*)$/i", $event->term, $matches)) { else if(preg_match("/^(source)[=|:](.*)$/i", $event->term, $matches)) {
$source = strtolower($matches[2]); $source = strtolower($matches[2]);
if(preg_match("/^(any|none)$/", $source)){ if(preg_match("/^(any|none)$/i", $source)){
$not = ($source == "any" ? "NOT" : ""); $not = ($source == "any" ? "NOT" : "");
$event->add_querylet(new Querylet("images.source IS $not NULL")); $event->add_querylet(new Querylet("images.source IS $not NULL"));
}else{ }else{
$event->add_querylet(new Querylet('images.source LIKE :src', array("src"=>"%$source%"))); $event->add_querylet(new Querylet('images.source LIKE :src', array("src"=>"%$source%")));
} }
} }
else if(preg_match("/^posted([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])([0-9-]*)$/", $event->term, $matches)) { else if(preg_match("/^posted([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])([0-9-]*)$/i", $event->term, $matches)) {
$cmp = ltrim($matches[1], ":") ?: "="; $cmp = ltrim($matches[1], ":") ?: "=";
$val = $matches[2]; $val = $matches[2];
$event->add_querylet(new Querylet("images.posted $cmp :posted{$this->stpen}", array("posted{$this->stpen}"=>$val))); $event->add_querylet(new Querylet("images.posted $cmp :posted{$this->stpen}", array("posted{$this->stpen}"=>$val)));
} }
else if(preg_match("/^size([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)x(\d+)$/", $event->term, $matches)) { else if(preg_match("/^size([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)x(\d+)$/i", $event->term, $matches)) {
$cmp = ltrim($matches[1], ":") ?: "="; $cmp = ltrim($matches[1], ":") ?: "=";
$args = array("width{$this->stpen}"=>int_escape($matches[2]), "height{$this->stpen}"=>int_escape($matches[3])); $args = array("width{$this->stpen}"=>int_escape($matches[2]), "height{$this->stpen}"=>int_escape($matches[3]));
$event->add_querylet(new Querylet("width $cmp :width{$this->stpen} AND height $cmp :height{$this->stpen}", $args)); $event->add_querylet(new Querylet("width $cmp :width{$this->stpen} AND height $cmp :height{$this->stpen}", $args));
} }
else if(preg_match("/^width([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/", $event->term, $matches)) { else if(preg_match("/^width([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) {
$cmp = ltrim($matches[1], ":") ?: "="; $cmp = ltrim($matches[1], ":") ?: "=";
$event->add_querylet(new Querylet("width $cmp :width{$this->stpen}", array("width{$this->stpen}"=>int_escape($matches[2])))); $event->add_querylet(new Querylet("width $cmp :width{$this->stpen}", array("width{$this->stpen}"=>int_escape($matches[2]))));
} }
else if(preg_match("/^height([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/", $event->term, $matches)) { else if(preg_match("/^height([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)$/i", $event->term, $matches)) {
$cmp = ltrim($matches[1], ":") ?: "="; $cmp = ltrim($matches[1], ":") ?: "=";
$event->add_querylet(new Querylet("height $cmp :height{$this->stpen}",array("height{$this->stpen}"=>int_escape($matches[2])))); $event->add_querylet(new Querylet("height $cmp :height{$this->stpen}",array("height{$this->stpen}"=>int_escape($matches[2]))));
} }

View File

@ -214,7 +214,7 @@ class Notes extends Extension {
$notes = int_escape($matches[1]); $notes = int_escape($matches[1]);
$event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE note = $notes)")); $event->add_querylet(new Querylet("images.id IN (SELECT image_id FROM notes WHERE note = $notes)"));
} }
else if(preg_match("/^notes([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)%/", $event->term, $matches)) { else if(preg_match("/^notes([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(\d+)%/i", $event->term, $matches)) {
$cmp = ltrim($matches[1], ":") ?: "="; $cmp = ltrim($matches[1], ":") ?: "=";
$notes = $matches[2]; $notes = $matches[2];
$event->add_querylet(new Querylet("images.id IN (SELECT id FROM images WHERE notes $cmp $notes)")); $event->add_querylet(new Querylet("images.id IN (SELECT id FROM images WHERE notes $cmp $notes)"));

View File

@ -1,6 +1,6 @@
$(function() { $(function() {
if(window.notes) { if(window.notes) {
$('#main_image').imgNotes(window.notes); $('#main_image').imgNotes({notes: window.notes});
} }
$('#cancelnote').click(function(){ $('#cancelnote').click(function(){

View File

@ -63,7 +63,7 @@ class NumericScore extends Extension {
} }
die($html); die($html);
} }
if($event->page_matches("numeric_score_vote") && $user->check_auth_token()) { else if($event->page_matches("numeric_score_vote") && $user->check_auth_token()) {
if(!$user->is_anonymous()) { if(!$user->is_anonymous()) {
$image_id = int_escape($_POST['image_id']); $image_id = int_escape($_POST['image_id']);
$char = $_POST['vote']; $char = $_POST['vote'];
@ -76,7 +76,7 @@ class NumericScore extends Extension {
$page->set_redirect(make_link("post/view/$image_id")); $page->set_redirect(make_link("post/view/$image_id"));
} }
} }
if($event->page_matches("numeric_score/remove_votes_on") && $user->check_auth_token()) { else if($event->page_matches("numeric_score/remove_votes_on") && $user->check_auth_token()) {
if($user->can("edit_other_vote")) { if($user->can("edit_other_vote")) {
$image_id = int_escape($_POST['image_id']); $image_id = int_escape($_POST['image_id']);
$database->execute( $database->execute(
@ -89,83 +89,62 @@ class NumericScore extends Extension {
$page->set_redirect(make_link("post/view/$image_id")); $page->set_redirect(make_link("post/view/$image_id"));
} }
} }
if($event->page_matches("numeric_score/remove_votes_by") && $user->check_auth_token()) { else if($event->page_matches("numeric_score/remove_votes_by") && $user->check_auth_token()) {
if($user->can("edit_other_vote")) { if($user->can("edit_other_vote")) {
$this->delete_votes_by(int_escape($_POST['user_id'])); $this->delete_votes_by(int_escape($_POST['user_id']));
$page->set_mode("redirect"); $page->set_mode("redirect");
$page->set_redirect(make_link()); $page->set_redirect(make_link());
} }
} }
if($event->page_matches("popular_by_day") || $event->page_matches("popular_by_month") || $event->page_matches("popular_by_year")) { else if($event->page_matches("popular_by_day") || $event->page_matches("popular_by_month") || $event->page_matches("popular_by_year")) {
$t_images = $config->get_int("index_images"); //FIXME: popular_by isn't linked from anywhere
list($day, $month, $year) = array(date("d"), date("m"), date("Y"));
//TODO: Add Popular_by_week. if(!empty($_GET['day'])){
$D = (int) $_GET['day'];
if($D >= 1 && $D <= 31) $day = $D;
}
if(!empty($_GET['month'])){
$M = (int) $_GET['month'];
if($M >= 1 && $M <= 12) $month = $M;
}
if(!empty($_GET['year'])){
$Y = (int) $_GET['year'];
if($Y >= 1970 && $Y < 2100) $year = $Y;
}
//year
if(empty($_GET['year'])){
$year = date("Y");
}else{
$year = $_GET['year'];
}
//month
if(empty($_GET['month']) || int_escape($_GET['month']) > 12){
$month = date("m");
}else{
$month = $_GET['month'];
}
//day
if(empty($_GET['day']) || int_escape($_GET['day']) > 31){
$day = date("d");
}else{
$day = $_GET['day'];
}
$totaldate = $year."/".$month."/".$day; $totaldate = $year."/".$month."/".$day;
$sql = $sql = "SELECT id FROM images
"SELECT * FROM images WHERE EXTRACT(YEAR FROM posted) = :year
WHERE EXTRACT(YEAR FROM posted) = :year ";
"; $args = array("limit" => $config->get_int("index_images"), "year" => $year);
$agrs = array("limit" => $t_images, "year" => $year);
if($event->page_matches("popular_by_day")){ if($event->page_matches("popular_by_day")){
$sql .= $sql .=
"AND EXTRACT(MONTH FROM posted) = :month "AND EXTRACT(MONTH FROM posted) = :month
AND EXTRACT(DAY FROM posted) = :day AND EXTRACT(DAY FROM posted) = :day";
AND NOT numeric_score=0
";
//array_push doesn't seem to like using double arrows
//this requires us to instead create two arrays and merge
$sgra = array("month" => $month, "day" => $day);
$args = array_merge($agrs, $sgra);
$args = array_merge($args, array("month" => $month, "day" => $day));
$dte = array($totaldate, date("F jS, Y", (strtotime($totaldate))), "\\y\\e\\a\\r\\=Y\\&\\m\\o\\n\\t\\h\\=m\\&\\d\\a\\y\\=d", "day"); $dte = array($totaldate, date("F jS, Y", (strtotime($totaldate))), "\\y\\e\\a\\r\\=Y\\&\\m\\o\\n\\t\\h\\=m\\&\\d\\a\\y\\=d", "day");
} }
if($event->page_matches("popular_by_month")){ else if($event->page_matches("popular_by_month")){
$sql .= $sql .= "AND EXTRACT(MONTH FROM posted) = :month";
"AND EXTRACT(MONTH FROM posted) = :month
AND NOT numeric_score=0
";
$sgra = array("month" => $month);
$args = array_merge($agrs, $sgra);
$title = date("F Y", (strtotime($totaldate))); $args = array_merge($args, array("month" => $month));
$dte = array($totaldate, $title, "\\y\\e\\a\\r\\=Y\\&\\m\\o\\n\\t\\h\\=m", "month"); $dte = array($totaldate, date("F Y", (strtotime($totaldate))), "\\y\\e\\a\\r\\=Y\\&\\m\\o\\n\\t\\h\\=m", "month");
} }
if($event->page_matches("popular_by_year")){ else if($event->page_matches("popular_by_year")){
$sql .= "AND NOT numeric_score=0"; $dte = array($totaldate, $year, "\\y\\e\\a\\r\=Y", "year");
$dte = array($totaldate, $year, "\y\e\a\\r\=Y", "year");
$args = $agrs;
} }
$sql .= " ORDER BY numeric_score DESC LIMIT :limit OFFSET 0"; $sql .= " AND NOT numeric_score=0 ORDER BY numeric_score DESC LIMIT :limit OFFSET 0";
//filter images by year/score != 0 > limit to max images on one page > order from highest to lowest score //filter images by score != 0 + date > limit to max images on one page > order from highest to lowest score
$result = $database->get_all($sql, $args);
$result = $database->get_col($sql, $args);
$images = array(); $images = array();
foreach($result as $singleResult) { foreach($result as $id) { $images[] = Image::by_id($id); }
$images[] = Image::by_id($singleResult["id"]);
}
$this->theme->view_popular($images, $dte); $this->theme->view_popular($images, $dte);
} }
} }
@ -217,12 +196,12 @@ class NumericScore extends Extension {
public function onSearchTermParse(SearchTermParseEvent $event) { public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array(); $matches = array();
if(preg_match("/^score([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(-?\d+)$/", $event->term, $matches)) { if(preg_match("/^score([:]?<|[:]?>|[:]?<=|[:]?>=|[:|=])(-?\d+)$/i", $event->term, $matches)) {
$cmp = ltrim($matches[1], ":") ?: "="; $cmp = ltrim($matches[1], ":") ?: "=";
$score = $matches[2]; $score = $matches[2];
$event->add_querylet(new Querylet("numeric_score $cmp $score")); $event->add_querylet(new Querylet("numeric_score $cmp $score"));
} }
if(preg_match("/^upvoted_by[=|:](.*)$/", $event->term, $matches)) { else if(preg_match("/^upvoted_by[=|:](.*)$/i", $event->term, $matches)) {
$duser = User::by_name($matches[1]); $duser = User::by_name($matches[1]);
if(is_null($duser)) { if(is_null($duser)) {
throw new SearchTermParseException( throw new SearchTermParseException(
@ -232,7 +211,7 @@ class NumericScore extends Extension {
"images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)", "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)",
array("ns_user_id"=>$duser->id))); array("ns_user_id"=>$duser->id)));
} }
if(preg_match("/^downvoted_by[=|:](.*)$/", $event->term, $matches)) { else if(preg_match("/^downvoted_by[=|:](.*)$/i", $event->term, $matches)) {
$duser = User::by_name($matches[1]); $duser = User::by_name($matches[1]);
if(is_null($duser)) { if(is_null($duser)) {
throw new SearchTermParseException( throw new SearchTermParseException(
@ -242,18 +221,39 @@ class NumericScore extends Extension {
"images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)", "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)",
array("ns_user_id"=>$duser->id))); array("ns_user_id"=>$duser->id)));
} }
if(preg_match("/^upvoted_by_id[=|:](\d+)$/", $event->term, $matches)) { else if(preg_match("/^upvoted_by_id[=|:](\d+)$/i", $event->term, $matches)) {
$iid = int_escape($matches[1]); $iid = int_escape($matches[1]);
$event->add_querylet(new Querylet( $event->add_querylet(new Querylet(
"images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)", "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=1)",
array("ns_user_id"=>$iid))); array("ns_user_id"=>$iid)));
} }
if(preg_match("/^downvoted_by_id[=|:](\d+)$/", $event->term, $matches)) { else if(preg_match("/^downvoted_by_id[=|:](\d+)$/i", $event->term, $matches)) {
$iid = int_escape($matches[1]); $iid = int_escape($matches[1]);
$event->add_querylet(new Querylet( $event->add_querylet(new Querylet(
"images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)", "images.id in (SELECT image_id FROM numeric_score_votes WHERE user_id=:ns_user_id AND score=-1)",
array("ns_user_id"=>$iid))); array("ns_user_id"=>$iid)));
} }
else if(preg_match("/^order[=|:](numeric_)?(score)[_]?(desc|asc)?$/i", $event->term, $matches)){
global $order_sql;
$default_order_for_column = "DESC";
$sort = isset($matches[3]) ? strtoupper($matches[3]) : $default_order_for_column;
$order_sql = "numeric_score $sort";
$event->add_querylet(new Querylet("1=1")); //small hack to avoid metatag being treated as normal tag
}
}
public function onTagTermParse(TagTermParseEvent $event) {
$matches = array();
if(preg_match("/^vote[=|:](up|down|remove)$/", $event->term, $matches)) {
global $user;
$score = ($matches[1] == "up" ? 1 : ($matches[1] == "down" ? -1 : 0));
if(!$user->is_anonymous()) {
send_event(new NumericScoreSetEvent($event->id, $user, $score));
}
}
if(!empty($matches)) $event->metatag = true;
} }
private function install() { private function install() {

View File

@ -62,27 +62,28 @@ class NumericScoreTheme extends Themelet {
} }
public function view_popular($images, $dte) { public function view_popular($images, $dte) {
global $user, $page; global $page, $config;
$pop_images = ''; $pop_images = "";
foreach($images as $image) { foreach($images as $image) {
$thumb_html = $this->build_thumb_html($image); $pop_images .= $this->build_thumb_html($image)."\n";
$pop_images .= '<span class="thumb">'.
'<a href="$image_link">'.$thumb_html.'</a>'.
'</span>';
} }
$b_dte = make_link("popular_by_".$dte[3]."?".date($dte[2], (strtotime('-1 '.$dte[3], strtotime($dte[0]))))); $b_dte = make_link("popular_by_".$dte[3]."?".date($dte[2], (strtotime('-1 '.$dte[3], strtotime($dte[0])))));
$f_dte = make_link("popular_by_".$dte[3]."?".date($dte[2], (strtotime('+1 '.$dte[3], strtotime($dte[0]))))); $f_dte = make_link("popular_by_".$dte[3]."?".date($dte[2], (strtotime('+1 '.$dte[3], strtotime($dte[0])))));
$html = '<center><h3><a href="'.$b_dte.'">&laquo;</a> '.$dte[1] $html = "\n".
.' <a href="'.$f_dte.'">&raquo;</a>' "<center>\n".
.'</h3></center> " <h3>\n".
<br>'.$pop_images; " <a href='{$b_dte}'>&laquo;</a> {$dte[1]} <a href='{$f_dte}'>&raquo;</a>\n".
" </h3>\n".
"</center>\n".
"<br/>\n".$pop_images;
$nav_html = "<a href=".make_link().">Index</a>"; $nav_html = "<a href=".make_link().">Index</a>";
$page->set_heading($config->get_string('title'));
$page->add_block(new Block("Navigation", $nav_html, "left", 10)); $page->add_block(new Block("Navigation", $nav_html, "left", 10));
$page->add_block(new Block(null, $html, "main", 30)); $page->add_block(new Block(null, $html, "main", 30));
} }

View File

@ -1,6 +1,6 @@
<?php <?php
/* /*
* Name: [beta] PM triggers * Name: [Beta] PM triggers
* Author: Shish <webmaster@shishnet.org> * Author: Shish <webmaster@shishnet.org>
* License: GPLv2 * License: GPLv2
* Description: Send PMs in response to certain events (eg image deletion) * Description: Send PMs in response to certain events (eg image deletion)
@ -11,7 +11,7 @@ class PMTrigger extends Extension {
$this->send( $this->send(
$event->image->owner_id, $event->image->owner_id,
"[System] An image you uploaded has been deleted", "[System] An image you uploaded has been deleted",
"Image le gone~ (#{$image->id}, {$image->get_tag_list()})" "Image le gone~ (#{$event->image->id}, {$event->image->get_tag_list()})"
); );
} }

View File

@ -293,7 +293,7 @@ class Pools extends Extension {
public function onSearchTermParse(SearchTermParseEvent $event) { public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array(); $matches = array();
if(preg_match("/^pool[=|:]([0-9]+|any|none)$/", $event->term, $matches)) { if(preg_match("/^pool[=|:]([0-9]+|any|none)$/i", $event->term, $matches)) {
$poolID = $matches[1]; $poolID = $matches[1];
if(preg_match("/^(any|none)$/", $poolID)){ if(preg_match("/^(any|none)$/", $poolID)){
@ -303,7 +303,7 @@ class Pools extends Extension {
$event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM pool_images WHERE pool_id = $poolID)")); $event->add_querylet(new Querylet("images.id IN (SELECT DISTINCT image_id FROM pool_images WHERE pool_id = $poolID)"));
} }
} }
else if(preg_match("/^pool_by_name[=|:](.*)$/", $event->term, $matches)) { else if(preg_match("/^pool_by_name[=|:](.*)$/i", $event->term, $matches)) {
$poolTitle = str_replace("_", " ", $matches[1]); $poolTitle = str_replace("_", " ", $matches[1]);
$pool = $this->get_single_pool_from_title($poolTitle); $pool = $this->get_single_pool_from_title($poolTitle);
@ -313,21 +313,26 @@ class Pools extends Extension {
} }
} }
public function add_post_from_tag(/*str*/ $poolTag, /*int*/ $imageID){ public function onTagTermParse(TagTermParseEvent $event) {
$poolTag = str_replace("_", " ", $poolTag); $matches = array();
//First check if pool tag is a title
if(ctype_digit($poolTag)){ if(preg_match("/^pool[=|:](.*)$/i", $event->term, $matches)) {
//If string only contains numeric characters, assume it is $poolID global $user;
if($this->get_single_pool($poolTag)){ //Make sure pool exists $poolTag = (string) str_replace("_", " ", $matches[1]);
$this->add_post($poolTag, $imageID);
$pool = null;
if(ctype_digit($poolTag)){ //If only digits, assume PoolID
$pool = $this->get_single_pool($poolTag);
}else{ //assume PoolTitle
$pool = $this->get_single_pool_from_title($poolTag);
} }
}else{
//If string doesn't contain only numeric characters, check to see if tag is title. if($pool ? $this->have_permission($user, $pool) : FALSE){
$pool = $this->get_single_pool_from_title($poolTag); $this->add_post($pool['id'], $event->id, true);
if($pool){
$this->add_post($pool['id'], $imageID);
} }
} }
if(!empty($matches)) $event->metatag = true;
} }
/* ------------------------------------------------- */ /* ------------------------------------------------- */
@ -830,9 +835,9 @@ class Pools extends Extension {
/* /*
* HERE WE ADD A SIMPLE POST FROM POOL * HERE WE ADD A SIMPLE POST FROM POOL
* USED WITH FOREACH IN revert_history() * USED WITH FOREACH IN revert_history() & onTagTermParse()
*/ */
private function add_post(/*int*/ $poolID, /*int*/ $imageID) { private function add_post(/*int*/ $poolID, /*int*/ $imageID, $history=false) {
global $database; global $database;
if(!$this->check_post($poolID, $imageID)) { if(!$this->check_post($poolID, $imageID)) {
@ -843,19 +848,29 @@ class Pools extends Extension {
} }
$database->execute("UPDATE pools SET posts=(SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid) WHERE id=:pid", array("pid"=>$poolID)); $database->execute("UPDATE pools SET posts=(SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid) WHERE id=:pid", array("pid"=>$poolID));
if($history){
$count = $database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", array("pid"=>$poolID));
$this->add_history($poolID, 1, $imageID, $count);
}
} }
/* /*
* HERE WE REMOVE A SIMPLE POST FROM POOL * HERE WE REMOVE A SIMPLE POST FROM POOL
* USED WITH FOREACH IN revert_history() * USED WITH FOREACH IN revert_history() & onTagTermParse()
*/ */
private function delete_post(/*int*/ $poolID, /*int*/ $imageID) { private function delete_post(/*int*/ $poolID, /*int*/ $imageID, $history=false) {
global $database; global $database;
$database->execute("DELETE FROM pool_images WHERE pool_id = :pid AND image_id = :iid", array("pid"=>$poolID, "iid"=>$imageID)); $database->execute("DELETE FROM pool_images WHERE pool_id = :pid AND image_id = :iid", array("pid"=>$poolID, "iid"=>$imageID));
$database->execute("UPDATE pools SET posts=(SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid) WHERE id=:pid", array("pid"=>$poolID)); $database->execute("UPDATE pools SET posts=(SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid) WHERE id=:pid", array("pid"=>$poolID));
if($history){
$count = $database->get_one("SELECT COUNT(*) FROM pool_images WHERE pool_id=:pid", array("pid"=>$poolID));
$this->add_history($poolID, 0, $imageID, $count);
}
} }
} }

View File

@ -121,7 +121,9 @@ class PoolsTheme extends Themelet {
$this->sidebar_options($page, $pool, $check_all); $this->sidebar_options($page, $pool, $check_all);
} }
} }
$page->add_block(new Block(html_escape($pool['title']), html_escape($pool['description']), "main", 10));
$bb = new BBCode();
$page->add_block(new Block(html_escape($pool['title']), $bb->format($pool['description']), "main", 10));
} }
else { else {
$pool_info = ' $pool_info = '
@ -412,8 +414,15 @@ class PoolsTheme extends Themelet {
$html .= "</tbody></table>"; $html .= "</tbody></table>";
$nav_html = '
<a href="'.make_link().'">Index</a>
<br><a href="'.make_link("pool/new").'">Create Pool</a>
<br><a href="'.make_link("pool/updated").'">Pool Changes</a>
';
$page->set_title("Recent Changes"); $page->set_title("Recent Changes");
$page->set_heading("Recent Changes"); $page->set_heading("Recent Changes");
$page->add_block(new Block("Navigation", $nav_html, "left", 10));
$page->add_block(new Block("Recent Changes", $html, "main", 10)); $page->add_block(new Block("Recent Changes", $html, "main", 10));
$this->display_paginator($page, "pool/updated", null, $pageNumber, $totalPages); $this->display_paginator($page, "pool/updated", null, $pageNumber, $totalPages);

View File

@ -45,11 +45,18 @@ class RandomImage extends Extension {
$page->set_data(file_get_contents($image->get_image_filename())); $page->set_data(file_get_contents($image->get_image_filename()));
} }
} }
if($action === "view") { else if($action === "view") {
if(!is_null($image)) { if(!is_null($image)) {
send_event(new DisplayingImageEvent($image, $page)); send_event(new DisplayingImageEvent($image, $page));
} }
} }
else if($action === "widget") {
if(!is_null($image)) {
$page->set_mode("data");
$page->set_type("text/html");
$page->set_data($this->theme->build_thumb_html($image));
}
}
} }
} }

View File

@ -13,56 +13,42 @@
class RandomList extends Extension { class RandomList extends Extension {
public function onPageRequest(PageRequestEvent $event) { public function onPageRequest(PageRequestEvent $event) {
global $config, $page; global $config, $page;
if($event->page_matches("random")) {
// set vars
$page->title = "Random Images";
$images_per_page = $config->get_int("random_images_list_count", 12);
$random_images = array();
$random_html = "<b>Refresh the page to view more images</b>
<div class='shm-image-list'>";
// generate random images if($event->page_matches("random")) {
for ($i = 0; $i < $images_per_page; $i++) // set vars
array_push($random_images, Image::by_random()); $page->title = "Random Images";
$images_per_page = $config->get_int("random_images_list_count", 12);
$random_images = array();
$random_html = "<b>Refresh the page to view more images</b>
<div class='shm-image-list'>";
// create html to display images // generate random images
foreach ($random_images as $image) for ($i = 0; $i < $images_per_page; $i++)
$random_html .= $this->build_random_html($image); array_push($random_images, Image::by_random());
// display it // create html to display images
$random_html .= "</div>"; foreach ($random_images as $image)
$page->add_block(new Block("Random Images", $random_html)); $random_html .= $this->theme->build_thumb_html($image);
// display it
$random_html .= "</div>";
$page->add_block(new Block("Random Images", $random_html));
} }
} }
public function onInitExt(InitExtEvent $event) {
global $config;
$config->set_default_int("random_images_list_count", 12);
}
public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("Random Images List");
// custom headers
$sb->add_int_option("random_images_list_count",
"Amount of Random images to display ");
$event->panel->add_block($sb);
}
private function build_random_html(Image $image, $query=null) {
$i_id = int_escape($image->id);
$h_view_link = make_link("post/view/$i_id", $query);
$h_thumb_link = $image->get_thumb_link();
$h_tip = html_escape($image->get_tooltip());
$tsize = get_thumbnail_size($image->width, $image->height);
return " public function onInitExt(InitExtEvent $event) {
<a href='$h_view_link' class='thumb shm-thumb' data-post-id='$i_id'> global $config;
<img id='thumb_$i_id' height='{$tsize[1]}' width='{$tsize[0]}' class='lazy' data-original='$h_thumb_link' src='/lib/static/grey.gif'><noscript> $config->set_default_int("random_images_list_count", 12);
<img id='thumb_$i_id' height='{$tsize[1]} width='{$tsize[0]} src='$h_thumb_link'></noscript></a> }
";
public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("Random Images List");
// custom headers
$sb->add_int_option("random_images_list_count",
"Amount of Random images to display ");
$event->panel->add_block($sb);
} }
} }
?> ?>

View File

@ -0,0 +1,4 @@
<?php
/* needed for access to build_thumb_html */
class RandomListTheme extends Themelet {}
?>

View File

@ -0,0 +1,123 @@
<?php
/**
* Name: Post Relationships
* Author: Angus Johnston <admin@codeanimu.net>
* License: GPLv2
* Description: Allow posts to have relationships (parent/child).
*/
class Relationships extends Extension {
public function onInitExt(InitExtEvent $event) {
global $config, $database;
// Create the database tables
if ($config->get_int("ext_relationships_version") < 1){
$database->Execute("ALTER TABLE images ADD parent_id INT NULL, ADD INDEX (parent_id);");
$database->Execute("ALTER TABLE images ADD has_children BOOL DEFAULT FALSE NOT NULL;");
$config->set_int("ext_relationships_version", 1);
log_info("relationships", "extension installed");
}
}
public function onImageInfoSet(ImageInfoSetEvent $event) {
global $user;
if(isset($_POST['tag_edit__tags']) ? !preg_match('/parent[=|:]/', $_POST["tag_edit__tags"]) : TRUE) { //Ignore tag_edit__parent if tags contain parent metatag
if (isset($_POST["tag_edit__parent"]) ? ctype_digit($_POST["tag_edit__parent"]) : FALSE) {
$this->set_parent($event->image->id, (int) $_POST["tag_edit__parent"]);
}else{
$this->remove_parent($event->image->id);
}
}
}
public function onDisplayingImage(DisplayingImageEvent $event) {
$this->theme->relationship_info($event->image);
}
public function onSearchTermParse(SearchTermParseEvent $event) {
$matches = array();
if(preg_match("/^parent[=|:]([0-9]+|any|none)$/", $event->term, $matches)) {
$parentID = $matches[1];
if(preg_match("/^(any|none)$/", $parentID)){
$not = ($parentID == "any" ? "NOT" : "");
$event->add_querylet(new Querylet("images.parent_id IS $not NULL"));
}else{
$event->add_querylet(new Querylet("images.parent_id = :pid", array("pid"=>$parentID)));
}
}
else if(preg_match("/^child[=|:](any|none)$/", $event->term, $matches)) {
$not = ($matches[1] == "any" ? "=" : "!=");
$event->add_querylet(new Querylet("images.has_children $not TRUE"));
}
}
public function onTagTermParse(TagTermParseEvent $event) {
$matches = array();
if(preg_match("/^parent[=|:]([0-9]+|none)$/", $event->term, $matches)) {
$parentID = $matches[1];
if($parentID == "none" || $parentID == "0"){
$this->remove_parent($event->id);
}else{
$this->set_parent($event->id, $parentID);
}
}
else if(preg_match("/^child[=|:]([0-9]+)$/", $event->term, $matches)) {
$childID = $matches[1];
$this->set_child($event->id, $childID);
}
if(!empty($matches)) $event->metatag = true;
}
public function onImageInfoBoxBuilding(ImageInfoBoxBuildingEvent $event) {
$event->add_part($this->theme->get_parent_editor_html($event->image), 45);
}
public function onImageDeletion(ImageDeletionEvent $event) {
global $database;
if($event->image->has_children){
$database->execute("UPDATE images SET parent_id = NULL WHERE parent_id = :iid", array("iid"=>$event->image->id));
}
if($event->image->parent_id !== NULL){
$database->execute("UPDATE images SET has_children = (SELECT * FROM (SELECT CASE WHEN (COUNT(*) - 1) > 0 THEN 1 ELSE 0 END FROM images WHERE parent_id = :pid) AS sub)
WHERE id = :pid", array("pid"=>$event->image->parent_id));
}
}
private function set_parent(/*int*/ $imageID, /*int*/ $parentID){
global $database;
if($database->get_row("SELECT 1 FROM images WHERE id = :pid", array("pid"=>$parentID))){
$database->execute("UPDATE images SET parent_id = :pid WHERE id = :iid", array("pid"=>$parentID, "iid"=>$imageID));
$database->execute("UPDATE images SET has_children = TRUE WHERE id = :pid", array("pid"=>$parentID));
}
}
private function set_child(/*int*/ $parentID, /*int*/ $childID){
global $database;
if($database->get_row("SELECT 1 FROM images WHERE id = :cid", array("cid"=>$childID))){
$database->execute("UPDATE images SET parent_id = :pid WHERE id = :cid", array("cid"=>$childID, "pid"=>$parentID));
$database->execute("UPDATE images SET has_children = TRUE WHERE id = :pid", array("pid"=>$parentID));
}
}
private function remove_parent(/*int*/ $imageID){
global $database;
$parentID = $database->get_one("SELECT parent_id FROM images WHERE id = :iid", array("iid"=>$imageID));
if($parentID){
$database->execute("UPDATE images SET parent_id = NULL WHERE id = :iid", array("iid"=>$imageID));
$database->execute("UPDATE images SET has_children = (SELECT * FROM (SELECT CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM images WHERE parent_id = :pid) AS sub)
WHERE id = :pid", array("pid"=>$parentID));
}
}
}
?>

View File

@ -0,0 +1,15 @@
.thumb IMG {
border-width: 2px !important;
}
.shm-thumb-has_child img {
border-color: lime !important;
}
.shm-thumb-has_parent img {
border-color: #cc0 !important;
}
.shm-thumb-has_child.shm-thumb-has_parent img {
border-color: lime #cc0 #cc0 lime !important;
}

View File

@ -0,0 +1,45 @@
<?php
class RelationshipsTheme extends Themelet {
public function relationship_info($image) {
global $page, $database;
if($image->parent_id !== NULL){
$a = "<a href='".make_link("post/view/".$image->parent_id)."'>parent post</a>";
$page->add_block(new Block(null, "This post belongs to a $a.", "main", 5));
}
if($image->has_children == TRUE){
$ids = $database->get_col("SELECT id FROM images WHERE parent_id = :iid", array("iid"=>$image->id));
$html = "This post has <a href='".make_link('post/list/parent='.$image->id.'/1')."'>".(count($ids) > 1 ? "child posts" : "a child post")."</a>";
$html .= " (post ";
foreach($ids as $id){
$html .= "#<a href='".make_link('post/view/'.$id)."'>{$id}</a>, ";
}
$html = rtrim($html, ", ").").";
$page->add_block(new Block(null, $html, "main", 6));
}
}
public function get_parent_editor_html(Image $image) {
global $user;
$h_parent_id = $image->parent_id;
$s_parent_id = $h_parent_id ?: "None.";
$html = "<tr>\n".
" <th>Parent</th>\n".
" <td>\n".
(!$user->is_anonymous() ?
" <span class='view' style='overflow: hidden; white-space: nowrap;'>{$s_parent_id}</span>\n".
" <input class='edit' type='text' name='tag_edit__parent' type='number' value='{$h_parent_id}'>\n"
:
$s_parent_id
).
" <td>\n".
"</tr>\n";
return $html;
}
}
?>

View File

@ -3,6 +3,34 @@
* Name: Tag Editor * Name: Tag Editor
* Author: Shish * Author: Shish
* Description: Allow images to have tags assigned to them * Description: Allow images to have tags assigned to them
* Documentation:
* Here is a list of the tagging metatags available out of the box;
* Shimmie extensions may provide other metatags:
* <ul>
* <li>source=(*, none) eg -- using this metatag will ignore anything set in the "Source" box
* <ul>
* <li>source=http://example.com -- set source to http://example.com
* <li>source=none -- set source to NULL
* </ul>
* </ul>
* <p>Metatags can be followed by ":" rather than "=" if you prefer.
* <br />I.E: "source:http://example.com", "source=http://example.com" etc.
* <p>Some tagging metatags provided by extensions:
* <ul>
* <li>Numeric Score
* <ul>
* <li>vote=(up, down, remove) -- vote, or remove your vote on an image
* </ul>
* <li>Pools
* <ul>
* <li>pool=(PoolID, PoolTitle) -- add post to pool (if exists)
* </ul>
* <li>Post Relationships
* <ul>
* <li>parent=(parentID, none) -- set parent ID of current image
* <li>child=(childID) -- set parent ID of child image to current image ID
* </ul>
* </ul>
*/ */
/* /*
@ -72,6 +100,25 @@ class LockSetEvent extends Event {
} }
} }
/*
* TagTermParseEvent:
* Signal that a tag term needs parsing
*/
class TagTermParseEvent extends Event {
var $term = null;
var $id = null;
var $metatag = false;
public function TagTermParseEvent($term, $id) {
$this->term = $term;
$this->id = $id;
}
public function is_metatag() {
return $this->metatag;
}
}
class TagEdit extends Extension { class TagEdit extends Extension {
public function onPageRequest(PageRequestEvent $event) { public function onPageRequest(PageRequestEvent $event) {
global $user, $page; global $user, $page;
@ -112,7 +159,9 @@ class TagEdit extends Extension {
send_event(new TagSetEvent($event->image, $_POST['tag_edit__tags'])); send_event(new TagSetEvent($event->image, $_POST['tag_edit__tags']));
} }
if($this->can_source($event->image) && isset($_POST['tag_edit__source'])) { if($this->can_source($event->image) && isset($_POST['tag_edit__source'])) {
send_event(new SourceSetEvent($event->image, $_POST['tag_edit__source'])); if(isset($_POST['tag_edit__tags']) ? !preg_match('/source[=|:]/', $_POST["tag_edit__tags"]) : TRUE){
send_event(new SourceSetEvent($event->image, $_POST['tag_edit__source']));
}
} }
if($user->can("edit_image_lock")) { if($user->can("edit_image_lock")) {
$locked = isset($_POST['tag_edit__locked']) && $_POST['tag_edit__locked']=="on"; $locked = isset($_POST['tag_edit__locked']) && $_POST['tag_edit__locked']=="on";
@ -169,6 +218,16 @@ class TagEdit extends Extension {
$event->add_part($this->theme->get_lock_editor_html($event->image), 42); $event->add_part($this->theme->get_lock_editor_html($event->image), 42);
} }
public function onTagTermParse(TagTermParseEvent $event) {
$matches = array();
if(preg_match("/^source[=|:](.*)$/i", $event->term, $matches)) {
$source = ($matches[1] !== "none" ? $matches[1] : null);
send_event(new SourceSetEvent(Image::by_id($event->id), $source));
}
if(!empty($matches)) $event->metatag = true;
}
private function can_tag(Image $image) { private function can_tag(Image $image) {
global $config, $user; global $config, $user;
@ -189,6 +248,18 @@ class TagEdit extends Extension {
log_info("tag_edit", "Mass editing tags: '$search' -> '$replace'"); log_info("tag_edit", "Mass editing tags: '$search' -> '$replace'");
if(count($search_set) == 1 && count($replace_set) == 1) {
$images = Image::find_images(0, 10, $replace_set);
if(count($images) == 0) {
log_info("tag_edit", "No images found with target tag, doing in-place rename");
$database->execute("DELETE FROM tags WHERE tag=:replace",
array("replace" => $replace_set[0]));
$database->execute("UPDATE tags SET tag=:replace WHERE tag=:search",
array("replace" => $replace_set[0], "search" => $search_set[0]));
return;
}
}
$last_id = -1; $last_id = -1;
while(true) { while(true) {
// make sure we don't look at the same images twice. // make sure we don't look at the same images twice.

View File

@ -1,166 +1,111 @@
<?php <?php
/** /**
* Name: Update * Name: [Beta] Update
* Author: DakuTree <dakutree@codeanimu.net> * Author: DakuTree <dakutree@codeanimu.net>
* Link: http://www.codeanimu.net * Link: http://www.codeanimu.net
* License: GPLv2 * License: GPLv2
* Description: Shimmie updater! (Requires php-curl library and admin panel extension) * Description: Shimmie updater! (Requires admin panel extension & transload engine (cURL/fopen/Wget))
*/ */
class Update extends Extension { class Update extends Extension {
public function onInitExt(InitExtEvent $event) { public function onInitExt(InitExtEvent $event) {
global $config; global $config;
$config->set_default_string("update_guser", "shish"); $config->set_default_string("update_guserrepo", "shish/shimmie2");
$config->set_default_string("update_grepo", "shimmie2");
$config->set_default_string("commit_hash", "unknown"); $config->set_default_string("commit_hash", "unknown");
$config->set_default_string("commit_time", "unknown"); $config->set_default_string("update_time", "01/01/1970");
} }
public function onSetupBuilding(SetupBuildingEvent $event) { public function onSetupBuilding(SetupBuildingEvent $event) {
$sb = new SetupBlock("Update"); $sb = new SetupBlock("Update");
$sb->add_text_option("update_guser", "User: "); $sb->add_text_option("update_guserrepo", "User/Repo: ");
$sb->add_text_option("update_grepo", "<br>Repo: ");
$event->panel->add_block($sb); $event->panel->add_block($sb);
} }
public function onAdminBuilding(AdminBuildingEvent $event) { public function onAdminBuilding(AdminBuildingEvent $event) {
global $config, $page; global $config;
if($config->get_string('transload_engine') !== "none"){
$latestCommit = $this->get_latest_commit(); $this->theme->display_admin_block();
if(is_null($latestCommit)) return; }
$commitMessage = $latestCommit["commit"]["message"];
$commitDT = explode("T", $latestCommit["commit"]["committer"]["date"]);
$commitTD = explode("-", $commitDT[1]);
$commitDateTime = $commitDT[0]." (".$commitTD[0].")";
$commitSHA = substr($latestCommit["sha"],0,7);
$html = "".
"Current Commit: ".$config->get_string('commit_hash')." | ".$config->get_string('commit_time').
"<br>Latest Commit: ".$commitSHA." | ".$commitDateTime." | ".$commitMessage.
"<br><a href='" . make_link('update') . "'>Update</a>".
"";
$page->add_block(new Block("Software Update", $html, "main"));
} }
public function onPageRequest(PageRequestEvent $event) { public function onPageRequest(PageRequestEvent $event) {
global $config, $user; global $config, $user, $page;
if($event->page_matches("update") && $user->is_admin()) { if($user->is_admin() && isset($_GET['sha'])){
$ok = $this->update_shimmie(); if($event->page_matches("update/download")){
$ok = $this->download_shimmie();
$page->set_mode("redirect");
if($ok) $page->set_redirect(make_link("update/update", "sha=".$_GET['sha']));
else $page->set_redirect(make_link("admin")); //TODO: Show error?
}elseif($event->page_matches("update/update")){
$ok = $this->update_shimmie();
$page->set_mode("redirect");
if($ok) $page->set_redirect(make_link("admin")); //TODO: Show success?
else $page->set_redirect(make_link("admin")); //TODO: Show error?
}
} }
} }
private function get_latest_commit() { private function download_shimmie() {
global $config; global $config;
if(!function_exists("curl_init")) return null; $commitSHA = $_GET['sha'];
$g_userrepo = $config->get_string('update_guserrepo');
//Grab latest info via JSON. $url = "https://codeload.github.com/".$g_userrepo."/zip/".$commitSHA;
$g_user = $config->get_string("update_guser"); $filename = "./data/update_{$commitSHA}.zip";
$g_repo = $config->get_string("update_grepo");
$base = "https://api.github.com/repos/".$g_user."/".$g_repo."/commits"; log_info("update", "Attempting to download Shimmie commit: ".$commitSHA);
$curl = curl_init(); if($headers = transload($url, $filename)){
curl_setopt($curl, CURLOPT_URL, $base); if(($headers['Content-Type'] !== "application/zip") || ((int) $headers['Content-Length'] !== filesize($filename))){
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); unlink("./data/update_{$commitSHA}.zip");
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); log_warning("update", "Download failed: not zip / not same size as remote file.");
$content = curl_exec($curl); return false;
curl_close($curl); }
$commits = json_decode($content, true);
return $commits[0]; return true;
}
log_warning("update", "Download failed to download.");
return false;
} }
private function update_shimmie() { private function update_shimmie() {
//This is a REALLY ugly function. (Damn my limited PHP knowledge >_<)
global $config, $page; global $config, $page;
$latestCommit = $this->get_latest_commit(); $commitSHA = $_GET['sha'];
if(is_null($latestCommit)) return; $g_userrepo = $config->get_string('update_guserrepo');
$commitDT = explode("T", $latestCommit["commit"]["committer"]["date"]); log_info("update", "Download succeeded. Attempting to update Shimmie.");
$commitTD = explode("-", $commitDT[1]); $config->set_bool("in_upgrade", TRUE);
$commitDateTime = $commitDT[0]." (".$commitTD[0].")"; $ok = FALSE;
$commitSHA = substr($latestCommit["sha"],0,7);
$html = ""; /** TODO: Backup all folders (except /data, /images, /thumbs) before attempting this?
$url = "http://nodeload.github.com/".$g_user."/".$g_repo."/zipball/".$commitSHA; Either that or point to https://github.com/shish/shimmie2/blob/master/README.txt -> Upgrade from 2.3.X **/
$mfile = "master.zip";
if(glob("*-shimmie2-".$commitSHA)) { //#3
$dir = glob("*-shimmie2-".$commitSHA);
preg_match('@^([a-zA-Z0-9]+\-[0-9a-z]+\-)([^/]+)@i', $dir[0], $matches);
if(!empty($matches[2])) {
$html .= "commit: ".$matches[2];
$commit = $matches[2];
mkdir("./backup");
$html .= "<br>backup folder created!";
$d_dir = data_path("cache");
//This should empty the /data/cache/ folder.
if (is_dir($d_dir)) {
$objects = scandir($d_dir);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (filetype($d_dir."/".$object) == "dir") rmdir($d_dir."/".$object); else unlink($d_dir."/".$object);
}
}
reset($objects);
$html .= "<br>data folder emptied!";
}
copy ("./data/config/shimmie.conf.php", "./backup/shimmie.conf.php");//Although this stays the same, will keep backup just incase.
$folders = array("./core", "./lib", "./themes", "./.htaccess", "./doxygen.conf", "./index.php", "./install.php", "./ext", "./contrib");
foreach($folders as $folder){
//TODO: Check MD5 of each file, don't rename if same.
rename ($folder, "./backup".substr($folder, 1)); //Move old files to backup
rename ("./".$matches[0].substr($folder, 1), $folder); //Move new files to main
}
$html .= "<br>old shimmie setup has been moved to /backup/ (excluding images/thumbs)!";
if (is_dir($matches[0])) {
$objects = scandir($matches[0]);
foreach ($objects as $object) {
if ($object != "." && $object != "..") {
if (filetype($matches[0]."/".$object) == "dir") rmdir($matches[0]."/".$object); else unlink($matches[0]."/".$object);
}
}
reset($objects);
rmdir($matches[0]);
$html .= "<br>".$matches[0]." deleted!";
}
$html .= "<br>shimmie updated (although you may have gotten errors, it should have worked!";
$html .= "<br>due to the way shimmie loads extensions, all optional extensions have been disabled";
$config->set_string("commit_hash", $commit);
$config->set_string("commit_time", $commitDateTime);
$html .= "<br>new commit_hash has been set!";
}
else {
$html .= "Error! Folder does not exist!?"; //Although this should be impossible, shall have it anyway.
}
}
elseif (file_exists($mfile)) { //#2
$zip = new ZipArchive;
if ($zip->open($mfile) === TRUE) {
$zip->extractTo('./');
$zip->close();
$html .= "extracted!";
$html .= "<br><a href='javascript:history.go(0)'>refresh</a> the page to continue!";
unlink($mfile); //Deletes master.zip
}
else {
$html .= "failed!";
}
}
else { //#1
//Taken from the upload ext.
transload($url, $mfile);
if(file_exists($mfile)) { $zip = new ZipArchive;
$html .= "downloaded!"; if ($zip->open("./data/update_$commitSHA.zip") === TRUE) {
$html .= "<br><a href='javascript:history.go(0)'>refresh</a> the page to continue!"; for($i = 1; $i < $zip->numFiles; $i++) {
} $filename = $zip->getNameIndex($i);
else {
$html .= "download failed!"; if(substr($filename, -1) !== "/"){
$html .= "<br><a href='javascript:history.go(0)'>refresh</a> to try again!"; copy("zip://".dirname(dirname(__DIR__)).'/'."./data/update_$commitSHA.zip"."#".$filename, substr($filename, 50));
$html .= "<br>if you keep having this problem, you may have a problem with your transload engine!"; }
} }
$ok = TRUE; //TODO: Do proper checking to see if everything copied properly
}else{ log_warning("update", "Update failed to open ZIP."); }
$zip->close();
unlink("./data/update_$commitSHA.zip");
$config->set_bool("in_upgrade", FALSE);
if($ok){
$config->set_string("commit_hash", $commitSHA);
$config->set_string("update_time", date('d-m-Y'));
log_info("update", "Update succeeded?");
} }
$page->add_block(new Block("Update", $html)); return $ok;
} }
} }

14
ext/update/script.js Normal file
View File

@ -0,0 +1,14 @@
$(function() {
if($('#updatecheck').length !== 0){
$.getJSON('https://api.github.com/repos/shish/shimmie2/commits', function(data){
var c = data[0];
$('#updatecheck').html('<a href="'+c['html_url']+'">'+c['sha']+'</a>' + " ("+c['commit']['message']+")");
var params = $.param({sha: c['sha'], date: c['commit']['committer']['date']});
$('#updatelink').attr('href', function(i, val){ return val + "?" + params; });
$('#updatelink').text("Update");
}).fail(function(){
$('#updatecheck').text("Loading failed. (Github down?)");
});
}
});

14
ext/update/theme.php Normal file
View File

@ -0,0 +1,14 @@
<?php
class UpdateTheme extends Themelet {
public function display_admin_block(){
global $page, $config;
$html = "".
"<b>Current Commit</b>: ".$config->get_string('commit_hash')." | (".$config->get_string('update_time').")".
"<br><b>Latest Commit</b>: <span id='updatecheck'>Loading...</span>".
"<br><a href='" . make_link('update/download') . "' id='updatelink'></a>";
//TODO: Show warning before use.
$page->add_block(new Block("Software Update", $html, "main", 75));
}
}
?>

4
lib/jquery-1.11.0.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
.ac_results{padding:0;border:1px solid black;background-color:white;overflow:hidden;z-index:99999}.ac_results ul{width:100%;list-style-position:outside;list-style:none;padding:0;margin:0}.ac_results li{margin:0;padding:2px 5px;cursor:default;display:block;font:menu;font-size:12px;line-height:16px;overflow:hidden}.ac_loading{background:white url('indicator.gif') right center no-repeat}.ac_odd{background-color:#eee}.ac_over{background-color:#0a246a;color:white}

File diff suppressed because one or more lines are too long

7
lib/jquery.autocomplete-2.4.4.min.css vendored Normal file
View File

@ -0,0 +1,7 @@
/**
* @fileOverview CSS for jquery-autocomplete, the jQuery Autocompleter
* @author <a href="mailto:dylan@dyve.net">Dylan Verheul</a>
* @license MIT | GPL | Apache 2.0, see LICENSE.txt
* @see https://github.com/dyve/jquery-autocomplete
*/
.acResults{padding:0;border:1px solid WindowFrame;background-color:Window;overflow:hidden}.acResults ul{margin:0;padding:0;list-style-position:outside;list-style:none}.acResults ul li{margin:0;padding:2px 5px;cursor:pointer;display:block;font:menu;font-size:12px;overflow:hidden}.acLoading{background:url(indicator.gif) right center no-repeat}.acSelect{background-color:Highlight;color:HighlightText}

9
lib/jquery.autocomplete-2.4.4.min.js vendored Normal file

File diff suppressed because one or more lines are too long

8
lib/jquery.cookie-1.4.0.min.js vendored Normal file
View File

@ -0,0 +1,8 @@
/*!
* jQuery Cookie Plugin v1.4.0
* https://github.com/carhartl/jquery-cookie
*
* Copyright 2013 Klaus Hartl
* Released under the MIT license
*/
(function(e){if(typeof define==="function"&&define.amd){define(["jquery"],e)}else{e(jQuery)}})(function(e){function n(e){return u.raw?e:encodeURIComponent(e)}function r(e){return u.raw?e:decodeURIComponent(e)}function i(e){return n(u.json?JSON.stringify(e):String(e))}function s(e){if(e.indexOf('"')===0){e=e.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\")}try{e=decodeURIComponent(e.replace(t," "))}catch(n){return}try{return u.json?JSON.parse(e):e}catch(n){}}function o(t,n){var r=u.raw?t:s(t);return e.isFunction(n)?n(r):r}var t=/\+/g;var u=e.cookie=function(t,s,a){if(s!==undefined&&!e.isFunction(s)){a=e.extend({},u.defaults,a);if(typeof a.expires==="number"){var f=a.expires,l=a.expires=new Date;l.setDate(l.getDate()+f)}return document.cookie=[n(t),"=",i(s),a.expires?"; expires="+a.expires.toUTCString():"",a.path?"; path="+a.path:"",a.domain?"; domain="+a.domain:"",a.secure?"; secure":""].join("")}var c=t?undefined:{};var h=document.cookie?document.cookie.split("; "):[];for(var p=0,d=h.length;p<d;p++){var v=h[p].split("=");var m=r(v.shift());var g=v.join("=");if(t&&t===m){c=o(g,s);break}if(!t&&(g=o(g))!==undefined){c[m]=g}}return c};u.defaults={};e.removeCookie=function(t,n){if(e.cookie(t)!==undefined){e.cookie(t,"",e.extend({},n,{expires:-1}));return true}return false}});

View File

@ -1 +0,0 @@
jQuery.cookie=function(b,j,m){if(typeof j!="undefined"){m=m||{};if(j===null){j="";m=$.extend({},m);m.expires=-1}var e="";if(m.expires&&(typeof m.expires=="number"||m.expires.toUTCString)){var f;if(typeof m.expires=="number"){f=new Date();f.setTime(f.getTime()+(m.expires*24*60*60*1000))}else{f=m.expires}e="; expires="+f.toUTCString()}var l=m.path?"; path="+(m.path):"";var g=m.domain?"; domain="+(m.domain):"";var a=m.secure?"; secure":"";document.cookie=[b,"=",encodeURIComponent(j),e,l,g,a].join("")}else{var d=null;if(document.cookie&&document.cookie!=""){var k=document.cookie.split(";");for(var h=0;h<k.length;h++){var c=jQuery.trim(k[h]);if(c.substring(0,b.length+1)==(b+"=")){d=decodeURIComponent(c.substring(b.length+1));break}}}return d}};

File diff suppressed because one or more lines are too long

2
lib/jquery.imgnotes-1.0.min.css vendored Normal file
View File

@ -0,0 +1,2 @@
/** imgnotes jQuery plugin v1.0.0 **/
.notesicon{background:url(notes.png) no-repeat #fff;overflow:hidden;position:absolute;height:27px;width:22px;z-index:1000000;cursor:pointer}.note{display:none;background:url(spacer.gif);border:2px solid #fff;overflow:hidden;position:absolute;z-index:0;cursor:default}.notep{display:none;background:#eee;font-size:8pt;margin-top:0;padding:2px;position:absolute;width:175px;cursor:default}#noteform{display:none;position:absolute;width:250px}#noteform textarea{width:100%}

15
lib/jquery.imgnotes-1.0.min.js vendored Normal file
View File

@ -0,0 +1,15 @@
/**
* imgnotes jQuery plugin
* version 1.0
*
* Copyright (c) 2008 - Dr. Tarique Sani <tarique@sanisoft.com>
*
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* @URL http://www.sanisoft.com/blog/2008/05/26/img-notes-jquery-plugin/
* @Example example.html
*
**/
(function(e){function t(){e(".note").hover(function(){e(".note").show();e(this).next(".notep").show();e(this).next(".notep").css("z-index",1e4)},function(){e(".note").show();e(this).next(".notep").hide();e(this).next(".notep").css("z-index",0)})}function n(t){note_left=parseInt(imgOffset.left)+parseInt(t.x1);note_top=parseInt(imgOffset.top)+parseInt(t.y1);note_p_top=note_top+parseInt(t.height)+5;note_area_div=e("<div class='note'></div>").css({left:note_left+"px",top:note_top+"px",width:t.width+"px",height:t.height+"px"});note_text_div=e('<div class="notep" >'+t.note+"</div>").css({left:note_left+"px",top:note_p_top+"px"});e("body").append(note_area_div);e("body").append(note_text_div)}function r(t){if(true!==t){return}notes_icon_left=parseInt(imgOffset.left)+parseInt(imgWidth)-36;notes_icon_top=parseInt(imgOffset.top)+parseInt(imgHieght)-40;notes_icon_div=note_area_div=e("<div class='notesicon'></div>").css({left:notes_icon_left+"px",top:notes_icon_top+"px"});e("body").append(notes_icon_div);e(".notesicon").toggle(function(){e.fn.imgNotes.showAll()},function(){e.fn.imgNotes.hideAll()})}e.fn.imgNotes=function(i){if(undefined==s){var s}if(undefined!=i.notes){s=i.notes}if(i.url){e.ajaxSetup({async:false});e.getJSON(i.url,function(e){s=e})}image=this;imgOffset=e(image).offset();imgHieght=e(image).height();imgWidth=e(image).width();e(s).each(function(){n(this)});e(image).hover(function(){e(".note").show()},function(){e(".note").hide();e(".notep").hide()});t();r(i.isMobile);e(window).resize(function(){e(".note").remove();e(".notep").remove();e(".notesicon").remove();imgOffset=e(image).offset();imgHieght=e(image).height();imgWidth=e(image).width();e(s).each(function(){n(this)});t();r(i.isMobile)})};e.fn.imgNotes.showAll=function(){e(".note").show();e(".notep").show()};e.fn.imgNotes.hideAll=function(){e(".note").hide();e(".notep").hide()}})(jQuery);

View File

@ -1,15 +0,0 @@
/*
* Lazy Load - jQuery plugin for lazy loading images
*
* Copyright (c) 2007-2012 Mika Tuupola
*
* Licensed under the MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Project home:
* http://www.appelsiini.net/projects/lazyload
*
* Version: 1.7.2
*
*/
(function(a,b){$window=a(b),a.fn.lazyload=function(c){function f(){var b=0;d.each(function(){var c=a(this);if(e.skip_invisible&&!c.is(":visible"))return;if(!a.abovethetop(this,e)&&!a.leftofbegin(this,e))if(!a.belowthefold(this,e)&&!a.rightoffold(this,e))c.trigger("appear");else if(++b>e.failure_limit)return!1})}var d=this,e={threshold:0,failure_limit:0,event:"scroll",effect:"show",container:b,data_attribute:"original",skip_invisible:!0,appear:null,load:null};return c&&(undefined!==c.failurelimit&&(c.failure_limit=c.failurelimit,delete c.failurelimit),undefined!==c.effectspeed&&(c.effect_speed=c.effectspeed,delete c.effectspeed),a.extend(e,c)),$container=e.container===undefined||e.container===b?$window:a(e.container),0===e.event.indexOf("scroll")&&$container.bind(e.event,function(a){return f()}),this.each(function(){var b=this,c=a(b);b.loaded=!1,c.one("appear",function(){if(!this.loaded){if(e.appear){var f=d.length;e.appear.call(b,f,e)}a("<img />").bind("load",function(){c.hide().attr("src",c.data(e.data_attribute))[e.effect](e.effect_speed),b.loaded=!0;var f=a.grep(d,function(a){return!a.loaded});d=a(f);if(e.load){var g=d.length;e.load.call(b,g,e)}}).attr("src",c.data(e.data_attribute))}}),0!==e.event.indexOf("scroll")&&c.bind(e.event,function(a){b.loaded||c.trigger("appear")})}),$window.bind("resize",function(a){f()}),f(),this},a.belowthefold=function(c,d){var e;return d.container===undefined||d.container===b?e=$window.height()+$window.scrollTop():e=$container.offset().top+$container.height(),e<=a(c).offset().top-d.threshold},a.rightoffold=function(c,d){var e;return d.container===undefined||d.container===b?e=$window.width()+$window.scrollLeft():e=$container.offset().left+$container.width(),e<=a(c).offset().left-d.threshold},a.abovethetop=function(c,d){var e;return d.container===undefined||d.container===b?e=$window.scrollTop():e=$container.offset().top,e>=a(c).offset().top+d.threshold+a(c).height()},a.leftofbegin=function(c,d){var e;return d.container===undefined||d.container===b?e=$window.scrollLeft():e=$container.offset().left,e>=a(c).offset().left+d.threshold+a(c).width()},a.inviewport=function(b,c){return!a.rightofscreen(b,c)&&!a.leftofscreen(b,c)&&!a.belowthefold(b,c)&&!a.abovethetop(b,c)},a.extend(a.expr[":"],{"below-the-fold":function(c){return a.belowthefold(c,{threshold:0,container:b})},"above-the-top":function(c){return!a.belowthefold(c,{threshold:0,container:b})},"right-of-screen":function(c){return a.rightoffold(c,{threshold:0,container:b})},"left-of-screen":function(c){return!a.rightoffold(c,{threshold:0,container:b})},"in-viewport":function(c){return!a.inviewport(c,{threshold:0,container:b})},"above-the-fold":function(c){return!a.belowthefold(c,{threshold:0,container:b})},"right-of-fold":function(c){return a.rightoffold(c,{threshold:0,container:b})},"left-of-fold":function(c){return!a.rightoffold(c,{threshold:0,container:b})}})})(jQuery,window);

View File

@ -1,386 +0,0 @@
/*
* imgAreaSelect jQuery plugin
* version 0.4
*
* Copyright (c) 2008 Michal Wojciechowski (odyniec.net)
*
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://odyniec.net/projects/imgareaselect/
*
*/
jQuery.imgAreaSelect = function (img, options) {
var $area = jQuery('<div></div>'),
$border1 = jQuery('<div></div>'),
$border2 = jQuery('<div></div>'),
$outLeft = jQuery('<div></div>'),
$outTop = jQuery('<div></div>'),
$outRight = jQuery('<div></div>'),
$outBottom = jQuery('<div></div>'),
imgOfs, imgWidth, imgHeight,
zIndex = 0, fixed = false,
startX, startY, moveX, moveY,
resizeMargin = 10, resize = [ ], V = 0, H = 1,
d, aspectRatio,
x1, x2, y1, y2, x, y,
selection = { x1: 0, y1: 0, x2: 0, y2: 0, width: 0, height: 0 };
var $a = $area.add($border1).add($border2);
var $o = $outLeft.add($outTop).add($outRight).add($outBottom);
function getZIndex()
{
var $p = jQuery(img);
while ($p.length && !$p.is('body')) {
if (!isNaN($p.css('z-index')) && $p.css('z-index') > zIndex)
zIndex = $p.css('z-index');
if ($p.css('position') == 'fixed') fixed = true;
$p = $p.parent();
}
}
function areaMouseMove(event)
{
x = event.pageX - selection.x1 - imgOfs.left;
y = event.pageY - selection.y1 - imgOfs.top;
resize = [ ];
if (options.resizable) {
if (y <= resizeMargin)
resize[V] = 'n';
else if (y >= selection.height - resizeMargin)
resize[V] = 's';
if (x <= resizeMargin)
resize[H] = 'w';
else if (x >= selection.width - resizeMargin)
resize[H] = 'e';
}
$border2.css('cursor', resize.length ? resize.join('') + '-resize' :
options.movable ? 'move' : '');
}
function areaMouseDown(event)
{
if (event.which != 1) return false;
if (options.resizable && resize.length > 0) {
jQuery('body').css('cursor', resize.join('') + '-resize');
x1 = (resize[H] == 'w' ? selection.x2 : selection.x1) + imgOfs.left;
y1 = (resize[V] == 'n' ? selection.y2 : selection.y1) + imgOfs.top;
jQuery(document).mousemove(selectingMouseMove);
$border2.unbind('mousemove', areaMouseMove);
jQuery(document).one('mouseup', function () {
resize = [ ];
jQuery('body').css('cursor', '');
if (options.autoHide)
$a.hide();
options.onSelectEnd(img, selection);
jQuery(document).unbind('mousemove', selectingMouseMove);
$border2.mousemove(areaMouseMove);
});
}
else if (options.movable) {
moveX = selection.x1 + imgOfs.left;
moveY = selection.y1 + imgOfs.top;
startX = event.pageX;
startY = event.pageY;
jQuery(document)
.mousemove(movingMouseMove)
.one('mouseup', function () {
options.onSelectEnd(img, selection);
jQuery(document).unbind('mousemove', movingMouseMove);
});
}
else
jQuery(img).mousedown(event);
return false;
}
function aspectRatioXY()
{
x2 = Math.max(imgOfs.left, Math.min(imgOfs.left + imgWidth,
x1 + Math.abs(y2 - y1) * aspectRatio * (x2 > x1 ? 1 : -1)));
y2 = Math.round(Math.max(imgOfs.top, Math.min(imgOfs.top + imgHeight,
y1 + Math.abs(x2 - x1) / aspectRatio * (y2 > y1 ? 1 : -1))));
x2 = Math.round(x2);
}
function aspectRatioYX()
{
y2 = Math.max(imgOfs.top, Math.min(imgOfs.top + imgHeight,
y1 + Math.abs(x2 - x1) / aspectRatio * (y2 > y1 ? 1 : -1)));
x2 = Math.round(Math.max(imgOfs.left, Math.min(imgOfs.left + imgWidth,
x1 + Math.abs(y2 - y1) * aspectRatio * (x2 > x1 ? 1 : -1))));
y2 = Math.round(y2);
}
function selectingMouseMove(event)
{
x2 = !resize.length || resize[H] || aspectRatio ? event.pageX : selection.x2 + imgOfs.left;
y2 = !resize.length || resize[V] || aspectRatio ? event.pageY : selection.y2 + imgOfs.top;
if (options.minWidth && Math.abs(x2 - x1) < options.minWidth) {
x2 = x1 - options.minWidth * (x2 < x1 ? 1 : -1);
if (x2 < imgOfs.left)
x1 = imgOfs.left + options.minWidth;
else if (x2 > imgOfs.left + imgWidth)
x1 = imgOfs.left + imgWidth - options.minWidth;
}
if (options.minHeight && Math.abs(y2 - y1) < options.minHeight) {
y2 = y1 - options.minHeight * (y2 < y1 ? 1 : -1);
if (y2 < imgOfs.top)
y1 = imgOfs.top + options.minHeight;
else if (y2 > imgOfs.top + imgHeight)
y1 = imgOfs.top + imgHeight - options.minHeight;
}
x2 = Math.max(imgOfs.left, Math.min(x2, imgOfs.left + imgWidth));
y2 = Math.max(imgOfs.top, Math.min(y2, imgOfs.top + imgHeight));
if (aspectRatio)
if (Math.abs(x2 - x1) / aspectRatio > Math.abs(y2 - y1))
aspectRatioYX();
else
aspectRatioXY();
if (options.maxWidth && Math.abs(x2 - x1) > options.maxWidth) {
x2 = x1 - options.maxWidth * (x2 < x1 ? 1 : -1);
if (aspectRatio) aspectRatioYX();
}
if (options.maxHeight && Math.abs(y2 - y1) > options.maxHeight) {
y2 = y1 - options.maxHeight * (y2 < y1 ? 1 : -1);
if (aspectRatio) aspectRatioXY();
}
selection.x1 = Math.min(x1, x2) - imgOfs.left;
selection.x2 = Math.max(x1, x2) - imgOfs.left;
selection.y1 = Math.min(y1, y2) - imgOfs.top;
selection.y2 = Math.max(y1, y2) - imgOfs.top;
selection.width = Math.abs(x2 - x1);
selection.height = Math.abs(y2 - y1);
$a.css({
left: (selection.x1 + imgOfs.left) + 'px',
top: (selection.y1 + imgOfs.top) + 'px',
width: Math.max(selection.width - options.borderWidth * 2, 0) + 'px',
height: Math.max(selection.height - options.borderWidth * 2, 0) + 'px'
});
$outLeft.css({ width: selection.x1 + 'px' });
$outTop.css({ left: imgOfs.left + selection.x1 + 'px', width: selection.width + 'px',
height: selection.y1 + 'px' });
$outRight.css({ left: imgOfs.left + selection.x2 + 'px', width: imgWidth - selection.x2 + 'px' });
$outBottom.css({ left: imgOfs.left + selection.x1 + 'px', top: imgOfs.top + selection.y2 + 'px',
width: selection.width + 'px', height: imgHeight - selection.y2 + 'px' });
options.onSelectChange(img, selection);
return false;
}
function movingMouseMove(event)
{
x1 = Math.max(imgOfs.left, Math.min(moveX + event.pageX - startX,
imgOfs.left + imgWidth - selection.width));
y1 = Math.max(imgOfs.top, Math.min(moveY + event.pageY - startY,
imgOfs.top + imgHeight - selection.height));
x2 = x1 + selection.width;
y2 = y1 + selection.height;
selection.x1 = x1 - imgOfs.left;
selection.y1 = y1 - imgOfs.top;
selection.x2 = x2 - imgOfs.left;
selection.y2 = y2 - imgOfs.top;
$a.css({
left: x1 + 'px',
top: y1 + 'px',
width: Math.max(x2 - x1 - options.borderWidth * 2, 0) + 'px',
height: Math.max(y2 - y1 - options.borderWidth * 2, 0) + 'px'
});
$outLeft.css({ width: selection.x1 + 'px' });
$outTop.css({ left: imgOfs.left + selection.x1 + 'px', width: selection.width + 'px',
height: selection.y1 + 'px' });
$outRight.css({ left: imgOfs.left + selection.x2 + 'px', width: imgWidth - selection.x2 + 'px' });
$outBottom.css({ left: imgOfs.left + selection.x1 + 'px', top: imgOfs.top + selection.y2 + 'px',
width: selection.width + 'px', height: imgHeight - selection.y2 + 'px' });
options.onSelectChange(img, selection);
event.preventDefault();
return false;
}
function imgMouseDown(event)
{
if (event.which != 1) return false;
startX = x1 = event.pageX;
startY = y1 = event.pageY;
resize = [ ];
$a.css({ width: '0px', height: '0px', left: x1, top: y1 });
$outLeft.css({ width: x1 - imgOfs.left + 'px' });
$outTop.css({ left: x1 + 'px', height: y1 - imgOfs.top + 'px', width: '0px' });
$outRight.css({ left: x1 + 'px', width: imgOfs.left + imgWidth - x1 + 'px' });
$outBottom.css({ left: x1 + 'px', top: y1 + 'px', width: '0px', height: imgOfs.top + imgHeight - y1 + 'px' });
$a.add($o).show();
jQuery(document).mousemove(selectingMouseMove);
$border2.unbind('mousemove', areaMouseMove);
selection.x1 = selection.x2 = x1 - imgOfs.left;
selection.y1 = selection.y2 = y1 - imgOfs.top;
options.onSelectStart(img, selection);
jQuery(document).one('mouseup', function () {
if (options.autoHide)
$a.add($o).hide();
options.onSelectEnd(img, selection);
jQuery(document).unbind('mousemove', selectingMouseMove);
$border2.mousemove(areaMouseMove);
});
return false;
}
this.setOptions = function(newOptions)
{
options = jQuery.extend(options, newOptions);
if (newOptions.x1 != null) {
x1 = (selection.x1 = newOptions.x1) + imgOfs.left;
y1 = (selection.y1 = newOptions.y1) + imgOfs.top;
x2 = (selection.x2 = newOptions.x2) + imgOfs.left;
y2 = (selection.y2 = newOptions.y2) + imgOfs.top;
selection.width = x2 - x1;
selection.height = y2 - y1;
$a.css({
left: x1 + 'px',
top: y1 + 'px',
width: Math.max(x2 - x1 - options.borderWidth * 2, 0) + 'px',
height: Math.max(y2 - y1 - options.borderWidth * 2, 0) + 'px'
});
$outLeft.css({ width: selection.x1 + 'px' });
$outTop.css({ left: x1 + 'px', width: selection.width + 'px', height: selection.y1 + 'px' });
$outRight.css({ left: x2 + 'px', width: (imgWidth - selection.x2) + 'px' });
$outBottom.css({ left: x1 + 'px', top: y2 + 'px', width: selection.width + 'px', height: (imgHeight - selection.y2) + 'px' });
$a.add($o).show();
options.onSelectChange(img, selection);
}
if (newOptions.hide) {
$a.hide();
$outLeft.hide();
$outRight.hide();
$outTop.hide();
$outBottom.hide();
} else if (newOptions.show) {
$a.show();
$outLeft.hide();
$outRight.hide();
$outTop.hide();
$outBottom.hide();
}
$a.css({ borderWidth: options.borderWidth + 'px' });
$area.css({ backgroundColor: options.selectionColor, opacity: options.selectionOpacity });
$border1.css({ borderStyle: 'solid', borderColor: options.borderColor1 });
$border2.css({ borderStyle: 'dashed', borderColor: options.borderColor2 });
$o.css({ opacity: options.outerOpacity, backgroundColor: options.outerColor });
aspectRatio = options.aspectRatio && (d = options.aspectRatio.split(/:/)) ?
d[0] / d[1] : null;
if (options.disable || options.enable === false) {
$a.unbind('mousemove', areaMouseMove).unbind('mousedown', areaMouseDown);
jQuery(img).add($o).unbind('mousedown', imgMouseDown);
}
else if (options.enable || options.disable === false) {
if (options.resizable || options.movable)
$a.mousemove(areaMouseMove).mousedown(areaMouseDown);
//jQuery(img).add($o).mousedown(imgMouseDown);
}
options.enable = options.disable = undefined;
};
imgWidth = jQuery(img).width();
imgHeight = jQuery(img).height();
imgOfs = jQuery(img).offset();
if (jQuery.browser.msie)
jQuery(img).attr('unselectable', 'on');
getZIndex();
$a.add($o).css({ display: 'none', position: fixed ? 'fixed' : 'absolute', overflow: 'hidden', zIndex: zIndex });
$area.css({ borderStyle: 'solid' });
$outLeft.css({ left: imgOfs.left + 'px', top: imgOfs.top + 'px', height: imgHeight + 'px' });
$outTop.css({ top: imgOfs.top + 'px' });
$outRight.css({ top: imgOfs.top + 'px', height: imgHeight + 'px' });
jQuery('body').append($o);
jQuery('body').append($a);
initOptions = {
borderColor1: '#000',
borderColor2: '#fff',
borderWidth: 1,
movable: true,
resizable: true,
selectionColor: '#fff',
selectionOpacity: 0.2,
outerColor: '#000',
outerOpacity: 0.2,
onSelectStart: function () {},
onSelectChange: function () {},
onSelectEnd: function () {}
};
options = jQuery.extend(initOptions, options);
this.setOptions(options);
};
jQuery.fn.imgAreaSelect = function (options) {
options = options || {};
this.each(function () {
if (jQuery(this).data('imgAreaSelect')){
jQuery(this).data('imgAreaSelect').setOptions(options);
} else {
if (options.enable === undefined && options.disable === undefined)
options.enable = true;
jQuery(this).data('imgAreaSelect', new jQuery.imgAreaSelect(this, options));
}
});
return this;
};

View File

@ -1,91 +0,0 @@
/**
* imgnotes jQuery plugin
* version 0.1
*
* Copyright (c) 2008 Dr. Tarique Sani <tarique@sanisoft.com>
*
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* @URL http://www.sanisoft.com/blog/2008/05/26/img-notes-jquery-plugin/
* @Example example.html
*
**/
//Wrap in a closure
(function($) {
$.fn.imgNotes = function(n) {
if(undefined != n){
notes = n;
}
image = this;
imgOffset = $(image).offset();
$(notes).each(function(){
appendnote(this);
});
$(image).hover(
function(){
$('.note').show();
},
function(){
$('.note').hide();
}
);
addnoteevents();
$(window).resize(function () {
$('.note').remove();
imgOffset = $(image).offset();
$(notes).each(function(){
appendnote(this);
});
addnoteevents();
});
}
function addnoteevents() {
$('.note').hover(
function(){
$('.note').show();
$(this).next('.notep').show();
$(this).next('.notep').css("z-index", 10000);
},
function(){
$('.note').show();
$(this).next('.notep').hide();
$(this).next('.notep').css("z-index", 0);
}
);
}
function appendnote(note_data){
note_left = parseInt(imgOffset.left) + parseInt(note_data.x1);
note_top = parseInt(imgOffset.top) + parseInt(note_data.y1);
note_p_top = note_top + parseInt(note_data.height)+5;
note_area_div = $("<div class='note'></div>").css({ left: note_left + 'px', top: note_top + 'px', width: note_data.width + 'px', height: note_data.height + 'px' });
note_text_div = $('<div class="notep" >'+ note_data.note.replace(/([^>]?)\n/g, '$1<br />\n') + '</div>').css({ left: note_left + 'px', top: note_p_top + 'px'});
//added by alpha
note_id_div = $('<div class="noteID" >'+note_data.note_id+'</div>').css({ left: note_left + 'px', top: note_p_top + 'px'}).hide();
$('body').append(note_area_div);
$('body').append(note_text_div);
//added by alpha
$('body').append(note_id_div);
}
// End the closure
})(jQuery);

2
lib/jquery.tablesorter-2.0.5.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,189 +0,0 @@
/**
* Timeago is a jQuery plugin that makes it easy to support automatically
* updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
*
* @name timeago
* @version 1.1.0
* @requires jQuery v1.2.3+
* @author Ryan McGeary
* @license MIT License - http://www.opensource.org/licenses/mit-license.php
*
* For usage and examples, visit:
* http://timeago.yarp.com/
*
* Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define(['jquery'], factory);
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
$.timeago = function(timestamp) {
if (timestamp instanceof Date) {
return inWords(timestamp);
} else if (typeof timestamp === "string") {
return inWords($.timeago.parse(timestamp));
} else if (typeof timestamp === "number") {
return inWords(new Date(timestamp));
} else {
return inWords($.timeago.datetime(timestamp));
}
};
var $t = $.timeago;
$.extend($.timeago, {
settings: {
refreshMillis: 60000,
allowFuture: false,
localeTitle: false,
cutoff: 0,
strings: {
prefixAgo: null,
prefixFromNow: null,
suffixAgo: "ago",
suffixFromNow: "from now",
seconds: "less than a minute",
minute: "about a minute",
minutes: "%d minutes",
hour: "about an hour",
hours: "about %d hours",
day: "a day",
days: "%d days",
month: "about a month",
months: "%d months",
year: "about a year",
years: "%d years",
wordSeparator: " ",
numbers: []
}
},
inWords: function(distanceMillis) {
var $l = this.settings.strings;
var prefix = $l.prefixAgo;
var suffix = $l.suffixAgo;
if (this.settings.allowFuture) {
if (distanceMillis < 0) {
prefix = $l.prefixFromNow;
suffix = $l.suffixFromNow;
}
}
var seconds = Math.abs(distanceMillis) / 1000;
var minutes = seconds / 60;
var hours = minutes / 60;
var days = hours / 24;
var years = days / 365;
function substitute(stringOrFunction, number) {
var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
var value = ($l.numbers && $l.numbers[number]) || number;
return string.replace(/%d/i, value);
}
var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
seconds < 90 && substitute($l.minute, 1) ||
minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
minutes < 90 && substitute($l.hour, 1) ||
hours < 24 && substitute($l.hours, Math.round(hours)) ||
hours < 42 && substitute($l.day, 1) ||
days < 30 && substitute($l.days, Math.round(days)) ||
days < 45 && substitute($l.month, 1) ||
days < 365 && substitute($l.months, Math.round(days / 30)) ||
years < 1.5 && substitute($l.year, 1) ||
substitute($l.years, Math.round(years));
var separator = $l.wordSeparator || "";
if ($l.wordSeparator === undefined) { separator = " "; }
return $.trim([prefix, words, suffix].join(separator));
},
parse: function(iso8601) {
var s = $.trim(iso8601);
s = s.replace(/\.\d+/,""); // remove milliseconds
s = s.replace(/-/,"/").replace(/-/,"/");
s = s.replace(/T/," ").replace(/Z/," UTC");
s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
return new Date(s);
},
datetime: function(elem) {
var iso8601 = $t.isTime(elem) ? $(elem).attr("datetime") : $(elem).attr("title");
return $t.parse(iso8601);
},
isTime: function(elem) {
// jQuery's `is()` doesn't play well with HTML5 in IE
return $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
}
});
// functions that can be called via $(el).timeago('action')
// init is default when no action is given
// functions are called with context of a single element
var functions = {
init: function(){
var refresh_el = $.proxy(refresh, this);
refresh_el();
var $s = $t.settings;
if ($s.refreshMillis > 0) {
setInterval(refresh_el, $s.refreshMillis);
}
},
update: function(time){
$(this).data('timeago', { datetime: $t.parse(time) });
refresh.apply(this);
}
};
$.fn.timeago = function(action, options) {
var fn = action ? functions[action] : functions.init;
if(!fn){
throw new Error("Unknown function name '"+ action +"' for timeago");
}
// each over objects here and call the requested function
this.each(function(){
fn.call(this, options);
});
return this;
};
function refresh() {
var data = prepareData(this);
var $s = $t.settings;
if (!isNaN(data.datetime)) {
if ( $s.cutoff == 0 || distance(data.datetime) < $s.cutoff) {
$(this).text(inWords(data.datetime));
}
}
return this;
}
function prepareData(element) {
element = $(element);
if (!element.data("timeago")) {
element.data("timeago", { datetime: $t.datetime(element) });
var text = $.trim(element.text());
if ($t.settings.localeTitle) {
element.attr("title", element.data('timeago').datetime.toLocaleString());
} else if (text.length > 0 && !($t.isTime(element) && element.attr("title"))) {
element.attr("title", text);
}
}
return element.data("timeago");
}
function inWords(date) {
return $t.inWords(distance(date));
}
function distance(date) {
return (new Date().getTime() - date.getTime());
}
// fix for IE6 suckage
document.createElement("abbr");
document.createElement("time");
}));

17
lib/jquery.timeago-1.3.1.min.js vendored Normal file
View File

@ -0,0 +1,17 @@
/**
* Timeago is a jQuery plugin that makes it easy to support automatically
* updating fuzzy timestamps (e.g. "4 minutes ago" or "about 1 day ago").
*
* @name timeago
* @version 1.3.1
* @requires jQuery v1.2.3+
* @author Ryan McGeary
* @license MIT License - http://www.opensource.org/licenses/mit-license.php
*
* For usage and examples, visit:
* http://timeago.yarp.com/
*
* Copyright (c) 2008-2013, Ryan McGeary (ryan -[at]- mcgeary [*dot*] org)
*/
(function(e){if(typeof define==="function"&&define.amd){define(["jquery"],e)}else{e(jQuery)}})(function(e){function r(){var n=i(this);var r=t.settings;if(!isNaN(n.datetime)){if(r.cutoff==0||o(n.datetime)<r.cutoff){e(this).text(s(n.datetime))}}return this}function i(n){n=e(n);if(!n.data("timeago")){n.data("timeago",{datetime:t.datetime(n)});var r=e.trim(n.text());if(t.settings.localeTitle){n.attr("title",n.data("timeago").datetime.toLocaleString())}else if(r.length>0&&!(t.isTime(n)&&n.attr("title"))){n.attr("title",r)}}return n.data("timeago")}function s(e){return t.inWords(o(e))}function o(e){return(new Date).getTime()-e.getTime()}e.timeago=function(t){if(t instanceof Date){return s(t)}else if(typeof t==="string"){return s(e.timeago.parse(t))}else if(typeof t==="number"){return s(new Date(t))}else{return s(e.timeago.datetime(t))}};var t=e.timeago;e.extend(e.timeago,{settings:{refreshMillis:6e4,allowFuture:false,localeTitle:false,cutoff:0,strings:{prefixAgo:null,prefixFromNow:null,suffixAgo:"ago",suffixFromNow:"from now",seconds:"less than a minute",minute:"about a minute",minutes:"%d minutes",hour:"about an hour",hours:"about %d hours",day:"a day",days:"%d days",month:"about a month",months:"%d months",year:"about a year",years:"%d years",wordSeparator:" ",numbers:[]}},inWords:function(t){function l(r,i){var s=e.isFunction(r)?r(i,t):r;var o=n.numbers&&n.numbers[i]||i;return s.replace(/%d/i,o)}var n=this.settings.strings;var r=n.prefixAgo;var i=n.suffixAgo;if(this.settings.allowFuture){if(t<0){r=n.prefixFromNow;i=n.suffixFromNow}}var s=Math.abs(t)/1e3;var o=s/60;var u=o/60;var a=u/24;var f=a/365;var c=s<45&&l(n.seconds,Math.round(s))||s<90&&l(n.minute,1)||o<45&&l(n.minutes,Math.round(o))||o<90&&l(n.hour,1)||u<24&&l(n.hours,Math.round(u))||u<42&&l(n.day,1)||a<30&&l(n.days,Math.round(a))||a<45&&l(n.month,1)||a<365&&l(n.months,Math.round(a/30))||f<1.5&&l(n.year,1)||l(n.years,Math.round(f));var h=n.wordSeparator||"";if(n.wordSeparator===undefined){h=" "}return e.trim([r,c,i].join(h))},parse:function(t){var n=e.trim(t);n=n.replace(/\.\d+/,"");n=n.replace(/-/,"/").replace(/-/,"/");n=n.replace(/T/," ").replace(/Z/," UTC");n=n.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2");return new Date(n)},datetime:function(n){var r=t.isTime(n)?e(n).attr("datetime"):e(n).attr("title");return t.parse(r)},isTime:function(t){return e(t).get(0).tagName.toLowerCase()==="time"}});var n={init:function(){var n=e.proxy(r,this);n();var i=t.settings;if(i.refreshMillis>0){setInterval(n,i.refreshMillis)}},update:function(n){e(this).data("timeago",{datetime:t.parse(n)});r.apply(this)}};e.fn.timeago=function(e,t){var r=e?n[e]:n.init;if(!r){throw new Error("Unknown function name '"+e+"' for timeago")}this.each(function(){r.call(this,t)});return this};document.createElement("abbr");document.createElement("time")})

File diff suppressed because one or more lines are too long

4
lib/modernizr-2.7.1.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,8 @@ $(document).ready(function() {
jQuery.timeago.settings.cutoff = 365 * dayMS; jQuery.timeago.settings.cutoff = 365 * dayMS;
$("time").timeago(); $("time").timeago();
//TODO: Possibly move to using TextExtJS for autocomplete? - http://textextjs.com/
// Also use autocomplete in tag box?
$('.autocomplete_tags').autocomplete(base_href + '/api/internal/tag_list/complete', { $('.autocomplete_tags').autocomplete(base_href + '/api/internal/tag_list/complete', {
width: 320, width: 320,
max: 15, max: 15,
@ -13,12 +15,10 @@ $(document).ready(function() {
multipleSeparator: ' ', multipleSeparator: ' ',
scroll: true, scroll: true,
scrollHeight: 300, scrollHeight: 300,
selectFirst: false selectFirst: false,
}); queryParamName: 's',
delay: 150,
$("IMG.lazy").show().lazyload({ minChars: 1
//effect: "fadeIn",
threshold: 200
}); });
$("TABLE.sortable").tablesorter(); $("TABLE.sortable").tablesorter();

BIN
lib/spacer.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 B

View File

@ -1,26 +1,5 @@
<?php <?php
class Themelet extends BaseThemelet { class Themelet extends BaseThemelet {
public function build_thumb_html(Image $image) {
global $config;
$h_view_link = make_link("post/view/{$image->id}");
$h_thumb_link = $image->get_thumb_link();
$h_tip = html_escape($image->get_tooltip());
$i_id = int_escape($image->id);
$h_tags = strtolower($image->get_tag_list());
// If file is flash or svg then sets thumbnail to max size.
if($image->ext == 'swf' || $image->ext == 'svg') {
$tsize = get_thumbnail_size($config->get_int('thumb_width'), $config->get_int('thumb_height'));
}
else{
$tsize = get_thumbnail_size($image->width, $image->height);
}
return "<a href='$h_view_link' class='shm-thumb shm-thumb-link' data-tags='$h_tags' data-post-id='$i_id'><img title='$h_tip' alt='$h_tip' ".
"width='{$tsize[0]}' height='{$tsize[1]}' src='$h_thumb_link' /></a>";
}
public function display_paginator(Page $page, $base, $query, $page_number, $total_pages) { public function display_paginator(Page $page, $base, $query, $page_number, $total_pages) {
if($total_pages == 0) $total_pages = 1; if($total_pages == 0) $total_pages = 1;
$body = $this->build_paginator($page_number, $total_pages, $base, $query); $body = $this->build_paginator($page_number, $total_pages, $base, $query);
@ -42,7 +21,7 @@ class Themelet extends BaseThemelet {
private function build_paginator($current_page, $total_pages, $base_url, $query) { private function build_paginator($current_page, $total_pages, $base_url, $query) {
$next = $current_page + 1; $next = $current_page + 1;
$prev = $current_page - 1; $prev = $current_page - 1;
$rand = rand(1, $total_pages); $rand = mt_rand(1, $total_pages);
$at_start = ($current_page <= 3 || $total_pages <= 3); $at_start = ($current_page <= 3 || $total_pages <= 3);
$at_end = ($current_page >= $total_pages -2); $at_end = ($current_page >= $total_pages -2);

View File

@ -1,26 +1,5 @@
<?php <?php
class Themelet extends BaseThemelet { class Themelet extends BaseThemelet {
public function build_thumb_html(Image $image) {
global $config;
$h_view_link = make_link("post/view/{$image->id}");
$h_thumb_link = $image->get_thumb_link();
$h_tip = html_escape($image->get_tooltip());
$i_id = int_escape($image->id);
$h_tags = strtolower($image->get_tag_list());
// If file is flash or svg then sets thumbnail to max size.
if($image->ext == 'swf' || $image->ext == 'svg') {
$tsize = get_thumbnail_size($config->get_int('thumb_width'), $config->get_int('thumb_height'));
}
else{
$tsize = get_thumbnail_size($image->width, $image->height);
}
return "<a href='$h_view_link' class='shm-thumb shm-thumb-link' data-tags='$h_tags' data-post-id='$i_id'><img title='$h_tip' alt='$h_tip' ".
"width='{$tsize[0]}' height='{$tsize[1]}' src='$h_thumb_link' /></a>";
}
public function display_paginator(Page $page, $base, $query, $page_number, $total_pages) { public function display_paginator(Page $page, $base, $query, $page_number, $total_pages) {
if($total_pages == 0) $total_pages = 1; if($total_pages == 0) $total_pages = 1;
$body = $this->build_paginator($page_number, $total_pages, $base, $query); $body = $this->build_paginator($page_number, $total_pages, $base, $query);
@ -42,7 +21,7 @@ class Themelet extends BaseThemelet {
private function build_paginator($current_page, $total_pages, $base_url, $query) { private function build_paginator($current_page, $total_pages, $base_url, $query) {
$next = $current_page + 1; $next = $current_page + 1;
$prev = $current_page - 1; $prev = $current_page - 1;
$rand = rand(1, $total_pages); $rand = mt_rand(1, $total_pages);
$at_start = ($current_page <= 3 || $total_pages <= 3); $at_start = ($current_page <= 3 || $total_pages <= 3);
$at_end = ($current_page >= $total_pages -2); $at_end = ($current_page >= $total_pages -2);

View File

@ -1,30 +1,5 @@
<?php <?php
class Themelet extends BaseThemelet { class Themelet extends BaseThemelet {
/**
* Generic thumbnail code; returns HTML rather than adding
* a block since thumbs tend to go inside blocks...
*/
public function build_thumb_html(Image $image) {
global $config;
$h_view_link = make_link("post/view/{$image->id}");
$h_thumb_link = $image->get_thumb_link();
$h_tip = html_escape($image->get_tooltip());
$i_id = int_escape($image->id);
$h_tags = strtolower($image->get_tag_list());
// If file is flash or svg then sets thumbnail to max size.
if($image->ext == 'swf' || $image->ext == 'svg') {
$tsize = get_thumbnail_size($config->get_int('thumb_width'), $config->get_int('thumb_height'));
}
else {
$tsize = get_thumbnail_size($image->width, $image->height);
}
return "<a href='$h_view_link' class='thumb shm-thumb shm-thumb-link' data-tags='$h_tags' data-post-id='$i_id'><img title='$h_tip' alt='$h_tip' ".
"width='{$tsize[0]}' height='{$tsize[1]}' src='$h_thumb_link' /></a>";
}
/** /**
* Add a generic paginator * Add a generic paginator
*/ */
@ -50,7 +25,7 @@ class Themelet extends BaseThemelet {
private function build_paginator($current_page, $total_pages, $base_url, $query) { private function build_paginator($current_page, $total_pages, $base_url, $query) {
$next = $current_page + 1; $next = $current_page + 1;
$prev = $current_page - 1; $prev = $current_page - 1;
$rand = rand(1, $total_pages); $rand = mt_rand(1, $total_pages);
$at_start = ($current_page <= 1 || $total_pages <= 1); $at_start = ($current_page <= 1 || $total_pages <= 1);
$at_end = ($current_page >= $total_pages); $at_end = ($current_page >= $total_pages);

View File

@ -1,34 +1,5 @@
<?php <?php
class Themelet extends BaseThemelet { class Themelet extends BaseThemelet {
/**
* Generic thumbnail code; returns HTML rather than adding
* a block since thumbs tend to go inside blocks...
*/
public function build_thumb_html(Image $image) {
global $config;
$i_id = (int) $image->id;
$h_view_link = make_link('post/view/'.$i_id);
$h_thumb_link = $image->get_thumb_link();
$h_tip = html_escape($image->get_tooltip());
$h_tags = strtolower($image->get_tag_list());
$base = get_base_href();
// If file is flash or svg then sets thumbnail to max size.
if($image->ext === 'swf' || $image->ext === 'svg'){
$tsize = get_thumbnail_size($config->get_int('thumb_width'), $config->get_int('thumb_height'));
}
else{
$tsize = get_thumbnail_size($image->width, $image->height);
}
return '<center class="shm-thumb" data-tags="'.$h_tags.'" data-post-id="'.$i_id.'"><div class="thumbblock">'.
'<a href="'.$h_view_link.'" class="thumb shm-thumb-link">'.
'<img id="thumb_'.$i_id.'" title="'.$h_tip.'" alt="'.$h_tip.'" height="'.$tsize[1].'" width="'.$tsize[0].'" class="lazy" data-original="'.$h_thumb_link.'" src="'.$base.'/lib/static/grey.gif">'.
'<noscript><img id="thumb_'.$i_id.'" title="'.$h_tip.'" alt="'.$h_tip.'" height="'.$tsize[1].'" width="'.$tsize[0].'" src="'.$h_thumb_link.'"></noscript>'.
"</a></div></center>\n";
}
/** /**
* Put something in a rounded rectangle box; specific to the default theme * Put something in a rounded rectangle box; specific to the default theme
*/ */
@ -40,7 +11,6 @@ class Themelet extends BaseThemelet {
"; ";
} }
/** /**
* Add a generic paginator * Add a generic paginator
*/ */
@ -67,7 +37,7 @@ class Themelet extends BaseThemelet {
private function build_paginator($current_page, $total_pages, $base_url, $query) { private function build_paginator($current_page, $total_pages, $base_url, $query) {
$next = $current_page + 1; $next = $current_page + 1;
$prev = $current_page - 1; $prev = $current_page - 1;
$rand = rand(1, $total_pages); $rand = mt_rand(1, $total_pages);
$at_start = ($current_page <= 1 || $total_pages <= 1); $at_start = ($current_page <= 1 || $total_pages <= 1);
$at_end = ($current_page >= $total_pages); $at_end = ($current_page >= $total_pages);