/**
  * Start or stop tracking changes after clearing out any existing tracked changes, applying the same to any children
  *
  */
 public function resetTrackChanges($trackChanges = true)
 {
     if (count($this->children)) {
         foreach ($this->children as $child) {
             $child->resetTrackChanges($trackChanges);
         }
     }
     return parent::resetTrackChanges();
 }
 /**
  * Custom processing for the options string in getConfigInputfields
  * 
  * Detects and confirms option deletions. 
  *
  * @param Inputfield $inputfield For the _options inputfield
  * @throws WireException
  *
  */
 protected function process(Inputfield $inputfield)
 {
     $value = $this->wire('input')->post('_options');
     if ($this->wire('process') != 'ProcessField' || !$this->wire('user')->isSuperuser()) {
         return;
     }
     $ns = "{$this}{$this->field}";
     // namespace for session
     if (!is_null($value)) {
         // _options has been posted
         if ($this->manager->useLanguages() && $inputfield->useLanguages) {
             // multi-language
             $valuesPerLanguage = array();
             $changed = false;
             foreach ($this->wire('languages') as $language) {
                 $key = $language->isDefault() ? "_options" : "_options__{$language}";
                 $valuesPerLanguage[$language->id] = $this->wire('input')->post($key);
                 $key = $language->isDefault() ? "value" : "value{$language}";
                 if ($inputfield->{$key} != $valuesPerLanguage[$language->id]) {
                     $changed = true;
                 }
             }
             if ($changed) {
                 $this->manager->setOptionsStringLanguages($this->field, $valuesPerLanguage, false);
             }
         } else {
             // non multi-language
             if ($value != $inputfield->attr('value')) {
                 $this->manager->setOptionsString($this->field, $value, false);
             }
         }
         $removedOptionIDs = $this->manager->getRemovedOptionIDs($this->field);
         // identified for removal
         if (count($removedOptionIDs)) {
             // stuff in session for next request
             $this->wire('session')->set($ns, 'removedOptionIDs', $removedOptionIDs);
         }
         $deleteOptionIDs = $this->wire('input')->post('_delete_options');
         $deleteConfirm = (int) $this->wire('input')->post('_delete_confirm');
         if ($deleteOptionIDs && $deleteConfirm) {
             // confirmed deleted
             if (!ctype_digit(str_replace(',', '', $deleteOptionIDs))) {
                 throw new WireException("Invalid deleteOptionIDs");
             }
             $deleteOptionIDs = explode(',', $deleteOptionIDs);
             foreach ($deleteOptionIDs as $key => $value) {
                 $deleteOptionIDs[$key] = (int) $value;
             }
             $this->manager->deleteOptionsByID($this->field, $deleteOptionIDs);
         }
     } else {
         // options not posted, check if there are any pending session activities
         $removedOptionIDs = $this->wire('session')->get($ns, 'removedOptionIDs');
         if (count($removedOptionIDs)) {
             $f = $this->wire('modules')->get('InputfieldHidden');
             $f->attr('name', '_delete_options');
             $f->attr('value', implode(',', $removedOptionIDs));
             $this->inputfields->prepend($f);
             // setup for confirmation
             $f = $this->wire('modules')->get('InputfieldCheckbox');
             $f->attr('name', '_delete_confirm');
             $f->label = $this->_('Please confirm that you want to delete options');
             $f->label2 = $this->_n('Delete this option', 'Delete these options', count($removedOptionIDs));
             $this->warning($f->label);
             $removeOptions = $this->manager->getOptionsByID($this->field, $removedOptionIDs);
             $delimiter = $this->_('DELETE:') . ' ';
             $f->description .= $delimiter . $removeOptions->implode("\n{$delimiter}", 'title');
             // collapse other inputfields since we prefer them to focus on this one only for now
             foreach ($this->inputfields as $i) {
                 $i->collapsed = Inputfield::collapsedYes;
             }
             // add our confirmation field
             $this->inputfields->prepend($f);
             // was stuffed in session from previous request, unset it now since this is a one time thing
             $this->wire('session')->remove($ns, 'removedOptionIDs');
         }
     }
 }
 /**
  * Get any configuration Inputfields common to all InputfieldWrappers
  *
  */
 public function ___getConfigInputfields()
 {
     $inputfields = parent::___getConfigInputfields();
     // remove all options for 'collapsed' except collapsedYes and collapsedNo
     foreach ($inputfields as $f) {
         if ($f->attr('name') != 'collapsed') {
             continue;
         }
         foreach ($f->getOptions() as $value => $label) {
             if (!in_array($value, array(Inputfield::collapsedNo, Inputfield::collapsedYes))) {
                 $f->removeOption($value);
             }
         }
     }
     return $inputfields;
 }