SlideShare ist ein Scribd-Unternehmen logo
1 von 74
Downloaden Sie, um offline zu lesen
Instant
Dynamic Forms
      with
             #states
Konstantin Käfer
                   2




    2006
#states   3
4
Anatomy of a state
                                                         5




$form['payment_information'] = array(
   '#type' => 'fieldset',
   '#title' => t('Payment information'),
   '#collapsible' => TRUE,
   '#collapsed' => TRUE,
   '#states' => array(
     'expanded' => array(
        '[name="payment"]' => array('checked' => TRUE)
      ),
   ),
);
Anatomy of a state
                                                         5




$form['payment_information'] = array(
   '#type' => 'fieldset',
   '#title' => t('Payment information'),
   '#collapsible' => TRUE,
   '#collapsed' => TRUE,
   '#states' => array(
     'expanded' => array(
        '[name="payment"]' => array('checked' => TRUE)
      ),
   ),
);
Anatomy of a state
                                                         5




$form['payment_information'] = array(
   '#type' => 'fieldset',
   '#title' => t('Payment information'),
   '#collapsible' => TRUE,
   '#collapsed' => TRUE,
   '#states' => array(
     'expanded' => array(
        '[name="payment"]' => array('checked' => TRUE)
      ),
   ),
);
Anatomy of a state
                                                         5




$form['payment_information'] = array(
   '#type' => 'fieldset',
   '#title' => t('Payment information'),
   '#collapsible' => TRUE,
   '#collapsed' => TRUE,
   '#states' => array(
     'expanded' => array(
        '[name="payment"]' => array('checked' => TRUE)
      ),
   ),
);
Anatomy of a state
                                                         5




$form['payment_information'] = array(
   '#type' => 'fieldset',
   '#title' => t('Payment information'),
   '#collapsible' => TRUE,
   '#collapsed' => TRUE,
   '#states' => array(
     'expanded' => array(
        '[name="payment"]' => array('checked' => TRUE)
      ),
   ),
);
Anatomy of a state
                                                         5




$form['payment_information'] = array(
   '#type' => 'fieldset',
   '#title' => t('Payment information'),
   '#collapsible' => TRUE,
   '#collapsed' => TRUE,
   '#states' => array(
     'expanded' => array(
        '[name="payment"]' => array('checked' => TRUE)
      ),
   ),
);
Anatomy of a state
                                                         5




$form['payment_information'] = array(
   '#type' => 'fieldset',
   '#title' => t('Payment information'),
   '#collapsible' => TRUE,
   '#collapsed' => TRUE,
   '#states' => array(
     'expanded' => array(
        '[name="payment"]' => array('checked' => TRUE)
      ),
   ),
);
Anatomy of a state
                                                         5




$form['payment_information'] = array(
   '#type' => 'fieldset',
   '#title' => t('Payment information'),
   '#collapsible' => TRUE,
   '#collapsed' => TRUE,
   '#states' => array(
     'expanded' => array(
        '[name="payment"]' => array('checked' => TRUE)
      ),
   ),
);
Declarative definition
                                                    6


'expanded' => array(
   '[name="payment"]' => array('checked' => TRUE)
),



 ➜ Expanded when the element “payment”
   is checked
Dependencies
                                                         7


$form['payment_information'] = array(...
   '#states' => array(
     'expanded' => array(
        '[name="payment"]' => array('checked' => TRUE)
      ),
   ),
);
                      <fieldset>

           Depends on           Influences


           <input type="checkbox">
Targeting elements
                                                8


◆   Uses plain CSS selectors with jQuery
◆ [name="payment"]
    #edit-payment
    .payment :checkbox, #edit-payment




◆   Don’t use #selector for auto-assigned IDs
States
                                           9


◆   Arbitrary names are possible
◆   visible    irrelevant      confirmed
    checked    valid           important


◆   Prefixing with ! negates
◆   visible = !invisible
    invisible = !visible
State aliases
                                                     10


◆   Associate custom aliases              Primary
                                           name
◆   Drupal.states.State.aliases
      ['unimportant'] = '!important';


◆ enabled = !disabled       invisible = !visible
    invalid = !valid        untouched = !touched
    optional = !required    filled = !empty
    unchecked = !checked    irrelevant = !relevant
    expanded = !collapsed   readwrite = !readonly
Drawbacks
                                 11


◆   Doesn’t support OR and XOR
Drawbacks
                                       11


◆   Doesn’t !
         chsupport OR and XOR
      Pat
              drupal.org/node/735528
AND operator
                                        12


'disabled' => array(

     '[name="ccv"]' => array(
       'invalid' => TRUE
     ),


     '[name="card_number"]' => array(
       'invalid' => TRUE
     ),

),
OR operator
                                        13


'disabled' => array(
   array(
     '[name="ccv"]' => array(
        'invalid' => TRUE
      ),
   ),
   array(
     '[name="card_number"]' => array(
        'invalid' => TRUE
      ),
   ),
),
OR operator
                                        13


