text:
<?php

namespace PHPImageWorkshop\Core;

use PHPImageWorkshop\Core\Exception\ImageWorkshopLibException as ImageWorkshopLibException;

// If no autoloader, uncomment these lines:
require_once(__DIR__.'/Exception/ImageWorkshopLibException.php');

/**
 * ImageWorkshopLib class
 *
 * Contains some tools to help in some ImageWorkshop calculations
 *
 * @link http://phpimageworkshop.com
 * @author Sybio (Clément Guillemain  / @Sybio01)
 * @license http://en.wikipedia.org/wiki/MIT_License
 * @copyright Clément Guillemain
 */
class ImageWorkshopLib
{
    /**
     * @var integer
     */
    const ERROR_FONT_NOT_FOUND = 3;

    /**
     * Calculate the left top positions of a layer inside a parent layer container
     * $position: http://phpimageworkshop.com/doc/22/corners-positions-schema-of-an-image.html
     *
     * @param integer $containerWidth
     * @param integer $containerHeight
     * @param integer $layerWidth
     * @param integer $layerHeight
     * @param integer $layerPositionX
     * @param integer $layerPositionY
     * @param string $position
     *
     * @return array
     */
    public static function calculatePositions($containerWidth, $containerHeight, $layerWidth, $layerHeight, $layerPositionX, $layerPositionY, $position = 'LT')
    {
        $position = strtolower($position);

        if ($position == 'rt') {

            $layerPositionX = $containerWidth - $layerWidth - $layerPositionX;

        } elseif ($position == 'lb') {

            $layerPositionY = $containerHeight - $layerHeight - $layerPositionY;

        } elseif ($position == 'rb') {

            $layerPositionX = $containerWidth - $layerWidth - $layerPositionX;
            $layerPositionY = $containerHeight - $layerHeight - $layerPositionY;

        } elseif ($position == 'mm') {

            $layerPositionX = (($containerWidth - $layerWidth) / 2) + $layerPositionX;
            $layerPositionY = (($containerHeight - $layerHeight) / 2) + $layerPositionY;

        } elseif ($position == 'mt') {

            $layerPositionX = (($containerWidth - $layerWidth) / 2) + $layerPositionX;

        } elseif ($position == 'mb') {

            $layerPositionX = (($containerWidth - $layerWidth) / 2) + $layerPositionX;
            $layerPositionY = $containerHeight - $layerHeight - $layerPositionY;

        } elseif ($position == 'lm') {

            $layerPositionY = (($containerHeight - $layerHeight) / 2) + $layerPositionY;

        } elseif ($position == 'rm') {

            $layerPositionX = $containerWidth - $layerWidth - $layerPositionX;
            $layerPositionY = (($containerHeight - $layerHeight) / 2) + $layerPositionY;
        }

        return array(
            'x' => $layerPositionX,
            'y' => $layerPositionY,
        );
    }

    /**
     * Convert Hex color to RGB color format
     *
     * @param string $hex
     *
     * @return array
     */
    public static function convertHexToRGB($hex)
    {
        return array(
            'R' => (int) base_convert(substr($hex, 0, 2), 16, 10),
            'G' => (int) base_convert(substr($hex, 2, 2), 16, 10),
            'B' => (int) base_convert(substr($hex, 4, 2), 16, 10),
        );
    }

    /**
     * Generate a new image resource var
     *
     * @param integer $width
     * @param integer $height
     * @param string $color
     * @param integer $opacity
     *
     * @return resource
     */
    public static function generateImage($width = 100, $height = 100, $color = 'ffffff', $opacity = 127)
    {
        $RGBColors = ImageWorkshopLib::convertHexToRGB($color);

        $image = imagecreatetruecolor($width, $height);
        imagesavealpha($image, true);
        $color = imagecolorallocatealpha($image, $RGBColors['R'], $RGBColors['G'], $RGBColors['B'], $opacity);
        imagefill($image, 0, 0, $color);

        return $image;
    }

    /**
     * Return dimension of a text
     *
     * @param $fontSize
     * @param $fontAngle
     * @param $fontFile
     * @param $text
     *
     * @return array or boolean
     */
    public static function getTextBoxDimension($fontSize, $fontAngle, $fontFile, $text)
    {
        if (!file_exists($fontFile)) {
            throw new ImageWorkshopLibException('Can\'t find a font file at this path : "'.$fontFile.'".', static::ERROR_FONT_NOT_FOUND);
        }

        $box = imagettfbbox($fontSize, $fontAngle, $fontFile, $text);

		if (!$box) {

			return false;
		}

        $minX = min(array($box[0], $box[2], $box[4], $box[6]));
        $maxX = max(array($box[0], $box[2], $box[4], $box[6]));
        $minY = min(array($box[1], $box[3], $box[5], $box[7]));
        $maxY = max(array($box[1], $box[3], $box[5], $box[7]));
        $width = ($maxX - $minX);
        $height = ($maxY - $minY);
        $left = abs($minX) + $width;
        $top = abs($minY) + $height;

        // to calculate the exact bounding box, we write the text in a large image
        $img = @imagecreatetruecolor($width << 2, $height << 2);
        $white = imagecolorallocate($img, 255, 255, 255);
        $black = imagecolorallocate($img, 0, 0, 0);
        imagefilledrectangle($img, 0, 0, imagesx($img), imagesy($img), $black);

        // for ensure that the text is completely in the image
        imagettftext($img, $fontSize, $fontAngle, $left, $top, $white, $fontFile, $text);

        // start scanning (0=> black => empty)
        $rleft = $w4 = $width<<2;
        $rright = 0;
        $rbottom = 0;
        $rtop = $h4 = $height<<2;

        for ($x = 0; $x < $w4; $x++) {

			for ($y = 0; $y < $h4; $y++) {

				if (imagecolorat($img, $x, $y)) {

					$rleft = min($rleft, $x);
					$rright = max($rright, $x);
					$rtop = min($rtop, $y);
					$rbottom = max($rbottom, $y);
				}
			}
		}

        imagedestroy($img);

        return array(
            'left' => $left - $rleft,
            'top' => $top - $rtop,
            'width' => $rright - $rleft + 1,
            'height' => $rbottom - $rtop + 1,
        );
    }

    /**
     * Copy an image on another one and converse transparency
     *
     * @param resource $destImg
     * @param resource $srcImg
     * @param integer $destX
     * @param integer $destY
     * @param integer $srcX
     * @param integer $srcY
     * @param integer $srcW
     * @param integer $srcH
     * @param integer $pct
     */
    public static function imageCopyMergeAlpha(&$destImg, &$srcImg, $destX, $destY, $srcX, $srcY, $srcW, $srcH, $pct = 0)
    {
        $destX = (int) $destX;
        $destY = (int) $destY;
        $srcX = (int) $srcX;
        $srcY = (int) $srcY;
        $srcW = (int) $srcW;
        $srcH = (int) $srcH;
        $pct = (int) $pct;
        $destW = imageSX($destImg);
        $destH = imageSY($destImg);

        for ($y = 0; $y < $srcH + $srcY; $y++) {

            for ($x = 0; $x < $srcW + $srcX; $x++) {

                if ($x + $destX >= 0 && $x + $destX < $destW && $x + $srcX >= 0 && $x + $srcX < $srcW && $y + $destY >= 0 && $y + $destY < $destH && $y + $srcY >= 0 && $y + $srcY < $srcH) {

                    $destPixel = imageColorsForIndex($destImg, imageColorat($destImg, $x + $destX, $y + $destY));
                    $srcImgColorat = imageColorat($srcImg, $x + $srcX, $y + $srcY);

                    if ($srcImgColorat >= 0) {

                        $srcPixel = imageColorsForIndex($srcImg, $srcImgColorat);

                        $srcAlpha = 1 - ($srcPixel['alpha'] / 127);
                        $destAlpha = 1 - ($destPixel['alpha'] / 127);
                        $opacity = $srcAlpha * $pct / 100;

                        if ($destAlpha >= $opacity) {
    						$alpha = $destAlpha;
    					}

                        if ($destAlpha < $opacity) {
    						$alpha = $opacity;
    					}

                        if ($alpha > 1) {
    						$alpha = 1;
    					}

                        if ($opacity > 0) {

                            $destRed = round((($destPixel['red'] * $destAlpha * (1 - $opacity))));
                            $destGreen = round((($destPixel['green'] * $destAlpha * (1 - $opacity))));
                            $destBlue = round((($destPixel['blue'] * $destAlpha * (1 - $opacity))));
                            $srcRed = round((($srcPixel['red'] * $opacity)));
                            $srcGreen = round((($srcPixel['green'] * $opacity)));
                            $srcBlue = round((($srcPixel['blue'] * $opacity)));
                            $red = round(($destRed + $srcRed  ) / ($destAlpha * (1 - $opacity) + $opacity));
                            $green = round(($destGreen + $srcGreen) / ($destAlpha * (1 - $opacity) + $opacity));
                            $blue = round(($destBlue + $srcBlue ) / ($destAlpha * (1 - $opacity) + $opacity));

                            if ($red   > 255) {
    							$red   = 255;
    						}

                            if ($green > 255) {
    							$green = 255;
                            }

    						if ($blue  > 255) {
    							$blue  = 255;
    						}

                            $alpha = round((1 - $alpha) * 127);
                            $color = imageColorAllocateAlpha($destImg, $red, $green, $blue, $alpha);
                            imageSetPixel($destImg, $x + $destX, $y + $destY, $color);
                        }
                    }
                }
            }
        }
    }

    /**
     * Merge two image var
     *
     * @param resource $destinationImage
     * @param resource $sourceImage
     * @param integer $destinationPosX
     * @param integer $destinationPosY
     * @param integer $sourcePosX
     * @param integer $sourcePosY
     */
    public static function mergeTwoImages(&$destinationImage, $sourceImage, $destinationPosX = 0, $destinationPosY = 0, $sourcePosX = 0, $sourcePosY = 0)
    {
        imageCopy($destinationImage, $sourceImage, $destinationPosX, $destinationPosY, $sourcePosX, $sourcePosY, imageSX($sourceImage), imageSY($sourceImage));
    }
}


text:
<?php

namespace PHPImageWorkshop\Core\Exception;

use PHPImageWorkshop\Exception\ImageWorkshopBaseException as ImageWorkshopBaseException;

// If no autoloader, uncomment these lines:
require_once(__DIR__.'/../../Exception/ImageWorkshopBaseException.php');

/**
 * ImageWorkshopLayerException
 *
 * Manage ImageWorkshopLayer exceptions
 *
 * @link http://phpimageworkshop.com
 * @author Sybio (Clément Guillemain  / @Sybio01)
 * @license http://en.wikipedia.org/wiki/MIT_License
 * @copyright Clément Guillemain
 */
class ImageWorkshopLayerException extends ImageWorkshopBaseException
{
}

repo_language: PHP

mime_type: text/plain


text:
<?php

namespace PHPImageWorkshop\Core\Exception;

use PHPImageWorkshop\Exception\ImageWorkshopBaseException as ImageWorkshopBaseException;

// If no autoloader, uncomment these lines:
require_once(__DIR__.'/../../Exception/ImageWorkshopBaseException.php');

/**
 * ImageWorkshopLibException
 *
 * Manage ImageWorkshopLib exceptions
 *
 * @link http://phpimageworkshop.com
 * @author Sybio (Clément Guillemain  / @Sybio01)
 * @license http://en.wikipedia.org/wiki/MIT_License
 * @copyright Clément Guillemain
 */
class ImageWorkshopLibException extends ImageWorkshopBaseException
{
}


text:
<?php

namespace PHPImageWorkshop\Exception;

use PHPImageWorkshop\Exception\ImageWorkshopBaseException as ImageWorkshopBaseException;

// If no autoloader, uncomment these lines:
require_once(__DIR__.'/ImageWorkshopBaseException.php');

/**
 * ImageWorkshopException
 *
 * Manage ImageWorkshop exceptions
 *
 * @link http://phpimageworkshop.com
 * @author Sybio (Clément Guillemain  / @Sybio01)
 * @license http://en.wikipedia.org/wiki/MIT_License
 * @copyright Clément Guillemain
 */
class ImageWorkshopException extends ImageWorkshopBaseException
{
}


text:
<?php

namespace PHPImageWorkshop\Exception;

/**
 * ImageWorkshopBaseException
 *
 * The inherited exception class
 *
 * @link http://phpimageworkshop.com
 * @author Bjørn Børresen | Sybio (Clément Guillemain  / @Sybio01)
 * @license http://en.wikipedia.org/wiki/MIT_License
 * @copyright Clément Guillemain
 */
class ImageWorkshopBaseException extends \Exception
{
    /**
     * Constructor
     *
     * @param string $message
     * @param integer $code
     * @param Exception $previous
     */
    public function __construct($message, $code = 0, \Exception $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }

    /**
     * __toString method
     *
     * @return string
     */
    public function __toString()
    {
        return __CLASS__.": [{$this->code}]: {$this->message}\n";
    }
}


text:
<?php

namespace PHPImageWorkshop\Exif;

/**
 * Container for all EXIF orientations.
 */
final class ExifOrientations
{
    const UNDEFINED    = 0;
    const TOP_LEFT     = 1;
    const TOP_RIGHT    = 2;
    const BOTTOM_RIGHT = 3;
    const BOTTOM_LEFT  = 4;
    const LEFT_TOP     = 5;
    const RIGHT_TOP    = 6;
    const RIGHT_BOTTOM = 7;
    const LEFT_BOTTOM  = 8;
}


text:
#!/usr/bin/env sh
if [ ! -f "/etc/periodic/15min/archive.sh" ]; then
  cp /var/www/.docker/config/app/cron/15min/archive.sh /etc/periodic/15min/archive.sh
  chmod +x /etc/periodic/15min/archive.sh
  (crontab -l ; echo "*/10 * * * * /etc/periodic/15min/archive.sh > /proc/1/fd/1 2>/proc/1/fd/2") | sort - | uniq - | crontab -
fi

if [ ! -f "/etc/periodic/hourly/audit.sh" ]; then
  cp /var/www/.docker/config/app/cron/hourly/audit.sh /etc/periodic/hourly/audit.sh
  chmod +x /etc/periodic/hourly/audit.sh
  (crontab -l ; echo "0 4 * * * /etc/periodic/hourly/audit.sh > /proc/1/fd/1 2>/proc/1/fd/2") | sort - | uniq - | crontab -
fi

if [ ! -f "/etc/periodic/hourly/thumbnails.sh" ]; then
  cp /var/www/.docker/config/app/cron/hourly/thumbnails.sh /etc/periodic/hourly/thumbnails.sh
  chmod +x /etc/periodic/hourly/thumbnails.sh
  (crontab -l ; echo "0 5 * * * /etc/periodic/hourly/thumbnails.sh > /proc/1/fd/1 2>/proc/1/fd/2") | sort - | uniq - | crontab -
fi

crond


text:
#!/usr/bin/env sh
if [ -f "config.json.linux" ]; then
echo "Updating config.json"

jq '.base.cookie.ipb_member_id=env.CONF_MEMBERID | .base.cookie.ipb_pass_hash=env.CONF_PASSHASH | .base.cookie.ipb_accesskey=env.CONF_ACCESSKEY | .base.tempDir=env.CONF_TEMPDIR | .base.archiveDir=env.CONF_ARCHDIR | .base.imagesDir=env.CONF_IMGDIR | .default.db.dsn=env.CONF_SQLDSN | .default.db.user=env.DB_USER | .default.db.pass=env.DB_PASS | .default.sphinxql.dsn=env.CONF_SPHINXDSN | .default.memcache.host="memcache"' config.json.linux > config.json
cp config.json.linux www/config.json
echo "Updated config"
fi


text:
<?php

chdir('../');
require 'common.php';

$api = new ApiHandler();
$api->handle($_REQUEST);

?>


text:
<!DOCTYPE html>

	<meta charset="utf-8">

	<meta name="viewport" content="width=device-width, user-scalable=no">
	<meta name="mobile-web-app-capable" content="yes">

	<title>ExHentai Archive</title>

	<link rel="icon" type="image/png" href="img/icon.png">

	<link rel="stylesheet" href="css/exhen.css">
    <link rel="stylesheet" href="css/foundation-icons.css">

		<form method="get" action="/" class="search-form" id="search-form">

                <input type="text" class="search" placeholder="Search" name="search" />

					Order

Posted

Archived

Random

Weight

				<button class="search-button button">Search</button>

		</form>

            <button class="toggle-button button">▼</button>

                    SPV
                    <input type="checkbox" name="viewertype" value="0" class="fancy-switch viewtype" />

                    MPV

                    Show unarchived
                    <input type="checkbox" name="unarchived" value="0" class="fancy-switch unarchived" />

                    Read/Unread
                    <select class="read-switch">
                        <option value="false">Both</option>
                        <option value="0">Unread</option>
                        <option value="1">Read</option>
                    </select>

                    Color
                    <select class="color-switch">
                        <option value="false">All</option>
                        <option value="black">Black</option>
                        <option value="red">Red</option>
                        <option value="green">Green</option>
                        <option value="blue">Blue</option>
                        <option value="pink">Pink</option>
                        <option value="purple">Purple</option>
                        <option value="white">White</option>
                    </select>

		Click to load previous

		Click to load next

				Actions

Delete

Resize

Download

Similar

ExHentai

			X

End

                <select class="color-select">
                    <option value="black">Black</option>
                    <option value="red">Red</option>
                    <option value="green">Green</option>
                    <option value="blue">Blue</option>
                    <option value="pink">Pink</option>
                    <option value="purple">Purple</option>
                    <option value="white">White</option>
                </select>

                    <input type="checkbox" id="read" name="read" value="0">


text:
/*
 * Foundation Icons v 3.0
 * Made by ZURB 2013 http://zurb.com/playground/foundation-icon-fonts-3
 * MIT License
 */

@font-face {
  font-family: "foundation-icons";
  src: url("../font/foundation-icons.eot");
  src: url("../font/foundation-icons.eot?#iefix") format("embedded-opentype"),
       url("../font/foundation-icons.woff") format("woff"),
       url("../font/foundation-icons.ttf") format("truetype"),
       url("../font/foundation-icons.svg#fontcustom") format("svg");
  font-weight: normal;
  font-style: normal;
}

.fi-address-book:before,
.fi-alert:before,
.fi-align-center:before,
.fi-align-justify:before,
.fi-align-left:before,
.fi-align-right:before,
.fi-anchor:before,
.fi-annotate:before,
.fi-archive:before,
.fi-arrow-down:before,
.fi-arrow-left:before,
.fi-arrow-right:before,
.fi-arrow-up:before,
.fi-arrows-compress:before,
.fi-arrows-expand:before,
.fi-arrows-in:before,
.fi-arrows-out:before,
.fi-asl:before,
.fi-asterisk:before,
.fi-at-sign:before,
.fi-background-color:before,
.fi-battery-empty:before,
.fi-battery-full:before,
.fi-battery-half:before,
.fi-bitcoin-circle:before,
.fi-bitcoin:before,
.fi-blind:before,
.fi-bluetooth:before,
.fi-bold:before,
.fi-book-bookmark:before,
.fi-book:before,
.fi-bookmark:before,
.fi-braille:before,
.fi-burst-new:before,
.fi-burst-sale:before,
.fi-burst:before,
.fi-calendar:before,
.fi-camera:before,
.fi-check:before,
.fi-checkbox:before,
.fi-clipboard-notes:before,
.fi-clipboard-pencil:before,
.fi-clipboard:before,
.fi-clock:before,
.fi-closed-caption:before,
.fi-cloud:before,
.fi-comment-minus:before,
.fi-comment-quotes:before,
.fi-comment-video:before,
.fi-comment:before,
.fi-comments:before,
.fi-compass:before,
.fi-contrast:before,
.fi-credit-card:before,
.fi-crop:before,
.fi-crown:before,
.fi-css3:before,
.fi-database:before,
.fi-die-five:before,
.fi-die-four:before,
.fi-die-one:before,
.fi-die-six:before,
.fi-die-three:before,
.fi-die-two:before,
.fi-dislike:before,
.fi-dollar-bill:before,
.fi-dollar:before,
.fi-download:before,
.fi-eject:before,
.fi-elevator:before,
.fi-euro:before,
.fi-eye:before,
.fi-fast-forward:before,
.fi-female-symbol:before,
.fi-female:before,
.fi-filter:before,
.fi-first-aid:before,
.fi-flag:before,
.fi-folder-add:before,
.fi-folder-lock:before,
.fi-folder:before,
.fi-foot:before,
.fi-foundation:before,
.fi-graph-bar:before,
.fi-graph-horizontal:before,
.fi-graph-pie:before,
.fi-graph-trend:before,
.fi-guide-dog:before,
.fi-hearing-aid:before,
.fi-heart:before,
.fi-home:before,
.fi-html5:before,
.fi-indent-less:before,
.fi-indent-more:before,
.fi-info:before,
.fi-italic:before,
.fi-key:before,
.fi-laptop:before,
.fi-layout:before,
.fi-lightbulb:before,
.fi-like:before,
.fi-link:before,
.fi-list-bullet:before,
.fi-list-number:before,
.fi-list-thumbnails:before,
.fi-list:before,
.fi-lock:before,
.fi-loop:before,
.fi-magnifying-glass:before,
.fi-mail:before,
.fi-male-female:before,
.fi-male-symbol:before,
.fi-male:before,
.fi-map:before,
.fi-marker:before,
.fi-megaphone:before,
.fi-microphone:before,
.fi-minus-circle:before,
.fi-minus:before,
.fi-mobile-signal:before,
.fi-mobile:before,
.fi-monitor:before,
.fi-mountains:before,
.fi-music:before,
.fi-next:before,
.fi-no-dogs:before,
.fi-no-smoking:before,
.fi-page-add:before,
.fi-page-copy:before,
.fi-page-csv:before,
.fi-page-delete:before,
.fi-page-doc:before,
.fi-page-edit:before,
.fi-page-export-csv:before,
.fi-page-export-doc:before,
.fi-page-export-pdf:before,
.fi-page-export:before,
.fi-page-filled:before,
.fi-page-multiple:before,
.fi-page-pdf:before,
.fi-page-remove:before,
.fi-page-search:before,
.fi-page:before,
.fi-paint-bucket:before,
.fi-paperclip:before,
.fi-pause:before,
.fi-paw:before,
.fi-paypal:before,
.fi-pencil:before,
.fi-photo:before,
.fi-play-circle:before,
.fi-play-video:before,
.fi-play:before,
.fi-plus:before,
.fi-pound:before,
.fi-power:before,
.fi-previous:before,
.fi-price-tag:before,
.fi-pricetag-multiple:before,
.fi-print:before,
.fi-prohibited:before,
.fi-projection-screen:before,
.fi-puzzle:before,
.fi-quote:before,
.fi-record:before,
.fi-refresh:before,
.fi-results-demographics:before,
.fi-results:before,
.fi-rewind-ten:before,
.fi-rewind:before,
.fi-rss:before,
.fi-safety-cone:before,
.fi-save:before,
.fi-share:before,
.fi-sheriff-badge:before,
.fi-shield:before,
.fi-shopping-bag:before,
.fi-shopping-cart:before,
.fi-shuffle:before,
.fi-skull:before,
.fi-social-500px:before,
.fi-social-adobe:before,
.fi-social-amazon:before,
.fi-social-android:before,
.fi-social-apple:before,
.fi-social-behance:before,
.fi-social-bing:before,
.fi-social-blogger:before,
.fi-social-delicious:before,
.fi-social-designer-news:before,
.fi-social-deviant-art:before,
.fi-social-digg:before,
.fi-social-dribbble:before,
.fi-social-drive:before,
.fi-social-dropbox:before,
.fi-social-evernote:before,
.fi-social-facebook:before,
.fi-social-flickr:before,
.fi-social-forrst:before,
.fi-social-foursquare:before,
.fi-social-game-center:before,
.fi-social-github:before,
.fi-social-google-plus:before,
.fi-social-hacker-news:before,
.fi-social-hi5:before,
.fi-social-instagram:before,
.fi-social-joomla:before,
.fi-social-lastfm:before,
.fi-social-linkedin:before,
.fi-social-medium:before,
.fi-social-myspace:before,
.fi-social-orkut:before,
.fi-social-path:before,
.fi-social-picasa:before,
.fi-social-pinterest:before,
.fi-social-rdio:before,
.fi-social-reddit:before,
.fi-social-skillshare:before,
.fi-social-skype:before,
.fi-social-smashing-mag:before,
.fi-social-snapchat:before,
.fi-social-spotify:before,
.fi-social-squidoo:before,
.fi-social-stack-overflow:before,
.fi-social-steam:before,
.fi-social-stumbleupon:before,
.fi-social-treehouse:before,
.fi-social-tumblr:before,
.fi-social-twitter:before,
.fi-social-vimeo:before,
.fi-social-windows:before,
.fi-social-xbox:before,
.fi-social-yahoo:before,
.fi-social-yelp:before,
.fi-social-youtube:before,
.fi-social-zerply:before,
.fi-social-zurb:before,
.fi-sound:before,
.fi-star:before,
.fi-stop:before,
.fi-strikethrough:before,
.fi-subscript:before,
.fi-superscript:before,
.fi-tablet-landscape:before,
.fi-tablet-portrait:before,
.fi-target-two:before,
.fi-target:before,
.fi-telephone-accessible:before,
.fi-telephone:before,
.fi-text-color:before,
.fi-thumbnails:before,
.fi-ticket:before,
.fi-torso-business:before,
.fi-torso-female:before,
.fi-torso:before,
.fi-torsos-all-female:before,
.fi-torsos-all:before,
.fi-torsos-female-male:before,
.fi-torsos-male-female:before,
.fi-torsos:before,
.fi-trash:before,
.fi-trees:before,
.fi-trophy:before,
.fi-underline:before,
.fi-universal-access:before,
.fi-unlink:before,
.fi-unlock:before,
.fi-upload-cloud:before,
.fi-upload:before,
.fi-usb:before,
.fi-video:before,
.fi-volume-none:before,
.fi-volume-strike:before,
.fi-volume:before,
.fi-web:before,
.fi-wheelchair:before,
.fi-widget:before,
.fi-wrench:before,
.fi-x-circle:before,
.fi-x:before,
.fi-yen:before,
.fi-zoom-in:before,
.fi-zoom-out:before {
  font-family: "foundation-icons";
  font-style: normal;
  font-weight: normal;
  font-variant: normal;
  text-transform: none;
  line-height: 1;
  -webkit-font-smoothing: antialiased;
  display: inline-block;
  text-decoration: inherit;
}

.fi-address-book:before { content: "\f100"; }
.fi-alert:before { content: "\f101"; }
.fi-align-center:before { content: "\f102"; }
.fi-align-justify:before { content: "\f103"; }
.fi-align-left:before { content: "\f104"; }
.fi-align-right:before { content: "\f105"; }
.fi-anchor:before { content: "\f106"; }
.fi-annotate:before { content: "\f107"; }
.fi-archive:before { content: "\f108"; }
.fi-arrow-down:before { content: "\f109"; }
.fi-arrow-left:before { content: "\f10a"; }
.fi-arrow-right:before { content: "\f10b"; }
.fi-arrow-up:before { content: "\f10c"; }
.fi-arrows-compress:before { content: "\f10d"; }
.fi-arrows-expand:before { content: "\f10e"; }
.fi-arrows-in:before { content: "\f10f"; }
.fi-arrows-out:before { content: "\f110"; }
.fi-asl:before { content: "\f111"; }
.fi-asterisk:before { content: "\f112"; }
.fi-at-sign:before { content: "\f113"; }
.fi-background-color:before { content: "\f114"; }
.fi-battery-empty:before { content: "\f115"; }
.fi-battery-full:before { content: "\f116"; }
.fi-battery-half:before { content: "\f117"; }
.fi-bitcoin-circle:before { content: "\f118"; }
.fi-bitcoin:before { content: "\f119"; }
.fi-blind:before { content: "\f11a"; }
.fi-bluetooth:before { content: "\f11b"; }
.fi-bold:before { content: "\f11c"; }
.fi-book-bookmark:before { content: "\f11d"; }
.fi-book:before { content: "\f11e"; }
.fi-bookmark:before { content: "\f11f"; }
.fi-braille:before { content: "\f120"; }
.fi-burst-new:before { content: "\f121"; }
.fi-burst-sale:before { content: "\f122"; }
.fi-burst:before { content: "\f123"; }
.fi-calendar:before { content: "\f124"; }
.fi-camera:before { content: "\f125"; }
.fi-check:before { content: "\f126"; }
.fi-checkbox:before { content: "\f127"; }
.fi-clipboard-notes:before { content: "\f128"; }
.fi-clipboard-pencil:before { content: "\f129"; }
.fi-clipboard:before { content: "\f12a"; }
.fi-clock:before { content: "\f12b"; }
.fi-closed-caption:before { content: "\f12c"; }
.fi-cloud:before { content: "\f12d"; }
.fi-comment-minus:before { content: "\f12e"; }
.fi-comment-quotes:before { content: "\f12f"; }
.fi-comment-video:before { content: "\f130"; }
.fi-comment:before { content: "\f131"; }
.fi-comments:before { content: "\f132"; }
.fi-compass:before { content: "\f133"; }
.fi-contrast:before { content: "\f134"; }
.fi-credit-card:before { content: "\f135"; }
.fi-crop:before { content: "\f136"; }
.fi-crown:before { content: "\f137"; }
.fi-css3:before { content: "\f138"; }
.fi-database:before { content: "\f139"; }
.fi-die-five:before { content: "\f13a"; }
.fi-die-four:before { content: "\f13b"; }
.fi-die-one:before { content: "\f13c"; }
.fi-die-six:before { content: "\f13d"; }
.fi-die-three:before { content: "\f13e"; }
.fi-die-two:before { content: "\f13f"; }
.fi-dislike:before { content: "\f140"; }
.fi-dollar-bill:before { content: "\f141"; }
.fi-dollar:before { content: "\f142"; }
.fi-download:before { content: "\f143"; }
.fi-eject:before { content: "\f144"; }
.fi-elevator:before { content: "\f145"; }
.fi-euro:before { content: "\f146"; }
.fi-eye:before { content: "\f147"; }
.fi-fast-forward:before { content: "\f148"; }
.fi-female-symbol:before { content: "\f149"; }
.fi-female:before { content: "\f14a"; }
.fi-filter:before { content: "\f14b"; }
.fi-first-aid:before { content: "\f14c"; }
.fi-flag:before { content: "\f14d"; }
.fi-folder-add:before { content: "\f14e"; }
.fi-folder-lock:before { content: "\f14f"; }
.fi-folder:before { content: "\f150"; }
.fi-foot:before { content: "\f151"; }
.fi-foundation:before { content: "\f152"; }
.fi-graph-bar:before { content: "\f153"; }
.fi-graph-horizontal:before { content: "\f154"; }
.fi-graph-pie:before { content: "\f155"; }
.fi-graph-trend:before { content: "\f156"; }
.fi-guide-dog:before { content: "\f157"; }
.fi-hearing-aid:before { content: "\f158"; }
.fi-heart:before { content: "\f159"; }
.fi-home:before { content: "\f15a"; }
.fi-html5:before { content: "\f15b"; }
.fi-indent-less:before { content: "\f15c"; }
.fi-indent-more:before { content: "\f15d"; }
.fi-info:before { content: "\f15e"; }
.fi-italic:before { content: "\f15f"; }
.fi-key:before { content: "\f160"; }
.fi-laptop:before { content: "\f161"; }
.fi-layout:before { content: "\f162"; }
.fi-lightbulb:before { content: "\f163"; }
.fi-like:before { content: "\f164"; }
.fi-link:before { content: "\f165"; }
.fi-list-bullet:before { content: "\f166"; }
.fi-list-number:before { content: "\f167"; }
.fi-list-thumbnails:before { content: "\f168"; }
.fi-list:before { content: "\f169"; }
.fi-lock:before { content: "\f16a"; }
.fi-loop:before { content: "\f16b"; }
.fi-magnifying-glass:before { content: "\f16c"; }
.fi-mail:before { content: "\f16d"; }
.fi-male-female:before { content: "\f16e"; }
.fi-male-symbol:before { content: "\f16f"; }
.fi-male:before { content: "\f170"; }
.fi-map:before { content: "\f171"; }
.fi-marker:before { content: "\f172"; }
.fi-megaphone:before { content: "\f173"; }
.fi-microphone:before { content: "\f174"; }
.fi-minus-circle:before { content: "\f175"; }
.fi-minus:before { content: "\f176"; }
.fi-mobile-signal:before { content: "\f177"; }
.fi-mobile:before { content: "\f178"; }
.fi-monitor:before { content: "\f179"; }
.fi-mountains:before { content: "\f17a"; }
.fi-music:before { content: "\f17b"; }
.fi-next:before { content: "\f17c"; }
.fi-no-dogs:before { content: "\f17d"; }
.fi-no-smoking:before { content: "\f17e"; }
.fi-page-add:before { content: "\f17f"; }
.fi-page-copy:before { content: "\f180"; }
.fi-page-csv:before { content: "\f181"; }
.fi-page-delete:before { content: "\f182"; }
.fi-page-doc:before { content: "\f183"; }
.fi-page-edit:before { content: "\f184"; }
.fi-page-export-csv:before { content: "\f185"; }
.fi-page-export-doc:before { content: "\f186"; }
.fi-page-export-pdf:before { content: "\f187"; }
.fi-page-export:before { content: "\f188"; }
.fi-page-filled:before { content: "\f189"; }
.fi-page-multiple:before { content: "\f18a"; }
.fi-page-pdf:before { content: "\f18b"; }
.fi-page-remove:before { content: "\f18c"; }
.fi-page-search:before { content: "\f18d"; }
.fi-page:before { content: "\f18e"; }
.fi-paint-bucket:before { content: "\f18f"; }
.fi-paperclip:before { content: "\f190"; }
.fi-pause:before { content: "\f191"; }
.fi-paw:before { content: "\f192"; }
.fi-paypal:before { content: "\f193"; }
.fi-pencil:before { content: "\f194"; }
.fi-photo:before { content: "\f195"; }
.fi-play-circle:before { content: "\f196"; }
.fi-play-video:before { content: "\f197"; }
.fi-play:before { content: "\f198"; }
.fi-plus:before { content: "\f199"; }
.fi-pound:before { content: "\f19a"; }
.fi-power:before { content: "\f19b"; }
.fi-previous:before { content: "\f19c"; }
.fi-price-tag:before { content: "\f19d"; }
.fi-pricetag-multiple:before { content: "\f19e"; }
.fi-print:before { content: "\f19f"; }
.fi-prohibited:before { content: "\f1a0"; }
.fi-projection-screen:before { content: "\f1a1"; }
.fi-puzzle:before { content: "\f1a2"; }
.fi-quote:before { content: "\f1a3"; }
.fi-record:before { content: "\f1a4"; }
.fi-refresh:before { content: "\f1a5"; }
.fi-results-demographics:before { content: "\f1a6"; }
.fi-results:before { content: "\f1a7"; }
.fi-rewind-ten:before { content: "\f1a8"; }
.fi-rewind:before { content: "\f1a9"; }
.fi-rss:before { content: "\f1aa"; }
.fi-safety-cone:before { content: "\f1ab"; }
.fi-save:before { content: "\f1ac"; }
.fi-share:before { content: "\f1ad"; }
.fi-sheriff-badge:before { content: "\f1ae"; }
.fi-shield:before { content: "\f1af"; }
.fi-shopping-bag:before { content: "\f1b0"; }
.fi-shopping-cart:before { content: "\f1b1"; }
.fi-shuffle:before { content: "\f1b2"; }
.fi-skull:before { content: "\f1b3"; }
.fi-social-500px:before { content: "\f1b4"; }
.fi-social-adobe:before { content: "\f1b5"; }
.fi-social-amazon:before { content: "\f1b6"; }
.fi-social-android:before { content: "\f1b7"; }
.fi-social-apple:before { content: "\f1b8"; }
.fi-social-behance:before { content: "\f1b9"; }
.fi-social-bing:before { content: "\f1ba"; }
.fi-social-blogger:before { content: "\f1bb"; }
.fi-social-delicious:before { content: "\f1bc"; }
.fi-social-designer-news:before { content: "\f1bd"; }
.fi-social-deviant-art:before { content: "\f1be"; }
.fi-social-digg:before { content: "\f1bf"; }
.fi-social-dribbble:before { content: "\f1c0"; }
.fi-social-drive:before { content: "\f1c1"; }
.fi-social-dropbox:before { content: "\f1c2"; }
.fi-social-evernote:before { content: "\f1c3"; }
.fi-social-facebook:before { content: "\f1c4"; }
.fi-social-flickr:before { content: "\f1c5"; }
.fi-social-forrst:before { content: "\f1c6"; }
.fi-social-foursquare:before { content: "\f1c7"; }
.fi-social-game-center:before { content: "\f1c8"; }
.fi-social-github:before { content: "\f1c9"; }
.fi-social-google-plus:before { content: "\f1ca"; }
.fi-social-hacker-news:before { content: "\f1cb"; }
.fi-social-hi5:before { content: "\f1cc"; }
.fi-social-instagram:before { content: "\f1cd"; }
.fi-social-joomla:before { content: "\f1ce"; }
.fi-social-lastfm:before { content: "\f1cf"; }
.fi-social-linkedin:before { content: "\f1d0"; }
.fi-social-medium:before { content: "\f1d1"; }
.fi-social-myspace:before { content: "\f1d2"; }
.fi-social-orkut:before { content: "\f1d3"; }
.fi-social-path:before { content: "\f1d4"; }
.fi-social-picasa:before { content: "\f1d5"; }
.fi-social-pinterest:before { content: "\f1d6"; }
.fi-social-rdio:before { content: "\f1d7"; }
.fi-social-reddit:before { content: "\f1d8"; }
.fi-social-skillshare:before { content: "\f1d9"; }
.fi-social-skype:before { content: "\f1da"; }
.fi-social-smashing-mag:before { content: "\f1db"; }
.fi-social-snapchat:before { content: "\f1dc"; }
.fi-social-spotify:before { content: "\f1dd"; }
.fi-social-squidoo:before { content: "\f1de"; }
.fi-social-stack-overflow:before { content: "\f1df"; }
.fi-social-steam:before { content: "\f1e0"; }
.fi-social-stumbleupon:before { content: "\f1e1"; }
.fi-social-treehouse:before { content: "\f1e2"; }
.fi-social-tumblr:before { content: "\f1e3"; }
.fi-social-twitter:before { content: "\f1e4"; }
.fi-social-vimeo:before { content: "\f1e5"; }
.fi-social-windows:before { content: "\f1e6"; }
.fi-social-xbox:before { content: "\f1e7"; }
.fi-social-yahoo:before { content: "\f1e8"; }
.fi-social-yelp:before { content: "\f1e9"; }
.fi-social-youtube:before { content: "\f1ea"; }
.fi-social-zerply:before { content: "\f1eb"; }
.fi-social-zurb:before { content: "\f1ec"; }
.fi-sound:before { content: "\f1ed"; }
.fi-star:before { content: "\f1ee"; }
.fi-stop:before { content: "\f1ef"; }
.fi-strikethrough:before { content: "\f1f0"; }
.fi-subscript:before { content: "\f1f1"; }
.fi-superscript:before { content: "\f1f2"; }
.fi-tablet-landscape:before { content: "\f1f3"; }
.fi-tablet-portrait:before { content: "\f1f4"; }
.fi-target-two:before { content: "\f1f5"; }
.fi-target:before { content: "\f1f6"; }
.fi-telephone-accessible:before { content: "\f1f7"; }
.fi-telephone:before { content: "\f1f8"; }
.fi-text-color:before { content: "\f1f9"; }
.fi-thumbnails:before { content: "\f1fa"; }
.fi-ticket:before { content: "\f1fb"; }
.fi-torso-business:before { content: "\f1fc"; }
.fi-torso-female:before { content: "\f1fd"; }
.fi-torso:before { content: "\f1fe"; }
.fi-torsos-all-female:before { content: "\f1ff"; }
.fi-torsos-all:before { content: "\f200"; }
.fi-torsos-female-male:before { content: "\f201"; }
.fi-torsos-male-female:before { content: "\f202"; }
.fi-torsos:before { content: "\f203"; }
.fi-trash:before { content: "\f204"; }
.fi-trees:before { content: "\f205"; }
.fi-trophy:before { content: "\f206"; }
.fi-underline:before { content: "\f207"; }
.fi-universal-access:before { content: "\f208"; }
.fi-unlink:before { content: "\f209"; }
.fi-unlock:before { content: "\f20a"; }
.fi-upload-cloud:before { content: "\f20b"; }
.fi-upload:before { content: "\f20c"; }
.fi-usb:before { content: "\f20d"; }
.fi-video:before { content: "\f20e"; }
.fi-volume-none:before { content: "\f20f"; }
.fi-volume-strike:before { content: "\f210"; }
.fi-volume:before { content: "\f211"; }
.fi-web:before { content: "\f212"; }
.fi-wheelchair:before { content: "\f213"; }
.fi-widget:before { content: "\f214"; }
.fi-wrench:before { content: "\f215"; }
.fi-x-circle:before { content: "\f216"; }
.fi-x:before { content: "\f217"; }
.fi-yen:before { content: "\f218"; }
.fi-zoom-in:before { content: "\f219"; }
.fi-zoom-out:before { content: "\f21a"; }


