diff --git a/.gitmodules b/.gitmodules
index 7749162..9403b01 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,3 @@
[submodule "addons"]
path = addons
- url = ./addons
+ url = https://github.com/atk4/atk4-addons.git
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9e8402e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,16 @@
+# sink
+Kitchen Sink Project for Agile Toolkit 4.3 - Demonstration of various features.
+
+## Recommend a good example
+
+Struggling with implementing something? Ask on forum and if your
+problem is common, we will also add the solution here.
+
+https://forum.agiletoolkit.org
+
+## Add example yourself
+
+Fork this repository and create pull request implementing new feature.
+Use this as example:
+
+https://github.com/atk4/sink/pull/3
diff --git a/admin/lib/Admin.php b/admin/lib/Admin.php
index 0b322e4..a19763c 100755
--- a/admin/lib/Admin.php
+++ b/admin/lib/Admin.php
@@ -26,20 +26,23 @@ function init() {
}
function initLayout(){
parent::initLayout();
- $this->page_object->add('View_ForkMe');
+ if(!$_GET['cut_page'])$this->page_object->add('View_ForkMe');
}
function initBasic(){
$sm = $this->api->menu->addMenu('Core Features');
- $sm ->addMenuItem('core/hello', 'Hello World');
- $sm ->addMenuItem('core/form', 'Basic Form');
+ $sm ->addItem('Hello World', 'core/hello');
+ $sm ->addItem('Basic Form', 'core/form');
+ $sm ->addItem('Validation', 'core/validation');
+ $sm ->addItem('Virtual Page', 'core/vp');
$sm = $this->api->menu->addMenu('JavaScript');
- $sm ->addMenuItem('js/timepicker', 'TimePicker');
- $sm ->addMenuItem('js/boys-n-girls', 'Boys and Girls');
+ $sm ->addItem('TimePicker', 'js/timepicker');
+ $sm ->addItem('Boys and Girls', 'js/boys-n-girls');
+ $sm ->addItem('Dog and Cat', 'js/dog-n-cat');
$sm = $this->api->menu->addMenu('Agile Data');
$sm->addItem('.. vs Slick 3.1.0 (scala)','db/slick');
@@ -47,12 +50,12 @@ function initBasic(){
$sm = $this->api->menu->addMenu('Real-time components');
- $sm ->addMenuItem('realtime/console', 'Real-time console');
+ $sm ->addItem('Real-time console', 'realtime/console');
$sm = $this->api->menu->addMenu('Miscelanious');
- $sm ->addMenuItem('misc/alert-button', 'Alert Button');
- $sm ->addMenuItem('misc/virtual-pages', 'Virtual Pages');
+ $sm ->addItem('Alert Button', 'misc/alert-button');
+ $sm ->addItem('Virtual Pages', 'misc/virtual-pages');
try {
$this->dbConnect();
diff --git a/admin/page/core/validation.php b/admin/page/core/validation.php
new file mode 100644
index 0000000..f21ba32
--- /dev/null
+++ b/admin/page/core/validation.php
@@ -0,0 +1,153 @@
+add('View_Hint')->set('This example clarifies the usage of the validation hooks in ATK 4.3+');
+
+ $t = $this->add('Tabs');
+
+ $t->addTabURL('./submit','onSubmit');
+ $t->addTabURL('./validator','validator');
+ $t->addTabURL('./validator2','validator2');
+ $t->addTabURL('./validator3','validator3');
+ $t->addTabURL('./callback','callback');
+ $t->addTabURL('./class','class');
+ }
+
+ /**
+ * This demonstrates backwards-compatible validation on submit.
+ * http://book.agiletoolkit.org/views/form/validation.html#form-validation-examples
+ *
+ * Although documentation is using older method displayFieldError(),
+ * which should be updated to simply error()
+ */
+ function page_submit() {
+ $f = $this->add('Form');
+ $f->addField('large_number');
+ $f->addField('mandatory');
+ $f->addField('mandatory2')->validateNotNull();
+ $f->addSubmit();
+
+ $f->onSubmit(function($f){
+ if($f['large_number']<1000)return $f->error('large_number','is not large enough');
+ if(!$f['mandatory'])return $f->error('mandatory','write something here');
+ return 'all good';
+ });
+ }
+
+ /**
+ * This takes advantage of a new "validator" class, which is described here
+ * http://book.agiletoolkit.org/controller/validator.html
+ *
+ * We are using field->validate() method, which basically will associate
+ * validation string with the field
+ */
+ function page_validator() {
+ $f = $this->add('Form');
+ $f->addField('large_number')->validate('>1000?is not large enough');
+ $f->addField('mandatory')->validate('required');
+ $f->addField('mandatory2')->validateNotNull();
+ $f->addSubmit();
+
+ $f->onSubmit(function($f){
+ return 'all good';
+ });
+ }
+
+ /**
+ * This also uses Controller_Validator, but calls it through $form->validate()
+ * This method allows you to define multiple rules with a single call and is
+ * directly passed to is(). Also when calling through validate(), this
+ * also binds validation to 'validate' hook.
+ */
+ function page_validator2() {
+ $f = $this->add('Form');
+ $f->addField('large_number');
+ $f->addField('mandatory');
+ $f->addField('mandatory2')->validateNotNull();
+
+ $f->validate([
+ 'large_number|>1000?is not large enough',
+ 'mandatory|required'
+ ]);
+
+ $f->addSubmit();
+
+ $f->onSubmit(function($f){
+ return 'all good';
+ });
+ }
+
+ /**
+ * This approach uses validator manually, and performs validation from onSubmit
+ * method, but still uses the Controller_Validator. I recommend that you
+ * use validator/validator2 approach.
+ */
+ function page_validator3() {
+ $f = $this->add('Form');
+ $f->addField('large_number');
+ $f->addField('mandatory');
+ $f->addField('mandatory2')->validateNotNull();
+
+
+ $f->addSubmit();
+
+ $f->onSubmit(function($f){
+ $f->add('Controller_Validator')->is([
+ 'large_number|>1000?is not large enough',
+ 'mandatory|required'
+ ])->now();
+
+ return 'all good';
+ });
+ }
+
+ /**
+ * Controller_Validator also supports your own callbacks, like below.
+ * I am also using post-validate hook for my manual call-back, because
+ * it's what validate() method uses.
+ */
+ function page_callback() {
+ $f = $this->add('Form');
+ $f->addField('large_number')->validate(function($v,$a){ if($a<1000)$v->fail('is not large enough'); });
+ $f->addField('mandatory');
+ $f->addHook('post-validate', function($f){
+ if(!$f['mandatory'])
+ $f->error('mandatory','write something here');
+
+ /*
+ * also works, but longer
+ throw $this->exception('write something here','ValidityCheck')
+ ->setField('mandatory');
+ */
+ });
+ $f->addField('mandatory2')->validateField(function($f){ if(!$f->get())return 'must not be null'; });
+ $f->addSubmit();
+
+ $f->onSubmit(function($f){
+ return 'all good';
+ });
+ }
+
+ /**
+ * This demonstrates how validation works in a custom class, with redefining
+ * performValidation method().
+ */
+ function page_class() {
+ $f = $this->add('Form');
+ $f->addField('LargeNumber','large_number');
+ $f->addField('mandatory');
+ $f->addField('mandatory2')->validateNotNull();
+ $f->addSubmit();
+
+ $f->onSubmit(function($f){
+ return 'all good';
+ });
+ }
+}
+
+class Form_Field_LargeNumber extends Form_Field_Line {
+ function performValidation() {
+ if($this->get()<1000) $this->form->error($this->short_name,'too small');
+ }
+}
diff --git a/admin/page/js/dogncat.php b/admin/page/js/dogncat.php
new file mode 100644
index 0000000..068852e
--- /dev/null
+++ b/admin/page/js/dogncat.php
@@ -0,0 +1,33 @@
+add('View_Box')->set('Nothing');
+
+ if($_GET['dog'])$vm->set('It is the dog');
+ if($_GET['cat'])$vm->set('It is the cat');
+
+ $button=$this->add('Button');
+ $button->set('Dog');
+ $button->on('click',$vm->js()->reload(['dog'=>true]));
+
+ $button=$this->add('Button');
+ $button->set('Cat');
+ $button->on('click',$vm->js()->reload(['cat'=>true]));
+
+ }
+}
diff --git a/admin/page/misc/virtualpages.php b/admin/page/misc/virtualpages.php
index e19b5c0..c1d1fcc 100644
--- a/admin/page/misc/virtualpages.php
+++ b/admin/page/misc/virtualpages.php
@@ -5,7 +5,81 @@ class page_misc_virtualpages extends Page {
function init() {
parent::init();
- $this->add('View_Info')->set('This is main page');
+
+ // Demo 1
+ $this->add('View_Info')->set('You can get the manual URL of a virtual page and use it as you wish');
+
+ $vp = $this->add('VirtualPage');
+ $vp->set(function($p){
+ $p->add('View_Info')->set('you are now on a virtual page');
+ });
+
+ $this->add('Button')->link($vp->getURL());
+
+ // Demo 2
+
+ $this->add('HR');
+
+ $this->add('View_Info')->set('VirtualPage does not normally render, but you can add it into various views for
+ som added effects. For example if you add $vp into a Button, you can use click() method. The second button will only respond if you move your mouse cursor directly over the icon');
+
+ $this->add('Button')->set('Button 1')->add('VirtualPage')->bindEvent()->set(function($p){
+ $p->add('View_Info')->set('Clicked button 1');
+ });
+
+ $this->add('Button')->set(['Button 2','icon'=>'check'])->add('VirtualPage')->bindEvent('Mouseovered the icon?','mouseenter','.icon-check')->set(function($p){
+ $p->add('View_Info')->set('Hovered icon of Button 2');
+ });
+
+ $this->add('HR');
+
+ // Demo 3
+
+ $this->add('View_Info')->set('VirtualPage is also integrated into other views in Agile Toolkit. For example on() event uses Virtual Page for doing call-backs.');
+
+ // Call-back is funneled into enternal VirtualPage.
+ $this->add('Button')->set('click me')->on('click',function($b){ return $b->fadeOut('slow'); });
+
+ $this->add('Button')->set(['hover my icon', 'icon'=>'check'])->on('mouseleave','.icon-check',function($b){ return $b->fadeOut('slow'); });
+
+ // Another example is Real-time Console that also uses Virtual Page.
+
+ $this->add('HR');
+
+ // Demo 4
+
+ $this->add('View_Info')->set('As the previous example(s) use custom events and custom selectors, we can now combine virtual page with grid');
+
+ $gr = $this->add('SampleGrid');
+ $gr->addColumn('button','test1');
+ if(isset($_GET['test1']))$this->js()->univ()->successMessage('Old-style buttons on a grid require checking of _GET argument and executing. ID='.$_GET['test1'])->execute();
+
+
+ $gr->addColumn('template','test2')->setTemplate('');
+ $gr->on('click', '.test2', function($js, $data){ return $js->univ()->successMessage('With on() and virtual page, we know id='.$data['id']); });
+
+
+ $vp = $this->add('VirtualPage');
+ $gr->addColumn('template','test3')->setTemplate('');
+ $gr->on('click', '.test3')->univ()->dialogURL('Dialog here', [ $vp->getURL(), 'id'=>$this->js()->_selectorThis()->data('id')]);
+ $vp->set(function($p){
+ $p->add('View_Info')->set('Using virtual page we can now get id='.$_GET['id']);
+ });
+
+
+ $vp = $gr->add('VirtualPage');
+ $vp->addColumn('test4','Delete', ['icon'=>'trash']);
+ $gr->js(true)->_selector('.pb_test4')->addClass('atk-swatch-red');
+ $vp->set(function($p){
+ $p->add('View_Info')->set('A more integrated way to get id='.$p->id);
+ });
+
+
+ $this->add('HR');
+
+ // Demo 5
+
+ $this->add('View_Info')->set('Virtual pages are used to create page within a page. Here you see a button, that opens a "virtual page" that does not have an URL of its own, but will be triggered by a view and will take over rendering, when the dialog is displayed.');
$vp1 = $this->add('VirtualPage','vp1');
$vp1->set(function ($p1) {
@@ -20,5 +94,29 @@ function init() {
});
$this->add('Button')->set('Open Virtual Page1')->js('click')->univ()->frameURL('Page 1',$vp1->getURL(),['width'=>500,'height'=>300]);
+
+
+
+
+ }
+
+
+
+}
+
+class SampleGrid extends Grid {
+ function init(){
+ parent::init();
+
+ $m = $this->add('Model');
+ $m->addField('name');
+ $m->addField('surname');
+ $m->setSource('Array',[
+ ['name'=>'Vinny', 'surname'=>'Sihra'],
+ ['name'=>'Zoe', 'surname'=>'Shatwell'],
+ ['name'=>'Darcy', 'surname'=>'Wild'],
+ ]);
+
+ $this->setModel($m);
}
}
diff --git a/composer.json b/composer.json
index f379e09..b55a76f 100755
--- a/composer.json
+++ b/composer.json
@@ -1,7 +1,7 @@
{
"type":"project",
"require":{
- "atk4\/atk4":"dev-master",
+ "atk4\/atk4":"*",
"educoder\/pest":"1.0.0"
},
"autoload":{
diff --git a/composer.lock b/composer.lock
index e70a3e9..bb14d01 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,21 +4,21 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "cc1e5c868abb597ea8dfce72da8a4e39",
- "content-hash": "7948fc81034b786f3e24890de05c9906",
+ "hash": "62d5a4a89ba821f1b8296ab15dd52087",
+ "content-hash": "7f252e95e6df21b877b8ff39b785f2a2",
"packages": [
{
"name": "atk4/atk4",
- "version": "dev-master",
+ "version": "4.3.2",
"source": {
"type": "git",
"url": "https://github.com/atk4/atk4.git",
- "reference": "443f110e1f08d81d3785a0f9da18f42da69c297e"
+ "reference": "0eb774a28165db5cca5b0520851d212f11ade6f9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/atk4/atk4/zipball/443f110e1f08d81d3785a0f9da18f42da69c297e",
- "reference": "443f110e1f08d81d3785a0f9da18f42da69c297e",
+ "url": "https://api.github.com/repos/atk4/atk4/zipball/0eb774a28165db5cca5b0520851d212f11ade6f9",
+ "reference": "0eb774a28165db5cca5b0520851d212f11ade6f9",
"shasum": ""
},
"type": "library",
@@ -39,7 +39,7 @@
"atk4",
"framework"
],
- "time": "2016-02-04 18:10:53"
+ "time": "2016-02-29 12:21:49"
},
{
"name": "educoder/pest",
@@ -87,9 +87,7 @@
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
- "stability-flags": {
- "atk4/atk4": 20
- },
+ "stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
diff --git a/docs/database.sql b/docs/database.sql
index 684ed97..1502dd1 100644
--- a/docs/database.sql
+++ b/docs/database.sql
@@ -74,15 +74,6 @@ VALUES
UNLOCK TABLES;
-/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
-/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
-/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
-/*!40101 SET NAMES utf8 */;
-/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
-/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
-/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
-
-
# Dump of table item
# ------------------------------------------------------------
@@ -190,13 +181,6 @@ UNLOCK TABLES;
-/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
-/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
-/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
-/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
-/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
-
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;