Skip to content

Commit

Permalink
Implement Modal Dialogs (#71)
Browse files Browse the repository at this point in the history
* Implement basic reloading for #51

* Apply fixes from StyleCI

* Add functionality in order to reload in-place

* Apply fixes from StyleCI

* Include <script> when calling reload call-back.

* Implement beforeRender and beforeOutput hooks.

* Implemented $app->terminate(output)

* cleanup $app->add(), although i think perhaps we should remove this??

* track application execution state.

* Add comments and constructor for CallBack (supports defaults)

* Add documentation for callbacks.

* add documentation for app into index.

* Add CallbackLater which is not executed immediatelly.

* Refactor jsReload to use callbackLater - more reliable.

* Add test-suite for callbacks.

* Add documentation for Reloading.

* Apply fixes from StyleCI

* add field->jsInput() method + docs

* Added really cool demo with counter containers.

* Apply fixes from StyleCI

* remove stopPropagation and preventDefault from default events

* fix test to reflect our update with the propagation

* Allow callback to pass argument.

* Implemented VirtualPage

* added trigger for modal dialogs

* added demo page.

* Apply fixes from StyleCI

* Add link to new demo.

* add VirtualPage::set() so that we can move code to callback

* be more reasonable with random data amount.

* pass VirtualPage object instead of URL for sexy syntax.

* Add another example with clickable table columns.

* imply ability to click on table with mouse pointer.

* Apply fixes from StyleCI

* Fix timezone warning. Update version to 1.1

* Apply fixes from StyleCI
  • Loading branch information
romaninsh authored and DarkSide666 committed Mar 20, 2017
1 parent cbdb51b commit 70ee2f7
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 8 deletions.
5 changes: 4 additions & 1 deletion demos/init.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<?php

date_default_timezone_set('UTC');

require '../vendor/autoload.php';

$app = new \atk4\ui\App('Agile UI v0.4 - Demo Suite', ['icon'=>'user']);
$app = new \atk4\ui\App('Agile UI v1.1 - Demo Suite', ['icon'=>'user']);

$app->initLayout((isset($_GET['layout']) && $_GET['layout'] === 'centered') ? 'Centered' : 'Admin');

Expand Down Expand Up @@ -31,6 +33,7 @@
$basic = $layout->leftMenu->addGroup(['Interactivity', 'icon'=>'talk']);
$basic->addItem('JavaScript Events', ['button2']);
$basic->addItem('Element Reloading', ['reloading']);
$basic->addItem('Modal Dialogs', ['modal']);

$f = basename($_SERVER['PHP_SELF']);

Expand Down
63 changes: 63 additions & 0 deletions demos/modal.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

require 'init.php';
// Re-usable component implementing counter
class Counter extends \atk4\ui\FormField\Line
{
public $content = 20; // default

public function init()
{
parent::init();

$this->actionLeft = new \atk4\ui\Button(['icon'=> 'minus']);
$this->action = new \atk4\ui\Button(['icon'=> 'plus']);

$this->actionLeft->js('click', $this->jsInput()->val(new \atk4\ui\jsExpression('parseInt([])-1', [$this->jsInput()->val()])));
$this->action->js('click', $this->jsInput()->val(new \atk4\ui\jsExpression('parseInt([])+1', [$this->jsInput()->val()])));
}
}

// Test 1 - Basic reloading
$layout->add(['Header', 'Virtual Page Logic']);

$vp = $layout->add('VirtualPage'); // this page will not be visible unless you trigger it specifically
$vp->add(['Header', 'Contens of your pop-up here']);
$vp->add(['LoremIpsum', 'size'=>2]);
$vp->add(new Counter());

$bar = $layout->add('Buttons');
$bar->add('Button')->set('Go to Virtual Page')->link($vp->getURL());
$bar->add('Button')->set('Open in pop-up mode')->link($vp->getURL('popup'));
$bar->add('Button')->set('Open in cut-out mode')->link($vp->getURL('cut'));

$layout->add(['Header', 'Actual pop-ups']);

$bar = $layout->add('Buttons');
$bar->add('Button')->set('Open in pop-up mode')->on('click', new \atk4\ui\jsExpression('window.open([], "", "width=800,height=500")', [$vp->getURL('popup')]));
$bar->add('Button')->set('Load in Modal')->on('click', new \atk4\ui\jsModal('My Popup Title', $vp->getURL('cut')));

$bar->add('Button')->set('Load slowly in Modal')->on('click', new \atk4\ui\jsModal('My Popup Title', $vp->getURL('cut').'&slow=true'));
if (isset($_GET['slow'])) {
sleep(1);
}

$layout->add(['Header', 'Modal when you click on table row']);
$t = $layout->add(['Table', 'celled'=>true]);
$t->setModel(new SomeData());

$frame = $layout->add('VirtualPage');
$frame->set(function ($frame) {
$frame->add(['Header', 'Clicked row with ID = '.$_GET['id']]);
});

$t->on('click', 'tr', new \atk4\ui\jsModal(
'Row Clicked',
new \atk4\ui\jsExpression(
'[]+"&id="+[]', [
$frame->getURL('cut'),
(new \atk4\ui\jQuery(new \atk4\ui\jsExpression('this')))->data('id'),
]
)
));
$t->addStyle('cursor', 'pointer');
2 changes: 1 addition & 1 deletion demos/somedatadef.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Persistence_Faker extends \atk4\data\Persistence
{
public $faker = null;

public $count = 50;
public $count = 10;

public function __construct($opts = [])
{
Expand Down
14 changes: 10 additions & 4 deletions src/Callback.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ class Callback
*/
public $POST_trigger = false;

/**
* Contains either false if callback wasn't triggered or the value passed
* as an argument to a call-back:.
*
* e.g. following URL of getURL('test') will result in $triggered = 'test';
*/
public $triggered = false;

/**
Expand Down Expand Up @@ -72,13 +78,13 @@ public function set($callback, $args = [])

if ($this->POST_trigger) {
if (isset($_POST[$this->name])) {
$this->triggered = true;
$this->triggered = $_POST[$this->name];

return call_user_func_array($callback, $args);
}
} else {
if (isset($_GET[$this->name])) {
$this->triggered = true;
$this->triggered = $_GET[$this->name];

return call_user_func_array($callback, $args);
}
Expand All @@ -90,12 +96,12 @@ public function set($callback, $args = [])
*
* @return string
*/
public function getURL()
public function getURL($arg = 'callback')
{
if ($this->POST_trigger) {
return $_SERVER['REQUEST_URI'];
}

return $this->app->url([$this->name=>'callback']);
return $this->app->url([$this->name=>$arg]);
}
}
89 changes: 89 additions & 0 deletions src/VirtualPage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

namespace atk4\ui;

/**
* Virtual page normally does not render, yet it has it's own trigger and will respond
* to the trigger in a number of useful way depending on trigger's argument:.
*
* - cut = will only output HTML of this VirtualPage and it's sub-elements
* - popup = will add VirtualPage directly into body, ideal for pop-up windows
* - normal = will get rid of all the normal components inside Layout's content replacing them
* the render of this page. Will preserve menus and top bar but that's it.
*/
class VirtualPage extends View
{
public $cb = null;

public $fx = [];

public function init()
{
parent::init();

$this->cb = $this->add('CallbackLater');

$this->cb->set(function () {
if ($this->cb->triggered && $this->fx) {
foreach ($this->fx as $fx) {
$fx($this);
}
}

if ($this->cb->triggered == 'cut') {
$this->app->terminate($this->render());
}

if ($this->cb->triggered == 'popup') {
$this->ui = 'container'; // to maintain some gaps..
$this->app->html->template->set('title', $this->app->title);
$this->app->html->template->setHTML('Content', parent::getHTML());
$this->app->html->template->appendHTML('HEAD', $this->getJS());

$this->app->terminate($this->app->html->template->render());
}

// Remove all elements from inside the Content
foreach ($this->app->layout->elements as $key => $view) {
if ($view instanceof View && $view->region == 'Content') {
unset($this->app->layout->elements[$key]);
}
}

$this->app->layout->template->setHTML('Content', parent::getHTML());
$this->app->layout->_js_actions = array_merge($this->app->layout->_js_actions, $this->_js_actions);

$this->app->html->template->setHTML('Content', $this->app->layout->getHTML());
$this->app->html->template->appendHTML('HEAD', $this->app->layout->getJS());

$this->app->terminate($this->app->html->template->render());
});
}

public function set($fx = [], $junk = null)
{
if (!$fx) {
return;
}
if (!is_array($fx)) {
$fx = [$fx];
}
$this->fx = $fx;

return $this;
}

public function getURL($mode = 'callback')
{
return $this->cb->getURL($mode);
}

/**
* VirtualPage is not rendered normally. It's invisible. Only when
* it is triggered, it will exclusively output
* it's content.
*/
public function getHTML()
{
}
}
35 changes: 35 additions & 0 deletions src/jsModal.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

namespace atk4\ui;

/**
* This class generates action, that will be able to loop-back to the callback method.
*/
class jsModal extends jsExpression
{
public function __construct($title, $url)
{
if ($url instanceof VirtualPage) {
$url = $url->getURL('cut');
}

$content = '
<i class="close icon"></i>
<div class="header">
'.htmlspecialchars($title).'
</div>
<div class="image content">
<div class="ui active inverted dimmer">
<div class="ui text loader">Loading</div>
</div>
</div>
';

parent::__construct('
var m=$("<div>").appendTo("body").addClass("ui fullscreen scrolling modal").html([content]);
m.modal({onHide: function() { m.children().remove(); return true; }}).modal("show").find(".content").load([url], function() { m.modal("refresh"); })',
['content'=>$content, 'url'=>$url]);
}
}
2 changes: 0 additions & 2 deletions tests/CallbackTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ public function testCallbackNotFiring()
$cb = $app->add('Callback');

// don't simulate triggering

$cb->set(function ($x) use (&$var) {
$var = $x;
}, [34]);
Expand Down Expand Up @@ -102,7 +101,6 @@ public function testCallbackLaterNotFiring()
$cb = $app->add('CallbackLater');

// don't simulate triggering

$cb->set(function ($x) use (&$var) {
$var = $x;
}, [34]);
Expand Down

0 comments on commit 70ee2f7

Please sign in to comment.