Version 5.1 - All the GraphQL #32
@ -36,11 +36,6 @@ class CSSMin extends BaseMin {
|
|||||||
$this->group = $groups[$group];
|
$this->group = $groups[$group];
|
||||||
$this->last_modified = $this->get_last_modified();
|
$this->last_modified = $this->get_last_modified();
|
||||||
|
|
||||||
$this->requested_time = $this->get_if_modified();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __destruct()
|
|
||||||
{
|
|
||||||
$this->send();
|
$this->send();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,11 +46,10 @@ class CSSMin extends BaseMin {
|
|||||||
*/
|
*/
|
||||||
protected function send()
|
protected function send()
|
||||||
{
|
{
|
||||||
/*if($this->last_modified >= $this->requested_time)
|
if($this->last_modified >= $this->get_if_modified() && $this->is_not_debug())
|
||||||
{
|
{
|
||||||
header('304 Not Modified');
|
throw new FileNotChangedException();
|
||||||
die();
|
}
|
||||||
}*/
|
|
||||||
|
|
||||||
$css = ( ! array_key_exists('debug', $_GET))
|
$css = ( ! array_key_exists('debug', $_GET))
|
||||||
? $this->compress($this->get_css())
|
? $this->compress($this->get_css())
|
||||||
@ -70,7 +64,7 @@ class CSSMin extends BaseMin {
|
|||||||
* @param string $buffer
|
* @param string $buffer
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function compress($buffer)
|
protected function compress($buffer)
|
||||||
{
|
{
|
||||||
//Remove CSS comments
|
//Remove CSS comments
|
||||||
$buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
|
$buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
|
||||||
@ -142,7 +136,7 @@ class CSSMin extends BaseMin {
|
|||||||
|
|
||||||
// Correct paths that have changed due to concatenation
|
// Correct paths that have changed due to concatenation
|
||||||
// based on rules in the config file
|
// based on rules in the config file
|
||||||
// $css = str_replace($this->path_from, $this->path_to, $css);
|
$css = str_replace($this->path_from, $this->path_to, $css);
|
||||||
|
|
||||||
return $css;
|
return $css;
|
||||||
}
|
}
|
||||||
@ -152,20 +146,16 @@ class CSSMin extends BaseMin {
|
|||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function output($css)
|
protected function output($css)
|
||||||
{
|
{
|
||||||
//This GZIPs the CSS for transmission to the user
|
$etag = md5($css);
|
||||||
//making file size smaller and transfer rate quicker
|
|
||||||
ob_start("ob_gzhandler");
|
|
||||||
|
|
||||||
header("Content-Type: text/css; charset=utf8");
|
if ($etag === $this->get_if_none_match() && $this->is_not_debug())
|
||||||
header("Cache-control: public, max-age=691200, must-revalidate");
|
{
|
||||||
header("Last-Modified: ".gmdate('D, d M Y H:i:s', $this->last_modified)." GMT");
|
throw new FileNotChangedException();
|
||||||
header("Expires: ".gmdate('D, d M Y H:i:s', (filemtime(basename(__FILE__)) + 691200))." GMT");
|
}
|
||||||
|
|
||||||
echo $css;
|
$this->send_final_output($css, 'text/css', $this->last_modified, $etag);
|
||||||
|
|
||||||
ob_end_flush();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,6 +167,18 @@ class CSSMin extends BaseMin {
|
|||||||
$config = require('../app/config/minify_config.php');
|
$config = require('../app/config/minify_config.php');
|
||||||
$groups = require($config['css_groups_file']);
|
$groups = require($config['css_groups_file']);
|
||||||
|
|
||||||
|
if ( ! array_key_exists($_GET['g'], $groups))
|
||||||
|
{
|
||||||
|
throw new InvalidArgumentException('You must specify a css group that exists');
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
new CSSMin($config, $groups);
|
new CSSMin($config, $groups);
|
||||||
|
}
|
||||||
|
catch (FileNotChangedException $e)
|
||||||
|
{
|
||||||
|
BaseMin::send304();
|
||||||
|
}
|
||||||
|
|
||||||
//End of css.php
|
//End of css.php
|
@ -44,48 +44,42 @@ class JSMin extends BaseMin {
|
|||||||
$this->cache_file = "{$this->js_root}cache/{$group}";
|
$this->cache_file = "{$this->js_root}cache/{$group}";
|
||||||
$this->last_modified = $this->get_last_modified();
|
$this->last_modified = $this->get_last_modified();
|
||||||
|
|
||||||
$this->requested_time = $this->get_if_modified();
|
|
||||||
|
|
||||||
$this->cache_modified = (is_file($this->cache_file))
|
$this->cache_modified = (is_file($this->cache_file))
|
||||||
? filemtime($this->cache_file)
|
? filemtime($this->cache_file)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
|
||||||
|
|
||||||
public function __destruct()
|
|
||||||
{
|
|
||||||
// Output some JS!
|
// Output some JS!
|
||||||
$this->send();
|
$this->send();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function send()
|
protected function send()
|
||||||
{
|
{
|
||||||
// If the browser's cached version is up to date,
|
// Override caching if debug key is set
|
||||||
// don't resend the file
|
if($this->is_debug_call())
|
||||||
/*if($this->last_modified === $this->requested_time)
|
|
||||||
{
|
|
||||||
header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified');
|
|
||||||
exit();
|
|
||||||
}*/
|
|
||||||
|
|
||||||
//Determine what to do: rebuild cache, send files as is, or send cache.
|
|
||||||
// If debug is set, just concatenate
|
|
||||||
if(array_key_exists('debug', $_GET))
|
|
||||||
{
|
{
|
||||||
return $this->output($this->get_files());
|
return $this->output($this->get_files());
|
||||||
}
|
}
|
||||||
else if($this->cache_modified < $this->last_modified)
|
|
||||||
|
// If the browser's cached version is up to date,
|
||||||
|
// don't resend the file
|
||||||
|
if($this->last_modified >= $this->get_if_modified() && $this->is_not_debug())
|
||||||
|
{
|
||||||
|
throw new FileNotChangedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
if($this->cache_modified < $this->last_modified)
|
||||||
{
|
{
|
||||||
$js = $this->minify($this->get_files());
|
$js = $this->minify($this->get_files());
|
||||||
|
|
||||||
//Make sure cache file gets created/updated
|
//Make sure cache file gets created/updated
|
||||||
if (file_put_contents($this->cache_file, $js) === FALSE)
|
if (file_put_contents($this->cache_file, $js) === FALSE)
|
||||||
{
|
{
|
||||||
die('Cache file was not created. Make sure you have the correct folder permissions.');
|
echo 'Cache file was not created. Make sure you have the correct folder permissions.';
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->output($js);
|
return $this->output($js);
|
||||||
}
|
}
|
||||||
// Otherwise, send the cached file
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return $this->output(file_get_contents($this->cache_file));
|
return $this->output(file_get_contents($this->cache_file));
|
||||||
@ -185,7 +179,7 @@ class JSMin extends BaseMin {
|
|||||||
* @param string $js
|
* @param string $js
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function minify($js)
|
protected function minify($js)
|
||||||
{
|
{
|
||||||
$options = [
|
$options = [
|
||||||
'output_info' => 'errors',
|
'output_info' => 'errors',
|
||||||
@ -218,19 +212,14 @@ class JSMin extends BaseMin {
|
|||||||
*/
|
*/
|
||||||
protected function output($js)
|
protected function output($js)
|
||||||
{
|
{
|
||||||
//This GZIPs the js for transmission to the user
|
$etag = md5($js);
|
||||||
//making file size smaller and transfer rate quicker
|
|
||||||
ob_start('ob_gzhandler');
|
|
||||||
|
|
||||||
// Set important caching headers
|
if (($etag === $this->get_if_none_match()) && ! $this->is_debug_call())
|
||||||
header('Content-Type: application/javascript; charset=utf8');
|
{
|
||||||
header('Cache-control: public, max-age=691200, must-revalidate');
|
throw new FileNotChangedException();
|
||||||
header('Last-Modified: '.gmdate('D, d M Y H:i:s', $this->last_modified).' GMT');
|
}
|
||||||
header('Expires: '.gmdate('D, d M Y H:i:s', (filemtime(__FILE__) + 691200)).' GMT');
|
|
||||||
|
|
||||||
echo $js;
|
$this->send_final_output($js, 'application/javascript', $this->last_modified, $etag);
|
||||||
|
|
||||||
ob_end_flush();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,11 +238,16 @@ if ( ! is_dir($cache_dir))
|
|||||||
|
|
||||||
if ( ! array_key_exists($_GET['g'], $groups))
|
if ( ! array_key_exists($_GET['g'], $groups))
|
||||||
{
|
{
|
||||||
header('Content-Type: application/javascript; charset=utf8');
|
throw new InvalidArgumentException('You must specify a js group that exists');
|
||||||
echo '// You must specify a group that exists';
|
|
||||||
die();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
new JSMin($config, $groups);
|
new JSMin($config, $groups);
|
||||||
|
}
|
||||||
|
catch (FileNotChangedException $e)
|
||||||
|
{
|
||||||
|
BaseMin::send304();
|
||||||
|
}
|
||||||
|
|
||||||
//end of js.php
|
//end of js.php
|
@ -18,7 +18,7 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
$.get('/public/templates/anime-ajax-search-results.html', tempHtml => {
|
$.get('/public/templates/anime-ajax-search-results.html', tempHtml => {
|
||||||
$('#search').on('keypress', AnimeClient.throttle(250, function(e) {
|
AnimeClient.on('#search', 'keypress', AnimeClient.throttle(250, function(e) {
|
||||||
let query = encodeURIComponent($(this).val());
|
let query = encodeURIComponent($(this).val());
|
||||||
if (query === '') {
|
if (query === '') {
|
||||||
return;
|
return;
|
||||||
|
@ -34,12 +34,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// okay, lets actually make some changes!
|
// okay, lets actually make some changes!
|
||||||
$.ajax({
|
AnimeClient.ajax(AnimeClient.url('/anime/update'), {
|
||||||
data: data,
|
data: data,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
mimeType: 'application/json',
|
mimeType: 'application/json',
|
||||||
url: AnimeClient.url('/anime/update'),
|
|
||||||
success: (res) => {
|
success: (res) => {
|
||||||
if (res.status === 'completed') {
|
if (res.status === 'completed') {
|
||||||
$(this).closest('article, tr').hide();
|
$(this).closest('article, tr').hide();
|
||||||
|
70
public/js/base/ajax.js
Normal file
70
public/js/base/ajax.js
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
AnimeClient = (function (ac) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Url encoding for non-get requests
|
||||||
|
*
|
||||||
|
* @param data
|
||||||
|
* @returns {string}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
function serialize(data) {
|
||||||
|
let pairs = [];
|
||||||
|
|
||||||
|
Object.keys(data).forEach((name) => {
|
||||||
|
let value = data[name].toString();
|
||||||
|
|
||||||
|
name = encodeURIComponent(name);
|
||||||
|
value = encodeURIComponent(value);
|
||||||
|
|
||||||
|
pairs.push(`${name}=${value}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
return pairs.join("&");
|
||||||
|
};
|
||||||
|
|
||||||
|
ac.ajax = function(url, config) {
|
||||||
|
// Set some sane defaults
|
||||||
|
config = config || {};
|
||||||
|
config.data = config.data || {};
|
||||||
|
config.type = config.type || 'GET';
|
||||||
|
config.dataType = config.dataType || 'json';
|
||||||
|
config.success = config.success || ac.noop;
|
||||||
|
config.error = config.error || ac.noop;
|
||||||
|
|
||||||
|
let request = new XMLHttpRequest();
|
||||||
|
let method = String(config.type).toUpperCase();
|
||||||
|
|
||||||
|
request.open(method, url);
|
||||||
|
|
||||||
|
request.onreadystatechange = () => {
|
||||||
|
if (request.readyState === 4) {
|
||||||
|
if (request.status > 400) {
|
||||||
|
config.error.call(request.statusText, request.statusText, request.response);
|
||||||
|
} else {
|
||||||
|
config.success.call(request.responseText, request.response, request.responseText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (method) {
|
||||||
|
case "GET":
|
||||||
|
request.send(null);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
|
||||||
|
request.send(serialize(config.data));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ac.get = function(url, data, callback) {
|
||||||
|
return ac.ajax(url, {
|
||||||
|
data: data,
|
||||||
|
success: callback
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return ac;
|
||||||
|
|
||||||
|
})(AnimeClient);
|
@ -1,8 +1,39 @@
|
|||||||
const AnimeClient = (function($, w) {
|
var AnimeClient = (function(w) {
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const slice = Array.prototype.slice;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
/**
|
||||||
|
* Placeholder function
|
||||||
|
*/
|
||||||
|
noop: () => {},
|
||||||
|
/**
|
||||||
|
* DOM selector
|
||||||
|
*
|
||||||
|
* @param {string} selector - The dom selector string
|
||||||
|
* @param {object} context
|
||||||
|
* @return {array} - arrau of dom elements
|
||||||
|
*/
|
||||||
|
$(selector, context) {
|
||||||
|
if (typeof selector != "string" || selector === undefined) {
|
||||||
|
return selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
context = (context != null && context.nodeType === 1)
|
||||||
|
? context
|
||||||
|
: document;
|
||||||
|
|
||||||
|
let elements = [];
|
||||||
|
if (selector.match(/^#([\w]+$)/)) {
|
||||||
|
elements.push(document.getElementById(selector.split('#')[1]));
|
||||||
|
} else {
|
||||||
|
elements = slice.apply(context.querySelectorAll(selector));
|
||||||
|
}
|
||||||
|
|
||||||
|
return elements;
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* Scroll to the top of the Page
|
* Scroll to the top of the Page
|
||||||
*
|
*
|
||||||
@ -71,4 +102,4 @@ const AnimeClient = (function($, w) {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
})(Zepto, window);
|
})(window);
|
41
public/js/base/event.js
Normal file
41
public/js/base/event.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
AnimeClient = (function (ac) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
function add(sel, event, listener) {
|
||||||
|
// Recurse!
|
||||||
|
if (! event.match(/^([\w\-]+)$/)) {
|
||||||
|
event.split(' ').forEach((evt) => {
|
||||||
|
add(sel, evt, listener);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
sel.addEventListener(event, listener, false);
|
||||||
|
}
|
||||||
|
function delegate(sel, target, event, listener) {
|
||||||
|
// Attach the listener to the parent
|
||||||
|
add(sel, event, (e) => {
|
||||||
|
// Get live version of the target selector
|
||||||
|
ac.$(target, sel).forEach((element) => {
|
||||||
|
if(e.target == element) {
|
||||||
|
listener.call(element, e);
|
||||||
|
e.stopPropagation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ac.on = function (sel, event, target, listener) {
|
||||||
|
if (arguments.length === 3) {
|
||||||
|
listener = target;
|
||||||
|
ac.$(sel).forEach((el) => {
|
||||||
|
add(el, event, listener);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ac.$(sel).forEach((el) => {
|
||||||
|
delegate(el, target, event, listener);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ac;
|
||||||
|
})(AnimeClient);
|
@ -1,13 +1,13 @@
|
|||||||
/**
|
/**
|
||||||
* Event handlers
|
* Event handlers
|
||||||
*/
|
*/
|
||||||
(($) => {
|
((ac) => {
|
||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Close event for messages
|
// Close event for messages
|
||||||
$('header').on('click', '.message', function() {
|
ac.on('header', 'click', '.message', function () {
|
||||||
$(this).hide();
|
this.setAttribute('hidden', 'hidden');
|
||||||
});
|
});
|
||||||
|
|
||||||
})(Zepto);
|
})(AnimeClient);
|
@ -25,13 +25,12 @@
|
|||||||
// Update the total count
|
// Update the total count
|
||||||
data[type + "s_read"] = ++completed;
|
data[type + "s_read"] = ++completed;
|
||||||
|
|
||||||
$.ajax({
|
AnimeClient.ajax(AnimeClient.url('/manga/update'), {
|
||||||
data: data,
|
data: data,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
type: 'POST',
|
type: 'POST',
|
||||||
mimeType: 'application/json',
|
mimeType: 'application/json',
|
||||||
url: AnimeClient.url('/manga/update'),
|
success: (res) => {
|
||||||
success: (res, status) => {
|
|
||||||
parent_sel.find(`.${type}s_read`).text(completed);
|
parent_sel.find(`.${type}s_read`).text(completed);
|
||||||
AnimeClient.showMessage('success', `Sucessfully updated ${manga_name}`);
|
AnimeClient.showMessage('success', `Sucessfully updated ${manga_name}`);
|
||||||
AnimeClient.scrollToTop();
|
AnimeClient.scrollToTop();
|
||||||
|
@ -30,18 +30,89 @@ while($i < $pia_len)
|
|||||||
$i = $j + 1;
|
$i = $j + 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class FileNotChangedException extends \Exception {}
|
||||||
class BaseMin {
|
class BaseMin {
|
||||||
public function get_if_modified()
|
|
||||||
|
/**
|
||||||
|
* Get value of the if-modified-since header
|
||||||
|
*
|
||||||
|
* @return int - timestamp to compare for cache control
|
||||||
|
*/
|
||||||
|
protected function get_if_modified()
|
||||||
{
|
{
|
||||||
return (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER))
|
return (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER))
|
||||||
? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])
|
? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])
|
||||||
: time();
|
: time();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function get_if_none_match()
|
/**
|
||||||
|
* Get value of etag to compare to hash of output
|
||||||
|
*
|
||||||
|
* @return string - the etag to compare
|
||||||
|
*/
|
||||||
|
protected function get_if_none_match()
|
||||||
{
|
{
|
||||||
return (array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER))
|
return (array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER))
|
||||||
? $_SERVER['HTTP_IF_NONE_MATCH']
|
? $_SERVER['HTTP_IF_NONE_MATCH']
|
||||||
: '';
|
: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether or not to send debug version
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
protected function is_not_debug()
|
||||||
|
{
|
||||||
|
return ! $this->is_debug_call();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether or not to send debug version
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
protected function is_debug_call()
|
||||||
|
{
|
||||||
|
return array_key_exists('debug', $_GET);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send actual output to browser
|
||||||
|
*
|
||||||
|
* @param string $content - the body of the response
|
||||||
|
* @param string $mime_type - the content type
|
||||||
|
* @param int $last_modified - the last modified date
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function send_final_output($content, $mime_type, $last_modified, $etag)
|
||||||
|
{
|
||||||
|
//This GZIPs the CSS for transmission to the user
|
||||||
|
//making file size smaller and transfer rate quicker
|
||||||
|
ob_start("ob_gzhandler");
|
||||||
|
|
||||||
|
$expires = $last_modified + 691200;
|
||||||
|
$last_modified_date = gmdate('D, d M Y H:i:s', $last_modified);
|
||||||
|
$expires_date = gmdate('D, d M Y H:i:s', $expires);
|
||||||
|
|
||||||
|
header("Content-Type: {$mime_type}; charset=utf8");
|
||||||
|
header("Cache-control: public, max-age=691200, must-revalidate");
|
||||||
|
header("Etag: {$etag}");
|
||||||
|
header("Last-Modified: {$last_modified_date} GMT");
|
||||||
|
header("Expires: {$expires_date} GMT");
|
||||||
|
|
||||||
|
echo $content;
|
||||||
|
|
||||||
|
ob_end_flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a 304 Not Modified header
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function send304()
|
||||||
|
{
|
||||||
|
header("status: 304 Not Modified", true, 304);
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user