'disabled' => array(
   array(
     '[name="ccv"]' => array(
        'invalid' => TRUE
      ),
   ),     Numeric keys
   array(
     '[name="card_number"]' => array(
        'invalid' => TRUE
      ),
   ),
),
XOR operator
                                        14


'disabled' => array('xor',
   array(
     '[name="ccv"]' => array(
        'invalid' => TRUE
      ),
   ),
   array(
     '[name="card_number"]' => array(
        'invalid' => TRUE
      ),
   ),
),
XOR operator
                                             14


'disabled' => array('xor',        Operator
   array(
     '[name="ccv"]' => array(
        'invalid' => TRUE
      ),
   ),
   array(
     '[name="card_number"]' => array(
        'invalid' => TRUE
      ),
   ),
),
Drawbacks
                                       15


◆   Doesn’t !
         chsupport OR and XOR
      Pat
              drupal.org/node/735528
Drawbacks
                                       15


◆   Doesn’t !
         chsupport OR and XOR
      Pat
              drupal.org/node/735528

◆   Doesn’t support radio buttons
Drawbacks
                                       15


◆   Doesn’t !
         chsupport OR and XOR
      Pat
              drupal.org/node/735528

◆   Doesn’t support radio buttons
          end!
      E xt
Triggers
Default Triggers
                                       17


Drupal.states.Trigger.states = {
   ...
   checked: {
     'change': function () {
        return this.attr('checked');
      }
   },
   ...
};
Default Triggers
                                       17


Drupal.states.Trigger.states = {
   ...
   checked: {   Native DOM event
     'change': function () {
        return this.attr('checked');
      }
   },
   ...
};
Default Triggers
                                       17


Drupal.states.Trigger.states = {
   ...
   checked: {
     'change': function () {
        return this.attr('checked');
      }
   },
   ...
};
Default Triggers
                                       17


Drupal.states.Trigger.states = {
   ...
   checked: {
     'change': function () {
        return this.attr('checked');
      }
   },
   ...
};           Value function
Default Triggers
                                                                              18


Initialization                         Execution
Drupal.states.Trigger.states = {       Drupal.states.Trigger.states = {
   ...                                    ...
   checked: {                             checked: {
     'change': function () {                'change': function () {
        return this.attr('checked');           return this.attr('checked');
      }                                      }
   },                                     },
   ...                                    ...
};                                     };



$('#element').bind('change',           $('#element').bind('change',
   function() {                           function() {
     ...                                    ...
   }                                      }
);                                     );
Default Triggers
                                                                              18


Initialization                         Execution
Drupal.states.Trigger.states = {       Drupal.states.Trigger.states = {
   ...                                    ...
   checked: {                             checked: {
     'change': function () {                'change': function () {
        return this.attr('checked');           return this.attr('checked');
      }                                      }
   },                                     },
   ...                                    ...
};                                     };



$('#element').bind('change',           $('#element').bind('change',
   function() {                           function() {
     ...                                    ...
   }                                      }
);                                     );
Default Triggers
                                                                              18


Initialization                         Execution
Drupal.states.Trigger.states = {       Drupal.states.Trigger.states = {
   ...                                    ...
   checked: {                             checked: {
     'change': function () {                'change': function () {
        return this.attr('checked');           return this.attr('checked');
      }                                      }
   },                                     },
   ...                                    ...
};                                     };



$('#element').bind('change',           $('#element').bind('change',
   function() {                           function() {
     ...                                    ...
   }                                      }
);                                     );
Multiple Triggers
                                   19


Drupal.states.Trigger.states = {
   ...
   value: {
     'keyup': function () {
        return this.val();
      },
     'change': function () {
        return this.val();
      }
   },
   ...
};
Multiple Triggers
                                     20


Drupal.states.Trigger.states = {
   ...
   value: {
     'keyup change': function () {
        return this.val();
      }
   },
   ...
};
Custom Triggers
                                                     21


'#states' => array(
   'disabled' => array(
     '[name="delayed"]' => array('value' => 'foo')
   ),
),
Custom Triggers
                                                    22


Drupal.states.Trigger.states.delayedValue =
  function(element) {
    var value = element.val(), oldValue, timeout;
    var trigger = function() {
      if (oldValue !== value) {
         element.trigger({
           type: 'state:delayedValue',
           value: value,
           oldValue: oldValue
         });
         oldValue = value;
       }
    };

    ...
  };
Custom Triggers
                                                    22


Drupal.states.Trigger.states.delayedValue =
  function(element) {
    var value = element.val(), oldValue, timeout;
    var trigger = function() {
      if (oldValue !== value) {
         element.trigger({
           type: 'state:delayedValue',
           value: value,
           oldValue: oldValue
         });
         oldValue = value;
       }
    };

    ...
  };
Custom Triggers
                                                    22


Drupal.states.Trigger.states.delayedValue =
  function(element) {
    var value = element.val(), oldValue, timeout;
    var trigger = function() {
      if (oldValue !== value) {
         element.trigger({
           type: 'state:delayedValue',
           value: value,
           oldValue: oldValue
         });
         oldValue = value;
       }
    };

    ...
  };
Custom Triggers
                                                    22


Drupal.states.Trigger.states.delayedValue =
  function(element) {
    var value = element.val(), oldValue, timeout;
    var trigger = function() {
      if (oldValue !== value) {
         element.trigger({
           type: 'state:delayedValue',
           value: value,
           oldValue: oldValue
         });
         oldValue = value;
       }
    };

    ...
  };
Custom Triggers
                                                    22


Drupal.states.Trigger.states.delayedValue =
  function(element) {
    var value = element.val(), oldValue, timeout;
    var trigger = function() {
      if (oldValue !== value) {
         element.trigger({
           type: 'state:delayedValue',
           value: value,
           oldValue: oldValue
         });
         oldValue = value;
       }
    };

    ...
  };
Custom Triggers
                                                     23


Drupal.states.Trigger.states.delayedValue =
  function(element) {
    ...

       element.bind('keyup change', function (e) {
         if (timeout) clearTimeout(timeout);
         timeout = setTimeout(function() {
           value = element.val();
           trigger();
         }, 1000);
       });

       Drupal.states.postponed.push(trigger);
  };
Custom Triggers
                                                     23


Drupal.states.Trigger.states.delayedValue =
  function(element) {
    ...

       element.bind('keyup change', function (e) {
         if (timeout) clearTimeout(timeout);
         timeout = setTimeout(function() {
           value = element.val();
           trigger();
         }, 1000);
       });

       Drupal.states.postponed.push(trigger);
  };
Custom Triggers
                                                     23


Drupal.states.Trigger.states.delayedValue =
  function(element) {
    ...

       element.bind('keyup change', function (e) {
         if (timeout) clearTimeout(timeout);
         timeout = setTimeout(function() {
           value = element.val();
           trigger();
         }, 1000);
       });

       Drupal.states.postponed.push(trigger);
  };
Custom Triggers
                                                     23


Drupal.states.Trigger.states.delayedValue =
  function(element) {
    ...

       element.bind('keyup change', function (e) {
         if (timeout) clearTimeout(timeout);
         timeout = setTimeout(function() {
           value = element.val();
           trigger();
         }, 1000);
       });

       Drupal.states.postponed.push(trigger);
  };
Custom Triggers
                                                     23


Drupal.states.Trigger.states.delayedValue =
  function(element) {
    ...

       element.bind('keyup change', function (e) {
         if (timeout) clearTimeout(timeout);
         timeout = setTimeout(function() {
           value = element.val();
           trigger();
         }, 1000);
       });

       Drupal.states.postponed.push(trigger);
  };
Custom Triggers
                                              24


Drupal.states.Trigger.states.toggle =
  function(element) {
    var value = true, oldValue = undefined;
    var trigger = function() {
       value = !value;
       element.trigger({
         type: 'state:toggle',
         value: value,
         oldValue: oldValue
       });
       oldValue = value;
    };

    setInterval(trigger, 1000);
     Drupal.states.postponed.push(trigger);
  };
Comparisons
Comparisons
                                                         26


$form['payment_information'] = array(
   ...
   '#states' => array(
     'expanded' => array(
        '[name="payment"]' => array('checked' => TRUE)
      ),
   ),
);
Comparisons
                                                         26


$form['payment_information'] = array(
   ...
   '#states' => array(
     'expanded' => array(
        '[name="payment"]' => array('checked' => TRUE)
      ),
   ),                                      ===
);
Advanced Comparisons
                                               27


states.Dependant.comparisons = {
   'RegExp': function (reference, value) {
     return reference.test(value);
   },
   'Function': function (reference, value) {
     return reference(value);
   }
};
Advanced Comparisons
                                               27


states.Dependant.comparisons = {
   'RegExp': function (reference, value) {
     return reference.test(value);
   },
   'Function': function (reference, value) {
     return reference(value);
   }
};
       Prototype name
