/**
  * Generates the head HTML and return the results as a string
  *
  * @param   JDocument  $document  The document for which the head will be created
  *
  * @return  string  The head hTML
  *
  * @since   11.1
  */
 public function fetchHead(Document $document)
 {
     // Trigger the onBeforeCompileHead event (skip for installation, since it causes an error)
     $app = Factory::getApplication();
     $app->triggerEvent('onBeforeCompileHead');
     // Get line endings
     $lnEnd = $document->_getLineEnd();
     $tab = $document->_getTab();
     $tagEnd = ' />';
     $buffer = '';
     // Generate charset when using HTML5 (should happen first)
     if ($document->isHtml5()) {
         $buffer .= $tab . '<meta charset="' . $document->getCharset() . '" />' . $lnEnd;
     }
     // Generate base tag (need to happen early)
     $base = $document->getBase();
     if (!empty($base)) {
         $buffer .= $tab . '<base href="' . $document->getBase() . '" />' . $lnEnd;
     }
     // Generate META tags (needs to happen as early as possible in the head)
     foreach ($document->_metaTags as $type => $tag) {
         foreach ($tag as $name => $content) {
             if ($type == 'http-equiv' && !($document->isHtml5() && $name == 'content-type')) {
                 $buffer .= $tab . '<meta http-equiv="' . $name . '" content="' . htmlspecialchars($content) . '" />' . $lnEnd;
             } elseif ($type == 'standard' && !empty($content)) {
                 $buffer .= $tab . '<meta name="' . $name . '" content="' . htmlspecialchars($content) . '" />' . $lnEnd;
             }
         }
     }
     // Don't add empty descriptions
     $documentDescription = $document->getDescription();
     if ($documentDescription) {
         $buffer .= $tab . '<meta name="description" content="' . htmlspecialchars($documentDescription) . '" />' . $lnEnd;
     }
     // Don't add empty generators
     $generator = $document->getGenerator();
     if ($generator) {
         $buffer .= $tab . '<meta name="generator" content="' . htmlspecialchars($generator) . '" />' . $lnEnd;
     }
     $buffer .= $tab . '<title>' . htmlspecialchars($document->getTitle(), ENT_COMPAT, 'UTF-8') . '</title>' . $lnEnd;
     // Generate link declarations
     foreach ($document->_links as $link => $linkAtrr) {
         $buffer .= $tab . '<link href="' . $link . '" ' . $linkAtrr['relType'] . '="' . $linkAtrr['relation'] . '"';
         if ($temp = ArrayHelper::toString($linkAtrr['attribs'])) {
             $buffer .= ' ' . $temp;
         }
         $buffer .= ' />' . $lnEnd;
     }
     // Generate stylesheet links
     foreach ($document->_styleSheets as $strSrc => $strAttr) {
         $buffer .= $tab . '<link rel="stylesheet" href="' . $strSrc . '" type="' . $strAttr['mime'] . '"';
         if (!is_null($strAttr['media'])) {
             $buffer .= ' media="' . $strAttr['media'] . '" ';
         }
         if ($temp = ArrayHelper::toString($strAttr['attribs'])) {
             $buffer .= ' ' . $temp;
         }
         $buffer .= $tagEnd . $lnEnd;
     }
     // Generate stylesheet declarations
     foreach ($document->_style as $type => $content) {
         $buffer .= $tab . '<style type="' . $type . '">' . $lnEnd;
         // This is for full XHTML support.
         if ($document->_mime != 'text/html') {
             $buffer .= $tab . $tab . '<![CDATA[' . $lnEnd;
         }
         $buffer .= $content . $lnEnd;
         // See above note
         if ($document->_mime != 'text/html') {
             $buffer .= $tab . $tab . ']]>' . $lnEnd;
         }
         $buffer .= $tab . '</style>' . $lnEnd;
     }
     // Generate script file links
     foreach ($document->_scripts as $strSrc => $strAttr) {
         $buffer .= $tab . '<script src="' . $strSrc . '"';
         if (!is_null($strAttr['mime'])) {
             $buffer .= ' type="' . $strAttr['mime'] . '"';
         }
         if ($strAttr['defer']) {
             $buffer .= ' defer="defer"';
         }
         if ($strAttr['async']) {
             $buffer .= ' async="async"';
         }
         $buffer .= '></script>' . $lnEnd;
     }
     // Generate script declarations
     foreach ($document->_script as $type => $content) {
         $buffer .= $tab . '<script type="' . $type . '">' . $lnEnd;
         // This is for full XHTML support.
         if ($document->_mime != 'text/html') {
             $buffer .= $tab . $tab . '<![CDATA[' . $lnEnd;
         }
         $buffer .= $content . $lnEnd;
         // See above note
         if ($document->_mime != 'text/html') {
             $buffer .= $tab . $tab . ']]>' . $lnEnd;
         }
         $buffer .= $tab . '</script>' . $lnEnd;
     }
     // Generate script language declarations.
     if (count(Text::script())) {
         $buffer .= $tab . '<script type="text/javascript">' . $lnEnd;
         $buffer .= $tab . $tab . '(function() {' . $lnEnd;
         $buffer .= $tab . $tab . $tab . 'var strings = ' . json_encode(Text::script()) . ';' . $lnEnd;
         $buffer .= $tab . $tab . $tab . 'if (typeof Joomla == \'undefined\') {' . $lnEnd;
         $buffer .= $tab . $tab . $tab . $tab . 'Joomla = {};' . $lnEnd;
         $buffer .= $tab . $tab . $tab . $tab . 'Joomla.JText = strings;' . $lnEnd;
         $buffer .= $tab . $tab . $tab . '}' . $lnEnd;
         $buffer .= $tab . $tab . $tab . 'else {' . $lnEnd;
         $buffer .= $tab . $tab . $tab . $tab . 'Joomla.JText.load(strings);' . $lnEnd;
         $buffer .= $tab . $tab . $tab . '}' . $lnEnd;
         $buffer .= $tab . $tab . '})();' . $lnEnd;
         $buffer .= $tab . '</script>' . $lnEnd;
     }
     foreach ($document->_custom as $custom) {
         $buffer .= $tab . $custom . $lnEnd;
     }
     return $buffer;
 }
    /**
     * Add unobtrusive javascript support for the advanced uploader.
     *
     * @param   string  $id            An index.
     * @param   array   $params        An array of options for the uploader.
     * @param   string  $upload_queue  The HTML id of the upload queue element (??).
     *
     * @return  void
     *
     * @since   11.1
     */
    public static function uploader($id = 'file-upload', $params = array(), $upload_queue = 'upload-queue')
    {
        // Include MooTools framework
        self::framework();
        Html::_('script', 'system/swf.js', true, true);
        Html::_('script', 'system/progressbar.js', true, true);
        Html::_('script', 'system/uploader.js', true, true);
        $document = Factory::getDocument();
        if (!isset(self::$loaded[__METHOD__])) {
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_FILENAME');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_UPLOAD_COMPLETED');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_ERROR_OCCURRED');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_ALL_FILES');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_PROGRESS_OVERALL');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_CURRENT_TITLE');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_REMOVE');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_REMOVE_TITLE');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_CURRENT_FILE');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_CURRENT_PROGRESS');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_FILE_ERROR');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_FILE_SUCCESSFULLY_UPLOADED');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_VALIDATION_ERROR_DUPLICATE');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_VALIDATION_ERROR_SIZELIMITMIN');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_VALIDATION_ERROR_SIZELIMITMAX');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_VALIDATION_ERROR_FILELISTMAX');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_VALIDATION_ERROR_FILELISTSIZEMAX');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_ERROR_HTTPSTATUS');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_ERROR_SECURITYERROR');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_ERROR_IOERROR');
            Text::script('JLIB_HTML_BEHAVIOR_UPLOADER_ALL_FILES');
        }
        if (isset(self::$loaded[__METHOD__][$id])) {
            return;
        }
        $onFileSuccess = '\\function(file, response) {
			var json = new Hash(JSON.decode(response, true) || {});

			if (json.get(\'status\') == \'1\') {
				file.element.addClass(\'file-success\');
				file.info.set(\'html\', \'<strong>\' + Joomla.JText._(\'JLIB_HTML_BEHAVIOR_UPLOADER_FILE_SUCCESSFULLY_UPLOADED\') + \'</strong>\');
			} else {
				file.element.addClass(\'file-failed\');
				file.info.set(\'html\', \'<strong>\' +
					Joomla.JText._(\'JLIB_HTML_BEHAVIOR_UPLOADER_ERROR_OCCURRED\',
						\'An Error Occurred\').substitute({ error: json.get(\'error\') }) + \'</strong>\');
			}
		}';
        // Setup options object
        $opt['verbose'] = true;
        $opt['url'] = isset($params['targetURL']) ? $params['targetURL'] : null;
        $opt['path'] = isset($params['swf']) ? $params['swf'] : Uri::root(true) . '/media/system/swf/uploader.swf';
        $opt['height'] = isset($params['height']) && $params['height'] ? (int) $params['height'] : null;
        $opt['width'] = isset($params['width']) && $params['width'] ? (int) $params['width'] : null;
        $opt['multiple'] = isset($params['multiple']) && !$params['multiple'] ? false : true;
        $opt['queued'] = isset($params['queued']) && !$params['queued'] ? (int) $params['queued'] : null;
        $opt['target'] = isset($params['target']) ? $params['target'] : '\\document.id(\'upload-browse\')';
        $opt['instantStart'] = isset($params['instantStart']) && $params['instantStart'] ? true : false;
        $opt['allowDuplicates'] = isset($params['allowDuplicates']) && !$params['allowDuplicates'] ? false : true;
        // "limitSize" is the old parameter name.  Remove in 1.7
        $opt['fileSizeMax'] = isset($params['limitSize']) && $params['limitSize'] ? (int) $params['limitSize'] : null;
        // "fileSizeMax" is the new name.  If supplied, it will override the old value specified for limitSize
        $opt['fileSizeMax'] = isset($params['fileSizeMax']) && $params['fileSizeMax'] ? (int) $params['fileSizeMax'] : $opt['fileSizeMax'];
        $opt['fileSizeMin'] = isset($params['fileSizeMin']) && $params['fileSizeMin'] ? (int) $params['fileSizeMin'] : null;
        // "limitFiles" is the old parameter name.  Remove in 1.7
        $opt['fileListMax'] = isset($params['limitFiles']) && $params['limitFiles'] ? (int) $params['limitFiles'] : null;
        // "fileListMax" is the new name.  If supplied, it will override the old value specified for limitFiles
        $opt['fileListMax'] = isset($params['fileListMax']) && $params['fileListMax'] ? (int) $params['fileListMax'] : $opt['fileListMax'];
        $opt['fileListSizeMax'] = isset($params['fileListSizeMax']) && $params['fileListSizeMax'] ? (int) $params['fileListSizeMax'] : null;
        // "types" is the old parameter name.  Remove in 1.7
        $opt['typeFilter'] = isset($params['types']) ? '\\' . $params['types'] : '\\{Joomla.JText._(\'JLIB_HTML_BEHAVIOR_UPLOADER_ALL_FILES\'): \'*.*\'}';
        $opt['typeFilter'] = isset($params['typeFilter']) ? '\\' . $params['typeFilter'] : $opt['typeFilter'];
        // Optional functions
        $opt['createReplacement'] = isset($params['createReplacement']) ? '\\' . $params['createReplacement'] : null;
        $opt['onFileComplete'] = isset($params['onFileComplete']) ? '\\' . $params['onFileComplete'] : null;
        $opt['onBeforeStart'] = isset($params['onBeforeStart']) ? '\\' . $params['onBeforeStart'] : null;
        $opt['onStart'] = isset($params['onStart']) ? '\\' . $params['onStart'] : null;
        $opt['onComplete'] = isset($params['onComplete']) ? '\\' . $params['onComplete'] : null;
        $opt['onFileSuccess'] = isset($params['onFileSuccess']) ? '\\' . $params['onFileSuccess'] : $onFileSuccess;
        if (!isset($params['startButton'])) {
            $params['startButton'] = 'upload-start';
        }
        if (!isset($params['clearButton'])) {
            $params['clearButton'] = 'upload-clear';
        }
        $opt['onLoad'] = '\\function() {
				document.id(\'' . $id . '\').removeClass(\'hide\'); // we show the actual UI
				document.id(\'upload-noflash\').destroy(); // ... and hide the plain form

				// We relay the interactions with the overlayed flash to the link
				this.target.addEvents({
					click: function() {
						return false;
					},
					mouseenter: function() {
						this.addClass(\'hover\');
					},
					mouseleave: function() {
						this.removeClass(\'hover\');
						this.blur();
					},
					mousedown: function() {
						this.focus();
					}
				});

				// Interactions for the 2 other buttons

				document.id(\'' . $params['clearButton'] . '\').addEvent(\'click\', function() {
					Uploader.remove(); // remove all files
					return false;
				});

				document.id(\'' . $params['startButton'] . '\').addEvent(\'click\', function() {
					Uploader.start(); // start upload
					return false;
				});
			}';
        $options = Html::getJSObject($opt);
        // Attach tooltips to document
        $uploaderInit = 'window.addEvent(\'domready\', function(){
				var Uploader = new FancyUpload2(document.id(\'' . $id . '\'), document.id(\'' . $upload_queue . '\'), ' . $options . ' );
				});';
        $document->addScriptDeclaration($uploaderInit);
        // Set static array
        self::$loaded[__METHOD__][$id] = true;
        return;
    }
 /**
  * Test...
  *
  * @covers  Joomla\Language\Text::script
  *
  * @return  void
  *
  * @since   1.1.2
  */
 public function testScript()
 {
     $string = 'foobar';
     $key = strtoupper($string);
     $strings = Text::script($string);
     $this->assertArrayHasKey($key, $strings);
     $this->assertEquals($string, $strings[$key]);
     $string = 'foo\\\\bar';
     $key = strtoupper($string);
     $strings = Text::script($string, array('interpretBackSlashes' => true));
     $this->assertArrayHasKey($key, $strings);
     $this->assertEquals('foo\\bar', $strings[$key]);
     $string = "foo\\bar's";
     $key = strtoupper($string);
     $strings = Text::script($string, array('jsSafe' => true));
     $this->assertArrayHasKey($key, $strings);
     $this->assertEquals("foo\\\\bar\\'s", $strings[$key]);
 }