text:
@font-face {
	font-family: 'Open Sans';
	src: url('../font/OpenSans.eot');
	src: url('../font/OpenSans.eot?#iefix') format('embedded-opentype'),
		 url('../font/OpenSans.woff2') format('woff2'),
		 url('../font/OpenSans.woff') format('woff'),
		 url('../font/OpenSans.ttf') format('truetype'),
		 url('../font/OpenSans.svg#OpenSansRegular') format('svg');
}

body {
    margin: 0;
    font-family: 'Open Sans', sans-serif;
    background: #222;
    font-weight: 300;
    color: #ddd;
}

.cf:before,
.cf:after {
    content: " ";
    display: table;
}

.cf:after {
    clear: both;
}

.gallery-item {
    padding-top: 24.20%;
    display: inline-block;
    position: relative;
    background: no-repeat center;
    background-size: cover;
    width: 16.666%;
    margin-bottom: -5px;
    overflow: hidden;
    cursor: pointer;
    color: inherit;
}

.gallery-item.landscape {
    background-size: 100% auto;
}

.gallery-item .top,
.gallery-item .bottom {
    position: absolute;
    background: rgba(0, 0, 0, 0.7);
    padding: 10px;
    left: 0;
    opacity: 0;
    transition: opacity 50ms;
    width: 100%;
}

.gallery-item .top {
    top: 0;
    color: white;
    text-shadow:
    -1px -1px 0 #000,
    1px -1px 0 #000,
    -1px 1px 0 #000,
    1px 1px 0 #000;
}

.gallery-item .bottom {
    bottom: 0;
    max-height: 70%;
    overflow-y: auto;
}

.tags {
    font-size: 11px;
}

.tags .tag {
    display: inline-block;
    margin: 0 4px 4px 0;
    padding: 2px 4px;
    border-radius: 3px;
    transition: all 100ms;
    cursor: pointer;
    color: inherit;
    text-decoration: none;
}

.tags .tag:hover {
    box-shadow: 0px 0px 5px rgba(255, 255, 255, 0.51);
}

.tags .tag-character {
    background: rgba(134, 18, 18, 0.75);
}

.tags .tag-parody {
    background: rgba(90, 0, 133, 0.75);
}

.tags .tag-language {
    background: rgba(48, 48, 165, 0.75);
}

.tags .tag-group {
    background: rgba(48, 165, 53, 0.75);
}

.tags .tag-artist {
    background: rgba(48, 165, 156, 0.75);
}

.tags .tag-female {
    background: rgba(165, 48, 151, 0.75);
}

.tags .tag-male {
    background: rgba(134, 134, 134, 0.75);
}

.tags .tag-misc {
    background: rgba(165, 160, 54, 0.75);
}

.tags .tag-reclass {
    background: rgba(139, 110, 201, 0.75);
}

.tags .fi-book,
.tags .fi-book-bookmark {
    font-size: 20px;
    color: white;
    text-shadow:
    -1px -1px 0 #000,
    1px -1px 0 #000,
    -1px 1px 0 #000,
    1px 1px 0 #000;
    cursor: pointer;
}

.tags #read {
    display: none;
}

.gallery-item .date,
.gallery-item .weight {
    float: right;
    margin-top: 4px;
}

.gallery-item:hover .top,
.gallery-item:hover .bottom {
    opacity: 1;
}

.template {
    display: none;
}

.reader-container {
    display: none;
    position: fixed;
    width: 100%;
    height: 100%;
    background: inherit;
    top: 0;
    left: 0;
}

html.reader-active .reader-container {
    display: block;
}

html.reader-active,
html.reader-active body {
    overflow: hidden;
}

.reader-container .close.button {
    width: 40px;
}

.reader-container .image-holder {
    position: relative;
    top: 0;
    left: 0;
    -webkit-user-drag: none;
    -moz-user-drag: none;
    user-drag: none;
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
}

.reader-container .image-holder.init {
    opacity: 0;
}

.reader-container .image-holder.ui-draggable-dragging {
    cursor: move;
}

header {
    text-align: center;
    padding: 20px 20px 50px 20px;
}

.search {
    padding: 8px 10px;
    padding-right: 40px;
    width: 100%;
    background: none;
    border: 1px solid #999;
    border-radius: 2px;
    font: inherit;
    font-size: 22px;
    margin: 0;
    height: 48px;
    color: inherit;
}

.button {
    font: inherit;
    font-size: 22px;
    background: none;
    border: 1px solid #999;
    border-radius: 2px;
    width: 126px;
    text-align: center;
    line-height: 46px;
    padding: 0;
    margin: 0;
    display: inline-block;
    color: inherit;
    cursor: pointer;
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
}

.toggle-button {
    display: inline-block;
    width: 55px;
    vertical-align: top;
    position: absolute;
    left: 0;
    top: 0;
}

.search-under-options {
    display: none;
    padding-top: 50px;
    height: 200px;
}

.search-under-options > .switches-outer {
    right: auto !important;
    left: 0 !important;
    top: auto !important;
    position: absolute;
}

.search-form {
    display: flex;
    flex-direction: row;
}

* {
    box-sizing: border-box;
    -moz-box-sizing: border-box;
}

.search:focus,
.search:active,
.button:focus,
.button:active {
    outline: none;
    border: 1px solid rgb(209, 135, 0);
}

.reader-container .control {
    position: absolute;
    top: 0;
    height: 100%;
    width: 100px;
    background: rgba(0, 0, 0, 0.74) url(/img/arrow-prev.png) no-repeat center;
    display: none;
    opacity: 0;
    -webkit-user-select: none;
    -moz-user-select: none;
    user-select: none;
    cursor: pointer;
    transition: opacity 200ms;
}

