Created
December 9, 2010 21:10
-
-
Save fprochazka/735345 to your computer and use it in GitHub Desktop.
Inteligent Head JS (http://headjs.com/) loading component
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace Kdyby\Component; | |
use Nette; | |
use Nette\String; | |
use Nette\Web\Html; | |
use Kdyby; | |
/** | |
* @author Filip Procházka <hosiplan@kdyby.org> | |
*/ | |
class Headjs extends Kdyby\Control\LookoutControl | |
{ | |
const PACKAGE_FULL = 'head'; | |
const PACKAGE_MIN = 'head.min'; | |
const PACKAGE_LOAD = 'head.load.min'; | |
const EXECUTE_SEQUENCE = 'sequence'; | |
const EXECUTE_PARALEL = 'paralel'; | |
/** @var string */ | |
private $dir; | |
/** @var array */ | |
private $files = array(); | |
/** @var array */ | |
private $printed = array(); | |
/** @var bool */ | |
private $loaded = FALSE; | |
/** @var string */ | |
private $package; | |
/** @var Nette\Caching\Cache */ | |
private $cache; | |
/** | |
* @param Nette\Caching\Cache $cache | |
*/ | |
public function setCache(Nette\Caching\Cache $cache) | |
{ | |
$this->cache = $cache; | |
} | |
/** | |
* @return Nette\Caching\Cache | |
*/ | |
public function getCache() | |
{ | |
return $this->cache; | |
} | |
/** | |
* @param string $package | |
*/ | |
public function setPackage($package) | |
{ | |
$this->package = $package; | |
} | |
/** | |
* @return string | |
*/ | |
public function getPackage() | |
{ | |
return $this->package; | |
} | |
/** | |
* @param string $dir | |
*/ | |
public function setJavascriptDir($dir) | |
{ | |
$this->dir = $dir; | |
} | |
/** | |
* @return string | |
*/ | |
public function getJavascriptDir() | |
{ | |
return $this->dir; | |
} | |
/** | |
* @param string $file | |
*/ | |
public function addScript($file) | |
{ | |
$this->files[] = $file; | |
} | |
public function viewDefault($file1 = NULL, $file2 = NULL, $file3 = NULL) | |
{ | |
$files = func_get_args(); | |
$package = $this->package ?: self::PACKAGE_MIN; | |
$this->renderHtml($this->dir . '/' . $package . ".js", $files); | |
} | |
public function viewLoad($file1 = NULL, $file2 = NULL, $file3 = NULL) | |
{ | |
$files = func_get_args(); | |
$package = $this->package ?: self::PACKAGE_MIN; | |
$this->renderHtml($this->dir . '/' . $package . ".js", $files); | |
} | |
/** | |
* @param string $file | |
* @return boolean | |
*/ | |
protected function isRelative($file) | |
{ | |
return !String::match($file, '~^[a-z0-9]{1,5}:\/\/.+~i'); | |
} | |
/** | |
* @param string $string | |
* @return boolean | |
*/ | |
protected function isClosure($string) | |
{ | |
return String::match($string, '~^\s*?function\s*?\(\s*?\)\s*?\{.*?\}\s*?$~i'); | |
} | |
/** | |
* @param string $src | |
* @param array $files | |
*/ | |
protected function renderHtml($src, $files) | |
{ | |
if (!$this->loaded) { | |
echo $this->renderLoad($src), "\n"; | |
$this->loaded = TRUE; | |
} | |
$files = array_diff(array_merge($this->files, $files), $this->printed); | |
if ($files) { | |
if (count($files) === 1 && $this->isClosure(reset($files))) { | |
trigger_error(__CLASS__.": won't process function when have no files to load!", E_USER_WARNING); | |
} | |
if (!$this->cache || !isset($this->cache[$files])) { | |
$init = $this->renderInit($files)."\n"; | |
if ($this->cache && !isset($this->cache[$files])) { | |
$this->cache[$files] = $init; | |
} | |
} else { | |
$init = $this->cache[$files]; | |
} | |
$this->printed = array_merge($this->printed, $files); | |
echo $init; | |
} | |
} | |
/** | |
* @param string $src | |
* @return string | |
*/ | |
protected function renderLoad($src) | |
{ | |
$script = Html::el('script'); | |
$script->type = 'text/javascript'; | |
$script->src = $src; | |
return (string)$script; | |
} | |
/** | |
* @param array $files | |
* @param string $execute | |
* @return string | |
*/ | |
protected function renderInit(array $files, $execute = self::EXECUTE_SEQUENCE) | |
{ | |
$script = Html::el('script'); | |
$script->type = 'text/javascript'; | |
$script->src = NULL; | |
if ($execute === self::EXECUTE_SEQUENCE) { | |
$chain = array(); | |
foreach ($files as $file) { | |
if ($this->isClosure($file)) { | |
$chain[] = trim($file); | |
} else { | |
$chain[] = '"'. ($this->isRelative($file) ? $this->dir.'/'.$file : $file) .'"'; | |
} | |
} | |
$script->setHtml("\n\thead.js(".implode(', ', $chain).");\n"); | |
} else { | |
$chain = NULL; | |
foreach ($files as $file) { | |
$file = $this->isRelative($file) ? $this->dir . '/' . $file : $file; | |
$chain .= '.js("'.$file.'")'; | |
} | |
$script->setHtml("\n\thead".$chain.";\n"); | |
} | |
return (string)$script; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// this class is required for smooth run of Headjs component | |
namespace Kdyby\Control; | |
use Nette; | |
use Nette\String; | |
class LookoutControl extends Nette\Application\Control | |
{ | |
/** @var string */ | |
private $view; | |
/** @var array */ | |
private $renderParams = array(); | |
/** @var array */ | |
private static $methods = array(); | |
/** | |
* @return array | |
*/ | |
public function getRenderParams() | |
{ | |
return $this->renderParams; | |
} | |
/** | |
* @return string | |
*/ | |
public function getView() | |
{ | |
return $this->view; | |
} | |
/** | |
* @param string $type | |
* @param mixed $param | |
* @return string | |
*/ | |
final public function render($type = NULL, $param = NULL) | |
{ | |
$class = get_class($this); | |
if (!isset(self::$methods[$class])) { | |
self::$methods[$class] = get_class_methods($this); | |
} | |
$this->view = $this->view ?: 'default'; | |
$this->renderParams = $this->renderParams ?: func_get_args(); | |
$viewMethod = 'view' . ucfirst($this->view); | |
if (in_array('beforeRender', self::$methods[$class])) { | |
call_user_func_array(array($this, 'beforeRender'), $this->renderParams); | |
} | |
$dir = dirname($this->reflection->fileName); | |
$view = lcfirst($this->view); | |
$templates = array( | |
$dir . '/' . $view . '.latte', | |
$dir . '/' . $view . '.phtml' | |
); | |
foreach ($templates as $file){ | |
if (file_exists($file)) { | |
$this->template->setFile($file); | |
break; | |
} | |
} | |
ob_start(); | |
call_user_func_array(array($this, $viewMethod), $this->renderParams); | |
$output = ob_get_clean(); | |
if (!$output && file_exists($file)) { // raw output from function | |
$output = (string)$this->template; | |
} | |
echo $output; | |
if (in_array('afterRender', self::$methods[$class])) { | |
call_user_func_array(array($this, 'afterRender'), $this->renderParams); | |
} | |
$this->view = NULL; | |
$this->renderParams = array(); | |
} | |
/** | |
* Calls self::render($view, $args) instead of nonexisting render<view>($args) methods | |
* @param string $method | |
* @param array $args | |
* @return mixed | |
*/ | |
public function __call($method, $args) | |
{ | |
if (String::startsWith($method, 'render')) { | |
$this->view = substr($method, 6); | |
$this->renderParams = $args; | |
return call_user_func(array($this, 'render')); | |
} | |
return parent::__call($method, $args); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment