From a5690e524998e187a674fe78d702cd93e943cbc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Kutn=C3=BD?= Date: Tue, 7 Mar 2017 12:03:20 +0100 Subject: [PATCH] Asynchronous control rendering trait + js for instant loading --- .gitignore | 3 ++ Makefile | 10 +++++ README.md | 61 ++++++++++++++++++++++++++- bower.json | 14 +++++++ composer.json | 35 ++++++++++++++++ src/UI/AsyncControlLink.php | 46 ++++++++++++++++++++ src/UI/AsyncControlTrait.php | 63 ++++++++++++++++++++++++++++ src/UI/templates/asyncLoadLink.latte | 5 +++ src/assets/async.nette.ajax.js | 24 +++++++++++ 9 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 Makefile create mode 100644 bower.json create mode 100644 composer.json create mode 100644 src/UI/AsyncControlLink.php create mode 100644 src/UI/AsyncControlTrait.php create mode 100644 src/UI/templates/asyncLoadLink.latte create mode 100644 src/assets/async.nette.ajax.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ca60d37 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/vendor +/composer.lock +/composer.phar diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..013a450 --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +run-tests: + make composer.phar + php composer.phar install --no-interaction + vendor/bin/phpstan analyse -l 5 src + +composer.phar: + # Download Composer https://getcomposer.org/download/ + php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" + php composer-setup.php + php -r "unlink('composer-setup.php');" diff --git a/README.md b/README.md index 10886ee..5a2866b 100644 --- a/README.md +++ b/README.md @@ -1 +1,60 @@ -# AsyncControl \ No newline at end of file +# AsyncControl + +Trait for asynchronous control rendering. + +## Usage + +### Trait + +```php +setAsyncRenderer([$this, 'customRender']); +//or +$this->setAsyncRenderer(function () { + //control rendering +}); +``` + +### Template + +```latte +{control comments:async} +``` + +or with custom message + +```latte +{control comments:async 'Show comments'} +``` + +## Configuring + +You can set default message and attributes used for loading link in `bootstrap.php` + +```php + ['btn', 'ajax']]); +``` + +or in application setup + +```neon +services: + application: + setup: + - Pd\AsyncControl\UI\AsyncControlLink::setDefault('Load content', {class: [btn, ajax]}) +``` diff --git a/bower.json b/bower.json new file mode 100644 index 0000000..6f3dbc3 --- /dev/null +++ b/bower.json @@ -0,0 +1,14 @@ +{ + "name": "async.nette.ajax.js", + "homepage": "https://github.com/peckadesign/AsyncControl", + "authors": [ + "PeckaDesign ", + "Vít Kutný " + ], + "main": "src/assets/async.nette.ajax.js", + "license": "MIT", + "dependencies": { + "jquery": ">=1.7", + "nette.ajax.js": ">=2.0" + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..10a73c7 --- /dev/null +++ b/composer.json @@ -0,0 +1,35 @@ +{ + "name": "pd/async-control", + "description": "Trait for asynchronous control rendering", + "keywords": [ + "async", + "control", + "nette" + ], + "homepage": "https://github.com/peckadesign/AsyncControl", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PeckaDesign", + "homepage": "http://www.peckadesign.cz" + }, + { + "name": "Vít Kutný", + "homepage": "https://github.com/vitkutny" + } + ], + "require": { + "php": "~7.0", + "nette/application": "^2.2" + }, + "require-dev": { + "phpstan/phpstan": "~0.6.0" + }, + "autoload": { + "psr-4": { + "Pd\\AsyncControl\\": "src/" + } + } +} diff --git a/src/UI/AsyncControlLink.php b/src/UI/AsyncControlLink.php new file mode 100644 index 0000000..01b5b06 --- /dev/null +++ b/src/UI/AsyncControlLink.php @@ -0,0 +1,46 @@ +message = $message === NULL ? self::$defaultMessage : $message; + $this->attributes = $attributes === NULL ? self::$defaultAttributes : $attributes; + } + + + public static function setDefault(string $message, array $attributes = []) + { + self::$defaultMessage = $message; + self::$defaultAttributes = $attributes; + } + + + public function getMessage(): string + { + return $this->message; + } + + + public function getAttributes(): array + { + return $this->attributes; + } +} diff --git a/src/UI/AsyncControlTrait.php b/src/UI/AsyncControlTrait.php new file mode 100644 index 0000000..4e7679b --- /dev/null +++ b/src/UI/AsyncControlTrait.php @@ -0,0 +1,63 @@ +getPresenter(FALSE)) || ! $presenter->isAjax()) { + return; + } + ob_start(function () { + }); + try { + $this->renderAsync(); + } catch (\Throwable $e) { + ob_end_clean(); + throw $e; + } catch (\Exception $e) { + ob_end_clean(); + throw $e; + } + $content = ob_get_clean(); + $presenter->getPayload()->snippets[$this->getSnippetId('async')] = $content; + $presenter->sendPayload(); + } + + + public function renderAsync(string $linkMessage = NULL, array $linkAttributes = NULL) + { + if ($this instanceof Control && strpos((string) $this->getPresenter()->getParameter(Presenter::SIGNAL_KEY), sprintf('%s-', $this->getUniqueId())) !== 0) { + $template = $this->createTemplate(); + $template->link = new AsyncControlLink($linkMessage, $linkAttributes); + $template->setFile(__DIR__ . '/templates/asyncLoadLink.latte'); + $template->render(); + } elseif (is_callable($this->asyncRenderer)) { + call_user_func($this->asyncRenderer); + } else { + $this->render(); + } + } + + + public function setAsyncRenderer(callable $renderer) + { + $this->asyncRenderer = $renderer; + } +} diff --git a/src/UI/templates/asyncLoadLink.latte b/src/UI/templates/asyncLoadLink.latte new file mode 100644 index 0000000..597da0d --- /dev/null +++ b/src/UI/templates/asyncLoadLink.latte @@ -0,0 +1,5 @@ +
+ + {$link->getMessage()|translate} + +
diff --git a/src/assets/async.nette.ajax.js b/src/assets/async.nette.ajax.js new file mode 100644 index 0000000..178bc93 --- /dev/null +++ b/src/assets/async.nette.ajax.js @@ -0,0 +1,24 @@ +(function ($) { + $.nette.ext({ + init: function () { + this.init(); + }, + success: function () { + this.init(); + } + }, { + init: function () { + $('[data-async]').each(function () { + var $this = $(this); + if ($this.data('asyncInitialized')) { + return; + } + $this.data('asyncInitialized', true); + $.nette.ajax({ + url: $this.data('asyncLink') || $this.attr('href'), + off: ['history', 'unique'] + }); + }); + } + }); +})(window.jQuery);