.reader-container .control-next {
    right: 0;
    background-image: url(/img/arrow-next.png);
}

.reader-container .control-hotspot {
    position: absolute;
    top: 0;
    width: 10px;
    height: 100%;
}

.reader-container .control-hotspot-next {
    right: 0;
}

.reader-container .control:hover,
.reader-container .control-hotspot:hover + .control {
    display: block;
    opacity: 1;
}

.spinner {
    width: 50px;
    height: 30px;
    text-align: center;
    font-size: 10px;
    margin: 0 auto;
}

.spinner > div {
    background-color: #ddd;
    height: 100%;
    width: 6px;
    display: inline-block;
    -webkit-animation: stretchdelay 1.2s infinite ease-in-out;
    animation: stretchdelay 1.2s infinite ease-in-out;
}

.spinner .rect2 {
    -webkit-animation-delay: -1.1s;
    animation-delay: -1.1s;
}

.spinner .rect3 {
    -webkit-animation-delay: -1.0s;
    animation-delay: -1.0s;
}

.spinner .rect4 {
    -webkit-animation-delay: -0.9s;
    animation-delay: -0.9s;
}
.spinner .rect5 {
    -webkit-animation-delay: -0.8s;
    animation-delay: -0.8s;
}

@-webkit-keyframes stretchdelay {
    0%, 40%, 100% {
        -webkit-transform: scaleY(0.4)
    }
    20% {
        -webkit-transform: scaleY(1.0)
    }
}

@keyframes stretchdelay {
    0%, 40%, 100% {
        transform: scaleY(0.4);
        -webkit-transform: scaleY(0.4);
    }
    20% {
        transform: scaleY(1.0);
        -webkit-transform: scaleY(1.0);
    }
}

.spinner.spinner-top {
    display: none;
}

.load-previous,
.load-next {
    display: none;
    text-align: center;
    font-size: 22px;
    padding: 15px 0 20px;
}

.load-previous.active,
.load-next.active {
    display: block;
}

.load-next {
    padding-top: 20px;
}

.load-previous .inner:hover,
.load-next .inner:hover {
    color: rgb(255, 169, 169);
    cursor: pointer;
}

.suggestions {
    position: absolute;
    list-style: none;
    background: #222;
    border: 1px solid #999;
    border-top: none;
    z-index: 1;
    margin: 0;
    text-align: left;
    padding: 0;
    font-size: 18px;
    display: none;
}

.suggestions li {
    padding: 10px 20px;
}

.suggestions.active {
    display: block;
}

.suggestions li:hover,
.suggestions li.active {
    background: rgb(209, 135, 0);
    cursor: pointer;
    color: #222;
}

.suggestions li:hover .highlight,
.suggestions li.active .highlight {
    color: rgb(255, 255, 255);
}

.reader-container .thumbs-hotspot {
    position: absolute;
    top: 0;
    width: 10px;
    height: 100%;
}

.gallery-thumbs-outer {
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    background: rgba(0, 0, 0, 0.33);
    padding: 10px;
    transition: margin 200ms;
    transition-timing-function: ease-out;
    overflow: hidden;
    width: 180px;
    margin-left: -180px;
}

.gallery-thumbs-outer .gallery-thumb {
    width: 140px;
    height: 200px;
    display: block;
    background-size: 100% auto;
    background-repeat: no-repeat;
    background-position: center;
    cursor: pointer;
}

.gallery-thumbs-outer .gallery-thumb ~ .gallery-thumb {
    margin-top: 6px
}

.gallery-thumbs-outer .thumbs {
    overflow: auto;
    white-space: nowrap;
    max-height: 100%;
    padding-right: 20px;
}

.gallery-thumbs-outer:hover,
.thumbs-hotspot:hover + .gallery-thumbs-outer {
    margin: 0;
}

.gallery-thumbs-outer:hover + .gallery-info,
.thumbs-hotspot:hover + .gallery-thumbs-outer + .gallery-info {
    left: 180px;
}

.gallery-info {
    position: absolute;
    top: 0;
    left: 0;
    padding: 5px;
    z-index: 10;
    max-width: 540px;
    transition: left 200ms;
    transition-timing-function: ease-out;
}

.gallery-info:hover {
    z-index: 50
}

.gallery-info .title {
    font-size: 12px;
    text-shadow: 1px 1px 1px #000;
}

.gallery-info .tags {
    padding: 5px 0;
    max-width: 60%;
}

.gallery-info .expand {
    display: none;
}

.gallery-info:hover .expand {
    display: block;
}

.gallery-info .origtitle {
    color: #aaa;
    font-size: 12px;
}

.pages-container {
    height: 100%;
    overflow: auto;
    padding: 0 20px;
}

.pages-container > .inner {
    margin: 0 auto;
    position: relative;
    z-index: 30;
    max-width: 1200px;
    text-align: center;
    font-size: 0;
}

.pages-container .page.loaded ~ .page.loaded {
    margin-top: 20px;
}

.pages-container .page > img {
    max-width: 100%;
}

.pages-container .spinner {
    margin: 100px auto 80px;
}

.pages-container .page.loaded .index {
    position: absolute;
    bottom: 0;
    right: -30px;
    display: block;
    font-size: 16px;
    width: 30px;
    text-align: center;
}

.pages-container .page {
    position: relative;
}

.suggestions .highlight {
    color: rgb(255, 169, 169);
}

.reader-container .gallery-actions {
    position: absolute;
    top: 10px;
    right: 120px;
    z-index: 99999;
}

.gallery-actions .page-count {
    font-size: 20px;
    margin-right: 10px;
    text-shadow: 1px 1px 2px #000;
}

.dropdown-button .menu-outer {
    display: none;
    position: absolute;
}

.dropdown-button .menu-outer ul {
    list-style: none;
    margin: 10px 0 0;
    padding: 0;
    border: 1px solid #999;
    border-radius: 2px;
    z-index: 111;
    position: relative;
    background: #222;
}

.dropdown-button .menu-outer ul li {
    font-size: 22px;
    padding: 4px 16px;
}

.dropdown-button .menu-outer ul li:hover {
    cursor: pointer;
    color: rgb(255, 169, 169);
}

.input-clear {
    display: none;
    width: 18px;
    height: 18px;
    background: url(/img/input-clear.png) no-repeat center;
    position: absolute;
    top: 50%;
    margin-top: -9px;
    right: 30px;
    cursor: pointer;
}

.search:hover + * + .input-clear,
.search:focus ~ .input-clear,
.input-clear:hover {
    display: inline-block;
}

*::-webkit-input-placeholder {
    color: #aaa;
}

*::-moz-placeholder {
    color: #aaa;
}

.end-flash {
    position: fixed;
    top: 50%;
    left: 50%;
    margin-left: -50px;
    font-size: 40px;
    background: rgba(0, 0, 0, 0.8);
    width: 100px;
    text-align: center;
    border-radius: 10px;
    opacity: 0;
    display: none;
}

.end-flash.active {
    opacity: 1;
    display: block;
}

.end-flash.transition {
    transition: opacity 800ms;
    display: block;
}

.dropdown-button.active .menu-outer {
    display: block;
}

.dropdown-button {
    display: inline-block;
}

.actions-menu {
    margin-right: 6px;
}

.reader-container .button {
    font-size: 20px;
    line-height: 38px;
    width: 100px;
    text-shadow: 1px 1px 2px #000;
}

.reader-container .dropdown-button .menu-outer ul li {
    font-size: 20px;
    padding: 4px 14px;
}

.gallery-item .weight:before {
    content: "|";
    padding-left: 5px;
    padding-right: 5px;
    font-size: 10px;
    vertical-align: top;
    line-height: 15px;
}

.input-wrap {
    padding-right: 14px;
    flex-grow: 1;
    position: relative;
}

.search-options > * ~ * {
    margin-left: 10px;
}

.search-options {
    flex-shrink: 0;
}

.switches-outer {
    display: inline-block;
    vertical-align: top;
    position: absolute;
    top: 0;
    right: 0;
}

.switches-outer label {
    margin-left: 20px;
}

input[type="checkbox"].fancy-switch {
    position: absolute;
    opacity: 0;
}

input[type="checkbox"].fancy-switch + div {
    vertical-align: top;
    width: 45px;
    height: 22px;
    border-radius: 999px;
    background-color: rgba(0, 0, 0, 0.1);
    transition: .4s;
    box-shadow: inset 0 0 0 0px rgba(0, 0, 0, 0.4);
    border: 1px solid #999;
    display: inline-block;
}

input[type="checkbox"].fancy-switch:checked + div {
    width: 45px;
    background-position: 0 0;
    border: 1px solid rgb(209, 135, 0);
}

input[type="checkbox"].fancy-switch + div > div {
    float: left;
    width: 20px;
    height: 20px;
    border-radius: inherit;
    transition: transform .4s;
    box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.3), 0px 0px 0 1px rgba(0, 0, 0, 0.4);
    pointer-events: none;
    margin-top: 0px;
    margin-left: 0px;
    border: 1px solid #999;
}

input[type="checkbox"].fancy-switch:checked + div > div {
    transform: translate3d(24px, 0, 0);
    box-shadow: 0px 0px 0 1px rgb(209, 135, 0);
    border: none;
    background: inherit;
}

/*
 * Second Thing
 */
input[type="checkbox"].viewtype + div {
    vertical-align: top;
    width: 45px;
    height: 22px;
    border-radius: 999px;
    background-color: rgba(0, 0, 0, 0.1);
    transition: .4s;
    box-shadow: inset 0 0 0 0px rgba(0, 0, 0, 0.4);
    border: 1px solid rgb(3, 155, 229);
    display: inline-block;
}

input[type="checkbox"].viewtype:checked + div {
    width: 45px;
    background-position: 0 0;
    border: 1px solid rgb(229, 57, 53);
}

input[type="checkbox"].viewtype + div > div {
    float: left;
    width: 20px;
    height: 20px;
    border-radius: inherit;
    transition: transform .4s;
    box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.3), 0px 0px 0 1px rgba(0, 0, 0, 0.4);
    pointer-events: none;
    margin-top: 0px;
    margin-left: 0px;
    border: 1px solid rgb(3, 155, 229);
}

input[type="checkbox"].viewtype:checked + div > div {
    transform: translate3d(24px, 0, 0);
    box-shadow: 0px 0px 0 1px rgb(229, 57, 53);
    border: none;
    background: inherit;
}

.switches-outer label span {
    display: inline-block;
    margin-right: 10px;
}

.search-under {
    position: relative;
    height: 22px;
    margin-top: 20px;
}

.gallery-item.unarchived {
    background-size: contain;
}

.gallery-item.viewtype {
    background-size: contain;
}

.switches-outer label {
    cursor: pointer;
}

::-webkit-scrollbar {
    width: 12px;
}

::-webkit-scrollbar-track {
    border-radius: 10px;
}

::-webkit-scrollbar-thumb {
    border-radius: 10px;
    border: 1px solid #ddd;
}

@media (max-width: 1400px) {
    .gallery-item {
        width: 20%;
        padding-top: 29%;
    }
}

@media (max-width: 1100px) {
    .gallery-item {
        width: 25%;
        padding-top: 36.35%;
    }
}

@media (max-width: 900px) {
    .gallery-item {
        width: 33.333333333%;
        padding-top: 48.4%;
    }
    .search-count {
		float: left;
	}
}

@media (max-width: 720px) {
    .gallery-item .top,
    .gallery-item .bottom {
        display: none !important;
    }
	.search-count {
		float: left;
	}
    .gallery-info {
        display: none;
    }
}

@media (max-width: 580px) {
    .search-form {
        flex-wrap: wrap;
    }
	.search-count {
		float: left;
	}
    .search-options {
        flex-grow: 1;
        margin-top: 12px;
    }
}


text:
function api(action, params, callback) {
    params = $.extend(params, { action: action });

    var ret = $.ajax({
        url: 'api.php',
        dataType: 'json',
        aysnc: true,
        data: params,
        success: function(resp) {
            if(!resp.ret) {
                alert('API error: ' + resp.message);
            } else {
                if($.isFunction(callback)) {
                    callback(resp.data);
                }
            }
        }
    });

    return ret;
}

function getConfig() {
    return $.ajax({
        type: 'GET',
        url: 'config.json',
        dataType: 'json',
        success: function(data) { return data.responseJSON; },
        data: {},
        async: false
    }).responseJSON;
}

function getRotationDegrees(obj) {
    var matrix = obj.css("-webkit-transform") ||
    obj.css("-moz-transform")    ||
    obj.css("-ms-transform")     ||
    obj.css("-o-transform")      ||
    obj.css("transform");
    if(matrix !== 'none') {
        var values = matrix.split('(')[1].split(')')[0].split(',');
        var a = values[0];
        var b = values[1];
        var angle = Math.round(Math.atan2(b, a) * (180/Math.PI));
    } else { var angle = 0; }
    return (angle < 0) ? angle + 360 : angle;
}

$.fn.animateRotate = function(angle, duration, easing, complete) {
  var args = $.speed(duration, easing, complete);
  var step = args.step;
  return this.each(function(i, e) {
    args.complete = $.proxy(args.complete, e);
    args.step = function(now) {
      $.style(e, 'transform', 'rotate(' + now + 'deg)');
      if (step) return step.apply(e, arguments);
    };

    var curdeg = getRotationDegrees($(this));
    $({deg: curdeg}).animate({deg: angle}, args);
  });
};

