/**
  * @see \qtism\runtime\rendering\markup\xhtml\AbstractXhtmlRenderer::appendChildren()
  */
 protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendChildren($fragment, $component, $base);
     if ($this->getRenderingEngine()->getShufflingPolicy() === AbstractMarkupRenderingEngine::CONTEXT_AWARE && $component->mustShuffle() === true) {
         Utils::shuffle($fragment->firstChild, new ShufflableCollection($component->getSimpleChoices()->getArrayCopy()));
     }
     // Put the choice elements into an unordered list.
     // Dev note: it seems we need a trick ... http://php.net/manual/en/domnode.removechild.php#90292
     $choiceElts = $fragment->firstChild->getElementsByTagName('li');
     $choiceQueue = array();
     $ulElt = $fragment->ownerDocument->createElement('ul');
     foreach ($choiceElts as $choiceElt) {
         $choiceQueue[] = $choiceElt;
     }
     foreach ($choiceQueue as $choiceElt) {
         $ifStatements = Utils::extractStatements($choiceElt, Utils::EXTRACT_IF);
         $incStatements = Utils::extractStatements($choiceElt, Utils::EXTRACT_INCLUDE);
         $fragment->firstChild->removeChild($choiceElt);
         $ulElt->appendChild($choiceElt);
         // Re-append qtism-include/qtism-endinclude.
         $statements = Utils::extractStatements($choiceElt, Utils::EXTRACT_INCLUDE);
         if (empty($incStatements) === false) {
             $choiceElt->parentNode->insertBefore($incStatements[0], $choiceElt);
             $choiceElt->parentNode->insertBefore($incStatements[1], $choiceElt->nextSibling);
         }
         // Re-append qtism-if/qtism-endif.
         if (empty($ifStatements) === false) {
             $choiceElt->parentNode->insertBefore($ifStatements[0], $choiceElt);
             $choiceElt->parentNode->insertBefore($ifStatements[1], $choiceElt->nextSibling);
         }
     }
     $fragment->firstChild->appendChild($ulElt);
 }
 protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendChildren($fragment, $component, $base);
     if ($this->getRenderingEngine()->mustShuffle() === true) {
         Utils::shuffle($fragment->firstChild, new ShufflableCollection($component->getSimpleAssociableChoices()->getArrayCopy()));
     }
     // The number of possible associations to display is maxAssociations if the attribute is present and different from 0, otherwise:
     //
     // * minAssociations, if different from 0 is used to determine the possible associations to display. Otherwise,
     // * a single possible association is displayed. Actions to undertake when this first association is done by the candidate depends on the implementation.
     $nbAssoc = ($assoc = $component->getMaxAssociations()) > 0 ? $assoc : (($assoc = $component->getMinAssociations()) > 0 ? $assoc : 1);
     for ($i = 0; $i < $nbAssoc; $i++) {
         $associationElt = $fragment->ownerDocument->createElement('div');
         $associationElt->setAttribute('class', 'qti-association');
         // A container for the first selected option...
         $firstElt = $fragment->ownerDocument->createElement('span');
         $firstElt->setAttribute('class', 'qti-association-first');
         $associationElt->appendChild($firstElt);
         // And a second container for the second selected option.
         $secondElt = $fragment->ownerDocument->createElement('span');
         $secondElt->setAttribute('class', 'qti-association-second');
         $associationElt->appendChild($secondElt);
         $fragment->firstChild->appendChild($associationElt);
     }
 }
 /**
  * @see \qtism\runtime\rendering\markup\xhtml\AbstractXhtmlRenderer::appendChildren()
  */
 protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendChildren($fragment, $component, $base);
     $titleElt = $fragment->ownerDocument->createTextNode($component->getTitle());
     $fragment->firstChild->appendChild($titleElt);
     $fragment->firstChild->setAttribute('title', $component->getTitle());
 }
 protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendChildren($fragment, $component, $base);
     if ($this->getRenderingEngine()->mustShuffle() === true) {
         Utils::shuffle($fragment->firstChild, new ShufflableCollection($component->getContent()->getArrayCopy()));
     }
 }
 /**
  * @see \qtism\runtime\rendering\markup\xhtml\AbstractXhtmlRenderer::appendChildren()
  */
 protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendChildren($fragment, $component, $base);
     $width = null;
     $height = null;
     if ($component->getObject()->hasWidth() === true) {
         $width = $component->getObject()->getWidth();
     }
     if ($component->getObject()->hasHeight() === true) {
         $height = $component->getObject()->getHeight();
     }
     $imgElt = $fragment->ownerDocument->createElement('img');
     $imgElt->setAttribute('src', $component->getObject()->getData());
     // Replace <object> by <img>.
     $objectElt = $fragment->firstChild->getElementsByTagName('object')->item(0);
     $fragment->firstChild->replaceChild($imgElt, $objectElt);
     // Append a <canvas>.
     $canvasElt = $fragment->ownerDocument->createElement('canvas');
     $fragment->firstChild->appendChild($canvasElt);
     if (empty($width) === false) {
         $imgElt->setAttribute('width', $width);
         $canvasElt->setAttribute('width', $width);
     }
     if (empty($height) === false) {
         $imgElt->setAttribute('height', $height);
         $canvasElt->setAttribute('height', $height);
     }
 }
 protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendChildren($fragment, $component, $base);
     if ($this->getRenderingEngine()->mustShuffle() === true) {
         Utils::shuffle($fragment->firstChild, new ShufflableCollection($component->getSimpleChoices()->getArrayCopy()));
     }
     // Get back the 'qti-simpleChoice' elements.
     $elts = $fragment->firstChild->childNodes;
     $choices = array();
     for ($i = 0; $i < $elts->length; $i++) {
         if ($elts->item($i)->nodeType === XML_ELEMENT_NODE) {
             $classes = $elts->item($i)->getAttribute('class');
             if (mb_strpos($classes, 'qti-simpleChoice', 0, 'UTF-8') !== false) {
                 $choices[] = $elts->item($i);
             }
         }
     }
     // Give a unique id for the input->name attribute.
     $inputId = uniqid();
     if ($component->getMaxChoices() === 0 || $component->getMaxChoices() > 1) {
         foreach ($choices as $c) {
             $checkbox = $fragment->ownerDocument->createElement('input');
             $checkbox->setAttribute('type', 'checkbox');
             $checkbox->setAttribute('name', $inputId);
             $c->insertBefore($checkbox, $c->firstChild);
         }
     } else {
         foreach ($choices as $c) {
             $radio = $fragment->ownerDocument->createElement('input');
             $radio->setAttribute('type', 'radio');
             $radio->setAttribute('name', $inputId);
             $c->insertBefore($radio, $c->firstChild);
         }
     }
 }
 /**
  * @see \qtism\runtime\rendering\markup\xhtml\AbstractXhtmlRenderer::appendChildren()
  */
 protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendChildren($fragment, $component, $base);
     if ($this->getRenderingEngine()->getShufflingPolicy() === AbstractMarkupRenderingEngine::CONTEXT_AWARE && $component->mustShuffle() === true) {
         Utils::shuffle($fragment->firstChild, new ShufflableCollection($component->getGapChoices()->getArrayCopy()));
     }
 }
 protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendChildren($fragment, $component, $base);
     $submitElt = $fragment->ownerDocument->createElement('input');
     $submitElt->setAttribute('type', 'submit');
     $submitElt->setAttribute('value', $component->getTitle());
     $fragment->firstChild->appendChild($submitElt);
 }
 protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendChildren($fragment, $component, $base);
     // Insert an element representing the slider 'widget' itself.
     $sliderElt = $fragment->firstChild->ownerDocument->createElement('div');
     $sliderElt->setAttribute('class', 'qti-slider');
     $fragment->firstChild->appendChild($sliderElt);
 }
 /**
  * @see \qtism\runtime\rendering\markup\xhtml\InteractionRenderer::appendAttributes()
  */
 protected function appendAttributes(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendAttributes($fragment, $component, $base);
     $this->additionalClass('qti-blockInteraction');
     $this->additionalClass('qti-hottextInteraction');
     $fragment->firstChild->setAttribute('data-max-choices', $component->getMaxChoices());
     $fragment->firstChild->setAttribute('data-min-choices', $component->getMinChoices());
 }
 protected function appendAttributes(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendAttributes($fragment, $component, $base);
     $this->additionalClass('qti-positionObjectInteraction');
     $fragment->firstChild->setAttribute('data-max-choices', $component->getMaxChoices());
     if ($component->hasMinChoices() === true) {
         $fragment->firstChild->setAttribute('data-min-choices', $component->getMinChoices());
     }
     if ($component->hasCenterPoint() === true) {
         $fragment->firstChild->setAttribute('data-center-point', $component->getCenterPoint()->getX() . " " . $component->getCenterPoint()->getY());
     }
 }
 /**
  * @see \qtism\runtime\rendering\markup\xhtml\AbstractXhtmlRenderer::appendChildren()
  */
 protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendChildren($fragment, $component, $base);
     if ($this->getRenderingEngine()->getShufflingPolicy() === AbstractMarkupRenderingEngine::CONTEXT_AWARE && $component->mustShuffle() === true) {
         Utils::shuffle($fragment->firstChild, new ShufflableCollection($component->getSimpleAssociableChoices()->getArrayCopy()));
     }
     // Put the choice elements into an unordered list.
     // Dev note: it seems we need a trick ... http://php.net/manual/en/domnode.removechild.php#90292
     // @dev Bwaaaah copy/paste!
     $choiceElts = $fragment->firstChild->getElementsByTagName('li');
     $choiceQueue = array();
     $ulElt = $fragment->ownerDocument->createElement('ul');
     foreach ($choiceElts as $choiceElt) {
         $choiceQueue[] = $choiceElt;
     }
     foreach ($choiceQueue as $choiceElt) {
         $ifStatements = Utils::extractStatements($choiceElt, Utils::EXTRACT_IF);
         $incStatements = Utils::extractStatements($choiceElt, Utils::EXTRACT_INCLUDE);
         $fragment->firstChild->removeChild($choiceElt);
         $ulElt->appendChild($choiceElt);
         if (empty($incStatements) === false) {
             $choiceElt->parentNode->insertBefore($incStatements[0], $choiceElt);
             $choiceElt->parentNode->insertBefore($incStatements[1], $choiceElt->nextSibling);
         }
         if (empty($ifStatements) === false) {
             $choiceElt->parentNode->insertBefore($ifStatements[0], $choiceElt);
             $choiceElt->parentNode->insertBefore($ifStatements[1], $choiceElt->nextSibling);
         }
     }
     $fragment->firstChild->appendChild($ulElt);
     // The number of possible associations to display is maxAssociations if the attribute is present and different from 0, otherwise:
     //
     // * minAssociations, if different from 0 is used to determine the possible associations to display. Otherwise,
     // * a single possible association is displayed. Actions to undertake when this first association is done by the candidate depends on the implementation.
     // QUESTION: Should we delegate that to implementers decisions i.e. JS libraries to generate as they whish?
     // Below is commented code of such a generation directly in the markup...
     // At the present time, my feeling is to delegate ...
     $nbAssoc = ($assoc = $component->getMaxAssociations()) > 0 ? $assoc : (($assoc = $component->getMinAssociations()) > 0 ? $assoc : 1);
     for ($i = 0; $i < $nbAssoc; $i++) {
         $associationElt = $fragment->ownerDocument->createElement('div');
         $associationElt->setAttribute('class', 'qti-association');
         // A container for the first selected option...
         $firstElt = $fragment->ownerDocument->createElement('span');
         $firstElt->setAttribute('class', 'qti-association-first');
         $associationElt->appendChild($firstElt);
         // And a second container for the second selected option.
         $secondElt = $fragment->ownerDocument->createElement('span');
         $secondElt->setAttribute('class', 'qti-association-second');
         $associationElt->appendChild($secondElt);
         $fragment->firstChild->appendChild($associationElt);
     }
 }
 /**
  * @see \qtism\runtime\rendering\markup\xhtml\AbstractXhtmlRenderer::appendChildren()
  */
 protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendChildren($fragment, $component);
     $inputFileElt = $fragment->ownerDocument->createElement('input');
     $inputFileElt->setAttribute('type', 'file');
     if ($component->hasType() === true) {
         $inputFileElt->setAttribute('accept', $component->getType());
     }
     $submitElt = $fragment->ownerDocument->createElement('input');
     $submitElt->setAttribute('type', 'submit');
     $fragment->firstChild->appendChild($inputFileElt);
     $fragment->firstChild->appendChild($submitElt);
 }
 protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendChildren($fragment, $component, $base);
     // Retrieve the two rendered simpleMatchSets and shuffle if needed.
     $currentSet = 0;
     $choiceElts = array();
     $simpleMatchSetElts = array();
     for ($i = 0; $i < $fragment->firstChild->childNodes->length; $i++) {
         $n = $fragment->firstChild->childNodes->item($i);
         if (Utils::hasClass($n, 'qti-simpleMatchSet') === true) {
             $simpleMatchSetElts[] = $n;
             $sets = $component->getSimpleMatchSets();
             if ($this->getRenderingEngine()->mustShuffle() === true) {
                 Utils::shuffle($n, new ShufflableCollection($sets[$currentSet]->getSimpleAssociableChoices()->getArrayCopy()));
             }
             // Retrieve the two content of the two simpleMatchSets, separately.
             $choiceElts[] = Marshaller::getChildElementsByTagName($n, 'div');
             $currentSet++;
         }
     }
     // simpleMatchSet class cannot be rendered into a table :/
     foreach ($simpleMatchSetElts as $sms) {
         $fragment->firstChild->removeChild($sms);
     }
     $table = $fragment->ownerDocument->createElement('table');
     $fragment->firstChild->appendChild($table);
     // Build the table header.
     $tr = $fragment->ownerDocument->createElement('tr');
     $table->appendChild($tr);
     // Empty upper left cell.
     $tr->appendChild($fragment->ownerDocument->createElement('th'));
     for ($i = 0; $i < count($choiceElts[1]); $i++) {
         $tr->appendChild(XmlUtils::changeElementName($choiceElts[1][$i], 'th'));
     }
     // Build all remaining rows.
     for ($i = 0; $i < count($choiceElts[0]); $i++) {
         $tr = $fragment->ownerDocument->createElement('tr');
         $tr->appendChild(XmlUtils::changeElementName($choiceElts[0][$i], 'th'));
         $table->appendChild($tr);
         for ($j = 0; $j < count($choiceElts[1]); $j++) {
             $input = $fragment->ownerDocument->createElement('input');
             $input->setAttribute('type', 'checkbox');
             $td = $fragment->ownerDocument->createElement('td');
             $td->appendChild($input);
             $tr->appendChild($td);
         }
     }
 }
 /**
  * @see \qtism\runtime\rendering\markup\xhtml\InteractionRenderer::appendAttributes()
  */
 protected function appendAttributes(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendAttributes($fragment, $component, $base);
     $this->additionalClass('qti-stringInteraction');
     $fragment->firstChild->setAttribute('data-base', $component->getBase());
     if ($component->hasStringIdentifier() === true) {
         $fragment->firstChild->setAttribute('data-string-identifier', $component->getStringIdentifier());
     }
     if ($component->hasExpectedLength() === true) {
         $fragment->firstChild->setAttribute('data-expected-length', $component->getExpectedLength());
     }
     if ($component->hasPatternMask() === true) {
         $fragment->firstChild->setAttribute('data-pattern-mask', $component->getPatternMask());
     }
     if ($component->hasPlaceholderText() === true) {
         $fragment->firstChild->setAttribute('data-placeholder-text', $component->getPlaceholderText());
     }
 }
 /**
  * @see \qtism\runtime\rendering\markup\xhtml\AbstractXhtmlRenderer::appendChildren()
  */
 protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendChildren($fragment, $component, $base);
     $width = null;
     $height = null;
     if ($component->getObject()->hasWidth() === true) {
         $width = $component->getObject()->getWidth();
     }
     if ($component->getObject()->hasHeight() === true) {
         $height = $component->getObject()->getHeight();
     }
     $media = null;
     if (in_array($component->getObject()->getType(), $this->getVideoTypes()) === true) {
         // Transform the object element representing the video.
         $media = $fragment->ownerDocument->createElement('video');
         $source = $fragment->ownerDocument->createElement('source');
         $source->setAttribute('type', $component->getObject()->getType());
         $source->setAttribute('src', $component->getObject()->getData());
         $media->appendChild($source);
     } elseif (in_array($component->getObject()->getType(), $this->getAudioTypes()) === true) {
         $media = $fragment->ownerDocument->createElement('audio');
         $source = $fragment->ownerDocument->createElement('source');
         $source->setAttribute('type', $component->getObject()->getType());
         $source->setAttribute('src', $component->getObject()->getData());
         $media->appendChild($source);
     } elseif (in_array($component->getObject()->getType(), $this->getImageTypes()) === true) {
         $media = $fragment->ownerDocument->createElement('img');
         $media->setAttribute('src', $component->getObject()->getData());
     }
     if (empty($media) !== true) {
         // Search for the <object> to be replaced.
         $objects = $fragment->firstChild->getElementsByTagName('object');
         $fragment->firstChild->replaceChild($media, $objects->item(0));
         if (empty($width) !== true) {
             $media->setAttribute('width', $width);
         }
         if (empty($height) !== true) {
             $media->setAttribute('height', $height);
         }
     }
 }
 /**
  * @see \qtism\runtime\rendering\markup\xhtml\AbstractXhtmlRenderer::appendChildren()
  */
 protected function appendChildren(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendChildren($fragment, $component, $base);
     // Retrieve the two rendered simpleMatchSets and shuffle if needed.
     $currentSet = 0;
     $choiceElts = array();
     $simpleMatchSetElts = array();
     for ($i = 0; $i < $fragment->firstChild->childNodes->length; $i++) {
         $n = $fragment->firstChild->childNodes->item($i);
         if (Utils::hasClass($n, 'qti-simpleMatchSet') === true) {
             $simpleMatchSetElts[] = $n;
             $sets = $component->getSimpleMatchSets();
             if ($this->getRenderingEngine()->getShufflingPolicy() === AbstractMarkupRenderingEngine::CONTEXT_AWARE && $component->mustShuffle()) {
                 Utils::shuffle($n, new ShufflableCollection($sets[$currentSet]->getSimpleAssociableChoices()->getArrayCopy()));
             }
             // Retrieve the two content of the two simpleMatchSets, separately.
             $choiceElts[] = Marshaller::getChildElementsByTagName($n, 'li');
             $currentSet++;
         }
     }
     // simpleMatchSet class cannot be rendered into a table :/
     foreach ($simpleMatchSetElts as $sms) {
         $fragment->firstChild->removeChild($sms);
     }
     $table = $fragment->ownerDocument->createElement('table');
     $fragment->firstChild->appendChild($table);
     // Build the table header.
     $tr = $fragment->ownerDocument->createElement('tr');
     $table->appendChild($tr);
     // Empty upper left cell.
     $tr->appendChild($fragment->ownerDocument->createElement('th'));
     $ifVerticalStatementsStorage = array();
     for ($i = 0; $i < count($choiceElts[1]); $i++) {
         $ifStatements = Utils::extractStatements($choiceElts[1][$i], Utils::EXTRACT_IF);
         $incStatements = Utils::extractStatements($choiceElts[1][$i], Utils::EXTRACT_INCLUDE);
         if (empty($incStatements) === false) {
             $tr->appendChild($incStatements[0]);
         }
         if (empty($ifStatements) === false) {
             $ifVerticalStatementsStorage[$i] = $ifStatements;
             $tr->appendChild($ifStatements[0]);
         }
         $th = XmlUtils::changeElementName($choiceElts[1][$i], 'th');
         $tr->appendChild($th);
         if (empty($incStatements) === false) {
             $th->parentNode->insertBefore($incStatements[1], $th->nextSibling);
         }
         if (empty($ifStatements) === false) {
             $th->parentNode->insertBefore($ifStatements[1], $th->nextSibling);
         }
     }
     // Build all remaining rows.
     for ($i = 0; $i < count($choiceElts[0]); $i++) {
         $tr = $fragment->ownerDocument->createElement('tr');
         $ifStatements = Utils::extractStatements($choiceElts[0][$i], Utils::EXTRACT_IF);
         $incStatements = Utils::extractStatements($choiceElts[0][$i], Utils::EXTRACT_INCLUDE);
         $th = XmlUtils::changeElementName($choiceElts[0][$i], 'th');
         $tr->appendChild($th);
         $table->appendChild($tr);
         if (empty($incStatements) === false) {
             $tr->parentNode->insertBefore($incStatements[0], $tr);
         }
         if (empty($ifStatements) === false) {
             $tr->parentNode->insertBefore($ifStatements[0], $tr);
         }
         for ($j = 0; $j < count($choiceElts[1]); $j++) {
             $input = $fragment->ownerDocument->createElement('input');
             $input->setAttribute('type', 'checkbox');
             $td = $fragment->ownerDocument->createElement('td');
             $td->appendChild($input);
             $tr->appendChild($td);
             if (isset($ifVerticalStatementsStorage[$j])) {
                 $td->parentNode->insertBefore($ifVerticalStatementsStorage[$j][0]->cloneNode(), $td);
                 $td->parentNode->insertBefore($ifVerticalStatementsStorage[$j][1]->cloneNode(), $td->nextSibling);
             }
         }
         if (empty($incStatements) === false && isset($td)) {
             $tr->parentNode->insertBefore($incStatements[1], $tr->nextSibling);
         }
         if (empty($ifStatements) === false && isset($td)) {
             $tr->parentNode->insertBefore($ifStatements[1], $tr->nextSibling);
         }
     }
 }
 /**
  * @see \qtism\runtime\rendering\markup\xhtml\InteractionRenderer::appendAttributes()
  */
 protected function appendAttributes(DOMDocumentFragment $fragment, QtiComponent $component, $base = '')
 {
     parent::appendAttributes($fragment, $component, $base);
     $this->additionalClass('qti-graphicInteraction');
 }