JSON only allows
strings and numbers   28
:(   29
Advanced Comparisons
                                                      30


'invalid' => array(
   '[name="card_number"]' => array(
     '!value' => '0000 0000 0000 0000',
   ),
),


'invalid' => array(
   '[name="card_number"]' => array(
     '!value' => array('regex' => '^(d{4}[ -]*){4}$'),
   ),
),
Advanced Comparisons
                                                      30


'invalid' => array(
   '[name="card_number"]' => array(
     '!value' => '0000 0000 0000 0000',
   ),
),


'invalid' => array(
   '[name="card_number"]' => array(
     '!value' => array('regex' => '^(d{4}[ -]*){4}$'),
   ),
),
Advanced Comparisons
                                                       31


Drupal.states.Dependant.comparisons.Object =
  function(reference, value) {
    if ('regex' in reference) {
       return RegExp(reference.regex, ↵
                       reference.flags).test(value);
     }
    else {
       return reference.indexOf(value) !== false;
     }
  };
Advanced Comparisons
                                                      32




'invalid' => array(
   '[name="card_number"]' => array(
     '!value' => array('regex' => '^(d{4}[ -]*){4}$'),
   ),
),
Transitions
State changes
                                               34


◆   Transition an element from one state
    to another

 Direct                  Indirect
◆ Triggered by user     ◆ Triggered by other

◆ Notify listeners        element
                        ◆ Transition element
State changes
                                                  35




$(document).bind('state:checked', function(e) {
  if (e.trigger) {
    $(e.target).attr('checked', e.value);
  }
});
State changes
                                                  35




$(document).bind('state:checked', function(e) {
  if (e.trigger) {
    $(e.target).attr('checked', e.value);
  }
});
State changes
                                                  35




$(document).bind('state:checked', function(e) {
  if (e.trigger) {
    $(e.target).attr('checked', e.value);
  }
});
State changes
                                                  35




$(document).bind('state:checked', function(e) {
  if (e.trigger) {
    $(e.target).attr('checked', e.value);
  }
});
State changes
                                                  35




$(document).bind('state:checked', function(e) {
  if (e.trigger) {
    $(e.target).attr('checked', e.value);
  }
});
document



<html>                  ◆   Event bubbling allows
                            overwriting handlers
<body>                      for specific regions

<div id="body">         ◆   CSS selectors allow
                            overwriting handlers
<div class="element">       for specific elements
                                                    36



<input type="text">     State changes
Future Work
Domain-specific language
                                            38


state_of('[name="baz"]')
  ->is('checked')
    ->when('[name="bar"]')->checked()
      ->and('[name="foo"]')->value('foo')
    ->orWhen('[name="bar"]')->unchecked()

 ->is('disabled')
   ->when('[name="bar"]')->unchecked()

 ->is('invisible')
   ->when('[name="foo"]')->empty();



                      Ideas?
Copy & Paste support   39
Multi-value support
                                                40


// The value of at least one element is true.
{'any': true}

// At least two elements are true.
{'n > 2': true}

// The third element is false.
{'2': false}
Extended values
                                                    41


// The value is greater than 8 or smaller than 5.
[ {'>': 8}, {'<': 5} ]

// At least two elements are between 5 and 8.
{'n > 2': {'>': 5, '<': 8}}

// The sum of the values of all elements is
// greater than 10.
{'sum': {'>=': 10}}
Questions?
                              42




kkaefer.com/2010/states.pdf
    mail@kkaefer.com

Weitere ähnliche Inhalte

Was ist angesagt?

Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitmfrost503
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...Rafael Dohms
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix itRafael Dohms
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonfRafael Dohms
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome TownRoss Tuck
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介Jace Ju
 
PHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object CalisthenicsPHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object CalisthenicsGuilherme Blanco
 
Javascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introductionJavascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introductionIban Martinez
 
dcs plus Catalogue 2015
dcs plus Catalogue 2015dcs plus Catalogue 2015
dcs plus Catalogue 2015dcs plus
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design PatternsHugo Hamon
 
Programa simulacion de ventas de aeropuerto
Programa simulacion de ventas de aeropuertoPrograma simulacion de ventas de aeropuerto
Programa simulacion de ventas de aeropuertoAnel Sosa
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm OldRoss Tuck
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistenceHugo Hamon
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsRoss Tuck
 
R57shell
R57shellR57shell
R57shellady36
 

Was ist angesagt? (20)

Mocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnitMocking Dependencies in PHPUnit
Mocking Dependencies in PHPUnit
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHP Yo...
 
Your code sucks, let's fix it
Your code sucks, let's fix itYour code sucks, let's fix it
Your code sucks, let's fix it
 
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
“Writing code that lasts” … or writing code you won’t hate tomorrow. - PHPKonf
 
Command Bus To Awesome Town
Command Bus To Awesome TownCommand Bus To Awesome Town
Command Bus To Awesome Town
 
購物車程式架構簡介
購物車程式架構簡介購物車程式架構簡介
購物車程式架構簡介
 
PHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object CalisthenicsPHP for Adults: Clean Code and Object Calisthenics
PHP for Adults: Clean Code and Object Calisthenics
 
Javascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introductionJavascript & jQuery: A pragmatic introduction
Javascript & jQuery: A pragmatic introduction
 
Unit testing zend framework apps
Unit testing zend framework appsUnit testing zend framework apps
Unit testing zend framework apps
 
dcs plus Catalogue 2015
dcs plus Catalogue 2015dcs plus Catalogue 2015
dcs plus Catalogue 2015
 
Leveraging Symfony2 Forms
Leveraging Symfony2 FormsLeveraging Symfony2 Forms
Leveraging Symfony2 Forms
 
Coding website
Coding websiteCoding website
Coding website
 
php plus mysql
php plus mysqlphp plus mysql
php plus mysql
 
Database Design Patterns
Database Design PatternsDatabase Design Patterns
Database Design Patterns
 
Separation of concerns - DPC12
Separation of concerns - DPC12Separation of concerns - DPC12
Separation of concerns - DPC12
 
Programa simulacion de ventas de aeropuerto
Programa simulacion de ventas de aeropuertoPrograma simulacion de ventas de aeropuerto
Programa simulacion de ventas de aeropuerto
 
Things I Believe Now That I'm Old
Things I Believe Now That I'm OldThings I Believe Now That I'm Old
Things I Believe Now That I'm Old
 
The History of PHPersistence
The History of PHPersistenceThe History of PHPersistence
The History of PHPersistence
 
Models and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and HobgoblinsModels and Service Layers, Hemoglobin and Hobgoblins
Models and Service Layers, Hemoglobin and Hobgoblins
 
R57shell
R57shellR57shell
R57shell
 

Ähnlich wie Instant Dynamic Forms with #states

Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB jhchabran
 
Gta v savegame
Gta v savegameGta v savegame
Gta v savegamehozayfa999
 
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...Mateusz Zalewski
 
PHP record- with all programs and output
PHP record- with all programs and outputPHP record- with all programs and output
PHP record- with all programs and outputKavithaK23
 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needKacper Gunia
 
Taking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order FunctionsTaking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order FunctionsDavid Golden
 
The Art of Transduction
The Art of TransductionThe Art of Transduction
The Art of TransductionDavid Stockton
 
Slaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubySlaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubyJason Yeo Jie Shun
 
Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuerysergioafp
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersKacper Gunia
 
Desarrollo de módulos en Drupal e integración con dispositivos móviles
Desarrollo de módulos en Drupal e integración con dispositivos móvilesDesarrollo de módulos en Drupal e integración con dispositivos móviles
Desarrollo de módulos en Drupal e integración con dispositivos móvilesLuis Curo Salvatierra
 
Fields in Core: How to create a custom field
Fields in Core: How to create a custom fieldFields in Core: How to create a custom field
Fields in Core: How to create a custom fieldIvan Zugec
 
TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012
TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012
TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012Amazon Web Services
 
Refactoring group 1 - chapter 3,4,6
Refactoring   group 1 - chapter 3,4,6Refactoring   group 1 - chapter 3,4,6
Refactoring group 1 - chapter 3,4,6Duy Lâm
 
The State of Lithium
The State of LithiumThe State of Lithium
The State of LithiumNate Abele
 
究極のコントローラを目指す
究極のコントローラを目指す究極のコントローラを目指す
究極のコントローラを目指すYasuo Harada
 

Ähnlich wie Instant Dynamic Forms with #states (20)

Php functions
Php functionsPhp functions
Php functions
 
Php & my sql
Php & my sqlPhp & my sql
Php & my sql
 
Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB Introduction à CoffeeScript pour ParisRB
Introduction à CoffeeScript pour ParisRB
 
Gta v savegame
Gta v savegameGta v savegame
Gta v savegame
 
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
[PHPCon 2023] “Kto to pisał?!... a, to ja.”, czyli sposoby żeby znienawidzić ...
 
Drupal7 dbtng
Drupal7  dbtngDrupal7  dbtng
Drupal7 dbtng
 
PHP record- with all programs and output
PHP record- with all programs and outputPHP record- with all programs and output
PHP record- with all programs and output
 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
 
Taking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order FunctionsTaking Perl to Eleven with Higher-Order Functions
Taking Perl to Eleven with Higher-Order Functions
 
The Art of Transduction
The Art of TransductionThe Art of Transduction
The Art of Transduction
 
Slaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in RubySlaying the Dragon: Implementing a Programming Language in Ruby
Slaying the Dragon: Implementing a Programming Language in Ruby
 
Advanced jQuery
Advanced jQueryAdvanced jQuery
Advanced jQuery
 
PHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4DevelopersPHPSpec - the only Design Tool you need - 4Developers
PHPSpec - the only Design Tool you need - 4Developers
 
Arrays in php
Arrays in phpArrays in php
Arrays in php
 
Desarrollo de módulos en Drupal e integración con dispositivos móviles
Desarrollo de módulos en Drupal e integración con dispositivos móvilesDesarrollo de módulos en Drupal e integración con dispositivos móviles
Desarrollo de módulos en Drupal e integración con dispositivos móviles
 
Fields in Core: How to create a custom field
Fields in Core: How to create a custom fieldFields in Core: How to create a custom field
Fields in Core: How to create a custom field
 
TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012
TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012
TLS305 Using DynamoDB with the AWS SDK for PHP - AWS re: Invent 2012
 
Refactoring group 1 - chapter 3,4,6
Refactoring   group 1 - chapter 3,4,6Refactoring   group 1 - chapter 3,4,6
Refactoring group 1 - chapter 3,4,6
 
The State of Lithium
The State of LithiumThe State of Lithium
The State of Lithium
 
究極のコントローラを目指す
究極のコントローラを目指す究極のコントローラを目指す
究極のコントローラを目指す
 

Mehr von Konstantin Käfer

Mehr von Konstantin Käfer (6)

Front End Performance
Front End PerformanceFront End Performance
Front End Performance
 
Front End Performance
Front End PerformanceFront End Performance
Front End Performance
 
Developing JavaScript Widgets
Developing JavaScript WidgetsDeveloping JavaScript Widgets
Developing JavaScript Widgets
 
Front End Performance
Front End PerformanceFront End Performance
Front End Performance
 
Typography on the Web
Typography on the WebTypography on the Web
Typography on the Web
 
What's New in Web Development
What's New in Web DevelopmentWhat's New in Web Development
What's New in Web Development
 

Kürzlich hochgeladen

Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxBkGupta21
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfMounikaPolabathina
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESmohitsingh558521
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 

Kürzlich hochgeladen (20)

Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
unit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptxunit 4 immunoblotting technique complete.pptx
unit 4 immunoblotting technique complete.pptx
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
What is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdfWhat is DBT - The Ultimate Data Build Tool.pdf
What is DBT - The Ultimate Data Build Tool.pdf
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICESSALESFORCE EDUCATION CLOUD | FEXLE SERVICES
SALESFORCE EDUCATION CLOUD | FEXLE SERVICES
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 

Instant Dynamic Forms with #states

  • 1. Instant Dynamic Forms with #states
  • 4. 4
  • 5. Anatomy of a state 5 $form['payment_information'] = array( '#type' => 'fieldset', '#title' => t('Payment information'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#states' => array( 'expanded' => array( '[name="payment"]' => array('checked' => TRUE) ), ), );
  • 6. Anatomy of a state 5 $form['payment_information'] = array( '#type' => 'fieldset', '#title' => t('Payment information'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#states' => array( 'expanded' => array( '[name="payment"]' => array('checked' => TRUE) ), ), );
  • 7. Anatomy of a state 5 $form['payment_information'] = array( '#type' => 'fieldset', '#title' => t('Payment information'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#states' => array( 'expanded' => array( '[name="payment"]' => array('checked' => TRUE) ), ), );
  • 8. Anatomy of a state 5 $form['payment_information'] = array( '#type' => 'fieldset', '#title' => t('Payment information'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#states' => array( 'expanded' => array( '[name="payment"]' => array('checked' => TRUE) ), ), );
  • 9. Anatomy of a state 5 $form['payment_information'] = array( '#type' => 'fieldset', '#title' => t('Payment information'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#states' => array( 'expanded' => array( '[name="payment"]' => array('checked' => TRUE) ), ), );
  • 10. Anatomy of a state 5 $form['payment_information'] = array( '#type' => 'fieldset', '#title' => t('Payment information'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#states' => array( 'expanded' => array( '[name="payment"]' => array('checked' => TRUE) ), ), );
  • 11. Anatomy of a state 5 $form['payment_information'] = array( '#type' => 'fieldset', '#title' => t('Payment information'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#states' => array( 'expanded' => array( '[name="payment"]' => array('checked' => TRUE) ), ), );
  • 12. Anatomy of a state 5 $form['payment_information'] = array( '#type' => 'fieldset', '#title' => t('Payment information'), '#collapsible' => TRUE, '#collapsed' => TRUE, '#states' => array( 'expanded' => array( '[name="payment"]' => array('checked' => TRUE) ), ), );
  • 13. Declarative definition 6 'expanded' => array( '[name="payment"]' => array('checked' => TRUE) ), ➜ Expanded when the element “payment” is checked
  • 14. Dependencies 7 $form['payment_information'] = array(... '#states' => array( 'expanded' => array( '[name="payment"]' => array('checked' => TRUE) ), ), ); <fieldset> Depends on Influences <input type="checkbox">
  • 15. Targeting elements 8 ◆ Uses plain CSS selectors with jQuery ◆ [name="payment"] #edit-payment .payment :checkbox, #edit-payment ◆ Don’t use #selector for auto-assigned IDs
  • 16. States 9 ◆ Arbitrary names are possible ◆ visible irrelevant confirmed checked valid important ◆ Prefixing with ! negates ◆ visible = !invisible invisible = !visible
  • 17. State aliases 10 ◆ Associate custom aliases Primary name ◆ Drupal.states.State.aliases ['unimportant'] = '!important'; ◆ enabled = !disabled invisible = !visible invalid = !valid untouched = !touched optional = !required filled = !empty unchecked = !checked irrelevant = !relevant expanded = !collapsed readwrite = !readonly
  • 18. Drawbacks 11 ◆ Doesn’t support OR and XOR
  • 19. Drawbacks 11 ◆ Doesn’t ! chsupport OR and XOR Pat drupal.org/node/735528
  • 20. AND operator 12 'disabled' => array( '[name="ccv"]' => array( 'invalid' => TRUE ), '[name="card_number"]' => array( 'invalid' => TRUE ), ),
  • 21. OR operator 13 'disabled' => array( array( '[name="ccv"]' => array( 'invalid' => TRUE ), ), array( '[name="card_number"]' => array( 'invalid' => TRUE ), ), ),
  • 22. OR operator 13 'disabled' => array( array( '[name="ccv"]' => array( 'invalid' => TRUE ), ), Numeric keys array( '[name="card_number"]' => array( 'invalid' => TRUE ), ), ),
  • 23. XOR operator 14 'disabled' => array('xor', array( '[name="ccv"]' => array( 'invalid' => TRUE ), ), array( '[name="card_number"]' => array( 'invalid' => TRUE ), ), ),
  • 24. XOR operator 14 'disabled' => array('xor', Operator array( '[name="ccv"]' => array( 'invalid' => TRUE ), ), array( '[name="card_number"]' => array( 'invalid' => TRUE ), ), ),
  • 25. Drawbacks 15 ◆ Doesn’t ! chsupport OR and XOR Pat drupal.org/node/735528
  • 26. Drawbacks 15 ◆ Doesn’t ! chsupport OR and XOR Pat drupal.org/node/735528 ◆ Doesn’t support radio buttons
  • 27. Drawbacks 15 ◆ Doesn’t ! chsupport OR and XOR Pat drupal.org/node/735528 ◆ Doesn’t support radio buttons end! E xt
  • 29. Default Triggers 17 Drupal.states.Trigger.states = { ... checked: { 'change': function () { return this.attr('checked'); } }, ... };
  • 30. Default Triggers 17 Drupal.states.Trigger.states = { ... checked: { Native DOM event 'change': function () { return this.attr('checked'); } }, ... };
  • 31. Default Triggers 17 Drupal.states.Trigger.states = { ... checked: { 'change': function () { return this.attr('checked'); } }, ... };
  • 32. Default Triggers 17 Drupal.states.Trigger.states = { ... checked: { 'change': function () { return this.attr('checked'); } }, ... }; Value function
  • 33. Default Triggers 18 Initialization Execution Drupal.states.Trigger.states = { Drupal.states.Trigger.states = { ... ... checked: { checked: { 'change': function () { 'change': function () { return this.attr('checked'); return this.attr('checked'); } } }, }, ... ... }; }; $('#element').bind('change', $('#element').bind('change', function() { function() { ... ... } } ); );
  • 34. Default Triggers 18 Initialization Execution Drupal.states.Trigger.states = { Drupal.states.Trigger.states = { ... ... checked: { checked: { 'change': function () { 'change': function () { return this.attr('checked'); return this.attr('checked'); } } }, }, ... ... }; }; $('#element').bind('change', $('#element').bind('change', function() { function() { ... ... } } ); );
  • 35. Default Triggers 18 Initialization Execution Drupal.states.Trigger.states = { Drupal.states.Trigger.states = { ... ... checked: { checked: { 'change': function () { 'change': function () { return this.attr('checked'); return this.attr('checked'); } } }, }, ... ... }; }; $('#element').bind('change', $('#element').bind('change', function() { function() { ... ... } } ); );
  • 36. Multiple Triggers 19 Drupal.states.Trigger.states = { ... value: { 'keyup': function () { return this.val(); }, 'change': function () { return this.val(); } }, ... };
  • 37. Multiple Triggers 20 Drupal.states.Trigger.states = { ... value: { 'keyup change': function () { return this.val(); } }, ... };
  • 38. Custom Triggers 21 '#states' => array( 'disabled' => array( '[name="delayed"]' => array('value' => 'foo') ), ),
  • 39. Custom Triggers 22 Drupal.states.Trigger.states.delayedValue = function(element) { var value = element.val(), oldValue, timeout; var trigger = function() { if (oldValue !== value) { element.trigger({ type: 'state:delayedValue', value: value, oldValue: oldValue }); oldValue = value; } }; ... };
  • 40. Custom Triggers 22 Drupal.states.Trigger.states.delayedValue = function(element) { var value = element.val(), oldValue, timeout; var trigger = function() { if (oldValue !== value) { element.trigger({ type: 'state:delayedValue', value: value, oldValue: oldValue }); oldValue = value; } }; ... };
  • 41. Custom Triggers 22 Drupal.states.Trigger.states.delayedValue = function(element) { var value = element.val(), oldValue, timeout; var trigger = function() { if (oldValue !== value) { element.trigger({ type: 'state:delayedValue', value: value, oldValue: oldValue }); oldValue = value; } }; ... };
  • 42. Custom Triggers 22 Drupal.states.Trigger.states.delayedValue = function(element) { var value = element.val(), oldValue, timeout; var trigger = function() { if (oldValue !== value) { element.trigger({ type: 'state:delayedValue', value: value, oldValue: oldValue }); oldValue = value; } }; ... };
  • 43. Custom Triggers 22 Drupal.states.Trigger.states.delayedValue = function(element) { var value = element.val(), oldValue, timeout; var trigger = function() { if (oldValue !== value) { element.trigger({ type: 'state:delayedValue', value: value, oldValue: oldValue }); oldValue = value; } }; ... };
  • 44. Custom Triggers 23 Drupal.states.Trigger.states.delayedValue = function(element) { ... element.bind('keyup change', function (e) { if (timeout) clearTimeout(timeout); timeout = setTimeout(function() { value = element.val(); trigger(); }, 1000); }); Drupal.states.postponed.push(trigger); };
  • 45. Custom Triggers 23 Drupal.states.Trigger.states.delayedValue = function(element) { ... element.bind('keyup change', function (e) { if (timeout) clearTimeout(timeout); timeout = setTimeout(function() { value = element.val(); trigger(); }, 1000); }); Drupal.states.postponed.push(trigger); };
  • 46. Custom Triggers 23 Drupal.states.Trigger.states.delayedValue = function(element) { ... element.bind('keyup change', function (e) { if (timeout) clearTimeout(timeout); timeout = setTimeout(function() { value = element.val(); trigger(); }, 1000); }); Drupal.states.postponed.push(trigger); };
  • 47. Custom Triggers 23 Drupal.states.Trigger.states.delayedValue = function(element) { ... element.bind('keyup change', function (e) { if (timeout) clearTimeout(timeout); timeout = setTimeout(function() { value = element.val(); trigger(); }, 1000); }); Drupal.states.postponed.push(trigger); };
  • 48. Custom Triggers 23 Drupal.states.Trigger.states.delayedValue = function(element) { ... element.bind('keyup change', function (e) { if (timeout) clearTimeout(timeout); timeout = setTimeout(function() { value = element.val(); trigger(); }, 1000); }); Drupal.states.postponed.push(trigger); };
  • 49. Custom Triggers 24 Drupal.states.Trigger.states.toggle = function(element) { var value = true, oldValue = undefined; var trigger = function() { value = !value; element.trigger({ type: 'state:toggle', value: value, oldValue: oldValue }); oldValue = value; }; setInterval(trigger, 1000); Drupal.states.postponed.push(trigger); };
  • 51. Comparisons 26 $form['payment_information'] = array( ... '#states' => array( 'expanded' => array( '[name="payment"]' => array('checked' => TRUE) ), ), );
  • 52. Comparisons 26 $form['payment_information'] = array( ... '#states' => array( 'expanded' => array( '[name="payment"]' => array('checked' => TRUE) ), ), === );
  • 53. Advanced Comparisons 27 states.Dependant.comparisons = { 'RegExp': function (reference, value) { return reference.test(value); }, 'Function': function (reference, value) { return reference(value); } };
  • 54. Advanced Comparisons 27 states.Dependant.comparisons = { 'RegExp': function (reference, value) { return reference.test(value); }, 'Function': function (reference, value) { return reference(value); } }; Prototype name
  • 55. JSON only allows strings and numbers 28
  • 56. :( 29
  • 57. Advanced Comparisons 30 'invalid' => array( '[name="card_number"]' => array( '!value' => '0000 0000 0000 0000', ), ), 'invalid' => array( '[name="card_number"]' => array( '!value' => array('regex' => '^(d{4}[ -]*){4}$'), ), ),
  • 58. Advanced Comparisons 30 'invalid' => array( '[name="card_number"]' => array( '!value' => '0000 0000 0000 0000', ), ), 'invalid' => array( '[name="card_number"]' => array( '!value' => array('regex' => '^(d{4}[ -]*){4}$'), ), ),
  • 59. Advanced Comparisons 31 Drupal.states.Dependant.comparisons.Object = function(reference, value) { if ('regex' in reference) { return RegExp(reference.regex, ↵ reference.flags).test(value); } else { return reference.indexOf(value) !== false; } };
  • 60. Advanced Comparisons 32 'invalid' => array( '[name="card_number"]' => array( '!value' => array('regex' => '^(d{4}[ -]*){4}$'), ), ),
  • 62. State changes 34 ◆ Transition an element from one state to another Direct Indirect ◆ Triggered by user ◆ Triggered by other ◆ Notify listeners element ◆ Transition element
  • 63. State changes 35 $(document).bind('state:checked', function(e) { if (e.trigger) { $(e.target).attr('checked', e.value); } });
  • 64. State changes 35 $(document).bind('state:checked', function(e) { if (e.trigger) { $(e.target).attr('checked', e.value); } });
  • 65. State changes 35 $(document).bind('state:checked', function(e) { if (e.trigger) { $(e.target).attr('checked', e.value); } });
  • 66. State changes 35 $(document).bind('state:checked', function(e) { if (e.trigger) { $(e.target).attr('checked', e.value); } });
  • 67. State changes 35 $(document).bind('state:checked', function(e) { if (e.trigger) { $(e.target).attr('checked', e.value); } });
  • 68. document <html> ◆ Event bubbling allows overwriting handlers <body> for specific regions <div id="body"> ◆ CSS selectors allow overwriting handlers <div class="element"> for specific elements 36 <input type="text"> State changes
  • 70. Domain-specific language 38 state_of('[name="baz"]') ->is('checked') ->when('[name="bar"]')->checked() ->and('[name="foo"]')->value('foo') ->orWhen('[name="bar"]')->unchecked() ->is('disabled') ->when('[name="bar"]')->unchecked() ->is('invisible') ->when('[name="foo"]')->empty(); Ideas?
  • 71. Copy & Paste support 39
  • 72. Multi-value support 40 // The value of at least one element is true. {'any': true} // At least two elements are true. {'n > 2': true} // The third element is false. {'2': false}
  • 73. Extended values 41 // The value is greater than 8 or smaller than 5. [ {'>': 8}, {'<': 5} ] // At least two elements are between 5 and 8. {'n > 2': {'>': 5, '<': 8}} // The sum of the values of all elements is // greater than 10. {'sum': {'>=': 10}}
  • 74. Questions? 42 kkaefer.com/2010/states.pdf mail@kkaefer.com