$(document).ready(function() {

	var storage = false;

    // mpv: true/1
    // spv: false/0
    var mode = false;

	if (typeof(Storage) != "undefined") {
		storage = true;
        if (localStorage.getItem("viewType") === null) {
            localStorage.setItem("viewType", "spv");
        }

        if (localStorage.getItem("viewType") == "spv") {
            $(".viewtype").prop("checked", false);
            mode = false;
        } else if (localStorage.getItem("viewType") == "mpv") {
            $(".viewtype").prop("checked", true);
            mode = true;
        }
        switchGalleryView(mode);
	}

    $(".viewtype").change(function() {
       if($(this).prop("checked")) {
           localStorage.setItem("viewType", "mpv");
           mode = true;
       } else {
           localStorage.setItem("viewType", "spv");
           mode = false;
       }
       location.reload();
    });

	function renderTags(container, tagGroups) {
		$('.tag', container).remove();

		for(var ns in tagGroups) {
			var tags = tagGroups[ns];

			for(var x in tags) {
				var tag = tags[x];

				var tagItem = $('');

                var tagSearch = escapeTag(ns + ':' + tag);
                var url = '?' + $.param({ search: tagSearch });
                tagItem.prop('href', url);

				tagItem.text(tag);
				tagItem.addClass('tag tag-' + ns);
				tagItem.data('tag', tag);
				tagItem.data('ns', ns);
				tagItem.prop('title', ns + ':' + tag);
				container.prepend(tagItem);
			}
		}
	}

    function escapeTag(tag) {
        if(tag.indexOf(' ') >= 0) {
            return '"' + tag + '"'
        } else {
            return tag;
        }
    }

    function colorNameToRGBA(color) {
        if (color == "red")    { return "rgba(244,  67,  54,  0.7)"; }
        if (color == "pink")   { return "rgba(233,  30,  99,  0.7)"; }
        if (color == "purple") { return "rgba(156,  39, 176,  0.7)"; }
        if (color == "blue")   { return "rgba(33,  150, 243,  0.7)"; }
        if (color == "green")  { return "rgba(76,  175,  80,  0.7)"; }
        if (color == "black")  { return "rgba(0,     0,   0,  0.7)"; }
        if (color == "white")  { return "rgba(255, 255, 255,  0.7)"; }
        return "rgba(0, 0, 0, 0.7)";
    }

    function gallerySourceToName(gallerySource) {
        switch(gallerySource)
        {
            case "0":
                return "ExHentai";
            case "1":
                return "File";
            default:
                return "Error";
        }
        return "Super Error";
    }

    function switchGalleryView(mode) {
        if (!mode  && $(".pages-container").length) {
			console.log("Switching to Single Page Viewer");
			$(".pages-container").remove();

			$(".reader-container").append("");

			$(".reader-container").append("

");
			$(".reader-container").append("

");

			$(".reader-container").append("

");
			$(".reader-container").append("

");
		}
		else if (mode && $(".image-holder").length) {
			console.log("Switching to Multi Page Viewer");
			$(".image-holder").remove();
			$(".control-hotspot").remove();
			$(".control").remove();

			$(".reader-container").append("

</div
");
		}
    }

	$('.gallery-list').each(function() {
		var galleryList = $(this);
		var page = 0;
		var topPage = 0;
		var loading = false;
		var search = null;
		var xhr = null;
		var loadersBottom = $('.loaders-bottom');
		var loadersTop = $('.loaders-top');
		var searchCount = $('.search-count');
		var searchForm = $('.search-form');
		var order = 'posted';
		var init = false;
		var end = false;
		var randomSeed = 0;
        var unarchived = false;
        var color = false;
        var read = false;
        var preloadedPages = { };

		function loadPage(fwd) {
			loading = true;
			end = false;

			if(xhr) {
				xhr.abort();
			}

			if(fwd) {
				loadersBottom.addClass('active');
				$('.load-next').removeClass('active');
			} else {
				loadersTop.addClass('active');
				$('.load-previous').removeClass('active');
			}

			var loadPage = page;
			if(!fwd) {
				topPage--;
				if(topPage < 0) {
					topPage = 0;
				}

				loadPage = topPage;
			}

			var params = { search: search, page: loadPage, order: order };

			if(order === 'random') {
				params.seed = randomSeed;
			}

            if(unarchived) {
                params.unarchived = unarchived;
            }

            if(color) {
                params.color = color;
            }

            if(read !== false) {
                params.read = read;
            }

            function renderResult(result) {
            	var collection = [ ];
				var galleries = result.galleries;
				var topWeight = null;

				$.each(galleries, function(i, gallery) {
					var item = $('.template .gallery-item').clone();
					item.data('gallery', gallery);
                    item.attr("id", "gallery-" + gallery.id);

                    if (gallery.archived == 1) {
                        var url = '?' + $.param({ action: 'gallery', id: gallery.id, index: 0 });
                    } else {
                        var url = 'https://exhentai.org/g/' + gallery.exhenid + '/' + gallery.hash;
                    }

                    if (!!+gallery.read) {
                        $("#read-container", item).addClass("fi-book-bookmark");
                    } else {
                        $("#read-container", item).addClass("fi-book");
                    }

                    $("#read", item).prop("checked", !!+gallery.read);

                    $("#read-container", item).click(function(e) {
                       e.stopPropagation();
                       $("#read", item).trigger("click");
                    });

                    $("#read", item).change(function() {
                        var result = $(this).prop("checked") ? 1 : 0;
                        api("update", {id: gallery.id, readStatus: result}, function(data) {
                            if (data.ret == false) {
                                alert("Error updating read status of gallery.");
                            } else {
                                if (result) {
                                    $("#read-container", item).removeClass("fi-book");
                                    $("#read-container", item).addClass("fi-book-bookmark");
                                } else {
                                    $("#read-container", item).removeClass("fi-book-bookmark");
                                    $("#read-container", item).addClass("fi-book");
                                }
                            }
                        });
                    });

                    $(".color-select", item).val(gallery.color);

                    $(".color-select", item).click(function(e) {
                        e.stopPropagation();
                    });

                    $(".color-select", item).change(function() {
                        var newColor = $(this).val();
                        console.log(newColor);
                        api("updateColor", {id: gallery.id, color: newColor }, function(data) {
                            if (data.ret == false) {
                                alert("There was an error changing the color of this gallery.");
                            } else {
                                $(".top", item).css("background", colorNameToRGBA(newColor));
                            }
                        });
                    });

                    $(item).click(function(e) {
                        window.location.url = url;
                    });

                    $(".top", item).css("background", colorNameToRGBA(gallery.color));

					if (i == 0) {
						item.addClass('page-break');
						item.data('page', loadPage);
					}

                    if(gallery.archived == 0) {
                        item.addClass('unarchived');
                    }

					var source = gallerySourceToName(gallery.source);
					$('.title', item).text("[" + source + "] " + gallery.name);
					$('.date', item).text(gallery.posted_formatted);

					if(gallery.ranked_weight) {
						if(topWeight === null) {
							topWeight = gallery.ranked_weight;
						}

						var pc = Math.round((gallery.ranked_weight / topWeight) * 100);
						$('.weight', item).show().text(pc + '%');
                    } else {
						$('.weight', item).hide();
					}

					if(gallery.thumb) {
						if(gallery.thumb.landscape) {
							item.addClass('landscape');
						}

						item.css({
							backgroundImage: 'url(' + gallery.thumb.url + ')'
						})
					} else {
                        if(gallery.archived == 1) {
                            var url = 'api.php?' + $.param({ action: 'gallerythumb', id: gallery.id, index: 0, type: 1 });
                        } else {
                            var url = 'api.php?' + $.param({ action: 'exgallerythumb', id: gallery.id });
                        }

						item.css({
							backgroundImage: 'url(' + url + ')'
						});
					}

					var tagList = $('.tags', item);
					renderTags(tagList, gallery.tags);

					collection.push(item);
				});

				if(fwd) {
					galleryList.append(collection);
				} else {
					galleryList.prepend(collection);
				}

				if(galleries.length > 0) {
					if(!history.state || history.state.action == 'galleries') {
						var state = buildHistoryState();
						state.data.page = loadPage;
						setHistoryState(true, state);
					}

					if(fwd) {
						page++;
					}
				}

				if(!result.end) {
					$('.load-next').addClass('active');
				} else {
					end = true;
				}

				var displayCount = $('.gallery-item', galleryList).length;
                var totalCount = result.meta.total;

                if(window['Intl'] && window['Intl']['NumberFormat']) {
                    displayCount = Intl.NumberFormat().format(displayCount);
                    totalCount = Intl.NumberFormat().format(totalCount);
                }

				searchCount.show().text('Displaying ' + displayCount + ' of ' + totalCount + ' results');

				if(topPage != 0) {
					$('.load-previous').addClass('active');
				} else {
					$('.load-previous').removeClass('active');
				}

				loadersTop.removeClass('active');
				loadersBottom.removeClass('active');

				loading = false;

				if(fwd && !end) {
					delete preloadedPages[params.page];

					params.page++;
					xhr = api('galleries', params, function(result) {
						preloadedPages[params.page] = result;
					});
				}
            }

            if(preloadedPages[params.page]) {
            	renderResult(preloadedPages[params.page]);
            } else {
            	xhr = api('galleries', params, function(result) {
					renderResult(result);
				});
            }
		}

        galleryList.on('click', '.gallery-item', function() {
            var galleryItem = $(this);
            var gallery = galleryItem.data('gallery');

            if(gallery.archived == 0) {
                var url = 'https://exhentai.org/g/' + gallery.exhenid + '/' + gallery.hash;
                window.open(url);
            } else {
                reader.trigger('loadgallery', [ gallery ]);
            }

            return false;
        });

		function setHistoryState(replace, state) {
			var urlParams = { };
			if(state.data.search) urlParams.search = state.data.search;
			if(state.data.page && state.data.page > 0) urlParams.page = state.data.page;
			if(state.data.order != 'posted') urlParams.order = state.data.order;
            if(state.data.unarchived) urlParams.unarchived = state.data.unarchived;
            if(state.data.read) urlParams.read = state.data.read;
            if(state.data.color) urlParams.color = state.data.color;

			var url = Object.keys(urlParams).length > 0 ? '?' + $.param(urlParams) : '/';

			if(replace) {
                history.replaceState(state, document.title, url);
			} else {
                history.pushState(state, document.title, url);
			}
		}

		function setHistory(replace) {
			var state = buildHistoryState();
			setHistoryState(replace, state);
		}

		function buildHistoryState() {
			var state = { action: 'galleries', data: { search: search, page: page - 1, order: order, unarchived: unarchived, read: read, color: color } };

			if(order === 'random') {
				state.data.seed = randomSeed;
			}

			return state;
		}

		galleryList.on('sethistory', function(e, replace) {
			setHistory(replace);
		});

		searchForm.submit(function() {
			search = $('.search', searchForm).val();
			searchCount.hide();
			galleryList.empty();
			page = 0;
			topPage = 0;
			preloadedPages = { };
			randomiseSeed();
			loadPage(true);
			setHistory(false);

			return false;
		});

		function randomiseSeed() {
			randomSeed = Math.floor(Math.random() * 0x7ffffff).toString(36);
		}

        $('.unarchived').change(function() {
            unarchived = $(this).prop('checked');

            searchForm.submit();
        });

        $('.read-switch').change(function() {
            if ($(this).val() != "false")
            {
               read = $(this).val();
            }
            else
            {
               read = false;
            }

            searchForm.submit();
        });

        $('.color-switch').change(function() {
           if($(this).val() != "false")
           {
               color = $(this).val();
           }
           else
           {
               color = false;
           }

           searchForm.submit();
        });

		$('.input-clear').on('click', function() {
			if(order === 'weight') {
				order = 'posted';
				setOrderLabel();
			}

			$('.search', searchForm).val('');
			searchForm.submit();
		});

		$('.search-order ul li', searchForm).on('click', function() {
			var trigger = $(this);
			order = trigger.data('order');

			var menu = $('.search-order', searchForm);
			$('.label', menu).text(trigger.text());

			var menuOuter = $('.menu-outer', menu);
			menuOuter.hide();
			setTimeout(function() {
				menuOuter.removeAttr('style');
			}, 1);

			searchForm.submit();

			return false;
		});

        $('.toggle-button').on('click', function() {
           if ($('.search-under-options').is(':hidden')) {
               $('.search-under-options').stop(true, true).fadeIn({ duration: 400, queue: false }).css('display', 'none').slideDown(400);
               $('.toggle-button').stop(true, true).animateRotate(-180);
           } else {
               $('.toggle-button').stop(true, true).animateRotate(0);
               $('.search-under-options').stop(true, true).fadeOut({ duration: 400, queue: false }).slideUp(400);
           }

           return false;
        });

		galleryList.on('click', '.tag', function() {
			var tag = $(this);
            var searchTag = tag.data('ns') + ':' + tag.data('tag');
            searchTag = escapeTag(searchTag);

			$('.search').val(searchTag);
			$('.search-form').submit();

			return false;
		});

		function setOrderLabel() {
			var label = $('.search-order .label', searchForm);

			if(order != 'posted' || label.text() != 'Order') {
				var orderOpt = $('.search-order li[data-order="' + order + '"]');
				label.text(orderOpt.text());
			}
		}

		galleryList.on('loadstate', function(e, data) {
			init = true;

			data = $.extend({ search: '', page: 0, order: order }, data);

			search = data.search;
			page = data.page;
			topPage = page;
			order = data.order;
			randomSeed = data.seed;
            unarchived = data.unarchived;
            read = data.read;
            color = data.color;

			if(!randomSeed && order === 'random') {
				randomiseSeed();
			}

			setOrderLabel();
            $('.unarchived').prop('checked', unarchived);
            if (read) {
                $('.read-switch').val(read);
            } else {
                $('.read-switch').val("false");
            }

            if (color) {
                $('.color-switch').val(color);
            } else {
                $('.color-switch').val("false");
            }

			$('.search').val(search);
			searchCount.hide();
			galleryList.empty();
			loadPage(true);

			if(!history.state || history.state.action != 'galleries') {
				setHistory(false);
			}
		});

		galleryList.on('init', function() {
			if(!init) {
				init = true;

				galleryList.trigger('loadstate', [ { page: 0, search: '' } ]);
			}

			if(!history.state || history.state.action != 'galleries') {
				setHistory(false);
			}
		});

		$('.load-previous .inner').click(function() {
			loadPage(false);
		});

		$('.load-next .inner').click(function() {
			loadPage(true);
		});

		var win = $(window);
		var doc = $(document);
		win.scroll(function() {
			if(!end) {
                var winHeight = win.height();
				if(win.scrollTop() + (winHeight * 1.2) >= doc.height()) {
					if(!loading) {
						loadPage(true);
					}
				}
			}
		});

		var pageUpdateProc = null;
		win.scroll(function() {
			clearTimeout(pageUpdateProc);

			if(!history.state || history.state.action == 'galleries') {
				pageUpdateProc = setTimeout(function() {
					if(!history.state || history.state.action == 'galleries') {
						var scroll = win.scrollTop() + win.height();
						var pageBreaks = $('.page-break', galleryList);
						var lastBreak = null;

						for(var i = 0; i < pageBreaks.length; i++) {
							var pageBreak = pageBreaks.eq(i);

							if(pageBreak.position().top > scroll) {
								break;
							}

							lastBreak = i;
						}

						if(lastBreak !== null) {
							var newPage = pageBreaks.eq(lastBreak).data('page');
							var state = history.state;
							state.data.page = newPage;
							setHistoryState(true, state);
						}
					}
				}, 100);
			}
		});
	});

	$('.search').each(function() {
		var input = $(this);
		var keywordXhr = null;
		var list = $('.suggestions');
		var term = null;
		var selectionStart = null;

		this.form.autocomplete = 'off';

		function getTerm() {
			return input.val().slice(0, selectionStart).trim();
		}

		input.keydown(function(e) {
			if(e.keyCode === 38) { //arrow up
				var selected = $('li.active', list);
				if(selected.length > 0) {
					if(selected.is(':not(:first-child)')) {
						selected.removeClass('active').prev().addClass('active');
					}
				} else {
					$('li', list).first().addClass('active');
				}

				return false;
			} else if(e.keyCode === 40) { //arrow down
				var selected = $('li.active', list);
				if(selected.length > 0) {
					if(selected.is(':not(:last-child)')) {
						selected.removeClass('active').next().addClass('active');
					}
				}
				else {
					$('li', list).first().addClass('active');
				}

				return false;
			} else if(e.keyCode === 13) { //enter
				var selected = $('li.active', list);
				if(selected.length > 0) {
					selected.click();
					return false;
				}

                list.empty();
                list.removeClass('active');
			} else if(e.keyCode === 27) { //esc
				list.empty();
				list.removeClass('active');
			}
		});

		input.keyup(function(e) {
			selectionStart = this.selectionStart;
			var newTerm = getTerm();

			if(keywordXhr) {
				keywordXhr.abort();
			}

			if(e.keyCode === 13 || e.keyCode === 27) { //enter, esc

			} else if(newTerm && newTerm.length > 1 && newTerm != term) {
				term = newTerm;

				keywordXhr = api('suggested', { term: term }, function(keywords) {
					list.empty();
					list.removeClass('active');

					if(keywords.length > 0) {
						var termBits = term.split(' ');

						for(var i in keywords) {
							var keyword = keywords[i];
							var itemHtml = keyword;
							var ignoreWord = false;

							for(var x in termBits) {
								var tempTerm = termBits.slice(x).join(' ');
								if(keyword.indexOf(tempTerm) >= 0) {
									if(keyword !== tempTerm) {
										var regex = new RegExp(tempTerm);
										itemHtml = itemHtml.split(regex).join('' + tempTerm + '');
									} else {
										ignoreWord = true;
									}

									break;
								}
							}

							if(!ignoreWord) {
								var li = $('
');
								li.data('keyword', keyword);
								li.html(itemHtml);
								li.appendTo(list);
							}
						}

						if($('> *', list).length > 0) {
							list.addClass('active');
						}
					}
				});
			}
			else if(getTerm() != term) {
				list.empty();
				list.removeClass('active');
			}
		});

		list.on('click', 'li', function() {
			var item = $(this);
			var keyword = item.data('keyword');
			var value = input.val();
			var pre = value.slice(0, selectionStart);

			var keywordBits = keyword.split(' ');
			var preBits = pre.split(' ').reverse();

			var newPre = '';

			for(var i in preBits) {
				if(i === 0) {
					continue;
				}

				var found = false;
				for(var x in keywordBits) {
					if(keywordBits[x].indexOf(preBits[i]) === 0) {
						found = true;
						delete keywordBits[x];
					}
				}

				if(!found) {
					newPre = preBits.slice(i).reverse().join(' ');
					newPre += ' ';
					break;
				}
			}

			newPre += escapeTag(keyword);

			if(newPre) {
				var newValue = newPre + value.slice(selectionStart);

				input.val(newValue);
				list.removeClass('active');
				input.focus();
				$('.search-form').submit();
			}

			return false;
		});

		function closeList() {
			if(keywordXhr) {
				keywordXhr.abort();
			}

			list.removeClass('active');
		}

		input.parent('form').submit(closeList);
	});

	var reader = $('.reader-container');
	reader.each(function() {
		var container = $(this);
		var imageHolder = $('.image-holder', container);
		var thumbsList = $('.gallery-thumbs-outer .thumbs', container);
		var infoContainer = $('.gallery-info', container);
		var preload = $('');
		var gallery = null;
		var currentIndex = 0;
		var firstImage = false;
		var endFlash = $('.end-flash');
		var pagesContainer = $('.pages-container', container);
		var pages = null;
		var scrollProc = null;
		var scrolling = false;
		var configData = getConfig();

		imageHolder.on('load', function() {
			if (this.width > 0 && this.height > 0) {
				var win = $(window);
				var pos = imageHolder.position();

				if (firstImage) {
					if (this.width > win.width()) {
						imageHolder.width(win.width());
					}

					if (this.height > win.height()) {
						imageHolder.width((this.width / this.height) * win.height());
					}

					imageHolder.css({
						left : (win.width() - this.width) / 2,
						top: (win.height() - this.height) / 2
					});

					imageHolder.removeClass('init');

					firstImage = false;
				} else if (this.height > win.height() || pos.top < 0) {
					imageHolder.stop().animate({
						top: 0
					}, Math.abs(pos.top) * 0.7);
				}
			}
			preloadImage(currentIndex + 1);
		});

		function onImageLoad() {
			if(this.width > 0 && this.height > 0) {
				var img = $(this);
				var page = img.parent('.page');
				page.addClass('loaded');
				page.removeClass('loading');
				page.next('.spinner').remove();
			}
			preloadImage(currentIndex + 1);
		}

		function preloadImage(index) {
			if(index < gallery.numfiles) {
				preload.data('index', index);
				preload.prop('src', getImageUrl(index));
			}
		}

		preload.on('load', function() {
			var index = preload.data('index');
			if(!index) {
				index = 0;
			}

            if (mode) {
                // Loads the first three images in MPV instead of preloading them.
                 if((index - currentIndex) <= 3) {
                     loadImage(index, false, false, false, false);
                 }
            }
			preloadImage(index + 1);
		});

		function createSpinner(index) {
			var spinner = $('.template .spinner').clone();
			pages.eq(index).after(spinner);
		}

		function onScroll() {
			var scrollTop = pagesContainer.scrollTop();
			var winHeight = $(window).innerHeight();
			var inView = false;

			pages.each(function(i) {
				var page = pages.eq(i);
				var pageHeight = page.height();

				if(page.hasClass('loaded')) {
					var pos = page.position();

					if(scrollTop < (pos.top + pageHeight)) {
						if(scrollTop >= pos.top) {
							inView = i;
						}

						if((scrollTop + winHeight) >= (pos.top + pageHeight)) {
							var nextPage = page.next('.page');

							if(nextPage.length > 0 && !nextPage.hasClass('loaded') && !nextPage.hasClass('loading')) {
								loadImage(i + 1, false, true, false, true);
                                $('.page-count').text((parseInt(i) + 1) + "/" + gallery.numfiles);
								return false;
							}
						}
					}
				}
			});

			if(inView) {
				currentIndex = inView;
				setHistoryState(inView, true);
			}
		}

		pagesContainer.scroll(function() {
			clearTimeout(scrollProc);

			if(!scrolling) {
				scrollProc = setTimeout(onScroll, 100);
			}
		});

		function getImageUrl(index) {
			var params = { action: 'archiveimage', id: gallery.id, index: index };

            if (!mode) {
                var trueWidth = Math.round(window.devicePixelRatio * window.screen.availWidth);
                if (trueWidth <= 1000) {
                    params.resize = trueWidth;
                }
            }

            if (mode) {
                params.resize = Math.ceil(window.screen.availWidth / 128) * 128;
            }

			return 'api.php?' + $.param(params);
		}

		function scrollToPage(index) {
			scrolling = true;

			var page = pages.eq(index);
			pagesContainer.animate({ scrollTop: page.position().top }, 500, function() {
				scrolling = false;
			});
		}

		function setHistoryState(index, replaceHistory) {
			if(replaceHistory) {
				history.replaceState({ action: 'gallery', data: { gallery: gallery, index: index } }, document.title, '?' + $.param({ action: 'gallery', id: gallery.id, index: index }));
			} else {
				history.pushState({ action: 'gallery', data: { gallery: gallery, index: index } }, document.title, '?' + $.param({ action: 'gallery', id: gallery.id, index: index }));
			}
		}

		function loadImage(index, setHistory, replaceHistory, scroll, updateCurIndex) {
			if(gallery && index < gallery.numfiles && index >= 0) {
                if (!mode) {
                    var url = getImageUrl(index);
                    imageHolder.prop('src', url);
                }

                if (mode) {
                    var page = pages.eq(index);
                    var img = page.find('img');
                    if(!page.hasClass('loading') && !page.hasClass('loaded')) {
                        var preloadIndex = preload.data('index');
                        if (preloadIndex != index) {
                            preload.prop('src', '');
                        }

                        page.addClass('loading');
                        img.prop('src', img.data('src'));

                        if (scroll) {
                            scrollToPage(index);
                        }

                        createSpinner(index);
                    } else {
                        if (scroll) {
                            scrollToPage(index);
                        }
                    }
                }

				if(setHistory) {
					setHistoryState(index, replaceHistory);
				}

                if(updateCurIndex) {
				    currentIndex = index;
                }
			} else if(index >= gallery.numfiles) {
				endFlash.removeClass('transition').addClass('active');

				setTimeout(function() {
					endFlash.addClass('transition').removeClass('active');
				}, 0);
			}
		}

		endFlash.on('transitionend', function() {
			endFlash.removeClass('transition');
		});

		function close() {
            var id = gallery.id;
            var percentRead = ((currentIndex + 1) / gallery.numfiles) * 100;
            if (percentRead >= configData["base"]["autoReadPercentage"]) {
                api("update", {id: gallery.id, readStatus: 1}, function(data) {
                    if (data.ret == false) {
                        alert("Error updating read status of gallery.");
                    } else {
                        $("#gallery-" + id + " #read-container").removeClass("fi-book");
                        $("#gallery-" + id + " #read-container").addClass("fi-book-bookmark");
                    }
                });
            }
			$('html').removeClass('reader-active');
			imageHolder.prop('src', '');
			gallery = null;
			$(window).off('.resize');
			preload.data('index', 0).prop('src', '');
			$('.gallery-list').trigger('init');
			$(document).off('mousewheel.reader');
		}

		$('.close', container).click(close);
		reader.on('close', close);

		$('.gallery-info .tags', container).on('click', '.tag', function() {
			var tag = $(this);
			var searchTag = tag.data('ns') + ':' + tag.data('tag');
            searchTag = escapeTag(searchTag);

			close();

			$('.gallery-list').trigger('loadstate', [ { search: searchTag } ]);
		});

		reader.on('loadstate', function(e, data) {
			if(!gallery || data.gallery.id != gallery.id) {
				loadGallery(data.gallery, data.index);

			} else {
				loadImage(data.index, false, false, false, true);

			}
		});

		function loadGallery(newGallery, index) {
			gallery = newGallery;

			imageHolder.width('auto').height('auto');
			imageHolder.addClass('init');

			$('html').addClass('reader-active');

            if (mode) {
                thumbsList.empty();
                for(var i = 0; i < gallery.numfiles; i++) {
                    var url = 'api.php?' + $.param({ action: 'gallerythumb', id: gallery.id, index: i, type: 2 });

                    var thumb = $('
');
                    thumb.data('index', i);
                    thumb.css({
                        backgroundImage: 'url(' + url + ')'
                    });

                    thumb.appendTo(thumbsList);
                }
            }

			var source = gallerySourceToName(gallery.source);
			$('.title', infoContainer).text("[" + source + "] "+ gallery.name);
            $('.page-count').text((parseInt(index) + 1) + "/" + gallery.numfiles);
			if(gallery.origtitle != gallery.name) {
				$('.origtitle', infoContainer).show().text(gallery.origtitle);
			} else {
				$('.origtitle', infoContainer).hide();
			}

			renderTags($('.tags', infoContainer), gallery.tags);

			index = parseInt(index);
			if(!index || index >= gallery.numfiles) {
				index = 0;
			}

            $('.page-count').text((parseInt(index) + 1) + "/" + gallery.numfiles);

            if (mode) {
                var pagesTarget = $('.inner', pagesContainer);
                pagesTarget.empty();
                for(var i = 0; i < gallery.numfiles; i++) {
                    var page = $('.template .page').clone();
                    var pageImg = $('img', page);
                    var url = getImageUrl(i);
                    pageImg.data('src', url);
                    pageImg.on('load', onImageLoad);
                    $('.index', page).text(i + 1);
                    pagesTarget.append(page);
                }
                pages = $('.page', pagesContainer);
            }

			$('.actions-menu ul li[data-action=\'source\']').text(gallerySourceToName(gallery.source));

			firstImage = true;
			if(history.state && history.state.action != 'gallery') {
				loadImage(index, true, false, false, true);
			} else {
				loadImage(index, true, true, false, true);
			}
		}

        if (!mode) {
            var win = $(window);
            win.on('resize.reader', function() {
                var width = win.width();
                var height = win.height();
                var oldWidth = win.data('oldWidth');
                var oldHeight = win.data('oldHeight');

                if (oldWidth && oldHeight) {
                    imageHolder.css({
                        top: '+=' + ((height - oldHeight) / 2),
                        left: '+=' + ((width - oldWidth) / 2)
                    });
                }

                win.data('oldWidth', width)
                win.data('oldHeight', height);
            });
        }

		container.on('loadgallery', function(e, newGallery, index) {
			loadGallery(newGallery, index);

		});

		$('.control-next').click(function() {
			loadImage(currentIndex + 1, true, false, false, true);
            $('.page-count').text((currentIndex + 1) + "/" + gallery.numfiles);
		});

		$('.control-prev').click(function() {
			loadImage(currentIndex - 1, true, false, false, true);
            $('.page-count').text((currentIndex + 1) + "/" + gallery.numfiles);
		});

		thumbsList.on('click', '.gallery-thumb', function() {
			var index = $(this).data('index');
			if (!mode) {
				loadImage(index, true, false, true, true);
                $('.page-count').text((index + 1) + "/" + gallery.numfiles);
			} else if (mode) {
				loadImage(index, true, false, false, true);
                $('.page-count').text((index + 1) + "/" + gallery.numfiles);
			}
		});

		$(document).on('keyup.reader', 'html.reader-active', function(e) {
			if(e.keyCode === 39) { // right arrow or WAS(D)
				if (!mode) {
					loadImage(currentIndex + 1, true, true, true, true);
                    $('.page-count').text((currentIndex + 1) + "/" + gallery.numfiles);
				} else if (mode) {
					loadImage(currentIndex + 1, true, true, false, true);
                    $('.page-count').text((currentIndex + 1) + "/" + gallery.numfiles);
				}
			}
		});

		$(document).on('keyup.reader', 'html.reader-active', function(e) {
			if(e.keyCode === 37) { // left arrow or W(A)SD
				if (!mode) {
					loadImage(currentIndex - 1, true, true, true, true);
                    $('.page-count').text((currentIndex + 1) + "/" + gallery.numfiles);
				} else if (mode) {
					loadImage(currentIndex - 1, true, true, false, true);
                    $('.page-count').text((currentIndex + 1) + "/" + gallery.numfiles);
				}
			}
		});

		$(document).on('keydown.reader keyup.reader', 'html.reader-active', function(e) {
			if(e.keyCode === 27) { // ESC
				close();
			}
		});

		$('.actions-menu ul li', container).click(function() {
			var trigger = $(this);
			var action = trigger.data('action');

			if(action == 'delete') {
				var key = prompt('Enter access key');
				if(key) {
					api('deletegallery', { id: gallery.id, key: key }, function(data) {
						close();
					});
				}
			} else if(action == 'resize') {
				firstImage = true;
				imageHolder.width('auto').height('auto');
				imageHolder.trigger('load');
			} else if(action == 'download') {
				var url = '/api.php?' + $.param({ action: 'download', id: gallery.id });
				window.open(url);
			} else if(action == 'similar') {
				var tagList = [ ];
				for(var ns in gallery.tags) {
					for(var i in gallery.tags[ns]) {
						var tag = ns + ':' + gallery.tags[ns][i];

						tag = tag.replace('"', '\\\\"');
						tag = '"' + tag + '"';

						tagList.push(tag);
					}
				}

				close();

				var search = tagList.join(' | ');

				$('.gallery-list').trigger('loadstate', [ { search: search, order: 'weight' } ]);
			} else if(action == 'original') {
				if ($('.actions-menu ul li[data-action=\'source\']').text() == 'File') {
					alert('1-' + gallery.id + '.zip');
				} else {
					var url = 'https://exhentai.org/g/' + gallery.exhenid + '/' + gallery.hash;
					window.open(url);
				}
			}

			return false;
		});
	});

	function setupDropdowns() {
		var dropdowns = $('.dropdown-button');

		dropdowns.click(function() {
			$(this).toggleClass('active');
		});

		$(document).click(function(e) {
			if(dropdowns.hasClass('active') && dropdowns.has(e.target).length === 0) {
				dropdowns.removeClass('active');
			}
		});

		$('ul li', dropdowns).click(function() {
			$(this).parents('.dropdown-button').removeClass('active');
		});
	}

	setupDropdowns();

	$(window).on('popstate', function(e) {
		if(e.originalEvent.state) {
			switch(e.originalEvent.state.action) {
				case 'galleries': {
					reader.trigger('close');
					$('.gallery-list').trigger('loadstate', [ e.originalEvent.state.data ]);
					break;
				}
				case 'gallery': {
					reader.trigger('loadstate', [ e.originalEvent.state.data ]);
					break;
				}
			}
		}
	});

	if(window.location.search == '') {
		$('.gallery-list').trigger('init');
	} else {
		var query = decodeQuery();
		if(!query.action || query.action == 'galleries') {
			$('.gallery-list').trigger('loadstate', [ { page: query.page, search: query.search, order: query.order, seed: query.seed, unarchived: query.unarchived, read: query.read, color: query.color } ]);
		} else if(query.action == 'gallery') {
			api('gallery', { id: query.id }, function(gallery) {
				reader.trigger('loadgallery', [ gallery, query.index ])
			});
		}
	}

	function decodeQuery() {
		var ret = {};
		var bits = window.location.search.slice(1).replace(/\+/g, '%20').split('&');
		for(var i in bits)
		{
			var keyvalue = bits[i].split('=');
			ret[decodeURIComponent(keyvalue[0])] = keyvalue.length == 1 ? false : decodeURIComponent(keyvalue[1]);
		}

		return ret;
	}

});


text:
SAS
===

All things SAS related (programs, macros, presentations, etc)

repo_name: scottbass/SAS

repo_language: SAS