From be28b979d4e17f694498d975b005757fe8db3673 Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 24 Aug 2015 16:07:52 +0200 Subject: [PATCH] Dev Removed unused files. --- application/components/AuditArray.php | 73 - .../components/SessionWriteNotifier.php | 91 - .../controllers/admin/authentication.php | 300 - application/controllers/admin/questions.php | 1110 --- .../ExtendedClientScript.php | 309 - .../ExtendedClientScript/cssmin/cssmin.php | 5080 -------------- .../ExtendedClientScript/jsmin/JSMin.php | 374 - application/extensions/Menu/MenuWidget.php | 653 -- application/extensions/Menu/assets/nav.css | 97 - application/extensions/Menu/assets/nav.js | 7 - .../extensions/Menu/views/adminmenu.php | 29 - .../extensions/yii-jsoneditor/JsonEditor.php | 6 +- .../jsoneditor-2.3.6/HISTORY.md | 296 - .../yii-jsoneditor/jsoneditor-2.3.6/LICENSE | 176 - .../yii-jsoneditor/jsoneditor-2.3.6/NOTICE | 17 - .../yii-jsoneditor/jsoneditor-2.3.6/README.md | 114 - .../jsoneditor-2.3.6/docs/api.md | 191 - .../jsoneditor-2.3.6/docs/usage.md | 137 - .../examples/01_basic_usage.html | 45 - .../jsoneditor-2.3.6/examples/02_viewer.html | 40 - .../examples/03_switch_mode.html | 70 - .../requirejs_demo/requirejs_demo.html | 19 - .../examples/requirejs_demo/scripts/main.js | 25 - .../requirejs_demo/scripts/require.js | 35 - .../jsoneditor-2.3.6/img/jsoneditor-icons.png | Bin 14438 -> 0 bytes .../jsoneditor-2.3.6/jsoneditor-min.css | 1 - .../jsoneditor-2.3.6/jsoneditor-min.js | 34 - .../jsoneditor-2.3.6/jsoneditor.css | 623 -- .../jsoneditor-2.3.6/jsoneditor.js | 6041 ----------------- .../jsoneditor-2.3.6/lib/ace/ace.js | 11 - .../jsoneditor-2.3.6/lib/ace/ext-searchbox.js | 1 - .../jsoneditor-2.3.6/lib/ace/mode-json.js | 1 - .../lib/ace/theme-jsoneditor.js | 144 - .../lib/ace/theme-textmate.js | 163 - .../jsoneditor-2.3.6/lib/ace/worker-json.js | 1 - .../jsoneditor-2.3.6/lib/jsonlint/README.md | 62 - .../jsoneditor-2.3.6/lib/jsonlint/jsonlint.js | 432 -- application/helpers/common_helper.php | 131 - composer.json | 3 +- composer.lock | 38 +- 40 files changed, 40 insertions(+), 16940 deletions(-) delete mode 100644 application/components/AuditArray.php delete mode 100644 application/components/SessionWriteNotifier.php delete mode 100644 application/controllers/admin/authentication.php delete mode 100644 application/controllers/admin/questions.php delete mode 100644 application/extensions/ExtendedClientScript/ExtendedClientScript.php delete mode 100644 application/extensions/ExtendedClientScript/cssmin/cssmin.php delete mode 100644 application/extensions/ExtendedClientScript/jsmin/JSMin.php delete mode 100644 application/extensions/Menu/MenuWidget.php delete mode 100644 application/extensions/Menu/assets/nav.css delete mode 100644 application/extensions/Menu/assets/nav.js delete mode 100644 application/extensions/Menu/views/adminmenu.php delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/HISTORY.md delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/LICENSE delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/NOTICE delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/README.md delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/docs/api.md delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/docs/usage.md delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/01_basic_usage.html delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/02_viewer.html delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/03_switch_mode.html delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/requirejs_demo/requirejs_demo.html delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/requirejs_demo/scripts/main.js delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/requirejs_demo/scripts/require.js delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/img/jsoneditor-icons.png delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/jsoneditor-min.css delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/jsoneditor-min.js delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/jsoneditor.css delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/jsoneditor.js delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/ace.js delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/ext-searchbox.js delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/mode-json.js delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/theme-jsoneditor.js delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/theme-textmate.js delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/worker-json.js delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/jsonlint/README.md delete mode 100644 application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/jsonlint/jsonlint.js diff --git a/application/components/AuditArray.php b/application/components/AuditArray.php deleted file mode 100644 index 488eacb1ee2..00000000000 --- a/application/components/AuditArray.php +++ /dev/null @@ -1,73 +0,0 @@ -data[$offset]); - } - - /** - * (PHP 5 >= 5.0.0)
- * Offset to retrieve - * @link http://php.net/manual/en/arrayaccess.offsetget.php - * @param mixed $offset

- * The offset to retrieve. - *

- * @return mixed Can return all value types. - */ - public function offsetGet($offset) - { - return $this->data[$offset]; - } - - /** - * (PHP 5 >= 5.0.0)
- * Offset to set - * @link http://php.net/manual/en/arrayaccess.offsetset.php - * @param mixed $offset

- * The offset to assign the value to. - *

- * @param mixed $value

- * The value to set. - *

- * @return void - */ - public function offsetSet($offset, $value) - { -// echo '
';
-//        echo "Writing at $offset: ";
-////        throw new \Exception();
-//        print_r($value);
-//        echo '
'; -// @ob_flush(); - $this->data[$offset] = $value; - } - - /** - * (PHP 5 >= 5.0.0)
- * Offset to unset - * @link http://php.net/manual/en/arrayaccess.offsetunset.php - * @param mixed $offset

- * The offset to unset. - *

- * @return void - */ - public function offsetUnset($offset) - { - //get the trace - $trace = debug_backtrace(); - unset($this->data[$offset]); -// // Get the class that is asking for who awoke it -// $class = $trace[1]['class']; -// if (!isset($trace[1]['class']) || $trace[1]['class'] != 'CHttpSession') { -// throw new \Exception('Writing to session, are we?'); -// } else { -// -// } - - // TODO: Implement offsetUnset() method. - } - -} \ No newline at end of file diff --git a/application/components/SessionWriteNotifier.php b/application/components/SessionWriteNotifier.php deleted file mode 100644 index 6d1628fd008..00000000000 --- a/application/components/SessionWriteNotifier.php +++ /dev/null @@ -1,91 +0,0 @@ -session = &$_SESSION; - } else { - $this->session = $reference; - } - } - public function offsetExists($offset) - { - return isset($this->session[$offset]); - } - - /** - * (PHP 5 >= 5.0.0)
- * Offset to retrieve - * @link http://php.net/manual/en/arrayaccess.offsetget.php - * @param mixed $offset

- * The offset to retrieve. - *

- * @return mixed Can return all value types. - */ - public function offsetGet($offset) - { - if (!isset($this->session[$offset])) { - $this->session[$offset] = []; - } - - if (is_array($this->session[$offset])) { - return new SessionWriteNotifier($this->session[$offset]); - } - return $this->session[$offset]; - // TODO: Implement offsetGet() method. - } - - /** - * (PHP 5 >= 5.0.0)
- * Offset to set - * @link http://php.net/manual/en/arrayaccess.offsetset.php - * @param mixed $offset

- * The offset to assign the value to. - *

- * @param mixed $value

- * The value to set. - *

- * @return void - */ - public function offsetSet($offset, $value) - { - //get the trace - $trace = debug_backtrace(); - - // Get the class that is asking for who awoke it - if (!isset($trace[1]['class']) || $trace[1]['class'] != 'CHttpSession') { - throw new \Exception('Writing to session, are we?'); - } else { - $this->session[$offset] = $value; - } - // TODO: Implement offsetSet() method. - } - - /** - * (PHP 5 >= 5.0.0)
- * Offset to unset - * @link http://php.net/manual/en/arrayaccess.offsetunset.php - * @param mixed $offset

- * The offset to unset. - *

- * @return void - */ - public function offsetUnset($offset) - { - //get the trace - $trace = debug_backtrace(); - - // Get the class that is asking for who awoke it - $class = $trace[1]['class']; - if (!isset($trace[1]['class']) || $trace[1]['class'] != 'CHttpSession') { - throw new \Exception('Writing to session, are we?'); - } else { - unset($this->session[$offset]); - } - - // TODO: Implement offsetUnset() method. - } - -} \ No newline at end of file diff --git a/application/controllers/admin/authentication.php b/application/controllers/admin/authentication.php deleted file mode 100644 index 51cff54097b..00000000000 --- a/application/controllers/admin/authentication.php +++ /dev/null @@ -1,300 +0,0 @@ -_redirectIfLoggedIn(); - - // Make sure after first run / update the authdb plugin is registered and active - // it can not be deactivated - if (!class_exists('Authdb', false)) { - $plugin = Plugin::model()->findByAttributes(array('name'=>'Authdb')); - if (!$plugin) { - $plugin = new Plugin(); - $plugin->name = 'Authdb'; - $plugin->active = 1; - $plugin->save(); - App()->getPluginManager()->loadPlugin('Authdb', $plugin->id); - } else { - $plugin->active = 1; - $plugin->save(); - } - } - - $beforeLogin = new PluginEvent('beforeLogin'); - $beforeLogin->set('identity', new LSUserIdentity('', '')); - - App()->getPluginManager()->dispatchEvent($beforeLogin); - /* @var $identity LSUserIdentity */ - $identity = $beforeLogin->get('identity'); - - if (!$beforeLogin->isStopped() && is_null(App()->getRequest()->getPost('login_submit'))) - { - if (!is_null($beforeLogin->get('default'))) { - $aData['defaultAuth'] = $beforeLogin->get('default'); - } - $newLoginForm = new PluginEvent('newLoginForm'); - App()->getPluginManager()->dispatchEvent($newLoginForm); - $aData['summary'] = $this->_getSummary('logout'); - $aData['pluginContent'] = $newLoginForm->getAllContent(); - $this->_renderWrappedTemplate('authentication', 'login', $aData); - } else { - // Handle getting the post and populating the identity there - $authMethod = App()->getRequest()->getPost('authMethod', $identity->plugin); - $identity->plugin = $authMethod; - - $event = new PluginEvent('afterLoginFormSubmit'); - $event->set('identity', $identity); - App()->getPluginManager()->dispatchEvent($event, array($authMethod)); - $identity = $event->get('identity'); - - // Now authenticate - if ($identity->authenticate()) - { - FailedLoginAttempt::model()->deleteAttempts(); - App()->user->setState('plugin', $authMethod); - $this->getController()->_GetSessionUserRights(Yii::app()->session['loginID']); - Yii::app()->session['just_logged_in'] = true; - Yii::app()->session['loginsummary'] = $this->_getSummary(); - - $event = new PluginEvent('afterSuccessfulLogin'); - App()->getPluginManager()->dispatchEvent($event); - - $this->_doRedirect(); - - } else { - // Failed - $event = new PluginEvent('afterFailedLoginAttempt'); - $event->set('identity', $identity); - App()->getPluginManager()->dispatchEvent($event); - - $message = $identity->errorMessage; - if (empty($message)) { - // If no message, return a default message - $message = gT('Incorrect username and/or password!'); - } - App()->user->setFlash('loginError', $message); - $this->getController()->redirect(array('/admin/authentication/sa/login')); - } - } - } - - /** - * Logout user - */ - public function logout() - { - /* Adding beforeLogout event */ - $beforeLogout = new PluginEvent('beforeLogout'); - App()->getPluginManager()->dispatchEvent($beforeLogout); - // Expire the CSRF cookie - $cookie = new CHttpCookie('YII_CSRF_TOKEN', ''); - $cookie->expire = time()-3600; - Yii::app()->request->cookies['YII_CSRF_TOKEN'] = $cookie; - App()->user->logout(); - App()->user->setFlash('loginmessage', gT('Logout successful.')); - - /* Adding afterLogout event */ - $event = new PluginEvent('afterLogout'); - App()->getPluginManager()->dispatchEvent($event); - - $this->getController()->redirect(array('/admin/authentication/sa/login')); - } - - /** - * Forgot Password screen - */ - public function forgotpassword() - { - $this->_redirectIfLoggedIn(); - - if (!Yii::app()->request->getPost('action')) - { - $this->_renderWrappedTemplate('authentication', 'forgotpassword'); - } - else - { - $sUserName = Yii::app()->request->getPost('user'); - $sEmailAddr = Yii::app()->request->getPost('email'); - - $aFields = User::model()->findAllByAttributes(array('users_name' => $sUserName, 'email' => $sEmailAddr)); - - // Preventing attacker from easily knowing whether the user and email address are valid or not (and slowing down brute force attacks) - usleep(rand(Yii::app()->getConfig("minforgottenpasswordemaildelay"),Yii::app()->getConfig("maxforgottenpasswordemaildelay"))); - - if (count($aFields) < 1 || ($aFields[0]['uid'] != 1 && !Permission::model()->hasGlobalPermission('auth_db','read',$aFields[0]['uid']))) - { - // Wrong or unknown username and/or email. For security reasons, we don't show a fail message - $aData['message'] = '
'.gT($this->sent_email_message).'
'; - } - else - { - $aData['message'] = '
'.$this->_sendPasswordEmail($sEmailAddr, $aFields).'
'; - } - $this->_renderWrappedTemplate('authentication', 'message', $aData); - } - } - - /** - * Send the forgot password email - * - * @param string $sEmailAddr - * @param array $aFields - */ - private function _sendPasswordEmail($sEmailAddr, $aFields) - { - $sFrom = Yii::app()->getConfig("siteadminname") . " <" . Yii::app()->getConfig("siteadminemail") . ">"; - $sTo = $sEmailAddr; - $sSubject = gT('User data'); - $sNewPass = createPassword(); - $sSiteName = Yii::app()->getConfig('sitename'); - $sSiteAdminBounce = Yii::app()->getConfig('siteadminbounce'); - - $username = sprintf(gT('Username: %s'), $aFields[0]['users_name']); - $email = sprintf(gT('Email: %s'), $sEmailAddr); - $password = sprintf(gT('New password: %s'), $sNewPass); - - $body = array(); - $body[] = sprintf(gT('Your user data for accessing %s'), Yii::app()->getConfig('sitename')); - $body[] = $username; - $body[] = $password; - $body = implode("\n", $body); - - if (SendEmailMessage($body, $sSubject, $sTo, $sFrom, $sSiteName, false, $sSiteAdminBounce)) - { - User::model()->updatePassword($aFields[0]['uid'], $sNewPass); - // For security reasons, we don't show a successful message - $sMessage = gT($this->sent_email_message); - } - else - { - $sMessage = gT('Email failed'); - } - - return $sMessage; - } - - /** - * Get's the summary - * @param string $sMethod login|logout - * @param string $sSummary Default summary - * @return string Summary - */ - private function _getSummary($sMethod = 'login', $sSummary = '') - { - if (!empty($sSummary)) - { - return $sSummary; - } - - switch ($sMethod) { - case 'logout' : - $sSummary = gT('Please log in first.'); - break; - - case 'login' : - default : - $sSummary = '
' . sprintf(gT('Welcome %s!'), Yii::app()->session['full_name']) . '
 '; - if (!empty(Yii::app()->session['redirect_after_login']) && strpos(Yii::app()->session['redirect_after_login'], 'logout') === FALSE) - { - Yii::app()->session['metaHeader'] = ''; - $sSummary = '

' . gT('Reloading screen. Please wait.') . ''; - unset(Yii::app()->session['redirect_after_login']); - } - break; - } - - return $sSummary; - } - - /** - * Redirects a logged in user to the administration page - */ - private function _redirectIfLoggedIn() - { - if (!Yii::app()->user->getIsGuest()) - { - $this->getController()->redirect(array('/admin')); - } - } - - /** - * Check if a user can log in - * @return bool|array - */ - private function _userCanLogin() - { - $failed_login_attempts = FailedLoginAttempt::model(); - $failed_login_attempts->cleanOutOldAttempts(); - - if ($failed_login_attempts->isLockedOut()) - { - return $this->_getAuthenticationFailedErrorMessage(); - } - else - { - return true; - } - } - - /** - * Redirect after login - */ - private function _doRedirect() - { - $returnUrl = App()->user->getReturnUrl(array('/admin')); - $this->getController()->redirect($returnUrl); - } - - /** - * Renders template(s) wrapped in header and footer - * - * @param string $sAction Current action, the folder to fetch views from - * @param string|array $aViewUrls View url(s) - * @param array $aData Data to be passed on. Optional. - */ - protected function _renderWrappedTemplate($sAction = 'authentication', $aViewUrls = array(), $aData = array()) - { - $aData['display']['menu_bars'] = false; - parent::_renderWrappedTemplate($sAction, $aViewUrls, $aData); - } - -} diff --git a/application/controllers/admin/questions.php b/application/controllers/admin/questions.php deleted file mode 100644 index da79d3c2927..00000000000 --- a/application/controllers/admin/questions.php +++ /dev/null @@ -1,1110 +0,0 @@ -getConfig('tempdir') . DIRECTORY_SEPARATOR . randomChars(20); - $sExtension = pathinfo($_FILES['the_file']['name'], PATHINFO_EXTENSION); - - if (!@move_uploaded_file($_FILES['the_file']['tmp_name'], $sFullFilepath)) - $fatalerror = sprintf(gT("An error occurred uploading your file. This may be caused by incorrect permissions in your %s folder."), Yii::app()->getConfig('tempdir')); - - // validate that we have a SID and GID - if (!$surveyid) - $fatalerror .= gT("No SID (Survey) has been provided. Cannot import question."); - - if (!$gid) - $fatalerror .= gT("No GID (Group) has been provided. Cannot import question"); - - if (isset($fatalerror)) - { - unlink($sFullFilepath); - $this->getController()->error($fatalerror); - } - - // IF WE GOT THIS FAR, THEN THE FILE HAS BEEN UPLOADED SUCCESFULLY - Yii::app()->loadHelper('admin/import'); - - if (strtolower($sExtension) == 'lsq') - $aImportResults = XMLImportQuestion($sFullFilepath, $surveyid, $gid); - else - $this->getController()->error(gT('Unknown file extension')); - - fixLanguageConsistency($surveyid); - - if (isset($aImportResults['fatalerror'])) - { - unlink($sFullFilepath); - $this->getController()->error($aImportResults['fatalerror']); - } - - unlink($sFullFilepath); - - $aData['aImportResults'] = $aImportResults; - $aData['surveyid'] = $surveyid; - $aData['gid'] = $gid; - $aData['sExtension'] = $sExtension; - $aViewUrls[] = 'import_view'; - } - - $this->_renderWrappedTemplate('survey/Question', $aViewUrls, $aData); - } - - /** - * Load edit default values of a question screen - * - * @access public - * @param int $surveyid - * @param int $gid - * @param int $qid - * @return void - */ - public function editdefaultvalues($surveyid, $gid, $qid) - { - $surveyid = sanitize_int($surveyid); - $gid = sanitize_int($gid); - $qid = sanitize_int($qid); - - - Yii::app()->loadHelper('surveytranslator'); - - $questlangs = Survey::model()->findByPk($surveyid)->additionalLanguages; - $baselang = Survey::model()->findByPk($surveyid)->language; - array_unshift($questlangs, $baselang); - - $questionrow = Question::model()->findByAttributes(array( - 'qid' => $qid, - 'gid' => $gid, - 'language' => $baselang - ))->attributes; - $qtproperties = getQuestionTypeList('', 'array'); - - $langopts = array(); - foreach ($questlangs as $language) - { - $langopts[$language] = array(); - $langopts[$language][$questionrow['type']] = array(); - - // If there are answerscales - if ($qtproperties[$questionrow['type']]['answerscales'] > 0) - { - for ($scale_id = 0; $scale_id < $qtproperties[$questionrow['type']]['answerscales']; $scale_id++) - { - $langopts[$language][$questionrow['type']][$scale_id] = array(); - - $defaultvalue = DefaultValue::model()->findByAttributes(array( - 'specialtype' => '', - 'qid' => $qid, - 'scale_id' => $scale_id, - 'language' => $language - )); - - $defaultvalue = $defaultvalue != null ? $defaultvalue->defaultvalue : null; - - $langopts[$language][$questionrow['type']][$scale_id]['defaultvalue'] = $defaultvalue; - - $answerresult = Answer::model()->findAllByAttributes(array( - 'qid' => $qid, - 'language' => $language - ), array('order' => 'sortorder')); - $langopts[$language][$questionrow['type']][$scale_id]['answers'] = $answerresult; - - if ($questionrow['other'] == 'Y') - { - $defaultvalue = DefaultValue::model()->findByAttributes(array( - 'specialtype' => 'other', - 'qid' => $qid, - 'scale_id' => $scale_id, - 'language' => $language - )); - - $defaultvalue = $defaultvalue != null ? $defaultvalue->defaultvalue : null; - $langopts[$language][$questionrow['type']]['Ydefaultvalue'] = $defaultvalue; - } - } - } - - // If there are subquestions and no answerscales - if ($qtproperties[$questionrow['type']]['answerscales'] == 0 && - $qtproperties[$questionrow['type']]['subquestions'] > 0) - { - for ($scale_id = 0; $scale_id < $qtproperties[$questionrow['type']]['subquestions']; $scale_id++) - { - $langopts[$language][$questionrow['type']][$scale_id] = array(); - - $sqresult = Question::model()->findAllByAttributes(array( - 'sid' => $surveyid, - 'gid' => $gid, - 'parent_qid' => $qid, - 'language' => $language, - 'scale_id' => 0 - ), array('order' => 'question_order')); - - $langopts[$language][$questionrow['type']][$scale_id]['sqresult'] = array(); - - $options = array(); - if ($questionrow['type'] == 'M' || $questionrow['type'] == 'P') - $options = array('' => gT(''), 'Y' => gT('Checked')); - - foreach ($sqresult as $aSubquestion) - { - $defaultvalue = DefaultValue::model()->findByAttributes(array( - 'specialtype' => '', - 'qid' => $qid, - 'sqid' => $aSubquestion['qid'], - 'scale_id' => $scale_id, - 'language' => $language - )); - $defaultvalue = $defaultvalue != null ? $defaultvalue->defaultvalue : null; - - $aSubquestion = $aSubquestion->attributes; - $aSubquestion['defaultvalue'] = $defaultvalue; - $aSubquestion['options'] = $options; - - $langopts[$language][$questionrow['type']][$scale_id]['sqresult'][] = $aSubquestion; - } - } - } - if ($qtproperties[$questionrow['type']]['answerscales'] == 0 && - $qtproperties[$questionrow['type']]['subquestions'] == 0) - { - $defaultvalue = DefaultValue::model()->findByAttributes(array( - 'specialtype' => '', - 'qid' => $qid, - 'scale_id' => 0, - 'language' => $language - )); - $langopts[$language][$questionrow['type']][0] = $defaultvalue != null ? $defaultvalue->defaultvalue : null; - } - - } - - $aData = array( - 'qid' => $qid, - 'surveyid' => $surveyid, - 'langopts' => $langopts, - 'questionrow' => $questionrow, - 'questlangs' => $questlangs, - 'gid' => $gid, - 'qtproperties' => $qtproperties, - 'baselang' => $baselang, - ); - $aData['display']['menu_bars']['surveysummary'] = 'editdefaultvalues'; - $aData['display']['menu_bars']['qid_action'] = 'editdefaultvalues'; - - $this->_renderWrappedTemplate('survey/Question', 'editdefaultvalues_view', $aData); - } - - /** - * Load complete editing of answer options screen. - * - * @access public - * @param int $surveyid - * @param int $gid - * @param int $qid - * @return - */ - public function answeroptions($surveyid, $gid, $qid) - { - $surveyid = sanitize_int($surveyid); - $qid = sanitize_int($qid); - $gid = sanitize_int($gid); - App()->getClientScript()->registerScriptFile(Yii::app()->getConfig('adminscripts') . 'answers.js'); - //App()->getClientScript()->registerScriptFile(Yii::app()->getConfig('generalscripts') . 'jquery/jquery.blockUI.js'); - - $aData['display']['menu_bars']['surveysummary'] = 'viewgroup'; - $aData['display']['menu_bars']['gid_action'] = 'addquestion'; - $aData['display']['menu_bars']['qid_action'] = 'editansweroptions'; - - $aData['surveyid'] = $surveyid; - $aData['gid'] = $gid; - $aData['qid'] = $qid; - - Yii::app()->session['FileManagerContext'] = "edit:answer:{$surveyid}"; - - $aViewUrls = $this->_editansweroptions($surveyid, $gid, $qid); - - $this->_renderWrappedTemplate('survey/Question', $aViewUrls, $aData); - } - - /** - * Load editing of answer options specific screen only. - * - * @access public - * @param int $surveyid - * @param int $gid - * @param int $qid - * @return void - */ - public function _editansweroptions($surveyid, $gid, $qid) - { - Yii::app()->loadHelper('database'); - $surveyid = sanitize_int($surveyid); - $qid = sanitize_int($qid); - $gid = sanitize_int($gid); - - // Get languages select on survey. - $anslangs = Survey::model()->findByPk($surveyid)->additionalLanguages; - $baselang = Survey::model()->findByPk($surveyid)->language; - - $qrow = Question::model()->findByAttributes(array('qid' => $qid, 'language' => $baselang)); - $qtype = $qrow['type']; - - $qtypes = getQuestionTypeList('', 'array'); - - $scalecount = $qtypes[$qtype]['answerscales']; - - // Check if there is at least one answer - for ($i = 0; $i < $scalecount; $i++) - { - $ans = new CDbCriteria; - $ans->addCondition("qid=$qid")->addCondition("scale_id=$i")->addCondition("language='$baselang'"); - $qresult = Answer::model()->count($ans); - - if ((int)$qresult==0) - { - $oAnswer= new Answer; - $oAnswer->qid = $qid; - $oAnswer->code = 'A1'; - $oAnswer->answer = ""; - $oAnswer->language = $baselang; - $oAnswer->sortorder = 0; - $oAnswer->scale_id = $i; - $oAnswer->save(); - } - } - - - // Check that there are answers for every language supported by the survey - for ($i = 0; $i < $scalecount; $i++) - { - foreach ($anslangs as $language) - { - $ans = new CDbCriteria; - $ans->addCondition("qid=$qid")->addCondition("scale_id=$i")->addCondition("language='$language'"); - $iAnswerCount = Answer::model()->count($ans); - - // Means that no record for the language exists in the answers table - if (empty($iAnswerCount)) - { - foreach (Answer::model()->findAllByAttributes(array( - 'qid' => $qid, - 'scale_id' => $i, - 'language' => $baselang - )) as $answer) - - $oAnswer= new Answer; - $oAnswer->qid = $answer->qid; - $oAnswer->code = $answer->code; - $oAnswer->answer = $answer->answer; - $oAnswer->language = $language; - $oAnswer->sortorder = $answer->sortorder; - $oAnswer->scale_id = $i; - $oAnswer->assessment_value = $answer->assessment_value; - $oAnswer->save(); - } - } - } - - // Makes an array with ALL the languages supported by the survey -> $anslangs - array_unshift($anslangs, $baselang); - - // Delete the answers in languages not supported by the survey - $criteria = new CDbCriteria; - $criteria->addColumnCondition(array('qid' => $qid)); - $criteria->addNotInCondition('language', $anslangs); - $languageresult = Answer::model()->deleteAll($criteria); - - if (!isset($_POST['ansaction'])) - { - // Check if any nulls exist. If they do, redo the sortorders - $ans = new CDbCriteria; - $ans->addCondition("qid=$qid")->addCondition("scale_id=$i")->addCondition("language='$baselang'"); - $cacount = Answer::model()->count($ans); - if (!empty($cacount)) - Answer::model()->updateSortOrder($qid, Survey::model()->findByPk($surveyid)->language); - } - - Yii::app()->loadHelper('admin/htmleditor'); - - $row = Answer::model()->findByAttributes(array( - 'qid' => $qid, - 'language' => Survey::model()->findByPk($surveyid)->language - ), array('order' => 'sortorder desc')); - - if (!is_null($row)) - $maxsortorder = $row->sortorder + 1; - else - $maxsortorder = 1; - - $aData['surveyid'] = $surveyid; - $aData['gid'] = $gid; - $aData['qid'] = $qid; - $aData['anslangs'] = $anslangs; - $aData['scalecount'] = $scalecount; - - // The following line decides if the assessment input fields are visible or not - $sumresult1 = Survey::model()->with(array('languagesettings'=>array('condition'=>'surveyls_language=language')))->together()->findByAttributes(array('sid' => $surveyid)); - if (is_null($sumresult1)) - $this->getController()->error('Invalid survey ID'); - - $surveyinfo = $sumresult1->attributes; - $surveyinfo = array_merge($surveyinfo, $sumresult1->defaultlanguage->attributes); - $surveyinfo = array_map('flattenText', $surveyinfo); - $assessmentvisible = ($surveyinfo['assessments'] == 'Y' && $qtypes[$qtype]['assessable'] == 1); - $aData['assessmentvisible'] = $assessmentvisible; - - $aViewUrls['answerOptions_view'][] = $aData; - - return $aViewUrls; - } - - /** - * Load complete subquestions screen. - * - * @access public - * @param int $surveyid - * @param int $gid - * @param int $qid - * @return void - */ - public function subquestions($surveyid, $gid, $qid) - { - $aData['surveyid'] = $surveyid = sanitize_int($surveyid); - $aData['gid'] = $gid = sanitize_int($gid); - $aData['qid'] = $qid = sanitize_int($qid); - - App()->getClientScript()->registerScriptFile(Yii::app()->getConfig('adminscripts') . 'subquestions.js'); - Yii::app()->session['FileManagerContext'] = "edit:answer:{$surveyid}"; - - $aData['display']['menu_bars']['surveysummary'] = 'viewgroup'; - $aData['display']['menu_bars']['gid_action'] = 'addquestion'; - $aData['display']['menu_bars']['qid_action'] = 'editsubquestions'; - $aViewUrls = $this->_editsubquestion($surveyid, $gid, $qid); - - $this->_renderWrappedTemplate('survey/Question', $aViewUrls, $aData); - } - - /** - * Load only subquestion specific screen only. - * - * @access public - * @param int $surveyid - * @param int $gid - * @param int $qid - * @return void - */ - public function _editsubquestion($surveyid, $gid, $qid) - { - $surveyid = sanitize_int($surveyid); - $qid = sanitize_int($qid); - $gid = sanitize_int($gid); - - // Get languages select on survey. - $anslangs = Survey::model()->findByPk($surveyid)->additionalLanguages; - $baselang = Survey::model()->findByPk($surveyid)->language; - - $aParentQuestion = Question::model()->findByPk(array('qid' => $qid, 'language' => $baselang))->attributes; - - $sQuestiontype = $aParentQuestion['type']; - $aQuestiontypeInfo = getQuestionTypeList($sQuestiontype, 'array'); - $iScaleCount = $aQuestiontypeInfo[$sQuestiontype]['subquestions']; - - for ($iScale = 0; $iScale < $iScaleCount; $iScale++) - { - $subquestiondata = Question::model()->findAllByAttributes(array( - 'parent_qid' => $qid, - 'language' => $baselang, - 'scale_id' => $iScale - )); - - if (empty($subquestiondata)) - { - //Question::model()->insert(); - $data = array( - 'sid' => $surveyid, - 'gid' => $gid, - 'parent_qid' => $qid, - 'title' => 'SQ001', - 'question' => '', - 'question_order' => 1, - 'language' => $baselang, - 'relevance' => '1', - 'scale_id' => $iScale, - ); - Question::model()->insertRecords($data); - - $subquestiondata = Question::model()->findAllByAttributes(array( - 'parent_qid' => $qid, - 'language' => $baselang, - 'scale_id' => $iScale - )); - } - - // Check that there are subquestions for every language supported by the survey - foreach ($anslangs as $language) - { - foreach ($subquestiondata as $row) - { - $qrow = Question::model()->count(' - parent_qid = :qid AND - language = :language AND - qid = '.$row->qid.' AND - scale_id = :iScale', - array( - ':qid' => $qid, - ':language' => $language, - ':iScale' => $iScale - )); - - // Means that no record for the language exists in the questions table - if (empty($qrow)) - { - switchMSSQLIdentityInsert('questions', true); - - $question = new Question; - $question->qid = $row->qid; - $question->sid = $surveyid; - $question->gid = $row->gid; - $question->parent_qid = $qid; - $question->title = $row->title; - $question->question = $row->question; - $question->question_order = $row->question_order; - $question->language = $language; - $question->scale_id = $iScale; - $question->relevance = $row->relevance; - $question->save(); - /** //activerecord is not not new bugfix! - Question::model()->insert(array( - 'qid' => $row->qid, - 'sid' => $surveyid, - 'gid' => $row->gid, - 'parent_qid' => $qid, - 'title' => $row->title, - 'question' => $row->question, - 'question_order' => $row->question_order, - 'language' => $language, - 'scale_id' => $iScale, - )); - */ - switchMSSQLIdentityInsert('questions', false); - } - } - } - } - - array_unshift($anslangs, $baselang); - - // Delete the subquestions in languages not supported by the survey - $criteria = new CDbCriteria; - $criteria->addColumnCondition(array('parent_qid' => $qid)); - $criteria->addNotInCondition('language', $anslangs); - Question::model()->deleteAll($criteria); - - // Check sort order for subquestions - $qresult = Question::model()->findByAttributes(array('qid' => $qid, 'language' => $baselang)); - if (!is_null($qresult)) - $qtype = $qresult->type; - - if (!empty($_POST['ansaction'])) - { - // Check if any nulls exist. If they do, redo the sortorders - $cacount = Question::model()->count(array( - 'parent_qid' => $qid, - 'question_order' => null, - 'language' => $baselang - )); - - if ($cacount) - Answer::model()->updateSortOrder($qid, Survey::model()->findByPk($surveyid)->language); - } - - Yii::app()->loadHelper('admin/htmleditor'); - - // Print Key Control JavaScript - $result = Question::model()->findAllBYAttributes(array( - 'parent_qid' => $qid, - 'language' => Survey::model()->findByPk($surveyid)->language - ), array('order' => 'question_order desc')); - - $aData['anscount'] = $anscount = count($result); - $row = $result[0]->attributes; - $aData['row'] = $row; - $maxsortorder = $row['question_order'] + 1; - - /** - * The following line decides if the assessment input fields are visible or not - * for some question types the assessment values is set in the label set instead of the answers - */ - $qtypes = getQuestionTypeList('', 'array'); - Yii::app()->loadHelper('surveytranslator'); - - $aData['scalecount'] = $scalecount = $qtypes[$qtype]['subquestions']; - - $sumresult1 = Survey::model()->with(array('languagesettings'=>array('condition'=>'surveyls_language=language')))->together()->findByAttributes(array('sid' => $surveyid)); - if ($sumresult1 == null) - $this->getController()->error('Invalid survey id'); - - $surveyinfo = $sumresult1->attributes; - $surveyinfo = array_merge($surveyinfo, $sumresult1->defaultlanguage->attributes); - $surveyinfo = array_map('flattenText', $surveyinfo); - - $aData['activated'] = $activated = $surveyinfo['active']; - $aData['surveyid'] = $surveyid; - $aData['gid'] = $gid; - $aData['qid'] = $qid; - $aData['aParentQuestion'] = $aParentQuestion; - $aData['anslangs'] = $anslangs; - $aData['maxsortorder'] = $maxsortorder; - - foreach ($anslangs as $anslang) - { - for ($scale_id = 0; $scale_id < $scalecount; $scale_id++) - { - $criteria = new CDbCriteria; - $criteria->condition = 'parent_qid = :pqid AND language = :language AND scale_id = :scale_id'; - $criteria->order = 'question_order, title ASC'; - $criteria->params = array(':pqid' => $qid, ':language' => $anslang, ':scale_id' => $scale_id); - $aData['results'][$anslang][$scale_id] = Question::model()->findAll($criteria); - } - } - - $aViewUrls['subQuestion_view'][] = $aData; - - return $aViewUrls; - } - - /** - * Load edit/new question screen depending on $action. - * - * @access public - * @param string $action - * @param int $surveyid - * @param int $gid - * @param int $qid - * @return void - */ - public function index($sa, $surveyid, $gid, $qid=null) - { - $action = $sa; - $surveyid = sanitize_int($surveyid); - $gid = sanitize_int($gid); - if (isset($qid)) - $qid = sanitize_int($qid); - - $aViewUrls = array(); - $aData['surveyid'] = $surveyid; - $aData['gid'] = $gid; - $aData['qid'] = $qid; - $aData['display']['menu_bars']['surveysummary'] = 'viewgroup'; - $aData['display']['menu_bars']['gid_action'] = 'addquestion'; - Yii::app()->session['FileManagerContext'] = "create:question:{$surveyid}"; - - if (App()->user->checkAccess('surveycontent', ['crud' => 'read', 'entity' => 'survey', 'entity_id' => $surveyid])) - { - $surveyinfo = getSurveyInfo($surveyid); - Yii::app()->loadHelper('admin/htmleditor'); - Yii::app()->loadHelper('surveytranslator'); - - if (isset($_POST['sortorder'])) - $postsortorder = sanitize_int($_POST['sortorder']); - - $aData['adding'] = $adding = $action == 'addquestion'; - $aData['copying'] = $copying = $action == 'copyquestion'; - $questlangs = Survey::model()->findByPk($surveyid)->additionalLanguages; - $baselang = Survey::model()->findByPk($surveyid)->language; - $questlangs[] = $baselang; - $questlangs = array_flip($questlangs); - - // Prepare selector Mode TODO: with and without image - if (!$adding) - { - Yii::app()->session['FileManagerContext'] = "edit:question:{$surveyid}"; - $aData['display']['menu_bars']['qid_action'] = 'editquestion'; - - $egresult = Question::model()->findAllByAttributes(array('sid' => $surveyid, 'gid' => $gid, 'qid' => $qid)); - - foreach ($egresult as $esrow) - { - if (!array_key_exists($esrow->language, $questlangs)) // Language Exists, BUT ITS NOT ON THE SURVEY ANYMORE. - $esrow->delete(); - else - $questlangs[$esrow->language] = 99; - - if ($esrow->language == $baselang) - { - $esrow = $esrow->attributes; - $basesettings = array( - 'question_order' => $esrow['question_order'], - 'other' => $esrow['other'], - 'mandatory' => $esrow['mandatory'], - 'type' => $esrow['type'], - 'title' => $esrow['title'], - 'preg' => $esrow['preg'], - 'question' => $esrow['question'], - 'help' => $esrow['help'] - ); - } - } - - if (!$egresult) - $this->getController()->error('Invalid question id'); - - while (list($key, $value) = each($questlangs)) - { - if ($value != 99) - { - $arQuestion=new Question; - $arQuestion->qid = $qid; - $arQuestion->sid = $surveyid; - $arQuestion->gid = $gid; - $arQuestion->type = $basesettings['type']; - $arQuestion->title = $basesettings['title']; - $arQuestion->question = $basesettings['question']; - $arQuestion->preg = $basesettings['preg']; - $arQuestion->help = $basesettings['help']; - $arQuestion->other = $basesettings['other']; - $arQuestion->mandatory = $basesettings['mandatory']; - $arQuestion->question_order = $basesettings['question_order']; - $arQuestion->language = $key; - $arQuestion->insert(); - } - } - - $eqresult = Question::model()->with('groups')->together()->findByAttributes(array( - 'sid' => $surveyid, - 'gid' => $gid, - 'qid' => $qid, - 'language' => $baselang - )); - } - else - { - // This is needed to properly color-code content if it contains replacements - LimeExpressionManager::StartProcessingPage(false,Yii::app()->baseUrl,true); // so can click on syntax highlighting to edit questions - } - - $qtypelist = getQuestionTypeList('', 'array'); - $qDescToCode = 'qDescToCode = {'; - $qCodeToInfo = 'qCodeToInfo = {'; - foreach ($qtypelist as $qtype => $qdesc) - { - $qDescToCode .= " '{$qdesc['description']}' : '{$qtype}', \n"; - $qCodeToInfo .= " '{$qtype}' : '" . ls_json_encode($qdesc) . "', \n"; - } - $aData['qTypeOutput'] = "$qDescToCode 'null':'null' }; \n $qCodeToInfo 'null':'null' };"; - - if (!$adding) - { - $eqrow = array_merge($eqresult->attributes, $eqresult->groups->attributes);; - - // Todo: handler in case that record is not found - if ($copying) - $eqrow['title'] = ''; - } - else - { - $eqrow['language'] = $baselang; - $eqrow['title'] = ''; - $eqrow['question'] = ''; - $eqrow['help'] = ''; - $eqrow['type'] = 'T'; - $eqrow['lid'] = 0; - $eqrow['lid1'] = 0; - $eqrow['gid'] = $gid; - $eqrow['other'] = 'N'; - $eqrow['mandatory'] = 'N'; - $eqrow['preg'] = ''; - $eqrow['relevance'] = 1; - $eqrow['group_name'] = ''; - } - $eqrow['conditions_number'] = Condition::Model()->count("qid=:qid", array('qid' => $qid)); - - $aData['eqrow'] = $eqrow; - $aData['surveyid'] = $surveyid; - $aData['gid'] = $gid; - - if (!$adding) - { - $criteria = new CDbCriteria; - $criteria->addColumnCondition(array('sid' => $surveyid, 'gid' => $gid, 'qid' => $qid)); - $criteria->params[':lang'] = $baselang; - $criteria->addCondition('language != :lang'); - $aqresult = Question::model()->findAll($criteria); - $aData['aqresult'] = $aqresult; - } - - $aData['action'] = $action; - - $sumresult1 = Survey::model()->findByPk($surveyid); - if (is_null($sumresult1)) - $this->getController()->error('Invalid Survey ID'); - - $surveyinfo = $sumresult1->attributes; - $surveyinfo = array_map('flattenText', $surveyinfo); - $aData['activated'] = $activated = $surveyinfo['active']; - - if ($activated != "Y") - { - // Prepare selector Class for javascript function - if (Yii::app()->session['questionselectormode'] !== 'default') { - $selectormodeclass = Yii::app()->session['questionselectormode']; - } else { - $selectormodeclass = \SettingGlobal::get('defaultquestionselectormode', 'default'); - } - - $aData['selectormodeclass'] = $selectormodeclass; - } - - if (!$adding) - $qattributes = questionAttributes(); - else - $qattributes = array(); - - if ($adding) - { - // Get the questions for this group - $baselang = Survey::model()->findByPk($surveyid)->language; - $oqresult = Question::model()->findAllByAttributes(array('sid' => $surveyid, 'gid' => $gid, 'language' => $baselang, 'parent_qid'=> 0), array('order' => 'question_order')); - $aData['oqresult'] = $oqresult; - } - App()->getClientScript()->registerScriptFile(Yii::app()->getConfig('adminscripts') . 'questions.js'); - - $aViewUrls['editQuestion_view'][] = $aData; - $aViewUrls['questionJavascript_view'][] = array('type' => $eqrow['type']); - } - else - include('accessDenied.php'); - - $this->_renderWrappedTemplate('survey/Question', $aViewUrls, $aData); - } - - /** - * Function responsible for deleting a question. - * - * @access public - * @param string $action - * @param int $surveyid - * @param int $gid - * @param int $qid - * @return void - */ - public function delete($surveyid, $gid, $qid) - { - $surveyid = sanitize_int($surveyid); - $gid = sanitize_int($gid); - $qid = sanitize_int($qid); - - if (App()->user->checkAccess('surveycontent', ['crud' => 'delete', 'entity' => 'survey', 'entity_id' => $surveyid])) - { - if (!isset($qid)) - $qid = returnGlobal('qid'); - - LimeExpressionManager::RevertUpgradeConditionsToRelevance(NULL,$qid); - - // Check if any other questions have conditions which rely on this question. Don't delete if there are. - // TMSW Condition->Relevance: Allow such deletes - can warn about missing relevance separately. - $ccresult = Condition::model()->findAllByAttributes(array('cqid' => $qid)); - $cccount = count($ccresult); - - // There are conditions dependent on this question - if ($cccount) - { - foreach ($ccresult as $ccr) - { - $qidarray[] = $ccr->qid; - } - if (isset($qidarray)) - $qidlist = implode(", ", $qidarray); - $message =gT("Question could not be deleted. There are conditions for other questions that rely on this question. You cannot delete this question until those conditions are removed."); - $message .="
".gT("Look at survey logic files")."."; - $this->getController()->error( - $message, - $this->getController()->createUrl("admin/survey/sa/view/surveyid/{$surveyid}/gid/{$gid}/qid/{$qid}") - ); - } - else - { - $row = Question::model()->findByAttributes(array('qid' => $qid))->attributes; - $gid = $row['gid']; - - // See if there are any conditions/attributes/answers/defaultvalues for this question, - // and delete them now as well - Condition::model()->deleteAllByAttributes(array('qid' => $qid)); - QuestionAttribute::model()->deleteAllByAttributes(array('qid' => $qid)); - Answer::model()->deleteAllByAttributes(array('qid' => $qid)); - - $criteria = new CDbCriteria; - $criteria->addCondition('qid = :qid1 or parent_qid = :qid2'); - $criteria->params[':qid1'] = $qid; - $criteria->params[':qid2'] = $qid; - Question::model()->deleteAll($criteria); - - DefaultValue::model()->deleteAllByAttributes(array('qid' => $qid)); - QuotaMember::model()->deleteAllByAttributes(array('qid' => $qid)); - - Question::model()->updateQuestionOrder($gid, $surveyid); - - $qid = ""; - $postqid = ""; - $_GET['qid'] = ""; - } - - Yii::app()->session['flashmessage'] = gT("Question was successfully deleted."); - - $this->getController()->redirect(array('admin/survey/sa/view/surveyid/' . $surveyid . '/gid/' . $gid)); - } - else - { - Yii::app()->session['flashmessage'] = gT("You are not authorized to delete questions."); - $this->getController()->redirect(array('admin/survey/sa/view/surveyid/' . $surveyid . '/gid/' . $gid)); - } - } - - /** - * This function prepares the data for the advanced question attributes view - * - * @access public - * @return void - */ - public function ajaxquestionattributes() - { - $surveyid = (int) Yii::app()->request->getParam('sid',0); - $qid = (int) Yii::app()->request->getParam('qid',0); - $type = Yii::app()->request->getParam('question_type'); - $thissurvey = getSurveyInfo($surveyid); - if(!$thissurvey) die(); - $aLanguages = array_merge(array(Survey::model()->findByPk($surveyid)->language), Survey::model()->findByPk($surveyid)->additionalLanguages); - - $aAttributesWithValues = Question::model()->getAdvancedSettingsWithValues($qid, $type, $surveyid); - uasort($aAttributesWithValues, 'categorySort'); - - $aAttributesPrepared = array(); - foreach ($aAttributesWithValues as $iKey => $aAttribute) - { - if ($aAttribute['i18n'] == false) - $aAttributesPrepared[] = $aAttribute; - else - { - foreach ($aLanguages as $sLanguage) - { - $aAttributeModified = $aAttribute; - $aAttributeModified['name'] = $aAttributeModified['name'] . '_' . $sLanguage; - $aAttributeModified['language'] = $sLanguage; - if ($aAttributeModified['readonly'] == true && $thissurvey['active'] == 'N') - $aAttributeModified['readonly'] == false; - - if (isset($aAttributeModified[$sLanguage]['value'])) - $aAttributeModified['value'] = $aAttributeModified[$sLanguage]['value']; - else - $aAttributeModified['value'] = $aAttributeModified['default']; - - $aAttributesPrepared[] = $aAttributeModified; - } - } - } - $aData['bIsActive'] = ($thissurvey['active']=='Y'); - $aData['attributedata'] = $aAttributesPrepared; - $this->getController()->renderPartial('/admin/survey/Question/advanced_settings_view', $aData); - } - - /** - * This function prepares the data for label set details - * - * @access public - * @return void - */ - public function ajaxlabelsetdetails() - { - $lid=returnglobal('lid'); - Yii::app()->loadHelper('surveytranslator'); - - $labelsetdata=LabelSet::model()->find('lid=:lid',array(':lid' => $lid)); //$connect->GetArray($query); - - $labelsetlanguages=explode(' ',$labelsetdata->languages); - foreach ($labelsetlanguages as $language){ - - $criteria=new CDbCriteria; - $criteria->condition='lid=:lid and language=:language'; - $criteria->params=array(':lid'=>$lid, ':language'=>$language); - $criteria->order='sortorder'; - $labelsdata=Label::model()->findAll($criteria); - $i=0; - $data=array(); - foreach($labelsdata as $labeldata) - { - $data[$i]['lid'] = $labeldata->lid; - $data[$i]['code'] = $labeldata->code; - $data[$i]['title'] = $labeldata->title; - $data[$i]['sortorder'] = $labeldata->sortorder; - $data[$i]['assessment_value'] = $labeldata->assessment_value; - $data[$i]['language'] = $labeldata->language; - $i++; - } - $labels = $data; - //$labels=dbExecuteAssoc($query); //Label::model()->find(array('lid' => $lid, 'language' => $language), array('order' => 'sortorder')); //$connect->GetArray($query); - $resultdata[]=array($language=>array($labels,getLanguageNameFromCode($language,false))); - } - header('Content-type: application/json'); - echo json_encode($resultdata); - } - - /** - * This function prepares the data for labelset - * - * @access public - * @return void - */ - public function ajaxlabelsetpicker() - { - $match=(int)returnglobal('match'); - $surveyid=returnglobal('sid'); - if ($match==1) - { - $language=GetBaseLanguageFromSurveyID($surveyid); - } - else - { - $language=null; - } - $resultdata=getlabelsets($language); - // Label set title really don't need HTML - foreach($resultdata as &$aResult) - { - $aResult = array_map('flattenText', $aResult); - } - header('Content-type: application/json'); - echo ls_json_encode($resultdata); - } - - public function ajaxchecklabel() - { - $iLabelID = (int) Yii::app()->request->getParam('lid'); - $aNewLanguages = Yii::app()->request->getParam('languages'); - $bCheckAssessments = Yii::app()->request->getParam('bCheckAssessments',0); - $arLabelSet=LabelSet::model()->find('lid=:lid',array(':lid' => $iLabelID)); - $iLabelsWithAssessmentValues=Label::model()->count('lid=:lid AND assessment_value<>0',array(':lid' => $iLabelID)); - $aLabelSetLanguages=explode(' ',$arLabelSet->languages); - $aErrorMessages=array(); - if ($bCheckAssessments && $iLabelsWithAssessmentValues) - { - $aErrorMessages[]=gT('The existing label set has assessment values assigned.').''.gT('If you replace the label set the existing asssessment values will be lost.').''; - } - if (count(array_diff($aLabelSetLanguages,$aNewLanguages))) - { - $aErrorMessages[]=gT('The existing label set has different/more languages.').''.gT('If you replace the label set these translations will be lost.').''; - } - if (count($aErrorMessages)){ - foreach ($aErrorMessages as $sErrorMessage) - { - echo $sErrorMessage.'
'; - } - eT('Do you really want to continue?'); - } - else - { - eT('You are about to replace an existing label set with the current answer options.'); - echo '
'; - eT('Continue?'); - } - } - - - - public function ajaxValidate($surveyid,$qid=false){ - $iSurveyId=$surveyid; - $iQid=$qid; - $oSurvey=Survey::model()->findByPk($surveyid); - if($oSurvey) - { - $sLanguage=$oSurvey->language;// Validate only on default language - } - else - { - Yii::app()->end();// Or throw error 500 - } - if(!$iQid) - { - $oQuestion=new Question('insert'); - $oQuestion->sid=$iSurveyId; - $oQuestion->language=$sLanguage; - } - else - { - $oQuestion=Question::model()->find('qid=:qid and language=:language',array(":qid"=>$iQid,":language"=>$sLanguage)); - if(!$oQuestion){ - throw new Exception('Invalid question id.'); - } - } - $oQuestion->title=App()->request->getParam('title'); - $oQuestion->other=App()->request->getParam('other'); - $oQuestion->validate(); - - header('Content-type: application/json'); - echo CJSON::encode($oQuestion->getErrors()); - Yii::app()->end(); - } - /** - * Todo : update whole view to use CActiveForm - */ -# protected function performAjaxValidation($model) -# { -# if(trueYii::app()->request->getPost('ajax')=='user-form') -# { -# echo CActiveForm::validate($model); -# Yii::app()->end(); -# } -# } - /** - * Renders template(s) wrapped in header and footer - * - * @param string $sAction Current action, the folder to fetch views from - * @param string|array $aViewUrls View url(s) - * @param array $aData Data to be passed on. Optional. - */ - protected function _renderWrappedTemplate($sAction = 'survey/Question', $aViewUrls = array(), $aData = array()) - { - parent::_renderWrappedTemplate($sAction, $aViewUrls, $aData); - } -} diff --git a/application/extensions/ExtendedClientScript/ExtendedClientScript.php b/application/extensions/ExtendedClientScript/ExtendedClientScript.php deleted file mode 100644 index cde979a88b1..00000000000 --- a/application/extensions/ExtendedClientScript/ExtendedClientScript.php +++ /dev/null @@ -1,309 +0,0 @@ - - * @author Alexander Makarov - * @author Kir <> - * - * @link http://www.yiiframework.com/ - * @copyright Copyright © 2008-2011 - * @license htp://www.yiiframework.com/license/ - * @version 0.9.0 - * - */ - -class ExtendedClientScript extends CClientScript -{ - /** - * Compress all Javascript files with JSMin. JSMin must be installed as an extension in $jssminPath. - * github.com/rgrove/jsmin-php/ - */ - public $compressJs = false; - /** - * Compress all CSS files with CssMin. CssMin must be installed as an extension in $cssMinPath. - * Specific browserhacks will be removed, so don't add them in to be compressed CSS files. - * code.google.com/p/cssmin/ - */ - public $compressCss = false; - /** - * DEPRECATED/LEGACY - * Combine all JS and CSS files into one. Be careful with relative paths in CSS. - */ - public $combineFiles = false; - /** - * Combine all non-remote JS files into one. - */ - public $combineJs = false; - /** - * Combine all non-remote CSS files into one. Be careful with relative paths in CSS. - */ - public $combineCss = false; - /** - * Exclude certain files from inclusion. array('/path/to/excluded/file') Useful for fixed base - * and incidental additional JS. - */ - public $excludeFiles = array(); - /** - * Path where the combined/compressed file will be stored. Will use coreScriptUrl if not defined - */ - public $filePath; - /** - * If true, all files to be included will be checked if they are modified. - * To enhance speed (eg production) set to false. - */ - public $autoRefresh = true; - /** - * Relative Url where the combined/compressed file can be found - */ - public $fileUrl; - /** - * Path where files can be found - */ - public $basePath; - /** - * Used for garbage collection. If not accessed during that period: remove. - */ - public $ttlDays = 1; - /** - * prefix for the combined/compressed files - */ - public $prefix = 'c_'; - /** - * path to JsMin - */ - public $jsMinPath = 'ext.ExtendedClientScript.jsmin.*'; - /** - * path to CssMin - */ - public $cssMinPath = 'ext.ExtendedClientScript.cssmin.*'; - /** - * CssMin filter options. Default values according cssMin doc. - */ - public $cssMinFilters = array - ( - 'ImportImports' => false, - 'RemoveComments' => true, - 'RemoveEmptyRulesets' => true, - 'RemoveEmptyAtBlocks' => true, - 'ConvertLevel3AtKeyframes' => false, - 'ConvertLevel3Properties' => false, - 'Variables' => true, - 'RemoveLastDelarationSemiColon' => true - ); - /** - * CssMin plugin options. Maximum compression and conversion. - */ - public $cssMinPlugins = array - ( - 'Variables' => true, - 'ConvertFontWeight' => true, - 'ConvertHslColors' => true, - 'ConvertRgbColors' => true, - 'ConvertNamedColors' => true, - 'CompressColorValues' => true, - 'CompressUnitValues' => true, - 'CompressExpressionValues' => true, - ); - - private $_changesHash = ''; - private $_renewFile; - - /** - * Will combine/compress JS and CSS if wanted/needed, and will continue with original - * renderHead afterwards - * - * @param $output - */ - public function renderHead(&$output) - { - if ($this->combineFiles) - $this->combineJs = $this->combineCss = true; - - $this->renderJs($output, parent::POS_HEAD); - - if ($this->combineCss) - { - if (count($this->cssFiles) !== 0) - { - foreach ($this->cssFiles as $url => $media) - if(! $this->isRemoteFile($url)) - $cssFiles[$media][$url] = $url; // Exclude remote files - - foreach ($cssFiles as $media => $url) - $this->combineAndCompress('css', $url, $media); - } - } - parent::renderHead($output); - } - - /** - * Will combine/compress JS if wanted/needed, and will continue with original - * renderBodyEnd afterwards - * - * @param $output - */ - public function renderBodyBegin(&$output) - { - $this->renderJs($output, parent::POS_BEGIN); - parent::renderBodyBegin($output); - } - - /** - * Will combine/compress JS if wanted/needed, and will continue with original - * renderBodyEnd afterwards - * - * @param $output - */ - public function renderBodyEnd(&$output) - { - $this->renderJs($output, parent::POS_END); - parent::renderBodyEnd($output); - } - - - /** - * - * - * @param $output - * @param $pos - */ - private function renderJs($output, $pos) - { - if ($this->combineJs) - { - if (isset($this->scriptFiles[$pos]) && count($this->scriptFiles[$pos]) !== 0) - { - $jsFiles = $this->scriptFiles[$pos]; - - foreach ($jsFiles as &$fileName) - (!empty($this->excludeFiles) && in_array($fileName, $this->excludeFiles) || $this->isRemoteFile($fileName)) AND $fileName = false; - - $jsFiles = array_filter($jsFiles); - $this->combineAndCompress('js', $jsFiles, $pos); - } - } - } - - /** - * Performs the actual combining and compressing - * - * @param $type - * @param $urls - * @param $pos - */ - private function combineAndCompress($type, $urls, $pos) - { - $this->fileUrl or $this->fileUrl = $this->getCoreScriptUrl(); - $this->basePath or $this->basePath = \Yii::getPathOfAlias('webroot'); - $this->filePath or $this->filePath = $this->basePath.$this->fileUrl; - - $optionsHash = ($type == 'js') ? md5($this->basePath . $this->compressJs . $this->ttlDays . $this->prefix) - : md5($this->basePath . $this->compressCss . $this->ttlDays . $this->prefix . serialize($this->cssMinFilters) . serialize($this->cssMinPlugins)); - - if ($this->autoRefresh) - { - $mtimes = array(); - - foreach ($urls as $file) - { - $fileName = $this->basePath.'/'.trim($file,'/'); - - if(file_exists($fileName)) - { - $mtimes[] = filemtime($fileName); - } - } - $this->_changesHash = md5(serialize($mtimes)); - } - - $combineHash = md5(implode('',$urls)); - - $fileName = $this->prefix.md5($combineHash.$optionsHash.$this->_changesHash).".$type"; - - $this->_renewFile = (file_exists($this->filePath.'/'.$fileName)) ? false : true; - - if ($this->_renewFile) - { - $this->garbageCollect($type); - $combinedFile = ''; - - foreach ($urls as $key => $file) - $combinedFile .= file_get_contents($this->basePath.'/'.$file); - - if ($type == 'js' && $this->compressJs) - $combinedFile = $this->minifyJs($combinedFile); - - if ($type == 'css' && $this->compressCss) - $combinedFile = $this->minifyCss($combinedFile); - - file_put_contents($this->filePath.'/'.$fileName, $combinedFile); - } - - foreach ($urls as $url) - $this->scriptMap[basename($url)] = $this->fileUrl.'/'.$fileName; - - $this->remapScripts(); - } - - private function garbageCollect($type) - { - $files = CFileHelper::findFiles($this->filePath, array('fileTypes' => array($type), 'level'=> 0)); - - foreach($files as $file) - { - if (strpos($file, $this->prefix) !== false && $this->fileTTL($file)) - unlink($file); - } - } - - /** - * See if file is ready for deletion - * - * @param $file - */ - private function fileTTL($file) - { - if(!file_exists($file)) return false; - $ttl = $this->ttlDays * 60 * 60 * 24; - return ((fileatime($file) + $ttl) < time()) ? true : false; - } - - /** - * Minify javascript with JSMin - * - * @param $js - */ - private function minifyJs($js) - { - Yii::import($this->jsMinPath); - return JSMin::minify($js); - } - - /** - * Minify css with cssmin - * - * @param $css - */ - private function minifyCss($css) - { - Yii::import($this->cssMinPath); - return cssmin::minify($css, $this->cssMinFilters, $this->cssMinPlugins); - } - - /** - * See if file is on remote server - * - * @param $file - */ - private function isRemoteFile($file) { - return (strpos($file, 'http://') === 0 || strpos($file, 'https://') === 0) ? true : false; - } -} \ No newline at end of file diff --git a/application/extensions/ExtendedClientScript/cssmin/cssmin.php b/application/extensions/ExtendedClientScript/cssmin/cssmin.php deleted file mode 100644 index 8507201184d..00000000000 --- a/application/extensions/ExtendedClientScript/cssmin/cssmin.php +++ /dev/null @@ -1,5080 +0,0 @@ - - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * -- - * - * @package CssMin - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -/** - * Abstract definition of a CSS token class. - * - * Every token has to extend this class. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -abstract class aCssToken - { - /** - * Returns the token as string. - * - * @return string - */ - abstract public function __toString(); - } - -/** - * Abstract definition of a for a ruleset start token. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -abstract class aCssRulesetStartToken extends aCssToken - { - - } - -/** - * Abstract definition of a for ruleset end token. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -abstract class aCssRulesetEndToken extends aCssToken - { - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return "}"; - } - } - -/** - * Abstract definition of a parser plugin. - * - * Every parser plugin have to extend this class. A parser plugin contains the logic to parse one or aspects of a - * stylesheet. - * - * @package CssMin/Parser/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -abstract class aCssParserPlugin - { - /** - * Plugin configuration. - * - * @var array - */ - protected $configuration = array(); - /** - * The CssParser of the plugin. - * - * @var CssParser - */ - protected $parser = null; - /** - * Plugin buffer. - * - * @var string - */ - protected $buffer = ""; - /** - * Constructor. - * - * @param CssParser $parser The CssParser object of this plugin. - * @param array $configuration Plugin configuration [optional] - * @return void - */ - public function __construct(CssParser $parser, array $configuration = null) - { - $this->configuration = $configuration; - $this->parser = $parser; - } - /** - * Returns the array of chars triggering the parser plugin. - * - * @return array - */ - abstract public function getTriggerChars(); - /** - * Returns the array of states triggering the parser plugin or FALSE if every state will trigger the parser plugin. - * - * @return array - */ - abstract public function getTriggerStates(); - /** - * Parser routine of the plugin. - * - * @param integer $index Current index - * @param string $char Current char - * @param string $previousChar Previous char - * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing - */ - abstract public function parse($index, $char, $previousChar, $state); - } - -/** - * Abstract definition of a minifier plugin class. - * - * Minifier plugin process the parsed tokens one by one to apply changes to the token. Every minifier plugin has to - * extend this class. - * - * @package CssMin/Minifier/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -abstract class aCssMinifierPlugin - { - /** - * Plugin configuration. - * - * @var array - */ - protected $configuration = array(); - /** - * The CssMinifier of the plugin. - * - * @var CssMinifier - */ - protected $minifier = null; - /** - * Constructor. - * - * @param CssMinifier $minifier The CssMinifier object of this plugin. - * @param array $configuration Plugin configuration [optional] - * @return void - */ - public function __construct(CssMinifier $minifier, array $configuration = array()) - { - $this->configuration = $configuration; - $this->minifier = $minifier; - } - /** - * Apply the plugin to the token. - * - * @param aCssToken $token Token to process - * @return boolean Return TRUE to break the processing of this token; FALSE to continue - */ - abstract public function apply(aCssToken &$token); - /** - * -- - * - * @return array - */ - abstract public function getTriggerTokens(); - } - -/** - * Abstract definition of a minifier filter class. - * - * Minifier filters allows a pre-processing of the parsed token to add, edit or delete tokens. Every minifier filter - * has to extend this class. - * - * @package CssMin/Minifier/Filters - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -abstract class aCssMinifierFilter - { - /** - * Filter configuration. - * - * @var array - */ - protected $configuration = array(); - /** - * The CssMinifier of the filter. - * - * @var CssMinifier - */ - protected $minifier = null; - /** - * Constructor. - * - * @param CssMinifier $minifier The CssMinifier object of this plugin. - * @param array $configuration Filter configuration [optional] - * @return void - */ - public function __construct(CssMinifier $minifier, array $configuration = array()) - { - $this->configuration = $configuration; - $this->minifier = $minifier; - } - /** - * Filter the tokens. - * - * @param array $tokens Array of objects of type aCssToken - * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array - */ - abstract public function apply(array &$tokens); - } - -/** - * Abstract formatter definition. - * - * Every formatter have to extend this class. - * - * @package CssMin/Formatter - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -abstract class aCssFormatter - { - /** - * Indent string. - * - * @var string - */ - protected $indent = " "; - /** - * Declaration padding. - * - * @var integer - */ - protected $padding = 0; - /** - * Tokens. - * - * @var array - */ - protected $tokens = array(); - /** - * Constructor. - * - * @param array $tokens Array of CssToken - * @param string $indent Indent string [optional] - * @param integer $padding Declaration value padding [optional] - */ - public function __construct(array $tokens, $indent = null, $padding = null) - { - $this->tokens = $tokens; - $this->indent = !is_null($indent) ? $indent : $this->indent; - $this->padding = !is_null($padding) ? $padding : $this->padding; - } - /** - * Returns the array of aCssToken as formatted string. - * - * @return string - */ - abstract public function __toString(); - } - -/** - * Abstract definition of a ruleset declaration token. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -abstract class aCssDeclarationToken extends aCssToken - { - /** - * Is the declaration flagged as important? - * - * @var boolean - */ - public $IsImportant = false; - /** - * Is the declaration flagged as last one of the ruleset? - * - * @var boolean - */ - public $IsLast = false; - /** - * Property name of the declaration. - * - * @var string - */ - public $Property = ""; - /** - * Value of the declaration. - * - * @var string - */ - public $Value = ""; - /** - * Set the properties of the @font-face declaration. - * - * @param string $property Property of the declaration - * @param string $value Value of the declaration - * @param boolean $isImportant Is the !important flag is set? - * @param boolean $IsLast Is the declaration the last one of the block? - * @return void - */ - public function __construct($property, $value, $isImportant = false, $isLast = false) - { - $this->Property = $property; - $this->Value = $value; - $this->IsImportant = $isImportant; - $this->IsLast = $isLast; - } - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return $this->Property . ":" . $this->Value . ($this->IsImportant ? " !important" : "") . ($this->IsLast ? "" : ";"); - } - } - -/** - * Abstract definition of a for at-rule block start token. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -abstract class aCssAtBlockStartToken extends aCssToken - { - - } - -/** - * Abstract definition of a for at-rule block end token. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -abstract class aCssAtBlockEndToken extends aCssToken - { - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return "}"; - } - } - -/** - * {@link aCssFromatter Formatter} returning the CSS source in {@link http://goo.gl/etzLs Whitesmiths indent style}. - * - * @package CssMin/Formatter - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssWhitesmithsFormatter extends aCssFormatter - { - /** - * Implements {@link aCssFormatter::__toString()}. - * - * @return string - */ - public function __toString() - { - $r = array(); - $level = 0; - for ($i = 0, $l = count($this->tokens); $i < $l; $i++) - { - $token = $this->tokens[$i]; - $class = get_class($token); - $indent = str_repeat($this->indent, $level); - if ($class === "CssCommentToken") - { - $lines = array_map("trim", explode("\n", $token->Comment)); - for ($ii = 0, $ll = count($lines); $ii < $ll; $ii++) - { - $r[] = $indent . (substr($lines[$ii], 0, 1) == "*" ? " " : "") . $lines[$ii]; - } - } - elseif ($class === "CssAtCharsetToken") - { - $r[] = $indent . "@charset " . $token->Charset . ";"; - } - elseif ($class === "CssAtFontFaceStartToken") - { - $r[] = $indent . "@font-face"; - $r[] = $this->indent . $indent . "{"; - $level++; - } - elseif ($class === "CssAtImportToken") - { - $r[] = $indent . "@import " . $token->Import . " " . implode(", ", $token->MediaTypes) . ";"; - } - elseif ($class === "CssAtKeyframesStartToken") - { - $r[] = $indent . "@keyframes \"" . $token->Name . "\""; - $r[] = $this->indent . $indent . "{"; - $level++; - } - elseif ($class === "CssAtMediaStartToken") - { - $r[] = $indent . "@media " . implode(", ", $token->MediaTypes); - $r[] = $this->indent . $indent . "{"; - $level++; - } - elseif ($class === "CssAtPageStartToken") - { - $r[] = $indent . "@page"; - $r[] = $this->indent . $indent . "{"; - $level++; - } - elseif ($class === "CssAtVariablesStartToken") - { - $r[] = $indent . "@variables " . implode(", ", $token->MediaTypes); - $r[] = $this->indent . $indent . "{"; - $level++; - } - elseif ($class === "CssRulesetStartToken" || $class === "CssAtKeyframesRulesetStartToken") - { - $r[] = $indent . implode(", ", $token->Selectors); - $r[] = $this->indent . $indent . "{"; - $level++; - } - elseif ($class == "CssAtFontFaceDeclarationToken" - || $class === "CssAtKeyframesRulesetDeclarationToken" - || $class === "CssAtPageDeclarationToken" - || $class == "CssAtVariablesDeclarationToken" - || $class === "CssRulesetDeclarationToken" - ) - { - $declaration = $indent . $token->Property . ": "; - if ($this->padding) - { - $declaration = str_pad($declaration, $this->padding, " ", STR_PAD_RIGHT); - } - $r[] = $declaration . $token->Value . ($token->IsImportant ? " !important" : "") . ";"; - } - elseif ($class === "CssAtFontFaceEndToken" - || $class === "CssAtMediaEndToken" - || $class === "CssAtKeyframesEndToken" - || $class === "CssAtKeyframesRulesetEndToken" - || $class === "CssAtPageEndToken" - || $class === "CssAtVariablesEndToken" - || $class === "CssRulesetEndToken" - ) - { - $r[] = $indent . "}"; - $level--; - } - } - return implode("\n", $r); - } - } - -/** - * This {@link aCssMinifierPlugin} will process var-statement and sets the declaration value to the variable value. - * - * This plugin only apply the variable values. The variable values itself will get parsed by the - * {@link CssVariablesMinifierFilter}. - * - * Example: - * - * @variables - * { - * defaultColor: black; - * } - * color: var(defaultColor); - * - * - * Will get converted to: - * - * color:black; - * - * - * @package CssMin/Minifier/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssVariablesMinifierPlugin extends aCssMinifierPlugin - { - /** - * Regular expression matching a value. - * - * @var string - */ - private $reMatch = "/var\((.+)\)/iSU"; - /** - * Parsed variables. - * - * @var array - */ - private $variables = null; - /** - * Returns the variables. - * - * @return array - */ - public function getVariables() - { - return $this->variables; - } - /** - * Implements {@link aCssMinifierPlugin::minify()}. - * - * @param aCssToken $token Token to process - * @return boolean Return TRUE to break the processing of this token; FALSE to continue - */ - public function apply(aCssToken &$token) - { - if (stripos($token->Value, "var") !== false && preg_match_all($this->reMatch, $token->Value, $m)) - { - $mediaTypes = $token->MediaTypes; - if (!in_array("all", $mediaTypes)) - { - $mediaTypes[] = "all"; - } - for ($i = 0, $l = count($m[0]); $i < $l; $i++) - { - $variable = trim($m[1][$i]); - foreach ($mediaTypes as $mediaType) - { - if (isset($this->variables[$mediaType], $this->variables[$mediaType][$variable])) - { - // Variable value found => set the declaration value to the variable value and return - $token->Value = str_replace($m[0][$i], $this->variables[$mediaType][$variable], $token->Value); - continue 2; - } - } - // If no value was found trigger an error and replace the token with a CssNullToken - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": No value found for variable " . $variable . " in media types " . implode(", ", $mediaTypes) . "", (string) $token)); - $token = new CssNullToken(); - return true; - } - } - return false; - } - /** - * Implements {@link aMinifierPlugin::getTriggerTokens()} - * - * @return array - */ - public function getTriggerTokens() - { - return array - ( - "CssAtFontFaceDeclarationToken", - "CssAtPageDeclarationToken", - "CssRulesetDeclarationToken" - ); - } - /** - * Sets the variables. - * - * @param array $variables Variables to set - * @return void - */ - public function setVariables(array $variables) - { - $this->variables = $variables; - } - } - -/** - * This {@link aCssMinifierFilter minifier filter} will parse the variable declarations out of @variables at-rule - * blocks. The variables will get store in the {@link CssVariablesMinifierPlugin} that will apply the variables to - * declaration. - * - * @package CssMin/Minifier/Filters - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssVariablesMinifierFilter extends aCssMinifierFilter - { - /** - * Implements {@link aCssMinifierFilter::filter()}. - * - * @param array $tokens Array of objects of type aCssToken - * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array - */ - public function apply(array &$tokens) - { - $variables = array(); - $defaultMediaTypes = array("all"); - $mediaTypes = array(); - $remove = array(); - for($i = 0, $l = count($tokens); $i < $l; $i++) - { - // @variables at-rule block found - if (get_class($tokens[$i]) === "CssAtVariablesStartToken") - { - $remove[] = $i; - $mediaTypes = (count($tokens[$i]->MediaTypes) == 0 ? $defaultMediaTypes : $tokens[$i]->MediaTypes); - foreach ($mediaTypes as $mediaType) - { - if (!isset($variables[$mediaType])) - { - $variables[$mediaType] = array(); - } - } - // Read the variable declaration tokens - for($i = $i; $i < $l; $i++) - { - // Found a variable declaration => read the variable values - if (get_class($tokens[$i]) === "CssAtVariablesDeclarationToken") - { - foreach ($mediaTypes as $mediaType) - { - $variables[$mediaType][$tokens[$i]->Property] = $tokens[$i]->Value; - } - $remove[] = $i; - } - // Found the variables end token => break; - elseif (get_class($tokens[$i]) === "CssAtVariablesEndToken") - { - $remove[] = $i; - break; - } - } - } - } - // Variables in @variables at-rule blocks - foreach($variables as $mediaType => $null) - { - foreach($variables[$mediaType] as $variable => $value) - { - // If a var() statement in a variable value found... - if (stripos($value, "var") !== false && preg_match_all("/var\((.+)\)/iSU", $value, $m)) - { - // ... then replace the var() statement with the variable values. - for ($i = 0, $l = count($m[0]); $i < $l; $i++) - { - $variables[$mediaType][$variable] = str_replace($m[0][$i], (isset($variables[$mediaType][$m[1][$i]]) ? $variables[$mediaType][$m[1][$i]] : ""), $variables[$mediaType][$variable]); - } - } - } - } - // Remove the complete @variables at-rule block - foreach ($remove as $i) - { - $tokens[$i] = null; - } - if (!($plugin = $this->minifier->getPlugin("CssVariablesMinifierPlugin"))) - { - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The plugin CssVariablesMinifierPlugin was not found but is required for " . __CLASS__ . "")); - } - else - { - $plugin->setVariables($variables); - } - return count($remove); - } - } - -/** - * {@link aCssParserPlugin Parser plugin} for preserve parsing url() values. - * - * This plugin return no {@link aCssToken CssToken} but ensures that url() values will get parsed properly. - * - * @package CssMin/Parser/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssUrlParserPlugin extends aCssParserPlugin - { - /** - * Implements {@link aCssParserPlugin::getTriggerChars()}. - * - * @return array - */ - public function getTriggerChars() - { - return array("(", ")"); - } - /** - * Implements {@link aCssParserPlugin::getTriggerStates()}. - * - * @return array - */ - public function getTriggerStates() - { - return false; - } - /** - * Implements {@link aCssParserPlugin::parse()}. - * - * @param integer $index Current index - * @param string $char Current char - * @param string $previousChar Previous char - * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing - */ - public function parse($index, $char, $previousChar, $state) - { - // Start of string - if ($char === "(" && strtolower(substr($this->parser->getSource(), $index - 3, 4)) === "url(" && $state !== "T_URL") - { - $this->parser->pushState("T_URL"); - $this->parser->setExclusive(__CLASS__); - } - // Escaped LF in url => remove escape backslash and LF - elseif ($char === "\n" && $previousChar === "\\" && $state === "T_URL") - { - $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -2)); - } - // Parse error: Unescaped LF in string literal - elseif ($char === "\n" && $previousChar !== "\\" && $state === "T_URL") - { - $line = $this->parser->getBuffer(); - $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -1) . ")"); // Replace the LF with the url string delimiter - $this->parser->popState(); - $this->parser->unsetExclusive(); - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated string literal", $line . "_")); - } - // End of string - elseif ($char === ")" && $state === "T_URL") - { - $this->parser->popState(); - $this->parser->unsetExclusive(); - } - else - { - return false; - } - return true; - } - } - -/** - * {@link aCssParserPlugin Parser plugin} for preserve parsing string values. - * - * This plugin return no {@link aCssToken CssToken} but ensures that string values will get parsed properly. - * - * @package CssMin/Parser/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssStringParserPlugin extends aCssParserPlugin - { - /** - * Current string delimiter char. - * - * @var string - */ - private $delimiterChar = null; - /** - * Implements {@link aCssParserPlugin::getTriggerChars()}. - * - * @return array - */ - public function getTriggerChars() - { - return array("\"", "'", "\n"); - } - /** - * Implements {@link aCssParserPlugin::getTriggerStates()}. - * - * @return array - */ - public function getTriggerStates() - { - return false; - } - /** - * Implements {@link aCssParserPlugin::parse()}. - * - * @param integer $index Current index - * @param string $char Current char - * @param string $previousChar Previous char - * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing - */ - public function parse($index, $char, $previousChar, $state) - { - // Start of string - if (($char === "\"" || $char === "'") && $state !== "T_STRING") - { - $this->delimiterChar = $char; - $this->parser->pushState("T_STRING"); - $this->parser->setExclusive(__CLASS__); - } - // Escaped LF in string => remove escape backslash and LF - elseif ($char === "\n" && $previousChar === "\\" && $state === "T_STRING") - { - $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -2)); - } - // Parse error: Unescaped LF in string literal - elseif ($char === "\n" && $previousChar !== "\\" && $state === "T_STRING") - { - $line = $this->parser->getBuffer(); - $this->parser->popState(); - $this->parser->unsetExclusive(); - $this->parser->setBuffer(substr($this->parser->getBuffer(), 0, -1) . $this->delimiterChar); // Replace the LF with the current string char - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated string literal", $line . "_")); - $this->delimiterChar = null; - } - // End of string - elseif ($char === $this->delimiterChar && $state === "T_STRING") - { - // If the Previous char is a escape char count the amount of the previous escape chars. If the amount of - // escape chars is uneven do not end the string - if ($previousChar == "\\") - { - $source = $this->parser->getSource(); - $c = 1; - $i = $index - 2; - while (substr($source, $i, 1) === "\\") - { - $c++; $i--; - } - if ($c % 2) - { - return false; - } - } - $this->parser->popState(); - $this->parser->unsetExclusive(); - $this->delimiterChar = null; - } - else - { - return false; - } - return true; - } - } - -/** - * This {@link aCssMinifierFilter minifier filter} sorts the ruleset declarations of a ruleset by name. - * - * @package CssMin/Minifier/Filters - * @link http://code.google.com/p/cssmin/ - * @author Rowan Beentje - * @copyright Rowan Beentje - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssSortRulesetPropertiesMinifierFilter extends aCssMinifierFilter - { - /** - * Implements {@link aCssMinifierFilter::filter()}. - * - * @param array $tokens Array of objects of type aCssToken - * @return integer Count of added, changed or removed tokens; a return value larger than 0 will rebuild the array - */ - public function apply(array &$tokens) - { - $r = 0; - for ($i = 0, $l = count($tokens); $i < $l; $i++) - { - // Only look for ruleset start rules - if (get_class($tokens[$i]) !== "CssRulesetStartToken") { continue; } - // Look for the corresponding ruleset end - $endIndex = false; - for ($ii = $i + 1; $ii < $l; $ii++) - { - if (get_class($tokens[$ii]) !== "CssRulesetEndToken") { continue; } - $endIndex = $ii; - break; - } - if (!$endIndex) { break; } - $startIndex = $i; - $i = $endIndex; - // Skip if there's only one token in this ruleset - if ($endIndex - $startIndex <= 2) { continue; } - // Ensure that everything between the start and end is a declaration token, for safety - for ($ii = $startIndex + 1; $ii < $endIndex; $ii++) - { - if (get_class($tokens[$ii]) !== "CssRulesetDeclarationToken") { continue(2); } - } - $declarations = array_slice($tokens, $startIndex + 1, $endIndex - $startIndex - 1); - // Check whether a sort is required - $sortRequired = $lastPropertyName = false; - foreach ($declarations as $declaration) - { - if ($lastPropertyName) - { - if (strcmp($lastPropertyName, $declaration->Property) > 0) - { - $sortRequired = true; - break; - } - } - $lastPropertyName = $declaration->Property; - } - if (!$sortRequired) { continue; } - // Arrange the declarations alphabetically by name - usort($declarations, array(__CLASS__, "userDefinedSort1")); - // Update "IsLast" property - for ($ii = 0, $ll = count($declarations) - 1; $ii <= $ll; $ii++) - { - if ($ii == $ll) - { - $declarations[$ii]->IsLast = true; - } - else - { - $declarations[$ii]->IsLast = false; - } - } - // Splice back into the array. - array_splice($tokens, $startIndex + 1, $endIndex - $startIndex - 1, $declarations); - $r += $endIndex - $startIndex - 1; - } - return $r; - } - /** - * User defined sort function. - * - * @return integer - */ - public static function userDefinedSort1($a, $b) - { - return strcmp($a->Property, $b->Property); - } - } - -/** - * This {@link aCssToken CSS token} represents the start of a ruleset. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssRulesetStartToken extends aCssRulesetStartToken - { - /** - * Array of selectors. - * - * @var array - */ - public $Selectors = array(); - /** - * Set the properties of a ruleset token. - * - * @param array $selectors Selectors of the ruleset - * @return void - */ - public function __construct(array $selectors = array()) - { - $this->Selectors = $selectors; - } - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return implode(",", $this->Selectors) . "{"; - } - } - -/** - * {@link aCssParserPlugin Parser plugin} for parsing ruleset block with including declarations. - * - * Found rulesets will add a {@link CssRulesetStartToken} and {@link CssRulesetEndToken} to the - * parser; including declarations as {@link CssRulesetDeclarationToken}. - * - * @package CssMin/Parser/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssRulesetParserPlugin extends aCssParserPlugin - { - /** - * Implements {@link aCssParserPlugin::getTriggerChars()}. - * - * @return array - */ - public function getTriggerChars() - { - return array(",", "{", "}", ":", ";"); - } - /** - * Implements {@link aCssParserPlugin::getTriggerStates()}. - * - * @return array - */ - public function getTriggerStates() - { - return array("T_DOCUMENT", "T_AT_MEDIA", "T_RULESET::SELECTORS", "T_RULESET", "T_RULESET_DECLARATION"); - } - /** - * Selectors. - * - * @var array - */ - private $selectors = array(); - /** - * Implements {@link aCssParserPlugin::parse()}. - * - * @param integer $index Current index - * @param string $char Current char - * @param string $previousChar Previous char - * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing - */ - public function parse($index, $char, $previousChar, $state) - { - // Start of Ruleset and selectors - if ($char === "," && ($state === "T_DOCUMENT" || $state === "T_AT_MEDIA" || $state === "T_RULESET::SELECTORS")) - { - if ($state !== "T_RULESET::SELECTORS") - { - $this->parser->pushState("T_RULESET::SELECTORS"); - } - $this->selectors[] = $this->parser->getAndClearBuffer(",{"); - } - // End of selectors and start of declarations - elseif ($char === "{" && ($state === "T_DOCUMENT" || $state === "T_AT_MEDIA" || $state === "T_RULESET::SELECTORS")) - { - if ($this->parser->getBuffer() !== "") - { - $this->selectors[] = $this->parser->getAndClearBuffer(",{"); - if ($state == "T_RULESET::SELECTORS") - { - $this->parser->popState(); - } - $this->parser->pushState("T_RULESET"); - $this->parser->appendToken(new CssRulesetStartToken($this->selectors)); - $this->selectors = array(); - } - } - // Start of declaration - elseif ($char === ":" && $state === "T_RULESET") - { - $this->parser->pushState("T_RULESET_DECLARATION"); - $this->buffer = $this->parser->getAndClearBuffer(":;", true); - } - // Unterminated ruleset declaration - elseif ($char === ":" && $state === "T_RULESET_DECLARATION") - { - // Ignore Internet Explorer filter declarations - if ($this->buffer === "filter") - { - return false; - } - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_")); - } - // End of declaration - elseif (($char === ";" || $char === "}") && $state === "T_RULESET_DECLARATION") - { - $value = $this->parser->getAndClearBuffer(";}"); - if (strtolower(substr($value, -10, 10)) === "!important") - { - $value = trim(substr($value, 0, -10)); - $isImportant = true; - } - else - { - $isImportant = false; - } - $this->parser->popState(); - $this->parser->appendToken(new CssRulesetDeclarationToken($this->buffer, $value, $this->parser->getMediaTypes(), $isImportant)); - // Declaration ends with a right curly brace; so we have to end the ruleset - if ($char === "}") - { - $this->parser->appendToken(new CssRulesetEndToken()); - $this->parser->popState(); - } - $this->buffer = ""; - } - // End of ruleset - elseif ($char === "}" && $state === "T_RULESET") - { - $this->parser->popState(); - $this->parser->clearBuffer(); - $this->parser->appendToken(new CssRulesetEndToken()); - $this->buffer = ""; - $this->selectors = array(); - } - else - { - return false; - } - return true; - } - } - -/** - * This {@link aCssToken CSS token} represents the end of a ruleset. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssRulesetEndToken extends aCssRulesetEndToken - { - - } - -/** - * This {@link aCssToken CSS token} represents a ruleset declaration. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssRulesetDeclarationToken extends aCssDeclarationToken - { - /** - * Media types of the declaration. - * - * @var array - */ - public $MediaTypes = array("all"); - /** - * Set the properties of a ddocument- or at-rule @media level declaration. - * - * @param string $property Property of the declaration - * @param string $value Value of the declaration - * @param mixed $mediaTypes Media types of the declaration - * @param boolean $isImportant Is the !important flag is set - * @param boolean $isLast Is the declaration the last one of the ruleset - * @return void - */ - public function __construct($property, $value, $mediaTypes = null, $isImportant = false, $isLast = false) - { - parent::__construct($property, $value, $isImportant, $isLast); - $this->MediaTypes = $mediaTypes ? $mediaTypes : array("all"); - } - } - -/** - * This {@link aCssMinifierFilter minifier filter} sets the IsLast property of any last declaration in a ruleset, - * @font-face at-rule or @page at-rule block. If the property IsLast is TRUE the decrations will get stringified - * without tailing semicolon. - * - * @package CssMin/Minifier/Filters - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssRemoveLastDelarationSemiColonMinifierFilter extends aCssMinifierFilter - { - /** - * Implements {@link aCssMinifierFilter::filter()}. - * - * @param array $tokens Array of objects of type aCssToken - * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array - */ - public function apply(array &$tokens) - { - for ($i = 0, $l = count($tokens); $i < $l; $i++) - { - $current = get_class($tokens[$i]); - $next = isset($tokens[$i+1]) ? get_class($tokens[$i+1]) : false; - if (($current === "CssRulesetDeclarationToken" && $next === "CssRulesetEndToken") || - ($current === "CssAtFontFaceDeclarationToken" && $next === "CssAtFontFaceEndToken") || - ($current === "CssAtPageDeclarationToken" && $next === "CssAtPageEndToken")) - { - $tokens[$i]->IsLast = true; - } - } - return 0; - } - } - -/** - * This {@link aCssMinifierFilter minifier filter} will remove any empty rulesets (including @keyframes at-rule block - * rulesets). - * - * @package CssMin/Minifier/Filters - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssRemoveEmptyRulesetsMinifierFilter extends aCssMinifierFilter - { - /** - * Implements {@link aCssMinifierFilter::filter()}. - * - * @param array $tokens Array of objects of type aCssToken - * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array - */ - public function apply(array &$tokens) - { - $r = 0; - for ($i = 0, $l = count($tokens); $i < $l; $i++) - { - $current = get_class($tokens[$i]); - $next = isset($tokens[$i + 1]) ? get_class($tokens[$i + 1]) : false; - if (($current === "CssRulesetStartToken" && $next === "CssRulesetEndToken") || - ($current === "CssAtKeyframesRulesetStartToken" && $next === "CssAtKeyframesRulesetEndToken" && !array_intersect(array("from", "0%", "to", "100%"), array_map("strtolower", $tokens[$i]->Selectors))) - ) - { - $tokens[$i] = null; - $tokens[$i + 1] = null; - $i++; - $r = $r + 2; - } - } - return $r; - } - } - -/** - * This {@link aCssMinifierFilter minifier filter} will remove any empty @font-face, @keyframes, @media and @page - * at-rule blocks. - * - * @package CssMin/Minifier/Filters - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssRemoveEmptyAtBlocksMinifierFilter extends aCssMinifierFilter - { - /** - * Implements {@link aCssMinifierFilter::filter()}. - * - * @param array $tokens Array of objects of type aCssToken - * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array - */ - public function apply(array &$tokens) - { - $r = 0; - for ($i = 0, $l = count($tokens); $i < $l; $i++) - { - $current = get_class($tokens[$i]); - $next = isset($tokens[$i + 1]) ? get_class($tokens[$i + 1]) : false; - if (($current === "CssAtFontFaceStartToken" && $next === "CssAtFontFaceEndToken") || - ($current === "CssAtKeyframesStartToken" && $next === "CssAtKeyframesEndToken") || - ($current === "CssAtPageStartToken" && $next === "CssAtPageEndToken") || - ($current === "CssAtMediaStartToken" && $next === "CssAtMediaEndToken")) - { - $tokens[$i] = null; - $tokens[$i + 1] = null; - $i++; - $r = $r + 2; - } - } - return $r; - } - } - -/** - * This {@link aCssMinifierFilter minifier filter} will remove any comments from the array of parsed tokens. - * - * @package CssMin/Minifier/Filters - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssRemoveCommentsMinifierFilter extends aCssMinifierFilter - { - /** - * Implements {@link aCssMinifierFilter::filter()}. - * - * @param array $tokens Array of objects of type aCssToken - * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array - */ - public function apply(array &$tokens) - { - $r = 0; - for ($i = 0, $l = count($tokens); $i < $l; $i++) - { - if (get_class($tokens[$i]) === "CssCommentToken") - { - $tokens[$i] = null; - $r++; - } - } - return $r; - } - } - -/** - * CSS Parser. - * - * @package CssMin/Parser - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssParser - { - /** - * Parse buffer. - * - * @var string - */ - private $buffer = ""; - /** - * {@link aCssParserPlugin Plugins}. - * - * @var array - */ - private $plugins = array(); - /** - * Source to parse. - * - * @var string - */ - private $source = ""; - /** - * Current state. - * - * @var integer - */ - private $state = "T_DOCUMENT"; - /** - * Exclusive state. - * - * @var string - */ - private $stateExclusive = false; - /** - * Media types state. - * - * @var mixed - */ - private $stateMediaTypes = false; - /** - * State stack. - * - * @var array - */ - private $states = array("T_DOCUMENT"); - /** - * Parsed tokens. - * - * @var array - */ - private $tokens = array(); - /** - * Constructer. - * - * Create instances of the used {@link aCssParserPlugin plugins}. - * - * @param string $source CSS source [optional] - * @param array $plugins Plugin configuration [optional] - * @return void - */ - public function __construct($source = null, array $plugins = null) - { - $plugins = array_merge(array - ( - "Comment" => true, - "String" => true, - "Url" => true, - "Expression" => true, - "Ruleset" => true, - "AtCharset" => true, - "AtFontFace" => true, - "AtImport" => true, - "AtKeyframes" => true, - "AtMedia" => true, - "AtPage" => true, - "AtVariables" => true - ), is_array($plugins) ? $plugins : array()); - // Create plugin instances - foreach ($plugins as $name => $config) - { - if ($config !== false) - { - $class = "Css" . $name . "ParserPlugin"; - $config = is_array($config) ? $config : array(); - if (class_exists($class)) - { - $this->plugins[] = new $class($this, $config); - } - else - { - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The plugin " . $name . " with the class name " . $class . " was not found")); - } - } - } - if (!is_null($source)) - { - $this->parse($source); - } - } - /** - * Append a token to the array of tokens. - * - * @param aCssToken $token Token to append - * @return void - */ - public function appendToken(aCssToken $token) - { - $this->tokens[] = $token; - } - /** - * Clears the current buffer. - * - * @return void - */ - public function clearBuffer() - { - $this->buffer = ""; - } - /** - * Returns and clear the current buffer. - * - * @param string $trim Chars to use to trim the returned buffer - * @param boolean $tolower if TRUE the returned buffer will get converted to lower case - * @return string - */ - public function getAndClearBuffer($trim = "", $tolower = false) - { - $r = $this->getBuffer($trim, $tolower); - $this->buffer = ""; - return $r; - } - /** - * Returns the current buffer. - * - * @param string $trim Chars to use to trim the returned buffer - * @param boolean $tolower if TRUE the returned buffer will get converted to lower case - * @return string - */ - public function getBuffer($trim = "", $tolower = false) - { - $r = $this->buffer; - if ($trim) - { - $r = trim($r, " \t\n\r\0\x0B" . $trim); - } - if ($tolower) - { - $r = strtolower($r); - } - return $r; - } - /** - * Returns the current media types state. - * - * @return array - */ - public function getMediaTypes() - { - return $this->stateMediaTypes; - } - /** - * Returns the CSS source. - * - * @return string - */ - public function getSource() - { - return $this->source; - } - /** - * Returns the current state. - * - * @return integer The current state - */ - public function getState() - { - return $this->state; - } - /** - * Returns a plugin by class name. - * - * @param string $name Class name of the plugin - * @return aCssParserPlugin - */ - public function getPlugin($class) - { - static $index = null; - if (is_null($index)) - { - $index = array(); - for ($i = 0, $l = count($this->plugins); $i < $l; $i++) - { - $index[get_class($this->plugins[$i])] = $i; - } - } - return isset($index[$class]) ? $this->plugins[$index[$class]] : false; - } - /** - * Returns the parsed tokens. - * - * @return array - */ - public function getTokens() - { - return $this->tokens; - } - /** - * Returns if the current state equals the passed state. - * - * @param integer $state State to compare with the current state - * @return boolean TRUE is the state equals to the passed state; FALSE if not - */ - public function isState($state) - { - return ($this->state == $state); - } - /** - * Parse the CSS source and return a array with parsed tokens. - * - * @param string $source CSS source - * @return array Array with tokens - */ - public function parse($source) - { - // Reset - $this->source = ""; - $this->tokens = array(); - // Create a global and plugin lookup table for trigger chars; set array of plugins as local variable and create - // several helper variables for plugin handling - $globalTriggerChars = ""; - $plugins = $this->plugins; - $pluginCount = count($plugins); - $pluginIndex = array(); - $pluginTriggerStates = array(); - $pluginTriggerChars = array(); - for ($i = 0, $l = count($plugins); $i < $l; $i++) - { - $tPluginClassName = get_class($plugins[$i]); - $pluginTriggerChars[$i] = implode("", $plugins[$i]->getTriggerChars()); - $tPluginTriggerStates = $plugins[$i]->getTriggerStates(); - $pluginTriggerStates[$i] = $tPluginTriggerStates === false ? false : "|" . implode("|", $tPluginTriggerStates) . "|"; - $pluginIndex[$tPluginClassName] = $i; - for ($ii = 0, $ll = strlen($pluginTriggerChars[$i]); $ii < $ll; $ii++) - { - $c = substr($pluginTriggerChars[$i], $ii, 1); - if (strpos($globalTriggerChars, $c) === false) - { - $globalTriggerChars .= $c; - } - } - } - // Normalise line endings - $source = str_replace("\r\n", "\n", $source); // Windows to Unix line endings - $source = str_replace("\r", "\n", $source); // Mac to Unix line endings - $this->source = $source; - // Variables - $buffer = &$this->buffer; - $exclusive = &$this->stateExclusive; - $state = &$this->state; - $c = $p = null; - // -- - for ($i = 0, $l = strlen($source); $i < $l; $i++) - { - // Set the current Char - $c = $source[$i]; // Is faster than: $c = substr($source, $i, 1); - // Normalize and filter double whitespace characters - if ($exclusive === false) - { - if ($c === "\n" || $c === "\t") - { - $c = " "; - } - if ($c === " " && $p === " ") - { - continue; - } - } - $buffer .= $c; - // Extended processing only if the current char is a global trigger char - if (strpos($globalTriggerChars, $c) !== false) - { - // Exclusive state is set; process with the exclusive plugin - if ($exclusive) - { - $tPluginIndex = $pluginIndex[$exclusive]; - if (strpos($pluginTriggerChars[$tPluginIndex], $c) !== false && ($pluginTriggerStates[$tPluginIndex] === false || strpos($pluginTriggerStates[$tPluginIndex], $state) !== false)) - { - $r = $plugins[$tPluginIndex]->parse($i, $c, $p, $state); - // Return value is TRUE => continue with next char - if ($r === true) - { - continue; - } - // Return value is numeric => set new index and continue with next char - elseif ($r !== false && $r != $i) - { - $i = $r; - continue; - } - } - } - // Else iterate through the plugins - else - { - $triggerState = "|" . $state . "|"; - for ($ii = 0, $ll = $pluginCount; $ii < $ll; $ii++) - { - // Only process if the current char is one of the plugin trigger chars - if (strpos($pluginTriggerChars[$ii], $c) !== false && ($pluginTriggerStates[$ii] === false || strpos($pluginTriggerStates[$ii], $triggerState) !== false)) - { - // Process with the plugin - $r = $plugins[$ii]->parse($i, $c, $p, $state); - // Return value is TRUE => break the plugin loop and and continue with next char - if ($r === true) - { - break; - } - // Return value is numeric => set new index, break the plugin loop and and continue with next char - elseif ($r !== false && $r != $i) - { - $i = $r; - break; - } - } - } - } - } - $p = $c; // Set the parent char - } - return $this->tokens; - } - /** - * Remove the last state of the state stack and return the removed stack value. - * - * @return integer Removed state value - */ - public function popState() - { - $r = array_pop($this->states); - $this->state = $this->states[count($this->states) - 1]; - return $r; - } - /** - * Adds a new state onto the state stack. - * - * @param integer $state State to add onto the state stack. - * @return integer The index of the added state in the state stacks - */ - public function pushState($state) - { - $r = array_push($this->states, $state); - $this->state = $this->states[count($this->states) - 1]; - return $r; - } - /** - * Sets/restores the buffer. - * - * @param string $buffer Buffer to set - * @return void - */ - public function setBuffer($buffer) - { - $this->buffer = $buffer; - } - /** - * Set the exclusive state. - * - * @param string $exclusive Exclusive state - * @return void - */ - public function setExclusive($exclusive) - { - $this->stateExclusive = $exclusive; - } - /** - * Set the media types state. - * - * @param array $mediaTypes Media types state - * @return void - */ - public function setMediaTypes(array $mediaTypes) - { - $this->stateMediaTypes = $mediaTypes; - } - /** - * Sets the current state in the state stack; equals to {@link CssParser::popState()} + {@link CssParser::pushState()}. - * - * @param integer $state State to set - * @return integer - */ - public function setState($state) - { - $r = array_pop($this->states); - array_push($this->states, $state); - $this->state = $this->states[count($this->states) - 1]; - return $r; - } - /** - * Removes the exclusive state. - * - * @return void - */ - public function unsetExclusive() - { - $this->stateExclusive = false; - } - /** - * Removes the media types state. - * - * @return void - */ - public function unsetMediaTypes() - { - $this->stateMediaTypes = false; - } - } - -/** - * {@link aCssFromatter Formatter} returning the CSS source in {@link http://goo.gl/j4XdU OTBS indent style} (The One True Brace Style). - * - * @package CssMin/Formatter - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssOtbsFormatter extends aCssFormatter - { - /** - * Implements {@link aCssFormatter::__toString()}. - * - * @return string - */ - public function __toString() - { - $r = array(); - $level = 0; - for ($i = 0, $l = count($this->tokens); $i < $l; $i++) - { - $token = $this->tokens[$i]; - $class = get_class($token); - $indent = str_repeat($this->indent, $level); - if ($class === "CssCommentToken") - { - $lines = array_map("trim", explode("\n", $token->Comment)); - for ($ii = 0, $ll = count($lines); $ii < $ll; $ii++) - { - $r[] = $indent . (substr($lines[$ii], 0, 1) == "*" ? " " : "") . $lines[$ii]; - } - } - elseif ($class === "CssAtCharsetToken") - { - $r[] = $indent . "@charset " . $token->Charset . ";"; - } - elseif ($class === "CssAtFontFaceStartToken") - { - $r[] = $indent . "@font-face {"; - $level++; - } - elseif ($class === "CssAtImportToken") - { - $r[] = $indent . "@import " . $token->Import . " " . implode(", ", $token->MediaTypes) . ";"; - } - elseif ($class === "CssAtKeyframesStartToken") - { - $r[] = $indent . "@keyframes \"" . $token->Name . "\" {"; - $level++; - } - elseif ($class === "CssAtMediaStartToken") - { - $r[] = $indent . "@media " . implode(", ", $token->MediaTypes) . " {"; - $level++; - } - elseif ($class === "CssAtPageStartToken") - { - $r[] = $indent . "@page {"; - $level++; - } - elseif ($class === "CssAtVariablesStartToken") - { - $r[] = $indent . "@variables " . implode(", ", $token->MediaTypes) . " {"; - $level++; - } - elseif ($class === "CssRulesetStartToken" || $class === "CssAtKeyframesRulesetStartToken") - { - $r[] = $indent . implode(", ", $token->Selectors) . " {"; - $level++; - } - elseif ($class == "CssAtFontFaceDeclarationToken" - || $class === "CssAtKeyframesRulesetDeclarationToken" - || $class === "CssAtPageDeclarationToken" - || $class == "CssAtVariablesDeclarationToken" - || $class === "CssRulesetDeclarationToken" - ) - { - $declaration = $indent . $token->Property . ": "; - if ($this->padding) - { - $declaration = str_pad($declaration, $this->padding, " ", STR_PAD_RIGHT); - } - $r[] = $declaration . $token->Value . ($token->IsImportant ? " !important" : "") . ";"; - } - elseif ($class === "CssAtFontFaceEndToken" - || $class === "CssAtMediaEndToken" - || $class === "CssAtKeyframesEndToken" - || $class === "CssAtKeyframesRulesetEndToken" - || $class === "CssAtPageEndToken" - || $class === "CssAtVariablesEndToken" - || $class === "CssRulesetEndToken" - ) - { - $level--; - $r[] = str_repeat($indent, $level) . "}"; - } - } - return implode("\n", $r); - } - } - -/** - * This {@link aCssToken CSS token} is a utility token that extends {@link aNullToken} and returns only a empty string. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssNullToken extends aCssToken - { - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return ""; - } - } - -/** - * CSS Minifier. - * - * @package CssMin/Minifier - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssMinifier - { - /** - * {@link aCssMinifierFilter Filters}. - * - * @var array - */ - private $filters = array(); - /** - * {@link aCssMinifierPlugin Plugins}. - * - * @var array - */ - private $plugins = array(); - /** - * Minified source. - * - * @var string - */ - private $minified = ""; - /** - * Constructer. - * - * Creates instances of {@link aCssMinifierFilter filters} and {@link aCssMinifierPlugin plugins}. - * - * @param string $source CSS source [optional] - * @param array $filters Filter configuration [optional] - * @param array $plugins Plugin configuration [optional] - * @return void - */ - public function __construct($source = null, array $filters = null, array $plugins = null) - { - $filters = array_merge(array - ( - "ImportImports" => false, - "RemoveComments" => true, - "RemoveEmptyRulesets" => true, - "RemoveEmptyAtBlocks" => true, - "ConvertLevel3Properties" => false, - "ConvertLevel3AtKeyframes" => false, - "Variables" => true, - "RemoveLastDelarationSemiColon" => true - ), is_array($filters) ? $filters : array()); - $plugins = array_merge(array - ( - "Variables" => true, - "ConvertFontWeight" => false, - "ConvertHslColors" => false, - "ConvertRgbColors" => false, - "ConvertNamedColors" => false, - "CompressColorValues" => false, - "CompressUnitValues" => false, - "CompressExpressionValues" => false - ), is_array($plugins) ? $plugins : array()); - // Filters - foreach ($filters as $name => $config) - { - if ($config !== false) - { - $class = "Css" . $name . "MinifierFilter"; - $config = is_array($config) ? $config : array(); - if (class_exists($class)) - { - $this->filters[] = new $class($this, $config); - } - else - { - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The filter " . $name . " with the class name " . $class . " was not found")); - } - } - } - // Plugins - foreach ($plugins as $name => $config) - { - if ($config !== false) - { - $class = "Css" . $name . "MinifierPlugin"; - $config = is_array($config) ? $config : array(); - if (class_exists($class)) - { - $this->plugins[] = new $class($this, $config); - } - else - { - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": The plugin " . $name . " with the class name " . $class . " was not found")); - } - } - } - // -- - if (!is_null($source)) - { - $this->minify($source); - } - } - /** - * Returns the minified Source. - * - * @return string - */ - public function getMinified() - { - return $this->minified; - } - /** - * Returns a plugin by class name. - * - * @param string $name Class name of the plugin - * @return aCssMinifierPlugin - */ - public function getPlugin($class) - { - static $index = null; - if (is_null($index)) - { - $index = array(); - for ($i = 0, $l = count($this->plugins); $i < $l; $i++) - { - $index[get_class($this->plugins[$i])] = $i; - } - } - return isset($index[$class]) ? $this->plugins[$index[$class]] : false; - } - /** - * Minifies the CSS source. - * - * @param string $source CSS source - * @return string - */ - public function minify($source) - { - // Variables - $r = ""; - $parser = new CssParser($source); - $tokens = $parser->getTokens(); - $filters = $this->filters; - $filterCount = count($this->filters); - $plugins = $this->plugins; - $pluginCount = count($plugins); - $pluginIndex = array(); - $pluginTriggerTokens = array(); - $globalTriggerTokens = array(); - for ($i = 0, $l = count($plugins); $i < $l; $i++) - { - $tPluginClassName = get_class($plugins[$i]); - $pluginTriggerTokens[$i] = $plugins[$i]->getTriggerTokens(); - foreach ($pluginTriggerTokens[$i] as $v) - { - if (!in_array($v, $globalTriggerTokens)) - { - $globalTriggerTokens[] = $v; - } - } - $pluginTriggerTokens[$i] = "|" . implode("|", $pluginTriggerTokens[$i]) . "|"; - $pluginIndex[$tPluginClassName] = $i; - } - $globalTriggerTokens = "|" . implode("|", $globalTriggerTokens) . "|"; - /* - * Apply filters - */ - for($i = 0; $i < $filterCount; $i++) - { - // Apply the filter; if the return value is larger than 0... - if ($filters[$i]->apply($tokens) > 0) - { - // ...then filter null values and rebuild the token array - $tokens = array_values(array_filter($tokens)); - } - } - $tokenCount = count($tokens); - /* - * Apply plugins - */ - for($i = 0; $i < $tokenCount; $i++) - { - $triggerToken = "|" . get_class($tokens[$i]) . "|"; - if (strpos($globalTriggerTokens, $triggerToken) !== false) - { - for($ii = 0; $ii < $pluginCount; $ii++) - { - if (strpos($pluginTriggerTokens[$ii], $triggerToken) !== false || $pluginTriggerTokens[$ii] === false) - { - // Apply the plugin; if the return value is TRUE continue to the next token - if ($plugins[$ii]->apply($tokens[$i]) === true) - { - continue 2; - } - } - } - } - } - // Stringify the tokens - for($i = 0; $i < $tokenCount; $i++) - { - $r .= (string) $tokens[$i]; - } - $this->minified = $r; - return $r; - } - } - -/** - * CssMin - A (simple) css minifier with benefits - * - * -- - * Copyright (c) 2011 Joe Scylla - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * -- - * - * @package CssMin - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssMin - { - /** - * Index of classes - * - * @var array - */ - private static $classIndex = array(); - /** - * Parse/minify errors - * - * @var array - */ - private static $errors = array(); - /** - * Verbose output. - * - * @var boolean - */ - private static $isVerbose = false; - /** - * {@link http://goo.gl/JrW54 Autoload} function of CssMin. - * - * @param string $class Name of the class - * @return void - */ - public static function autoload($class) - { - if (isset(self::$classIndex[$class])) - { - require(self::$classIndex[$class]); - } - } - /** - * Return errors - * - * @return array of {CssError}. - */ - public static function getErrors() - { - return self::$errors; - } - /** - * Returns if there were errors. - * - * @return boolean - */ - public static function hasErrors() - { - return count(self::$errors) > 0; - } - /** - * Initialises CssMin. - * - * @return void - */ - public static function initialise() - { - // Create the class index for autoloading or including - $paths = array(dirname(__FILE__)); - while (list($i, $path) = each($paths)) - { - $subDirectorys = glob($path . "*", GLOB_MARK | GLOB_ONLYDIR | GLOB_NOSORT); - if (is_array($subDirectorys)) - { - foreach ($subDirectorys as $subDirectory) - { - $paths[] = $subDirectory; - } - } - $files = glob($path . "*.php", 0); - if (is_array($files)) - { - foreach ($files as $file) - { - $class = substr(basename($file), 0, -4); - self::$classIndex[$class] = $file; - } - } - } - krsort(self::$classIndex); - // Only use autoloading if spl_autoload_register() is available and no __autoload() is defined (because - // __autoload() breaks if spl_autoload_register() is used. - if (function_exists("spl_autoload_register") && !is_callable("__autoload")) - { - spl_autoload_register(array(__CLASS__, "autoload")); - } - // Otherwise include all class files - else - { - foreach (self::$classIndex as $class => $file) - { - if (!class_exists($class)) - { - require_once($file); - } - } - } - } - /** - * Minifies CSS source. - * - * @param string $source CSS source - * @param array $filters Filter configuration [optional] - * @param array $plugins Plugin configuration [optional] - * @return string Minified CSS - */ - public static function minify($source, array $filters = null, array $plugins = null) - { - self::$errors = array(); - $minifier = new CssMinifier($source, $filters, $plugins); - return $minifier->getMinified(); - } - /** - * Parse the CSS source. - * - * @param string $source CSS source - * @param array $plugins Plugin configuration [optional] - * @return array Array of aCssToken - */ - public static function parse($source, array $plugins = null) - { - self::$errors = array(); - $parser = new CssParser($source, $plugins); - return $parser->getTokens(); - } - /** - * -- - * - * @param boolean $to - * @return boolean - */ - public static function setVerbose($to) - { - self::$isVerbose = (boolean) $to; - return self::$isVerbose; - } - /** - * -- - * - * @param CssError $error - * @return void - */ - public static function triggerError(CssError $error) - { - self::$errors[] = $error; - if (self::$isVerbose) - { - trigger_error((string) $error, E_USER_WARNING); - } - } - } -// Initialises CssMin -CssMin::initialise(); - -/** - * This {@link aCssMinifierFilter minifier filter} import external css files defined with the @import at-rule into the - * current stylesheet. - * - * @package CssMin/Minifier/Filters - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssImportImportsMinifierFilter extends aCssMinifierFilter - { - /** - * Array with already imported external stylesheets. - * - * @var array - */ - private $imported = array(); - /** - * Implements {@link aCssMinifierFilter::filter()}. - * - * @param array $tokens Array of objects of type aCssToken - * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array - */ - public function apply(array &$tokens) - { - if (!isset($this->configuration["BasePath"]) || !is_dir($this->configuration["BasePath"])) - { - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Base path " . ($this->configuration["BasePath"] ? $this->configuration["BasePath"] : "null"). " is not a directory")); - return 0; - } - for ($i = 0, $l = count($tokens); $i < $l; $i++) - { - if (get_class($tokens[$i]) === "CssAtImportToken") - { - $import = $this->configuration["BasePath"] . "/" . $tokens[$i]->Import; - // Import file was not found/is not a file - if (!is_file($import)) - { - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Import file " . $import. " was not found.", (string) $tokens[$i])); - } - // Import file already imported; remove this @import at-rule to prevent recursions - elseif (in_array($import, $this->imported)) - { - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Import file " . $import. " was already imported.", (string) $tokens[$i])); - $tokens[$i] = null; - } - else - { - $this->imported[] = $import; - $parser = new CssParser(file_get_contents($import)); - $import = $parser->getTokens(); - // The @import at-rule has media types defined requiring special handling - if (count($tokens[$i]->MediaTypes) > 0 && !(count($tokens[$i]->MediaTypes) == 1 && $tokens[$i]->MediaTypes[0] == "all")) - { - $blocks = array(); - /* - * Filter or set media types of @import at-rule or remove the @import at-rule if no media type is matching the parent @import at-rule - */ - for($ii = 0, $ll = count($import); $ii < $ll; $ii++) - { - if (get_class($import[$ii]) === "CssAtImportToken") - { - // @import at-rule defines no media type or only the "all" media type; set the media types to the one defined in the parent @import at-rule - if (count($import[$ii]->MediaTypes) == 0 || (count($import[$ii]->MediaTypes) == 1 && $import[$ii]->MediaTypes[0] == "all")) - { - $import[$ii]->MediaTypes = $tokens[$i]->MediaTypes; - } - // @import at-rule defineds one or more media types; filter out media types not matching with the parent @import at-rule - elseif (count($import[$ii]->MediaTypes > 0)) - { - foreach ($import[$ii]->MediaTypes as $index => $mediaType) - { - if (!in_array($mediaType, $tokens[$i]->MediaTypes)) - { - unset($import[$ii]->MediaTypes[$index]); - } - } - $import[$ii]->MediaTypes = array_values($import[$ii]->MediaTypes); - // If there are no media types left in the @import at-rule remove the @import at-rule - if (count($import[$ii]->MediaTypes) == 0) - { - $import[$ii] = null; - } - } - } - } - /* - * Remove media types of @media at-rule block not defined in the @import at-rule - */ - for($ii = 0, $ll = count($import); $ii < $ll; $ii++) - { - if (get_class($import[$ii]) === "CssAtMediaStartToken") - { - foreach ($import[$ii]->MediaTypes as $index => $mediaType) - { - if (!in_array($mediaType, $tokens[$i]->MediaTypes)) - { - unset($import[$ii]->MediaTypes[$index]); - } - $import[$ii]->MediaTypes = array_values($import[$ii]->MediaTypes); - } - } - } - /* - * If no media types left of the @media at-rule block remove the complete block - */ - for($ii = 0, $ll = count($import); $ii < $ll; $ii++) - { - if (get_class($import[$ii]) === "CssAtMediaStartToken") - { - if (count($import[$ii]->MediaTypes) === 0) - { - for ($iii = $ii; $iii < $ll; $iii++) - { - if (get_class($import[$iii]) === "CssAtMediaEndToken") - { - break; - } - } - if (get_class($import[$iii]) === "CssAtMediaEndToken") - { - array_splice($import, $ii, $iii - $ii + 1, array()); - $ll = count($import); - } - } - } - } - /* - * If the media types of the @media at-rule equals the media types defined in the @import - * at-rule remove the CssAtMediaStartToken and CssAtMediaEndToken token - */ - for($ii = 0, $ll = count($import); $ii < $ll; $ii++) - { - if (get_class($import[$ii]) === "CssAtMediaStartToken" && count(array_diff($tokens[$i]->MediaTypes, $import[$ii]->MediaTypes)) === 0) - { - for ($iii = $ii; $iii < $ll; $iii++) - { - if (get_class($import[$iii]) == "CssAtMediaEndToken") - { - break; - } - } - if (get_class($import[$iii]) == "CssAtMediaEndToken") - { - unset($import[$ii]); - unset($import[$iii]); - $import = array_values($import); - $ll = count($import); - } - } - } - /** - * Extract CssAtImportToken and CssAtCharsetToken tokens - */ - for($ii = 0, $ll = count($import); $ii < $ll; $ii++) - { - $class = get_class($import[$ii]); - if ($class === "CssAtImportToken" || $class === "CssAtCharsetToken") - { - $blocks = array_merge($blocks, array_splice($import, $ii, 1, array())); - $ll = count($import); - } - } - /* - * Extract the @font-face, @media and @page at-rule block - */ - for($ii = 0, $ll = count($import); $ii < $ll; $ii++) - { - $class = get_class($import[$ii]); - if ($class === "CssAtFontFaceStartToken" || $class === "CssAtMediaStartToken" || $class === "CssAtPageStartToken" || $class === "CssAtVariablesStartToken") - { - for ($iii = $ii; $iii < $ll; $iii++) - { - $class = get_class($import[$iii]); - if ($class === "CssAtFontFaceEndToken" || $class === "CssAtMediaEndToken" || $class === "CssAtPageEndToken" || $class === "CssAtVariablesEndToken") - { - break; - } - } - $class = get_class($import[$iii]); - if (isset($import[$iii]) && ($class === "CssAtFontFaceEndToken" || $class === "CssAtMediaEndToken" || $class === "CssAtPageEndToken" || $class === "CssAtVariablesEndToken")) - { - $blocks = array_merge($blocks, array_splice($import, $ii, $iii - $ii + 1, array())); - $ll = count($import); - } - } - } - // Create the import array with extracted tokens and the rulesets wrapped into a @media at-rule block - $import = array_merge($blocks, array(new CssAtMediaStartToken($tokens[$i]->MediaTypes)), $import, array(new CssAtMediaEndToken())); - } - // Insert the imported tokens - array_splice($tokens, $i, 1, $import); - // Modify parameters of the for-loop - $i--; - $l = count($tokens); - } - } - } - } - } - -/** - * {@link aCssParserPlugin Parser plugin} for preserve parsing expression() declaration values. - * - * This plugin return no {@link aCssToken CssToken} but ensures that expression() declaration values will get parsed - * properly. - * - * @package CssMin/Parser/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssExpressionParserPlugin extends aCssParserPlugin - { - /** - * Count of left braces. - * - * @var integer - */ - private $leftBraces = 0; - /** - * Count of right braces. - * - * @var integer - */ - private $rightBraces = 0; - /** - * Implements {@link aCssParserPlugin::getTriggerChars()}. - * - * @return array - */ - public function getTriggerChars() - { - return array("(", ")", ";", "}"); - } - /** - * Implements {@link aCssParserPlugin::getTriggerStates()}. - * - * @return array - */ - public function getTriggerStates() - { - return false; - } - /** - * Implements {@link aCssParserPlugin::parse()}. - * - * @param integer $index Current index - * @param string $char Current char - * @param string $previousChar Previous char - * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing - */ - public function parse($index, $char, $previousChar, $state) - { - // Start of expression - if ($char === "(" && strtolower(substr($this->parser->getSource(), $index - 10, 11)) === "expression(" && $state !== "T_EXPRESSION") - { - $this->parser->pushState("T_EXPRESSION"); - $this->leftBraces++; - } - // Count left braces - elseif ($char === "(" && $state === "T_EXPRESSION") - { - $this->leftBraces++; - } - // Count right braces - elseif ($char === ")" && $state === "T_EXPRESSION") - { - $this->rightBraces++; - } - // Possible end of expression; if left and right braces are equal the expressen ends - elseif (($char === ";" || $char === "}") && $state === "T_EXPRESSION" && $this->leftBraces === $this->rightBraces) - { - $this->leftBraces = $this->rightBraces = 0; - $this->parser->popState(); - return $index - 1; - } - else - { - return false; - } - return true; - } - } - -/** - * CSS Error. - * - * @package CssMin - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssError - { - /** - * File. - * - * @var string - */ - public $File = ""; - /** - * Line. - * - * @var integer - */ - public $Line = 0; - /** - * Error message. - * - * @var string - */ - public $Message = ""; - /** - * Source. - * - * @var string - */ - public $Source = ""; - /** - * Constructor triggering the error. - * - * @param string $message Error message - * @param string $source Corresponding line [optional] - * @return void - */ - public function __construct($file, $line, $message, $source = "") - { - $this->File = $file; - $this->Line = $line; - $this->Message = $message; - $this->Source = $source; - } - /** - * Returns the error as formatted string. - * - * @return string - */ - public function __toString() - { - return $this->Message . ($this->Source ? ":
" . $this->Source . "": "") . "
in file " . $this->File . " at line " . $this->Line; - } - } - -/** - * This {@link aCssMinifierPlugin} will convert a color value in rgb notation to hexadecimal notation. - * - * Example: - * - * color: rgb(200,60%,5); - * - * - * Will get converted to: - * - * color:#c89905; - * - * - * @package CssMin/Minifier/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssConvertRgbColorsMinifierPlugin extends aCssMinifierPlugin - { - /** - * Regular expression matching the value. - * - * @var string - */ - private $reMatch = "/rgb\s*\(\s*([0-9%]+)\s*,\s*([0-9%]+)\s*,\s*([0-9%]+)\s*\)/iS"; - /** - * Implements {@link aCssMinifierPlugin::minify()}. - * - * @param aCssToken $token Token to process - * @return boolean Return TRUE to break the processing of this token; FALSE to continue - */ - public function apply(aCssToken &$token) - { - if (stripos($token->Value, "rgb") !== false && preg_match($this->reMatch, $token->Value, $m)) - { - for ($i = 1, $l = count($m); $i < $l; $i++) - { - if (strpos("%", $m[$i]) !== false) - { - $m[$i] = substr($m[$i], 0, -1); - $m[$i] = (int) (256 * ($m[$i] / 100)); - } - $m[$i] = str_pad(dechex($m[$i]), 2, "0", STR_PAD_LEFT); - } - $token->Value = str_replace($m[0], "#" . $m[1] . $m[2] . $m[3], $token->Value); - } - return false; - } - /** - * Implements {@link aMinifierPlugin::getTriggerTokens()} - * - * @return array - */ - public function getTriggerTokens() - { - return array - ( - "CssAtFontFaceDeclarationToken", - "CssAtPageDeclarationToken", - "CssRulesetDeclarationToken" - ); - } - } - -/** - * This {@link aCssMinifierPlugin} will convert named color values to hexadecimal notation. - * - * Example: - * - * color: black; - * border: 1px solid indigo; - * - * - * Will get converted to: - * - * color:#000; - * border:1px solid #4b0082; - * - * - * @package CssMin/Minifier/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssConvertNamedColorsMinifierPlugin extends aCssMinifierPlugin - { - - /** - * Regular expression matching the value. - * - * @var string - */ - private $reMatch = null; - /** - * Regular expression replacing the value. - * - * @var string - */ - private $reReplace = "\"\${1}\" . \$this->transformation[strtolower(\"\${2}\")] . \"\${3}\""; - /** - * Transformation table used by the {@link CssConvertNamedColorsMinifierPlugin::$reReplace replace regular expression}. - * - * @var array - */ - private $transformation = array - ( - "aliceblue" => "#f0f8ff", - "antiquewhite" => "#faebd7", - "aqua" => "#0ff", - "aquamarine" => "#7fffd4", - "azure" => "#f0ffff", - "beige" => "#f5f5dc", - "black" => "#000", - "blue" => "#00f", - "blueviolet" => "#8a2be2", - "brown" => "#a52a2a", - "burlywood" => "#deb887", - "cadetblue" => "#5f9ea0", - "chartreuse" => "#7fff00", - "chocolate" => "#d2691e", - "coral" => "#ff7f50", - "cornflowerblue" => "#6495ed", - "cornsilk" => "#fff8dc", - "crimson" => "#dc143c", - "darkblue" => "#00008b", - "darkcyan" => "#008b8b", - "darkgoldenrod" => "#b8860b", - "darkgray" => "#a9a9a9", - "darkgreen" => "#006400", - "darkkhaki" => "#bdb76b", - "darkmagenta" => "#8b008b", - "darkolivegreen" => "#556b2f", - "darkorange" => "#ff8c00", - "darkorchid" => "#9932cc", - "darkred" => "#8b0000", - "darksalmon" => "#e9967a", - "darkseagreen" => "#8fbc8f", - "darkslateblue" => "#483d8b", - "darkslategray" => "#2f4f4f", - "darkturquoise" => "#00ced1", - "darkviolet" => "#9400d3", - "deeppink" => "#ff1493", - "deepskyblue" => "#00bfff", - "dimgray" => "#696969", - "dodgerblue" => "#1e90ff", - "firebrick" => "#b22222", - "floralwhite" => "#fffaf0", - "forestgreen" => "#228b22", - "fuchsia" => "#f0f", - "gainsboro" => "#dcdcdc", - "ghostwhite" => "#f8f8ff", - "gold" => "#ffd700", - "goldenrod" => "#daa520", - "gray" => "#808080", - "green" => "#008000", - "greenyellow" => "#adff2f", - "honeydew" => "#f0fff0", - "hotpink" => "#ff69b4", - "indianred" => "#cd5c5c", - "indigo" => "#4b0082", - "ivory" => "#fffff0", - "khaki" => "#f0e68c", - "lavender" => "#e6e6fa", - "lavenderblush" => "#fff0f5", - "lawngreen" => "#7cfc00", - "lemonchiffon" => "#fffacd", - "lightblue" => "#add8e6", - "lightcoral" => "#f08080", - "lightcyan" => "#e0ffff", - "lightgoldenrodyellow" => "#fafad2", - "lightgreen" => "#90ee90", - "lightgrey" => "#d3d3d3", - "lightpink" => "#ffb6c1", - "lightsalmon" => "#ffa07a", - "lightseagreen" => "#20b2aa", - "lightskyblue" => "#87cefa", - "lightslategray" => "#789", - "lightsteelblue" => "#b0c4de", - "lightyellow" => "#ffffe0", - "lime" => "#0f0", - "limegreen" => "#32cd32", - "linen" => "#faf0e6", - "maroon" => "#800000", - "mediumaquamarine" => "#66cdaa", - "mediumblue" => "#0000cd", - "mediumorchid" => "#ba55d3", - "mediumpurple" => "#9370db", - "mediumseagreen" => "#3cb371", - "mediumslateblue" => "#7b68ee", - "mediumspringgreen" => "#00fa9a", - "mediumturquoise" => "#48d1cc", - "mediumvioletred" => "#c71585", - "midnightblue" => "#191970", - "mintcream" => "#f5fffa", - "mistyrose" => "#ffe4e1", - "moccasin" => "#ffe4b5", - "navajowhite" => "#ffdead", - "navy" => "#000080", - "oldlace" => "#fdf5e6", - "olive" => "#808000", - "olivedrab" => "#6b8e23", - "orange" => "#ffa500", - "orangered" => "#ff4500", - "orchid" => "#da70d6", - "palegoldenrod" => "#eee8aa", - "palegreen" => "#98fb98", - "paleturquoise" => "#afeeee", - "palevioletred" => "#db7093", - "papayawhip" => "#ffefd5", - "peachpuff" => "#ffdab9", - "peru" => "#cd853f", - "pink" => "#ffc0cb", - "plum" => "#dda0dd", - "powderblue" => "#b0e0e6", - "purple" => "#800080", - "red" => "#f00", - "rosybrown" => "#bc8f8f", - "royalblue" => "#4169e1", - "saddlebrown" => "#8b4513", - "salmon" => "#fa8072", - "sandybrown" => "#f4a460", - "seagreen" => "#2e8b57", - "seashell" => "#fff5ee", - "sienna" => "#a0522d", - "silver" => "#c0c0c0", - "skyblue" => "#87ceeb", - "slateblue" => "#6a5acd", - "slategray" => "#708090", - "snow" => "#fffafa", - "springgreen" => "#00ff7f", - "steelblue" => "#4682b4", - "tan" => "#d2b48c", - "teal" => "#008080", - "thistle" => "#d8bfd8", - "tomato" => "#ff6347", - "turquoise" => "#40e0d0", - "violet" => "#ee82ee", - "wheat" => "#f5deb3", - "white" => "#fff", - "whitesmoke" => "#f5f5f5", - "yellow" => "#ff0", - "yellowgreen" => "#9acd32" - ); - /** - * Overwrites {@link aCssMinifierPlugin::__construct()}. - * - * The constructor will create the {@link CssConvertNamedColorsMinifierPlugin::$reReplace replace regular expression} - * based on the {@link CssConvertNamedColorsMinifierPlugin::$transformation transformation table}. - * - * @param CssMinifier $minifier The CssMinifier object of this plugin. - * @param array $configuration Plugin configuration [optional] - * @return void - */ - public function __construct(CssMinifier $minifier, array $configuration = array()) - { - $this->reMatch = "/(^|\s)+(" . implode("|", array_keys($this->transformation)) . ")(\s|$)+/eiS"; - parent::__construct($minifier, $configuration); - } - /** - * Implements {@link aCssMinifierPlugin::minify()}. - * - * @param aCssToken $token Token to process - * @return boolean Return TRUE to break the processing of this token; FALSE to continue - */ - public function apply(aCssToken &$token) - { - $lcValue = strtolower($token->Value); - // Declaration value equals a value in the transformation table => simple replace - if (isset($this->transformation[$lcValue])) - { - $token->Value = $this->transformation[$lcValue]; - } - // Declaration value contains a value in the transformation table => regular expression replace - elseif (preg_match($this->reMatch, $token->Value)) - { - $token->Value = preg_replace($this->reMatch, $this->reReplace, $token->Value); - } - return false; - } - /** - * Implements {@link aMinifierPlugin::getTriggerTokens()} - * - * @return array - */ - public function getTriggerTokens() - { - return array - ( - "CssAtFontFaceDeclarationToken", - "CssAtPageDeclarationToken", - "CssRulesetDeclarationToken" - ); - } - } - -/** - * This {@link aCssMinifierFilter minifier filter} triggers on CSS Level 3 properties and will add declaration tokens - * with browser-specific properties. - * - * @package CssMin/Minifier/Filters - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssConvertLevel3PropertiesMinifierFilter extends aCssMinifierFilter - { - /** - * Css property transformations table. Used to convert CSS3 and proprietary properties to the browser-specific - * counterparts. - * - * @var array - */ - private $transformations = array - ( - // Property Array(Mozilla, Webkit, Opera, Internet Explorer); NULL values are placeholders and will get ignored - "animation" => array(null, "-webkit-animation", null, null), - "animation-delay" => array(null, "-webkit-animation-delay", null, null), - "animation-direction" => array(null, "-webkit-animation-direction", null, null), - "animation-duration" => array(null, "-webkit-animation-duration", null, null), - "animation-fill-mode" => array(null, "-webkit-animation-fill-mode", null, null), - "animation-iteration-count" => array(null, "-webkit-animation-iteration-count", null, null), - "animation-name" => array(null, "-webkit-animation-name", null, null), - "animation-play-state" => array(null, "-webkit-animation-play-state", null, null), - "animation-timing-function" => array(null, "-webkit-animation-timing-function", null, null), - "appearance" => array("-moz-appearance", "-webkit-appearance", null, null), - "backface-visibility" => array(null, "-webkit-backface-visibility", null, null), - "background-clip" => array(null, "-webkit-background-clip", null, null), - "background-composite" => array(null, "-webkit-background-composite", null, null), - "background-inline-policy" => array("-moz-background-inline-policy", null, null, null), - "background-origin" => array(null, "-webkit-background-origin", null, null), - "background-position-x" => array(null, null, null, "-ms-background-position-x"), - "background-position-y" => array(null, null, null, "-ms-background-position-y"), - "background-size" => array(null, "-webkit-background-size", null, null), - "behavior" => array(null, null, null, "-ms-behavior"), - "binding" => array("-moz-binding", null, null, null), - "border-after" => array(null, "-webkit-border-after", null, null), - "border-after-color" => array(null, "-webkit-border-after-color", null, null), - "border-after-style" => array(null, "-webkit-border-after-style", null, null), - "border-after-width" => array(null, "-webkit-border-after-width", null, null), - "border-before" => array(null, "-webkit-border-before", null, null), - "border-before-color" => array(null, "-webkit-border-before-color", null, null), - "border-before-style" => array(null, "-webkit-border-before-style", null, null), - "border-before-width" => array(null, "-webkit-border-before-width", null, null), - "border-border-bottom-colors" => array("-moz-border-bottom-colors", null, null, null), - "border-bottom-left-radius" => array("-moz-border-radius-bottomleft", "-webkit-border-bottom-left-radius", null, null), - "border-bottom-right-radius" => array("-moz-border-radius-bottomright", "-webkit-border-bottom-right-radius", null, null), - "border-end" => array("-moz-border-end", "-webkit-border-end", null, null), - "border-end-color" => array("-moz-border-end-color", "-webkit-border-end-color", null, null), - "border-end-style" => array("-moz-border-end-style", "-webkit-border-end-style", null, null), - "border-end-width" => array("-moz-border-end-width", "-webkit-border-end-width", null, null), - "border-fit" => array(null, "-webkit-border-fit", null, null), - "border-horizontal-spacing" => array(null, "-webkit-border-horizontal-spacing", null, null), - "border-image" => array("-moz-border-image", "-webkit-border-image", null, null), - "border-left-colors" => array("-moz-border-left-colors", null, null, null), - "border-radius" => array("-moz-border-radius", "-webkit-border-radius", null, null), - "border-border-right-colors" => array("-moz-border-right-colors", null, null, null), - "border-start" => array("-moz-border-start", "-webkit-border-start", null, null), - "border-start-color" => array("-moz-border-start-color", "-webkit-border-start-color", null, null), - "border-start-style" => array("-moz-border-start-style", "-webkit-border-start-style", null, null), - "border-start-width" => array("-moz-border-start-width", "-webkit-border-start-width", null, null), - "border-top-colors" => array("-moz-border-top-colors", null, null, null), - "border-top-left-radius" => array("-moz-border-radius-topleft", "-webkit-border-top-left-radius", null, null), - "border-top-right-radius" => array("-moz-border-radius-topright", "-webkit-border-top-right-radius", null, null), - "border-vertical-spacing" => array(null, "-webkit-border-vertical-spacing", null, null), - "box-align" => array("-moz-box-align", "-webkit-box-align", null, null), - "box-direction" => array("-moz-box-direction", "-webkit-box-direction", null, null), - "box-flex" => array("-moz-box-flex", "-webkit-box-flex", null, null), - "box-flex-group" => array(null, "-webkit-box-flex-group", null, null), - "box-flex-lines" => array(null, "-webkit-box-flex-lines", null, null), - "box-ordinal-group" => array("-moz-box-ordinal-group", "-webkit-box-ordinal-group", null, null), - "box-orient" => array("-moz-box-orient", "-webkit-box-orient", null, null), - "box-pack" => array("-moz-box-pack", "-webkit-box-pack", null, null), - "box-reflect" => array(null, "-webkit-box-reflect", null, null), - "box-shadow" => array("-moz-box-shadow", "-webkit-box-shadow", null, null), - "box-sizing" => array("-moz-box-sizing", null, null, null), - "color-correction" => array(null, "-webkit-color-correction", null, null), - "column-break-after" => array(null, "-webkit-column-break-after", null, null), - "column-break-before" => array(null, "-webkit-column-break-before", null, null), - "column-break-inside" => array(null, "-webkit-column-break-inside", null, null), - "column-count" => array("-moz-column-count", "-webkit-column-count", null, null), - "column-gap" => array("-moz-column-gap", "-webkit-column-gap", null, null), - "column-rule" => array("-moz-column-rule", "-webkit-column-rule", null, null), - "column-rule-color" => array("-moz-column-rule-color", "-webkit-column-rule-color", null, null), - "column-rule-style" => array("-moz-column-rule-style", "-webkit-column-rule-style", null, null), - "column-rule-width" => array("-moz-column-rule-width", "-webkit-column-rule-width", null, null), - "column-span" => array(null, "-webkit-column-span", null, null), - "column-width" => array("-moz-column-width", "-webkit-column-width", null, null), - "columns" => array(null, "-webkit-columns", null, null), - "filter" => array(__CLASS__, "filter"), - "float-edge" => array("-moz-float-edge", null, null, null), - "font-feature-settings" => array("-moz-font-feature-settings", null, null, null), - "font-language-override" => array("-moz-font-language-override", null, null, null), - "font-size-delta" => array(null, "-webkit-font-size-delta", null, null), - "font-smoothing" => array(null, "-webkit-font-smoothing", null, null), - "force-broken-image-icon" => array("-moz-force-broken-image-icon", null, null, null), - "highlight" => array(null, "-webkit-highlight", null, null), - "hyphenate-character" => array(null, "-webkit-hyphenate-character", null, null), - "hyphenate-locale" => array(null, "-webkit-hyphenate-locale", null, null), - "hyphens" => array(null, "-webkit-hyphens", null, null), - "force-broken-image-icon" => array("-moz-image-region", null, null, null), - "ime-mode" => array(null, null, null, "-ms-ime-mode"), - "interpolation-mode" => array(null, null, null, "-ms-interpolation-mode"), - "layout-flow" => array(null, null, null, "-ms-layout-flow"), - "layout-grid" => array(null, null, null, "-ms-layout-grid"), - "layout-grid-char" => array(null, null, null, "-ms-layout-grid-char"), - "layout-grid-line" => array(null, null, null, "-ms-layout-grid-line"), - "layout-grid-mode" => array(null, null, null, "-ms-layout-grid-mode"), - "layout-grid-type" => array(null, null, null, "-ms-layout-grid-type"), - "line-break" => array(null, "-webkit-line-break", null, "-ms-line-break"), - "line-clamp" => array(null, "-webkit-line-clamp", null, null), - "line-grid-mode" => array(null, null, null, "-ms-line-grid-mode"), - "logical-height" => array(null, "-webkit-logical-height", null, null), - "logical-width" => array(null, "-webkit-logical-width", null, null), - "margin-after" => array(null, "-webkit-margin-after", null, null), - "margin-after-collapse" => array(null, "-webkit-margin-after-collapse", null, null), - "margin-before" => array(null, "-webkit-margin-before", null, null), - "margin-before-collapse" => array(null, "-webkit-margin-before-collapse", null, null), - "margin-bottom-collapse" => array(null, "-webkit-margin-bottom-collapse", null, null), - "margin-collapse" => array(null, "-webkit-margin-collapse", null, null), - "margin-end" => array("-moz-margin-end", "-webkit-margin-end", null, null), - "margin-start" => array("-moz-margin-start", "-webkit-margin-start", null, null), - "margin-top-collapse" => array(null, "-webkit-margin-top-collapse", null, null), - "marquee " => array(null, "-webkit-marquee", null, null), - "marquee-direction" => array(null, "-webkit-marquee-direction", null, null), - "marquee-increment" => array(null, "-webkit-marquee-increment", null, null), - "marquee-repetition" => array(null, "-webkit-marquee-repetition", null, null), - "marquee-speed" => array(null, "-webkit-marquee-speed", null, null), - "marquee-style" => array(null, "-webkit-marquee-style", null, null), - "mask" => array(null, "-webkit-mask", null, null), - "mask-attachment" => array(null, "-webkit-mask-attachment", null, null), - "mask-box-image" => array(null, "-webkit-mask-box-image", null, null), - "mask-clip" => array(null, "-webkit-mask-clip", null, null), - "mask-composite" => array(null, "-webkit-mask-composite", null, null), - "mask-image" => array(null, "-webkit-mask-image", null, null), - "mask-origin" => array(null, "-webkit-mask-origin", null, null), - "mask-position" => array(null, "-webkit-mask-position", null, null), - "mask-position-x" => array(null, "-webkit-mask-position-x", null, null), - "mask-position-y" => array(null, "-webkit-mask-position-y", null, null), - "mask-repeat" => array(null, "-webkit-mask-repeat", null, null), - "mask-repeat-x" => array(null, "-webkit-mask-repeat-x", null, null), - "mask-repeat-y" => array(null, "-webkit-mask-repeat-y", null, null), - "mask-size" => array(null, "-webkit-mask-size", null, null), - "match-nearest-mail-blockquote-color" => array(null, "-webkit-match-nearest-mail-blockquote-color", null, null), - "max-logical-height" => array(null, "-webkit-max-logical-height", null, null), - "max-logical-width" => array(null, "-webkit-max-logical-width", null, null), - "min-logical-height" => array(null, "-webkit-min-logical-height", null, null), - "min-logical-width" => array(null, "-webkit-min-logical-width", null, null), - "object-fit" => array(null, null, "-o-object-fit", null), - "object-position" => array(null, null, "-o-object-position", null), - "opacity" => array(__CLASS__, "opacity"), - "outline-radius" => array("-moz-outline-radius", null, null, null), - "outline-bottom-left-radius" => array("-moz-outline-radius-bottomleft", null, null, null), - "outline-bottom-right-radius" => array("-moz-outline-radius-bottomright", null, null, null), - "outline-top-left-radius" => array("-moz-outline-radius-topleft", null, null, null), - "outline-top-right-radius" => array("-moz-outline-radius-topright", null, null, null), - "padding-after" => array(null, "-webkit-padding-after", null, null), - "padding-before" => array(null, "-webkit-padding-before", null, null), - "padding-end" => array("-moz-padding-end", "-webkit-padding-end", null, null), - "padding-start" => array("-moz-padding-start", "-webkit-padding-start", null, null), - "perspective" => array(null, "-webkit-perspective", null, null), - "perspective-origin" => array(null, "-webkit-perspective-origin", null, null), - "perspective-origin-x" => array(null, "-webkit-perspective-origin-x", null, null), - "perspective-origin-y" => array(null, "-webkit-perspective-origin-y", null, null), - "rtl-ordering" => array(null, "-webkit-rtl-ordering", null, null), - "scrollbar-3dlight-color" => array(null, null, null, "-ms-scrollbar-3dlight-color"), - "scrollbar-arrow-color" => array(null, null, null, "-ms-scrollbar-arrow-color"), - "scrollbar-base-color" => array(null, null, null, "-ms-scrollbar-base-color"), - "scrollbar-darkshadow-color" => array(null, null, null, "-ms-scrollbar-darkshadow-color"), - "scrollbar-face-color" => array(null, null, null, "-ms-scrollbar-face-color"), - "scrollbar-highlight-color" => array(null, null, null, "-ms-scrollbar-highlight-color"), - "scrollbar-shadow-color" => array(null, null, null, "-ms-scrollbar-shadow-color"), - "scrollbar-track-color" => array(null, null, null, "-ms-scrollbar-track-color"), - "stack-sizing" => array("-moz-stack-sizing", null, null, null), - "svg-shadow" => array(null, "-webkit-svg-shadow", null, null), - "tab-size" => array("-moz-tab-size", null, "-o-tab-size", null), - "table-baseline" => array(null, null, "-o-table-baseline", null), - "text-align-last" => array(null, null, null, "-ms-text-align-last"), - "text-autospace" => array(null, null, null, "-ms-text-autospace"), - "text-combine" => array(null, "-webkit-text-combine", null, null), - "text-decorations-in-effect" => array(null, "-webkit-text-decorations-in-effect", null, null), - "text-emphasis" => array(null, "-webkit-text-emphasis", null, null), - "text-emphasis-color" => array(null, "-webkit-text-emphasis-color", null, null), - "text-emphasis-position" => array(null, "-webkit-text-emphasis-position", null, null), - "text-emphasis-style" => array(null, "-webkit-text-emphasis-style", null, null), - "text-fill-color" => array(null, "-webkit-text-fill-color", null, null), - "text-justify" => array(null, null, null, "-ms-text-justify"), - "text-kashida-space" => array(null, null, null, "-ms-text-kashida-space"), - "text-overflow" => array(null, null, "-o-text-overflow", "-ms-text-overflow"), - "text-security" => array(null, "-webkit-text-security", null, null), - "text-size-adjust" => array(null, "-webkit-text-size-adjust", null, "-ms-text-size-adjust"), - "text-stroke" => array(null, "-webkit-text-stroke", null, null), - "text-stroke-color" => array(null, "-webkit-text-stroke-color", null, null), - "text-stroke-width" => array(null, "-webkit-text-stroke-width", null, null), - "text-underline-position" => array(null, null, null, "-ms-text-underline-position"), - "transform" => array("-moz-transform", "-webkit-transform", "-o-transform", null), - "transform-origin" => array("-moz-transform-origin", "-webkit-transform-origin", "-o-transform-origin", null), - "transform-origin-x" => array(null, "-webkit-transform-origin-x", null, null), - "transform-origin-y" => array(null, "-webkit-transform-origin-y", null, null), - "transform-origin-z" => array(null, "-webkit-transform-origin-z", null, null), - "transform-style" => array(null, "-webkit-transform-style", null, null), - "transition" => array("-moz-transition", "-webkit-transition", "-o-transition", null), - "transition-delay" => array("-moz-transition-delay", "-webkit-transition-delay", "-o-transition-delay", null), - "transition-duration" => array("-moz-transition-duration", "-webkit-transition-duration", "-o-transition-duration", null), - "transition-property" => array("-moz-transition-property", "-webkit-transition-property", "-o-transition-property", null), - "transition-timing-function" => array("-moz-transition-timing-function", "-webkit-transition-timing-function", "-o-transition-timing-function", null), - "user-drag" => array(null, "-webkit-user-drag", null, null), - "user-focus" => array("-moz-user-focus", null, null, null), - "user-input" => array("-moz-user-input", null, null, null), - "user-modify" => array("-moz-user-modify", "-webkit-user-modify", null, null), - "user-select" => array("-moz-user-select", "-webkit-user-select", null, null), - "white-space" => array(__CLASS__, "whiteSpace"), - "window-shadow" => array("-moz-window-shadow", null, null, null), - "word-break" => array(null, null, null, "-ms-word-break"), - "word-wrap" => array(null, null, null, "-ms-word-wrap"), - "writing-mode" => array(null, "-webkit-writing-mode", null, "-ms-writing-mode"), - "zoom" => array(null, null, null, "-ms-zoom") - ); - /** - * Implements {@link aCssMinifierFilter::filter()}. - * - * @param array $tokens Array of objects of type aCssToken - * @return integer Count of added, changed or removed tokens; a return value large than 0 will rebuild the array - */ - public function apply(array &$tokens) - { - $r = 0; - $transformations = &$this->transformations; - for ($i = 0, $l = count($tokens); $i < $l; $i++) - { - if (get_class($tokens[$i]) === "CssRulesetDeclarationToken") - { - $tProperty = $tokens[$i]->Property; - if (isset($transformations[$tProperty])) - { - $result = array(); - if (is_callable($transformations[$tProperty])) - { - $result = call_user_func_array($transformations[$tProperty], array($tokens[$i])); - if (!is_array($result) && is_object($result)) - { - $result = array($result); - } - } - else - { - $tValue = $tokens[$i]->Value; - $tMediaTypes = $tokens[$i]->MediaTypes; - foreach ($transformations[$tProperty] as $property) - { - if ($property !== null) - { - $result[] = new CssRulesetDeclarationToken($property, $tValue, $tMediaTypes); - } - } - } - if (count($result) > 0) - { - array_splice($tokens, $i + 1, 0, $result); - $i += count($result); - $l += count($result); - } - } - } - } - return $r; - } - /** - * Transforms the Internet Explorer specific declaration property "filter" to Internet Explorer 8+ compatible - * declaratiopn property "-ms-filter". - * - * @param aCssToken $token - * @return array - */ - private static function filter($token) - { - $r = array - ( - new CssRulesetDeclarationToken("-ms-filter", "\"" . $token->Value . "\"", $token->MediaTypes), - ); - return $r; - } - /** - * Transforms "opacity: {value}" into browser specific counterparts. - * - * @param aCssToken $token - * @return array - */ - private static function opacity($token) - { - // Calculate the value for Internet Explorer filter statement - $ieValue = (int) ((float) $token->Value * 100); - $r = array - ( - // Internet Explorer >= 8 - new CssRulesetDeclarationToken("-ms-filter", "\"alpha(opacity=" . $ieValue . ")\"", $token->MediaTypes), - // Internet Explorer >= 4 <= 7 - new CssRulesetDeclarationToken("filter", "alpha(opacity=" . $ieValue . ")", $token->MediaTypes), - new CssRulesetDeclarationToken("zoom", "1", $token->MediaTypes) - ); - return $r; - } - /** - * Transforms "white-space: pre-wrap" into browser specific counterparts. - * - * @param aCssToken $token - * @return array - */ - private static function whiteSpace($token) - { - if (strtolower($token->Value) === "pre-wrap") - { - $r = array - ( - // Firefox < 3 - new CssRulesetDeclarationToken("white-space", "-moz-pre-wrap", $token->MediaTypes), - // Webkit - new CssRulesetDeclarationToken("white-space", "-webkit-pre-wrap", $token->MediaTypes), - // Opera >= 4 <= 6 - new CssRulesetDeclarationToken("white-space", "-pre-wrap", $token->MediaTypes), - // Opera >= 7 - new CssRulesetDeclarationToken("white-space", "-o-pre-wrap", $token->MediaTypes), - // Internet Explorer >= 5.5 - new CssRulesetDeclarationToken("word-wrap", "break-word", $token->MediaTypes) - ); - return $r; - } - else - { - return array(); - } - } - } - -/** - * This {@link aCssMinifierFilter minifier filter} will convert @keyframes at-rule block to browser specific counterparts. - * - * @package CssMin/Minifier/Filters - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssConvertLevel3AtKeyframesMinifierFilter extends aCssMinifierFilter - { - /** - * Implements {@link aCssMinifierFilter::filter()}. - * - * @param array $tokens Array of objects of type aCssToken - * @return integer Count of added, changed or removed tokens; a return value larger than 0 will rebuild the array - */ - public function apply(array &$tokens) - { - $r = 0; - $transformations = array("-moz-keyframes", "-webkit-keyframes"); - for ($i = 0, $l = count($tokens); $i < $l; $i++) - { - if (get_class($tokens[$i]) === "CssAtKeyframesStartToken") - { - for ($ii = $i; $ii < $l; $ii++) - { - if (get_class($tokens[$ii]) === "CssAtKeyframesEndToken") - { - break; - } - } - if (get_class($tokens[$ii]) === "CssAtKeyframesEndToken") - { - $add = array(); - $source = array(); - for ($iii = $i; $iii <= $ii; $iii++) - { - $source[] = clone($tokens[$iii]); - } - foreach ($transformations as $transformation) - { - $t = array(); - foreach ($source as $token) - { - $t[] = clone($token); - } - $t[0]->AtRuleName = $transformation; - $add = array_merge($add, $t); - } - if (isset($this->configuration["RemoveSource"]) && $this->configuration["RemoveSource"] === true) - { - array_splice($tokens, $i, $ii - $i + 1, $add); - } - else - { - array_splice($tokens, $ii + 1, 0, $add); - } - $l = count($tokens); - $i = $ii + count($add); - $r += count($add); - } - } - } - return $r; - } - } - -/** - * This {@link aCssMinifierPlugin} will convert a color value in hsl notation to hexadecimal notation. - * - * Example: - * - * color: hsl(232,36%,48%); - * - * - * Will get converted to: - * - * color:#4e5aa7; - * - * - * @package CssMin/Minifier/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssConvertHslColorsMinifierPlugin extends aCssMinifierPlugin - { - /** - * Regular expression matching the value. - * - * @var string - */ - private $reMatch = "/^hsl\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*%\s*,\s*([0-9]+)\s*%\s*\)/iS"; - /** - * Implements {@link aCssMinifierPlugin::minify()}. - * - * @param aCssToken $token Token to process - * @return boolean Return TRUE to break the processing of this token; FALSE to continue - */ - public function apply(aCssToken &$token) - { - if (stripos($token->Value, "hsl") !== false && preg_match($this->reMatch, $token->Value, $m)) - { - $token->Value = str_replace($m[0], $this->hsl2hex($m[1], $m[2], $m[3]), $token->Value); - } - return false; - } - /** - * Implements {@link aMinifierPlugin::getTriggerTokens()} - * - * @return array - */ - public function getTriggerTokens() - { - return array - ( - "CssAtFontFaceDeclarationToken", - "CssAtPageDeclarationToken", - "CssRulesetDeclarationToken" - ); - } - /** - * Convert a HSL value to hexadecimal notation. - * - * Based on: {@link http://www.easyrgb.com/index.php?X=MATH&H=19#text19}. - * - * @param integer $hue Hue - * @param integer $saturation Saturation - * @param integer $lightness Lightnesss - * @return string - */ - private function hsl2hex($hue, $saturation, $lightness) - { - $hue = $hue / 360; - $saturation = $saturation / 100; - $lightness = $lightness / 100; - if ($saturation == 0) - { - $red = $lightness * 255; - $green = $lightness * 255; - $blue = $lightness * 255; - } - else - { - if ($lightness < 0.5 ) - { - $v2 = $lightness * (1 + $saturation); - } - else - { - $v2 = ($lightness + $saturation) - ($saturation * $lightness); - } - $v1 = 2 * $lightness - $v2; - $red = 255 * self::hue2rgb($v1, $v2, $hue + (1 / 3)); - $green = 255 * self::hue2rgb($v1, $v2, $hue); - $blue = 255 * self::hue2rgb($v1, $v2, $hue - (1 / 3)); - } - return "#" . str_pad(dechex(round($red)), 2, "0", STR_PAD_LEFT) . str_pad(dechex(round($green)), 2, "0", STR_PAD_LEFT) . str_pad(dechex(round($blue)), 2, "0", STR_PAD_LEFT); - } - /** - * Apply hue to a rgb color value. - * - * @param integer $v1 Value 1 - * @param integer $v2 Value 2 - * @param integer $hue Hue - * @return integer - */ - private function hue2rgb($v1, $v2, $hue) - { - if ($hue < 0) - { - $hue += 1; - } - if ($hue > 1) - { - $hue -= 1; - } - if ((6 * $hue) < 1) - { - return ($v1 + ($v2 - $v1) * 6 * $hue); - } - if ((2 * $hue) < 1) - { - return ($v2); - } - if ((3 * $hue) < 2) - { - return ($v1 + ($v2 - $v1) * (( 2 / 3) - $hue) * 6); - } - return $v1; - } - } - -/** - * This {@link aCssMinifierPlugin} will convert the font-weight values normal and bold to their numeric notation. - * - * Example: - * - * font-weight: normal; - * font: bold 11px monospace; - * - * - * Will get converted to: - * - * font-weight:400; - * font:700 11px monospace; - * - * - * @package CssMin/Minifier/Pluginsn - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssConvertFontWeightMinifierPlugin extends aCssMinifierPlugin - { - /** - * Array of included declaration properties this plugin will process; others declaration properties will get - * ignored. - * - * @var array - */ - private $include = array - ( - "font", - "font-weight" - ); - /** - * Regular expression matching the value. - * - * @var string - */ - private $reMatch = null; - /** - * Regular expression replace the value. - * - * @var string - */ - private $reReplace = "\"\${1}\" . \$this->transformation[\"\${2}\"] . \"\${3}\""; - /** - * Transformation table used by the {@link CssConvertFontWeightMinifierPlugin::$reReplace replace regular expression}. - * - * @var array - */ - private $transformation = array - ( - "normal" => "400", - "bold" => "700" - ); - /** - * Overwrites {@link aCssMinifierPlugin::__construct()}. - * - * The constructor will create the {@link CssConvertFontWeightMinifierPlugin::$reReplace replace regular expression} - * based on the {@link CssConvertFontWeightMinifierPlugin::$transformation transformation table}. - * - * @param CssMinifier $minifier The CssMinifier object of this plugin. - * @return void - */ - public function __construct(CssMinifier $minifier) - { - $this->reMatch = "/(^|\s)+(" . implode("|", array_keys($this->transformation)). ")(\s|$)+/eiS"; - parent::__construct($minifier); - } - /** - * Implements {@link aCssMinifierPlugin::minify()}. - * - * @param aCssToken $token Token to process - * @return boolean Return TRUE to break the processing of this token; FALSE to continue - */ - public function apply(aCssToken &$token) - { - if (in_array($token->Property, $this->include) && preg_match($this->reMatch, $token->Value, $m)) - { - $token->Value = preg_replace($this->reMatch, $this->reReplace, $token->Value); - } - return false; - } - /** - * Implements {@link aMinifierPlugin::getTriggerTokens()} - * - * @return array - */ - public function getTriggerTokens() - { - return array - ( - "CssAtFontFaceDeclarationToken", - "CssAtPageDeclarationToken", - "CssRulesetDeclarationToken" - ); - } - } - -/** - * This {@link aCssMinifierPlugin} will compress several unit values to their short notations. Examples: - * - * - * padding: 0.5em; - * border: 0px; - * margin: 0 0 0 0; - * - * - * Will get compressed to: - * - * - * padding:.5px; - * border:0; - * margin:0; - * - * - * -- - * - * @package CssMin/Minifier/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssCompressUnitValuesMinifierPlugin extends aCssMinifierPlugin - { - /** - * Regular expression used for matching and replacing unit values. - * - * @var array - */ - private $re = array - ( - "/(^| |-)0\.([0-9]+?)(0+)?(%|em|ex|px|in|cm|mm|pt|pc)/iS" => "\${1}.\${2}\${4}", - "/(^| )-?(\.?)0(%|em|ex|px|in|cm|mm|pt|pc)/iS" => "\${1}0", - "/(^0\s0\s0\s0)|(^0\s0\s0$)|(^0\s0$)/iS" => "0" - ); - /** - * Regular expression matching the value. - * - * @var string - */ - private $reMatch = "/(^| |-)0\.([0-9]+?)(0+)?(%|em|ex|px|in|cm|mm|pt|pc)|(^| )-?(\.?)0(%|em|ex|px|in|cm|mm|pt|pc)|(^0\s0\s0\s0$)|(^0\s0\s0$)|(^0\s0$)/iS"; - /** - * Implements {@link aCssMinifierPlugin::minify()}. - * - * @param aCssToken $token Token to process - * @return boolean Return TRUE to break the processing of this token; FALSE to continue - */ - public function apply(aCssToken &$token) - { - if (preg_match($this->reMatch, $token->Value)) - { - foreach ($this->re as $reMatch => $reReplace) - { - $token->Value = preg_replace($reMatch, $reReplace, $token->Value); - } - } - return false; - } - /** - * Implements {@link aMinifierPlugin::getTriggerTokens()} - * - * @return array - */ - public function getTriggerTokens() - { - return array - ( - "CssAtFontFaceDeclarationToken", - "CssAtPageDeclarationToken", - "CssRulesetDeclarationToken" - ); - } - } - -/** - * This {@link aCssMinifierPlugin} compress the content of expresssion() declaration values. - * - * For compression of expressions {@link https://github.com/rgrove/jsmin-php/ JSMin} will get used. JSMin have to be - * already included or loadable via {@link http://goo.gl/JrW54 PHP autoloading}. - * - * @package CssMin/Minifier/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssCompressExpressionValuesMinifierPlugin extends aCssMinifierPlugin - { - /** - * Implements {@link aCssMinifierPlugin::minify()}. - * - * @param aCssToken $token Token to process - * @return boolean Return TRUE to break the processing of this token; FALSE to continue - */ - public function apply(aCssToken &$token) - { - if (class_exists("JSMin") && stripos($token->Value, "expression(") !== false) - { - $value = $token->Value; - $value = substr($token->Value, stripos($token->Value, "expression(") + 10); - $value = trim(JSMin::minify($value)); - $token->Value = "expression(" . $value . ")"; - } - return false; - } - /** - * Implements {@link aMinifierPlugin::getTriggerTokens()} - * - * @return array - */ - public function getTriggerTokens() - { - return array - ( - "CssAtFontFaceDeclarationToken", - "CssAtPageDeclarationToken", - "CssRulesetDeclarationToken" - ); - } - } - -/** - * This {@link aCssMinifierPlugin} will convert hexadecimal color value with 6 chars to their 3 char hexadecimal - * notation (if possible). - * - * Example: - * - * color: #aabbcc; - * - * - * Will get converted to: - * - * color:#abc; - * - * - * @package CssMin/Minifier/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssCompressColorValuesMinifierPlugin extends aCssMinifierPlugin - { - /** - * Regular expression matching 6 char hexadecimal color values. - * - * @var string - */ - private $reMatch = "/\#([0-9a-f]{6})/iS"; - /** - * Implements {@link aCssMinifierPlugin::minify()}. - * - * @param aCssToken $token Token to process - * @return boolean Return TRUE to break the processing of this token; FALSE to continue - */ - public function apply(aCssToken &$token) - { - if (strpos($token->Value, "#") !== false && preg_match($this->reMatch, $token->Value, $m)) - { - $value = strtolower($m[1]); - if ($value[0] == $value[1] && $value[2] == $value[3] && $value[4] == $value[5]) - { - $token->Value = str_replace($m[0], "#" . $value[0] . $value[2] . $value[4], $token->Value); - } - } - return false; - } - /** - * Implements {@link aMinifierPlugin::getTriggerTokens()} - * - * @return array - */ - public function getTriggerTokens() - { - return array - ( - "CssAtFontFaceDeclarationToken", - "CssAtPageDeclarationToken", - "CssRulesetDeclarationToken" - ); - } - } - -/** - * This {@link aCssToken CSS token} represents a CSS comment. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssCommentToken extends aCssToken - { - /** - * Comment as Text. - * - * @var string - */ - public $Comment = ""; - /** - * Set the properties of a comment token. - * - * @param string $comment Comment including comment delimiters - * @return void - */ - public function __construct($comment) - { - $this->Comment = $comment; - } - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return $this->Comment; - } - } - -/** - * {@link aCssParserPlugin Parser plugin} for parsing comments. - * - * Adds a {@link CssCommentToken} to the parser if a comment was found. - * - * @package CssMin/Parser/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssCommentParserPlugin extends aCssParserPlugin - { - /** - * Implements {@link aCssParserPlugin::getTriggerChars()}. - * - * @return array - */ - public function getTriggerChars() - { - return array("*", "/"); - } - /** - * Implements {@link aCssParserPlugin::getTriggerStates()}. - * - * @return array - */ - public function getTriggerStates() - { - return false; - } - /** - * Stored buffer for restore. - * - * @var string - */ - private $restoreBuffer = ""; - /** - * Implements {@link aCssParserPlugin::parse()}. - * - * @param integer $index Current index - * @param string $char Current char - * @param string $previousChar Previous char - * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing - */ - public function parse($index, $char, $previousChar, $state) - { - if ($char === "*" && $previousChar === "/" && $state !== "T_COMMENT") - { - $this->parser->pushState("T_COMMENT"); - $this->parser->setExclusive(__CLASS__); - $this->restoreBuffer = substr($this->parser->getAndClearBuffer(), 0, -2); - } - elseif ($char === "/" && $previousChar === "*" && $state === "T_COMMENT") - { - $this->parser->popState(); - $this->parser->unsetExclusive(); - $this->parser->appendToken(new CssCommentToken("/*" . $this->parser->getAndClearBuffer())); - $this->parser->setBuffer($this->restoreBuffer); - } - else - { - return false; - } - return true; - } - } - -/** - * This {@link aCssToken CSS token} represents the start of a @variables at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtVariablesStartToken extends aCssAtBlockStartToken - { - /** - * Media types of the @variables at-rule block. - * - * @var array - */ - public $MediaTypes = array(); - /** - * Set the properties of a @variables at-rule token. - * - * @param array $mediaTypes Media types - * @return void - */ - public function __construct($mediaTypes = null) - { - $this->MediaTypes = $mediaTypes ? $mediaTypes : array("all"); - } - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return ""; - } - } - -/** - * {@link aCssParserPlugin Parser plugin} for parsing @variables at-rule block with including declarations. - * - * Found @variables at-rule blocks will add a {@link CssAtVariablesStartToken} and {@link CssAtVariablesEndToken} to the - * parser; including declarations as {@link CssAtVariablesDeclarationToken}. - * - * @package CssMin/Parser/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtVariablesParserPlugin extends aCssParserPlugin - { - /** - * Implements {@link aCssParserPlugin::getTriggerChars()}. - * - * @return array - */ - public function getTriggerChars() - { - return array("@", "{", "}", ":", ";"); - } - /** - * Implements {@link aCssParserPlugin::getTriggerStates()}. - * - * @return array - */ - public function getTriggerStates() - { - return array("T_DOCUMENT", "T_AT_VARIABLES::PREPARE", "T_AT_VARIABLES", "T_AT_VARIABLES_DECLARATION"); - } - /** - * Implements {@link aCssParserPlugin::parse()}. - * - * @param integer $index Current index - * @param string $char Current char - * @param string $previousChar Previous char - * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing - */ - public function parse($index, $char, $previousChar, $state) - { - // Start of @variables at-rule block - if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 10)) === "@variables") - { - $this->parser->pushState("T_AT_VARIABLES::PREPARE"); - $this->parser->clearBuffer(); - return $index + 10; - } - // Start of @variables declarations - elseif ($char === "{" && $state === "T_AT_VARIABLES::PREPARE") - { - $this->parser->setState("T_AT_VARIABLES"); - $mediaTypes = array_filter(array_map("trim", explode(",", $this->parser->getAndClearBuffer("{")))); - $this->parser->appendToken(new CssAtVariablesStartToken($mediaTypes)); - } - // Start of @variables declaration - if ($char === ":" && $state === "T_AT_VARIABLES") - { - $this->buffer = $this->parser->getAndClearBuffer(":"); - $this->parser->pushState("T_AT_VARIABLES_DECLARATION"); - } - // Unterminated @variables declaration - elseif ($char === ":" && $state === "T_AT_VARIABLES_DECLARATION") - { - // Ignore Internet Explorer filter declarations - if ($this->buffer === "filter") - { - return false; - } - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @variables declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_")); - } - // End of @variables declaration - elseif (($char === ";" || $char === "}") && $state === "T_AT_VARIABLES_DECLARATION") - { - $value = $this->parser->getAndClearBuffer(";}"); - if (strtolower(substr($value, -10, 10)) === "!important") - { - $value = trim(substr($value, 0, -10)); - $isImportant = true; - } - else - { - $isImportant = false; - } - $this->parser->popState(); - $this->parser->appendToken(new CssAtVariablesDeclarationToken($this->buffer, $value, $isImportant)); - $this->buffer = ""; - } - // End of @variables at-rule block - elseif ($char === "}" && $state === "T_AT_VARIABLES") - { - $this->parser->popState(); - $this->parser->clearBuffer(); - $this->parser->appendToken(new CssAtVariablesEndToken()); - } - else - { - return false; - } - return true; - } - } - -/** - * This {@link aCssToken CSS token} represents the end of a @variables at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtVariablesEndToken extends aCssAtBlockEndToken - { - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return ""; - } - } - -/** - * This {@link aCssToken CSS token} represents a declaration of a @variables at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtVariablesDeclarationToken extends aCssDeclarationToken - { - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return ""; - } - } - -/** -* This {@link aCssToken CSS token} represents the start of a @page at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtPageStartToken extends aCssAtBlockStartToken - { - /** - * Selector. - * - * @var string - */ - public $Selector = ""; - /** - * Sets the properties of the @page at-rule. - * - * @param string $selector Selector - * @return void - */ - public function __construct($selector = "") - { - $this->Selector = $selector; - } - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return "@page" . ($this->Selector ? " " . $this->Selector : "") . "{"; - } - } - -/** - * {@link aCssParserPlugin Parser plugin} for parsing @page at-rule block with including declarations. - * - * Found @page at-rule blocks will add a {@link CssAtPageStartToken} and {@link CssAtPageEndToken} to the - * parser; including declarations as {@link CssAtPageDeclarationToken}. - * - * @package CssMin/Parser/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtPageParserPlugin extends aCssParserPlugin - { - /** - * Implements {@link aCssParserPlugin::getTriggerChars()}. - * - * @return array - */ - public function getTriggerChars() - { - return array("@", "{", "}", ":", ";"); - } - /** - * Implements {@link aCssParserPlugin::getTriggerStates()}. - * - * @return array - */ - public function getTriggerStates() - { - return array("T_DOCUMENT", "T_AT_PAGE::SELECTOR", "T_AT_PAGE", "T_AT_PAGE_DECLARATION"); - } - /** - * Implements {@link aCssParserPlugin::parse()}. - * - * @param integer $index Current index - * @param string $char Current char - * @param string $previousChar Previous char - * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing - */ - public function parse($index, $char, $previousChar, $state) - { - // Start of @page at-rule block - if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 5)) === "@page") - { - $this->parser->pushState("T_AT_PAGE::SELECTOR"); - $this->parser->clearBuffer(); - return $index + 5; - } - // Start of @page declarations - elseif ($char === "{" && $state === "T_AT_PAGE::SELECTOR") - { - $selector = $this->parser->getAndClearBuffer("{"); - $this->parser->setState("T_AT_PAGE"); - $this->parser->clearBuffer(); - $this->parser->appendToken(new CssAtPageStartToken($selector)); - } - // Start of @page declaration - elseif ($char === ":" && $state === "T_AT_PAGE") - { - $this->parser->pushState("T_AT_PAGE_DECLARATION"); - $this->buffer = $this->parser->getAndClearBuffer(":", true); - } - // Unterminated @font-face declaration - elseif ($char === ":" && $state === "T_AT_PAGE_DECLARATION") - { - // Ignore Internet Explorer filter declarations - if ($this->buffer === "filter") - { - return false; - } - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @page declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_")); - } - // End of @page declaration - elseif (($char === ";" || $char === "}") && $state == "T_AT_PAGE_DECLARATION") - { - $value = $this->parser->getAndClearBuffer(";}"); - if (strtolower(substr($value, -10, 10)) == "!important") - { - $value = trim(substr($value, 0, -10)); - $isImportant = true; - } - else - { - $isImportant = false; - } - $this->parser->popState(); - $this->parser->appendToken(new CssAtPageDeclarationToken($this->buffer, $value, $isImportant)); - // -- - if ($char === "}") - { - $this->parser->popState(); - $this->parser->appendToken(new CssAtPageEndToken()); - } - $this->buffer = ""; - } - // End of @page at-rule block - elseif ($char === "}" && $state === "T_AT_PAGE") - { - $this->parser->popState(); - $this->parser->clearBuffer(); - $this->parser->appendToken(new CssAtPageEndToken()); - } - else - { - return false; - } - return true; - } - } - -/** - * This {@link aCssToken CSS token} represents the end of a @page at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtPageEndToken extends aCssAtBlockEndToken - { - - } - -/** - * This {@link aCssToken CSS token} represents a declaration of a @page at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtPageDeclarationToken extends aCssDeclarationToken - { - - } - -/** - * This {@link aCssToken CSS token} represents the start of a @media at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtMediaStartToken extends aCssAtBlockStartToken - { - /** - * Sets the properties of the @media at-rule. - * - * @param array $mediaTypes Media types - * @return void - */ - public function __construct(array $mediaTypes = array()) - { - $this->MediaTypes = $mediaTypes; - } - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return "@media " . implode(",", $this->MediaTypes) . "{"; - } - } - -/** - * {@link aCssParserPlugin Parser plugin} for parsing @media at-rule block. - * - * Found @media at-rule blocks will add a {@link CssAtMediaStartToken} and {@link CssAtMediaEndToken} to the parser. - * This plugin will also set the the current media types using {@link CssParser::setMediaTypes()} and - * {@link CssParser::unsetMediaTypes()}. - * - * @package CssMin/Parser/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtMediaParserPlugin extends aCssParserPlugin - { - /** - * Implements {@link aCssParserPlugin::getTriggerChars()}. - * - * @return array - */ - public function getTriggerChars() - { - return array("@", "{", "}"); - } - /** - * Implements {@link aCssParserPlugin::getTriggerStates()}. - * - * @return array - */ - public function getTriggerStates() - { - return array("T_DOCUMENT", "T_AT_MEDIA::PREPARE", "T_AT_MEDIA"); - } - /** - * Implements {@link aCssParserPlugin::parse()}. - * - * @param integer $index Current index - * @param string $char Current char - * @param string $previousChar Previous char - * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing - */ - public function parse($index, $char, $previousChar, $state) - { - if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 6)) === "@media") - { - $this->parser->pushState("T_AT_MEDIA::PREPARE"); - $this->parser->clearBuffer(); - return $index + 6; - } - elseif ($char === "{" && $state === "T_AT_MEDIA::PREPARE") - { - $mediaTypes = array_filter(array_map("trim", explode(",", $this->parser->getAndClearBuffer("{")))); - $this->parser->setMediaTypes($mediaTypes); - $this->parser->setState("T_AT_MEDIA"); - $this->parser->appendToken(new CssAtMediaStartToken($mediaTypes)); - } - elseif ($char === "}" && $state === "T_AT_MEDIA") - { - $this->parser->appendToken(new CssAtMediaEndToken()); - $this->parser->clearBuffer(); - $this->parser->unsetMediaTypes(); - $this->parser->popState(); - } - else - { - return false; - } - return true; - } - } - -/** - * This {@link aCssToken CSS token} represents the end of a @media at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtMediaEndToken extends aCssAtBlockEndToken - { - - } - -/** - * This {@link aCssToken CSS token} represents the start of a @keyframes at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtKeyframesStartToken extends aCssAtBlockStartToken - { - /** - * Name of the at-rule. - * - * @var string - */ - public $AtRuleName = "keyframes"; - /** - * Name - * - * @var string - */ - public $Name = ""; - /** - * Sets the properties of the @page at-rule. - * - * @param string $selector Selector - * @return void - */ - public function __construct($name, $atRuleName = null) - { - $this->Name = $name; - if (!is_null($atRuleName)) - { - $this->AtRuleName = $atRuleName; - } - } - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return "@" . $this->AtRuleName . " \"" . $this->Name . "\"{"; - } - } - -/** - * This {@link aCssToken CSS token} represents the start of a ruleset of a @keyframes at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtKeyframesRulesetStartToken extends aCssRulesetStartToken - { - /** - * Array of selectors. - * - * @var array - */ - public $Selectors = array(); - /** - * Set the properties of a ruleset token. - * - * @param array $selectors Selectors of the ruleset - * @return void - */ - public function __construct(array $selectors = array()) - { - $this->Selectors = $selectors; - } - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return implode(",", $this->Selectors) . "{"; - } - } - -/** - * This {@link aCssToken CSS token} represents the end of a ruleset of a @keyframes at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtKeyframesRulesetEndToken extends aCssRulesetEndToken - { - - } - -/** - * This {@link aCssToken CSS token} represents a ruleset declaration of a @keyframes at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtKeyframesRulesetDeclarationToken extends aCssDeclarationToken - { - - } - -/** - * {@link aCssParserPlugin Parser plugin} for parsing @keyframes at-rule blocks, rulesets and declarations. - * - * @package CssMin/Parser/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtKeyframesParserPlugin extends aCssParserPlugin - { - /** - * @var string Keyword - */ - private $atRuleName = ""; - /** - * Selectors. - * - * @var array - */ - private $selectors = array(); - /** - * Implements {@link aCssParserPlugin::getTriggerChars()}. - * - * @return array - */ - public function getTriggerChars() - { - return array("@", "{", "}", ":", ",", ";"); - } - /** - * Implements {@link aCssParserPlugin::getTriggerStates()}. - * - * @return array - */ - public function getTriggerStates() - { - return array("T_DOCUMENT", "T_AT_KEYFRAMES::NAME", "T_AT_KEYFRAMES", "T_AT_KEYFRAMES_RULESETS", "T_AT_KEYFRAMES_RULESET", "T_AT_KEYFRAMES_RULESET_DECLARATION"); - } - /** - * Implements {@link aCssParserPlugin::parse()}. - * - * @param integer $index Current index - * @param string $char Current char - * @param string $previousChar Previous char - * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing - */ - public function parse($index, $char, $previousChar, $state) - { - // Start of @keyframes at-rule block - if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 10)) === "@keyframes") - { - $this->atRuleName = "keyframes"; - $this->parser->pushState("T_AT_KEYFRAMES::NAME"); - $this->parser->clearBuffer(); - return $index + 10; - } - // Start of @keyframes at-rule block (@-moz-keyframes) - elseif ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 15)) === "@-moz-keyframes") - { - $this->atRuleName = "-moz-keyframes"; - $this->parser->pushState("T_AT_KEYFRAMES::NAME"); - $this->parser->clearBuffer(); - return $index + 15; - } - // Start of @keyframes at-rule block (@-webkit-keyframes) - elseif ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 18)) === "@-webkit-keyframes") - { - $this->atRuleName = "-webkit-keyframes"; - $this->parser->pushState("T_AT_KEYFRAMES::NAME"); - $this->parser->clearBuffer(); - return $index + 18; - } - // Start of @keyframes rulesets - elseif ($char === "{" && $state === "T_AT_KEYFRAMES::NAME") - { - $name = $this->parser->getAndClearBuffer("{\"'"); - $this->parser->setState("T_AT_KEYFRAMES_RULESETS"); - $this->parser->clearBuffer(); - $this->parser->appendToken(new CssAtKeyframesStartToken($name, $this->atRuleName)); - } - // Start of @keyframe ruleset and selectors - if ($char === "," && $state === "T_AT_KEYFRAMES_RULESETS") - { - $this->selectors[] = $this->parser->getAndClearBuffer(",{"); - } - // Start of a @keyframes ruleset - elseif ($char === "{" && $state === "T_AT_KEYFRAMES_RULESETS") - { - if ($this->parser->getBuffer() !== "") - { - $this->selectors[] = $this->parser->getAndClearBuffer(",{"); - $this->parser->pushState("T_AT_KEYFRAMES_RULESET"); - $this->parser->appendToken(new CssAtKeyframesRulesetStartToken($this->selectors)); - $this->selectors = array(); - } - } - // Start of @keyframes ruleset declaration - elseif ($char === ":" && $state === "T_AT_KEYFRAMES_RULESET") - { - $this->parser->pushState("T_AT_KEYFRAMES_RULESET_DECLARATION"); - $this->buffer = $this->parser->getAndClearBuffer(":;", true); - } - // Unterminated @keyframes ruleset declaration - elseif ($char === ":" && $state === "T_AT_KEYFRAMES_RULESET_DECLARATION") - { - // Ignore Internet Explorer filter declarations - if ($this->buffer === "filter") - { - return false; - } - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @keyframes ruleset declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_")); - } - // End of declaration - elseif (($char === ";" || $char === "}") && $state === "T_AT_KEYFRAMES_RULESET_DECLARATION") - { - $value = $this->parser->getAndClearBuffer(";}"); - if (strtolower(substr($value, -10, 10)) === "!important") - { - $value = trim(substr($value, 0, -10)); - $isImportant = true; - } - else - { - $isImportant = false; - } - $this->parser->popState(); - $this->parser->appendToken(new CssAtKeyframesRulesetDeclarationToken($this->buffer, $value, $isImportant)); - // Declaration ends with a right curly brace; so we have to end the ruleset - if ($char === "}") - { - $this->parser->appendToken(new CssAtKeyframesRulesetEndToken()); - $this->parser->popState(); - } - $this->buffer = ""; - } - // End of @keyframes ruleset - elseif ($char === "}" && $state === "T_AT_KEYFRAMES_RULESET") - { - $this->parser->clearBuffer(); - - $this->parser->popState(); - $this->parser->appendToken(new CssAtKeyframesRulesetEndToken()); - } - // End of @keyframes rulesets - elseif ($char === "}" && $state === "T_AT_KEYFRAMES_RULESETS") - { - $this->parser->clearBuffer(); - $this->parser->popState(); - $this->parser->appendToken(new CssAtKeyframesEndToken()); - } - else - { - return false; - } - return true; - } - } - -/** - * This {@link aCssToken CSS token} represents the end of a @keyframes at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtKeyframesEndToken extends aCssAtBlockEndToken - { - - } - -/** - * This {@link aCssToken CSS token} represents a @import at-rule. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1.b1 (2001-02-22) - */ -class CssAtImportToken extends aCssToken - { - /** - * Import path of the @import at-rule. - * - * @var string - */ - public $Import = ""; - /** - * Media types of the @import at-rule. - * - * @var array - */ - public $MediaTypes = array(); - /** - * Set the properties of a @import at-rule token. - * - * @param string $import Import path - * @param array $mediaTypes Media types - * @return void - */ - public function __construct($import, $mediaTypes) - { - $this->Import = $import; - $this->MediaTypes = $mediaTypes ? $mediaTypes : array(); - } - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return "@import \"" . $this->Import . "\"" . (count($this->MediaTypes) > 0 ? " " . implode(",", $this->MediaTypes) : ""). ";"; - } - } - -/** - * {@link aCssParserPlugin Parser plugin} for parsing @import at-rule. - * - * If a @import at-rule was found this plugin will add a {@link CssAtImportToken} to the parser. - * - * @package CssMin/Parser/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtImportParserPlugin extends aCssParserPlugin - { - /** - * Implements {@link aCssParserPlugin::getTriggerChars()}. - * - * @return array - */ - public function getTriggerChars() - { - return array("@", ";", ",", "\n"); - } - /** - * Implements {@link aCssParserPlugin::getTriggerStates()}. - * - * @return array - */ - public function getTriggerStates() - { - return array("T_DOCUMENT", "T_AT_IMPORT"); - } - /** - * Implements {@link aCssParserPlugin::parse()}. - * - * @param integer $index Current index - * @param string $char Current char - * @param string $previousChar Previous char - * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing - */ - public function parse($index, $char, $previousChar, $state) - { - if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 7)) === "@import") - { - $this->parser->pushState("T_AT_IMPORT"); - $this->parser->clearBuffer(); - return $index + 7; - } - elseif (($char === ";" || $char === "\n") && $state === "T_AT_IMPORT") - { - $this->buffer = $this->parser->getAndClearBuffer(";"); - $pos = false; - foreach (array(")", "\"", "'") as $needle) - { - if (($pos = strrpos($this->buffer, $needle)) !== false) - { - break; - } - } - $import = substr($this->buffer, 0, $pos + 1); - if (stripos($import, "url(") === 0) - { - $import = substr($import, 4, -1); - } - $import = trim($import, " \t\n\r\0\x0B'\""); - $mediaTypes = array_filter(array_map("trim", explode(",", trim(substr($this->buffer, $pos + 1), " \t\n\r\0\x0B{")))); - if ($pos) - { - $this->parser->appendToken(new CssAtImportToken($import, $mediaTypes)); - } - else - { - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Invalid @import at-rule syntax", $this->parser->buffer)); - } - $this->parser->popState(); - } - else - { - return false; - } - return true; - } - } - -/** - * This {@link aCssToken CSS token} represents the start of a @font-face at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtFontFaceStartToken extends aCssAtBlockStartToken - { - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return "@font-face{"; - } - } - -/** - * {@link aCssParserPlugin Parser plugin} for parsing @font-face at-rule block with including declarations. - * - * Found @font-face at-rule blocks will add a {@link CssAtFontFaceStartToken} and {@link CssAtFontFaceEndToken} to the - * parser; including declarations as {@link CssAtFontFaceDeclarationToken}. - * - * @package CssMin/Parser/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtFontFaceParserPlugin extends aCssParserPlugin - { - /** - * Implements {@link aCssParserPlugin::getTriggerChars()}. - * - * @return array - */ - public function getTriggerChars() - { - return array("@", "{", "}", ":", ";"); - } - /** - * Implements {@link aCssParserPlugin::getTriggerStates()}. - * - * @return array - */ - public function getTriggerStates() - { - return array("T_DOCUMENT", "T_AT_FONT_FACE::PREPARE", "T_AT_FONT_FACE", "T_AT_FONT_FACE_DECLARATION"); - } - /** - * Implements {@link aCssParserPlugin::parse()}. - * - * @param integer $index Current index - * @param string $char Current char - * @param string $previousChar Previous char - * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing - */ - public function parse($index, $char, $previousChar, $state) - { - // Start of @font-face at-rule block - if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 10)) === "@font-face") - { - $this->parser->pushState("T_AT_FONT_FACE::PREPARE"); - $this->parser->clearBuffer(); - return $index + 10; - } - // Start of @font-face declarations - elseif ($char === "{" && $state === "T_AT_FONT_FACE::PREPARE") - { - $this->parser->setState("T_AT_FONT_FACE"); - $this->parser->clearBuffer(); - $this->parser->appendToken(new CssAtFontFaceStartToken()); - } - // Start of @font-face declaration - elseif ($char === ":" && $state === "T_AT_FONT_FACE") - { - $this->parser->pushState("T_AT_FONT_FACE_DECLARATION"); - $this->buffer = $this->parser->getAndClearBuffer(":", true); - } - // Unterminated @font-face declaration - elseif ($char === ":" && $state === "T_AT_FONT_FACE_DECLARATION") - { - // Ignore Internet Explorer filter declarations - if ($this->buffer === "filter") - { - return false; - } - CssMin::triggerError(new CssError(__FILE__, __LINE__, __METHOD__ . ": Unterminated @font-face declaration", $this->buffer . ":" . $this->parser->getBuffer() . "_")); - } - // End of @font-face declaration - elseif (($char === ";" || $char === "}") && $state === "T_AT_FONT_FACE_DECLARATION") - { - $value = $this->parser->getAndClearBuffer(";}"); - if (strtolower(substr($value, -10, 10)) === "!important") - { - $value = trim(substr($value, 0, -10)); - $isImportant = true; - } - else - { - $isImportant = false; - } - $this->parser->popState(); - $this->parser->appendToken(new CssAtFontFaceDeclarationToken($this->buffer, $value, $isImportant)); - $this->buffer = ""; - // -- - if ($char === "}") - { - $this->parser->appendToken(new CssAtFontFaceEndToken()); - $this->parser->popState(); - } - } - // End of @font-face at-rule block - elseif ($char === "}" && $state === "T_AT_FONT_FACE") - { - $this->parser->appendToken(new CssAtFontFaceEndToken()); - $this->parser->clearBuffer(); - $this->parser->popState(); - } - else - { - return false; - } - return true; - } - } - -/** - * This {@link aCssToken CSS token} represents the end of a @font-face at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtFontFaceEndToken extends aCssAtBlockEndToken - { - - } - -/** - * This {@link aCssToken CSS token} represents a declaration of a @font-face at-rule block. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtFontFaceDeclarationToken extends aCssDeclarationToken - { - - } - -/** - * This {@link aCssToken CSS token} represents a @charset at-rule. - * - * @package CssMin/Tokens - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtCharsetToken extends aCssToken - { - /** - * Charset of the @charset at-rule. - * - * @var string - */ - public $Charset = ""; - /** - * Set the properties of @charset at-rule token. - * - * @param string $charset Charset of the @charset at-rule token - * @return void - */ - public function __construct($charset) - { - $this->Charset = $charset; - } - /** - * Implements {@link aCssToken::__toString()}. - * - * @return string - */ - public function __toString() - { - return "@charset " . $this->Charset . ";"; - } - } - -/** - * {@link aCssParserPlugin Parser plugin} for parsing @charset at-rule. - * - * If a @charset at-rule was found this plugin will add a {@link CssAtCharsetToken} to the parser. - * - * @package CssMin/Parser/Plugins - * @link http://code.google.com/p/cssmin/ - * @author Joe Scylla - * @copyright 2008 - 2011 Joe Scylla - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 3.0.1 - */ -class CssAtCharsetParserPlugin extends aCssParserPlugin - { - /** - * Implements {@link aCssParserPlugin::getTriggerChars()}. - * - * @return array - */ - public function getTriggerChars() - { - return array("@", ";", "\n"); - } - /** - * Implements {@link aCssParserPlugin::getTriggerStates()}. - * - * @return array - */ - public function getTriggerStates() - { - return array("T_DOCUMENT", "T_AT_CHARSET"); - } - /** - * Implements {@link aCssParserPlugin::parse()}. - * - * @param integer $index Current index - * @param string $char Current char - * @param string $previousChar Previous char - * @return mixed TRUE will break the processing; FALSE continue with the next plugin; integer set a new index and break the processing - */ - public function parse($index, $char, $previousChar, $state) - { - if ($char === "@" && $state === "T_DOCUMENT" && strtolower(substr($this->parser->getSource(), $index, 8)) === "@charset") - { - $this->parser->pushState("T_AT_CHARSET"); - $this->parser->clearBuffer(); - return $index + 8; - } - elseif (($char === ";" || $char === "\n") && $state === "T_AT_CHARSET") - { - $charset = $this->parser->getAndClearBuffer(";"); - $this->parser->popState(); - $this->parser->appendToken(new CssAtCharsetToken($charset)); - } - else - { - return false; - } - return true; - } - } diff --git a/application/extensions/ExtendedClientScript/jsmin/JSMin.php b/application/extensions/ExtendedClientScript/jsmin/JSMin.php deleted file mode 100644 index 9a312640e8a..00000000000 --- a/application/extensions/ExtendedClientScript/jsmin/JSMin.php +++ /dev/null @@ -1,374 +0,0 @@ - - * @copyright 2002 Douglas Crockford (jsmin.c) - * @copyright 2008 Ryan Grove (PHP port) - * @license http://opensource.org/licenses/mit-license.php MIT License - * @version 1.1.1 (2008-03-02) - * @link https://github.com/rgrove/jsmin-php/ - */ - -class JSMin { - const ORD_LF = 10; - const ORD_SPACE = 32; - const ACTION_KEEP_A = 1; - const ACTION_DELETE_A = 2; - const ACTION_DELETE_A_B= 3; - - protected $a = ''; - protected $b = ''; - protected $input = ''; - protected $inputIndex = 0; - protected $inputLength = 0; - protected $lookAhead = null; - protected $output = ''; - - // -- Public Static Methods -------------------------------------------------- - - /** - * Minify Javascript - * - * @uses __construct() - * @uses min() - * @param string $js Javascript to be minified - * @return string - */ - public static function minify($js) { - $jsmin = new JSMin($js); - return $jsmin->min(); - } - - // -- Public Instance Methods ------------------------------------------------ - - /** - * Constructor - * - * @param string $input Javascript to be minified - */ - public function __construct($input) { - $this->input = str_replace("\r\n", "\n", $input); - $this->inputLength = strlen($this->input); - } - - // -- Protected Instance Methods --------------------------------------------- - - /** - * Action -- do something! What to do is determined by the $command argument. - * - * action treats a string as a single character. Wow! - * action recognizes a regular expression if it is preceded by ( or , or =. - * - * @uses next() - * @uses get() - * @throws JSMinException If parser errors are found: - * - Unterminated string literal - * - Unterminated regular expression set in regex literal - * - Unterminated regular expression literal - * @param int $command One of class constants: - * ACTION_KEEP_A Output A. Copy B to A. Get the next B. - * ACTION_DELETE_A Copy B to A. Get the next B. (Delete A). - * ACTION_DELETE_A_B Get the next B. (Delete B). - */ - protected function action($command) { - switch($command) { - case self::ACTION_KEEP_A: - $this->output .= $this->a; - - case self::ACTION_DELETE_A: - $this->a = $this->b; - - if ($this->a === "'" || $this->a === '"') { - for (;;) { - $this->output .= $this->a; - $this->a = $this->get(); - - if ($this->a === $this->b) { - break; - } - - if (ord($this->a) <= self::ORD_LF) { - throw new JSMinException('Unterminated string literal.'); - } - - if ($this->a === '\\') { - $this->output .= $this->a; - $this->a = $this->get(); - } - } - } - - case self::ACTION_DELETE_A_B: - $this->b = $this->next(); - - if ($this->b === '/' && ( - $this->a === '(' || $this->a === ',' || $this->a === '=' || - $this->a === ':' || $this->a === '[' || $this->a === '!' || - $this->a === '&' || $this->a === '|' || $this->a === '?' || - $this->a === '{' || $this->a === '}' || $this->a === ';' || - $this->a === "\n" )) { - - $this->output .= $this->a . $this->b; - - for (;;) { - $this->a = $this->get(); - - if ($this->a === '[') { - /* - inside a regex [...] set, which MAY contain a '/' itself. Example: mootools Form.Validator near line 460: - return Form.Validator.getValidator('IsEmpty').test(element) || (/^(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]\.?){0,63}[a-z0-9!#$%&'*+/=?^_`{|}~-]@(?:(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)*[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\])$/i).test(element.get('value')); - */ - for (;;) { - $this->output .= $this->a; - $this->a = $this->get(); - - if ($this->a === ']') { - break; - } elseif ($this->a === '\\') { - $this->output .= $this->a; - $this->a = $this->get(); - } elseif (ord($this->a) <= self::ORD_LF) { - throw new JSMinException('Unterminated regular expression set in regex literal.'); - } - } - } elseif ($this->a === '/') { - break; - } elseif ($this->a === '\\') { - $this->output .= $this->a; - $this->a = $this->get(); - } elseif (ord($this->a) <= self::ORD_LF) { - throw new JSMinException('Unterminated regular expression literal.'); - } - - $this->output .= $this->a; - } - - $this->b = $this->next(); - } - } - } - - /** - * Get next char. Convert ctrl char to space. - * - * @return string|null - */ - protected function get() { - $c = $this->lookAhead; - $this->lookAhead = null; - - if ($c === null) { - if ($this->inputIndex < $this->inputLength) { - $c = substr($this->input, $this->inputIndex, 1); - $this->inputIndex += 1; - } else { - $c = null; - } - } - - if ($c === "\r") { - return "\n"; - } - - if ($c === null || $c === "\n" || ord($c) >= self::ORD_SPACE) { - return $c; - } - - return ' '; - } - - /** - * Is $c a letter, digit, underscore, dollar sign, or non-ASCII character. - * - * @return bool - */ - protected function isAlphaNum($c) { - return ord($c) > 126 || $c === '\\' || preg_match('/^[\w\$]$/', $c) === 1; - } - - /** - * Perform minification, return result - * - * @uses action() - * @uses isAlphaNum() - * @return string - */ - protected function min() { - $this->a = "\n"; - $this->action(self::ACTION_DELETE_A_B); - - while ($this->a !== null) { - switch ($this->a) { - case ' ': - if ($this->isAlphaNum($this->b)) { - $this->action(self::ACTION_KEEP_A); - } else { - $this->action(self::ACTION_DELETE_A); - } - break; - - case "\n": - switch ($this->b) { - case '{': - case '[': - case '(': - case '+': - case '-': - $this->action(self::ACTION_KEEP_A); - break; - - case ' ': - $this->action(self::ACTION_DELETE_A_B); - break; - - default: - if ($this->isAlphaNum($this->b)) { - $this->action(self::ACTION_KEEP_A); - } - else { - $this->action(self::ACTION_DELETE_A); - } - } - break; - - default: - switch ($this->b) { - case ' ': - if ($this->isAlphaNum($this->a)) { - $this->action(self::ACTION_KEEP_A); - break; - } - - $this->action(self::ACTION_DELETE_A_B); - break; - - case "\n": - switch ($this->a) { - case '}': - case ']': - case ')': - case '+': - case '-': - case '"': - case "'": - $this->action(self::ACTION_KEEP_A); - break; - - default: - if ($this->isAlphaNum($this->a)) { - $this->action(self::ACTION_KEEP_A); - } - else { - $this->action(self::ACTION_DELETE_A_B); - } - } - break; - - default: - $this->action(self::ACTION_KEEP_A); - break; - } - } - } - - return $this->output; - } - - /** - * Get the next character, skipping over comments. peek() is used to see - * if a '/' is followed by a '/' or '*'. - * - * @uses get() - * @uses peek() - * @throws JSMinException On unterminated comment. - * @return string - */ - protected function next() { - $c = $this->get(); - - if ($c === '/') { - switch($this->peek()) { - case '/': - for (;;) { - $c = $this->get(); - - if (ord($c) <= self::ORD_LF) { - return $c; - } - } - - case '*': - $this->get(); - - for (;;) { - switch($this->get()) { - case '*': - if ($this->peek() === '/') { - $this->get(); - return ' '; - } - break; - - case null: - throw new JSMinException('Unterminated comment.'); - } - } - - default: - return $c; - } - } - - return $c; - } - - /** - * Get next char. If is ctrl character, translate to a space or newline. - * - * @uses get() - * @return string|null - */ - protected function peek() { - $this->lookAhead = $this->get(); - return $this->lookAhead; - } -} - -// -- Exceptions --------------------------------------------------------------- -class JSMinException extends Exception {} \ No newline at end of file diff --git a/application/extensions/Menu/MenuWidget.php b/application/extensions/Menu/MenuWidget.php deleted file mode 100644 index 660684e8e36..00000000000 --- a/application/extensions/Menu/MenuWidget.php +++ /dev/null @@ -1,653 +0,0 @@ - '', - 'alt' => '', - 'type' => 'link' - ); - - public $surveyId = null; - public $groupId = null; - public $questionId = null; - - public function run() - { - $this->render('adminmenu', array('menu' => $this->menuMain())); - if (isset($this->surveyId)) - { - $this->render('adminmenu', array('menu' => $this->menuSurvey($this->surveyId))); - } - if (isset($this->groupId)) - { - $this->render('adminmenu', array('menu' => $this->menuGroup($this->groupId))); - } - if (isset($this->questionId)) - { - $this->render('adminmenu', array('menu' => $this->menuQuestion($this->questionId))); - } - } - - - - protected function menuMain() - { - $title = CHtml::tag('strong', array(), gT('Administration')); - if(App()->user->id) - { - $title .= ' -- ' . gT("Logged in as:"); - $text = ' ' . Yii::app()->session['user'] . ' ' . CHtml::image(Yii::app()->getConfig('adminimageurl'). 'profile_edit.png', gT("Edit your personal preferences")); - $title .= CHtml::tag('strong', array(), CHtml::link($text, array('admin/user', 'sa' => 'personalsettings'))); - } - $menu['title'] = CHtml::tag('div', array('class'=>'menubar-title-left'), $title); - $menu['role'] = 'main'; - $menu['imageUrl'] = App()->getConfig('adminimageurl'); - $menu['items']['left'][] = array( - 'href' => array('admin/survey'), - 'alt' => gT('Default administration page'), - 'image' => 'home.png', - ); - $menu['items']['left'][] = 'separator'; - if(App()->user->checkAccess('users')) - { - $menu['items']['left'][] = array( - 'href' => array('admin/user'), - 'alt' => gT('Manage survey administrators'), - 'image' => 'security.png', - ); - } - - $menu['items']['left'][] = $this->userGroups(); - $menu['items']['left'][] = $this->globalSettings(); - $menu['items']['left'][] = 'separator'; - $menu['items']['left'][] = $this->checkIntegrity(); - $menu['items']['left'][] = $this->dumpDatabase(); - $menu['items']['left'][] = 'separator'; - $menu['items']['left'][] = $this->editLabels(); - $menu['items']['left'][] = 'separator'; - $menu['items']['left'][] = $this->editTemplates(); - $menu['items']['left'][] = 'separator'; - $menu['items']['left'][] = $this->participantDatabase(); - $menu['items']['left'][] = $this->pluginManager(); - - $surveys = getSurveyList(true); - $tmpList = array(); - $timeadjust = \SettingGlobal::get('timeadjust'); - foreach ($surveys as $survey) - { - if($survey['active']!='Y') - { - $group = gT("Inactive"); - $list = 'inactive'; - } elseif($survey['expires']!='' && $survey['expires'] < dateShift(date("Y-m-d H:i:s"), "Y-m-d H:i:s", $timeadjust)) - { - $group = gT("Expired"); - $list = 'expired'; - } else - { - $group = gt("Active"); - $list = 'active'; - } - $tmpList[$list][] = array( - 'id' => $survey['sid'], - 'title' => $survey['surveyls_title'], - 'group' => $group - ); - } - $surveyList = array(); - if (array_key_exists('active', $tmpList)) { - $surveyList = array_merge($surveyList, $tmpList['active']); - } - if (array_key_exists('expired', $tmpList)) { - $surveyList = array_merge($surveyList, $tmpList['expired']); - } - if (array_key_exists('inactive', $tmpList)) { - $surveyList = array_merge($surveyList, $tmpList['inactive']); - } - $menu['items']['right'][] = array( - 'title' => gT('Surveys:'), - 'type' => 'select', - 'name' => 'surveyid', - 'route' => 'admin/survey/sa/view', - 'param' => 'surveyid', - 'empty' => gT('No surveys available.'), - 'values' => $surveyList, - 'value' => $this->surveyId - ); - $menu['items']['right'][] = array( - 'href' => array('admin/survey', 'sa' => 'index'), - 'alt' => gT('Detailed list of surveys'), - 'image' => 'surveylist.png' - ); - - $menu['items']['right'][] = $this->createSurvey(); - $menu['items']['right'][] = 'separator'; - - - $menu['items']['right'][] = array( - 'href' => ['users/logout'], - 'alt' => gT('Logout'), - 'image' => 'logout.png' - ); - - $menu['items']['right'][] = array( - 'href' => "http://docs.limesurvey.org", - 'alt' => gT('LimeSurvey online manual'), - 'image' => 'showhelp.png' - ); - - $event = new PluginEvent('afterAdminMenuLoad', $this); - $event->set('menu', $menu); - - $result = App()->getPluginManager()->dispatchEvent($event); - - $menu = $result->get('menu'); - return $menu; - } - - protected function menuQuestion($questionId) - { - $question = Question::model()->findByPk($questionId); - - $menu['title'] = "Question {$question->code} (id: {$questionId})"; - $menu['role'] = 'question'; - $menu['imageUrl'] = App()->getConfig('adminimageurl'); - - $menu['items']['left'][] = array( - 'alt' => gT('Preview this question'), - 'type' => 'link', - 'image' => 'preview.png', - 'target' => '_blank', - 'href' => array('questions/preview/', 'id' => $questionId) - ); - $menu['items']['left'][] = 'separator'; - - return $menu; - } - - protected function menuSurvey($surveyId) - { - /** - * @todo Remove direct session access. - * @todo Remove admin specific setting; language is a property of any session. - */ - $surveyInfo = getSurveyInfo($surveyId, Yii::app()->session['adminlang']); - $menu['title'] = "Survey {$surveyInfo['surveyls_title']} (id: {$surveyId})"; - $menu['role'] = 'survey'; - $menu['imageUrl'] = App()->getConfig('adminimageurl'); - - if ($surveyInfo['active'] == 'Y') - { - $menu['items']['left'][] = array( - 'type' => 'image', - 'image' => 'active.png', - ); - /** - * @todo Get request changes state. - */ - $menu['items']['left'][] = array( - 'type' => 'image', - 'image' => 'deactivate.png', - ); - } - else - { - $menu['items']['left'][] = array( - 'type' => 'image', - 'image' => 'inactive.png', - ); - $menu['items']['left'][] = array( - 'href' => array('admin/survey', 'sa' => 'activate', 'surveyid' => $surveyId), - 'image' => 'activate.png', - ); - - } - $menu['items']['left'][] = 'separator'; - $languages = array($surveyInfo['language']); - if (isset($surveyInfo['additional_languages'])) - { - $languages = array_merge($languages, array_filter(explode(' ', $surveyInfo['additional_languages']))); - } - foreach ($languages as $language) - { - $subitems[] = array( - 'type' => 'link', - 'title' => getLanguageNameFromCode($language, false), - 'image' => 'do_30.png', - 'href' => array('survey/index', 'sid' => $surveyId, 'newtest' => 'Y', 'lang' => $language) - ); - } - $menu['items']['left'][] = array( - 'type' => 'sub', - 'href' => array('survey/index', 'sid' => $surveyId, 'newtest' => 'Y'), - 'image' => 'do.png', - 'items' => array( - array( - 'type' => 'sub', - 'items' => $subitems, - 'href' => array('survey/index', 'sid' => $surveyId, 'newtest' => 'Y'), - 'title' => gT('Test this survey'), - 'image' => 'do_30.png' - ) - ) - ); - - $menu['items']['left'][] = array( - 'type' => 'sub', - 'href' => array('surveys/update', 'id' => $surveyId), - 'image' => 'edit.png', - 'items' => array( - array( - 'type' => 'link', - 'title' => gT('Edit text elements'), - 'image' => 'edit_30.png', - 'href' => array('admin/survey', 'sa' => 'editlocalsettings', 'surveyid' => $surveyId) - ), - array( - 'type' => 'link', - 'title' => gT('General settings'), - 'image' => 'survey_settings_30.png', - 'href' => array('admin/survey', 'sa' => 'editsurveysettings', 'surveyid' => $surveyId) - ), - array( - 'type' => 'link', - 'title' => gT('Survey permissions'), - 'image' => 'survey_security_30.png', - 'href' => array('admin/surveypermission', 'sa' => 'view', 'surveyid' => $surveyId) - ), - array( - 'type' => 'link', - 'title' => gT('Quotas'), - 'image' => 'quota_30.png', - 'href' => array('admin/quotas', 'sa' => 'index', 'surveyid' => $surveyId) - ), - array( - 'type' => 'link', - 'title' => gT('Assessments'), - 'image' => 'assessments_30.png', - 'href' => array('admin/assessments', 'sa' => 'index', 'surveyid' => $surveyId) - ), - array( - 'type' => 'link', - 'title' => gT('Email templates'), - 'image' => 'emailtemplates_30.png', - 'href' => array('admin/emailtemplates', 'sa' => 'index', 'surveyid' => $surveyId) - ), - array( - 'type' => 'link', - 'title' => gT('Survey logic file'), - 'image' => 'quality_assurance_30.png', - 'href' => array('admin/expressions', 'sa' => 'survey_logic_file', 'sid' => $surveyId) - ), - - ) - ); - $menu['items']['left'][] = array( - 'type' => 'sub', - 'href' => array('surveys/update', 'id' => $surveyId), - 'image' => 'tools.png', - 'items' => array( - array( - 'type' => 'link', - 'title' => gT('Delete survey'), - 'image' => 'delete_30.png', - 'href' => array('admin/survey', 'sa' => 'delete', 'surveyid' => $surveyId) - ), - array( - 'type' => 'link', - 'title' => gT('Quick-translation'), - 'image' => 'translate_30.png', - 'href' => array('admin/translate', 'sa' => 'index', 'surveyid' => $surveyId) - ), - array( - 'type' => 'link', - 'title' => gT('Expression manager'), - 'image' => 'expressionmanager_30.png', - 'href' => array('admin/expressions') - ), - array( - 'type' => 'link', - 'title' => gT('Reset conditions'), - 'image' => 'resetsurveylogic_30.png' - ), - array( - 'type' => 'sub', - 'title' => gT('Regenerate question codes'), - 'image' => 'resetsurveylogic_30.png', - 'items' => array( - array( - 'title' => gT('Straight'), - 'image' => 'resetsurveylogic_30.png', - 'href' => array('admin/survey', 'sa' => 'regenquestioncodes', 'surveyid' => $surveyId, 'subaction' => 'straight') - ), - array( - 'title' => gT('By group'), - 'image' => 'resetsurveylogic_30.png', - 'href' => array('admin/survey', 'sa' => 'regenquestioncodes', 'surveyid' => $surveyId, 'subaction' => 'bygroup') - ) - ) - ), - ) - ); - $menu['items']['right'][] = array( - 'title' => 'QuestionGroup:', - 'type' => 'select', - 'name' => 'id', - 'route' => 'groups/view', - 'values' => QuestionGroup::model()->findListByAttributes(array('sid' => $surveyId), 'group_name', 'gid'), - 'value' => $this->groupId - ); - $menu['items']['right'][] = array( - 'alt' => gT('Add new group to survey'), - 'type' => 'link', - 'image' => 'add.png', - 'href' => array('admin/questiongroups', 'sa' => 'add', 'surveyid' => $surveyId) - - ); - - return $menu; - } - - protected function menuGroup($groupId) - { - $group = QuestionGroup::model()->findByAttributes(array('gid' => $groupId)); - $menu['title'] = "Group {$group->group_name} (id: {$groupId})"; - $menu['role'] = 'group'; - $menu['imageUrl'] = App()->getConfig('adminimageurl'); - - $menu['items']['left'][] = array( - 'alt' => gT('Preview this group'), - 'type' => 'link', - 'image' => 'preview.png', - 'target' => '_blank', - 'href' => array('groups/preview', 'id' => $groupId) - ); - $menu['items']['left'][] = 'separator'; - $menu['items']['left'][] = array( - 'alt' => gT('Edit current question group'), - 'type' => 'link', - 'image' => 'edit.png', - 'href' => array('admin/questiongroups', 'sa' => 'edit', 'surveyid' => $group->sid, 'gid' => $groupId) - ); - $menu['items']['left'][] = 'separator'; - - $menu['items']['left'][] = 'separator'; - - $menu['items']['right'][] = array( - 'type' => 'select', - 'title' => gT('Questions'), - 'name' => 'id', - 'route' => 'questions/update', - 'values' => Question::model()->findListByAttributes(array('sid' => $group->sid, 'gid' => $groupId), 'code', 'qid'), - 'value' => $this->questionId - ); - $menu['items']['right'][] = array( - 'alt' => gT('Add new question to group'), - 'type' => 'link', - 'image' => 'add.png', - 'href' => array('questions/create', 'gid' => $groupId) - - ); - return $menu; - } - - protected function renderItem($item, &$allowSeparator, $imageUrl, $level = 0) - { - $result = ''; - if (is_array($item)) - { - $allowSeparator = true; - if (isset($item['image'])) - { - $result .= CHtml::image($imageUrl . $item['image'], isset($item['alt']) ? $item['alt'] : ''); - } - if (isset($item['title'])) - { - $result .= $item['title']; - } - - if(isset($item['values'])) - { - - $result = $this->renderSelect($item); - } - - if (isset($item['href'])) - { - $options = array(); - if (isset($item['target'])) - { - $options['target'] = $item['target']; - } - $result = CHtml::link($result, $item['href'], $options); - } - - if(isset($item['items'])) - { - $result = $this->renderSub($item, $imageUrl, $level + 1); - } - - - - } - elseif (is_string($item) && $item == 'separator' && $allowSeparator) - { - $result = CHtml::image($imageUrl . 'separator.gif'); - $allowSeparator = false; - } - - - return CHtml::tag('li', array(), $result); - } - - protected function renderMenu($menu) - { - foreach ($menu['items'] as $class => $menuItems) - { - echo CHtml::openTag('ol', array('class' => "menubar-$class level0")); - $allowSeparator = false; - foreach($menuItems as $item) - { - echo $this->renderItem($item, $allowSeparator, $menu['imageUrl']); - } - echo CHtml::closeTag('ol'); - - } - } - - protected function renderSelect($item) - { - $result = CHtml::label($item['title'], $item['name']); - if (is_array(current($item['values']))) - { - $listData = CHtml::listData($item['values'], 'id', 'title', 'group'); - } - else - { - $listData = $item['values']; - } - if (!empty($listData)) - { - $htmlOptions = array( - 'class' => 'select', - 'id' => $item['name'], - 'prompt' => ''//gT('Please choose...') - ); - if (isset($item['route'])) - { - $htmlOptions['data-route'] = $item['route']; - } - $result .= $this->widget('WhSelect2', array( - 'name' => $item['name'], - 'value' => $item['value'], - 'data' => $listData, - 'pluginOptions' => array( - 'minimumResultsForSearch' => 10, - 'placeholder' => gT('Please choose...') - ), - 'htmlOptions' => $htmlOptions - ), true); - } - elseif (isset($item['empty'])) - { - $result .= CHtml::tag('span', array(), ' '. $item['empty']); - } - return $result; - } - - protected function renderSub($item, $imageUrl, $level) - { - $result = ''; - if (isset($item['image'])) - { - $result .= CHtml::image($imageUrl . $item['image']); - } - if (isset($item['title'])) - { - $result .= $item['title']; - } - if (isset($item['href'])) - { - $result = CHtml::link($result, $item['href']); - } - - $result .= CHtml::openTag('ol', array('class' => "level$level")); - - foreach ($item['items'] as $subItem) - { - $allowSeparator = false; - $result .= $this->renderItem($subItem, $allowSeparator, $imageUrl, $level); - } - $result .= CHtml::closeTag('ol'); - return $result; - } - - protected function globalSettings() - { - if (App()->user->checkAccess('settings')) - { - return array( - 'href' => array('admin/globalsettings'), - 'image' => 'global.png', - 'alt' => gT('Global settings') - ); - } - } - - protected function checkIntegrity() - { - if (App()->user->checkAccess('settings')) - { - return array( - 'href' => array('admin/checkintegrity'), - 'image' => 'checkdb.png', - 'alt' => gT('Check Data Integrity') - ); - } - } - - - protected function createSurvey() - { - if (App()->user->checkAccess('surveys', ['crud' => 'create'])) - { - return array( - 'href' => array('admin/survey', 'sa' => 'newsurvey'), - 'image' => 'add.png', - 'alt' => gT('Create, import, or copy a survey') - ); - } - } - protected function dumpDatabase() - { - if (App()->user->checkAccess('superadmin')) - { - if (in_array(Yii::app()->db->getDriverName(), array('mysql', 'mysqli')) || Yii::app()->getConfig('demo_mode') == true) - { - return array( - 'image' => 'backup.png', - 'href' => array("admin/dumpdb"), - 'alt' => gT('Backup Entire Database') - ); - } - else - { - return array( - 'image' => 'backup_disabled.png', - 'alt' => gT('The database export is only available for MySQL databases. For other database types please use the according backup mechanism to create a database dump.'), - 'type' => 'image' - ); - } - } - } - - protected function editLabels() - { - if (App()->user->checkAccess('labelsets')) - { - return array( - 'href' => array('admin/labels', 'sa' => 'view'), - 'image' => 'labels.png', - 'alt' => gT('Edit label sets') - ); - } - } - - protected function editTemplates() - { - if (App()->user->checkAccess('templates')) - { - return array( - 'href' => array('admin/templates/'), - 'alt' => gT('Template Editor'), - 'image' => 'templates.png' - ); - } - } - - protected function userGroups() - { - if(App()->user->checkAccess('usergroups')) - { - return array( - 'href' => array('admin/usergroups', 'sa' => 'index'), - 'alt' => gT('Create/edit user groups'), - 'image' => 'usergroup.png' - ); - } - } - - protected function participantDatabase() - { - if (App()->user->checkAccess('participantpanel')) - { - return array( - 'alt' => gT('Central participant database/panel'), - 'href' => array('admin/participants'), - 'image' => 'cpdb.png' - ); - } - } - - protected function pluginManager() - { - if (App()->user->checkAccess('superadmin')) - { - return array( - 'href' => array('/plugins'), - 'alt' => gT('Plugin manager'), - 'image' => 'plugin.png' - ); - } - } - - } - - diff --git a/application/extensions/Menu/assets/nav.css b/application/extensions/Menu/assets/nav.css deleted file mode 100644 index 82d8b417a9f..00000000000 --- a/application/extensions/Menu/assets/nav.css +++ /dev/null @@ -1,97 +0,0 @@ -nav { - overflow: hidden; - border-color: #EFEFEF; - border-style: solid; - border-width: 1px; - padding: 2px; -} - -nav ol { - background-color: white; - list-style: none; - padding: 0px; - margin: 0px; - display: inline-block; - box-shadow: 7px 7px 5px rgba(50, 50, 50, 0.75); -} - -nav > ol.menubar-left { - float: left; -} - -nav > ol.menubar-right { - float: right; -} - - -nav li { - -moz-box-sizing: border-box; - box-sizing: border-box; - white-space:nowrap; - padding: 5px; -} - -nav ol.level0 > li { - padding: 2px !important; -} - - -nav a { - display: inline-block; - - width: 100%; -} - -nav img { - float: none !important; - vertical-align: middle; -} - -nav ol.level0 { - box-shadow: none !important; -} -nav ol.level0 > li { - display: inline-block; -} - -nav ol.level1 { - z-index: 1; - position: absolute; - display: block; - visibility: hidden; -} - - -nav ol.level1 > li { - position: relative; -} - -nav ol.level1 img { - margin-right: 10px; -} - -nav ol.level2 { - top: 0px; - visibility: hidden; - position: absolute; - left: 100%; -} - -nav li:hover > ol { - visibility: visible; -} - -nav li:hover{ - background-color: #e0dfde; -} - -nav select, nav label { - margin: 0px; - display: inline-block; -} - -nav .select { - width: 300px; -} -/* Fix bootstrap causing menu to disappear on FF */ -nav.menubar { clear: both; } \ No newline at end of file diff --git a/application/extensions/Menu/assets/nav.js b/application/extensions/Menu/assets/nav.js deleted file mode 100644 index b7be921875e..00000000000 --- a/application/extensions/Menu/assets/nav.js +++ /dev/null @@ -1,7 +0,0 @@ -$(document).ready(function() { - $('select[data-route]').on('change', function(event) { - var params = {} - params[$(this).attr('name')] = $(this).val(); - window.location.href = LS.createUrl($(this).data('route'), params); - }); -}); diff --git a/application/extensions/Menu/views/adminmenu.php b/application/extensions/Menu/views/adminmenu.php deleted file mode 100644 index e580dd2efe0..00000000000 --- a/application/extensions/Menu/views/adminmenu.php +++ /dev/null @@ -1,29 +0,0 @@ -getClientScript()->registerCssFile(App()->getAssetManager()->publish(Yii::getPathOfAlias('ext.Menu.assets'). '/nav.css')); - App()->getClientScript()->registerScriptFile(App()->getAssetManager()->publish(Yii::getPathOfAlias('ext.Menu.assets'). '/nav.js')); -?> -

'; - } - if (isset($menu['items'])) - { - echo ''; - } - ?> - - diff --git a/application/extensions/yii-jsoneditor/JsonEditor.php b/application/extensions/yii-jsoneditor/JsonEditor.php index 8fb65e1e568..1319faa81f4 100644 --- a/application/extensions/yii-jsoneditor/JsonEditor.php +++ b/application/extensions/yii-jsoneditor/JsonEditor.php @@ -15,11 +15,9 @@ class JsonEditor extends CInputWidget 'class' => 'jsoneditor-wrapper' ); - protected $libraryDir = 'jsoneditor-2.3.6'; - - public function init() + public function init() { - $this->baseUrl = Yii::app()->assetManager->publish(__DIR__ . "/" . $this->libraryDir) . "/"; + $this->baseUrl = \Yii::getPathOfAlias(App()->params['bower-asset']) . '/jsoneditor/dist/'; $this->registerClientScript(); } diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/HISTORY.md b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/HISTORY.md deleted file mode 100644 index 68412997b8e..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/HISTORY.md +++ /dev/null @@ -1,296 +0,0 @@ -# JSON Editor Online - History - -http://jsoneditoronline.org - - -## 2014-01-03, version 2.3.6 - -- Fixed positioning issue of the action menu. - - -## 2013-12-09, version 2.3.5 - -- Fixed a positioning issue of the action menu again. -- Fixed an issue with non-breaking space characters. - - -## 2013-11-19, version 2.3.4 - -- Dropped support for IE8, cleaned up legacy code for old browsers. -- Disabled saving files using HTML5 on Firefox to prevent a Firefox bug - blocking cut/paste functionality in editable divs after using a.download. - - -## 2013-10-17, version 2.3.3 - -- Added support for search (Ctrl+F) in the code editor Ace. -- Fixed a positioning issue of the action menu when in bootstrap modal. - (thanks tsash). - - -## 2013-09-26, version 2.3.2 - -- The web application is now available offline. Thanks ayanamist. - - -## 2013-09-24, version 2.3.1 - -- Fixed non-working action menu when in bootstrap modal (z-index issue). -- Fixed missing main field in package.json. - - -## 2013-09-13, version 2.3.0 - -- Implemented an option `modes`, which creates a menu in the editor - where the user can switch between the selected editor modes. -- Fixed wrong title on fields with value `null`. -- Fixed buggy loading of files in the web application. - - -## 2013-08-01, version 2.2.2 - -- Fixed non working option `indentation`. -- Fixed css not being loaded with AMD in case of multiple scripts. -- Fixed a security error in the server side file retriever script of - the web application. - - -## 2013-05-27, version 2.2.1 - -- Fixed undefined options in TextEditor. Thanks Wiseon3. -- Fixed non-working save function on Firefox 21. Thanks youxiachai. - - -## 2013-05-04, version 2.2.0 - -- Unified JSONFormatter and JSONEditor in one editor with a switchable mode. -- Urls are navigable now. -- Improved error and log handling. -- Added jsoneditor to package managers npm and bower. - - -## 2013-03-11, version 2.1.1 - -- Fixed an issue with console outputs on IE8, causing the editor not to work - at all on IE8. - - -## 2013-03-08, version 2.1.0 - -- Replaced the plain text editor with code editor Ace, which brings in syntax - highlighting and code inspection. -- Improved the splitter between the two panels. Panels can be hided. - - -## 2013-02-26, version 2.0.2 - -- Fixed: dragarea of the root node was wrongly visible is removed now. - - -## 2013-02-21, version 2.0.1 - -- Fixed undefined variable in the redo method. -- Removed the "hide ads" button. Not allowed by Google AdSense, sorry. - - -## 2013-02-09, version 2.0.0 - -- Implemented a context menu, replacing the action buttons on the right side of - the editor and the inline action buttons. This gives a cleaner interface, - more space for the actual contents, and more room for new controls (like - insert and sort). -- Implemented shortcut keys. The JSON Editor can be used with just a keyboard. -- Implemented sort action, which sorts the childs of an array or object. -- Implemented auto scrolling up and down when dragging a node and reaching - the top or bottom of the editor. -- Added support for CommonJS and RequireJS. -- Added more examples. -- Improved performance and memory usage. -- Implemented a new mode 'form', in which only values are editable and the - fields are fixed. -- Minor improvements and bug fixes. - - -## 2012-12-08, version 1.7.0 - -- Implemented two modes: 'editor' (default), and 'viewer'. In viewer mode, - the data and datastructure is read-only. -- Implemented methods set(json, name), setName(name), and getName(), which - allows for setting and getting the field name of the root node. -- Fixed an issue where the search bar does not work when there is no global - window.editor object. - - -## 2012-11-26, version 1.6.2 - -- Fixed a bug in the change callback handler, resulting in an infinite loop - when requesting the contents of the editor inside the callback (issue #19). - - -## 2012-11-21, version 1.6.1 - -- Added a request header "Accept: application/json" when loading files and urls. - - -## 2012-11-03, version 1.6.0 - -- Added feature to the web application to load and save files from disk and url. -- Improved error messages in the web application using JSONLint. -- Made the web application pass the W3C markup validation service. -- Added option 'change' to both editor and formatter, which allows to set a - callback which is triggered when the contents of the editor or formatter - changes. -- Changed the default indentation of the JSONFormatter to 4 spaces. -- Renamed options 'enableSearch' and 'enableHistory' to 'search' and 'history' - respectively. -- Added parameter 'json' to the JSONFormatter constructor. -- Added option 'indentation' to the JSONFormatter. - - -## 2012-10-08, version 1.5.1 - -- Replaced the paid Chrome App with a free, hosted Chrome App (with ads). - - -## 2012-10-02, version 1.5.0 - -- Implemented history: undo/redo all actions. -- Created menu icons (instead of text buttons). -- Cleaned up the code (removed unused params, improved comments, etc). -- Minor performance improvements. - - -## 2012-08-31, version 1.4.4 - -- Changed: description of advertisement now gives information about the Chrome - App (without ads). -- Changed: Chrome App is now configured to be available offline. -- Fixed: When zooming your browser window, the fields/values did get wrapped - on Chrome (thanks Henri Gourvest), and on Firefox sometimes the jsoneditor - disappeared due to wrapping of the interface contents. - - -## 2012-08-25, version 1.4.3 - -- Changed: changed code for the buttons to copy from formatter to editor and - vice versa, no inline javascript (gives security policy errors in chrome app). - - -## 2012-08-25, version 1.4.2 - -- Changed: other bootstrapping mechanism for the chrome app, in a separate - javascript file, as inline javascript is not allowed (security policy). -- Fixed: drop down menu for changing the field type did throw javascript errors - (did not break any functionality though). - - -## 2012-08-23, version 1.4.1 - -- New: Chrome app created. - - -## 2012-08-23, version 1.4.0 - -- New: Improved icon, logo, and interface header. - - -## 2012-08-19, version 1.3.0 - -- New: Added buttons next and previous to the search box in the upper right. -- New: Escape characters are automatically inserted before " and \ missing - and escape character, making the string contents valid JSON. New lines are - automatically replaced with \n. (Thanks Steve Clay) -- Changed: all icons have been put in a single sprite. This will improve page - load times as there are much less server requests needed to load the editor. - - -## 2012-08-12, version 1.2.0 - -- New: Added search functionality. Search results are expanded and highlighed. - Quickkeys in the search box: Enter (next), Shift+Enter (previous), Ctrl+Enter - (search again). -- New: The position of the vertical separator between left and right panel is - stored. -- New: Link to the sourcecode on github added at the bottom of the page. -- Changed: Refinements in the layout: fonts, colors, icons. -- Fixed: leading an trailing spaces not being displayed in the editor. -- Fixed: wrapping of long words and urls in Chrome. -- Fixed: ignoring functions and undefined values in the loaded JSON object - (they where interpreted as empty object and string instead of being ignored). - - -## 2012-07-01, version 1.1.1 - -- Fixed global event listener for the focus/blur events, causing changes in - fields and values not always being registered. -- Fixed a css issue with Firefox (box-sizing of the editor). - - -## 2012-04-24, version 1.1 - -- Fixed a bug. Dragging an object down which has been expanded and collapsed - again did not work. -- Using a minified version of jsoneditor.js, to improve page load time and - save bandwidth. - - -## 2012-04-21, version 1.0 - -- Values are no longer aligned in one global column, but placed directly right - from the field. Having field and value close together improves readability, - especially in case of deeply nested data. -- Values are colorized by their type: strings are green, values read, booleans - blue, and null is purple. -- Font is changed to a monotype font for better readability. -- Special characters like \t are now handled nicely. -- Overall performance and memory usage improved. -- When clicking on whitespace, focus is set to the closest field or value. -- some other small interface tweaks. -- Fixed a bug with casting a value from type auto to string and vice versa - (the value was not casted at all). - - -## 2012-03-01, version 0.9.10 - -- Nicer looking select box for the field types, with icons. -- Improved drag and drop: better visualized, and now working in all browers. -- Previous values will be restored after changing the type of a field. When - changing the type back, the previous value or childs will be restored. -- When hovering buttons (fieldtype, duplicate, delete, add) or when dragging - a field, corresponding field including its childs is highlighted. This makes - it easier to see what part of the data will be edited. -- Errors are now displayed in a message window on top of the page instead of - an alert which pops up. -- Fixed a bug with displaying enters in fields. -- Fixed a bug where the last trailing enter was removed when setting json - in the editor. -- Added a fix to get around Internet Explorer 8 issues with vertical scrollbars. - - -## 2012-01-29, version 0.9.9 - -- Fields can be duplicated -- Support for drag and drop: - - fields in the editor itself can be moved via drag and drop - - fields can be exported from the editor as JSON - - external JSON can be dropped inside the editor -- When changing type from array to object and vice versa, childs will be - maintained instead of removed. -- Updated interface. Works now in IE8 too. - - -## 2012-01-16, version 0.9.8 - -- Improved the performance of expanding a node with all its childs. - - -## 2012-01-09, version 0.9.7 - -- Added functionallity to expand/collapse a node and all its childs. Click - the expand button of a node while holding Ctrl down. -- Small interface improvements - - -## 2011-11-28, version 0.9.6 - -- First fully usable version of the JSON editor \ No newline at end of file diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/LICENSE b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/LICENSE deleted file mode 100644 index ea2712c09fe..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/LICENSE +++ /dev/null @@ -1,176 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/NOTICE b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/NOTICE deleted file mode 100644 index 53ca4b0afce..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/NOTICE +++ /dev/null @@ -1,17 +0,0 @@ -JSON Editor Online -http://jsoneditoronline.org - -Copyright (C) 2011-2013 Jos de Jong - - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/README.md b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/README.md deleted file mode 100644 index c1110661464..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/README.md +++ /dev/null @@ -1,114 +0,0 @@ -# JSON Editor Online -http://jsoneditoronline.org/ - - -### Description - -JSON Editor Online is a web-based tool to view, edit, and format JSON. -It has various modes such as a tree editor, a code editor, and a plain text -editor. - -The editor can be used as a component in your own web application. The library -can be loaded as CommonJS module, AMD module, or as a regular javascript file. - -Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 9+. - -### Screenshot - -The web application shows two panels side by side: a code editor on the left, -and a tree editor on the right. Files and urls can be loaded via the main menu. - - - jsoneditor - - - -### Features - -#### Tree editor -- Edit, add, move, remove, and duplicate fields and values. -- Change type of values. -- Sort arrays and objects. -- Colorized code. -- Search & highlight text in the treeview. -- Undo and redo all actions. - -#### Code editor -- Format and compact JSON. -- Colorized code (powered by Ace). -- Inspect JSON (powered by Ace). - -#### Text editor -- Format and compact JSON. - - -### Documentation - -- [Docs](https://github.com/josdejong/jsoneditor/tree/master/docs) -- [Examples](https://github.com/josdejong/jsoneditor/tree/master/examples) -- [Source](https://github.com/josdejong/jsoneditor) -- [History](https://github.com/josdejong/jsoneditor/blob/master/HISTORY.md) - - -### Install - -with npm: - - npm install jsoneditor - -with bower: - - bower install jsoneditor - -download: - -[http://jsoneditoronline.org/downloads/](http://jsoneditoronline.org/downloads/) - - -### Use - -```html - - - - - - - -
- - - - -``` - -### Build - -The code of the JSON Editor is located in the folder `jsoneditor`. -The code for the web application in `app/web`. -To build the library from sourcecode, run - - jake - -in the root of the project. This will generate the files `jsoneditor.js`, -`jsoneditor.css`, and minified versions, and will create a folder `build` -containing the zipped library and the built web application. diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/docs/api.md b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/docs/api.md deleted file mode 100644 index 2f8439bb4f9..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/docs/api.md +++ /dev/null @@ -1,191 +0,0 @@ -# API Reference - -## JSONEditor - -### Constructor - -#### `JSONEditor(container [, options] [, json])` - -Constructs a new JSONEditor. - -*Parameters:* - -- `{Element} container` - An HTML DIV element. The JSONEditor will be created inside this container - element. -- `{Object} options` - Optional object with options. Available options: - - - `{function} change`. - Set a callback method triggered when the contents of the JSONEditor change. - Called without parameters. - - `{function} error`. - Set a callback method triggered when an error occurs. - Invoked with the error as first argument. The callback is only invoked - for errors triggered by a users action. - - `{boolean} history`. - Enables history, adds a button Undo and Redo to the menu of the JSONEditor. - True by default. Only applicable when `mode` is 'tree' or 'form'. - - `{String} mode`. - Set the editor mode. Available values: 'tree' (default), 'view', 'form', - 'code', 'text'. In 'view' mode, the data and datastructure is read-only. - In 'form' mode, only the value can be changed, the datastructure is read-only. - Mode 'code' requires the Ace editor to be loaded on the page. - Mode 'text' shows the data as plain text. - - `{String[]} modes`. - Create a box in the editor menu where the user can switch between the specified - modes. Available values: see option `mode`. - - `{String} name`. - Initial field name for the root node, is undefined by default. - Can also be set using `JSONEditor.setName(name)`. - Only applicable when `mode` is 'tree', 'view', or 'form'. - - `{boolean} search`. - Enables a search box in the upper right corner of the JSONEditor. - True by default. - Only applicable when `mode` is 'tree', 'view', or 'form'. - - `{Number} indentation`. - Number of indentation spaces. 2 by default. - Only applicable when `mode` is 'code' or 'text'. - -- `{JSON} json` - Initial JSON data to be loaded into the JSONEditor. Alternatively, the method `JSONEditor.set(json)` can be used to load JSON data into the editor. - -*Returns:* - -- `{jsoneditor.JSONEditor} editor` - New instance of a JSONEditor. - - -### Methods - -#### `JSONEditor.collapseAll()` - -Collapse all fields. Only applicable for mode 'tree', 'view', and 'form'. - -#### `JSONEditor.expandAll()` - -Expand all fields. Only applicable for mode 'tree', 'view', and 'form'. - -#### `JSONEditor.set(json)` - -Set JSON data. - -*Parameters:* - -- `{JSON} json` - JSON data to be displayed in the JSONEditor. - -#### `JSONEditor.setMode(mode)` - -Switch mode. Mode `code` requires the [Ace editor](http://ace.ajax.org/). - -*Parameters:* - -- `{String} mode` - Available values: `tree`, 'view', `form`, `code`, `text`. - -#### `JSONEditor.setName(name)` - -Set a field name for the root node. - -*Parameters:* - -- `{String | undefined} name` - Field name of the root node. If undefined, the current name will be removed. - -#### `JSONEditor.setText(jsonString)` - -Set text data in the formatter. - -*Parameters:* -- `{String} jsonString` Contents of the JSONformatter as string. - -#### `JSONEditor.get()` - -Get JSON data. - -*Returns:* -- `{JSON} json` JSON data from the JSONEditor. - -#### `JSONEditor.getName()` - -Retrieve the current field name of the root node. - -*Returns:* - -- `{String | undefined} name` - Current field name of the root node, or undefined if not set. - -#### `JSONEditor.getText()` - -Get JSON data as string. - -*Returns:* -- `{String} jsonString` Contents of the JSONformatter as string. - - -### Examples - -A tree editor: - -```js -var options = { - "mode": "tree", - "search": true -}; -var editor = new jsoneditor.JSONEditor (container, options); -var json = { - "Array": [1, 2, 3], - "Boolean": true, - "Null": null, - "Number": 123, - "Object": {"a": "b", "c": "d"}, - "String": "Hello World" -}; -editor.set(json); -editor.expandAll(); - -var json = editor.get(json); -``` - -A text editor: - -```js -var options = { - "mode": "text", - "indentation": 2 -}; -var editor = new jsoneditor.JSONEditor (container, options); -var json = { - "Array": [1, 2, 3], - "Boolean": true, - "Null": null, - "Number": 123, - "Object": {"a": "b", "c": "d"}, - "String": "Hello World" -}; -editor.set(json); - -var json = editor.get(json); -``` - -## JSON parsing and stringification - -In general to parse or stringify JSON data, the browsers built in JSON parser can be used. -To create a formatted string from a JSON object, use: - -```js -var formattedString = JSON.stringify(json, null, 2); -``` - -to create a compacted string from a JSON object, use: - -```js -var compactString = JSON.stringify(json); -``` - -To parse a String to a JSON object, use: - -```js -var json = JSON.parse(string); -``` diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/docs/usage.md b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/docs/usage.md deleted file mode 100644 index 751d30f5e51..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/docs/usage.md +++ /dev/null @@ -1,137 +0,0 @@ -# Usage - -### Install - -with npm: - - npm install jsoneditor - -with bower: - - bower install jsoneditor - -download: - -[http://jsoneditoronline.org/downloads/](http://jsoneditoronline.org/downloads/) - -The library consists of three files: one javascript file, one css file and an -image. Both full and minified version are available. - -## Load - -To implement JSONEditor in a web application, load the javascript and css file -in the head of the HTML page: - -```html - - -``` - -### Detailed error messages - -Optionally, [jsonlint](https://github.com/zaach/jsonlint) can be loaded to get -more detailed error messages. - -```html - -``` - -### Code editor - -The mode 'code' requires the [Ace editor](http://ace.ajax.org/) to be loaded. -Also, the content type must be specified on the page. - -```html - - - - - - -``` - -## Use - -In the body, create an div element with an id and a size: - -```html -
-``` - -After the page is loaded, load the editor with javascript: - -```js -var container = document.getElementById("jsoneditor"); -var options = { - mode: 'tree' -}; -var editor = new jsoneditor.JSONEditor(container, options); -``` - -To set JSON data in the editor: - -```js -var json = { - "Array": [1, 2, 3], - "Boolean": true, - "Null": null, - "Number": 123, - "Object": {"a": "b", "c": "d"}, - "String": "Hello World" -}; -editor.set(json); -``` - -To get JSON data from the editor: - -```js -var json = editor.get(); -``` - - -## Full Example - -```html - - - - - - - -

- - -

-
- - - - -``` - -For more examples, see the -[examples section](https://github.com/josdejong/jsoneditor/tree/master/examples). diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/01_basic_usage.html b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/01_basic_usage.html deleted file mode 100644 index 4f0e2afe476..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/01_basic_usage.html +++ /dev/null @@ -1,45 +0,0 @@ - - - - - - - - -

- - -

-
- - - - diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/02_viewer.html b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/02_viewer.html deleted file mode 100644 index be0306c26ae..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/02_viewer.html +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - -

- This editor is read-only (mode='viewer'). -

-
- - - - diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/03_switch_mode.html b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/03_switch_mode.html deleted file mode 100644 index be9f1465d68..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/03_switch_mode.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - -

- Switch editor mode using the mode box. - Note that the mode can be changed programmatically as well using the method - editor.setMode(mode), try it in the console of your browser. -

- -
- - - - diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/requirejs_demo/requirejs_demo.html b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/requirejs_demo/requirejs_demo.html deleted file mode 100644 index d1b3af776a6..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/requirejs_demo/requirejs_demo.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - -

- - -

-
- - diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/requirejs_demo/scripts/main.js b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/requirejs_demo/scripts/main.js deleted file mode 100644 index 6727839fe8b..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/requirejs_demo/scripts/main.js +++ /dev/null @@ -1,25 +0,0 @@ -var module = '../../../jsoneditor'; -require([module], function (jsoneditor) { - // create the editor - var container = document.getElementById('jsoneditor'); - var editor = new jsoneditor.JSONEditor(container); - - // set json - document.getElementById('setJSON').onclick = function () { - var json = { - 'array': [1, 2, 3], - 'boolean': true, - 'null': null, - 'number': 123, - 'object': {'a': 'b', 'c': 'd'}, - 'string': 'Hello World' - }; - editor.set(json); - }; - - // get json - document.getElementById('getJSON').onclick = function () { - var json = editor.get(); - alert(JSON.stringify(json, null, 2)); - }; -}); diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/requirejs_demo/scripts/require.js b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/requirejs_demo/scripts/require.js deleted file mode 100644 index 8de013dc9cf..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/examples/requirejs_demo/scripts/require.js +++ /dev/null @@ -1,35 +0,0 @@ -/* - RequireJS 2.1.2 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved. - Available via the MIT or new BSD license. - see: http://github.com/jrburke/requirejs for details -*/ -var requirejs,require,define; -(function(Y){function H(b){return"[object Function]"===L.call(b)}function I(b){return"[object Array]"===L.call(b)}function x(b,c){if(b){var d;for(d=0;dthis.depCount&&!this.defined){if(H(n)){if(this.events.error)try{e=j.execCb(c,n,b,e)}catch(d){a=d}else e=j.execCb(c,n,b,e);this.map.isDefine&&((b=this.module)&&void 0!==b.exports&&b.exports!==this.exports?e=b.exports:void 0===e&&this.usingExports&&(e=this.exports));if(a)return a.requireMap=this.map,a.requireModules=[this.map.id],a.requireType="define",C(this.error=a)}else e=n;this.exports=e;if(this.map.isDefine&& -!this.ignore&&(p[c]=e,l.onResourceLoad))l.onResourceLoad(j,this.map,this.depMaps);delete k[c];this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a=this.map,b=a.id,d=h(a.prefix);this.depMaps.push(d);s(d,"defined",t(this,function(e){var n,d;d=this.map.name;var v=this.map.parentMap?this.map.parentMap.name:null,f=j.makeRequire(a.parentMap,{enableBuildCallback:!0, -skipMap:!0});if(this.map.unnormalized){if(e.normalize&&(d=e.normalize(d,function(a){return c(a,v,!0)})||""),e=h(a.prefix+"!"+d,this.map.parentMap),s(e,"defined",t(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),d=i(k,e.id)){this.depMaps.push(e);if(this.events.error)d.on("error",t(this,function(a){this.emit("error",a)}));d.enable()}}else n=t(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),n.error=t(this,function(a){this.inited=!0;this.error= -a;a.requireModules=[b];E(k,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&delete k[a.map.id]});C(a)}),n.fromText=t(this,function(e,c){var d=a.name,u=h(d),v=O;c&&(e=c);v&&(O=!1);q(u);r(m.config,b)&&(m.config[d]=m.config[b]);try{l.exec(e)}catch(k){throw Error("fromText eval for "+d+" failed: "+k);}v&&(O=!0);this.depMaps.push(u);j.completeLoad(d);f([d],n)}),e.load(a.name,f,n,m)}));j.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){this.enabling=this.enabled=!0;x(this.depMaps,t(this,function(a, -b){var c,e;if("string"===typeof a){a=h(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=i(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;s(a,"defined",t(this,function(a){this.defineDep(b,a);this.check()}));this.errback&&s(a,"error",this.errback)}c=a.id;e=k[c];!r(N,c)&&(e&&!e.enabled)&&j.enable(a,this)}));E(this.pluginMaps,t(this,function(a){var b=i(k,a.id);b&&!b.enabled&&j.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c= -this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){x(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};j={config:m,contextName:b,registry:k,defined:p,urlFetched:S,defQueue:F,Module:W,makeModuleMap:h,nextTick:l.nextTick,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=m.pkgs,c=m.shim,e={paths:!0,config:!0,map:!0};E(a,function(a,b){e[b]?"map"===b?Q(m[b],a,!0,!0):Q(m[b],a,!0):m[b]=a});a.shim&&(E(a.shim,function(a, -b){I(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=j.makeShimExports(a);c[b]=a}),m.shim=c);a.packages&&(x(a.packages,function(a){a="string"===typeof a?{name:a}:a;b[a.name]={name:a.name,location:a.location||a.name,main:(a.main||"main").replace(ga,"").replace(aa,"")}}),m.pkgs=b);E(k,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=h(b))});if(a.deps||a.callback)j.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(Y,arguments)); -return b||a.exports&&Z(a.exports)}},makeRequire:function(a,d){function f(e,c,u){var i,m;d.enableBuildCallback&&(c&&H(c))&&(c.__requireJsBuild=!0);if("string"===typeof e){if(H(c))return C(J("requireargs","Invalid require call"),u);if(a&&r(N,e))return N[e](k[a.id]);if(l.get)return l.get(j,e,a);i=h(e,a,!1,!0);i=i.id;return!r(p,i)?C(J("notloaded",'Module name "'+i+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):p[i]}K();j.nextTick(function(){K();m=q(h(null,a));m.skipMap=d.skipMap; -m.init(e,c,u,{enabled:!0});B()});return f}d=d||{};Q(f,{isBrowser:z,toUrl:function(b){var d=b.lastIndexOf("."),g=null;-1!==d&&(g=b.substring(d,b.length),b=b.substring(0,d));return j.nameToUrl(c(b,a&&a.id,!0),g)},defined:function(b){return r(p,h(b,a,!1,!0).id)},specified:function(b){b=h(b,a,!1,!0).id;return r(p,b)||r(k,b)}});a||(f.undef=function(b){w();var c=h(b,a,!0),d=i(k,b);delete p[b];delete S[c.url];delete X[b];d&&(d.events.defined&&(X[b]=d.events),delete k[b])});return f},enable:function(a){i(k, -a.id)&&q(a).enable()},completeLoad:function(a){var b,c,d=i(m.shim,a)||{},h=d.exports;for(w();F.length;){c=F.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);D(c)}c=i(k,a);if(!b&&!r(p,a)&&c&&!c.inited){if(m.enforceDefine&&(!h||!Z(h)))return y(a)?void 0:C(J("nodefine","No define call for "+a,null,[a]));D([a,d.deps||[],d.exportsFn])}B()},nameToUrl:function(a,b){var c,d,h,f,j,k;if(l.jsExtRegExp.test(a))f=a+(b||"");else{c=m.paths;d=m.pkgs;f=a.split("/");for(j=f.length;0f.attachEvent.toString().indexOf("[native code"))&&!V?(O=!0,f.attachEvent("onreadystatechange", -b.onScriptLoad)):(f.addEventListener("load",b.onScriptLoad,!1),f.addEventListener("error",b.onScriptError,!1)),f.src=d,K=f,D?A.insertBefore(f,D):A.appendChild(f),K=null,f;$&&(importScripts(d),b.completeLoad(c))};z&&M(document.getElementsByTagName("script"),function(b){A||(A=b.parentNode);if(s=b.getAttribute("data-main"))return q.baseUrl||(G=s.split("/"),ba=G.pop(),ca=G.length?G.join("/")+"/":"./",q.baseUrl=ca,s=ba),s=s.replace(aa,""),q.deps=q.deps?q.deps.concat(s):[s],!0});define=function(b,c,d){var i, -f;"string"!==typeof b&&(d=c,c=b,b=null);I(c)||(d=c,c=[]);!c.length&&H(d)&&d.length&&(d.toString().replace(ia,"").replace(ja,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c));if(O){if(!(i=K))P&&"interactive"===P.readyState||M(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return P=b}),i=P;i&&(b||(b=i.getAttribute("data-requiremodule")),f=B[i.getAttribute("data-requirecontext")])}(f?f.defQueue:R).push([b,c,d])};define.amd= -{jQuery:!0};l.exec=function(b){return eval(b)};l(q)}})(this); diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/img/jsoneditor-icons.png b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/img/jsoneditor-icons.png deleted file mode 100644 index 7120088f9475d17ba3bd5f716bdf8bf4eeb1f32a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14438 zcmajm1yodFxG($xq@+XXl5UXh25AHYq`SL22M_@%=@OCdF6jp8?(UQr8ooWA^PO1h z-gW=K1)CWdW)HLW`#x_Fp`s*%_L}fD2n0ft{UE6d9Or?LLQDkU^JM&^18{g{A*Lt> z0#(JJJQ~3Rw_#jVWyC?{qr?Zm4RVtYs)`_xHw_3B2nK=ffx80tK_E9a5a`el1maHt zf$$tNnm-Bx-#{>ymyraHK<*@30)PXu-E;9|#YivRbg{RwfxrOrXCGkuU;uiW~{(#8hp*MuuKc(Oy3eMTF(dpRHYU`mjC~$ds(>ROA_U6jfeU}%Ms&L=o@a?4ko5VUh<_m6jOdA|Kh9C}NJjE?7~99bQmiiRR^{7b!XY!PUXyB1Ac0 zt{fd542mKXaV>O2euMjVwW<3Or`o13Y(GIr8(_Kl>Z2!@WX zu$((wzDS)R4g`8Uad>`qlQ@aMNlmS*+jW8KynXQTk*5Mlgx}xKDxPHt$;4=A!g>0% zG|5tdLJ)6G7`GM9Pa488G&SLto7D8}(c2NH-`l^Fj2$u$0sr$ zg?BJ?Oiavqxa+$kKi_2`?yngX9yn(3eXke$G}E1~|5@>4K}os4mX}GwNiIw}=Eew* z$P+H;hr^m!2nZy6Z#l;T3Y3cM>H>l6mj^}>K=X}%AI@Mvy1HP|-|i=;DfjEPHbpek>id!pp|=s|Avq-7sRHGc@%a2+yCrabFXXjprhv#i-t_dSYwL68Q`EzEmEp=Xyp|4w zwv6G^-OspAc#$2~nw zpn)mX;jtXw9f>}B85MYXsL{Re-9~rC z3LexXN9V)oh}f`ng(Vbu3kg4$nVGJWyr!#_x_S)RW5U>`y!Mg%4t`QZL|R%9NI*cQ zKfKl6%*+nW&{ABInIg^+!*>q}ix4J#5qAKx<+V{gI7*u+N2P^h)AsyCMqKK2x;#^Y z(K2pfuHVvk8AeEOgd_1mfw?^BWZr2<&b4-G zBOf=evB;&&#hQW`jKG|j5_voe3kpOpFHl&TW(=tx&?A*Fw7YLOmYRQ!XZCec;d_MyzdTXXnKyYGtK3 zk||(p(NaDzFlT@Wa&(8BgV;FfM>8LeYs80!hd`)`kt;1Xhwvaao7t8#SkU8RjWisn zH8cz9u|9`Sq;p{ z`17avp-Q;gZ20+-3>5gO1T5SFLDubylG&=e>NKy~zs3k7(V({fa zCC{3m-~Egx+KWM}_Q$w{DSrYRe(tZ1*N4pqWvr}ci(H_R-pW*_-@lia4CwYv-@F zqK_o)7#ZbLsy3_o!GYU{i+L#h$ar1NevAs)!YeH<85?(X$H&XMMpr-C7(UucghP&K z6JL+1{S^$9b9?k$nTQn=>kb<<1t}?Y?aNoqFMR$CgMW`cmW?Nk$352@*|pa%9Z=mw zF_F#DApGlFmcOmIuVm#qB?R}QVy|=!HO(_bM=?5wH9x2J+O7L$maJ&`=G{`(N2b#n8Yu`rcja3@4*4tt>+WVq#`yK4OuH zOMnJW{n1LEX<&RS#I$-%i>d1icBjQflX=omyMUD28XpaKcaTFvR)Q8|9=?~5$1qK?NM}h z9~#TT)XFm{uYY-Z`rKiR_iHp$z~gjzp|Uk+Yf;__8g`(;faYn=VfDAy<*uSc^Frv{ za^+YruU~1OsyZ}O?hFDf0nogJ8H^1;gDH^6tQ=s&#q+}4816v0MOLgplYo2~osKt) z+jDw;@-Ihc{ihiV{>SLVby0tBf>zcm1^i6@<9x2+z@h&#-^4ym?8cvYYQ*@xDvbc; z)$Y*Xzr^a7X_U-ZqqUoe|FJna3$q5>`j}MYemh}Z0}rIRYl&W5LG!B7|LOkvXbugJ zhV@^%Lz7SX)0%tiO>2AZS$r3I2AEyc*= z(JXj22;AvHjm21&5SoE!k^uy+$?XXGHuhlXqN02d{+AJv=f}Ity|HYEb^*1mwjcRP zxlSOCWI`>Oerx^X%XXie)0Gwvv}}}z%<88<)PYq;2qjHKh%|3I2)#+%Y?;vwOIf=b zD@rK(GE4vbdmEc5^(_P+#0{F9cZL!fff5s%FqBfK^=9{z#X6h0!uwQ+#zTYMeKvo4 ziSr-bZglJFs`gSil{?zN^5mMipCJhvih7@-4QdN0-Nry)#%MXb3n8zz)*+N+Zt`Pl zfLouR4wDLj2~S$7w0U`m%D91iq>bTmH?iT*EPZxJEH+7f;ZhdQx@GPXuT+m2yuXM1!DJc9pqRO`_Uk|*fmOj%#ct|8+ms_V8 zdGh4@rp2*(qV%|HC=EB7%+fq4a)xt(?JWPBzOBvZzl7y;Y2+GdWoOT0bP(N;)L(fF z35#q^H1Ch4>X50*D2w>-kg}8Ph#3G+Z(SQbqwuetnxyV_GTuwzVkZ)Lo=}Od{Ezqx zFSVEj!}~)T^0d$h5y!~cjX)CSIaQrPyWF?oT=X^hwSDWBpZ?bv_y5={Jk8V^!qb2i zWO7vKaKGNyoEObl*J<0O)Hf78L@*b6sGR*+O-fSbDN3KVd-jbDA>N+K7Zcu=@Q)$A z@z6yWHe9H)=@MD!HZ_(WR^nbFA1kX-SnET?QP)~JB*ZO}2?0%G+M%W(*%Fwwqo*y(~V$D4~h;_|)qug*TEMJr=} zTJfOx7nyI4M@`qu_iO$kJnLwlTYvk_R-kf!k`q-^_;e#wT}H(6z5fhSv(*HwRfnc` zj;x#e-sYTlw|aj%Mop8WL(9vV9*$h=JX`m8yv#mKg{rZL%w(ZrIaJ6jx|C;yfq#t) zGVfAIX|i3&Mq~*A|BHZ!xG>rs=k}D@Fz1YS=}({{C#;3wd{hrLd#vdQ-fdIPn#dPfRNF_gs%=TD^!8gE+c(zOo6 z?7B^1qWD#14tbs4ISlGtB;n8u2n+&F7U9D;*ogI8G;YQ5@FFue^5Y8z)VAsMTDtJ@ z;Y^a4ur972FRyg&nV)8TtznJlemo!U<6WWLhgPtrO6jZN&mQ6g#&I|?WcbOLgJ05v?3}td9lcy_;;*%;w zY@Ke3sI{%8K~{O$xUnk3QgeoZ=SCA50dG;qW)YuLIFHK4I8* z2#~LAab{BN%9CiE3)o6wXTwM6UN6%LZ3km=eZ=9Ss14Q_|LV~8v6+75yZu&Q(S^EK z@$aqvC4tO=+D7hxaLX@YmWYU+gjrz)FLz_V8=-ztZ75kS^H!k*=7r=%=3V+XM?YZ| z_A2qb$N7ti@i&aC(#>Iib-b0`-PT39o7xdsH+X}$Il}&Dx^{KFJLO<>43LWApWO$J z{JKS8Q6z9jX{mYkJ~=Ts1dmltKkoNCFKVV^IzG8?*qNi#2X;~KKc|)|K>lLEYWV&> zpX>U$`pr2uWO*^|?Zi9n+JKj*EtPQdYLK*2EY7wh4$CoF2jV$QKXQ=xqtw8GA%6;b z(%@+UO3p4_$a}gL=bh)5B_jdbms^vZvFVAbs_sxR;!FV-Y^5$);pf{t>z=`Ya6AR~@Q!p_9R|S|~O~b}Hk-YkqAHz7A{l-Przg8+}u~p=~m2 zxo0H2AhPcMbEjmMXj1%FVwl_8J>O9NadERdyP}-3d_Zw$>JdLaS?Wpf#2%xTAKFbE zVNB<7{&gP@m<)n5#tWp;Oeh&tR4_d-J}^DtUTq%?BIH80f#rN&ntWP}>@wJ>I0sI@ z649qJChGT#I1H|+SiAqD+4K8=yB_2mRxT!m#;t}1ys&+vHxeOhNi6 z;o~K|cyi=;rR-UeiU9qWM?8aCH(^NGQiJ_k^Kfzz-t|xYjg3ms+m7ISE_y-<6U!)# zVUJCLznS9V)0Z=VqgSWy?^*107aKWsbQp55873?{-r9D~F10Ms-f!{BvO-1E7(4fD ze;IUlKglGU=BH@^A&E@uG=RxO718bzALaa`BdXF&xdyE#^A)>L;XKa10&M_x+c-LU zvk=tfF0vwv%WkZ1yz)h!s@peynM`0VX!YRzDav~{vXuFt&fi$?)>r_~cYCI+3-XZB zbc<@W3UFfOd#*(FI0jYf)sR1Op{hCRl9J~JP{)f>_3>q+9UTt4i*JYnc|zR}ez4I~~2BCb-4 zSVW}w+6tBJN5hH5P2o5riZ-1gAd{UpHfiC;?;NU2q51fpPoBB36j*D@O;El~wb;^}uZpMm(iU7*JJ6E&%PP;lk*;@3;`l?T_MQq~*mf6TQ1AFB`wa4dVq1WW{j5HzjNf8N0S zOBjJnT66ZiQVg%q=G7Pb6{-hnKr$;Wq$g`WJS_eLw(L6}$gib+?qw)SKb2UGY?<>R>#ww$=^zRy`4*#O3N_*wwox5G&(Eo4DKV)RZ5 z-db<2rzn4E5uazTe^tTG*Vpr}(ha9dKO661P=FP}W+dm=X5R~E&)*$cg3~m8AD^6k zg`e)O_B_ts$|c*l_FhJL5nR6CMI)wr)%Er3Rpx=fl*h$m)8HOWcKTxv4)oW!01Y<6 zD+{P7Qf3lbfTmvAklIes#WylM0lfi1B$&R@Z`lLN+q4Y0R8io#%0=x#W|5Cg^w9{(=UB34(EG?RD7YxlAumdIRD2s;)a2!B1o7G_iE8 z9Y?%5EV0vIqmPB9Pv=4WgPKCX=5o5s?UUViK@^J>i&g1J;TPQ|ZNSKikwV1AV|ZF` zXPk#v7p;NF=Ji!jDhnHr_L0X}G65q4zQ%C2$|Q{gYD|RHU5pJYfs#f>p}umQ`XJs_ zmdt-3du#0Pp0zb>HkvQ@`GQ5ZqEMnY!}WJh#$CeU{~RU12@tyXhgw}V#V3#s`>fq1 z)QEU9IptU43%IyQ^AX0DHz;(?vYp8yex!p&BM zyM73FmE#D8l9zwNfx0=hd-TPQVpLPZV#!6zxPwm^M3M z%*Oi5o2qvjXTK@kVeqGz=K$I45|*$R7s1e`2XvEq%CTb6b`_7=QE&f7ATz2Rh*8e{ zE{*`meOipT_N&GOgB&uZ5!JK`{%Z;3pmawZ`}%e8k|B|8NkWW?BkH%*a@ph=q=4(& znJvv2tEppoD0GsavjNKv&LE9 zj=A1;FL#}O$TQ=xuwaY_;>dXbpW-xo9Kcc$=*mied1RQADGCjZP51>sMM#m>%mvj9k0 zLyr8d= z@teTdiSJZ=I^1W+v7J9V~Y%|`}6zj5F$r7`^PIB&tO_lIVv<#;8q7(tNumAHqIa| z4$ZOhYW8mtK8~8!Nt@;G=7%(rE?(tBx_UX9`){nx@}j5uthP3{Ix!wQlvyeoawpil z{qaSj$dXbAX)gzTtD~c9)wLOz(a`)H@moXSbi;-ny^dxBE1@7n(yY1zGEwU*ULLDY z1=)t&f5H|tG;TcT!i?!=t&4Enek$ckqv5j|b_Bu{6`klkTSZR3&10^v+xgi@$8tD; zH6DcSDiKzDer%^ z3Rt*0=!xUS?mx6*c4vy)I$`K9fN?|XpP`Iewwi=uQb-9C70%36t zugEWtDjGbV!6+Wi7YnsDRu)tG-Vw)C0)wM^Egy&@D4hhA9ma{S`o7b{6(g!+6xzRZ zyupKpHqP;TF7ZlTNnKE6j?6xmHx(NucL%~eCSI~6aHV`=kVybuZc&-tneWeCs~Q12 zsi2>tAKC0P&U-70Cs8K=vPy3Sx=Bc8I~MU!bh)0a?`N*mihu&DV?!AhZwupjJ>aVF zT(mkI5iG$A7T~K&9(-LLTzY%LbC2uyRrvZW0Hu2r2fJsKl@irmt6CDN(&O~Df@*)35@vOxh?KnuN(qb^4+b1`%5?kYWPXxvX7V_%Y>V*h-TF^7+(9n^g2qNn+ zbVlD^@OZjzcvrkrl2q}04(AJR(5cxS#^t?k#ETlf<}YAq)X^0fO6E7Mzw>3>AZ`%B ziTsLguqob!dhe@-ygn6cJRYloy`=~Q#NipjK>6R>3jR;U&VX*+iZg>OX9Ueis>@5XH1K}7Dn#+CkQAavMOam! z3QJ_?jHwh&Z!~s0g>TKy7Gpu}>>OXK5Xwmu<>vZFL8&4)#iBIjN{hj(i-v|H3MpVr zb*mOtb^v=9&XIj#vmYVpmB!`TBX6&4D<1LHgo}Jt?@Z5DeF+TulBFa&=FYi%pQhEi zUbh3?+S##DCNfEglV= ztru=k^z?S0NTVm1W&!q3)kH`Xms3L^=`X(JfYWfYE|YV7L2iHF1dJ7gCBvmGp)>`> ze43gQ8WA*lWWeWYur1}%K>fgn525NGTAks!yQJs$ci;sK5sxjOmV>v+`97fM7tEPM z$w(n{CHvecB*t`f28F;O4x5&z>+!VMuQtX#D)`fgG(30x>2OJv3<+~*o4j;<~ z>Z!IY==cT>mdYreO?JN83={q%W}S6nk@Mz#`B6*x8H?7q;ksPls}H>1>dsOCYL;?s zZRWD1ERiw&q|hO8vz!ow370EkAs!c+R#}J1bU1|bAYXDaEfvty53;Mvi{|X?{(Y0H zDhi2hfgOOIE%3uv=-sJ|+dMHn85%0Cq<+(N1K@3Sy@ESqQ zmuoq9^rvo*H@Jf=-5A{FTE#I@4i8ila7-H%x2p$uo$5wjVv!P)60g?K?hQ3LmpeI$ zE6!Cqb4LIC$Z7p_|EdM*<+;JiB2jL~V7NUg;Hei+1u0a8*U?bI2U>D6B{O{-(*%h4 z&To_9iX+v<4koF|MkxUPjA_y^CL|6HCtu3k zNg8J$A+Wq}3O3a#WxB9EBBvz%FU&7&YQ@jH&ejUWC#g)Fx`-POd#%)X9){}he ze=fFJ)}s^Az@le;=oRdZc#VFzQlut7CALa&7VDAaU0n5KX|R|KVWtmaXG7@I`b^Kw z0Dv4XOyA_lAE-9FK0v(B0+N@hJ<=7atkWL>FRd$T5E-?M{1U*? zc#fiwEimm->tr=Lnxw2PY<2fb8cs^(l@uOpJUO;x@Z_YY&uUhKh>J9StH*BCc!Qem z^5XW8$ai2``uyRn6Pu~C+D0?U|A-DySdjH~jRZRT?dDc9_E7eybJrm9)RSiVxudGO z7Cbb`H+K=Z*E16n;mBMo2Z?K^l+|MPV|K5{kkl zn?|Lms;zA^40J5oC2=&8a#HdOpBi6lqK(;b@ku270=V+GhObJTVPQLWoCdDIwEX-D zYz7g3N0r9Xv@OV|JbEceB8fO51}dfh=pzltf0Ij`3lyTr(B^opb?$oZqDvY?QA>ID-FRMPbE%OB2b%f<%B^&ul zT>h~s={<^@G^sxhxKO*ukGEyFMwYehnH$^}Ijb&XFvX48KcgKt^^P(7+gH`NTn`+^ z%}}=Ah3URa9>`DSQ zO8*{*RYA8(el3#6C5JMfY*HccO+-w^jd01Jb+valf?Gthq~7F}7zq-^^h6zhU{z7H zt9GVF!P6!RMARV!@!xE~X79xzl%~GbQBksX~*Sm{=lE*y_PYL z?6Z?4<77&4q*Uz^IIY&Aw6y!amI0P(`8?HvLbYl7m;2;-_z6r3$DaNg0ztw*W7^e8 zrLA5GjO(u(g9$jmvd;4Iiizml^i?aeEeYh#rFx8y4en)4in~j*^V3@5{>iMGI9wmo*&Nx$73=CX3jeZb{aDHc zT+Zs$egP(QyWysdlM#W-5HDe*=Wiip6;)Et?6l|`b+MVV_Dj6G$j9DRADj=cvgE+t zB~5-(->lIv4WPYvzJE=G(y1V&e*t#*3P4vbp4=;p^)wDp{%sDn9;6c2`sqi7)3r9L=at z#9PK$;NeYa7i8Vd&0i1aZSU5*2@`g`J^wCiik z#v_{gKez%c0tf4P#fYB|oze z;CW@Kv$xj?x|~+az}V})yS?SS5!`0uQ$SZ^V0ui=%Bmx`5t|L3DtOSiD%;m#cY3!X z*DzW3`Lj4^_>ZmA-B=<($f?Wot)CjbfqGk^??i%fby2;7pFcSE&idNhFp(YVU*r$DVgoAFn`2q!$%Lz4AtCOS07uDJ+u|(S=tQ%d9lf@} zij_qc$`Ab~WDNnjECG)2CR0XSvJYmE;p1d@_&QF<71m@C>!e9vt2WMn^$!2F>xc3+ z54HSQ(|Cn=JzYcUQgEV>PZ~cN5``%P%^4g=!=SIkZ>R!AIFWNWk?!v*;vLjrgb8v& zNhD-)7^)wIU!rKY25+YdN;EYq%JubB$TO(`>N<=f zF}qW~X#qQO#@2vCWsy_{GO_;PZ}22OhxGPn4PiP{?E$SM&xOdZxiX_rg~1pb5?>>! zTc`k9fv1aaHYrFq5z)8xyfjy5RxICw~Lo5mTZrUtq=F>{GQW^W}NoD9#3qR(xM zFH3ts<+m91q-`%!8!48MG+@Sg3o|_on`%*7scD z1g`LzL*dH$i}n4ET}nM!&B;2Mm_A6Zkd^XcP3?F49G(57;$jX*gi%qBRSzttU@0rB zzVvI^dn&*9aG4SmV|J#n-s`b$zfOSDy{npXxA{!PQ!Qj_QQ5{umSvE-iJID$O(tZA zBSPtCf}qd~-HZ$*43T2`FQ>EEJIO{$VArs_@&alK31w~CcFH25n=DsZx)9wqmlWxa(+r(Y;&!zJpH=34Aq0(hJ- z*t)s--L9RrEB|N7>0svtG=Mf-lZdnDnO^BFuQfNUy}Vp7Y99Ywa14)~t{g$P^NePi zn3%ja1{_{l5!~3N^6^KZ=XN7e;0?e#cV6uUuvJ!fm?Ek4jfF<&ks?v_7$&GNR^{_G z2bcd~%vUs70($jdNuNGN_~6{ooJL369o&UPLUnf!4sV-Xyf2}EL1GjSxXC=v(D)cP zzca3V%pO#1^r^czER%O)6Q>pBtgA(kby_9cQ~cN$7!iG2fCRbW{))wo?}CAgYH%sf zVBA~0m0PJ*6+705eT4T^a!|4`&t}$#|vo$TpZTs%Wcsv1nbap$0ZkQ=G*WTQ?Qz{(rS+Szq+AdgWA)&MK~JK$2XC zk}MWu0Ff9`q$}optEA%fQDCMJqkA88LMI$s`T!mgC81AR@=GS^|9kVye^2)0$SBwB ziK8BpObZk?WM`Wu1LoGArTY^8n*KIwrT429)+Wo$V)2r`h}tH|qRpZD4sLEy3piAM za#;THk@KrG8kxN>ai*fh)Iwe!CJYv4Tw?D5FG<1ClBSlXeBOJdaN{I^#>;cxUM}2$ zD1R(wb>#88meGuZeHT`S{~Wh^r|Rb?*VKIW-=@F7_4*neT{(xsinMcm(ok;D}ob^ut!dyeYvF+sBrXc_g7@LfG!snBqv*k0;I%)&l&oWQBp?JJ_+Qx z%bk4JYx$K6B`8Gnkilic37EF78pflTcB=Cg8}|GXej5z?uPj#G6URl4!yGi1t!UpC zO6~x540w4JV}FV$2J0cg7(!PTKo>|}V8NdT?fEp_x4vRL!S=6K_NQg*wE&(MrbbDR z=|DMj*F8dJpY;8U-ug%{*+$H{%zKWe&&y2q8lr)f*TgBC3;|HjN~V#Htq{26_lBvVyqHe3*^{|oP6XDjz+?&0W(gCn#RdBf~?RPx<} zyfqb9d>V&E2SG+BpTLrH@Xo7YVndxkQnq5SVmM2Q)W*M1HTBf`i5E2kr;0H9xAjxz#lUDgX8%4mgEuLzrXO~BmFaOz|e4H&2A~* zQJWv-e@^$M-#=f0ghVmaHAB$m1EX7?G8SCS$5NRSLMMUwNC7wFhfn5E1aB{FkH!dq zVd^S)Ui{|l4-XwT9k)XEX#G^ED}~+wOQ4n2?>7#;I(z~(0v`2b&{4p9+HhF-*Liu@ zqdbJt-Ijri`%r2H*nT(whqbpYKXguTZeIxx{sH4{NO?}Ik|I!ZXEh2tZUjyOBrByPSuSoE{Qm)- CdkcvG diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/jsoneditor-min.css b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/jsoneditor-min.css deleted file mode 100644 index 997371f77a6..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/jsoneditor-min.css +++ /dev/null @@ -1 +0,0 @@ -.jsoneditor .field,.jsoneditor .readonly,.jsoneditor .value{border:1px solid transparent;min-height:16px;min-width:32px;padding:2px;margin:1px;word-wrap:break-word;float:left}.jsoneditor .field p,.jsoneditor .value p{margin:0}.jsoneditor .value{word-break:break-word}.jsoneditor .readonly{min-width:16px;color:gray}.jsoneditor .empty{border-color:#d3d3d3;border-style:dashed;border-radius:2px}.jsoneditor .field.empty{background-image:url(img/jsoneditor-icons.png);background-position:0 -144px}.jsoneditor .value.empty{background-image:url(img/jsoneditor-icons.png);background-position:-48px -144px}.jsoneditor .value.url{color:green;text-decoration:underline}.jsoneditor a.value.url:focus,.jsoneditor a.value.url:hover{color:red}.jsoneditor .separator{padding:3px 0;vertical-align:top;color:gray}.jsoneditor .field.highlight,.jsoneditor .field[contenteditable=true]:focus,.jsoneditor .field[contenteditable=true]:hover,.jsoneditor .value.highlight,.jsoneditor .value[contenteditable=true]:focus,.jsoneditor .value[contenteditable=true]:hover{background-color:#FFFFAB;border:1px solid #ff0;border-radius:2px}.jsoneditor .field.highlight-active,.jsoneditor .field.highlight-active:focus,.jsoneditor .field.highlight-active:hover,.jsoneditor .value.highlight-active,.jsoneditor .value.highlight-active:focus,.jsoneditor .value.highlight-active:hover{background-color:#fe0;border:1px solid #ffc700;border-radius:2px}.jsoneditor div.tree button{width:24px;height:24px;padding:0;margin:0;border:0;cursor:pointer;background:transparent url(img/jsoneditor-icons.png)}.jsoneditor div.tree button.collapsed{background-position:0 -48px}.jsoneditor div.tree button.expanded{background-position:0 -72px}.jsoneditor div.tree button.contextmenu{background-position:-48px -72px}.jsoneditor div.tree button.contextmenu.selected,.jsoneditor div.tree button.contextmenu:focus,.jsoneditor div.tree button.contextmenu:hover{background-position:-48px -48px}.jsoneditor div.tree :focus{outline:0}.jsoneditor div.tree button:focus{background-color:#f5f5f5;outline:#e5e5e5 solid 1px}.jsoneditor div.tree button.invisible{visibility:hidden;background:0 0}.jsoneditor{color:#1A1A1A;border:1px solid #97B0F8;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;width:100%;height:100%;overflow:auto;position:relative;padding:0;line-height:100%}.jsoneditor div.tree table.tree{border-collapse:collapse;border-spacing:0;width:100%;margin:0}.jsoneditor div.outer{width:100%;height:100%;margin:-35px 0 0 0;padding:35px 0 0;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;overflow:hidden}.jsoneditor div.tree{width:100%;height:100%;position:relative;overflow:auto}.jsoneditor textarea.text{width:100%;height:100%;margin:0;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;border:0;background-color:#fff;resize:none}.jsoneditor tr.highlight{background-color:#FFFFAB}.jsoneditor div.tree button.dragarea{background:url(img/jsoneditor-icons.png) -72px -72px;cursor:move}.jsoneditor div.tree button.dragarea:focus,.jsoneditor div.tree button.dragarea:hover{background-position:-72px -48px}.jsoneditor td,.jsoneditor th,.jsoneditor tr{padding:0;margin:0}.jsoneditor td,.jsoneditor td.tree{vertical-align:top}.jsoneditor .field,.jsoneditor .value,.jsoneditor td,.jsoneditor textarea,.jsoneditor th{font-family:droid sans mono,monospace,courier new,courier,sans-serif;font-size:10pt;color:#1A1A1A}.jsoneditor-contextmenu{position:absolute;z-index:99999}.jsoneditor-contextmenu ul{position:relative;left:0;top:0;width:124px;background:#fff;border:1px solid #d3d3d3;box-shadow:2px 2px 12px rgba(128,128,128,.3);list-style:none;margin:0;padding:0}.jsoneditor-contextmenu ul li button{padding:0;margin:0;width:124px;height:24px;border:0;cursor:pointer;color:#4d4d4d;background:0 0;line-height:26px;text-align:left}.jsoneditor-contextmenu ul li button::-moz-focus-inner{padding:0;border:0}.jsoneditor-contextmenu ul li button:focus,.jsoneditor-contextmenu ul li button:hover{color:#1a1a1a;background-color:#f5f5f5;outline:0}.jsoneditor-contextmenu ul li button.default{width:92px}.jsoneditor-contextmenu ul li button.expand{float:right;width:32px;height:24px;border-left:1px solid #e5e5e5}.jsoneditor-contextmenu div.icon{float:left;width:24px;height:24px;border:0;padding:0;margin:0;background-image:url(img/jsoneditor-icons.png)}.jsoneditor-contextmenu ul li button div.expand{float:right;width:24px;height:24px;padding:0;margin:0 4px 0 0;background:url(img/jsoneditor-icons.png) 0 -72px;opacity:.4}.jsoneditor-contextmenu ul li button.expand:focus div.expand,.jsoneditor-contextmenu ul li button.expand:hover div.expand,.jsoneditor-contextmenu ul li button:focus div.expand,.jsoneditor-contextmenu ul li button:hover div.expand,.jsoneditor-contextmenu ul li.selected div.expand{opacity:1}.jsoneditor-contextmenu .separator{height:0;border-top:1px solid #e5e5e5;padding-top:5px;margin-top:5px}.jsoneditor-contextmenu button.remove>.icon{background-position:-24px -24px}.jsoneditor-contextmenu button.remove:focus>.icon,.jsoneditor-contextmenu button.remove:hover>.icon{background-position:-24px 0}.jsoneditor-contextmenu button.append>.icon{background-position:0 -24px}.jsoneditor-contextmenu button.append:focus>.icon,.jsoneditor-contextmenu button.append:hover>.icon{background-position:0 0}.jsoneditor-contextmenu button.insert>.icon{background-position:0 -24px}.jsoneditor-contextmenu button.insert:focus>.icon,.jsoneditor-contextmenu button.insert:hover>.icon{background-position:0 0}.jsoneditor-contextmenu button.duplicate>.icon{background-position:-48px -24px}.jsoneditor-contextmenu button.duplicate:focus>.icon,.jsoneditor-contextmenu button.duplicate:hover>.icon{background-position:-48px 0}.jsoneditor-contextmenu button.sort-asc>.icon{background-position:-168px -24px}.jsoneditor-contextmenu button.sort-asc:focus>.icon,.jsoneditor-contextmenu button.sort-asc:hover>.icon{background-position:-168px 0}.jsoneditor-contextmenu button.sort-desc>.icon{background-position:-192px -24px}.jsoneditor-contextmenu button.sort-desc:focus>.icon,.jsoneditor-contextmenu button.sort-desc:hover>.icon{background-position:-192px 0}.jsoneditor-contextmenu ul li .selected{background-color:#D5DDF6}.jsoneditor-contextmenu ul li{overflow:hidden}.jsoneditor-contextmenu ul li ul{display:none;position:relative;left:-10px;top:0;border:0;box-shadow:inset 0 0 10px rgba(128,128,128,.5);padding:0 10px;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.jsoneditor-contextmenu ul li ul li button{padding-left:24px}.jsoneditor-contextmenu ul li ul li button:focus,.jsoneditor-contextmenu ul li ul li button:hover{background-color:#f5f5f5}.jsoneditor-contextmenu button.type-string>.icon{background-position:-144px -24px}.jsoneditor-contextmenu button.type-string.selected>.icon,.jsoneditor-contextmenu button.type-string:focus>.icon,.jsoneditor-contextmenu button.type-string:hover>.icon{background-position:-144px 0}.jsoneditor-contextmenu button.type-auto>.icon{background-position:-120px -24px}.jsoneditor-contextmenu button.type-auto.selected>.icon,.jsoneditor-contextmenu button.type-auto:focus>.icon,.jsoneditor-contextmenu button.type-auto:hover>.icon{background-position:-120px 0}.jsoneditor-contextmenu button.type-object>.icon{background-position:-72px -24px}.jsoneditor-contextmenu button.type-object.selected>.icon,.jsoneditor-contextmenu button.type-object:focus>.icon,.jsoneditor-contextmenu button.type-object:hover>.icon{background-position:-72px 0}.jsoneditor-contextmenu button.type-array>.icon{background-position:-96px -24px}.jsoneditor-contextmenu button.type-array.selected>.icon,.jsoneditor-contextmenu button.type-array:focus>.icon,.jsoneditor-contextmenu button.type-array:hover>.icon{background-position:-96px 0}.jsoneditor-contextmenu button.type-modes>.icon{background-image:none;width:6px}.jsoneditor .menu{width:100%;height:35px;padding:2px;margin:0;overflow:hidden;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;color:#1A1A1A;background-color:#D5DDF6;border-bottom:1px solid #97B0F8}.jsoneditor .menu button{width:26px;height:26px;margin:2px;padding:0;border-radius:2px;border:1px solid #aec0f8;background:#e3eaf6 url(img/jsoneditor-icons.png);color:#4D4D4D;opacity:.8;font-family:arial,sans-serif;font-size:10pt;float:left}.jsoneditor .menu button:hover{background-color:#f0f2f5}.jsoneditor .menu button:active{background-color:#fff}.jsoneditor .menu button:disabled{background-color:#e3eaf6}.jsoneditor .menu button.collapse-all{background-position:0 -96px}.jsoneditor .menu button.expand-all{background-position:0 -120px}.jsoneditor .menu button.undo{background-position:-24px -96px}.jsoneditor .menu button.undo:disabled{background-position:-24px -120px}.jsoneditor .menu button.redo{background-position:-48px -96px}.jsoneditor .menu button.redo:disabled{background-position:-48px -120px}.jsoneditor .menu button.compact{background-position:-72px -96px}.jsoneditor .menu button.format{background-position:-72px -120px}.jsoneditor .menu button.modes{background-image:none;width:auto;padding-left:6px;padding-right:6px}.jsoneditor .menu button.separator{margin-left:10px}.jsoneditor .menu a{font-family:arial,sans-serif;font-size:10pt;color:#97B0F8;vertical-align:middle}.jsoneditor .menu a:hover{color:red}.jsoneditor .menu a.poweredBy{font-size:8pt;position:absolute;right:0;top:0;padding:10px}.jsoneditor .search .results,.jsoneditor .search input{font-family:arial,sans-serif;font-size:10pt;color:#1A1A1A}.jsoneditor .search{position:absolute;right:2px;top:2px}.jsoneditor .search .frame{border:1px solid #97B0F8;background-color:#fff;padding:0 2px;margin:0}.jsoneditor .search .frame table{border-collapse:collapse}.jsoneditor .search input{width:120px;border:0;outline:0;margin:1px}.jsoneditor .search .results{color:#4d4d4d;padding-right:5px;line-height:24px}.jsoneditor .search button{width:16px;height:24px;padding:0;margin:0;border:0;background:url(img/jsoneditor-icons.png);vertical-align:top}.jsoneditor .search button:hover{background-color:transparent}.jsoneditor .search button.refresh{width:18px;background-position:-99px -73px}.jsoneditor .search button.next{cursor:pointer;background-position:-124px -73px}.jsoneditor .search button.next:hover{background-position:-124px -49px}.jsoneditor .search button.previous{cursor:pointer;background-position:-148px -73px;margin-right:2px}.jsoneditor .search button.previous:hover{background-position:-148px -49px} \ No newline at end of file diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/jsoneditor-min.js b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/jsoneditor-min.js deleted file mode 100644 index b20da71614e..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/jsoneditor-min.js +++ /dev/null @@ -1,34 +0,0 @@ -/*! - * jsoneditor.js - * - * @brief - * JSONEditor is a web-based tool to view, edit, and format JSON. - * It shows data a clear, editable treeview. - * - * Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+ - * - * @license - * This json editor is open sourced with the intention to use the editor as - * a component in your own application. Not to just copy and monetize the editor - * as it is. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy - * of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - * Copyright (c) 2011-2013 Jos de Jong, http://jsoneditoronline.org - * - * @author Jos de Jong, - * @version 2.3.6 - * @date 2014-01-03 - */ -!function(){function e(t,i,o){if(!(this instanceof e))throw new Error('JSONEditor constructor called without "new".');var n=util.getInternetExplorerVersion();if(-1!=n&&9>n)throw new Error("Unsupported browser, IE9 or newer required. Please install the newest version of your browser.");arguments.length&&this._create(t,i,o)}function t(e,i,o){if(!(this instanceof t))throw new Error('TreeEditor constructor called without "new".');this._create(e,i,o)}function i(e,t,o){if(!(this instanceof i))throw new Error('TextEditor constructor called without "new".');this._create(e,t,o)}function o(e,t){this.editor=e,this.dom={},this.expanded=!1,t&&t instanceof Object?(this.setField(t.field,t.fieldEditable),this.setValue(t.value,t.type)):(this.setField(""),this.setValue(null))}function n(e){this.editor=e,this.dom={}}function s(e,t){function i(e,t,n){n.forEach(function(n){if("separator"==n.type){var s=document.createElement("div");s.className="separator",a=document.createElement("li"),a.appendChild(s),e.appendChild(a)}else{var r={},a=document.createElement("li");e.appendChild(a);var l=document.createElement("button");if(l.className=n.className,r.button=l,n.title&&(l.title=n.title),n.click&&(l.onclick=function(){o.hide(),n.click()}),a.appendChild(l),n.submenu){var d=document.createElement("div");d.className="icon",l.appendChild(d),l.appendChild(document.createTextNode(n.text));var h;if(n.click){l.className+=" default";var c=document.createElement("button");r.buttonExpand=c,c.className="expand",c.innerHTML='
',a.appendChild(c),n.submenuTitle&&(c.title=n.submenuTitle),h=c}else{var u=document.createElement("div");u.className="expand",l.appendChild(u),h=l}h.onclick=function(){o._onExpandItem(r),h.focus()};var p=[];r.subItems=p;var m=document.createElement("ul");r.ul=m,m.className="menu",m.style.height="0",a.appendChild(m),i(m,p,n.submenu)}else l.innerHTML='
'+n.text;t.push(r)}})}this.dom={};var o=this,n=this.dom;this.anchor=void 0,this.items=e,this.eventListeners={},this.selection=void 0,this.visibleSubmenu=void 0,this.onClose=t?t.close:void 0;var s=document.createElement("div");s.className="jsoneditor-contextmenu",n.menu=s;var r=document.createElement("ul");r.className="menu",s.appendChild(r),n.list=r,n.items=[];var a=document.createElement("button");n.focusButton=a;var l=document.createElement("li");l.style.overflow="hidden",l.style.height="0",l.appendChild(a),r.appendChild(l),i(r,this.dom.items,e),this.maxHeight=0,e.forEach(function(t){var i=24*(e.length+(t.submenu?t.submenu.length:0));o.maxHeight=Math.max(o.maxHeight,i)})}function r(e){this.editor=e,this.clear(),this.actions={editField:{undo:function(e){e.node.updateField(e.oldValue)},redo:function(e){e.node.updateField(e.newValue)}},editValue:{undo:function(e){e.node.updateValue(e.oldValue)},redo:function(e){e.node.updateValue(e.newValue)}},appendNode:{undo:function(e){e.parent.removeChild(e.node)},redo:function(e){e.parent.appendChild(e.node)}},insertBeforeNode:{undo:function(e){e.parent.removeChild(e.node)},redo:function(e){e.parent.insertBefore(e.node,e.beforeNode)}},insertAfterNode:{undo:function(e){e.parent.removeChild(e.node)},redo:function(e){e.parent.insertAfter(e.node,e.afterNode)}},removeNode:{undo:function(e){var t=e.parent,i=t.childs[e.index]||t.append;t.insertBefore(e.node,i)},redo:function(e){e.parent.removeChild(e.node)}},duplicateNode:{undo:function(e){e.parent.removeChild(e.clone)},redo:function(e){e.parent.insertAfter(e.clone,e.node)}},changeType:{undo:function(e){e.node.changeType(e.oldType)},redo:function(e){e.node.changeType(e.newType)}},moveNode:{undo:function(e){e.startParent.moveTo(e.node,e.startIndex)},redo:function(e){e.endParent.moveTo(e.node,e.endIndex)}},sort:{undo:function(e){var t=e.node;t.hideChilds(),t.sort=e.oldSort,t.childs=e.oldChilds,t.showChilds()},redo:function(e){var t=e.node;t.hideChilds(),t.sort=e.newSort,t.childs=e.newChilds,t.showChilds()}}}}function a(e,t,i){function o(t){e.setMode(t);var i=e.dom&&e.dom.modeBox;i&&i.focus()}for(var n={code:{text:"Code",title:"Switch to code highlighter",click:function(){o("code")}},form:{text:"Form",title:"Switch to form editor",click:function(){o("form")}},text:{text:"Text",title:"Switch to plain text editor",click:function(){o("text")}},tree:{text:"Tree",title:"Switch to tree editor",click:function(){o("tree")}},view:{text:"View",title:"Switch to tree view",click:function(){o("view")}}},r=[],a=0;ae&&i.scrollTop>0?(o+r-e)/3:e>s-r&&n+i.scrollTop3?(i.scrollTop+=n/3,o.animateCallback=t,o.animateTimeout=setTimeout(a,50)):(t&&t(!0),i.scrollTop=r,delete o.animateTimeout,delete o.animateCallback)};a()}else t&&t(!1)},t.prototype._createFrame=function(){this.frame=document.createElement("div"),this.frame.className="jsoneditor",this.container.appendChild(this.frame);var e=this,t=function(t){e._onEvent(t)};this.frame.onclick=function(e){var i=e.target;t(e),"BUTTON"==i.nodeName&&e.preventDefault()},this.frame.oninput=t,this.frame.onchange=t,this.frame.onkeydown=t,this.frame.onkeyup=t,this.frame.oncut=t,this.frame.onpaste=t,this.frame.onmousedown=t,this.frame.onmouseup=t,this.frame.onmouseover=t,this.frame.onmouseout=t,util.addEventListener(this.frame,"focus",t,!0),util.addEventListener(this.frame,"blur",t,!0),this.frame.onfocusin=t,this.frame.onfocusout=t,this.menu=document.createElement("div"),this.menu.className="menu",this.frame.appendChild(this.menu);var i=document.createElement("button");i.className="expand-all",i.title="Expand all fields",i.onclick=function(){e.expandAll()},this.menu.appendChild(i);var o=document.createElement("button");if(o.title="Collapse all fields",o.className="collapse-all",o.onclick=function(){e.collapseAll()},this.menu.appendChild(o),this.history){var n=document.createElement("button");n.className="undo separator",n.title="Undo last action (Ctrl+Z)",n.onclick=function(){e._onUndo()},this.menu.appendChild(n),this.dom.undo=n;var s=document.createElement("button");s.className="redo",s.title="Redo (Ctrl+Shift+Z)",s.onclick=function(){e._onRedo()},this.menu.appendChild(s),this.dom.redo=s,this.history.onChange=function(){n.disabled=!e.history.canUndo(),s.disabled=!e.history.canRedo()},this.history.onChange()}if(this.options&&this.options.modes&&this.options.modes.length){var r=a(this,this.options.modes,this.options.mode);this.menu.appendChild(r),this.dom.modeBox=r}this.options.search&&(this.searchBox=new l(this,this.menu))},t.prototype._onUndo=function(){this.history&&(this.history.undo(),this.options.change&&this.options.change())},t.prototype._onRedo=function(){this.history&&(this.history.redo(),this.options.change&&this.options.change())},t.prototype._onEvent=function(e){var i=e.target;"keydown"==e.type&&this._onKeyDown(e),"focus"==e.type&&(t.domFocus=i);var n=o.getNodeFromTarget(i);n&&n.onEvent(e)},t.prototype._onKeyDown=function(e){var i=e.which||e.keyCode,o=e.ctrlKey,n=e.shiftKey,s=!1;if(9==i&&setTimeout(function(){util.selectContentEditable(t.domFocus)},0),this.searchBox)if(o&&70==i)this.searchBox.dom.search.focus(),this.searchBox.dom.search.select(),s=!0;else if(114==i||o&&71==i){var r=!0;n?this.searchBox.previous(r):this.searchBox.next(r),s=!0}this.history&&(o&&!n&&90==i?(this._onUndo(),s=!0):o&&n&&90==i&&(this._onRedo(),s=!0)),s&&(e.preventDefault(),e.stopPropagation())},t.prototype._createTable=function(){var e=document.createElement("div");e.className="outer",this.contentOuter=e,this.content=document.createElement("div"),this.content.className="tree",e.appendChild(this.content),this.table=document.createElement("table"),this.table.className="tree",this.content.appendChild(this.table);var t;this.colgroupContent=document.createElement("colgroup"),this.mode.edit&&(t=document.createElement("col"),t.width="24px",this.colgroupContent.appendChild(t)),t=document.createElement("col"),t.width="24px",this.colgroupContent.appendChild(t),t=document.createElement("col"),this.colgroupContent.appendChild(t),this.table.appendChild(this.colgroupContent),this.tbody=document.createElement("tbody"),this.table.appendChild(this.tbody),this.frame.appendChild(e)},e.modes.tree={editor:t,data:"json"},e.modes.view={editor:t,data:"json"},e.modes.form={editor:t,data:"json"},e.modes.editor={editor:t,data:"json"},e.modes.viewer={editor:t,data:"json"},i.prototype._create=function(e,t,i){t=t||{},this.options=t,this.indentation=t.indentation?Number(t.indentation):2,this.mode="code"==t.mode?"code":"text","code"==this.mode&&"undefined"==typeof ace&&(this.mode="text",util.log("WARNING: Cannot load code editor, Ace library not loaded. Falling back to plain text editor"));var o=this;this.container=e,this.dom={},this.editor=void 0,this.textarea=void 0,this.width=e.clientWidth,this.height=e.clientHeight,this.frame=document.createElement("div"),this.frame.className="jsoneditor",this.frame.onclick=function(e){e.preventDefault()},this.menu=document.createElement("div"),this.menu.className="menu",this.frame.appendChild(this.menu);var n=document.createElement("button");n.className="format",n.title="Format JSON data, with proper indentation and line feeds",this.menu.appendChild(n),n.onclick=function(){try{o.format()}catch(e){o._onError(e)}};var s=document.createElement("button");if(s.className="compact",s.title="Compact JSON data, remove all whitespaces",this.menu.appendChild(s),s.onclick=function(){try{o.compact()}catch(e){o._onError(e)}},this.options&&this.options.modes&&this.options.modes.length){var r=a(this,this.options.modes,this.options.mode);this.menu.appendChild(r),this.dom.modeBox=r}if(this.content=document.createElement("div"),this.content.className="outer",this.frame.appendChild(this.content),this.container.appendChild(this.frame),"code"==this.mode){this.editorDom=document.createElement("div"),this.editorDom.style.height="100%",this.editorDom.style.width="100%",this.content.appendChild(this.editorDom);var l=ace.edit(this.editorDom);l.setTheme("ace/theme/jsoneditor"),l.setShowPrintMargin(!1),l.setFontSize(13),l.getSession().setMode("ace/mode/json"),l.getSession().setUseSoftTabs(!0),l.getSession().setUseWrapMode(!0),this.editor=l;var d=document.createElement("a");d.appendChild(document.createTextNode("powered by ace")),d.href="http://ace.ajax.org",d.target="_blank",d.className="poweredBy",d.onclick=function(){window.open(d.href,d.target)},this.menu.appendChild(d),t.change&&l.on("change",function(){t.change()})}else{var h=document.createElement("textarea");h.className="text",h.spellcheck=!1,this.content.appendChild(h),this.textarea=h,t.change&&(null===this.textarea.oninput?this.textarea.oninput=function(){t.change()}:this.textarea.onchange=function(){t.change()})}"string"==typeof i?this.setText(i):this.set(i)},i.prototype._delete=function(){this.frame&&this.container&&this.frame.parentNode==this.container&&this.container.removeChild(this.frame)},i.prototype._onError=function(e){if("function"==typeof this.onError&&(util.log("WARNING: JSONEditor.onError is deprecated. Use options.error instead."),this.onError(e)),!this.options||"function"!=typeof this.options.error)throw e;this.options.error(e)},i.prototype.compact=function(){var e=util.parse(this.getText());this.setText(JSON.stringify(e))},i.prototype.format=function(){var e=util.parse(this.getText());this.setText(JSON.stringify(e,null,this.indentation))},i.prototype.focus=function(){this.textarea&&this.textarea.focus(),this.editor&&this.editor.focus()},i.prototype.resize=function(){if(this.editor){var e=!1;this.editor.resize(e)}},i.prototype.set=function(e){this.setText(JSON.stringify(e,null,this.indentation))},i.prototype.get=function(){return util.parse(this.getText())},i.prototype.getText=function(){return this.textarea?this.textarea.value:this.editor?this.editor.getValue():""},i.prototype.setText=function(e){this.textarea&&(this.textarea.value=e),this.editor&&this.editor.setValue(e,-1)},e.modes.text={editor:i,data:"text",load:i.prototype.format},e.modes.code={editor:i,data:"text",load:i.prototype.format},o.prototype.setParent=function(e){this.parent=e},o.prototype.setField=function(e,t){this.field=e,this.fieldEditable=1==t},o.prototype.getField=function(){return void 0===this.field&&this._getDomField(),this.field},o.prototype.setValue=function(e,t){var i,n,s=this.childs;if(s)for(;s.length;)this.removeChild(s[0]);if(this.type=this._getType(e),t&&t!=this.type){if("string"!=t||"auto"!=this.type)throw new Error('Type mismatch: cannot cast value of type "'+this.type+' to the specified type "'+t+'"');this.type=t}if("array"==this.type){this.childs=[];for(var r=0,a=e.length;a>r;r++)i=e[r],void 0===i||i instanceof Function||(n=new o(this.editor,{value:i}),this.appendChild(n));this.value=""}else if("object"==this.type){this.childs=[];for(var l in e)e.hasOwnProperty(l)&&(i=e[l],void 0===i||i instanceof Function||(n=new o(this.editor,{field:l,value:i}),this.appendChild(n)));this.value=""}else this.childs=void 0,this.value=e},o.prototype.getValue=function(){if("array"==this.type){var e=[];return this.childs.forEach(function(t){e.push(t.getValue())}),e}if("object"==this.type){var t={};return this.childs.forEach(function(e){t[e.getField()]=e.getValue()}),t}return void 0===this.value&&this._getDomValue(),this.value},o.prototype.getLevel=function(){return this.parent?this.parent.getLevel()+1:0},o.prototype.clone=function(){var e=new o(this.editor);if(e.type=this.type,e.field=this.field,e.fieldInnerText=this.fieldInnerText,e.fieldEditable=this.fieldEditable,e.value=this.value,e.valueInnerText=this.valueInnerText,e.expanded=this.expanded,this.childs){var t=[];this.childs.forEach(function(i){var o=i.clone();o.setParent(e),t.push(o)}),e.childs=t}else e.childs=void 0;return e},o.prototype.expand=function(e){this.childs&&(this.expanded=!0,this.dom.expand&&(this.dom.expand.className="expanded"),this.showChilds(),0!=e&&this.childs.forEach(function(t){t.expand(e)}))},o.prototype.collapse=function(e){this.childs&&(this.hideChilds(),0!=e&&this.childs.forEach(function(t){t.collapse(e)}),this.dom.expand&&(this.dom.expand.className="collapsed"),this.expanded=!1)},o.prototype.showChilds=function(){var e=this.childs;if(e&&this.expanded){var t=this.dom.tr,i=t?t.parentNode:void 0;if(i){var o=this.getAppend(),n=t.nextSibling;n?i.insertBefore(o,n):i.appendChild(o),this.childs.forEach(function(e){i.insertBefore(e.getDom(),o),e.showChilds()})}}},o.prototype.hide=function(){var e=this.dom.tr,t=e?e.parentNode:void 0;t&&t.removeChild(e),this.hideChilds()},o.prototype.hideChilds=function(){var e=this.childs;if(e&&this.expanded){var t=this.getAppend();t.parentNode&&t.parentNode.removeChild(t),this.childs.forEach(function(e){e.hide()})}},o.prototype.appendChild=function(e){if(this._hasChilds()){if(e.setParent(this),e.fieldEditable="object"==this.type,"array"==this.type&&(e.index=this.childs.length),this.childs.push(e),this.expanded){var t=e.getDom(),i=this.getAppend(),o=i?i.parentNode:void 0;i&&o&&o.insertBefore(t,i),e.showChilds()}this.updateDom({updateIndexes:!0}),e.updateDom({recurse:!0})}},o.prototype.moveBefore=function(e,t){if(this._hasChilds()){var i=this.dom.tr?this.dom.tr.parentNode:void 0;if(i){var o=document.createElement("tr");o.style.height=i.clientHeight+"px",i.appendChild(o)}e.parent&&e.parent.removeChild(e),t instanceof n?this.appendChild(e):this.insertBefore(e,t),i&&i.removeChild(o)}},o.prototype.moveTo=function(e,t){if(e.parent==this){var i=this.childs.indexOf(e);t>i&&t++}var o=this.childs[t]||this.append;this.moveBefore(e,o)},o.prototype.insertBefore=function(e,t){if(this._hasChilds()){if(t==this.append)e.setParent(this),e.fieldEditable="object"==this.type,this.childs.push(e);else{var i=this.childs.indexOf(t);if(-1==i)throw new Error("Node not found");e.setParent(this),e.fieldEditable="object"==this.type,this.childs.splice(i,0,e)}if(this.expanded){var o=e.getDom(),n=t.getDom(),s=n?n.parentNode:void 0;n&&s&&s.insertBefore(o,n),e.showChilds()}this.updateDom({updateIndexes:!0}),e.updateDom({recurse:!0})}},o.prototype.insertAfter=function(e,t){if(this._hasChilds()){var i=this.childs.indexOf(t),o=this.childs[i+1];o?this.insertBefore(e,o):this.appendChild(e)}},o.prototype.search=function(e){var t,i=[],o=e?e.toLowerCase():void 0;if(delete this.searchField,delete this.searchValue,void 0!=this.field){var n=String(this.field).toLowerCase();t=n.indexOf(o),-1!=t&&(this.searchField=!0,i.push({node:this,elem:"field"})),this._updateDomField()}if(this._hasChilds()){if(this.childs){var s=[];this.childs.forEach(function(t){s=s.concat(t.search(e))}),i=i.concat(s)}if(void 0!=o){var r=!1;0==s.length?this.collapse(r):this.expand(r)}}else{if(void 0!=this.value){var a=String(this.value).toLowerCase();t=a.indexOf(o),-1!=t&&(this.searchValue=!0,i.push({node:this,elem:"value"}))}this._updateDomValue()}return i},o.prototype.scrollTo=function(e){if(!this.dom.tr||!this.dom.tr.parentNode)for(var t=this.parent,i=!1;t;)t.expand(i),t=t.parent;this.dom.tr&&this.dom.tr.parentNode&&this.editor.scrollTo(this.dom.tr.offsetTop,e)},o.focusElement=void 0,o.prototype.focus=function(e){if(o.focusElement=e,this.dom.tr&&this.dom.tr.parentNode){var t=this.dom;switch(e){case"drag":t.drag?t.drag.focus():t.menu.focus();break;case"menu":t.menu.focus();break;case"expand":this._hasChilds()?t.expand.focus():t.field&&this.fieldEditable?(t.field.focus(),util.selectContentEditable(t.field)):t.value&&!this._hasChilds()?(t.value.focus(),util.selectContentEditable(t.value)):t.menu.focus();break;case"field":t.field&&this.fieldEditable?(t.field.focus(),util.selectContentEditable(t.field)):t.value&&!this._hasChilds()?(t.value.focus(),util.selectContentEditable(t.value)):this._hasChilds()?t.expand.focus():t.menu.focus();break;case"value":default:t.value&&!this._hasChilds()?(t.value.focus(),util.selectContentEditable(t.value)):t.field&&this.fieldEditable?(t.field.focus(),util.selectContentEditable(t.field)):this._hasChilds()?t.expand.focus():t.menu.focus()}}},o.select=function(e){setTimeout(function(){util.selectContentEditable(e)},0)},o.prototype.blur=function(){this._getDomValue(!1),this._getDomField(!1)},o.prototype._duplicate=function(e){var t=e.clone();return this.insertAfter(t,e),t},o.prototype.containsNode=function(e){if(this==e)return!0;var t=this.childs;if(t)for(var i=0,o=t.length;o>i;i++)if(t[i].containsNode(e))return!0;return!1},o.prototype._move=function(e,t){if(e!=t){if(e.containsNode(this))throw new Error("Cannot move a field into a child of itself");e.parent&&e.parent.removeChild(e);var i=e.clone();e.clearDom(),t?this.insertBefore(i,t):this.appendChild(i)}},o.prototype.removeChild=function(e){if(this.childs){var t=this.childs.indexOf(e);if(-1!=t){e.hide(),delete e.searchField,delete e.searchValue;var i=this.childs.splice(t,1)[0];return this.updateDom({updateIndexes:!0}),i}}return void 0},o.prototype._remove=function(e){this.removeChild(e)},o.prototype.changeType=function(e){var t=this.type;if(t!=e){if("string"!=e&&"auto"!=e||"string"!=t&&"auto"!=t){var i,o=this.dom.tr?this.dom.tr.parentNode:void 0;i=this.expanded?this.getAppend():this.getDom();var n=i&&i.parentNode?i.nextSibling:void 0;this.hide(),this.clearDom(),this.type=e,"object"==e?(this.childs||(this.childs=[]),this.childs.forEach(function(e){e.clearDom(),delete e.index,e.fieldEditable=!0,void 0==e.field&&(e.field="")}),("string"==t||"auto"==t)&&(this.expanded=!0)):"array"==e?(this.childs||(this.childs=[]),this.childs.forEach(function(e,t){e.clearDom(),e.fieldEditable=!1,e.index=t}),("string"==t||"auto"==t)&&(this.expanded=!0)):this.expanded=!1,o&&(n?o.insertBefore(this.getDom(),n):o.appendChild(this.getDom())),this.showChilds()}else this.type=e;("auto"==e||"string"==e)&&(this.value="string"==e?String(this.value):this._stringCast(String(this.value)),this.focus()),this.updateDom({updateIndexes:!0})}},o.prototype._getDomValue=function(e){if(this.dom.value&&"array"!=this.type&&"object"!=this.type&&(this.valueInnerText=util.getInnerText(this.dom.value)),void 0!=this.valueInnerText)try{var t;if("string"==this.type)t=this._unescapeHTML(this.valueInnerText);else{var i=this._unescapeHTML(this.valueInnerText);t=this._stringCast(i)}if(t!==this.value){var o=this.value;this.value=t,this.editor._onAction("editValue",{node:this,oldValue:o,newValue:t,oldSelection:this.editor.selection,newSelection:this.editor.getSelection()})}}catch(n){if(this.value=void 0,1!=e)throw n}},o.prototype._updateDomValue=function(){var e=this.dom.value;if(e){var t=this.value,i="auto"==this.type?util.type(t):this.type,o="string"==i&&util.isUrl(t),n="";n=o&&!this.editor.mode.edit?"":"string"==i?"green":"number"==i?"red":"boolean"==i?"darkorange":this._hasChilds()?"":null===t?"#004ED0":"black",e.style.color=n;var s=""==String(this.value)&&"array"!=this.type&&"object"!=this.type;if(s?util.addClassName(e,"empty"):util.removeClassName(e,"empty"),o?util.addClassName(e,"url"):util.removeClassName(e,"url"),"array"==i||"object"==i){var r=this.childs?this.childs.length:0;e.title=this.type+" containing "+r+" items"}else"string"==i&&util.isUrl(t)?this.editor.mode.edit&&(e.title="Ctrl+Click or Ctrl+Enter to open url in new window"):e.title="";this.searchValueActive?util.addClassName(e,"highlight-active"):util.removeClassName(e,"highlight-active"),this.searchValue?util.addClassName(e,"highlight"):util.removeClassName(e,"highlight"),util.stripFormatting(e)}},o.prototype._updateDomField=function(){var e=this.dom.field;if(e){var t=""==String(this.field)&&"array"!=this.parent.type;t?util.addClassName(e,"empty"):util.removeClassName(e,"empty"),this.searchFieldActive?util.addClassName(e,"highlight-active"):util.removeClassName(e,"highlight-active"),this.searchField?util.addClassName(e,"highlight"):util.removeClassName(e,"highlight"),util.stripFormatting(e)}},o.prototype._getDomField=function(e){if(this.dom.field&&this.fieldEditable&&(this.fieldInnerText=util.getInnerText(this.dom.field)),void 0!=this.fieldInnerText)try{var t=this._unescapeHTML(this.fieldInnerText);if(t!==this.field){var i=this.field;this.field=t,this.editor._onAction("editField",{node:this,oldValue:i,newValue:t,oldSelection:this.editor.selection,newSelection:this.editor.getSelection()})}}catch(o){if(this.field=void 0,1!=e)throw o}},o.prototype.clearDom=function(){this.dom={}},o.prototype.getDom=function(){var e=this.dom;if(e.tr)return e.tr;if(e.tr=document.createElement("tr"),e.tr.node=this,this.editor.mode.edit){var t=document.createElement("td");if(this.parent){var i=document.createElement("button");e.drag=i,i.className="dragarea",i.title="Drag to move this field (Alt+Shift+Arrows)",t.appendChild(i)}e.tr.appendChild(t);var o=document.createElement("td"),n=document.createElement("button");e.menu=n,n.className="contextmenu",n.title="Click to open the actions menu (Ctrl+M)",o.appendChild(e.menu),e.tr.appendChild(o)}var s=document.createElement("td");return e.tr.appendChild(s),e.tree=this._createDomTree(),s.appendChild(e.tree),this.updateDom({updateIndexes:!0}),e.tr},o.prototype._onDragStart=function(e){var t=this;this.mousemove||(this.mousemove=util.addEventListener(document,"mousemove",function(e){t._onDrag(e)})),this.mouseup||(this.mouseup=util.addEventListener(document,"mouseup",function(e){t._onDragEnd(e)})),this.editor.highlighter.lock(),this.drag={oldCursor:document.body.style.cursor,startParent:this.parent,startIndex:this.parent.childs.indexOf(this),mouseX:e.pageX,level:this.getLevel()},document.body.style.cursor="move",e.preventDefault()},o.prototype._onDrag=function(e){var t,i,s,r,a,l,d,h,c,u,p,m,f,v,g=e.pageY,y=e.pageX,x=!1;if(t=this.dom.tr,c=util.getAbsoluteTop(t),m=t.offsetHeight,c>g){i=t;do i=i.previousSibling,d=o.getNodeFromTarget(i),u=i?util.getAbsoluteTop(i):0;while(i&&u>g);d&&!d.parent&&(d=void 0),d||(l=t.parentNode.firstChild,i=l?l.nextSibling:void 0,d=o.getNodeFromTarget(i),d==this&&(d=void 0)),d&&(i=d.dom.tr,u=i?util.getAbsoluteTop(i):0,g>u+m&&(d=void 0)),d&&(d.parent.moveBefore(this,d),x=!0)}else if(a=this.expanded&&this.append?this.append.getDom():this.dom.tr,r=a?a.nextSibling:void 0){p=util.getAbsoluteTop(r),s=r;do h=o.getNodeFromTarget(s),s&&(f=s.nextSibling?util.getAbsoluteTop(s.nextSibling):0,v=s?f-p:0,1==h.parent.childs.length&&h.parent.childs[0]==this&&(c+=23)),s=s.nextSibling;while(s&&g>c+v);if(h&&h.parent){var C=y-this.drag.mouseX,b=Math.round(C/24/2),N=this.drag.level+b,E=h.getLevel();for(i=h.dom.tr.previousSibling;N>E&&i;){if(d=o.getNodeFromTarget(i),d==this||d._isChildOf(this));else{if(!(d instanceof n))break;var _=d.parent.childs;if(!(_.length>1||1==_.length&&_[0]!=this))break;h=o.getNodeFromTarget(i),E=h.getLevel()}i=i.previousSibling}a.nextSibling!=h.dom.tr&&(h.parent.moveBefore(this,h),x=!0) -}}x&&(this.drag.mouseX=y,this.drag.level=this.getLevel()),this.editor.startAutoScroll(g),e.preventDefault()},o.prototype._onDragEnd=function(e){var t={node:this,startParent:this.drag.startParent,startIndex:this.drag.startIndex,endParent:this.parent,endIndex:this.parent.childs.indexOf(this)};(t.startParent!=t.endParent||t.startIndex!=t.endIndex)&&this.editor._onAction("moveNode",t),document.body.style.cursor=this.drag.oldCursor,this.editor.highlighter.unlock(),delete this.drag,this.mousemove&&(util.removeEventListener(document,"mousemove",this.mousemove),delete this.mousemove),this.mouseup&&(util.removeEventListener(document,"mouseup",this.mouseup),delete this.mouseup),this.editor.stopAutoScroll(),e.preventDefault()},o.prototype._isChildOf=function(e){for(var t=this.parent;t;){if(t==e)return!0;t=t.parent}return!1},o.prototype._createDomField=function(){return document.createElement("div")},o.prototype.setHighlight=function(e){this.dom.tr&&(this.dom.tr.className=e?"highlight":"",this.append&&this.append.setHighlight(e),this.childs&&this.childs.forEach(function(t){t.setHighlight(e)}))},o.prototype.updateValue=function(e){this.value=e,this.updateDom()},o.prototype.updateField=function(e){this.field=e,this.updateDom()},o.prototype.updateDom=function(e){var t=this.dom.tree;t&&(t.style.marginLeft=24*this.getLevel()+"px");var i=this.dom.field;if(i){1==this.fieldEditable?(i.contentEditable=this.editor.mode.edit,i.spellcheck=!1,i.className="field"):i.className="readonly";var o;o=void 0!=this.index?this.index:void 0!=this.field?this.field:this._hasChilds()?this.type:"",i.innerHTML=this._escapeHTML(o)}var n=this.dom.value;if(n){var s=this.childs?this.childs.length:0;n.innerHTML="array"==this.type?"["+s+"]":"object"==this.type?"{"+s+"}":this._escapeHTML(this.value)}this._updateDomField(),this._updateDomValue(),e&&1==e.updateIndexes&&this._updateDomIndexes(),e&&1==e.recurse&&this.childs&&this.childs.forEach(function(t){t.updateDom(e)}),this.append&&this.append.updateDom()},o.prototype._updateDomIndexes=function(){var e=this.dom.value,t=this.childs;e&&t&&("array"==this.type?t.forEach(function(e,t){e.index=t;var i=e.dom.field;i&&(i.innerHTML=t)}):"object"==this.type&&t.forEach(function(e){void 0!=e.index&&(delete e.index,void 0==e.field&&(e.field=""))}))},o.prototype._createDomValue=function(){var e;return"array"==this.type?(e=document.createElement("div"),e.className="readonly",e.innerHTML="[...]"):"object"==this.type?(e=document.createElement("div"),e.className="readonly",e.innerHTML="{...}"):!this.editor.mode.edit&&util.isUrl(this.value)?(e=document.createElement("a"),e.className="value",e.href=this.value,e.target="_blank",e.innerHTML=this._escapeHTML(this.value)):(e=document.createElement("div"),e.contentEditable=!this.editor.mode.view,e.spellcheck=!1,e.className="value",e.innerHTML=this._escapeHTML(this.value)),e},o.prototype._createDomExpandButton=function(){var e=document.createElement("button");return this._hasChilds()?(e.className=this.expanded?"expanded":"collapsed",e.title="Click to expand/collapse this field (Ctrl+E). \nCtrl+Click to expand/collapse including all childs."):(e.className="invisible",e.title=""),e},o.prototype._createDomTree=function(){var e=this.dom,t=document.createElement("table"),i=document.createElement("tbody");t.style.borderCollapse="collapse",t.className="values",t.appendChild(i);var o=document.createElement("tr");i.appendChild(o);var n=document.createElement("td");n.className="tree",o.appendChild(n),e.expand=this._createDomExpandButton(),n.appendChild(e.expand),e.tdExpand=n;var s=document.createElement("td");s.className="tree",o.appendChild(s),e.field=this._createDomField(),s.appendChild(e.field),e.tdField=s;var r=document.createElement("td");r.className="tree",o.appendChild(r),"object"!=this.type&&"array"!=this.type&&(r.appendChild(document.createTextNode(":")),r.className="separator"),e.tdSeparator=r;var a=document.createElement("td");return a.className="tree",o.appendChild(a),e.value=this._createDomValue(),a.appendChild(e.value),e.tdValue=a,t},o.prototype.onEvent=function(e){var t,i=e.type,o=e.target||e.srcElement,n=this.dom,s=this,r=this._hasChilds();if((o==n.drag||o==n.menu)&&("mouseover"==i?this.editor.highlighter.highlight(this):"mouseout"==i&&this.editor.highlighter.unhighlight()),"mousedown"==i&&o==n.drag&&this._onDragStart(e),"click"==i&&o==n.menu){var a=s.editor.highlighter;a.highlight(s),a.lock(),util.addClassName(n.menu,"selected"),this.showContextMenu(n.menu,function(){util.removeClassName(n.menu,"selected"),a.unlock(),a.unhighlight()})}if("click"==i&&o==n.expand&&r){var l=e.ctrlKey;this._onExpand(l)}var d=n.value;if(o==d)switch(i){case"focus":t=this;break;case"blur":case"change":this._getDomValue(!0),this._updateDomValue(),this.value&&(d.innerHTML=this._escapeHTML(this.value));break;case"input":this._getDomValue(!0),this._updateDomValue();break;case"keydown":case"mousedown":this.editor.selection=this.editor.getSelection();break;case"click":e.ctrlKey&&this.editor.mode.edit&&util.isUrl(this.value)&&window.open(this.value,"_blank");break;case"keyup":this._getDomValue(!0),this._updateDomValue();break;case"cut":case"paste":setTimeout(function(){s._getDomValue(!0),s._updateDomValue()},1)}var h=n.field;if(o==h)switch(i){case"focus":t=this;break;case"blur":case"change":this._getDomField(!0),this._updateDomField(),this.field&&(h.innerHTML=this._escapeHTML(this.field));break;case"input":this._getDomField(!0),this._updateDomField();break;case"keydown":case"mousedown":this.editor.selection=this.editor.getSelection();break;case"keyup":this._getDomField(!0),this._updateDomField();break;case"cut":case"paste":setTimeout(function(){s._getDomField(!0),s._updateDomField()},1)}var c=n.tree;if(o==c.parentNode)switch(i){case"click":var u=void 0!=e.offsetX?e.offsetX<24*(this.getLevel()+1):e.pageXo[i]?t:e[i]/g,">").replace(/ /g,"  ").replace(/^ /," ").replace(/ $/," "),i=JSON.stringify(t);return i.substring(1,i.length-1)},o.prototype._unescapeHTML=function(e){var t='"'+this._escapeJSON(e)+'"',i=util.parse(t);return i.replace(/</g,"<").replace(/>/g,">").replace(/ |\u00A0/g," ")},o.prototype._escapeJSON=function(e){for(var t="",i=0,o=e.length;o>i;){var n=e.charAt(i);"\n"==n?t+="\\n":"\\"==n?(t+=n,i++,n=e.charAt(i),-1=='"\\/bfnrtu'.indexOf(n)&&(t+="\\"),t+=n):t+='"'==n?'\\"':n,i++}return t},n.prototype=new o,n.prototype.getDom=function(){var e=this.dom;if(e.tr)return e.tr;var t=document.createElement("tr");if(t.node=this,e.tr=t,this.editor.mode.edit){e.tdDrag=document.createElement("td");var i=document.createElement("td");e.tdMenu=i;var o=document.createElement("button");o.className="contextmenu",o.title="Click to open the actions menu (Ctrl+M)",e.menu=o,i.appendChild(e.menu)}var n=document.createElement("td"),s=document.createElement("div");return s.innerHTML="(empty)",s.className="readonly",n.appendChild(s),e.td=n,e.text=s,this.updateDom(),t},n.prototype.updateDom=function(){var e=this.dom,t=e.td;t&&(t.style.paddingLeft=24*this.getLevel()+26+"px");var i=e.text;i&&(i.innerHTML="(empty "+this.parent.type+")");var o=e.tr;this.isVisible()?e.tr.firstChild||(e.tdDrag&&o.appendChild(e.tdDrag),e.tdMenu&&o.appendChild(e.tdMenu),o.appendChild(t)):e.tr.firstChild&&(e.tdDrag&&o.removeChild(e.tdDrag),e.tdMenu&&o.removeChild(e.tdMenu),o.removeChild(t))},n.prototype.isVisible=function(){return 0==this.parent.childs.length},n.prototype.showContextMenu=function(e,t){var i=this,n=o.TYPE_TITLES,r=[{text:"Append",title:"Append a new field with type 'auto' (Ctrl+Shift+Ins)",submenuTitle:"Select the type of the field to be appended",className:"insert",click:function(){i._onAppend("","","auto")},submenu:[{text:"Auto",className:"type-auto",title:n.auto,click:function(){i._onAppend("","","auto")}},{text:"Array",className:"type-array",title:n.array,click:function(){i._onAppend("",[])}},{text:"Object",className:"type-object",title:n.object,click:function(){i._onAppend("",{})}},{text:"String",className:"type-string",title:n.string,click:function(){i._onAppend("","","string")}}]}],a=new s(r,{close:t});a.show(e)},n.prototype.onEvent=function(e){var t=e.type,i=e.target||e.srcElement,o=this.dom,n=o.menu;if(i==n&&("mouseover"==t?this.editor.highlighter.highlight(this.parent):"mouseout"==t&&this.editor.highlighter.unhighlight()),"click"==t&&i==o.menu){var s=this.editor.highlighter;s.highlight(this.parent),s.lock(),util.addClassName(o.menu,"selected"),this.showContextMenu(o.menu,function(){util.removeClassName(o.menu,"selected"),s.unlock(),s.unhighlight()})}"keydown"==t&&this.onKeyDown(e)},s.prototype._getVisibleButtons=function(){var e=[],t=this;return this.dom.items.forEach(function(i){e.push(i.button),i.buttonExpand&&e.push(i.buttonExpand),i.subItems&&i==t.expandedItem&&i.subItems.forEach(function(t){e.push(t.button),t.buttonExpand&&e.push(t.buttonExpand)})}),e},s.visibleMenu=void 0,s.prototype.show=function(e){this.hide();var t=window.innerHeight,i=window.pageYOffset||document.scrollTop||0,o=t+i,n=e.offsetHeight,r=this.maxHeight,a=util.getAbsoluteLeft(e),l=util.getAbsoluteTop(e);o>l+n+r?(this.dom.menu.style.left=a+"px",this.dom.menu.style.top=l+n+"px",this.dom.menu.style.bottom=""):(this.dom.menu.style.left=a+"px",this.dom.menu.style.top="",this.dom.menu.style.bottom=t-l+"px"),document.body.appendChild(this.dom.menu);var d=this,h=this.dom.list;this.eventListeners.mousedown=util.addEventListener(document,"mousedown",function(e){var t=e.target;t==h||d._isChildOf(t,h)||(d.hide(),e.stopPropagation(),e.preventDefault())}),this.eventListeners.mousewheel=util.addEventListener(document,"mousewheel",function(e){e.stopPropagation(),e.preventDefault()}),this.eventListeners.keydown=util.addEventListener(document,"keydown",function(e){d._onKeyDown(e)}),this.selection=util.getSelection(),this.anchor=e,setTimeout(function(){d.dom.focusButton.focus()},0),s.visibleMenu&&s.visibleMenu.hide(),s.visibleMenu=this},s.prototype.hide=function(){this.dom.menu.parentNode&&(this.dom.menu.parentNode.removeChild(this.dom.menu),this.onClose&&this.onClose());for(var e in this.eventListeners)if(this.eventListeners.hasOwnProperty(e)){var t=this.eventListeners[e];t&&util.removeEventListener(document,e,t),delete this.eventListeners[e]}s.visibleMenu==this&&(s.visibleMenu=void 0)},s.prototype._onExpandItem=function(e){var t=this,i=e==this.expandedItem,o=this.expandedItem;if(o&&(o.ul.style.height="0",o.ul.style.padding="",setTimeout(function(){t.expandedItem!=o&&(o.ul.style.display="",util.removeClassName(o.ul.parentNode,"selected"))},300),this.expandedItem=void 0),!i){var n=e.ul;n.style.display="block";{n.clientHeight}setTimeout(function(){t.expandedItem==e&&(n.style.height=24*n.childNodes.length+"px",n.style.padding="5px 10px")},0),util.addClassName(n.parentNode,"selected"),this.expandedItem=e}},s.prototype._onKeyDown=function(e){var t,i,o,n,s=e.target,r=e.which,a=!1;27==r?(this.selection&&util.setSelection(this.selection),this.anchor&&this.anchor.focus(),this.hide(),a=!0):9==r?e.shiftKey?(t=this._getVisibleButtons(),i=t.indexOf(s),0==i&&(t[t.length-1].focus(),a=!0)):(t=this._getVisibleButtons(),i=t.indexOf(s),i==t.length-1&&(t[0].focus(),a=!0)):37==r?("expand"==s.className&&(t=this._getVisibleButtons(),i=t.indexOf(s),o=t[i-1],o&&o.focus()),a=!0):38==r?(t=this._getVisibleButtons(),i=t.indexOf(s),o=t[i-1],o&&"expand"==o.className&&(o=t[i-2]),o||(o=t[t.length-1]),o&&o.focus(),a=!0):39==r?(t=this._getVisibleButtons(),i=t.indexOf(s),n=t[i+1],n&&"expand"==n.className&&n.focus(),a=!0):40==r&&(t=this._getVisibleButtons(),i=t.indexOf(s),n=t[i+1],n&&"expand"==n.className&&(n=t[i+2]),n||(n=t[0]),n&&(n.focus(),a=!0),a=!0),a&&(e.stopPropagation(),e.preventDefault())},s.prototype._isChildOf=function(e,t){for(var i=e.parentNode;i;){if(i==t)return!0;i=i.parentNode}return!1},r.prototype.onChange=function(){},r.prototype.add=function(e,t){this.index++,this.history[this.index]={action:e,params:t,timestamp:new Date},this.index=0},r.prototype.canRedo=function(){return this.indexthis.results.length-1&&(t=0),this._setActiveResult(t,e)}},l.prototype.previous=function(e){if(void 0!=this.results){var t=this.results.length-1,i=void 0!=this.resultIndex?this.resultIndex-1:t;0>i&&(i=t),this._setActiveResult(i,e)}},l.prototype._setActiveResult=function(e,t){if(this.activeResult){var i=this.activeResult.node,o=this.activeResult.elem;"field"==o?delete i.searchFieldActive:delete i.searchValueActive,i.updateDom()}if(!this.results||!this.results[e])return this.resultIndex=void 0,this.activeResult=void 0,void 0;this.resultIndex=e;var n=this.results[this.resultIndex].node,s=this.results[this.resultIndex].elem;"field"==s?n.searchFieldActive=!0:n.searchValueActive=!0,this.activeResult=this.results[this.resultIndex],n.updateDom(),n.scrollTo(function(){t&&n.focus(s)})},l.prototype._clearDelay=function(){void 0!=this.timeout&&(clearTimeout(this.timeout),delete this.timeout)},l.prototype._onDelayedSearch=function(){this._clearDelay();var e=this;this.timeout=setTimeout(function(t){e._onSearch(t)},this.delay)},l.prototype._onSearch=function(e,t){this._clearDelay();var i=this.dom.search.value,o=i.length>0?i:void 0;if(o!=this.lastText||t)if(this.lastText=o,this.results=this.editor.search(o),this._setActiveResult(void 0),void 0!=o){var n=this.results.length;switch(n){case 0:this.dom.results.innerHTML="no results";break;case 1:this.dom.results.innerHTML="1 result";break;default:this.dom.results.innerHTML=n+" results"}}else this.dom.results.innerHTML=""},l.prototype._onKeyDown=function(e){var t=e.which;27==t?(this.dom.search.value="",this._onSearch(e),e.preventDefault(),e.stopPropagation()):13==t&&(e.ctrlKey?this._onSearch(e,!0):e.shiftKey?this.previous():this.next(),e.preventDefault(),e.stopPropagation())},l.prototype._onKeyUp=function(e){var t=e.keyCode;27!=t&&13!=t&&this._onDelayedSearch(e)},d.prototype.highlight=function(e){this.locked||(this.node!=e&&(this.node&&this.node.setHighlight(!1),this.node=e,this.node.setHighlight(!0)),this._cancelUnhighlight())},d.prototype.unhighlight=function(){if(!this.locked){var e=this;this.node&&(this._cancelUnhighlight(),this.unhighlightTimer=setTimeout(function(){e.node.setHighlight(!1),e.node=void 0,e.unhighlightTimer=void 0},0))}},d.prototype._cancelUnhighlight=function(){this.unhighlightTimer&&(clearTimeout(this.unhighlightTimer),this.unhighlightTimer=void 0)},d.prototype.lock=function(){this.locked=!0},d.prototype.unlock=function(){this.locked=!1},util={},util.parse=function(e){try{return JSON.parse(e)}catch(t){throw util.validate(e),t}},util.validate=function(e){"undefined"!=typeof jsonlint?jsonlint.parse(e):JSON.parse(e)},util.extend=function(e,t){for(var i in t)t.hasOwnProperty(i)&&(e[i]=t[i]);return e},util.clear=function(e){for(var t in e)e.hasOwnProperty(t)&&delete e[t];return e},util.log=function(){"undefined"!=typeof console&&"function"==typeof console.log&&console.log.apply(console,arguments)},util.type=function(e){return null===e?"null":void 0===e?"undefined":e instanceof Number||"number"==typeof e?"number":e instanceof String||"string"==typeof e?"string":e instanceof Boolean||"boolean"==typeof e?"boolean":e instanceof RegExp||"regexp"==typeof e?"regexp":Array.isArray(e)?"array":"object"};var h=/^https?:\/\/\S+$/;util.isUrl=function(e){return("string"==typeof e||e instanceof String)&&h.test(e)},util.getAbsoluteLeft=function(e){var t=e.getBoundingClientRect();return t.left+window.pageXOffset||document.scrollLeft||0},util.getAbsoluteTop=function(e){var t=e.getBoundingClientRect();return t.top+window.pageYOffset||document.scrollTop||0},util.addClassName=function(e,t){var i=e.className.split(" ");-1==i.indexOf(t)&&(i.push(t),e.className=i.join(" "))},util.removeClassName=function(e,t){var i=e.className.split(" "),o=i.indexOf(t);-1!=o&&(i.splice(o,1),e.className=i.join(" "))},util.stripFormatting=function(e){for(var t=e.childNodes,i=0,o=t.length;o>i;i++){var n=t[i];n.style&&n.removeAttribute("style");var s=n.attributes;if(s)for(var r=s.length-1;r>=0;r--){var a=s[r];1==a.specified&&n.removeAttribute(a.name)}util.stripFormatting(n)}},util.setEndOfContentEditable=function(e){var t,i;document.createRange&&(t=document.createRange(),t.selectNodeContents(e),t.collapse(!1),i=window.getSelection(),i.removeAllRanges(),i.addRange(t))},util.selectContentEditable=function(e){if(e&&"DIV"==e.nodeName){var t,i;window.getSelection&&document.createRange&&(i=document.createRange(),i.selectNodeContents(e),t=window.getSelection(),t.removeAllRanges(),t.addRange(i))}},util.getSelection=function(){if(window.getSelection){var e=window.getSelection();if(e.getRangeAt&&e.rangeCount)return e.getRangeAt(0)}return null},util.setSelection=function(e){if(e&&window.getSelection){var t=window.getSelection();t.removeAllRanges(),t.addRange(e)}},util.getSelectionOffset=function(){var e=util.getSelection();return e&&"startOffset"in e&&"endOffset"in e&&e.startContainer&&e.startContainer==e.endContainer?{startOffset:e.startOffset,endOffset:e.endOffset,container:e.startContainer.parentNode}:null},util.setSelectionOffset=function(e){if(document.createRange&&window.getSelection){var t=window.getSelection();if(t){var i=document.createRange();i.setStart(e.container.firstChild,e.startOffset),i.setEnd(e.container.firstChild,e.endOffset),util.setSelection(i)}}},util.getInnerText=function(e,t){var i=void 0==t;if(i&&(t={text:"",flush:function(){var e=this.text;return this.text="",e},set:function(e){this.text=e}}),e.nodeValue)return t.flush()+e.nodeValue;if(e.hasChildNodes()){for(var o=e.childNodes,n="",s=0,r=o.length;r>s;s++){var a=o[s];if("DIV"==a.nodeName||"P"==a.nodeName){var l=o[s-1],d=l?l.nodeName:void 0;d&&"DIV"!=d&&"P"!=d&&"BR"!=d&&(n+="\n",t.flush()),n+=util.getInnerText(a,t),t.set("\n")}else"BR"==a.nodeName?(n+=t.flush(),t.set("\n")):n+=util.getInnerText(a,t)}return n}return"P"==e.nodeName&&-1!=util.getInternetExplorerVersion()?t.flush():""},util.getInternetExplorerVersion=function(){if(-1==c){var e=-1;if("Microsoft Internet Explorer"==navigator.appName){var t=navigator.userAgent,i=new RegExp("MSIE ([0-9]{1,}[.0-9]{0,})");null!=i.exec(t)&&(e=parseFloat(RegExp.$1))}c=e}return c},util.isFirefox=function(){return-1!=navigator.userAgent.indexOf("Firefox")};var c=-1;util.addEventListener=function(e,t,i,o){if(e.addEventListener)return void 0===o&&(o=!1),"mousewheel"===t&&util.isFirefox()&&(t="DOMMouseScroll"),e.addEventListener(t,i,o),i;if(e.attachEvent){var n=function(){return i.call(e,window.event)};return e.attachEvent("on"+t,n),n}},util.removeEventListener=function(e,t,i,o){e.removeEventListener?(void 0===o&&(o=!1),"mousewheel"===t&&util.isFirefox()&&(t="DOMMouseScroll"),e.removeEventListener(t,i,o)):e.detachEvent&&e.detachEvent("on"+t,i)};var u={JSONEditor:e,JSONFormatter:function(){throw new Error('JSONFormatter is deprecated. Use JSONEditor with mode "text" or "code" instead')},util:util},p=function(){for(var e=document.getElementsByTagName("script"),t=0;t .icon { - background-position: -24px -24px; -} -.jsoneditor-contextmenu button.remove:hover > .icon, -.jsoneditor-contextmenu button.remove:focus > .icon { - background-position: -24px 0; -} - -.jsoneditor-contextmenu button.append > .icon { - background-position: 0 -24px; -} -.jsoneditor-contextmenu button.append:hover > .icon, -.jsoneditor-contextmenu button.append:focus > .icon { - background-position: 0 0; -} - -.jsoneditor-contextmenu button.insert > .icon { - background-position: 0 -24px; -} -.jsoneditor-contextmenu button.insert:hover > .icon, -.jsoneditor-contextmenu button.insert:focus > .icon { - background-position: 0 0; -} - -.jsoneditor-contextmenu button.duplicate > .icon { - background-position: -48px -24px; -} -.jsoneditor-contextmenu button.duplicate:hover > .icon, -.jsoneditor-contextmenu button.duplicate:focus > .icon { - background-position: -48px 0; -} - -.jsoneditor-contextmenu button.sort-asc > .icon { - background-position: -168px -24px; -} -.jsoneditor-contextmenu button.sort-asc:hover > .icon, -.jsoneditor-contextmenu button.sort-asc:focus > .icon { - background-position: -168px 0; -} - -.jsoneditor-contextmenu button.sort-desc > .icon { - background-position: -192px -24px; -} -.jsoneditor-contextmenu button.sort-desc:hover > .icon, -.jsoneditor-contextmenu button.sort-desc:focus > .icon { - background-position: -192px 0; -} - -/* ContextMenu - sub menu */ - -.jsoneditor-contextmenu ul li .selected { - background-color: #D5DDF6; -} - -.jsoneditor-contextmenu ul li { - overflow: hidden; -} - -.jsoneditor-contextmenu ul li ul { - display: none; - position: relative; - left: -10px; - top: 0; - - border: none; - box-shadow: inset 0 0 10px rgba(128, 128, 128, 0.5); - padding: 0 10px; - - /* TODO: transition is not supported on IE8-9 */ - -webkit-transition: all 0.3s ease-out; - -moz-transition: all 0.3s ease-out; - -o-transition: all 0.3s ease-out; - transition: all 0.3s ease-out; -} - -.jsoneditor-contextmenu ul li.selected ul { -} - -.jsoneditor-contextmenu ul li ul li button { - padding-left: 24px; -} - -.jsoneditor-contextmenu ul li ul li button:hover, -.jsoneditor-contextmenu ul li ul li button:focus { - background-color: #f5f5f5; - -} - -.jsoneditor-contextmenu button.type-string > .icon { - background-position: -144px -24px; -} -.jsoneditor-contextmenu button.type-string:hover > .icon, -.jsoneditor-contextmenu button.type-string:focus > .icon, -.jsoneditor-contextmenu button.type-string.selected > .icon{ - background-position: -144px 0; -} - -.jsoneditor-contextmenu button.type-auto > .icon { - background-position: -120px -24px; -} -.jsoneditor-contextmenu button.type-auto:hover > .icon, -.jsoneditor-contextmenu button.type-auto:focus > .icon, -.jsoneditor-contextmenu button.type-auto.selected > .icon { - background-position: -120px 0; -} - -.jsoneditor-contextmenu button.type-object > .icon { - background-position: -72px -24px; -} -.jsoneditor-contextmenu button.type-object:hover > .icon, -.jsoneditor-contextmenu button.type-object:focus > .icon, -.jsoneditor-contextmenu button.type-object.selected > .icon{ - background-position: -72px 0; -} - -.jsoneditor-contextmenu button.type-array > .icon { - background-position: -96px -24px; -} -.jsoneditor-contextmenu button.type-array:hover > .icon, -.jsoneditor-contextmenu button.type-array:focus > .icon, -.jsoneditor-contextmenu button.type-array.selected > .icon{ - background-position: -96px 0; -} - -.jsoneditor-contextmenu button.type-modes > .icon { - background-image: none; - width: 6px; -} - - -.jsoneditor .menu { - width: 100%; - height: 35px; - padding: 2px; - margin: 0; - overflow: hidden; - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - - color: #1A1A1A; - background-color: #D5DDF6; - border-bottom: 1px solid #97B0F8; -} - -.jsoneditor .menu button { - width: 26px; - height: 26px; - margin: 2px; - padding: 0; - border-radius: 2px; - border: 1px solid #aec0f8; - background: #e3eaf6 url('img/jsoneditor-icons.png'); - color: #4D4D4D; - opacity: 0.8; - - font-family: arial, sans-serif; - font-size: 10pt; - - float: left; -} - -.jsoneditor .menu button:hover { - background-color: #f0f2f5; -} -.jsoneditor .menu button:active { - background-color: #ffffff; -} -.jsoneditor .menu button:disabled { - background-color: #e3eaf6; -} - -.jsoneditor .menu button.collapse-all { - background-position: 0 -96px; -} -.jsoneditor .menu button.expand-all { - background-position: 0 -120px; -} -.jsoneditor .menu button.undo { - background-position: -24px -96px; -} -.jsoneditor .menu button.undo:disabled { - background-position: -24px -120px; -} -.jsoneditor .menu button.redo { - background-position: -48px -96px; -} -.jsoneditor .menu button.redo:disabled { - background-position: -48px -120px; -} -.jsoneditor .menu button.compact { - background-position: -72px -96px; -} -.jsoneditor .menu button.format { - background-position: -72px -120px; -} - -.jsoneditor .menu button.modes { - background-image: none; - width: auto; - padding-left: 6px; - padding-right: 6px; -} - -.jsoneditor .menu button.separator { - margin-left: 10px; -} - -.jsoneditor .menu a { - font-family: arial, sans-serif; - font-size: 10pt; - color: #97B0F8; - vertical-align: middle; -} - -.jsoneditor .menu a:hover { - color: red; -} - -.jsoneditor .menu a.poweredBy { - font-size: 8pt; - position: absolute; - right: 0; - top: 0; - padding: 10px; -} - -/* TODO: css for button:disabled is not supported by IE8 */ - - -.jsoneditor .search input, -.jsoneditor .search .results { - font-family: arial, sans-serif; - font-size: 10pt; - color: #1A1A1A; -} - -.jsoneditor .search { - position: absolute; - right: 2px; - top: 2px; -} - -.jsoneditor .search .frame { - border: 1px solid #97B0F8; - background-color: white; - padding: 0 2px; - margin: 0; -} - -.jsoneditor .search .frame table { - border-collapse: collapse; -} - -.jsoneditor .search input { - width: 120px; - border: none; - outline: none; - margin: 1px; -} - -.jsoneditor .search .results { - color: #4d4d4d; - padding-right: 5px; - line-height: 24px; -} - -.jsoneditor .search button { - width: 16px; - height: 24px; - padding: 0; - margin: 0; - border: none; - background: url('img/jsoneditor-icons.png'); - vertical-align: top; -} - -.jsoneditor .search button:hover { - background-color: transparent; -} - -.jsoneditor .search button.refresh { - width: 18px; - background-position: -99px -73px; -} - -.jsoneditor .search button.next { - cursor: pointer; - background-position: -124px -73px; -} -.jsoneditor .search button.next:hover { - background-position: -124px -49px; -} - -.jsoneditor .search button.previous { - cursor: pointer; - background-position: -148px -73px; - margin-right: 2px; -} -.jsoneditor .search button.previous:hover { - background-position: -148px -49px; -} - diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/jsoneditor.js b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/jsoneditor.js deleted file mode 100644 index a7f02472bb6..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/jsoneditor.js +++ /dev/null @@ -1,6041 +0,0 @@ -/*! - * jsoneditor.js - * - * @brief - * JSONEditor is a web-based tool to view, edit, and format JSON. - * It shows data a clear, editable treeview. - * - * Supported browsers: Chrome, Firefox, Safari, Opera, Internet Explorer 8+ - * - * @license - * This json editor is open sourced with the intention to use the editor as - * a component in your own application. Not to just copy and monetize the editor - * as it is. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy - * of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - * - * Copyright (c) 2011-2013 Jos de Jong, http://jsoneditoronline.org - * - * @author Jos de Jong, - * @version 2.3.6 - * @date 2014-01-03 - */ -(function () { - -/** - * @constructor JSONEditor - * @param {Element} container Container element - * @param {Object} [options] Object with options. available options: - * {String} mode Editor mode. Available values: - * 'tree' (default), 'view', - * 'form', 'text', and 'code'. - * {function} change Callback method, triggered - * on change of contents - * {Boolean} search Enable search box. - * True by default - * Only applicable for modes - * 'tree', 'view', and 'form' - * {Boolean} history Enable history (undo/redo). - * True by default - * Only applicable for modes - * 'tree', 'view', and 'form' - * {String} name Field name for the root node. - * Only applicable for modes - * 'tree', 'view', and 'form' - * {Number} indentation Number of indentation - * spaces. 4 by default. - * Only applicable for - * modes 'text' and 'code' - * @param {Object | undefined} json JSON object - */ -function JSONEditor (container, options, json) { - if (!(this instanceof JSONEditor)) { - throw new Error('JSONEditor constructor called without "new".'); - } - - // check for unsupported browser (IE8 and older) - var ieVersion = util.getInternetExplorerVersion(); - if (ieVersion != -1 && ieVersion < 9) { - throw new Error('Unsupported browser, IE9 or newer required. ' + - 'Please install the newest version of your browser.'); - } - - if (arguments.length) { - this._create(container, options, json); - } -} - -/** - * Configuration for all registered modes. Example: - * { - * tree: { - * editor: TreeEditor, - * data: 'json' - * }, - * text: { - * editor: TextEditor, - * data: 'text' - * } - * } - * - * @type { Object. } - */ -JSONEditor.modes = {}; - -/** - * Create the JSONEditor - * @param {Element} container Container element - * @param {Object} [options] See description in constructor - * @param {Object | undefined} json JSON object - * @private - */ -JSONEditor.prototype._create = function (container, options, json) { - this.container = container; - this.options = options || {}; - this.json = json || {}; - - var mode = this.options.mode || 'tree'; - this.setMode(mode); -}; - -/** - * Detach the editor from the DOM - * @private - */ -JSONEditor.prototype._delete = function () {}; - -/** - * Set JSON object in editor - * @param {Object | undefined} json JSON data - */ -JSONEditor.prototype.set = function (json) { - this.json = json; -}; - -/** - * Get JSON from the editor - * @returns {Object} json - */ -JSONEditor.prototype.get = function () { - return this.json; -}; - -/** - * Set string containing JSON for the editor - * @param {String | undefined} jsonText - */ -JSONEditor.prototype.setText = function (jsonText) { - this.json = util.parse(jsonText); -}; - -/** - * Get stringified JSON contents from the editor - * @returns {String} jsonText - */ -JSONEditor.prototype.getText = function () { - return JSON.stringify(this.json); -}; - -/** - * Set a field name for the root node. - * @param {String | undefined} name - */ -JSONEditor.prototype.setName = function (name) { - if (!this.options) { - this.options = {}; - } - this.options.name = name; -}; - -/** - * Get the field name for the root node. - * @return {String | undefined} name - */ -JSONEditor.prototype.getName = function () { - return this.options && this.options.name; -}; - -/** - * Change the mode of the editor. - * JSONEditor will be extended with all methods needed for the chosen mode. - * @param {String} mode Available modes: 'tree' (default), 'view', 'form', - * 'text', and 'code'. - */ -JSONEditor.prototype.setMode = function (mode) { - var container = this.container, - options = util.extend({}, this.options), - data, - name; - - options.mode = mode; - var config = JSONEditor.modes[mode]; - if (config) { - try { - if (config.data == 'text') { - // text - name = this.getName(); - data = this.getText(); - - this._delete(); - util.clear(this); - util.extend(this, config.editor.prototype); - this._create(container, options); - - this.setName(name); - this.setText(data); - } - else { - // json - name = this.getName(); - data = this.get(); - - this._delete(); - util.clear(this); - util.extend(this, config.editor.prototype); - this._create(container, options); - - this.setName(name); - this.set(data); - } - - if (typeof config.load === 'function') { - try { - config.load.call(this); - } - catch (err) {} - } - } - catch (err) { - this._onError(err); - } - } - else { - throw new Error('Unknown mode "' + options.mode + '"'); - } -}; - -/** - * Throw an error. If an error callback is configured in options.error, this - * callback will be invoked. Else, a regular error is thrown. - * @param {Error} err - * @private - */ -JSONEditor.prototype._onError = function(err) { - // TODO: onError is deprecated since version 2.2.0. cleanup some day - if (typeof this.onError === 'function') { - util.log('WARNING: JSONEditor.onError is deprecated. ' + - 'Use options.error instead.'); - this.onError(err); - } - - if (this.options && typeof this.options.error === 'function') { - this.options.error(err); - } - else { - throw err; - } -}; - -/** - * @constructor TreeEditor - * @param {Element} container Container element - * @param {Object} [options] Object with options. available options: - * {String} mode Editor mode. Available values: - * 'tree' (default), 'view', - * and 'form'. - * {Boolean} search Enable search box. - * True by default - * {Boolean} history Enable history (undo/redo). - * True by default - * {function} change Callback method, triggered - * on change of contents - * {String} name Field name for the root node. - * @param {Object | undefined} json JSON object - */ -function TreeEditor(container, options, json) { - if (!(this instanceof TreeEditor)) { - throw new Error('TreeEditor constructor called without "new".'); - } - - this._create(container, options, json); -} - -/** - * Create the TreeEditor - * @param {Element} container Container element - * @param {Object} [options] See description in constructor - * @param {Object | undefined} json JSON object - * @private - */ -TreeEditor.prototype._create = function (container, options, json) { - if (!container) { - throw new Error('No container element provided.'); - } - this.container = container; - this.dom = {}; - this.highlighter = new Highlighter(); - this.selection = undefined; // will hold the last input selection - - this._setOptions(options); - - if (this.options.history && !this.mode.view) { - this.history = new History(this); - } - - this._createFrame(); - this._createTable(); - - this.set(json || {}); -}; - -/** - * Detach the editor from the DOM - * @private - */ -TreeEditor.prototype._delete = function () { - if (this.frame && this.container && this.frame.parentNode == this.container) { - this.container.removeChild(this.frame); - } -}; - -/** - * Initialize and set default options - * @param {Object} [options] See description in constructor - * @private - */ -TreeEditor.prototype._setOptions = function (options) { - this.options = { - search: true, - history: true, - mode: 'tree', - name: undefined // field name of root node - }; - - // copy all options - if (options) { - for (var prop in options) { - if (options.hasOwnProperty(prop)) { - this.options[prop] = options[prop]; - } - } - - // check for deprecated options - if (options['enableSearch']) { - // deprecated since version 1.6.0, 2012-11-03 - this.options.search = options['enableSearch']; - util.log('WARNING: Option "enableSearch" is deprecated. Use "search" instead.'); - } - if (options['enableHistory']) { - // deprecated since version 1.6.0, 2012-11-03 - this.options.history = options['enableHistory']; - util.log('WARNING: Option "enableHistory" is deprecated. Use "history" instead.'); - } - if (options['mode'] == 'editor') { - // deprecated since version 2.2.0, 2013-04-30 - this.options.mode = 'tree'; - util.log('WARNING: Mode "editor" is deprecated. Use "tree" instead.'); - } - if (options['mode'] == 'viewer') { - // deprecated since version 2.2.0, 2013-04-30 - this.options.mode = 'view'; - util.log('WARNING: Mode "viewer" is deprecated. Use "view" instead.'); - } - } - - // interpret the mode options - this.mode = { - edit: (this.options.mode != 'view' && this.options.mode != 'form'), - view: (this.options.mode == 'view'), - form: (this.options.mode == 'form') - }; -}; - -// node currently being edited -TreeEditor.focusNode = undefined; - -/** - * Set JSON object in editor - * @param {Object | undefined} json JSON data - * @param {String} [name] Optional field name for the root node. - * Can also be set using setName(name). - */ -TreeEditor.prototype.set = function (json, name) { - // adjust field name for root node - if (name) { - // TODO: deprecated since version 2.2.0. Cleanup some day. - util.log('Warning: second parameter "name" is deprecated. ' + - 'Use setName(name) instead.'); - this.options.name = name; - } - - // verify if json is valid JSON, ignore when a function - if (json instanceof Function || (json === undefined)) { - this.clear(); - } - else { - this.content.removeChild(this.table); // Take the table offline - - // replace the root node - var params = { - 'field': this.options.name, - 'value': json - }; - var node = new Node(this, params); - this._setRoot(node); - - // expand - var recurse = false; - this.node.expand(recurse); - - this.content.appendChild(this.table); // Put the table online again - } - - // TODO: maintain history, store last state and previous document - if (this.history) { - this.history.clear(); - } -}; - -/** - * Get JSON object from editor - * @return {Object | undefined} json - */ -TreeEditor.prototype.get = function () { - // remove focus from currently edited node - if (TreeEditor.focusNode) { - TreeEditor.focusNode.blur(); - } - - if (this.node) { - return this.node.getValue(); - } - else { - return undefined; - } -}; - -/** - * Get the text contents of the TreeEditor - * @return {String} jsonText - */ -TreeEditor.prototype.getText = function() { - return JSON.stringify(this.get()); -}; - -/** - * Set the text contents of the TreeEditor - * @param {String} jsonText - */ -TreeEditor.prototype.setText = function(jsonText) { - this.set(util.parse(jsonText)); -}; - -/** - * Set a field name for the root node. - * @param {String | undefined} name - */ -TreeEditor.prototype.setName = function (name) { - this.options.name = name; - if (this.node) { - this.node.updateField(this.options.name); - } -}; - -/** - * Get the field name for the root node. - * @return {String | undefined} name - */ -TreeEditor.prototype.getName = function () { - return this.options.name; -}; - -/** - * Remove the root node from the editor - */ -TreeEditor.prototype.clear = function () { - if (this.node) { - this.node.collapse(); - this.tbody.removeChild(this.node.getDom()); - delete this.node; - } -}; - -/** - * Set the root node for the json editor - * @param {Node} node - * @private - */ -TreeEditor.prototype._setRoot = function (node) { - this.clear(); - - this.node = node; - - // append to the dom - this.tbody.appendChild(node.getDom()); -}; - -/** - * Search text in all nodes - * The nodes will be expanded when the text is found one of its childs, - * else it will be collapsed. Searches are case insensitive. - * @param {String} text - * @return {Object[]} results Array with nodes containing the search results - * The result objects contains fields: - * - {Node} node, - * - {String} elem the dom element name where - * the result is found ('field' or - * 'value') - */ -TreeEditor.prototype.search = function (text) { - var results; - if (this.node) { - this.content.removeChild(this.table); // Take the table offline - results = this.node.search(text); - this.content.appendChild(this.table); // Put the table online again - } - else { - results = []; - } - - return results; -}; - -/** - * Expand all nodes - */ -TreeEditor.prototype.expandAll = function () { - if (this.node) { - this.content.removeChild(this.table); // Take the table offline - this.node.expand(); - this.content.appendChild(this.table); // Put the table online again - } -}; - -/** - * Collapse all nodes - */ -TreeEditor.prototype.collapseAll = function () { - if (this.node) { - this.content.removeChild(this.table); // Take the table offline - this.node.collapse(); - this.content.appendChild(this.table); // Put the table online again - } -}; - -/** - * The method onChange is called whenever a field or value is changed, created, - * deleted, duplicated, etc. - * @param {String} action Change action. Available values: "editField", - * "editValue", "changeType", "appendNode", - * "removeNode", "duplicateNode", "moveNode", "expand", - * "collapse". - * @param {Object} params Object containing parameters describing the change. - * The parameters in params depend on the action (for - * example for "editValue" the Node, old value, and new - * value are provided). params contains all information - * needed to undo or redo the action. - * @private - */ -TreeEditor.prototype._onAction = function (action, params) { - // add an action to the history - if (this.history) { - this.history.add(action, params); - } - - // trigger the onChange callback - if (this.options.change) { - try { - this.options.change(); - } - catch (err) { - util.log('Error in change callback: ', err); - } - } -}; - -/** - * Start autoscrolling when given mouse position is above the top of the - * editor contents, or below the bottom. - * @param {Number} mouseY Absolute mouse position in pixels - */ -TreeEditor.prototype.startAutoScroll = function (mouseY) { - var me = this; - var content = this.content; - var top = util.getAbsoluteTop(content); - var height = content.clientHeight; - var bottom = top + height; - var margin = 24; - var interval = 50; // ms - - if ((mouseY < top + margin) && content.scrollTop > 0) { - this.autoScrollStep = ((top + margin) - mouseY) / 3; - } - else if (mouseY > bottom - margin && - height + content.scrollTop < content.scrollHeight) { - this.autoScrollStep = ((bottom - margin) - mouseY) / 3; - } - else { - this.autoScrollStep = undefined; - } - - if (this.autoScrollStep) { - if (!this.autoScrollTimer) { - this.autoScrollTimer = setInterval(function () { - if (me.autoScrollStep) { - content.scrollTop -= me.autoScrollStep; - } - else { - me.stopAutoScroll(); - } - }, interval); - } - } - else { - this.stopAutoScroll(); - } -}; - -/** - * Stop auto scrolling. Only applicable when scrolling - */ -TreeEditor.prototype.stopAutoScroll = function () { - if (this.autoScrollTimer) { - clearTimeout(this.autoScrollTimer); - delete this.autoScrollTimer; - } - if (this.autoScrollStep) { - delete this.autoScrollStep; - } -}; - - -/** - * Set the focus to an element in the TreeEditor, set text selection, and - * set scroll position. - * @param {Object} selection An object containing fields: - * {Element | undefined} dom The dom element - * which has focus - * {Range | TextRange} range A text selection - * {Number} scrollTop Scroll position - */ -TreeEditor.prototype.setSelection = function (selection) { - if (!selection) { - return; - } - - if ('scrollTop' in selection && this.content) { - // TODO: animated scroll - this.content.scrollTop = selection.scrollTop; - } - if (selection.range) { - util.setSelectionOffset(selection.range); - } - if (selection.dom) { - selection.dom.focus(); - } -}; - -/** - * Get the current focus - * @return {Object} selection An object containing fields: - * {Element | undefined} dom The dom element - * which has focus - * {Range | TextRange} range A text selection - * {Number} scrollTop Scroll position - */ -TreeEditor.prototype.getSelection = function () { - return { - dom: TreeEditor.domFocus, - scrollTop: this.content ? this.content.scrollTop : 0, - range: util.getSelectionOffset() - }; -}; - -/** - * Adjust the scroll position such that given top position is shown at 1/4 - * of the window height. - * @param {Number} top - * @param {function(boolean)} [callback] Callback, executed when animation is - * finished. The callback returns true - * when animation is finished, or false - * when not. - */ -TreeEditor.prototype.scrollTo = function (top, callback) { - var content = this.content; - if (content) { - var editor = this; - // cancel any running animation - if (editor.animateTimeout) { - clearTimeout(editor.animateTimeout); - delete editor.animateTimeout; - } - if (editor.animateCallback) { - editor.animateCallback(false); - delete editor.animateCallback; - } - - // calculate final scroll position - var height = content.clientHeight; - var bottom = content.scrollHeight - height; - var finalScrollTop = Math.min(Math.max(top - height / 4, 0), bottom); - - // animate towards the new scroll position - var animate = function () { - var scrollTop = content.scrollTop; - var diff = (finalScrollTop - scrollTop); - if (Math.abs(diff) > 3) { - content.scrollTop += diff / 3; - editor.animateCallback = callback; - editor.animateTimeout = setTimeout(animate, 50); - } - else { - // finished - if (callback) { - callback(true); - } - content.scrollTop = finalScrollTop; - delete editor.animateTimeout; - delete editor.animateCallback; - } - }; - animate(); - } - else { - if (callback) { - callback(false); - } - } -}; - -/** - * Create main frame - * @private - */ -TreeEditor.prototype._createFrame = function () { - // create the frame - this.frame = document.createElement('div'); - this.frame.className = 'jsoneditor'; - this.container.appendChild(this.frame); - - // create one global event listener to handle all events from all nodes - var editor = this; - var onEvent = function (event) { - editor._onEvent(event); - }; - this.frame.onclick = function (event) { - var target = event.target;// || event.srcElement; - - onEvent(event); - - // prevent default submit action of buttons when TreeEditor is located - // inside a form - if (target.nodeName == 'BUTTON') { - event.preventDefault(); - } - }; - this.frame.oninput = onEvent; - this.frame.onchange = onEvent; - this.frame.onkeydown = onEvent; - this.frame.onkeyup = onEvent; - this.frame.oncut = onEvent; - this.frame.onpaste = onEvent; - this.frame.onmousedown = onEvent; - this.frame.onmouseup = onEvent; - this.frame.onmouseover = onEvent; - this.frame.onmouseout = onEvent; - // Note: focus and blur events do not propagate, therefore they defined - // using an eventListener with useCapture=true - // see http://www.quirksmode.org/blog/archives/2008/04/delegating_the.html - util.addEventListener(this.frame, 'focus', onEvent, true); - util.addEventListener(this.frame, 'blur', onEvent, true); - this.frame.onfocusin = onEvent; // for IE - this.frame.onfocusout = onEvent; // for IE - - // create menu - this.menu = document.createElement('div'); - this.menu.className = 'menu'; - this.frame.appendChild(this.menu); - - // create expand all button - var expandAll = document.createElement('button'); - expandAll.className = 'expand-all'; - expandAll.title = 'Expand all fields'; - expandAll.onclick = function () { - editor.expandAll(); - }; - this.menu.appendChild(expandAll); - - // create expand all button - var collapseAll = document.createElement('button'); - collapseAll.title = 'Collapse all fields'; - collapseAll.className = 'collapse-all'; - collapseAll.onclick = function () { - editor.collapseAll(); - }; - this.menu.appendChild(collapseAll); - - // create undo/redo buttons - if (this.history) { - // create undo button - var undo = document.createElement('button'); - undo.className = 'undo separator'; - undo.title = 'Undo last action (Ctrl+Z)'; - undo.onclick = function () { - editor._onUndo(); - }; - this.menu.appendChild(undo); - this.dom.undo = undo; - - // create redo button - var redo = document.createElement('button'); - redo.className = 'redo'; - redo.title = 'Redo (Ctrl+Shift+Z)'; - redo.onclick = function () { - editor._onRedo(); - }; - this.menu.appendChild(redo); - this.dom.redo = redo; - - // register handler for onchange of history - this.history.onChange = function () { - undo.disabled = !editor.history.canUndo(); - redo.disabled = !editor.history.canRedo(); - }; - this.history.onChange(); - } - - // create mode box - if (this.options && this.options.modes && this.options.modes.length) { - var modeBox = createModeBox(this, this.options.modes, this.options.mode); - this.menu.appendChild(modeBox); - this.dom.modeBox = modeBox; - } - - // create search box - if (this.options.search) { - this.searchBox = new SearchBox(this, this.menu); - } -}; - -/** - * Perform an undo action - * @private - */ -TreeEditor.prototype._onUndo = function () { - if (this.history) { - // undo last action - this.history.undo(); - - // trigger change callback - if (this.options.change) { - this.options.change(); - } - } -}; - -/** - * Perform a redo action - * @private - */ -TreeEditor.prototype._onRedo = function () { - if (this.history) { - // redo last action - this.history.redo(); - - // trigger change callback - if (this.options.change) { - this.options.change(); - } - } -}; - -/** - * Event handler - * @param event - * @private - */ -TreeEditor.prototype._onEvent = function (event) { - var target = event.target; - - if (event.type == 'keydown') { - this._onKeyDown(event); - } - - if (event.type == 'focus') { - TreeEditor.domFocus = target; - } - - var node = Node.getNodeFromTarget(target); - if (node) { - node.onEvent(event); - } -}; - -/** - * Event handler for keydown. Handles shortcut keys - * @param {Event} event - * @private - */ -TreeEditor.prototype._onKeyDown = function (event) { - var keynum = event.which || event.keyCode; - var ctrlKey = event.ctrlKey; - var shiftKey = event.shiftKey; - var handled = false; - - if (keynum == 9) { // Tab or Shift+Tab - setTimeout(function () { - // select all text when moving focus to an editable div - util.selectContentEditable(TreeEditor.domFocus); - }, 0); - } - - if (this.searchBox) { - if (ctrlKey && keynum == 70) { // Ctrl+F - this.searchBox.dom.search.focus(); - this.searchBox.dom.search.select(); - handled = true; - } - else if (keynum == 114 || (ctrlKey && keynum == 71)) { // F3 or Ctrl+G - var focus = true; - if (!shiftKey) { - // select next search result (F3 or Ctrl+G) - this.searchBox.next(focus); - } - else { - // select previous search result (Shift+F3 or Ctrl+Shift+G) - this.searchBox.previous(focus); - } - - handled = true; - } - } - - if (this.history) { - if (ctrlKey && !shiftKey && keynum == 90) { // Ctrl+Z - // undo - this._onUndo(); - handled = true; - } - else if (ctrlKey && shiftKey && keynum == 90) { // Ctrl+Shift+Z - // redo - this._onRedo(); - handled = true; - } - } - - if (handled) { - event.preventDefault(); - event.stopPropagation(); - } -}; - -/** - * Create main table - * @private - */ -TreeEditor.prototype._createTable = function () { - var contentOuter = document.createElement('div'); - contentOuter.className = 'outer'; - this.contentOuter = contentOuter; - - this.content = document.createElement('div'); - this.content.className = 'tree'; - contentOuter.appendChild(this.content); - - this.table = document.createElement('table'); - this.table.className = 'tree'; - this.content.appendChild(this.table); - - // create colgroup where the first two columns don't have a fixed - // width, and the edit columns do have a fixed width - var col; - this.colgroupContent = document.createElement('colgroup'); - if (this.mode.edit) { - col = document.createElement('col'); - col.width = "24px"; - this.colgroupContent.appendChild(col); - } - col = document.createElement('col'); - col.width = "24px"; - this.colgroupContent.appendChild(col); - col = document.createElement('col'); - this.colgroupContent.appendChild(col); - this.table.appendChild(this.colgroupContent); - - this.tbody = document.createElement('tbody'); - this.table.appendChild(this.tbody); - - this.frame.appendChild(contentOuter); -}; - -// register modes at the JSONEditor -JSONEditor.modes.tree = { - editor: TreeEditor, - data: 'json' -}; -JSONEditor.modes.view = { - editor: TreeEditor, - data: 'json' -}; -JSONEditor.modes.form = { - editor: TreeEditor, - data: 'json' -}; -// Deprecated modes (deprecated since version 2.2.0) -JSONEditor.modes.editor = { - editor: TreeEditor, - data: 'json' -}; -JSONEditor.modes.viewer = { - editor: TreeEditor, - data: 'json' -}; - -/** - * Create a TextEditor and attach it to given container - * @constructor TextEditor - * @param {Element} container - * @param {Object} [options] Object with options. available options: - * {String} mode Available values: - * "text" (default) - * or "code". - * {Number} indentation Number of indentation - * spaces. 4 by default. - * {function} change Callback method - * triggered on change - * @param {JSON | String} [json] initial contents of the formatter - */ -function TextEditor(container, options, json) { - if (!(this instanceof TextEditor)) { - throw new Error('TextEditor constructor called without "new".'); - } - - this._create(container, options, json); -} - -/** - * Create a TextEditor and attach it to given container - * @constructor TextEditor - * @param {Element} container - * @param {Object} [options] See description in constructor - * @param {JSON | String} [json] initial contents of the formatter - * @private - */ -TextEditor.prototype._create = function (container, options, json) { - // read options - options = options || {}; - this.options = options; - if (options.indentation) { - this.indentation = Number(options.indentation); - } - else { - this.indentation = 2; // number of spaces - } - this.mode = (options.mode == 'code') ? 'code' : 'text'; - if (this.mode == 'code') { - // verify whether Ace editor is available and supported - if (typeof ace === 'undefined') { - this.mode = 'text'; - util.log('WARNING: Cannot load code editor, Ace library not loaded. ' + - 'Falling back to plain text editor'); - } - } - - var me = this; - this.container = container; - this.dom = {}; - this.editor = undefined; // ace code editor - this.textarea = undefined; // plain text editor (fallback when Ace is not available) - - this.width = container.clientWidth; - this.height = container.clientHeight; - - this.frame = document.createElement('div'); - this.frame.className = 'jsoneditor'; - this.frame.onclick = function (event) { - // prevent default submit action when TextEditor is located inside a form - event.preventDefault(); - }; - - // create menu - this.menu = document.createElement('div'); - this.menu.className = 'menu'; - this.frame.appendChild(this.menu); - - // create format button - var buttonFormat = document.createElement('button'); - buttonFormat.className = 'format'; - buttonFormat.title = 'Format JSON data, with proper indentation and line feeds'; - this.menu.appendChild(buttonFormat); - buttonFormat.onclick = function () { - try { - me.format(); - } - catch (err) { - me._onError(err); - } - }; - - // create compact button - var buttonCompact = document.createElement('button'); - buttonCompact.className = 'compact'; - buttonCompact.title = 'Compact JSON data, remove all whitespaces'; - this.menu.appendChild(buttonCompact); - buttonCompact.onclick = function () { - try { - me.compact(); - } - catch (err) { - me._onError(err); - } - }; - - // create mode box - if (this.options && this.options.modes && this.options.modes.length) { - var modeBox = createModeBox(this, this.options.modes, this.options.mode); - this.menu.appendChild(modeBox); - this.dom.modeBox = modeBox; - } - - this.content = document.createElement('div'); - this.content.className = 'outer'; - this.frame.appendChild(this.content); - - this.container.appendChild(this.frame); - - if (this.mode == 'code') { - this.editorDom = document.createElement('div'); - this.editorDom.style.height = '100%'; // TODO: move to css - this.editorDom.style.width = '100%'; // TODO: move to css - this.content.appendChild(this.editorDom); - - var editor = ace.edit(this.editorDom); - editor.setTheme('ace/theme/jsoneditor'); - editor.setShowPrintMargin(false); - editor.setFontSize(13); - editor.getSession().setMode('ace/mode/json'); - editor.getSession().setUseSoftTabs(true); - editor.getSession().setUseWrapMode(true); - this.editor = editor; - - var poweredBy = document.createElement('a'); - poweredBy.appendChild(document.createTextNode('powered by ace')); - poweredBy.href = 'http://ace.ajax.org'; - poweredBy.target = '_blank'; - poweredBy.className = 'poweredBy'; - poweredBy.onclick = function () { - // TODO: this anchor falls below the margin of the content, - // therefore the normal a.href does not work. We use a click event - // for now, but this should be fixed. - window.open(poweredBy.href, poweredBy.target); - }; - this.menu.appendChild(poweredBy); - - if (options.change) { - // register onchange event - editor.on('change', function () { - options.change(); - }); - } - } - else { - // load a plain text textarea - var textarea = document.createElement('textarea'); - textarea.className = 'text'; - textarea.spellcheck = false; - this.content.appendChild(textarea); - this.textarea = textarea; - - if (options.change) { - // register onchange event - if (this.textarea.oninput === null) { - this.textarea.oninput = function () { - options.change(); - } - } - else { - // oninput is undefined. For IE8- - this.textarea.onchange = function () { - options.change(); - } - } - } - } - - // load initial json object or string - if (typeof(json) == 'string') { - this.setText(json); - } - else { - this.set(json); - } -}; - -/** - * Detach the editor from the DOM - * @private - */ -TextEditor.prototype._delete = function () { - if (this.frame && this.container && this.frame.parentNode == this.container) { - this.container.removeChild(this.frame); - } -}; - -/** - * Throw an error. If an error callback is configured in options.error, this - * callback will be invoked. Else, a regular error is thrown. - * @param {Error} err - * @private - */ -TextEditor.prototype._onError = function(err) { - // TODO: onError is deprecated since version 2.2.0. cleanup some day - if (typeof this.onError === 'function') { - util.log('WARNING: JSONEditor.onError is deprecated. ' + - 'Use options.error instead.'); - this.onError(err); - } - - if (this.options && typeof this.options.error === 'function') { - this.options.error(err); - } - else { - throw err; - } -}; - -/** - * Compact the code in the formatter - */ -TextEditor.prototype.compact = function () { - var json = util.parse(this.getText()); - this.setText(JSON.stringify(json)); -}; - -/** - * Format the code in the formatter - */ -TextEditor.prototype.format = function () { - var json = util.parse(this.getText()); - this.setText(JSON.stringify(json, null, this.indentation)); -}; - -/** - * Set focus to the formatter - */ -TextEditor.prototype.focus = function () { - if (this.textarea) { - this.textarea.focus(); - } - if (this.editor) { - this.editor.focus(); - } -}; - -/** - * Resize the formatter - */ -TextEditor.prototype.resize = function () { - if (this.editor) { - var force = false; - this.editor.resize(force); - } -}; - -/** - * Set json data in the formatter - * @param {Object} json - */ -TextEditor.prototype.set = function(json) { - this.setText(JSON.stringify(json, null, this.indentation)); -}; - -/** - * Get json data from the formatter - * @return {Object} json - */ -TextEditor.prototype.get = function() { - return util.parse(this.getText()); -}; - -/** - * Get the text contents of the TextEditor - * @return {String} jsonText - */ -TextEditor.prototype.getText = function() { - if (this.textarea) { - return this.textarea.value; - } - if (this.editor) { - return this.editor.getValue(); - } - return ''; -}; - -/** - * Set the text contents of the TextEditor - * @param {String} jsonText - */ -TextEditor.prototype.setText = function(jsonText) { - if (this.textarea) { - this.textarea.value = jsonText; - } - if (this.editor) { - this.editor.setValue(jsonText, -1); - } -}; - -// register modes at the JSONEditor -JSONEditor.modes.text = { - editor: TextEditor, - data: 'text', - load: TextEditor.prototype.format -}; -JSONEditor.modes.code = { - editor: TextEditor, - data: 'text', - load: TextEditor.prototype.format -}; - -/** - * @constructor Node - * Create a new Node - * @param {TreeEditor} editor - * @param {Object} [params] Can contain parameters: - * {string} field - * {boolean} fieldEditable - * {*} value - * {String} type Can have values 'auto', 'array', - * 'object', or 'string'. - */ -function Node (editor, params) { - /** @type {TreeEditor} */ - this.editor = editor; - this.dom = {}; - this.expanded = false; - - if(params && (params instanceof Object)) { - this.setField(params.field, params.fieldEditable); - this.setValue(params.value, params.type); - } - else { - this.setField(''); - this.setValue(null); - } -}; - -/** - * Set parent node - * @param {Node} parent - */ -Node.prototype.setParent = function(parent) { - this.parent = parent; -}; - -/** - * Set field - * @param {String} field - * @param {boolean} [fieldEditable] - */ -Node.prototype.setField = function(field, fieldEditable) { - this.field = field; - this.fieldEditable = (fieldEditable == true); -}; - -/** - * Get field - * @return {String} - */ -Node.prototype.getField = function() { - if (this.field === undefined) { - this._getDomField(); - } - - return this.field; -}; - -/** - * Set value. Value is a JSON structure or an element String, Boolean, etc. - * @param {*} value - * @param {String} [type] Specify the type of the value. Can be 'auto', - * 'array', 'object', or 'string' - */ -Node.prototype.setValue = function(value, type) { - var childValue, child; - - // first clear all current childs (if any) - var childs = this.childs; - if (childs) { - while (childs.length) { - this.removeChild(childs[0]); - } - } - - // TODO: remove the DOM of this Node - - this.type = this._getType(value); - - // check if type corresponds with the provided type - if (type && type != this.type) { - if (type == 'string' && this.type == 'auto') { - this.type = type; - } - else { - throw new Error('Type mismatch: ' + - 'cannot cast value of type "' + this.type + - ' to the specified type "' + type + '"'); - } - } - - if (this.type == 'array') { - // array - this.childs = []; - for (var i = 0, iMax = value.length; i < iMax; i++) { - childValue = value[i]; - if (childValue !== undefined && !(childValue instanceof Function)) { - // ignore undefined and functions - child = new Node(this.editor, { - 'value': childValue - }); - this.appendChild(child); - } - } - this.value = ''; - } - else if (this.type == 'object') { - // object - this.childs = []; - for (var childField in value) { - if (value.hasOwnProperty(childField)) { - childValue = value[childField]; - if (childValue !== undefined && !(childValue instanceof Function)) { - // ignore undefined and functions - child = new Node(this.editor, { - 'field': childField, - 'value': childValue - }); - this.appendChild(child); - } - } - } - this.value = ''; - } - else { - // value - this.childs = undefined; - this.value = value; - /* TODO - if (typeof(value) == 'string') { - var escValue = JSON.stringify(value); - this.value = escValue.substring(1, escValue.length - 1); - util.log('check', value, this.value); - } - else { - this.value = value; - } - */ - } -}; - -/** - * Get value. Value is a JSON structure - * @return {*} value - */ -Node.prototype.getValue = function() { - //var childs, i, iMax; - - if (this.type == 'array') { - var arr = []; - this.childs.forEach (function (child) { - arr.push(child.getValue()); - }); - return arr; - } - else if (this.type == 'object') { - var obj = {}; - this.childs.forEach (function (child) { - obj[child.getField()] = child.getValue(); - }); - return obj; - } - else { - if (this.value === undefined) { - this._getDomValue(); - } - - return this.value; - } -}; - -/** - * Get the nesting level of this node - * @return {Number} level - */ -Node.prototype.getLevel = function() { - return (this.parent ? this.parent.getLevel() + 1 : 0); -}; - -/** - * Create a clone of a node - * The complete state of a clone is copied, including whether it is expanded or - * not. The DOM elements are not cloned. - * @return {Node} clone - */ -Node.prototype.clone = function() { - var clone = new Node(this.editor); - clone.type = this.type; - clone.field = this.field; - clone.fieldInnerText = this.fieldInnerText; - clone.fieldEditable = this.fieldEditable; - clone.value = this.value; - clone.valueInnerText = this.valueInnerText; - clone.expanded = this.expanded; - - if (this.childs) { - // an object or array - var cloneChilds = []; - this.childs.forEach(function (child) { - var childClone = child.clone(); - childClone.setParent(clone); - cloneChilds.push(childClone); - }); - clone.childs = cloneChilds; - } - else { - // a value - clone.childs = undefined; - } - - return clone; -}; - -/** - * Expand this node and optionally its childs. - * @param {boolean} [recurse] Optional recursion, true by default. When - * true, all childs will be expanded recursively - */ -Node.prototype.expand = function(recurse) { - if (!this.childs) { - return; - } - - // set this node expanded - this.expanded = true; - if (this.dom.expand) { - this.dom.expand.className = 'expanded'; - } - - this.showChilds(); - - if (recurse != false) { - this.childs.forEach(function (child) { - child.expand(recurse); - }); - } -}; - -/** - * Collapse this node and optionally its childs. - * @param {boolean} [recurse] Optional recursion, true by default. When - * true, all childs will be collapsed recursively - */ -Node.prototype.collapse = function(recurse) { - if (!this.childs) { - return; - } - - this.hideChilds(); - - // collapse childs in case of recurse - if (recurse != false) { - this.childs.forEach(function (child) { - child.collapse(recurse); - }); - - } - - // make this node collapsed - if (this.dom.expand) { - this.dom.expand.className = 'collapsed'; - } - this.expanded = false; -}; - -/** - * Recursively show all childs when they are expanded - */ -Node.prototype.showChilds = function() { - var childs = this.childs; - if (!childs) { - return; - } - if (!this.expanded) { - return; - } - - var tr = this.dom.tr; - var table = tr ? tr.parentNode : undefined; - if (table) { - // show row with append button - var append = this.getAppend(); - var nextTr = tr.nextSibling; - if (nextTr) { - table.insertBefore(append, nextTr); - } - else { - table.appendChild(append); - } - - // show childs - this.childs.forEach(function (child) { - table.insertBefore(child.getDom(), append); - child.showChilds(); - }); - } -}; - -/** - * Hide the node with all its childs - */ -Node.prototype.hide = function() { - var tr = this.dom.tr; - var table = tr ? tr.parentNode : undefined; - if (table) { - table.removeChild(tr); - } - this.hideChilds(); -}; - - -/** - * Recursively hide all childs - */ -Node.prototype.hideChilds = function() { - var childs = this.childs; - if (!childs) { - return; - } - if (!this.expanded) { - return; - } - - // hide append row - var append = this.getAppend(); - if (append.parentNode) { - append.parentNode.removeChild(append); - } - - // hide childs - this.childs.forEach(function (child) { - child.hide(); - }); -}; - - -/** - * Add a new child to the node. - * Only applicable when Node value is of type array or object - * @param {Node} node - */ -Node.prototype.appendChild = function(node) { - if (this._hasChilds()) { - // adjust the link to the parent - node.setParent(this); - node.fieldEditable = (this.type == 'object'); - if (this.type == 'array') { - node.index = this.childs.length; - } - this.childs.push(node); - - if (this.expanded) { - // insert into the DOM, before the appendRow - var newTr = node.getDom(); - var appendTr = this.getAppend(); - var table = appendTr ? appendTr.parentNode : undefined; - if (appendTr && table) { - table.insertBefore(newTr, appendTr); - } - - node.showChilds(); - } - - this.updateDom({'updateIndexes': true}); - node.updateDom({'recurse': true}); - } -}; - - -/** - * Move a node from its current parent to this node - * Only applicable when Node value is of type array or object - * @param {Node} node - * @param {Node} beforeNode - */ -Node.prototype.moveBefore = function(node, beforeNode) { - if (this._hasChilds()) { - // create a temporary row, to prevent the scroll position from jumping - // when removing the node - var tbody = (this.dom.tr) ? this.dom.tr.parentNode : undefined; - if (tbody) { - var trTemp = document.createElement('tr'); - trTemp.style.height = tbody.clientHeight + 'px'; - tbody.appendChild(trTemp); - } - - if (node.parent) { - node.parent.removeChild(node); - } - - if (beforeNode instanceof AppendNode) { - this.appendChild(node); - } - else { - this.insertBefore(node, beforeNode); - } - - if (tbody) { - tbody.removeChild(trTemp); - } - } -}; - -/** - * Move a node from its current parent to this node - * Only applicable when Node value is of type array or object. - * If index is out of range, the node will be appended to the end - * @param {Node} node - * @param {Number} index - */ -Node.prototype.moveTo = function (node, index) { - if (node.parent == this) { - // same parent - var currentIndex = this.childs.indexOf(node); - if (currentIndex < index) { - // compensate the index for removal of the node itself - index++; - } - } - - var beforeNode = this.childs[index] || this.append; - this.moveBefore(node, beforeNode); -}; - -/** - * Insert a new child before a given node - * Only applicable when Node value is of type array or object - * @param {Node} node - * @param {Node} beforeNode - */ -Node.prototype.insertBefore = function(node, beforeNode) { - if (this._hasChilds()) { - if (beforeNode == this.append) { - // append to the child nodes - - // adjust the link to the parent - node.setParent(this); - node.fieldEditable = (this.type == 'object'); - this.childs.push(node); - } - else { - // insert before a child node - var index = this.childs.indexOf(beforeNode); - if (index == -1) { - throw new Error('Node not found'); - } - - // adjust the link to the parent - node.setParent(this); - node.fieldEditable = (this.type == 'object'); - this.childs.splice(index, 0, node); - } - - if (this.expanded) { - // insert into the DOM - var newTr = node.getDom(); - var nextTr = beforeNode.getDom(); - var table = nextTr ? nextTr.parentNode : undefined; - if (nextTr && table) { - table.insertBefore(newTr, nextTr); - } - - node.showChilds(); - } - - this.updateDom({'updateIndexes': true}); - node.updateDom({'recurse': true}); - } -}; - -/** - * Insert a new child before a given node - * Only applicable when Node value is of type array or object - * @param {Node} node - * @param {Node} afterNode - */ -Node.prototype.insertAfter = function(node, afterNode) { - if (this._hasChilds()) { - var index = this.childs.indexOf(afterNode); - var beforeNode = this.childs[index + 1]; - if (beforeNode) { - this.insertBefore(node, beforeNode); - } - else { - this.appendChild(node); - } - } -}; - -/** - * Search in this node - * The node will be expanded when the text is found one of its childs, else - * it will be collapsed. Searches are case insensitive. - * @param {String} text - * @return {Node[]} results Array with nodes containing the search text - */ -Node.prototype.search = function(text) { - var results = []; - var index; - var search = text ? text.toLowerCase() : undefined; - - // delete old search data - delete this.searchField; - delete this.searchValue; - - // search in field - if (this.field != undefined) { - var field = String(this.field).toLowerCase(); - index = field.indexOf(search); - if (index != -1) { - this.searchField = true; - results.push({ - 'node': this, - 'elem': 'field' - }); - } - - // update dom - this._updateDomField(); - } - - // search in value - if (this._hasChilds()) { - // array, object - - // search the nodes childs - if (this.childs) { - var childResults = []; - this.childs.forEach(function (child) { - childResults = childResults.concat(child.search(text)); - }); - results = results.concat(childResults); - } - - // update dom - if (search != undefined) { - var recurse = false; - if (childResults.length == 0) { - this.collapse(recurse); - } - else { - this.expand(recurse); - } - } - } - else { - // string, auto - if (this.value != undefined ) { - var value = String(this.value).toLowerCase(); - index = value.indexOf(search); - if (index != -1) { - this.searchValue = true; - results.push({ - 'node': this, - 'elem': 'value' - }); - } - } - - // update dom - this._updateDomValue(); - } - - return results; -}; - -/** - * Move the scroll position such that this node is in the visible area. - * The node will not get the focus - * @param {function(boolean)} [callback] - */ -Node.prototype.scrollTo = function(callback) { - if (!this.dom.tr || !this.dom.tr.parentNode) { - // if the node is not visible, expand its parents - var parent = this.parent; - var recurse = false; - while (parent) { - parent.expand(recurse); - parent = parent.parent; - } - } - - if (this.dom.tr && this.dom.tr.parentNode) { - this.editor.scrollTo(this.dom.tr.offsetTop, callback); - } -}; - - -// stores the element name currently having the focus -Node.focusElement = undefined; - -/** - * Set focus to this node - * @param {String} [elementName] The field name of the element to get the - * focus available values: 'drag', 'menu', - * 'expand', 'field', 'value' (default) - */ -Node.prototype.focus = function(elementName) { - Node.focusElement = elementName; - - if (this.dom.tr && this.dom.tr.parentNode) { - var dom = this.dom; - - switch (elementName) { - case 'drag': - if (dom.drag) { - dom.drag.focus(); - } - else { - dom.menu.focus(); - } - break; - - case 'menu': - dom.menu.focus(); - break; - - case 'expand': - if (this._hasChilds()) { - dom.expand.focus(); - } - else if (dom.field && this.fieldEditable) { - dom.field.focus(); - util.selectContentEditable(dom.field); - } - else if (dom.value && !this._hasChilds()) { - dom.value.focus(); - util.selectContentEditable(dom.value); - } - else { - dom.menu.focus(); - } - break; - - case 'field': - if (dom.field && this.fieldEditable) { - dom.field.focus(); - util.selectContentEditable(dom.field); - } - else if (dom.value && !this._hasChilds()) { - dom.value.focus(); - util.selectContentEditable(dom.value); - } - else if (this._hasChilds()) { - dom.expand.focus(); - } - else { - dom.menu.focus(); - } - break; - - case 'value': - default: - if (dom.value && !this._hasChilds()) { - dom.value.focus(); - util.selectContentEditable(dom.value); - } - else if (dom.field && this.fieldEditable) { - dom.field.focus(); - util.selectContentEditable(dom.field); - } - else if (this._hasChilds()) { - dom.expand.focus(); - } - else { - dom.menu.focus(); - } - break; - } - } -}; - -/** - * Select all text in an editable div after a delay of 0 ms - * @param {Element} editableDiv - */ -Node.select = function(editableDiv) { - setTimeout(function () { - util.selectContentEditable(editableDiv); - }, 0); -}; - -/** - * Update the values from the DOM field and value of this node - */ -Node.prototype.blur = function() { - // retrieve the actual field and value from the DOM. - this._getDomValue(false); - this._getDomField(false); -}; - -/** - * Duplicate given child node - * new structure will be added right before the cloned node - * @param {Node} node the childNode to be duplicated - * @return {Node} clone the clone of the node - * @private - */ -Node.prototype._duplicate = function(node) { - var clone = node.clone(); - - /* TODO: adjust the field name (to prevent equal field names) - if (this.type == 'object') { - } - */ - - this.insertAfter(clone, node); - - return clone; -}; - -/** - * Check if given node is a child. The method will check recursively to find - * this node. - * @param {Node} node - * @return {boolean} containsNode - */ -Node.prototype.containsNode = function(node) { - if (this == node) { - return true; - } - - var childs = this.childs; - if (childs) { - // TODO: use the js5 Array.some() here? - for (var i = 0, iMax = childs.length; i < iMax; i++) { - if (childs[i].containsNode(node)) { - return true; - } - } - } - - return false; -}; - -/** - * Move given node into this node - * @param {Node} node the childNode to be moved - * @param {Node} beforeNode node will be inserted before given - * node. If no beforeNode is given, - * the node is appended at the end - * @private - */ -Node.prototype._move = function(node, beforeNode) { - if (node == beforeNode) { - // nothing to do... - return; - } - - // check if this node is not a child of the node to be moved here - if (node.containsNode(this)) { - throw new Error('Cannot move a field into a child of itself'); - } - - // remove the original node - if (node.parent) { - node.parent.removeChild(node); - } - - // create a clone of the node - var clone = node.clone(); - node.clearDom(); - - // insert or append the node - if (beforeNode) { - this.insertBefore(clone, beforeNode); - } - else { - this.appendChild(clone); - } - - /* TODO: adjust the field name (to prevent equal field names) - if (this.type == 'object') { - } - */ -}; - -/** - * Remove a child from the node. - * Only applicable when Node value is of type array or object - * @param {Node} node The child node to be removed; - * @return {Node | undefined} node The removed node on success, - * else undefined - */ -Node.prototype.removeChild = function(node) { - if (this.childs) { - var index = this.childs.indexOf(node); - - if (index != -1) { - node.hide(); - - // delete old search results - delete node.searchField; - delete node.searchValue; - - var removedNode = this.childs.splice(index, 1)[0]; - - this.updateDom({'updateIndexes': true}); - - return removedNode; - } - } - - return undefined; -}; - -/** - * Remove a child node node from this node - * This method is equal to Node.removeChild, except that _remove firex an - * onChange event. - * @param {Node} node - * @private - */ -Node.prototype._remove = function (node) { - this.removeChild(node); -}; - -/** - * Change the type of the value of this Node - * @param {String} newType - */ -Node.prototype.changeType = function (newType) { - var oldType = this.type; - - if (oldType == newType) { - // type is not changed - return; - } - - if ((newType == 'string' || newType == 'auto') && - (oldType == 'string' || oldType == 'auto')) { - // this is an easy change - this.type = newType; - } - else { - // change from array to object, or from string/auto to object/array - var table = this.dom.tr ? this.dom.tr.parentNode : undefined; - var lastTr; - if (this.expanded) { - lastTr = this.getAppend(); - } - else { - lastTr = this.getDom(); - } - var nextTr = (lastTr && lastTr.parentNode) ? lastTr.nextSibling : undefined; - - // hide current field and all its childs - this.hide(); - this.clearDom(); - - // adjust the field and the value - this.type = newType; - - // adjust childs - if (newType == 'object') { - if (!this.childs) { - this.childs = []; - } - - this.childs.forEach(function (child, index) { - child.clearDom(); - delete child.index; - child.fieldEditable = true; - if (child.field == undefined) { - child.field = ''; - } - }); - - if (oldType == 'string' || oldType == 'auto') { - this.expanded = true; - } - } - else if (newType == 'array') { - if (!this.childs) { - this.childs = []; - } - - this.childs.forEach(function (child, index) { - child.clearDom(); - child.fieldEditable = false; - child.index = index; - }); - - if (oldType == 'string' || oldType == 'auto') { - this.expanded = true; - } - } - else { - this.expanded = false; - } - - // create new DOM - if (table) { - if (nextTr) { - table.insertBefore(this.getDom(), nextTr); - } - else { - table.appendChild(this.getDom()); - } - } - this.showChilds(); - } - - if (newType == 'auto' || newType == 'string') { - // cast value to the correct type - if (newType == 'string') { - this.value = String(this.value); - } - else { - this.value = this._stringCast(String(this.value)); - } - - this.focus(); - } - - this.updateDom({'updateIndexes': true}); -}; - -/** - * Retrieve value from DOM - * @param {boolean} [silent] If true (default), no errors will be thrown in - * case of invalid data - * @private - */ -Node.prototype._getDomValue = function(silent) { - if (this.dom.value && this.type != 'array' && this.type != 'object') { - this.valueInnerText = util.getInnerText(this.dom.value); - } - - if (this.valueInnerText != undefined) { - try { - // retrieve the value - var value; - if (this.type == 'string') { - value = this._unescapeHTML(this.valueInnerText); - } - else { - var str = this._unescapeHTML(this.valueInnerText); - value = this._stringCast(str); - } - if (value !== this.value) { - var oldValue = this.value; - this.value = value; - this.editor._onAction('editValue', { - 'node': this, - 'oldValue': oldValue, - 'newValue': value, - 'oldSelection': this.editor.selection, - 'newSelection': this.editor.getSelection() - }); - } - } - catch (err) { - this.value = undefined; - // TODO: sent an action with the new, invalid value? - if (silent != true) { - throw err; - } - } - } -}; - -/** - * Update dom value: - * - the text color of the value, depending on the type of the value - * - the height of the field, depending on the width - * - background color in case it is empty - * @private - */ -Node.prototype._updateDomValue = function () { - var domValue = this.dom.value; - if (domValue) { - // set text color depending on value type - // TODO: put colors in css - var v = this.value; - var t = (this.type == 'auto') ? util.type(v) : this.type; - var isUrl = (t == 'string' && util.isUrl(v)); - var color = ''; - if (isUrl && !this.editor.mode.edit) { - color = ''; - } - else if (t == 'string') { - color = 'green'; - } - else if (t == 'number') { - color = 'red'; - } - else if (t == 'boolean') { - color = 'darkorange'; - } - else if (this._hasChilds()) { - color = ''; - } - else if (v === null) { - color = '#004ED0'; // blue - } - else { - // invalid value - color = 'black'; - } - domValue.style.color = color; - - // make background color light-gray when empty - var isEmpty = (String(this.value) == '' && this.type != 'array' && this.type != 'object'); - if (isEmpty) { - util.addClassName(domValue, 'empty'); - } - else { - util.removeClassName(domValue, 'empty'); - } - - // underline url - if (isUrl) { - util.addClassName(domValue, 'url'); - } - else { - util.removeClassName(domValue, 'url'); - } - - // update title - if (t == 'array' || t == 'object') { - var count = this.childs ? this.childs.length : 0; - domValue.title = this.type + ' containing ' + count + ' items'; - } - else if (t == 'string' && util.isUrl(v)) { - if (this.editor.mode.edit) { - domValue.title = 'Ctrl+Click or Ctrl+Enter to open url in new window'; - } - } - else { - domValue.title = ''; - } - - // highlight when there is a search result - if (this.searchValueActive) { - util.addClassName(domValue, 'highlight-active'); - } - else { - util.removeClassName(domValue, 'highlight-active'); - } - if (this.searchValue) { - util.addClassName(domValue, 'highlight'); - } - else { - util.removeClassName(domValue, 'highlight'); - } - - // strip formatting from the contents of the editable div - util.stripFormatting(domValue); - } -}; - -/** - * Update dom field: - * - the text color of the field, depending on the text - * - the height of the field, depending on the width - * - background color in case it is empty - * @private - */ -Node.prototype._updateDomField = function () { - var domField = this.dom.field; - if (domField) { - // make backgound color lightgray when empty - var isEmpty = (String(this.field) == '' && this.parent.type != 'array'); - if (isEmpty) { - util.addClassName(domField, 'empty'); - } - else { - util.removeClassName(domField, 'empty'); - } - - // highlight when there is a search result - if (this.searchFieldActive) { - util.addClassName(domField, 'highlight-active'); - } - else { - util.removeClassName(domField, 'highlight-active'); - } - if (this.searchField) { - util.addClassName(domField, 'highlight'); - } - else { - util.removeClassName(domField, 'highlight'); - } - - // strip formatting from the contents of the editable div - util.stripFormatting(domField); - } -}; - -/** - * Retrieve field from DOM - * @param {boolean} [silent] If true (default), no errors will be thrown in - * case of invalid data - * @private - */ -Node.prototype._getDomField = function(silent) { - if (this.dom.field && this.fieldEditable) { - this.fieldInnerText = util.getInnerText(this.dom.field); - } - - if (this.fieldInnerText != undefined) { - try { - var field = this._unescapeHTML(this.fieldInnerText); - - if (field !== this.field) { - var oldField = this.field; - this.field = field; - this.editor._onAction('editField', { - 'node': this, - 'oldValue': oldField, - 'newValue': field, - 'oldSelection': this.editor.selection, - 'newSelection': this.editor.getSelection() - }); - } - } - catch (err) { - this.field = undefined; - // TODO: sent an action here, with the new, invalid value? - if (silent != true) { - throw err; - } - } - } -}; - -/** - * Clear the dom of the node - */ -Node.prototype.clearDom = function() { - // TODO: hide the node first? - //this.hide(); - // TODO: recursively clear dom? - - this.dom = {}; -}; - -/** - * Get the HTML DOM TR element of the node. - * The dom will be generated when not yet created - * @return {Element} tr HTML DOM TR Element - */ -Node.prototype.getDom = function() { - var dom = this.dom; - if (dom.tr) { - return dom.tr; - } - - // create row - dom.tr = document.createElement('tr'); - dom.tr.node = this; - - if (this.editor.mode.edit) { - // create draggable area - var tdDrag = document.createElement('td'); - if (this.parent) { - var domDrag = document.createElement('button'); - dom.drag = domDrag; - domDrag.className = 'dragarea'; - domDrag.title = 'Drag to move this field (Alt+Shift+Arrows)'; - tdDrag.appendChild(domDrag); - } - dom.tr.appendChild(tdDrag); - - // create context menu - var tdMenu = document.createElement('td'); - var menu = document.createElement('button'); - dom.menu = menu; - menu.className = 'contextmenu'; - menu.title = 'Click to open the actions menu (Ctrl+M)'; - tdMenu.appendChild(dom.menu); - dom.tr.appendChild(tdMenu); - } - - // create tree and field - var tdField = document.createElement('td'); - dom.tr.appendChild(tdField); - dom.tree = this._createDomTree(); - tdField.appendChild(dom.tree); - - this.updateDom({'updateIndexes': true}); - - return dom.tr; -}; - -/** - * DragStart event, fired on mousedown on the dragarea at the left side of a Node - * @param {Event} event - * @private - */ -Node.prototype._onDragStart = function (event) { - var node = this; - if (!this.mousemove) { - this.mousemove = util.addEventListener(document, 'mousemove', - function (event) { - node._onDrag(event); - }); - } - - if (!this.mouseup) { - this.mouseup = util.addEventListener(document, 'mouseup', - function (event ) { - node._onDragEnd(event); - }); - } - - this.editor.highlighter.lock(); - this.drag = { - 'oldCursor': document.body.style.cursor, - 'startParent': this.parent, - 'startIndex': this.parent.childs.indexOf(this), - 'mouseX': event.pageX, - 'level': this.getLevel() - }; - document.body.style.cursor = 'move'; - - event.preventDefault(); -}; - -/** - * Drag event, fired when moving the mouse while dragging a Node - * @param {Event} event - * @private - */ -Node.prototype._onDrag = function (event) { - // TODO: this method has grown too large. Split it in a number of methods - var mouseY = event.pageY; - var mouseX = event.pageX; - - var trThis, trPrev, trNext, trFirst, trLast, trRoot; - var nodePrev, nodeNext; - var topThis, topPrev, topFirst, heightThis, bottomNext, heightNext; - var moved = false; - - // TODO: add an ESC option, which resets to the original position - - // move up/down - trThis = this.dom.tr; - topThis = util.getAbsoluteTop(trThis); - heightThis = trThis.offsetHeight; - if (mouseY < topThis) { - // move up - trPrev = trThis; - do { - trPrev = trPrev.previousSibling; - nodePrev = Node.getNodeFromTarget(trPrev); - topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0; - } - while (trPrev && mouseY < topPrev); - - if (nodePrev && !nodePrev.parent) { - nodePrev = undefined; - } - - if (!nodePrev) { - // move to the first node - trRoot = trThis.parentNode.firstChild; - trPrev = trRoot ? trRoot.nextSibling : undefined; - nodePrev = Node.getNodeFromTarget(trPrev); - if (nodePrev == this) { - nodePrev = undefined; - } - } - - if (nodePrev) { - // check if mouseY is really inside the found node - trPrev = nodePrev.dom.tr; - topPrev = trPrev ? util.getAbsoluteTop(trPrev) : 0; - if (mouseY > topPrev + heightThis) { - nodePrev = undefined; - } - } - - if (nodePrev) { - nodePrev.parent.moveBefore(this, nodePrev); - moved = true; - } - } - else { - // move down - trLast = (this.expanded && this.append) ? this.append.getDom() : this.dom.tr; - trFirst = trLast ? trLast.nextSibling : undefined; - if (trFirst) { - topFirst = util.getAbsoluteTop(trFirst); - trNext = trFirst; - do { - nodeNext = Node.getNodeFromTarget(trNext); - if (trNext) { - bottomNext = trNext.nextSibling ? - util.getAbsoluteTop(trNext.nextSibling) : 0; - heightNext = trNext ? (bottomNext - topFirst) : 0; - - if (nodeNext.parent.childs.length == 1 && nodeNext.parent.childs[0] == this) { - // We are about to remove the last child of this parent, - // which will make the parents appendNode visible. - topThis += 24 - 1; - // TODO: dangerous to suppose the height of the appendNode a constant of 24-1 px. - } - } - - trNext = trNext.nextSibling; - } - while (trNext && mouseY > topThis + heightNext); - - if (nodeNext && nodeNext.parent) { - // calculate the desired level - var diffX = (mouseX - this.drag.mouseX); - var diffLevel = Math.round(diffX / 24 / 2); - var level = this.drag.level + diffLevel; // desired level - var levelNext = nodeNext.getLevel(); // level to be - - // find the best fitting level (move upwards over the append nodes) - trPrev = nodeNext.dom.tr.previousSibling; - while (levelNext < level && trPrev) { - nodePrev = Node.getNodeFromTarget(trPrev); - if (nodePrev == this || nodePrev._isChildOf(this)) { - // neglect itself and its childs - } - else if (nodePrev instanceof AppendNode) { - var childs = nodePrev.parent.childs; - if (childs.length > 1 || - (childs.length == 1 && childs[0] != this)) { - // non-visible append node of a list of childs - // consisting of not only this node (else the - // append node will change into a visible "empty" - // text when removing this node). - nodeNext = Node.getNodeFromTarget(trPrev); - levelNext = nodeNext.getLevel(); - } - else { - break; - } - } - else { - break; - } - - trPrev = trPrev.previousSibling; - } - - // move the node when its position is changed - if (trLast.nextSibling != nodeNext.dom.tr) { - nodeNext.parent.moveBefore(this, nodeNext); - moved = true; - } - } - } - } - - if (moved) { - // update the dragging parameters when moved - this.drag.mouseX = mouseX; - this.drag.level = this.getLevel(); - } - - // auto scroll when hovering around the top of the editor - this.editor.startAutoScroll(mouseY); - - event.preventDefault(); -}; - -/** - * Drag event, fired on mouseup after having dragged a node - * @param {Event} event - * @private - */ -Node.prototype._onDragEnd = function (event) { - var params = { - 'node': this, - 'startParent': this.drag.startParent, - 'startIndex': this.drag.startIndex, - 'endParent': this.parent, - 'endIndex': this.parent.childs.indexOf(this) - }; - if ((params.startParent != params.endParent) || - (params.startIndex != params.endIndex)) { - // only register this action if the node is actually moved to another place - this.editor._onAction('moveNode', params); - } - - document.body.style.cursor = this.drag.oldCursor; - this.editor.highlighter.unlock(); - delete this.drag; - - if (this.mousemove) { - util.removeEventListener(document, 'mousemove', this.mousemove); - delete this.mousemove;} - if (this.mouseup) { - util.removeEventListener(document, 'mouseup', this.mouseup); - delete this.mouseup; - } - - // Stop any running auto scroll - this.editor.stopAutoScroll(); - - event.preventDefault(); -}; - -/** - * Test if this node is a child of an other node - * @param {Node} node - * @return {boolean} isChild - * @private - */ -Node.prototype._isChildOf = function (node) { - var n = this.parent; - while (n) { - if (n == node) { - return true; - } - n = n.parent; - } - - return false; -}; - -/** - * Create an editable field - * @return {Element} domField - * @private - */ -Node.prototype._createDomField = function () { - return document.createElement('div'); -}; - -/** - * Set highlighting for this node and all its childs. - * Only applied to the currently visible (expanded childs) - * @param {boolean} highlight - */ -Node.prototype.setHighlight = function (highlight) { - if (this.dom.tr) { - this.dom.tr.className = (highlight ? 'highlight' : ''); - - if (this.append) { - this.append.setHighlight(highlight); - } - - if (this.childs) { - this.childs.forEach(function (child) { - child.setHighlight(highlight); - }); - } - } -}; - -/** - * Update the value of the node. Only primitive types are allowed, no Object - * or Array is allowed. - * @param {String | Number | Boolean | null} value - */ -Node.prototype.updateValue = function (value) { - this.value = value; - this.updateDom(); -}; - -/** - * Update the field of the node. - * @param {String} field - */ -Node.prototype.updateField = function (field) { - this.field = field; - this.updateDom(); -}; - -/** - * Update the HTML DOM, optionally recursing through the childs - * @param {Object} [options] Available parameters: - * {boolean} [recurse] If true, the - * DOM of the childs will be updated recursively. - * False by default. - * {boolean} [updateIndexes] If true, the childs - * indexes of the node will be updated too. False by - * default. - */ -Node.prototype.updateDom = function (options) { - // update level indentation - var domTree = this.dom.tree; - if (domTree) { - domTree.style.marginLeft = this.getLevel() * 24 + 'px'; - } - - // update field - var domField = this.dom.field; - if (domField) { - if (this.fieldEditable == true) { - // parent is an object - domField.contentEditable = this.editor.mode.edit; - domField.spellcheck = false; - domField.className = 'field'; - } - else { - // parent is an array this is the root node - domField.className = 'readonly'; - } - - var field; - if (this.index != undefined) { - field = this.index; - } - else if (this.field != undefined) { - field = this.field; - } - else if (this._hasChilds()) { - field = this.type; - } - else { - field = ''; - } - domField.innerHTML = this._escapeHTML(field); - } - - // update value - var domValue = this.dom.value; - if (domValue) { - var count = this.childs ? this.childs.length : 0; - if (this.type == 'array') { - domValue.innerHTML = '[' + count + ']'; - } - else if (this.type == 'object') { - domValue.innerHTML = '{' + count + '}'; - } - else { - domValue.innerHTML = this._escapeHTML(this.value); - } - } - - // update field and value - this._updateDomField(); - this._updateDomValue(); - - // update childs indexes - if (options && options.updateIndexes == true) { - // updateIndexes is true or undefined - this._updateDomIndexes(); - } - - if (options && options.recurse == true) { - // recurse is true or undefined. update childs recursively - if (this.childs) { - this.childs.forEach(function (child) { - child.updateDom(options); - }); - } - } - - // update row with append button - if (this.append) { - this.append.updateDom(); - } -}; - -/** - * Update the DOM of the childs of a node: update indexes and undefined field - * names. - * Only applicable when structure is an array or object - * @private - */ -Node.prototype._updateDomIndexes = function () { - var domValue = this.dom.value; - var childs = this.childs; - if (domValue && childs) { - if (this.type == 'array') { - childs.forEach(function (child, index) { - child.index = index; - var childField = child.dom.field; - if (childField) { - childField.innerHTML = index; - } - }); - } - else if (this.type == 'object') { - childs.forEach(function (child) { - if (child.index != undefined) { - delete child.index; - - if (child.field == undefined) { - child.field = ''; - } - } - }); - } - } -}; - -/** - * Create an editable value - * @private - */ -Node.prototype._createDomValue = function () { - var domValue; - - if (this.type == 'array') { - domValue = document.createElement('div'); - domValue.className = 'readonly'; - domValue.innerHTML = '[...]'; - } - else if (this.type == 'object') { - domValue = document.createElement('div'); - domValue.className = 'readonly'; - domValue.innerHTML = '{...}'; - } - else { - if (!this.editor.mode.edit && util.isUrl(this.value)) { - // create a link in case of read-only editor and value containing an url - domValue = document.createElement('a'); - domValue.className = 'value'; - domValue.href = this.value; - domValue.target = '_blank'; - domValue.innerHTML = this._escapeHTML(this.value); - } - else { - // create and editable or read-only div - domValue = document.createElement('div'); - domValue.contentEditable = !this.editor.mode.view; - domValue.spellcheck = false; - domValue.className = 'value'; - domValue.innerHTML = this._escapeHTML(this.value); - } - } - - return domValue; -}; - -/** - * Create an expand/collapse button - * @return {Element} expand - * @private - */ -Node.prototype._createDomExpandButton = function () { - // create expand button - var expand = document.createElement('button'); - if (this._hasChilds()) { - expand.className = this.expanded ? 'expanded' : 'collapsed'; - expand.title = - 'Click to expand/collapse this field (Ctrl+E). \n' + - 'Ctrl+Click to expand/collapse including all childs.'; - } - else { - expand.className = 'invisible'; - expand.title = ''; - } - - return expand; -}; - - -/** - * Create a DOM tree element, containing the expand/collapse button - * @return {Element} domTree - * @private - */ -Node.prototype._createDomTree = function () { - var dom = this.dom; - var domTree = document.createElement('table'); - var tbody = document.createElement('tbody'); - domTree.style.borderCollapse = 'collapse'; // TODO: put in css - domTree.className = 'values'; - domTree.appendChild(tbody); - var tr = document.createElement('tr'); - tbody.appendChild(tr); - - // create expand button - var tdExpand = document.createElement('td'); - tdExpand.className = 'tree'; - tr.appendChild(tdExpand); - dom.expand = this._createDomExpandButton(); - tdExpand.appendChild(dom.expand); - dom.tdExpand = tdExpand; - - // create the field - var tdField = document.createElement('td'); - tdField.className = 'tree'; - tr.appendChild(tdField); - dom.field = this._createDomField(); - tdField.appendChild(dom.field); - dom.tdField = tdField; - - // create a separator - var tdSeparator = document.createElement('td'); - tdSeparator.className = 'tree'; - tr.appendChild(tdSeparator); - if (this.type != 'object' && this.type != 'array') { - tdSeparator.appendChild(document.createTextNode(':')); - tdSeparator.className = 'separator'; - } - dom.tdSeparator = tdSeparator; - - // create the value - var tdValue = document.createElement('td'); - tdValue.className = 'tree'; - tr.appendChild(tdValue); - dom.value = this._createDomValue(); - tdValue.appendChild(dom.value); - dom.tdValue = tdValue; - - return domTree; -}; - -/** - * Handle an event. The event is catched centrally by the editor - * @param {Event} event - */ -Node.prototype.onEvent = function (event) { - var type = event.type, - target = event.target || event.srcElement, - dom = this.dom, - node = this, - focusNode, - expandable = this._hasChilds(); - - // check if mouse is on menu or on dragarea. - // If so, highlight current row and its childs - if (target == dom.drag || target == dom.menu) { - if (type == 'mouseover') { - this.editor.highlighter.highlight(this); - } - else if (type == 'mouseout') { - this.editor.highlighter.unhighlight(); - } - } - - // drag events - if (type == 'mousedown' && target == dom.drag) { - this._onDragStart(event); - } - - // context menu events - if (type == 'click' && target == dom.menu) { - var highlighter = node.editor.highlighter; - highlighter.highlight(node); - highlighter.lock(); - util.addClassName(dom.menu, 'selected'); - this.showContextMenu(dom.menu, function () { - util.removeClassName(dom.menu, 'selected'); - highlighter.unlock(); - highlighter.unhighlight(); - }); - } - - // expand events - if (type == 'click' && target == dom.expand) { - if (expandable) { - var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all - this._onExpand(recurse); - } - } - - // value events - var domValue = dom.value; - if (target == domValue) { - //noinspection FallthroughInSwitchStatementJS - switch (type) { - case 'focus': - focusNode = this; - break; - - case 'blur': - case 'change': - this._getDomValue(true); - this._updateDomValue(); - if (this.value) { - domValue.innerHTML = this._escapeHTML(this.value); - } - break; - - case 'input': - this._getDomValue(true); - this._updateDomValue(); - break; - - case 'keydown': - case 'mousedown': - this.editor.selection = this.editor.getSelection(); - break; - - case 'click': - if (event.ctrlKey && this.editor.mode.edit) { - if (util.isUrl(this.value)) { - window.open(this.value, '_blank'); - } - } - break; - - case 'keyup': - this._getDomValue(true); - this._updateDomValue(); - break; - - case 'cut': - case 'paste': - setTimeout(function () { - node._getDomValue(true); - node._updateDomValue(); - }, 1); - break; - } - } - - // field events - var domField = dom.field; - if (target == domField) { - switch (type) { - case 'focus': - focusNode = this; - break; - - case 'blur': - case 'change': - this._getDomField(true); - this._updateDomField(); - if (this.field) { - domField.innerHTML = this._escapeHTML(this.field); - } - break; - - case 'input': - this._getDomField(true); - this._updateDomField(); - break; - - case 'keydown': - case 'mousedown': - this.editor.selection = this.editor.getSelection(); - break; - - case 'keyup': - this._getDomField(true); - this._updateDomField(); - break; - - case 'cut': - case 'paste': - setTimeout(function () { - node._getDomField(true); - node._updateDomField(); - }, 1); - break; - } - } - - // focus - // when clicked in whitespace left or right from the field or value, set focus - var domTree = dom.tree; - if (target == domTree.parentNode) { - switch (type) { - case 'click': - var left = (event.offsetX != undefined) ? - (event.offsetX < (this.getLevel() + 1) * 24) : - (event.pageX < util.getAbsoluteLeft(dom.tdSeparator));// for FF - if (left || expandable) { - // node is expandable when it is an object or array - if (domField) { - util.setEndOfContentEditable(domField); - domField.focus(); - } - } - else { - if (domValue) { - util.setEndOfContentEditable(domValue); - domValue.focus(); - } - } - break; - } - } - if ((target == dom.tdExpand && !expandable) || target == dom.tdField || - target == dom.tdSeparator) { - switch (type) { - case 'click': - if (domField) { - util.setEndOfContentEditable(domField); - domField.focus(); - } - break; - } - } - - if (type == 'keydown') { - this.onKeyDown(event); - } -}; - -/** - * Key down event handler - * @param {Event} event - */ -Node.prototype.onKeyDown = function (event) { - var keynum = event.which || event.keyCode; - var target = event.target || event.srcElement; - var ctrlKey = event.ctrlKey; - var shiftKey = event.shiftKey; - var altKey = event.altKey; - var handled = false; - var prevNode, nextNode, nextDom, nextDom2; - - // util.log(ctrlKey, keynum, event.charCode); // TODO: cleanup - if (keynum == 13) { // Enter - if (target == this.dom.value) { - if (!this.editor.mode.edit || event.ctrlKey) { - if (util.isUrl(this.value)) { - window.open(this.value, '_blank'); - handled = true; - } - } - } - else if (target == this.dom.expand) { - var expandable = this._hasChilds(); - if (expandable) { - var recurse = event.ctrlKey; // with ctrl-key, expand/collapse all - this._onExpand(recurse); - target.focus(); - handled = true; - } - } - } - else if (keynum == 68) { // D - if (ctrlKey) { // Ctrl+D - this._onDuplicate(); - handled = true; - } - } - else if (keynum == 69) { // E - if (ctrlKey) { // Ctrl+E and Ctrl+Shift+E - this._onExpand(shiftKey); // recurse = shiftKey - target.focus(); // TODO: should restore focus in case of recursing expand (which takes DOM offline) - handled = true; - } - } - else if (keynum == 77) { // M - if (ctrlKey) { // Ctrl+M - this.showContextMenu(target); - handled = true; - } - } - else if (keynum == 46) { // Del - if (ctrlKey) { // Ctrl+Del - this._onRemove(); - handled = true; - } - } - else if (keynum == 45) { // Ins - if (ctrlKey && !shiftKey) { // Ctrl+Ins - this._onInsertBefore(); - handled = true; - } - else if (ctrlKey && shiftKey) { // Ctrl+Shift+Ins - this._onInsertAfter(); - handled = true; - } - } - else if (keynum == 35) { // End - if (altKey) { // Alt+End - // find the last node - var lastNode = this._lastNode(); - if (lastNode) { - lastNode.focus(Node.focusElement || this._getElementName(target)); - } - handled = true; - } - } - else if (keynum == 36) { // Home - if (altKey) { // Alt+Home - // find the first node - var firstNode = this._firstNode(); - if (firstNode) { - firstNode.focus(Node.focusElement || this._getElementName(target)); - } - handled = true; - } - } - else if (keynum == 37) { // Arrow Left - if (altKey && !shiftKey) { // Alt + Arrow Left - // move to left element - var prevElement = this._previousElement(target); - if (prevElement) { - this.focus(this._getElementName(prevElement)); - } - handled = true; - } - else if (altKey && shiftKey) { // Alt + Shift Arrow left - if (this.expanded) { - var appendDom = this.getAppend(); - nextDom = appendDom ? appendDom.nextSibling : undefined; - } - else { - var dom = this.getDom(); - nextDom = dom.nextSibling; - } - if (nextDom) { - nextNode = Node.getNodeFromTarget(nextDom); - nextDom2 = nextDom.nextSibling; - nextNode2 = Node.getNodeFromTarget(nextDom2); - if (nextNode && nextNode instanceof AppendNode && - !(this.parent.childs.length == 1) && - nextNode2 && nextNode2.parent) { - nextNode2.parent.moveBefore(this, nextNode2); - this.focus(Node.focusElement || this._getElementName(target)); - } - } - } - } - else if (keynum == 38) { // Arrow Up - if (altKey && !shiftKey) { // Alt + Arrow Up - // find the previous node - prevNode = this._previousNode(); - if (prevNode) { - prevNode.focus(Node.focusElement || this._getElementName(target)); - } - handled = true; - } - else if (altKey && shiftKey) { // Alt + Shift + Arrow Up - // find the previous node - prevNode = this._previousNode(); - if (prevNode && prevNode.parent) { - prevNode.parent.moveBefore(this, prevNode); - this.focus(Node.focusElement || this._getElementName(target)); - } - handled = true; - } - } - else if (keynum == 39) { // Arrow Right - if (altKey && !shiftKey) { // Alt + Arrow Right - // move to right element - var nextElement = this._nextElement(target); - if (nextElement) { - this.focus(this._getElementName(nextElement)); - } - handled = true; - } - else if (altKey && shiftKey) { // Alt + Shift Arrow Right - dom = this.getDom(); - var prevDom = dom.previousSibling; - if (prevDom) { - prevNode = Node.getNodeFromTarget(prevDom); - if (prevNode && prevNode.parent && - (prevNode instanceof AppendNode) - && !prevNode.isVisible()) { - prevNode.parent.moveBefore(this, prevNode); - this.focus(Node.focusElement || this._getElementName(target)); - } - } - } - } - else if (keynum == 40) { // Arrow Down - if (altKey && !shiftKey) { // Alt + Arrow Down - // find the next node - nextNode = this._nextNode(); - if (nextNode) { - nextNode.focus(Node.focusElement || this._getElementName(target)); - } - handled = true; - } - else if (altKey && shiftKey) { // Alt + Shift + Arrow Down - // find the 2nd next node and move before that one - if (this.expanded) { - nextNode = this.append ? this.append._nextNode() : undefined; - } - else { - nextNode = this._nextNode(); - } - nextDom = nextNode ? nextNode.getDom() : undefined; - if (this.parent.childs.length == 1) { - nextDom2 = nextDom; - } - else { - nextDom2 = nextDom ? nextDom.nextSibling : undefined; - } - var nextNode2 = Node.getNodeFromTarget(nextDom2); - if (nextNode2 && nextNode2.parent) { - nextNode2.parent.moveBefore(this, nextNode2); - this.focus(Node.focusElement || this._getElementName(target)); - } - handled = true; - } - } - - if (handled) { - event.preventDefault(); - event.stopPropagation(); - } -}; - -/** - * Handle the expand event, when clicked on the expand button - * @param {boolean} recurse If true, child nodes will be expanded too - * @private - */ -Node.prototype._onExpand = function (recurse) { - if (recurse) { - // Take the table offline - var table = this.dom.tr.parentNode; // TODO: not nice to access the main table like this - var frame = table.parentNode; - var scrollTop = frame.scrollTop; - frame.removeChild(table); - } - - if (this.expanded) { - this.collapse(recurse); - } - else { - this.expand(recurse); - } - - if (recurse) { - // Put the table online again - frame.appendChild(table); - frame.scrollTop = scrollTop; - } -}; - -/** - * Remove this node - * @private - */ -Node.prototype._onRemove = function() { - this.editor.highlighter.unhighlight(); - var childs = this.parent.childs; - var index = childs.indexOf(this); - - // adjust the focus - var oldSelection = this.editor.getSelection(); - if (childs[index + 1]) { - childs[index + 1].focus(); - } - else if (childs[index - 1]) { - childs[index - 1].focus(); - } - else { - this.parent.focus(); - } - var newSelection = this.editor.getSelection(); - - // remove the node - this.parent._remove(this); - - // store history action - this.editor._onAction('removeNode', { - 'node': this, - 'parent': this.parent, - 'index': index, - 'oldSelection': oldSelection, - 'newSelection': newSelection - }); -}; - -/** - * Duplicate this node - * @private - */ -Node.prototype._onDuplicate = function() { - var oldSelection = this.editor.getSelection(); - var clone = this.parent._duplicate(this); - clone.focus(); - var newSelection = this.editor.getSelection(); - - this.editor._onAction('duplicateNode', { - 'node': this, - 'clone': clone, - 'parent': this.parent, - 'oldSelection': oldSelection, - 'newSelection': newSelection - }); -}; - -/** - * Handle insert before event - * @param {String} [field] - * @param {*} [value] - * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' - * @private - */ -Node.prototype._onInsertBefore = function (field, value, type) { - var oldSelection = this.editor.getSelection(); - - var newNode = new Node(this.editor, { - 'field': (field != undefined) ? field : '', - 'value': (value != undefined) ? value : '', - 'type': type - }); - newNode.expand(true); - this.parent.insertBefore(newNode, this); - this.editor.highlighter.unhighlight(); - newNode.focus('field'); - var newSelection = this.editor.getSelection(); - - this.editor._onAction('insertBeforeNode', { - 'node': newNode, - 'beforeNode': this, - 'parent': this.parent, - 'oldSelection': oldSelection, - 'newSelection': newSelection - }); -}; - -/** - * Handle insert after event - * @param {String} [field] - * @param {*} [value] - * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' - * @private - */ -Node.prototype._onInsertAfter = function (field, value, type) { - var oldSelection = this.editor.getSelection(); - - var newNode = new Node(this.editor, { - 'field': (field != undefined) ? field : '', - 'value': (value != undefined) ? value : '', - 'type': type - }); - newNode.expand(true); - this.parent.insertAfter(newNode, this); - this.editor.highlighter.unhighlight(); - newNode.focus('field'); - var newSelection = this.editor.getSelection(); - - this.editor._onAction('insertAfterNode', { - 'node': newNode, - 'afterNode': this, - 'parent': this.parent, - 'oldSelection': oldSelection, - 'newSelection': newSelection - }); -}; - -/** - * Handle append event - * @param {String} [field] - * @param {*} [value] - * @param {String} [type] Can be 'auto', 'array', 'object', or 'string' - * @private - */ -Node.prototype._onAppend = function (field, value, type) { - var oldSelection = this.editor.getSelection(); - - var newNode = new Node(this.editor, { - 'field': (field != undefined) ? field : '', - 'value': (value != undefined) ? value : '', - 'type': type - }); - newNode.expand(true); - this.parent.appendChild(newNode); - this.editor.highlighter.unhighlight(); - newNode.focus('field'); - var newSelection = this.editor.getSelection(); - - this.editor._onAction('appendNode', { - 'node': newNode, - 'parent': this.parent, - 'oldSelection': oldSelection, - 'newSelection': newSelection - }); -}; - -/** - * Change the type of the node's value - * @param {String} newType - * @private - */ -Node.prototype._onChangeType = function (newType) { - var oldType = this.type; - if (newType != oldType) { - var oldSelection = this.editor.getSelection(); - this.changeType(newType); - var newSelection = this.editor.getSelection(); - - this.editor._onAction('changeType', { - 'node': this, - 'oldType': oldType, - 'newType': newType, - 'oldSelection': oldSelection, - 'newSelection': newSelection - }); - } -}; - -/** - * Sort the childs of the node. Only applicable when the node has type 'object' - * or 'array'. - * @param {String} direction Sorting direction. Available values: "asc", "desc" - * @private - */ -Node.prototype._onSort = function (direction) { - if (this._hasChilds()) { - var order = (direction == 'desc') ? -1 : 1; - var prop = (this.type == 'array') ? 'value': 'field'; - this.hideChilds(); - - var oldChilds = this.childs; - var oldSort = this.sort; - - // copy the array (the old one will be kept for an undo action - this.childs = this.childs.concat(); - - // sort the arrays - this.childs.sort(function (a, b) { - if (a[prop] > b[prop]) return order; - if (a[prop] < b[prop]) return -order; - return 0; - }); - this.sort = (order == 1) ? 'asc' : 'desc'; - - this.editor._onAction('sort', { - 'node': this, - 'oldChilds': oldChilds, - 'oldSort': oldSort, - 'newChilds': this.childs, - 'newSort': this.sort - }); - - this.showChilds(); - } -}; - -/** - * Create a table row with an append button. - * @return {HTMLElement | undefined} buttonAppend or undefined when inapplicable - */ -Node.prototype.getAppend = function () { - if (!this.append) { - this.append = new AppendNode(this.editor); - this.append.setParent(this); - } - return this.append.getDom(); -}; - -/** - * Find the node from an event target - * @param {Node} target - * @return {Node | undefined} node or undefined when not found - * @static - */ -Node.getNodeFromTarget = function (target) { - while (target) { - if (target.node) { - return target.node; - } - target = target.parentNode; - } - - return undefined; -}; - -/** - * Get the previously rendered node - * @return {Node | null} previousNode - * @private - */ -Node.prototype._previousNode = function () { - var prevNode = null; - var dom = this.getDom(); - if (dom && dom.parentNode) { - // find the previous field - var prevDom = dom; - do { - prevDom = prevDom.previousSibling; - prevNode = Node.getNodeFromTarget(prevDom); - } - while (prevDom && (prevNode instanceof AppendNode && !prevNode.isVisible())); - } - return prevNode; -}; - -/** - * Get the next rendered node - * @return {Node | null} nextNode - * @private - */ -Node.prototype._nextNode = function () { - var nextNode = null; - var dom = this.getDom(); - if (dom && dom.parentNode) { - // find the previous field - var nextDom = dom; - do { - nextDom = nextDom.nextSibling; - nextNode = Node.getNodeFromTarget(nextDom); - } - while (nextDom && (nextNode instanceof AppendNode && !nextNode.isVisible())); - } - - return nextNode; -}; - -/** - * Get the first rendered node - * @return {Node | null} firstNode - * @private - */ -Node.prototype._firstNode = function () { - var firstNode = null; - var dom = this.getDom(); - if (dom && dom.parentNode) { - var firstDom = dom.parentNode.firstChild; - firstNode = Node.getNodeFromTarget(firstDom); - } - - return firstNode; -}; - -/** - * Get the last rendered node - * @return {Node | null} lastNode - * @private - */ -Node.prototype._lastNode = function () { - var lastNode = null; - var dom = this.getDom(); - if (dom && dom.parentNode) { - var lastDom = dom.parentNode.lastChild; - lastNode = Node.getNodeFromTarget(lastDom); - while (lastDom && (lastNode instanceof AppendNode && !lastNode.isVisible())) { - lastDom = lastDom.previousSibling; - lastNode = Node.getNodeFromTarget(lastDom); - } - } - return lastNode; -}; - -/** - * Get the next element which can have focus. - * @param {Element} elem - * @return {Element | null} nextElem - * @private - */ -Node.prototype._previousElement = function (elem) { - var dom = this.dom; - // noinspection FallthroughInSwitchStatementJS - switch (elem) { - case dom.value: - if (this.fieldEditable) { - return dom.field; - } - // intentional fall through - case dom.field: - if (this._hasChilds()) { - return dom.expand; - } - // intentional fall through - case dom.expand: - return dom.menu; - case dom.menu: - if (dom.drag) { - return dom.drag; - } - // intentional fall through - default: - return null; - } -}; - -/** - * Get the next element which can have focus. - * @param {Element} elem - * @return {Element | null} nextElem - * @private - */ -Node.prototype._nextElement = function (elem) { - var dom = this.dom; - // noinspection FallthroughInSwitchStatementJS - switch (elem) { - case dom.drag: - return dom.menu; - case dom.menu: - if (this._hasChilds()) { - return dom.expand; - } - // intentional fall through - case dom.expand: - if (this.fieldEditable) { - return dom.field; - } - // intentional fall through - case dom.field: - if (!this._hasChilds()) { - return dom.value; - } - default: - return null; - } -}; - -/** - * Get the dom name of given element. returns null if not found. - * For example when element == dom.field, "field" is returned. - * @param {Element} element - * @return {String | null} elementName Available elements with name: 'drag', - * 'menu', 'expand', 'field', 'value' - * @private - */ -Node.prototype._getElementName = function (element) { - var dom = this.dom; - for (var name in dom) { - if (dom.hasOwnProperty(name)) { - if (dom[name] == element) { - return name; - } - } - } - return null; -}; - -/** - * Test if this node has childs. This is the case when the node is an object - * or array. - * @return {boolean} hasChilds - * @private - */ -Node.prototype._hasChilds = function () { - return this.type == 'array' || this.type == 'object'; -}; - -// titles with explanation for the different types -Node.TYPE_TITLES = { - 'auto': 'Field type "auto". ' + - 'The field type is automatically determined from the value ' + - 'and can be a string, number, boolean, or null.', - 'object': 'Field type "object". ' + - 'An object contains an unordered set of key/value pairs.', - 'array': 'Field type "array". ' + - 'An array contains an ordered collection of values.', - 'string': 'Field type "string". ' + - 'Field type is not determined from the value, ' + - 'but always returned as string.' -}; - -/** - * Show a contextmenu for this node - * @param {HTMLElement} anchor Anchor element to attache the context menu to. - * @param {function} [onClose] Callback method called when the context menu - * is being closed. - */ -Node.prototype.showContextMenu = function (anchor, onClose) { - var node = this; - var titles = Node.TYPE_TITLES; - var items = []; - - items.push({ - 'text': 'Type', - 'title': 'Change the type of this field', - 'className': 'type-' + this.type, - 'submenu': [ - { - 'text': 'Auto', - 'className': 'type-auto' + - (this.type == 'auto' ? ' selected' : ''), - 'title': titles.auto, - 'click': function () { - node._onChangeType('auto'); - } - }, - { - 'text': 'Array', - 'className': 'type-array' + - (this.type == 'array' ? ' selected' : ''), - 'title': titles.array, - 'click': function () { - node._onChangeType('array'); - } - }, - { - 'text': 'Object', - 'className': 'type-object' + - (this.type == 'object' ? ' selected' : ''), - 'title': titles.object, - 'click': function () { - node._onChangeType('object'); - } - }, - { - 'text': 'String', - 'className': 'type-string' + - (this.type == 'string' ? ' selected' : ''), - 'title': titles.string, - 'click': function () { - node._onChangeType('string'); - } - } - ] - }); - - if (this._hasChilds()) { - var direction = ((this.sort == 'asc') ? 'desc': 'asc'); - items.push({ - 'text': 'Sort', - 'title': 'Sort the childs of this ' + this.type, - 'className': 'sort-' + direction, - 'click': function () { - node._onSort(direction); - }, - 'submenu': [ - { - 'text': 'Ascending', - 'className': 'sort-asc', - 'title': 'Sort the childs of this ' + this.type + ' in ascending order', - 'click': function () { - node._onSort('asc'); - } - }, - { - 'text': 'Descending', - 'className': 'sort-desc', - 'title': 'Sort the childs of this ' + this.type +' in descending order', - 'click': function () { - node._onSort('desc'); - } - } - ] - }); - } - - if (this.parent && this.parent._hasChilds()) { - // create a separator - items.push({ - 'type': 'separator' - }); - - // create append button (for last child node only) - var childs = node.parent.childs; - if (node == childs[childs.length - 1]) { - items.push({ - 'text': 'Append', - 'title': 'Append a new field with type \'auto\' after this field (Ctrl+Shift+Ins)', - 'submenuTitle': 'Select the type of the field to be appended', - 'className': 'append', - 'click': function () { - node._onAppend('', '', 'auto'); - }, - 'submenu': [ - { - 'text': 'Auto', - 'className': 'type-auto', - 'title': titles.auto, - 'click': function () { - node._onAppend('', '', 'auto'); - } - }, - { - 'text': 'Array', - 'className': 'type-array', - 'title': titles.array, - 'click': function () { - node._onAppend('', []); - } - }, - { - 'text': 'Object', - 'className': 'type-object', - 'title': titles.object, - 'click': function () { - node._onAppend('', {}); - } - }, - { - 'text': 'String', - 'className': 'type-string', - 'title': titles.string, - 'click': function () { - node._onAppend('', '', 'string'); - } - } - ] - }); - } - - // create insert button - items.push({ - 'text': 'Insert', - 'title': 'Insert a new field with type \'auto\' before this field (Ctrl+Ins)', - 'submenuTitle': 'Select the type of the field to be inserted', - 'className': 'insert', - 'click': function () { - node._onInsertBefore('', '', 'auto'); - }, - 'submenu': [ - { - 'text': 'Auto', - 'className': 'type-auto', - 'title': titles.auto, - 'click': function () { - node._onInsertBefore('', '', 'auto'); - } - }, - { - 'text': 'Array', - 'className': 'type-array', - 'title': titles.array, - 'click': function () { - node._onInsertBefore('', []); - } - }, - { - 'text': 'Object', - 'className': 'type-object', - 'title': titles.object, - 'click': function () { - node._onInsertBefore('', {}); - } - }, - { - 'text': 'String', - 'className': 'type-string', - 'title': titles.string, - 'click': function () { - node._onInsertBefore('', '', 'string'); - } - } - ] - }); - - // create duplicate button - items.push({ - 'text': 'Duplicate', - 'title': 'Duplicate this field (Ctrl+D)', - 'className': 'duplicate', - 'click': function () { - node._onDuplicate(); - } - }); - - // create remove button - items.push({ - 'text': 'Remove', - 'title': 'Remove this field (Ctrl+Del)', - 'className': 'remove', - 'click': function () { - node._onRemove(); - } - }); - } - - var menu = new ContextMenu(items, {close: onClose}); - menu.show(anchor); -}; - -/** - * get the type of a value - * @param {*} value - * @return {String} type Can be 'object', 'array', 'string', 'auto' - * @private - */ -Node.prototype._getType = function(value) { - if (value instanceof Array) { - return 'array'; - } - if (value instanceof Object) { - return 'object'; - } - if (typeof(value) == 'string' && typeof(this._stringCast(value)) != 'string') { - return 'string'; - } - - return 'auto'; -}; - -/** - * cast contents of a string to the correct type. This can be a string, - * a number, a boolean, etc - * @param {String} str - * @return {*} castedStr - * @private - */ -Node.prototype._stringCast = function(str) { - var lower = str.toLowerCase(), - num = Number(str), // will nicely fail with '123ab' - numFloat = parseFloat(str); // will nicely fail with ' ' - - if (str == '') { - return ''; - } - else if (lower == 'null') { - return null; - } - else if (lower == 'true') { - return true; - } - else if (lower == 'false') { - return false; - } - else if (!isNaN(num) && !isNaN(numFloat)) { - return num; - } - else { - return str; - } -}; - -/** - * escape a text, such that it can be displayed safely in an HTML element - * @param {String} text - * @return {String} escapedText - * @private - */ -Node.prototype._escapeHTML = function (text) { - var htmlEscaped = String(text) - .replace(//g, '>') - .replace(/ /g, '  ') // replace double space with an nbsp and space - .replace(/^ /, ' ') // space at start - .replace(/ $/, ' '); // space at end - - var json = JSON.stringify(htmlEscaped); - return json.substring(1, json.length - 1); -}; - -/** - * unescape a string. - * @param {String} escapedText - * @return {String} text - * @private - */ -Node.prototype._unescapeHTML = function (escapedText) { - var json = '"' + this._escapeJSON(escapedText) + '"'; - var htmlEscaped = util.parse(json); - return htmlEscaped - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/ |\u00A0/g, ' '); -}; - -/** - * escape a text to make it a valid JSON string. The method will: - * - replace unescaped double quotes with '\"' - * - replace unescaped backslash with '\\' - * - replace returns with '\n' - * @param {String} text - * @return {String} escapedText - * @private - */ -Node.prototype._escapeJSON = function (text) { - // TODO: replace with some smart regex (only when a new solution is faster!) - var escaped = ''; - var i = 0, iMax = text.length; - while (i < iMax) { - var c = text.charAt(i); - if (c == '\n') { - escaped += '\\n'; - } - else if (c == '\\') { - escaped += c; - i++; - - c = text.charAt(i); - if ('"\\/bfnrtu'.indexOf(c) == -1) { - escaped += '\\'; // no valid escape character - } - escaped += c; - } - else if (c == '"') { - escaped += '\\"'; - } - else { - escaped += c; - } - i++; - } - - return escaped; -}; - -/** - * @constructor AppendNode - * @extends Node - * @param {TreeEditor} editor - * Create a new AppendNode. This is a special node which is created at the - * end of the list with childs for an object or array - */ -function AppendNode (editor) { - /** @type {TreeEditor} */ - this.editor = editor; - this.dom = {}; -} - -AppendNode.prototype = new Node(); - -/** - * Return a table row with an append button. - * @return {Element} dom TR element - */ -AppendNode.prototype.getDom = function () { - // TODO: implement a new solution for the append node - var dom = this.dom; - - if (dom.tr) { - return dom.tr; - } - - // a row for the append button - var trAppend = document.createElement('tr'); - trAppend.node = this; - dom.tr = trAppend; - - // TODO: consistent naming - - if (this.editor.mode.edit) { - // a cell for the dragarea column - dom.tdDrag = document.createElement('td'); - - // create context menu - var tdMenu = document.createElement('td'); - dom.tdMenu = tdMenu; - var menu = document.createElement('button'); - menu.className = 'contextmenu'; - menu.title = 'Click to open the actions menu (Ctrl+M)'; - dom.menu = menu; - tdMenu.appendChild(dom.menu); - } - - // a cell for the contents (showing text 'empty') - var tdAppend = document.createElement('td'); - var domText = document.createElement('div'); - domText.innerHTML = '(empty)'; - domText.className = 'readonly'; - tdAppend.appendChild(domText); - dom.td = tdAppend; - dom.text = domText; - - this.updateDom(); - - return trAppend; -}; - -/** - * Update the HTML dom of the Node - */ -AppendNode.prototype.updateDom = function () { - var dom = this.dom; - var tdAppend = dom.td; - if (tdAppend) { - tdAppend.style.paddingLeft = (this.getLevel() * 24 + 26) + 'px'; - // TODO: not so nice hard coded offset - } - - var domText = dom.text; - if (domText) { - domText.innerHTML = '(empty ' + this.parent.type + ')'; - } - - // attach or detach the contents of the append node: - // hide when the parent has childs, show when the parent has no childs - var trAppend = dom.tr; - if (!this.isVisible()) { - if (dom.tr.firstChild) { - if (dom.tdDrag) { - trAppend.removeChild(dom.tdDrag); - } - if (dom.tdMenu) { - trAppend.removeChild(dom.tdMenu); - } - trAppend.removeChild(tdAppend); - } - } - else { - if (!dom.tr.firstChild) { - if (dom.tdDrag) { - trAppend.appendChild(dom.tdDrag); - } - if (dom.tdMenu) { - trAppend.appendChild(dom.tdMenu); - } - trAppend.appendChild(tdAppend); - } - } -}; - -/** - * Check whether the AppendNode is currently visible. - * the AppendNode is visible when its parent has no childs (i.e. is empty). - * @return {boolean} isVisible - */ -AppendNode.prototype.isVisible = function () { - return (this.parent.childs.length == 0); -}; - -/** - * Show a contextmenu for this node - * @param {HTMLElement} anchor The element to attach the menu to. - * @param {function} [onClose] Callback method called when the context menu - * is being closed. - */ -AppendNode.prototype.showContextMenu = function (anchor, onClose) { - var node = this; - var titles = Node.TYPE_TITLES; - var items = [ - // create append button - { - 'text': 'Append', - 'title': 'Append a new field with type \'auto\' (Ctrl+Shift+Ins)', - 'submenuTitle': 'Select the type of the field to be appended', - 'className': 'insert', - 'click': function () { - node._onAppend('', '', 'auto'); - }, - 'submenu': [ - { - 'text': 'Auto', - 'className': 'type-auto', - 'title': titles.auto, - 'click': function () { - node._onAppend('', '', 'auto'); - } - }, - { - 'text': 'Array', - 'className': 'type-array', - 'title': titles.array, - 'click': function () { - node._onAppend('', []); - } - }, - { - 'text': 'Object', - 'className': 'type-object', - 'title': titles.object, - 'click': function () { - node._onAppend('', {}); - } - }, - { - 'text': 'String', - 'className': 'type-string', - 'title': titles.string, - 'click': function () { - node._onAppend('', '', 'string'); - } - } - ] - } - ]; - - var menu = new ContextMenu(items, {close: onClose}); - menu.show(anchor); -}; - -/** - * Handle an event. The event is catched centrally by the editor - * @param {Event} event - */ -AppendNode.prototype.onEvent = function (event) { - var type = event.type; - var target = event.target || event.srcElement; - var dom = this.dom; - - // highlight the append nodes parent - var menu = dom.menu; - if (target == menu) { - if (type == 'mouseover') { - this.editor.highlighter.highlight(this.parent); - } - else if (type == 'mouseout') { - this.editor.highlighter.unhighlight(); - } - } - - // context menu events - if (type == 'click' && target == dom.menu) { - var highlighter = this.editor.highlighter; - highlighter.highlight(this.parent); - highlighter.lock(); - util.addClassName(dom.menu, 'selected'); - this.showContextMenu(dom.menu, function () { - util.removeClassName(dom.menu, 'selected'); - highlighter.unlock(); - highlighter.unhighlight(); - }); - } - - if (type == 'keydown') { - this.onKeyDown(event); - } -}; - -/** - * A context menu - * @param {Object[]} items Array containing the menu structure - * TODO: describe structure - * @param {Object} [options] Object with options. Available options: - * {function} close Callback called when the - * context menu is being closed. - * @constructor - */ -function ContextMenu (items, options) { - this.dom = {}; - - var me = this; - var dom = this.dom; - this.anchor = undefined; - this.items = items; - this.eventListeners = {}; - this.selection = undefined; // holds the selection before the menu was opened - this.visibleSubmenu = undefined; - this.onClose = options ? options.close : undefined; - - // create a container element - var menu = document.createElement('div'); - menu.className = 'jsoneditor-contextmenu'; - dom.menu = menu; - - // create a list to hold the menu items - var list = document.createElement('ul'); - list.className = 'menu'; - menu.appendChild(list); - dom.list = list; - dom.items = []; // list with all buttons - - // create a (non-visible) button to set the focus to the menu - var focusButton = document.createElement('button'); - dom.focusButton = focusButton; - var li = document.createElement('li'); - li.style.overflow = 'hidden'; - li.style.height = '0'; - li.appendChild(focusButton); - list.appendChild(li); - - function createMenuItems (list, domItems, items) { - items.forEach(function (item) { - if (item.type == 'separator') { - // create a separator - var separator = document.createElement('div'); - separator.className = 'separator'; - li = document.createElement('li'); - li.appendChild(separator); - list.appendChild(li); - } - else { - var domItem = {}; - - // create a menu item - var li = document.createElement('li'); - list.appendChild(li); - - // create a button in the menu item - var button = document.createElement('button'); - button.className = item.className; - domItem.button = button; - if (item.title) { - button.title = item.title; - } - if (item.click) { - button.onclick = function () { - me.hide(); - item.click(); - }; - } - li.appendChild(button); - - // create the contents of the button - if (item.submenu) { - // add the icon to the button - var divIcon = document.createElement('div'); - divIcon.className = 'icon'; - button.appendChild(divIcon); - button.appendChild(document.createTextNode(item.text)); - - var buttonSubmenu; - if (item.click) { - // submenu and a button with a click handler - button.className += ' default'; - - var buttonExpand = document.createElement('button'); - domItem.buttonExpand = buttonExpand; - buttonExpand.className = 'expand'; - buttonExpand.innerHTML = '
'; - li.appendChild(buttonExpand); - if (item.submenuTitle) { - buttonExpand.title = item.submenuTitle; - } - - buttonSubmenu = buttonExpand; - } - else { - // submenu and a button without a click handler - var divExpand = document.createElement('div'); - divExpand.className = 'expand'; - button.appendChild(divExpand); - - buttonSubmenu = button; - } - - // attach a handler to expand/collapse the submenu - buttonSubmenu.onclick = function () { - me._onExpandItem(domItem); - buttonSubmenu.focus(); - }; - - // create the submenu - var domSubItems = []; - domItem.subItems = domSubItems; - var ul = document.createElement('ul'); - domItem.ul = ul; - ul.className = 'menu'; - ul.style.height = '0'; - li.appendChild(ul); - createMenuItems(ul, domSubItems, item.submenu); - } - else { - // no submenu, just a button with clickhandler - button.innerHTML = '
' + item.text; - } - - domItems.push(domItem); - } - }); - } - createMenuItems(list, this.dom.items, items); - - // TODO: when the editor is small, show the submenu on the right instead of inline? - - // calculate the max height of the menu with one submenu expanded - this.maxHeight = 0; // height in pixels - items.forEach(function (item) { - var height = (items.length + (item.submenu ? item.submenu.length : 0)) * 24; - me.maxHeight = Math.max(me.maxHeight, height); - }); -} - -/** - * Get the currently visible buttons - * @return {Array.} buttons - * @private - */ -ContextMenu.prototype._getVisibleButtons = function () { - var buttons = []; - var me = this; - this.dom.items.forEach(function (item) { - buttons.push(item.button); - if (item.buttonExpand) { - buttons.push(item.buttonExpand); - } - if (item.subItems && item == me.expandedItem) { - item.subItems.forEach(function (subItem) { - buttons.push(subItem.button); - if (subItem.buttonExpand) { - buttons.push(subItem.buttonExpand); - } - // TODO: change to fully recursive method - }); - } - }); - - return buttons; -}; - -// currently displayed context menu, a singleton. We may only have one visible context menu -ContextMenu.visibleMenu = undefined; - -/** - * Attach the menu to an anchor - * @param {HTMLElement} anchor - */ -ContextMenu.prototype.show = function (anchor) { - this.hide(); - - // calculate whether the menu fits below the anchor - var windowHeight = window.innerHeight, - windowScroll = (window.pageYOffset || document.scrollTop || 0), - windowBottom = windowHeight + windowScroll, - anchorHeight = anchor.offsetHeight, - menuHeight = this.maxHeight; - - // position the menu - var left = util.getAbsoluteLeft(anchor); - var top = util.getAbsoluteTop(anchor); - if (top + anchorHeight + menuHeight < windowBottom) { - // display the menu below the anchor - this.dom.menu.style.left = left + 'px'; - this.dom.menu.style.top = (top + anchorHeight) + 'px'; - this.dom.menu.style.bottom = ''; - } - else { - // display the menu above the anchor - this.dom.menu.style.left = left + 'px'; - this.dom.menu.style.top = ''; - this.dom.menu.style.bottom = (windowHeight - top) + 'px'; - } - - // attach the menu to the document - document.body.appendChild(this.dom.menu); - - // create and attach event listeners - var me = this; - var list = this.dom.list; - this.eventListeners.mousedown = util.addEventListener( - document, 'mousedown', function (event) { - // hide menu on click outside of the menu - var target = event.target; - if ((target != list) && !me._isChildOf(target, list)) { - me.hide(); - event.stopPropagation(); - event.preventDefault(); - } - }); - this.eventListeners.mousewheel = util.addEventListener( - document, 'mousewheel', function (event) { - // block scrolling when context menu is visible - event.stopPropagation(); - event.preventDefault(); - }); - this.eventListeners.keydown = util.addEventListener( - document, 'keydown', function (event) { - me._onKeyDown(event); - }); - - // move focus to the first button in the context menu - this.selection = util.getSelection(); - this.anchor = anchor; - setTimeout(function () { - me.dom.focusButton.focus(); - }, 0); - - if (ContextMenu.visibleMenu) { - ContextMenu.visibleMenu.hide(); - } - ContextMenu.visibleMenu = this; -}; - -/** - * Hide the context menu if visible - */ -ContextMenu.prototype.hide = function () { - // remove the menu from the DOM - if (this.dom.menu.parentNode) { - this.dom.menu.parentNode.removeChild(this.dom.menu); - if (this.onClose) { - this.onClose(); - } - } - - // remove all event listeners - // all event listeners are supposed to be attached to document. - for (var name in this.eventListeners) { - if (this.eventListeners.hasOwnProperty(name)) { - var fn = this.eventListeners[name]; - if (fn) { - util.removeEventListener(document, name, fn); - } - delete this.eventListeners[name]; - } - } - - if (ContextMenu.visibleMenu == this) { - ContextMenu.visibleMenu = undefined; - } -}; - -/** - * Expand a submenu - * Any currently expanded submenu will be hided. - * @param {Object} domItem - * @private - */ -ContextMenu.prototype._onExpandItem = function (domItem) { - var me = this; - var alreadyVisible = (domItem == this.expandedItem); - - // hide the currently visible submenu - var expandedItem = this.expandedItem; - if (expandedItem) { - //var ul = expandedItem.ul; - expandedItem.ul.style.height = '0'; - expandedItem.ul.style.padding = ''; - setTimeout(function () { - if (me.expandedItem != expandedItem) { - expandedItem.ul.style.display = ''; - util.removeClassName(expandedItem.ul.parentNode, 'selected'); - } - }, 300); // timeout duration must match the css transition duration - this.expandedItem = undefined; - } - - if (!alreadyVisible) { - var ul = domItem.ul; - ul.style.display = 'block'; - var height = ul.clientHeight; // force a reflow in Firefox - setTimeout(function () { - if (me.expandedItem == domItem) { - ul.style.height = (ul.childNodes.length * 24) + 'px'; - ul.style.padding = '5px 10px'; - } - }, 0); - util.addClassName(ul.parentNode, 'selected'); - this.expandedItem = domItem; - } -}; - -/** - * Handle onkeydown event - * @param {Event} event - * @private - */ -ContextMenu.prototype._onKeyDown = function (event) { - var target = event.target; - var keynum = event.which; - var handled = false; - var buttons, targetIndex, prevButton, nextButton; - - if (keynum == 27) { // ESC - // hide the menu on ESC key - - // restore previous selection and focus - if (this.selection) { - util.setSelection(this.selection); - } - if (this.anchor) { - this.anchor.focus(); - } - - this.hide(); - - handled = true; - } - else if (keynum == 9) { // Tab - if (!event.shiftKey) { // Tab - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - if (targetIndex == buttons.length - 1) { - // move to first button - buttons[0].focus(); - handled = true; - } - } - else { // Shift+Tab - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - if (targetIndex == 0) { - // move to last button - buttons[buttons.length - 1].focus(); - handled = true; - } - } - } - else if (keynum == 37) { // Arrow Left - if (target.className == 'expand') { - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - prevButton = buttons[targetIndex - 1]; - if (prevButton) { - prevButton.focus(); - } - } - handled = true; - } - else if (keynum == 38) { // Arrow Up - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - prevButton = buttons[targetIndex - 1]; - if (prevButton && prevButton.className == 'expand') { - // skip expand button - prevButton = buttons[targetIndex - 2]; - } - if (!prevButton) { - // move to last button - prevButton = buttons[buttons.length - 1]; - } - if (prevButton) { - prevButton.focus(); - } - handled = true; - } - else if (keynum == 39) { // Arrow Right - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - nextButton = buttons[targetIndex + 1]; - if (nextButton && nextButton.className == 'expand') { - nextButton.focus(); - } - handled = true; - } - else if (keynum == 40) { // Arrow Down - buttons = this._getVisibleButtons(); - targetIndex = buttons.indexOf(target); - nextButton = buttons[targetIndex + 1]; - if (nextButton && nextButton.className == 'expand') { - // skip expand button - nextButton = buttons[targetIndex + 2]; - } - if (!nextButton) { - // move to first button - nextButton = buttons[0]; - } - if (nextButton) { - nextButton.focus(); - handled = true; - } - handled = true; - } - // TODO: arrow left and right - - if (handled) { - event.stopPropagation(); - event.preventDefault(); - } -}; - -/** - * Test if an element is a child of a parent element. - * @param {Element} child - * @param {Element} parent - * @return {boolean} isChild - */ -ContextMenu.prototype._isChildOf = function (child, parent) { - var e = child.parentNode; - while (e) { - if (e == parent) { - return true; - } - e = e.parentNode; - } - - return false; -}; - - -/** - * @constructor History - * Store action history, enables undo and redo - * @param {JSONEditor} editor - */ -function History (editor) { - this.editor = editor; - this.clear(); - - // map with all supported actions - this.actions = { - 'editField': { - 'undo': function (params) { - params.node.updateField(params.oldValue); - }, - 'redo': function (params) { - params.node.updateField(params.newValue); - } - }, - 'editValue': { - 'undo': function (params) { - params.node.updateValue(params.oldValue); - }, - 'redo': function (params) { - params.node.updateValue(params.newValue); - } - }, - 'appendNode': { - 'undo': function (params) { - params.parent.removeChild(params.node); - }, - 'redo': function (params) { - params.parent.appendChild(params.node); - } - }, - 'insertBeforeNode': { - 'undo': function (params) { - params.parent.removeChild(params.node); - }, - 'redo': function (params) { - params.parent.insertBefore(params.node, params.beforeNode); - } - }, - 'insertAfterNode': { - 'undo': function (params) { - params.parent.removeChild(params.node); - }, - 'redo': function (params) { - params.parent.insertAfter(params.node, params.afterNode); - } - }, - 'removeNode': { - 'undo': function (params) { - var parent = params.parent; - var beforeNode = parent.childs[params.index] || parent.append; - parent.insertBefore(params.node, beforeNode); - }, - 'redo': function (params) { - params.parent.removeChild(params.node); - } - }, - 'duplicateNode': { - 'undo': function (params) { - params.parent.removeChild(params.clone); - }, - 'redo': function (params) { - params.parent.insertAfter(params.clone, params.node); - } - }, - 'changeType': { - 'undo': function (params) { - params.node.changeType(params.oldType); - }, - 'redo': function (params) { - params.node.changeType(params.newType); - } - }, - 'moveNode': { - 'undo': function (params) { - params.startParent.moveTo(params.node, params.startIndex); - }, - 'redo': function (params) { - params.endParent.moveTo(params.node, params.endIndex); - } - }, - 'sort': { - 'undo': function (params) { - var node = params.node; - node.hideChilds(); - node.sort = params.oldSort; - node.childs = params.oldChilds; - node.showChilds(); - }, - 'redo': function (params) { - var node = params.node; - node.hideChilds(); - node.sort = params.newSort; - node.childs = params.newChilds; - node.showChilds(); - } - } - - // TODO: restore the original caret position and selection with each undo - // TODO: implement history for actions "expand", "collapse", "scroll", "setDocument" - }; -} - -/** - * The method onChange is executed when the History is changed, and can - * be overloaded. - */ -History.prototype.onChange = function () {}; - -/** - * Add a new action to the history - * @param {String} action The executed action. Available actions: "editField", - * "editValue", "changeType", "appendNode", - * "removeNode", "duplicateNode", "moveNode" - * @param {Object} params Object containing parameters describing the change. - * The parameters in params depend on the action (for - * example for "editValue" the Node, old value, and new - * value are provided). params contains all information - * needed to undo or redo the action. - */ -History.prototype.add = function (action, params) { - this.index++; - this.history[this.index] = { - 'action': action, - 'params': params, - 'timestamp': new Date() - }; - - // remove redo actions which are invalid now - if (this.index < this.history.length - 1) { - this.history.splice(this.index + 1, this.history.length - this.index - 1); - } - - // fire onchange event - this.onChange(); -}; - -/** - * Clear history - */ -History.prototype.clear = function () { - this.history = []; - this.index = -1; - - // fire onchange event - this.onChange(); -}; - -/** - * Check if there is an action available for undo - * @return {Boolean} canUndo - */ -History.prototype.canUndo = function () { - return (this.index >= 0); -}; - -/** - * Check if there is an action available for redo - * @return {Boolean} canRedo - */ -History.prototype.canRedo = function () { - return (this.index < this.history.length - 1); -}; - -/** - * Undo the last action - */ -History.prototype.undo = function () { - if (this.canUndo()) { - var obj = this.history[this.index]; - if (obj) { - var action = this.actions[obj.action]; - if (action && action.undo) { - action.undo(obj.params); - if (obj.params.oldSelection) { - this.editor.setSelection(obj.params.oldSelection); - } - } - else { - util.log('Error: unknown action "' + obj.action + '"'); - } - } - this.index--; - - // fire onchange event - this.onChange(); - } -}; - -/** - * Redo the last action - */ -History.prototype.redo = function () { - if (this.canRedo()) { - this.index++; - - var obj = this.history[this.index]; - if (obj) { - var action = this.actions[obj.action]; - if (action && action.redo) { - action.redo(obj.params); - if (obj.params.newSelection) { - this.editor.setSelection(obj.params.newSelection); - } - } - else { - util.log('Error: unknown action "' + obj.action + '"'); - } - } - - // fire onchange event - this.onChange(); - } -}; - -/** - * create a mode box to be used in the editor menu's - * @param {JSONEditor} editor - * @param {String[]} modes Available modes: 'code', 'form', 'text', 'tree', 'view' - * @param {String} current Available modes: 'code', 'form', 'text', 'tree', 'view' - * @returns {HTMLElement} box - */ -function createModeBox(editor, modes, current) { - /** - * Switch the mode of the editor - * @param {String} mode - */ - function switchMode(mode) { - // switch mode - editor.setMode(mode); - - // restore focus on mode box - var modeBox = editor.dom && editor.dom.modeBox; - if (modeBox) { - modeBox.focus(); - } - } - - // available modes - var availableModes = { - code: { - 'text': 'Code', - 'title': 'Switch to code highlighter', - 'click': function () { - switchMode('code') - } - }, - form: { - 'text': 'Form', - 'title': 'Switch to form editor', - 'click': function () { - switchMode('form'); - } - }, - text: { - 'text': 'Text', - 'title': 'Switch to plain text editor', - 'click': function () { - switchMode('text'); - } - }, - tree: { - 'text': 'Tree', - 'title': 'Switch to tree editor', - 'click': function () { - switchMode('tree'); - } - }, - view: { - 'text': 'View', - 'title': 'Switch to tree view', - 'click': function () { - switchMode('view'); - } - } - }; - - // list the selected modes - var items = []; - for (var i = 0; i < modes.length; i++) { - var mode = modes[i]; - var item = availableModes[mode]; - if (!item) { - throw new Error('Unknown mode "' + mode + '"'); - } - - item.className = 'type-modes' + ((current == mode) ? ' selected' : ''); - items.push(item); - } - - // retrieve the title of current mode - var currentMode = availableModes[current]; - if (!currentMode) { - throw new Error('Unknown mode "' + current + '"'); - } - var currentTitle = currentMode.text; - - // create the html element - var box = document.createElement('button'); - box.className = 'modes separator'; - box.innerHTML = currentTitle + ' ▾'; - box.title = 'Switch editor mode'; - box.onclick = function () { - var menu = new ContextMenu(items); - menu.show(box); - }; - - return box; -} - -/** - * @constructor SearchBox - * Create a search box in given HTML container - * @param {JSONEditor} editor The JSON Editor to attach to - * @param {Element} container HTML container element of where to - * create the search box - */ -function SearchBox (editor, container) { - var searchBox = this; - - this.editor = editor; - this.timeout = undefined; - this.delay = 200; // ms - this.lastText = undefined; - - this.dom = {}; - this.dom.container = container; - - var table = document.createElement('table'); - this.dom.table = table; - table.className = 'search'; - container.appendChild(table); - var tbody = document.createElement('tbody'); - this.dom.tbody = tbody; - table.appendChild(tbody); - var tr = document.createElement('tr'); - tbody.appendChild(tr); - - var td = document.createElement('td'); - tr.appendChild(td); - var results = document.createElement('div'); - this.dom.results = results; - results.className = 'results'; - td.appendChild(results); - - td = document.createElement('td'); - tr.appendChild(td); - var divInput = document.createElement('div'); - this.dom.input = divInput; - divInput.className = 'frame'; - divInput.title = 'Search fields and values'; - td.appendChild(divInput); - - // table to contain the text input and search button - var tableInput = document.createElement('table'); - divInput.appendChild(tableInput); - var tbodySearch = document.createElement('tbody'); - tableInput.appendChild(tbodySearch); - tr = document.createElement('tr'); - tbodySearch.appendChild(tr); - - var refreshSearch = document.createElement('button'); - refreshSearch.className = 'refresh'; - td = document.createElement('td'); - td.appendChild(refreshSearch); - tr.appendChild(td); - - var search = document.createElement('input'); - this.dom.search = search; - search.oninput = function (event) { - searchBox._onDelayedSearch(event); - }; - search.onchange = function (event) { // For IE 9 - searchBox._onSearch(event); - }; - search.onkeydown = function (event) { - searchBox._onKeyDown(event); - }; - search.onkeyup = function (event) { - searchBox._onKeyUp(event); - }; - refreshSearch.onclick = function (event) { - search.select(); - }; - - // TODO: ESC in FF restores the last input, is a FF bug, https://bugzilla.mozilla.org/show_bug.cgi?id=598819 - td = document.createElement('td'); - td.appendChild(search); - tr.appendChild(td); - - var searchNext = document.createElement('button'); - searchNext.title = 'Next result (Enter)'; - searchNext.className = 'next'; - searchNext.onclick = function () { - searchBox.next(); - }; - td = document.createElement('td'); - td.appendChild(searchNext); - tr.appendChild(td); - - var searchPrevious = document.createElement('button'); - searchPrevious.title = 'Previous result (Shift+Enter)'; - searchPrevious.className = 'previous'; - searchPrevious.onclick = function () { - searchBox.previous(); - }; - td = document.createElement('td'); - td.appendChild(searchPrevious); - tr.appendChild(td); -} - -/** - * Go to the next search result - * @param {boolean} [focus] If true, focus will be set to the next result - * focus is false by default. - */ -SearchBox.prototype.next = function(focus) { - if (this.results != undefined) { - var index = (this.resultIndex != undefined) ? this.resultIndex + 1 : 0; - if (index > this.results.length - 1) { - index = 0; - } - this._setActiveResult(index, focus); - } -}; - -/** - * Go to the prevous search result - * @param {boolean} [focus] If true, focus will be set to the next result - * focus is false by default. - */ -SearchBox.prototype.previous = function(focus) { - if (this.results != undefined) { - var max = this.results.length - 1; - var index = (this.resultIndex != undefined) ? this.resultIndex - 1 : max; - if (index < 0) { - index = max; - } - this._setActiveResult(index, focus); - } -}; - -/** - * Set new value for the current active result - * @param {Number} index - * @param {boolean} [focus] If true, focus will be set to the next result. - * focus is false by default. - * @private - */ -SearchBox.prototype._setActiveResult = function(index, focus) { - // de-activate current active result - if (this.activeResult) { - var prevNode = this.activeResult.node; - var prevElem = this.activeResult.elem; - if (prevElem == 'field') { - delete prevNode.searchFieldActive; - } - else { - delete prevNode.searchValueActive; - } - prevNode.updateDom(); - } - - if (!this.results || !this.results[index]) { - // out of range, set to undefined - this.resultIndex = undefined; - this.activeResult = undefined; - return; - } - - this.resultIndex = index; - - // set new node active - var node = this.results[this.resultIndex].node; - var elem = this.results[this.resultIndex].elem; - if (elem == 'field') { - node.searchFieldActive = true; - } - else { - node.searchValueActive = true; - } - this.activeResult = this.results[this.resultIndex]; - node.updateDom(); - - // TODO: not so nice that the focus is only set after the animation is finished - node.scrollTo(function () { - if (focus) { - node.focus(elem); - } - }); -}; - -/** - * Cancel any running onDelayedSearch. - * @private - */ -SearchBox.prototype._clearDelay = function() { - if (this.timeout != undefined) { - clearTimeout(this.timeout); - delete this.timeout; - } -}; - -/** - * Start a timer to execute a search after a short delay. - * Used for reducing the number of searches while typing. - * @param {Event} event - * @private - */ -SearchBox.prototype._onDelayedSearch = function (event) { - // execute the search after a short delay (reduces the number of - // search actions while typing in the search text box) - this._clearDelay(); - var searchBox = this; - this.timeout = setTimeout(function (event) { - searchBox._onSearch(event); - }, - this.delay); -}; - -/** - * Handle onSearch event - * @param {Event} event - * @param {boolean} [forceSearch] If true, search will be executed again even - * when the search text is not changed. - * Default is false. - * @private - */ -SearchBox.prototype._onSearch = function (event, forceSearch) { - this._clearDelay(); - - var value = this.dom.search.value; - var text = (value.length > 0) ? value : undefined; - if (text != this.lastText || forceSearch) { - // only search again when changed - this.lastText = text; - this.results = this.editor.search(text); - this._setActiveResult(undefined); - - // display search results - if (text != undefined) { - var resultCount = this.results.length; - switch (resultCount) { - case 0: this.dom.results.innerHTML = 'no results'; break; - case 1: this.dom.results.innerHTML = '1 result'; break; - default: this.dom.results.innerHTML = resultCount + ' results'; break; - } - } - else { - this.dom.results.innerHTML = ''; - } - } -}; - -/** - * Handle onKeyDown event in the input box - * @param {Event} event - * @private - */ -SearchBox.prototype._onKeyDown = function (event) { - var keynum = event.which; - if (keynum == 27) { // ESC - this.dom.search.value = ''; // clear search - this._onSearch(event); - event.preventDefault(); - event.stopPropagation(); - } - else if (keynum == 13) { // Enter - if (event.ctrlKey) { - // force to search again - this._onSearch(event, true); - } - else if (event.shiftKey) { - // move to the previous search result - this.previous(); - } - else { - // move to the next search result - this.next(); - } - event.preventDefault(); - event.stopPropagation(); - } -}; - -/** - * Handle onKeyUp event in the input box - * @param {Event} event - * @private - */ -SearchBox.prototype._onKeyUp = function (event) { - var keynum = event.keyCode; - if (keynum != 27 && keynum != 13) { // !show and !Enter - this._onDelayedSearch(event); // For IE 9 - } -}; - -/** - * The highlighter can highlight/unhighlight a node, and - * animate the visibility of a context menu. - * @constructor Highlighter - */ -function Highlighter () { - this.locked = false; -} - -/** - * Hightlight given node and its childs - * @param {Node} node - */ -Highlighter.prototype.highlight = function (node) { - if (this.locked) { - return; - } - - if (this.node != node) { - // unhighlight current node - if (this.node) { - this.node.setHighlight(false); - } - - // highlight new node - this.node = node; - this.node.setHighlight(true); - } - - // cancel any current timeout - this._cancelUnhighlight(); -}; - -/** - * Unhighlight currently highlighted node. - * Will be done after a delay - */ -Highlighter.prototype.unhighlight = function () { - if (this.locked) { - return; - } - - var me = this; - if (this.node) { - this._cancelUnhighlight(); - - // do the unhighlighting after a small delay, to prevent re-highlighting - // the same node when moving from the drag-icon to the contextmenu-icon - // or vice versa. - this.unhighlightTimer = setTimeout(function () { - me.node.setHighlight(false); - me.node = undefined; - me.unhighlightTimer = undefined; - }, 0); - } -}; - -/** - * Cancel an unhighlight action (if before the timeout of the unhighlight action) - * @private - */ -Highlighter.prototype._cancelUnhighlight = function () { - if (this.unhighlightTimer) { - clearTimeout(this.unhighlightTimer); - this.unhighlightTimer = undefined; - } -}; - -/** - * Lock highlighting or unhighlighting nodes. - * methods highlight and unhighlight do not work while locked. - */ -Highlighter.prototype.lock = function () { - this.locked = true; -}; - -/** - * Unlock highlighting or unhighlighting nodes - */ -Highlighter.prototype.unlock = function () { - this.locked = false; -}; - -// create namespace -util = {}; - -/** - * Parse JSON using the parser built-in in the browser. - * On exception, the jsonString is validated and a detailed error is thrown. - * @param {String} jsonString - */ -util.parse = function parse(jsonString) { - try { - return JSON.parse(jsonString); - } - catch (err) { - // try to throw a more detailed error message using validate - util.validate(jsonString); - throw err; - } -}; - -/** - * Validate a string containing a JSON object - * This method uses JSONLint to validate the String. If JSONLint is not - * available, the built-in JSON parser of the browser is used. - * @param {String} jsonString String with an (invalid) JSON object - * @throws Error - */ -util.validate = function validate(jsonString) { - if (typeof(jsonlint) != 'undefined') { - jsonlint.parse(jsonString); - } - else { - JSON.parse(jsonString); - } -}; - -/** - * Extend object a with the properties of object b - * @param {Object} a - * @param {Object} b - * @return {Object} a - */ -util.extend = function extend(a, b) { - for (var prop in b) { - if (b.hasOwnProperty(prop)) { - a[prop] = b[prop]; - } - } - return a; -}; - -/** - * Remove all properties from object a - * @param {Object} a - * @return {Object} a - */ -util.clear = function clear (a) { - for (var prop in a) { - if (a.hasOwnProperty(prop)) { - delete a[prop]; - } - } - return a; -}; - -/** - * Output text to the console, if console is available - * @param {...*} args - */ -util.log = function log (args) { - if (typeof console !== 'undefined' && typeof console.log === 'function') { - console.log.apply(console, arguments); - } -}; - -/** - * Get the type of an object - * @param {*} object - * @return {String} type - */ -util.type = function type (object) { - if (object === null) { - return 'null'; - } - if (object === undefined) { - return 'undefined'; - } - if ((object instanceof Number) || (typeof object === 'number')) { - return 'number'; - } - if ((object instanceof String) || (typeof object === 'string')) { - return 'string'; - } - if ((object instanceof Boolean) || (typeof object === 'boolean')) { - return 'boolean'; - } - if ((object instanceof RegExp) || (typeof object === 'regexp')) { - return 'regexp'; - } - if (Array.isArray(object)) { - return 'array'; - } - - return 'object'; -}; - -/** - * Test whether a text contains a url (matches when a string starts - * with 'http://*' or 'https://*' and has no whitespace characters) - * @param {String} text - */ -var isUrlRegex = /^https?:\/\/\S+$/; -util.isUrl = function isUrl (text) { - return (typeof text == 'string' || text instanceof String) && - isUrlRegex.test(text); -}; - -/** - * Retrieve the absolute left value of a DOM element - * @param {Element} elem A dom element, for example a div - * @return {Number} left The absolute left position of this element - * in the browser page. - */ -util.getAbsoluteLeft = function getAbsoluteLeft(elem) { - var rect = elem.getBoundingClientRect(); - return rect.left + window.pageXOffset || document.scrollLeft || 0; -}; - -/** - * Retrieve the absolute top value of a DOM element - * @param {Element} elem A dom element, for example a div - * @return {Number} top The absolute top position of this element - * in the browser page. - */ -util.getAbsoluteTop = function getAbsoluteTop(elem) { - var rect = elem.getBoundingClientRect(); - return rect.top + window.pageYOffset || document.scrollTop || 0; -}; - -/** - * add a className to the given elements style - * @param {Element} elem - * @param {String} className - */ -util.addClassName = function addClassName(elem, className) { - var classes = elem.className.split(' '); - if (classes.indexOf(className) == -1) { - classes.push(className); // add the class to the array - elem.className = classes.join(' '); - } -}; - -/** - * add a className to the given elements style - * @param {Element} elem - * @param {String} className - */ -util.removeClassName = function removeClassName(elem, className) { - var classes = elem.className.split(' '); - var index = classes.indexOf(className); - if (index != -1) { - classes.splice(index, 1); // remove the class from the array - elem.className = classes.join(' '); - } -}; - -/** - * Strip the formatting from the contents of a div - * the formatting from the div itself is not stripped, only from its childs. - * @param {Element} divElement - */ -util.stripFormatting = function stripFormatting(divElement) { - var childs = divElement.childNodes; - for (var i = 0, iMax = childs.length; i < iMax; i++) { - var child = childs[i]; - - // remove the style - if (child.style) { - // TODO: test if child.attributes does contain style - child.removeAttribute('style'); - } - - // remove all attributes - var attributes = child.attributes; - if (attributes) { - for (var j = attributes.length - 1; j >= 0; j--) { - var attribute = attributes[j]; - if (attribute.specified == true) { - child.removeAttribute(attribute.name); - } - } - } - - // recursively strip childs - util.stripFormatting(child); - } -}; - -/** - * Set focus to the end of an editable div - * code from Nico Burns - * http://stackoverflow.com/users/140293/nico-burns - * http://stackoverflow.com/questions/1125292/how-to-move-cursor-to-end-of-contenteditable-entity - * @param {Element} contentEditableElement A content editable div - */ -util.setEndOfContentEditable = function setEndOfContentEditable(contentEditableElement) { - var range, selection; - if(document.createRange) { - range = document.createRange();//Create a range (a range is a like the selection but invisible) - range.selectNodeContents(contentEditableElement);//Select the entire contents of the element with the range - range.collapse(false);//collapse the range to the end point. false means collapse to end rather than the start - selection = window.getSelection();//get the selection object (allows you to change selection) - selection.removeAllRanges();//remove any selections already made - selection.addRange(range);//make the range you have just created the visible selection - } -}; - -/** - * Select all text of a content editable div. - * http://stackoverflow.com/a/3806004/1262753 - * @param {Element} contentEditableElement A content editable div - */ -util.selectContentEditable = function selectContentEditable(contentEditableElement) { - if (!contentEditableElement || contentEditableElement.nodeName != 'DIV') { - return; - } - - var sel, range; - if (window.getSelection && document.createRange) { - range = document.createRange(); - range.selectNodeContents(contentEditableElement); - sel = window.getSelection(); - sel.removeAllRanges(); - sel.addRange(range); - } -}; - -/** - * Get text selection - * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore - * @return {Range | TextRange | null} range - */ -util.getSelection = function getSelection() { - if (window.getSelection) { - var sel = window.getSelection(); - if (sel.getRangeAt && sel.rangeCount) { - return sel.getRangeAt(0); - } - } - return null; -}; - -/** - * Set text selection - * http://stackoverflow.com/questions/4687808/contenteditable-selected-text-save-and-restore - * @param {Range | TextRange | null} range - */ -util.setSelection = function setSelection(range) { - if (range) { - if (window.getSelection) { - var sel = window.getSelection(); - sel.removeAllRanges(); - sel.addRange(range); - } - } -}; - -/** - * Get selected text range - * @return {Object} params object containing parameters: - * {Number} startOffset - * {Number} endOffset - * {Element} container HTML element holding the - * selected text element - * Returns null if no text selection is found - */ -util.getSelectionOffset = function getSelectionOffset() { - var range = util.getSelection(); - - if (range && 'startOffset' in range && 'endOffset' in range && - range.startContainer && (range.startContainer == range.endContainer)) { - return { - startOffset: range.startOffset, - endOffset: range.endOffset, - container: range.startContainer.parentNode - }; - } - - return null; -}; - -/** - * Set selected text range in given element - * @param {Object} params An object containing: - * {Element} container - * {Number} startOffset - * {Number} endOffset - */ -util.setSelectionOffset = function setSelectionOffset(params) { - if (document.createRange && window.getSelection) { - var selection = window.getSelection(); - if(selection) { - var range = document.createRange(); - // TODO: do not suppose that the first child of the container is a textnode, - // but recursively find the textnodes - range.setStart(params.container.firstChild, params.startOffset); - range.setEnd(params.container.firstChild, params.endOffset); - - util.setSelection(range); - } - } -}; - -/** - * Get the inner text of an HTML element (for example a div element) - * @param {Element} element - * @param {Object} [buffer] - * @return {String} innerText - */ -util.getInnerText = function getInnerText(element, buffer) { - var first = (buffer == undefined); - if (first) { - buffer = { - 'text': '', - 'flush': function () { - var text = this.text; - this.text = ''; - return text; - }, - 'set': function (text) { - this.text = text; - } - }; - } - - // text node - if (element.nodeValue) { - return buffer.flush() + element.nodeValue; - } - - // divs or other HTML elements - if (element.hasChildNodes()) { - var childNodes = element.childNodes; - var innerText = ''; - - for (var i = 0, iMax = childNodes.length; i < iMax; i++) { - var child = childNodes[i]; - - if (child.nodeName == 'DIV' || child.nodeName == 'P') { - var prevChild = childNodes[i - 1]; - var prevName = prevChild ? prevChild.nodeName : undefined; - if (prevName && prevName != 'DIV' && prevName != 'P' && prevName != 'BR') { - innerText += '\n'; - buffer.flush(); - } - innerText += util.getInnerText(child, buffer); - buffer.set('\n'); - } - else if (child.nodeName == 'BR') { - innerText += buffer.flush(); - buffer.set('\n'); - } - else { - innerText += util.getInnerText(child, buffer); - } - } - - return innerText; - } - else { - if (element.nodeName == 'P' && util.getInternetExplorerVersion() != -1) { - // On Internet Explorer, a

with hasChildNodes()==false is - // rendered with a new line. Note that a

with - // hasChildNodes()==true is rendered without a new line - // Other browsers always ensure there is a
inside the

, - // and if not, the

does not render a new line - return buffer.flush(); - } - } - - // br or unknown - return ''; -}; - -/** - * Returns the version of Internet Explorer or a -1 - * (indicating the use of another browser). - * Source: http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx - * @return {Number} Internet Explorer version, or -1 in case of an other browser - */ -util.getInternetExplorerVersion = function getInternetExplorerVersion() { - if (_ieVersion == -1) { - var rv = -1; // Return value assumes failure. - if (navigator.appName == 'Microsoft Internet Explorer') - { - var ua = navigator.userAgent; - var re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})"); - if (re.exec(ua) != null) { - rv = parseFloat( RegExp.$1 ); - } - } - - _ieVersion = rv; - } - - return _ieVersion; -}; - -/** - * Test whether the current browser is Firefox - * @returns {boolean} isFirefox - */ -util.isFirefox = function isFirefox () { - return (navigator.userAgent.indexOf("Firefox") != -1); -}; - -/** - * cached internet explorer version - * @type {Number} - * @private - */ -var _ieVersion = -1; - -/** - * Add and event listener. Works for all browsers - * @param {Element} element An html element - * @param {string} action The action, for example "click", - * without the prefix "on" - * @param {function} listener The callback function to be executed - * @param {boolean} [useCapture] false by default - * @return {function} the created event listener - */ -util.addEventListener = function addEventListener(element, action, listener, useCapture) { - if (element.addEventListener) { - if (useCapture === undefined) - useCapture = false; - - if (action === "mousewheel" && util.isFirefox()) { - action = "DOMMouseScroll"; // For Firefox - } - - element.addEventListener(action, listener, useCapture); - return listener; - } else if (element.attachEvent) { - // Old IE browsers - var f = function () { - return listener.call(element, window.event); - }; - element.attachEvent("on" + action, f); - return f; - } -}; - -/** - * Remove an event listener from an element - * @param {Element} element An html dom element - * @param {string} action The name of the event, for example "mousedown" - * @param {function} listener The listener function - * @param {boolean} [useCapture] false by default - */ -util.removeEventListener = function removeEventListener(element, action, listener, useCapture) { - if (element.removeEventListener) { - if (useCapture === undefined) - useCapture = false; - - if (action === "mousewheel" && util.isFirefox()) { - action = "DOMMouseScroll"; // For Firefox - } - - element.removeEventListener(action, listener, useCapture); - } else if (element.detachEvent) { - // Old IE browsers - element.detachEvent("on" + action, listener); - } -}; - - -// module exports -var jsoneditor = { - 'JSONEditor': JSONEditor, - 'JSONFormatter': function () { - throw new Error('JSONFormatter is deprecated. ' + - 'Use JSONEditor with mode "text" or "code" instead'); - }, - 'util': util -}; - -/** - * load jsoneditor.css - */ -var loadCss = function () { - // find the script named 'jsoneditor.js' or 'jsoneditor-min.js' or - // 'jsoneditor.min.js', and use its path to find the css file to be - // loaded. - var scripts = document.getElementsByTagName('script'); - for (var s = 0; s < scripts.length; s++) { - var src = scripts[s].src; - if (/(^|\/)jsoneditor([-\.]min)?.js$/.test(src)) { - var jsFile = src.split('?')[0]; - var cssFile = jsFile.substring(0, jsFile.length - 2) + 'css'; - - // load css file - var link = document.createElement('link'); - link.type = 'text/css'; - link.rel = 'stylesheet'; - link.href = cssFile; - document.getElementsByTagName('head')[0].appendChild(link); - - break; - } - } -}; - -/** - * CommonJS module exports - */ -if (typeof(module) != 'undefined' && typeof(exports) != 'undefined') { - loadCss(); - module.exports = exports = jsoneditor; -} - -/** - * AMD module exports - */ -if (typeof(require) != 'undefined' && typeof(define) != 'undefined') { - loadCss(); - define(function () { - return jsoneditor; - }); -} -else { - // attach the module to the window, load as a regular javascript file - window['jsoneditor'] = jsoneditor; -} - - -})(); diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/ace.js b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/ace.js deleted file mode 100644 index ef4ddb3280a..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/ace.js +++ /dev/null @@ -1,11 +0,0 @@ -(function(){function o(e){var i=function(e,t){return r("",e,t)},s=t;e&&(t[e]||(t[e]={}),s=t[e]);if(!s.define||!s.define.packaged)n.original=s.define,s.define=n,s.define.packaged=!0;if(!s.require||!s.require.packaged)r.original=s.require,s.require=i,s.require.packaged=!0}var e="",t=function(){return this}();if(!e&&typeof requirejs!="undefined")return;var n=function(e,t,r){if(typeof e!="string"){n.original?n.original.apply(window,arguments):(console.error("dropping module because define wasn't a string."),console.trace());return}arguments.length==2&&(r=t),n.modules||(n.modules={}),n.modules[e]=r},r=function(e,t,n){if(Object.prototype.toString.call(t)==="[object Array]"){var i=[];for(var o=0,u=t.length;o1&&u(t,"")>-1&&(a=RegExp(this.source,r.replace.call(o(this),"g","")),r.replace.call(e.slice(t.index),a,function(){for(var e=1;et.index&&this.lastIndex--}return t},s||(RegExp.prototype.test=function(e){var t=r.exec.call(this,e);return t&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--,!!t})}),define("ace/lib/es5-shim",["require","exports","module"],function(e,t,n){function r(){}function w(e){try{return Object.defineProperty(e,"sentinel",{}),"sentinel"in e}catch(t){}}function j(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e}function F(e){var t=typeof e;return e===null||t==="undefined"||t==="boolean"||t==="number"||t==="string"}function I(e){var t,n,r;if(F(e))return e;n=e.valueOf;if(typeof n=="function"){t=n.call(e);if(F(t))return t}r=e.toString;if(typeof r=="function"){t=r.call(e);if(F(t))return t}throw new TypeError}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!="function")throw new TypeError("Function.prototype.bind called on incompatible "+n);var i=u.call(arguments,1),s=function(){if(this instanceof s){var e=n.apply(this,i.concat(u.call(arguments)));return Object(e)===e?e:this}return n.apply(t,i.concat(u.call(arguments)))};return n.prototype&&(r.prototype=n.prototype,s.prototype=new r,r.prototype=null),s});var i=Function.prototype.call,s=Array.prototype,o=Object.prototype,u=s.slice,a=i.bind(o.toString),f=i.bind(o.hasOwnProperty),l,c,h,p,d;if(d=f(o,"__defineGetter__"))l=i.bind(o.__defineGetter__),c=i.bind(o.__defineSetter__),h=i.bind(o.__lookupGetter__),p=i.bind(o.__lookupSetter__);if([1,2].splice(0).length!=2)if(!function(){function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}var t=[],n;t.splice.apply(t,e(20)),t.splice.apply(t,e(26)),n=t.length,t.splice(5,0,"XXX"),n+1==t.length;if(n+1==t.length)return!0}())Array.prototype.splice=function(e,t){var n=this.length;e>0?e>n&&(e=n):e==void 0?e=0:e<0&&(e=Math.max(n+e,0)),e+ta)for(h=l;h--;)this[f+h]=this[a+h];if(s&&e===c)this.length=c,this.push.apply(this,i);else{this.length=c+s;for(h=0;h>>0;if(a(t)!="[object Function]")throw new TypeError;while(++s>>0,s=Array(i),o=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var u=0;u>>0,s=[],o,u=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var f=0;f>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduce of empty array with no initial value");var s=0,o;if(arguments.length>=2)o=arguments[1];else do{if(s in r){o=r[s++];break}if(++s>=i)throw new TypeError("reduce of empty array with no initial value")}while(!0);for(;s>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduceRight of empty array with no initial value");var s,o=i-1;if(arguments.length>=2)s=arguments[1];else do{if(o in r){s=r[o--];break}if(--o<0)throw new TypeError("reduceRight of empty array with no initial value")}while(!0);do o in this&&(s=t.call(void 0,s,r[o],o,n));while(o--);return s});if(!Array.prototype.indexOf||[0,1].indexOf(1,2)!=-1)Array.prototype.indexOf=function(t){var n=g&&a(this)=="[object String]"?this.split(""):q(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=j(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,j(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1};Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:o)});if(!Object.getOwnPropertyDescriptor){var y="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(y+t);if(!f(t,n))return;var r,i,s;r={enumerable:!0,configurable:!0};if(d){var u=t.__proto__;t.__proto__=o;var i=h(t,n),s=p(t,n);t.__proto__=u;if(i||s)return i&&(r.get=i),s&&(r.set=s),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var b;Object.prototype.__proto__===null?b=function(){return{__proto__:null}}:b=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=b();else{if(typeof t!="object")throw new TypeError("typeof prototype["+typeof t+"] != 'object'");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var E=w({}),S=typeof document=="undefined"||w(document.createElement("div"));if(!E||!S)var x=Object.defineProperty}if(!Object.defineProperty||x){var T="Property description must be an object: ",N="Object.defineProperty called on non-object: ",C="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(t,n,r){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(N+t);if(typeof r!="object"&&typeof r!="function"||r===null)throw new TypeError(T+r);if(x)try{return x.call(Object,t,n,r)}catch(i){}if(f(r,"value"))if(d&&(h(t,n)||p(t,n))){var s=t.__proto__;t.__proto__=o,delete t[n],t[n]=r.value,t.__proto__=s}else t[n]=r.value;else{if(!d)throw new TypeError(C);f(r,"get")&&l(t,n,r.get),f(r,"set")&&c(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)f(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(k){Object.freeze=function(t){return function(n){return typeof n=="function"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n="";while(f(t,n))n+="?";t[n]=!0;var r=f(t,n);return delete t[n],r});if(!Object.keys){var L=!0,A=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],O=A.length;for(var M in{toString:null})L=!1;Object.keys=function R(e){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError("Object.keys called on a non-object");var R=[];for(var t in e)f(e,t)&&R.push(t);if(L)for(var n=0,r=O;n5||Math.abs(e.clientY-a)>5;if(!f||i)o=0;o+=1,f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600)}o==1&&(u=e.clientX,a=e.clientY),r[s]("mousedown",e);if(o>4)o=0;else if(o>1)return r[s](l[o],e)}),i.isOldIE&&t.addListener(e,"dblclick",function(e){o=2,f&&clearTimeout(f),f=setTimeout(function(){f=null},n[o-1]||600),r[s]("mousedown",e),r[s](l[o],e)})},t.addCommandKeyListener=function(e,n){var r=t.addListener;if(i.isOldGecko||i.isOpera&&!("KeyboardEvent"in window)){var s=null;r(e,"keydown",function(e){s=e.keyCode}),r(e,"keypress",function(e){return o(n,e,s)})}else{var u=null;r(e,"keydown",function(e){return u=e.keyIdentifier||e.keyCode,o(n,e,e.keyCode)})}};if(window.postMessage&&!i.isOldIE){var u=1;t.nextTick=function(e,n){n=n||window;var r="zero-timeout-message-"+u;t.addListener(n,"message",function i(s){s.data==r&&(t.stopPropagation(s),t.removeListener(n,"message",i),e())}),n.postMessage(r,"*")}}t.nextFrame=window.requestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame,t.nextFrame?t.nextFrame=t.nextFrame.bind(window):t.nextFrame=function(e){setTimeout(e,17)}}),define("ace/lib/keys",["require","exports","module","ace/lib/oop"],function(e,t,n){var r=e("./oop"),i=function(){var e={MODIFIER_KEYS:{16:"Shift",17:"Ctrl",18:"Alt",224:"Meta"},KEY_MODS:{ctrl:1,alt:2,option:2,shift:4,meta:8,command:8},FUNCTION_KEYS:{8:"Backspace",9:"Tab",13:"Return",19:"Pause",27:"Esc",32:"Space",33:"PageUp",34:"PageDown",35:"End",36:"Home",37:"Left",38:"Up",39:"Right",40:"Down",44:"Print",45:"Insert",46:"Delete",96:"Numpad0",97:"Numpad1",98:"Numpad2",99:"Numpad3",100:"Numpad4",101:"Numpad5",102:"Numpad6",103:"Numpad7",104:"Numpad8",105:"Numpad9",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"Numlock",145:"Scrolllock"},PRINTABLE_KEYS:{32:" ",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",61:"=",65:"a",66:"b",67:"c",68:"d",69:"e",70:"f",71:"g",72:"h",73:"i",74:"j",75:"k",76:"l",77:"m",78:"n",79:"o",80:"p",81:"q",82:"r",83:"s",84:"t",85:"u",86:"v",87:"w",88:"x",89:"y",90:"z",107:"+",109:"-",110:".",188:",",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"}};for(var t in e.FUNCTION_KEYS){var n=e.FUNCTION_KEYS[t].toLowerCase();e[n]=parseInt(t,10)}return r.mixin(e,e.MODIFIER_KEYS),r.mixin(e,e.PRINTABLE_KEYS),r.mixin(e,e.FUNCTION_KEYS),e.enter=e["return"],e.escape=e.esc,e.del=e["delete"],e[173]="-",e}();r.mixin(t,i),t.keyCodeToString=function(e){return(i[e]||String.fromCharCode(e)).toLowerCase()}}),define("ace/lib/oop",["require","exports","module"],function(e,t,n){t.inherits=function(){var e=function(){};return function(t,n){e.prototype=n.prototype,t.super_=n.prototype,t.prototype=new e,t.prototype.constructor=t}}(),t.mixin=function(e,t){for(var n in t)e[n]=t[n]},t.implement=function(e,n){t.mixin(e,n)}}),define("ace/lib/useragent",["require","exports","module"],function(e,t,n){t.OS={LINUX:"LINUX",MAC:"MAC",WINDOWS:"WINDOWS"},t.getOS=function(){return t.isMac?t.OS.MAC:t.isLinux?t.OS.LINUX:t.OS.WINDOWS};if(typeof navigator!="object")return;var r=(navigator.platform.match(/mac|win|linux/i)||["other"])[0].toLowerCase(),i=navigator.userAgent;t.isWin=r=="win",t.isMac=r=="mac",t.isLinux=r=="linux",t.isIE=(navigator.appName=="Microsoft Internet Explorer"||navigator.appName.indexOf("MSAppHost")>=0)&&parseFloat(navigator.userAgent.match(/MSIE ([0-9]+[\.0-9]+)/)[1]),t.isOldIE=t.isIE&&t.isIE<9,t.isGecko=t.isMozilla=window.controllers&&window.navigator.product==="Gecko",t.isOldGecko=t.isGecko&&parseInt((navigator.userAgent.match(/rv\:(\d+)/)||[])[1],10)<4,t.isOpera=window.opera&&Object.prototype.toString.call(window.opera)=="[object Opera]",t.isWebKit=parseFloat(i.split("WebKit/")[1])||undefined,t.isChrome=parseFloat(i.split(" Chrome/")[1])||undefined,t.isAIR=i.indexOf("AdobeAIR")>=0,t.isIPad=i.indexOf("iPad")>=0,t.isTouchPad=i.indexOf("TouchPad")>=0}),define("ace/editor",["require","exports","module","ace/lib/fixoldbrowsers","ace/lib/oop","ace/lib/lang","ace/lib/useragent","ace/keyboard/textinput","ace/mouse/mouse_handler","ace/mouse/fold_handler","ace/keyboard/keybinding","ace/edit_session","ace/search","ace/range","ace/lib/event_emitter","ace/commands/command_manager","ace/commands/default_commands","ace/config"],function(e,t,n){e("./lib/fixoldbrowsers");var r=e("./lib/oop"),i=e("./lib/lang"),s=e("./lib/useragent"),o=e("./keyboard/textinput").TextInput,u=e("./mouse/mouse_handler").MouseHandler,a=e("./mouse/fold_handler").FoldHandler,f=e("./keyboard/keybinding").KeyBinding,l=e("./edit_session").EditSession,c=e("./search").Search,h=e("./range").Range,p=e("./lib/event_emitter").EventEmitter,d=e("./commands/command_manager").CommandManager,v=e("./commands/default_commands").commands,m=e("./config"),g=function(e,t){var n=e.getContainerElement();this.container=n,this.renderer=e,this.commands=new d(s.isMac?"mac":"win",v),this.textInput=new o(e.getTextAreaContainer(),this),this.renderer.textarea=this.textInput.getElement(),this.keyBinding=new f(this),this.$mouseHandler=new u(this),new a(this),this.$blockScrolling=0,this.$search=(new c).set({wrap:!0}),this.setSession(t||new l(""))};(function(){r.implement(this,p),this.setKeyboardHandler=function(e){if(typeof e=="string"&&e){this.$keybindingId=e;var t=this;m.loadModule(["keybinding",e],function(n){t.$keybindingId==e&&t.keyBinding.setKeyboardHandler(n&&n.handler)})}else delete this.$keybindingId,this.keyBinding.setKeyboardHandler(e)},this.getKeyboardHandler=function(){return this.keyBinding.getKeyboardHandler()},this.setSession=function(e){if(this.session==e)return;if(this.session){var t=this.session;this.session.removeEventListener("change",this.$onDocumentChange),this.session.removeEventListener("changeMode",this.$onChangeMode),this.session.removeEventListener("tokenizerUpdate",this.$onTokenizerUpdate),this.session.removeEventListener("changeTabSize",this.$onChangeTabSize),this.session.removeEventListener("changeWrapLimit",this.$onChangeWrapLimit),this.session.removeEventListener("changeWrapMode",this.$onChangeWrapMode),this.session.removeEventListener("onChangeFold",this.$onChangeFold),this.session.removeEventListener("changeFrontMarker",this.$onChangeFrontMarker),this.session.removeEventListener("changeBackMarker",this.$onChangeBackMarker),this.session.removeEventListener("changeBreakpoint",this.$onChangeBreakpoint),this.session.removeEventListener("changeAnnotation",this.$onChangeAnnotation),this.session.removeEventListener("changeOverwrite",this.$onCursorChange),this.session.removeEventListener("changeScrollTop",this.$onScrollTopChange),this.session.removeEventListener("changeLeftTop",this.$onScrollLeftChange);var n=this.session.getSelection();n.removeEventListener("changeCursor",this.$onCursorChange),n.removeEventListener("changeSelection",this.$onSelectionChange)}this.session=e,this.$onDocumentChange=this.onDocumentChange.bind(this),e.addEventListener("change",this.$onDocumentChange),this.renderer.setSession(e),this.$onChangeMode=this.onChangeMode.bind(this),e.addEventListener("changeMode",this.$onChangeMode),this.$onTokenizerUpdate=this.onTokenizerUpdate.bind(this),e.addEventListener("tokenizerUpdate",this.$onTokenizerUpdate),this.$onChangeTabSize=this.renderer.onChangeTabSize.bind(this.renderer),e.addEventListener("changeTabSize",this.$onChangeTabSize),this.$onChangeWrapLimit=this.onChangeWrapLimit.bind(this),e.addEventListener("changeWrapLimit",this.$onChangeWrapLimit),this.$onChangeWrapMode=this.onChangeWrapMode.bind(this),e.addEventListener("changeWrapMode",this.$onChangeWrapMode),this.$onChangeFold=this.onChangeFold.bind(this),e.addEventListener("changeFold",this.$onChangeFold),this.$onChangeFrontMarker=this.onChangeFrontMarker.bind(this),this.session.addEventListener("changeFrontMarker",this.$onChangeFrontMarker),this.$onChangeBackMarker=this.onChangeBackMarker.bind(this),this.session.addEventListener("changeBackMarker",this.$onChangeBackMarker),this.$onChangeBreakpoint=this.onChangeBreakpoint.bind(this),this.session.addEventListener("changeBreakpoint",this.$onChangeBreakpoint),this.$onChangeAnnotation=this.onChangeAnnotation.bind(this),this.session.addEventListener("changeAnnotation",this.$onChangeAnnotation),this.$onCursorChange=this.onCursorChange.bind(this),this.session.addEventListener("changeOverwrite",this.$onCursorChange),this.$onScrollTopChange=this.onScrollTopChange.bind(this),this.session.addEventListener("changeScrollTop",this.$onScrollTopChange),this.$onScrollLeftChange=this.onScrollLeftChange.bind(this),this.session.addEventListener("changeScrollLeft",this.$onScrollLeftChange),this.selection=e.getSelection(),this.selection.addEventListener("changeCursor",this.$onCursorChange),this.$onSelectionChange=this.onSelectionChange.bind(this),this.selection.addEventListener("changeSelection",this.$onSelectionChange),this.onChangeMode(),this.$blockScrolling+=1,this.onCursorChange(),this.$blockScrolling-=1,this.onScrollTopChange(),this.onScrollLeftChange(),this.onSelectionChange(),this.onChangeFrontMarker(),this.onChangeBackMarker(),this.onChangeBreakpoint(),this.onChangeAnnotation(),this.session.getUseWrapMode()&&this.renderer.adjustWrapLimit(),this.renderer.updateFull(),this._emit("changeSession",{session:e,oldSession:t})},this.getSession=function(){return this.session},this.setValue=function(e,t){return this.session.doc.setValue(e),t?t==1?this.navigateFileEnd():t==-1&&this.navigateFileStart():this.selectAll(),e},this.getValue=function(){return this.session.getValue()},this.getSelection=function(){return this.selection},this.resize=function(e){this.renderer.onResize(e)},this.setTheme=function(e){this.renderer.setTheme(e)},this.getTheme=function(){return this.renderer.getTheme()},this.setStyle=function(e){this.renderer.setStyle(e)},this.unsetStyle=function(e){this.renderer.unsetStyle(e)},this.setFontSize=function(e){typeof e=="number"&&(e+="px"),this.container.style.fontSize=e,this.renderer.updateFontSize()},this.$highlightBrackets=function(){this.session.$bracketHighlight&&(this.session.removeMarker(this.session.$bracketHighlight),this.session.$bracketHighlight=null);if(this.$highlightPending)return;var e=this;this.$highlightPending=!0,setTimeout(function(){e.$highlightPending=!1;var t=e.session.findMatchingBracket(e.getCursorPosition());if(t){var n=new h(t.row,t.column,t.row,t.column+1);e.session.$bracketHighlight=e.session.addMarker(n,"ace_bracket","text")}},50)},this.focus=function(){var e=this;setTimeout(function(){e.textInput.focus()}),this.textInput.focus()},this.isFocused=function(){return this.textInput.isFocused()},this.blur=function(){this.textInput.blur()},this.onFocus=function(){if(this.$isFocused)return;this.$isFocused=!0,this.renderer.showCursor(),this.renderer.visualizeFocus(),this._emit("focus")},this.onBlur=function(){if(!this.$isFocused)return;this.$isFocused=!1,this.renderer.hideCursor(),this.renderer.visualizeBlur(),this._emit("blur")},this.$cursorChange=function(){this.renderer.updateCursor()},this.onDocumentChange=function(e){var t=e.data,n=t.range,r;n.start.row==n.end.row&&t.action!="insertLines"&&t.action!="removeLines"?r=n.end.row:r=Infinity,this.renderer.updateLines(n.start.row,r),this._emit("change",e),this.$cursorChange()},this.onTokenizerUpdate=function(e){var t=e.data;this.renderer.updateLines(t.first,t.last)},this.onScrollTopChange=function(){this.renderer.scrollToY(this.session.getScrollTop())},this.onScrollLeftChange=function(){this.renderer.scrollToX(this.session.getScrollLeft())},this.onCursorChange=function(){this.$cursorChange(),this.$blockScrolling||this.renderer.scrollCursorIntoView(),this.$highlightBrackets(),this.$updateHighlightActiveLine(),this._emit("changeSelection")},this.$updateHighlightActiveLine=function(){var e=this.getSession(),t;this.$highlightActiveLine&&(this.$selectionStyle!="line"||!this.selection.isMultiLine())&&(t=this.getCursorPosition()),e.$highlightLineMarker&&!t?(e.removeMarker(e.$highlightLineMarker.id),e.$highlightLineMarker=null):!e.$highlightLineMarker&&t?e.$highlightLineMarker=e.highlightLines(t.row,t.row,"ace_active-line"):t&&(e.$highlightLineMarker.start.row=t.row,e.$highlightLineMarker.end.row=t.row,e._emit("changeBackMarker"))},this.onSelectionChange=function(e){var t=this.session;t.$selectionMarker&&t.removeMarker(t.$selectionMarker),t.$selectionMarker=null;if(!this.selection.isEmpty()){var n=this.selection.getRange(),r=this.getSelectionStyle();t.$selectionMarker=t.addMarker(n,"ace_selection",r)}else this.$updateHighlightActiveLine();var i=this.$highlightSelectedWord&&this.$getSelectionHighLightRegexp();this.session.highlight(i),this._emit("changeSelection")},this.$getSelectionHighLightRegexp=function(){var e=this.session,t=this.getSelectionRange();if(t.isEmpty()||t.isMultiLine())return;var n=t.start.column-1,r=t.end.column+1,i=e.getLine(t.start.row),s=i.length,o=i.substring(Math.max(n,0),Math.min(r,s));if(n>=0&&/^[\w\d]/.test(o)||r<=s&&/[\w\d]$/.test(o))return;o=i.substring(t.start.column,t.end.column);if(!/^[\w\d]+$/.test(o))return;var u=this.$search.$assembleRegExp({wholeWord:!0,caseSensitive:!0,needle:o});return u},this.onChangeFrontMarker=function(){this.renderer.updateFrontMarkers()},this.onChangeBackMarker=function(){this.renderer.updateBackMarkers()},this.onChangeBreakpoint=function(){this.renderer.updateBreakpoints()},this.onChangeAnnotation=function(){this.renderer.setAnnotations(this.session.getAnnotations())},this.onChangeMode=function(){this.renderer.updateText()},this.onChangeWrapLimit=function(){this.renderer.updateFull()},this.onChangeWrapMode=function(){this.renderer.onResize(!0)},this.onChangeFold=function(){this.$updateHighlightActiveLine(),this.renderer.updateFull()},this.getCopyText=function(){var e="";return this.selection.isEmpty()||(e=this.session.getTextRange(this.getSelectionRange())),this._emit("copy",e),e},this.onCopy=function(){this.commands.exec("copy",this)},this.onCut=function(){this.commands.exec("cut",this)},this.onPaste=function(e){if(this.$readOnly)return;this._emit("paste",e),this.insert(e)},this.execCommand=function(e,t){this.commands.exec(e,this,t)},this.insert=function(e){var t=this.session,n=t.getMode(),r=this.getCursorPosition();if(this.getBehavioursEnabled()){var i=n.transformAction(t.getState(r.row),"insertion",this,t,e);i&&(e=i.text)}e=e.replace(" ",this.session.getTabString());if(!this.selection.isEmpty())r=this.session.remove(this.getSelectionRange()),this.clearSelection();else if(this.session.getOverwrite()){var s=new h.fromPoints(r,r);s.end.column+=e.length,this.session.remove(s)}this.clearSelection();var o=r.column,u=t.getState(r.row),a=t.getLine(r.row),f=n.checkOutdent(u,a,e),l=t.insert(r,e);i&&i.selection&&(i.selection.length==2?this.selection.setSelectionRange(new h(r.row,o+i.selection[0],r.row,o+i.selection[1])):this.selection.setSelectionRange(new h(r.row+i.selection[0],i.selection[1],r.row+i.selection[2],i.selection[3])));if(t.getDocument().isNewLine(e)){var c=n.getNextLineIndent(u,a.slice(0,r.column),t.getTabString());this.moveCursorTo(r.row+1,0);var p=t.getTabSize(),d=Number.MAX_VALUE;for(var v=r.row+1;v<=l.row;++v){var m=0;a=t.getLine(v);for(var g=0;g0;++g)a.charAt(g)==" "?y-=p:a.charAt(g)==" "&&(y-=1);t.remove(new h(v,0,v,g))}t.indentRows(r.row+1,l.row,c)}f&&n.autoOutdent(u,t,r.row)},this.onTextInput=function(e){this.keyBinding.onTextInput(e)},this.onCommandKey=function(e,t,n){this.keyBinding.onCommandKey(e,t,n)},this.setOverwrite=function(e){this.session.setOverwrite(e)},this.getOverwrite=function(){return this.session.getOverwrite()},this.toggleOverwrite=function(){this.session.toggleOverwrite()},this.setScrollSpeed=function(e){this.$mouseHandler.setScrollSpeed(e)},this.getScrollSpeed=function(){return this.$mouseHandler.getScrollSpeed()},this.setDragDelay=function(e){this.$mouseHandler.setDragDelay(e)},this.getDragDelay=function(){return this.$mouseHandler.getDragDelay()},this.$selectionStyle="line",this.setSelectionStyle=function(e){if(this.$selectionStyle==e)return;this.$selectionStyle=e,this.onSelectionChange(),this._emit("changeSelectionStyle",{data:e})},this.getSelectionStyle=function(){return this.$selectionStyle},this.$highlightActiveLine=!0,this.setHighlightActiveLine=function(e){if(this.$highlightActiveLine==e)return;this.$highlightActiveLine=e,this.$updateHighlightActiveLine()},this.getHighlightActiveLine=function(){return this.$highlightActiveLine},this.$highlightGutterLine=!0,this.setHighlightGutterLine=function(e){if(this.$highlightGutterLine==e)return;this.renderer.setHighlightGutterLine(e),this.$highlightGutterLine=e},this.getHighlightGutterLine=function(){return this.$highlightGutterLine},this.$highlightSelectedWord=!0,this.setHighlightSelectedWord=function(e){if(this.$highlightSelectedWord==e)return;this.$highlightSelectedWord=e,this.$onSelectionChange()},this.getHighlightSelectedWord=function(){return this.$highlightSelectedWord},this.setAnimatedScroll=function(e){this.renderer.setAnimatedScroll(e)},this.getAnimatedScroll=function(){return this.renderer.getAnimatedScroll()},this.setShowInvisibles=function(e){this.renderer.setShowInvisibles(e)},this.getShowInvisibles=function(){return this.renderer.getShowInvisibles()},this.setDisplayIndentGuides=function(e){this.renderer.setDisplayIndentGuides(e)},this.getDisplayIndentGuides=function(){return this.renderer.getDisplayIndentGuides()},this.setShowPrintMargin=function(e){this.renderer.setShowPrintMargin(e)},this.getShowPrintMargin=function(){return this.renderer.getShowPrintMargin()},this.setPrintMarginColumn=function(e){this.renderer.setPrintMarginColumn(e)},this.getPrintMarginColumn=function(){return this.renderer.getPrintMarginColumn()},this.$readOnly=!1,this.setReadOnly=function(e){this.$readOnly=e,this.textInput.setReadOnly(e),this.renderer.$cursorLayer.setBlinking(!e)},this.getReadOnly=function(){return this.$readOnly},this.$modeBehaviours=!0,this.setBehavioursEnabled=function(e){this.$modeBehaviours=e},this.getBehavioursEnabled=function(){return this.$modeBehaviours},this.$modeWrapBehaviours=!0,this.setWrapBehavioursEnabled=function(e){this.$modeWrapBehaviours=e},this.getWrapBehavioursEnabled=function(){return this.$modeWrapBehaviours},this.setShowFoldWidgets=function(e){var t=this.renderer.$gutterLayer;if(t.getShowFoldWidgets()==e)return;this.renderer.$gutterLayer.setShowFoldWidgets(e),this.$showFoldWidgets=e,this.renderer.updateFull()},this.getShowFoldWidgets=function(){return this.renderer.$gutterLayer.getShowFoldWidgets()},this.setFadeFoldWidgets=function(e){this.renderer.setFadeFoldWidgets(e)},this.getFadeFoldWidgets=function(){return this.renderer.getFadeFoldWidgets()},this.remove=function(e){this.selection.isEmpty()&&(e=="left"?this.selection.selectLeft():this.selection.selectRight());var t=this.getSelectionRange();if(this.getBehavioursEnabled()){var n=this.session,r=n.getState(t.start.row),i=n.getMode().transformAction(r,"deletion",this,n,t);i&&(t=i)}this.session.remove(t),this.clearSelection()},this.removeWordRight=function(){this.selection.isEmpty()&&this.selection.selectWordRight(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeWordLeft=function(){this.selection.isEmpty()&&this.selection.selectWordLeft(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineStart=function(){this.selection.isEmpty()&&this.selection.selectLineStart(),this.session.remove(this.getSelectionRange()),this.clearSelection()},this.removeToLineEnd=function(){this.selection.isEmpty()&&this.selection.selectLineEnd();var e=this.getSelectionRange();e.start.column==e.end.column&&e.start.row==e.end.row&&(e.end.column=0,e.end.row++),this.session.remove(e),this.clearSelection()},this.splitLine=function(){this.selection.isEmpty()||(this.session.remove(this.getSelectionRange()),this.clearSelection());var e=this.getCursorPosition();this.insert("\n"),this.moveCursorToPosition(e)},this.transposeLetters=function(){if(!this.selection.isEmpty())return;var e=this.getCursorPosition(),t=e.column;if(t===0)return;var n=this.session.getLine(e.row),r,i;tt.toLowerCase()?1:0});var r=new h(0,0,0,0);for(var i=e.first;i<=e.last;i++){var s=t.getLine(i);r.start.row=i,r.end.row=i,r.end.column=s.length,t.replace(r,n[i-e.first])}},this.toggleCommentLines=function(){var e=this.session.getState(this.getCursorPosition().row),t=this.$getSelectedRows();this.session.getMode().toggleCommentLines(e,this.session,t.first,t.last)},this.getNumberAt=function(e,t){var n=/[\-]?[0-9]+(?:\.[0-9]+)?/g;n.lastIndex=0;var r=this.session.getLine(e);while(n.lastIndex=t){var s={value:i[0],start:i.index,end:i.index+i[0].length};return s}}return null},this.modifyNumber=function(e){var t=this.selection.getCursor().row,n=this.selection.getCursor().column,r=new h(t,n-1,t,n),i=this.session.getTextRange(r);if(!isNaN(parseFloat(i))&&isFinite(i)){var s=this.getNumberAt(t,n);if(s){var o=s.value.indexOf(".")>=0?s.start+s.value.indexOf(".")+1:s.end,u=s.start+s.value.length-o,a=parseFloat(s.value);a*=Math.pow(10,u),o!==s.end&&n=this.getFirstVisibleRow()&&e<=this.getLastVisibleRow()},this.isRowFullyVisible=function(e){return e>=this.renderer.getFirstFullyVisibleRow()&&e<=this.renderer.getLastFullyVisibleRow()},this.$getVisibleRowCount=function(){return this.renderer.getScrollBottomRow()-this.renderer.getScrollTopRow()+1},this.$moveByPage=function(e,t){var n=this.renderer,r=this.renderer.layerConfig,i=e*Math.floor(r.height/r.lineHeight);this.$blockScrolling++,t==1?this.selection.$moveSelection(function(){this.moveCursorBy(i,0)}):t==0&&(this.selection.moveCursorBy(i,0),this.selection.clearSelection()),this.$blockScrolling--;var s=n.scrollTop;n.scrollBy(0,i*r.lineHeight),t!=null&&n.scrollCursorIntoView(null,.5),n.animateScrolling(s)},this.selectPageDown=function(){this.$moveByPage(1,!0)},this.selectPageUp=function(){this.$moveByPage(-1,!0)},this.gotoPageDown=function(){this.$moveByPage(1,!1)},this.gotoPageUp=function(){this.$moveByPage(-1,!1)},this.scrollPageDown=function(){this.$moveByPage(1)},this.scrollPageUp=function(){this.$moveByPage(-1)},this.scrollToRow=function(e){this.renderer.scrollToRow(e)},this.scrollToLine=function(e,t,n,r){this.renderer.scrollToLine(e,t,n,r)},this.centerSelection=function(){var e=this.getSelectionRange(),t={row:Math.floor(e.start.row+(e.end.row-e.start.row)/2),column:Math.floor(e.start.column+(e.end.column-e.start.column)/2)};this.renderer.alignCursor(t,.5)},this.getCursorPosition=function(){return this.selection.getCursor()},this.getCursorPositionScreen=function(){return this.session.documentToScreenPosition(this.getCursorPosition())},this.getSelectionRange=function(){return this.selection.getRange()},this.selectAll=function(){this.$blockScrolling+=1,this.selection.selectAll(),this.$blockScrolling-=1},this.clearSelection=function(){this.selection.clearSelection()},this.moveCursorTo=function(e,t){this.selection.moveCursorTo(e,t)},this.moveCursorToPosition=function(e){this.selection.moveCursorToPosition(e)},this.jumpToMatching=function(e){var t=this.getCursorPosition(),n=this.session.getBracketRange(t);if(!n){n=this.find({needle:/[{}()\[\]]/g,preventScroll:!0,start:{row:t.row,column:t.column-1}});if(!n)return;var r=n.start;r.row==t.row&&Math.abs(r.column-t.column)<2&&(n=this.session.getBracketRange(r))}r=n&&n.cursor||r,r&&(e?n&&n.isEqual(this.getSelectionRange())?this.clearSelection():this.selection.selectTo(r.row,r.column):(this.clearSelection(),this.moveCursorTo(r.row,r.column)))},this.gotoLine=function(e,t,n){this.selection.clearSelection(),this.session.unfold({row:e-1,column:t||0}),this.$blockScrolling+=1,this.moveCursorTo(e-1,t||0),this.$blockScrolling-=1,this.isRowFullyVisible(e-1)||this.scrollToLine(e-1,!0,n)},this.navigateTo=function(e,t){this.clearSelection(),this.moveCursorTo(e,t)},this.navigateUp=function(e){this.selection.clearSelection(),e=e||1,this.selection.moveCursorBy(-e,0)},this.navigateDown=function(e){this.selection.clearSelection(),e=e||1,this.selection.moveCursorBy(e,0)},this.navigateLeft=function(e){if(!this.selection.isEmpty()){var t=this.getSelectionRange().start;this.moveCursorToPosition(t)}else{e=e||1;while(e--)this.selection.moveCursorLeft()}this.clearSelection()},this.navigateRight=function(e){if(!this.selection.isEmpty()){var t=this.getSelectionRange().end;this.moveCursorToPosition(t)}else{e=e||1;while(e--)this.selection.moveCursorRight()}this.clearSelection()},this.navigateLineStart=function(){this.selection.moveCursorLineStart(),this.clearSelection()},this.navigateLineEnd=function(){this.selection.moveCursorLineEnd(),this.clearSelection()},this.navigateFileEnd=function(){var e=this.renderer.scrollTop;this.selection.moveCursorFileEnd(),this.clearSelection(),this.renderer.animateScrolling(e)},this.navigateFileStart=function(){var e=this.renderer.scrollTop;this.selection.moveCursorFileStart(),this.clearSelection(),this.renderer.animateScrolling(e)},this.navigateWordRight=function(){this.selection.moveCursorWordRight(),this.clearSelection()},this.navigateWordLeft=function(){this.selection.moveCursorWordLeft(),this.clearSelection()},this.replace=function(e,t){t&&this.$search.set(t);var n=this.$search.find(this.session),r=0;return n?(this.$tryReplace(n,e)&&(r=1),n!==null&&(this.selection.setSelectionRange(n),this.renderer.scrollSelectionIntoView(n.start,n.end)),r):r},this.replaceAll=function(e,t){t&&this.$search.set(t);var n=this.$search.findAll(this.session),r=0;if(!n.length)return r;this.$blockScrolling+=1;var i=this.getSelectionRange();this.clearSelection(),this.selection.moveCursorTo(0,0);for(var s=n.length-1;s>=0;--s)this.$tryReplace(n[s],e)&&r++;return this.selection.setSelectionRange(i),this.$blockScrolling-=1,r},this.$tryReplace=function(e,t){var n=this.session.getTextRange(e);return t=this.$search.replace(n,t),t!==null?(e.end=this.session.replace(e,t),e):null},this.getLastSearchOptions=function(){return this.$search.getOptions()},this.find=function(e,t,n){t||(t={}),typeof e=="string"||e instanceof RegExp?t.needle=e:typeof e=="object"&&r.mixin(t,e);var i=this.selection.getRange();t.needle==null&&(e=this.session.getTextRange(i)||this.$search.$options.needle,e||(i=this.session.getWordRange(i.start.row,i.start.column),e=this.session.getTextRange(i)),this.$search.set({needle:e})),this.$search.set(t),t.start||this.$search.set({start:i});var s=this.$search.find(this.session);if(t.preventScroll)return s;if(s)return this.revealRange(s,n),s;t.backwards?i.start=i.end:i.end=i.start,this.selection.setRange(i)},this.findNext=function(e,t){this.find({skipCurrent:!0,backwards:!1},e,t)},this.findPrevious=function(e,t){this.find(e,{skipCurrent:!0,backwards:!0},t)},this.revealRange=function(e,t){this.$blockScrolling+=1,this.session.unfold(e),this.selection.setSelectionRange(e),this.$blockScrolling-=1;var n=this.renderer.scrollTop;this.renderer.scrollSelectionIntoView(e.start,e.end,.5),t!=0&&this.renderer.animateScrolling(n)},this.undo=function(){this.$blockScrolling++,this.session.getUndoManager().undo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.redo=function(){this.$blockScrolling++,this.session.getUndoManager().redo(),this.$blockScrolling--,this.renderer.scrollCursorIntoView(null,.5)},this.destroy=function(){this.renderer.destroy()}}).call(g.prototype),t.Editor=g}),define("ace/lib/lang",["require","exports","module"],function(e,t,n){t.stringReverse=function(e){return e.split("").reverse().join("")},t.stringRepeat=function(e,t){var n="";while(t>0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n=0){t=this.$clickSelection.start;if(i.start.row!=r.row||i.start.column!=r.column)r=i.end}else if(s==-1&&o==1)r=i.end,t=i.start;else{var u=a(this.$clickSelection,r);r=u.cursor,t=u.anchor}n.selection.setSelectionAnchor(t.row,t.column)}n.selection.selectToPosition(r),n.renderer.scrollCursorIntoView()},this.startDrag=function(){var e=this.editor;this.setState("drag"),this.dragRange=e.getSelectionRange();var t=e.getSelectionStyle();this.dragSelectionMarker=e.session.addMarker(this.dragRange,"ace_selection",t),e.clearSelection(),r.addCssClass(e.container,"ace_dragging"),this.$dragKeybinding||(this.$dragKeybinding={handleKeyboard:function(e,t,n,r){if(n=="esc")return{command:this.command}},command:{exec:function(e){var t=e.$mouseHandler;t.dragCursor=null,t.dragEnd(),t.startSelect()}}}),e.keyBinding.addKeyboardHandler(this.$dragKeybinding)},this.focusWait=function(){var e=u(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),t=(new Date).getTime();(e>s||t-this.mousedownEvent.time>this.$focusWaitTimout)&&this.startSelect()},this.dragWait=function(e){var t=u(this.mousedownEvent.x,this.mousedownEvent.y,this.x,this.y),n=(new Date).getTime(),r=this.editor;t>s?this.startSelect(this.mousedownEvent.getDocumentPosition()):n-this.mousedownEvent.time>r.getDragDelay()&&this.startDrag()},this.dragWaitEnd=function(e){this.mousedownEvent.domEvent=e,this.startSelect()},this.drag=function(){var e=this.editor;this.dragCursor=e.renderer.screenToTextCoordinates(this.x,this.y),e.moveCursorToPosition(this.dragCursor),e.renderer.scrollCursorIntoView()},this.dragEnd=function(e){var t=this.editor,n=this.dragCursor,i=this.dragRange;r.removeCssClass(t.container,"ace_dragging"),t.session.removeMarker(this.dragSelectionMarker),t.keyBinding.removeKeyboardHandler(this.$dragKeybinding);if(!n)return;t.clearSelection();if(e&&(e.ctrlKey||e.altKey)){var s=t.session,o=i;o.end=s.insert(n,s.getTextRange(i)),o.start=n}else{if(i.contains(n.row,n.column))return;var o=t.moveText(i,n)}if(!o)return;t.selection.setSelectionRange(o)},this.onDoubleClick=function(e){var t=e.getDocumentPosition(),n=this.editor,r=n.session,i=r.getBracketRange(t);if(i){i.isEmpty()&&(i.start.column--,i.end.column++),this.$clickSelection=i,this.setState("select");return}this.$clickSelection=n.selection.getWordRange(t.row,t.column),this.setState("selectByWords")},this.onTripleClick=function(e){var t=e.getDocumentPosition(),n=this.editor;this.setState("selectByLines"),this.$clickSelection=n.selection.getLineRange(t.row)},this.onQuadClick=function(e){var t=this.editor;t.selectAll(),this.$clickSelection=t.getSelectionRange(),this.setState("null")},this.onMouseWheel=function(e){if(e.getShiftKey()||e.getAccelKey())return;var t=this.editor,n=t.renderer.isScrollableBy(e.wheelX*e.speed,e.wheelY*e.speed);if(n)this.$passScrollEvent=!1;else{if(this.$passScrollEvent)return;if(!this.$scrollStopTimeout){var r=this;this.$scrollStopTimeout=setTimeout(function(){r.$passScrollEvent=!0,r.$scrollStopTimeout=null},200)}}return t.renderer.scrollBy(e.wheelX*e.speed,e.wheelY*e.speed),e.preventDefault()}}).call(o.prototype),t.DefaultHandlers=o}),define("ace/mouse/default_gutter_handler",["require","exports","module","ace/lib/dom","ace/lib/event"],function(e,t,n){function s(e){function f(){u=r.createElement("div"),u.className="ace_gutter-tooltip",u.style.display="none",t.container.appendChild(u)}function l(){u||f();var e=o.getDocumentPosition().row,r=n.$annotations[e];if(!r)return c();var i=t.session.getLength();if(e==i){var s=t.renderer.pixelToScreenCoordinates(0,o.y).row,l=o.$pos;if(s>t.session.documentToScreenRow(l.row,l.column))return c()}if(a==r)return;a=r.text.join("
"),u.style.display="block",u.innerHTML=a,t.on("mousewheel",c),h(o)}function c(){s&&(s=clearTimeout(s)),a&&(u.style.display="none",a=null,t.removeEventListener("mousewheel",c))}function h(e){var n=t.renderer.$gutter.getBoundingClientRect();u.style.left=e.x+15+"px",e.y+3*t.renderer.lineHeight+150)return;return clearInterval(o),t.session.removeMarker(n),n=null,t.selection.setSelectionRange(u,a),r.preventDefault(e)}),r.addListener(c,"drop",function(e){if(t.getReadOnly())return;return l=0,clearInterval(o),t.session.removeMarker(n),n=null,u.end=t.session.insert(f,e.dataTransfer.getData("Text")),u.start=f,t.focus(),t.selection.setSelectionRange(u),r.preventDefault(e)})};t.DragdropHandler=i}),define("ace/mouse/fold_handler",["require","exports","module"],function(e,t,n){function r(e){e.on("click",function(t){var n=t.getDocumentPosition(),r=e.session,i=r.getFoldAt(n.row,n.column,1);i&&(t.getAccelKey()?r.removeFold(i):r.expandFold(i),t.stop())}),e.on("guttermousedown",function(t){if(!e.isFocused())return;var n=e.renderer.$gutterLayer.getRegion(t);if(n=="foldWidgets"){var r=t.getDocumentPosition().row,i=e.session;i.foldWidgets&&i.foldWidgets[r]&&e.session.onFoldWidgetClick(r,t),t.stop()}}),e.on("gutterdblclick",function(t){var n=e.renderer.$gutterLayer.getRegion(t);if(n=="foldWidgets"){var r=t.getDocumentPosition().row,i=e.session,s=i.foldWidgets;if(!s||s[r])return;var o=r-1,u;while(o>=0){var a=s[o];a==null&&(a=s[o]=i.getFoldWidget());if(a=="start"){var f=i.getFoldWidgetRange(o);u||(u=f);if(f&&f.end.row>=r)break}o--}o==-1&&(f=u);if(f){var r=f.start.row,l=i.getFoldAt(r,i.getLine(r).length,1);l?i.removeFold(l):(i.addFold("...",f),e.renderer.scrollCursorIntoView({row:f.start.row,column:0}))}t.stop()}})}t.FoldHandler=r}),define("ace/keyboard/keybinding",["require","exports","module","ace/lib/keys","ace/lib/event"],function(e,t,n){var r=e("../lib/keys"),i=e("../lib/event"),s=function(e){this.$editor=e,this.$data={},this.$handlers=[],this.setDefaultHandler(e.commands)};(function(){this.setDefaultHandler=function(e){this.removeKeyboardHandler(this.$defaultHandler),this.$defaultHandler=e,this.addKeyboardHandler(e,0),this.$data={editor:this.$editor}},this.setKeyboardHandler=function(e){if(this.$handlers[this.$handlers.length-1]==e)return;while(this.$handlers[1])this.removeKeyboardHandler(this.$handlers[1]);this.addKeyboardHandler(e,1)},this.addKeyboardHandler=function(e,t){if(!e)return;var n=this.$handlers.indexOf(e);n!=-1&&this.$handlers.splice(n,1),t==undefined?this.$handlers.push(e):this.$handlers.splice(t,0,e),n==-1&&e.attach&&e.attach(this.$editor)},this.removeKeyboardHandler=function(e){var t=this.$handlers.indexOf(e);return t==-1?!1:(this.$handlers.splice(t,1),e.detach&&e.detach(this.$editor),!0)},this.getKeyboardHandler=function(){return this.$handlers[this.$handlers.length-1]},this.$callKeyboardHandlers=function(e,t,n,r){var s,o=!1,u=this.$editor.commands;for(var a=this.$handlers.length;a--;){s=this.$handlers[a].handleKeyboard(this.$data,e,t,n,r);if(!s||!s.command)continue;s.command=="null"?o=s.passEvent!=1:o=u.exec(s.command,this.$editor,s.args,r),o&&r&&e!=-1&&i.stopEvent(r);if(o)break}return o},this.onCommandKey=function(e,t,n){var i=r.keyCodeToString(n);this.$callKeyboardHandlers(t,i,n,e)},this.onTextInput=function(e){var t=this.$callKeyboardHandlers(-1,e);t||this.$editor.commands.exec("insertstring",this.$editor,e)}}).call(s.prototype),t.KeyBinding=s}),define("ace/edit_session",["require","exports","module","ace/config","ace/lib/oop","ace/lib/lang","ace/lib/net","ace/lib/event_emitter","ace/selection","ace/mode/text","ace/range","ace/document","ace/background_tokenizer","ace/search_highlight","ace/edit_session/folding","ace/edit_session/bracket_match"],function(e,t,n){var r=e("./config"),i=e("./lib/oop"),s=e("./lib/lang"),o=e("./lib/net"),u=e("./lib/event_emitter").EventEmitter,a=e("./selection").Selection,f=e("./mode/text").Mode,l=e("./range").Range,c=e("./document").Document,h=e("./background_tokenizer").BackgroundTokenizer,p=e("./search_highlight").SearchHighlight,d=function(e,t){this.$breakpoints=[],this.$decorations=[],this.$frontMarkers={},this.$backMarkers={},this.$markerId=1,this.$undoSelect=!0,this.$foldData=[],this.$foldData.toString=function(){var e="";return this.forEach(function(t){e+="\n"+t.toString()}),e},this.on("changeFold",this.onChangeFold.bind(this)),this.$onChange=this.onChange.bind(this);if(typeof e!="object"||!e.getLine)e=new c(e);this.setDocument(e),this.selection=new a(this),this.setMode(t)};(function(){function g(e){return e<4352?!1:e>=4352&&e<=4447||e>=4515&&e<=4519||e>=4602&&e<=4607||e>=9001&&e<=9002||e>=11904&&e<=11929||e>=11931&&e<=12019||e>=12032&&e<=12245||e>=12272&&e<=12283||e>=12288&&e<=12350||e>=12353&&e<=12438||e>=12441&&e<=12543||e>=12549&&e<=12589||e>=12593&&e<=12686||e>=12688&&e<=12730||e>=12736&&e<=12771||e>=12784&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=13054||e>=13056&&e<=19903||e>=19968&&e<=42124||e>=42128&&e<=42182||e>=43360&&e<=43388||e>=44032&&e<=55203||e>=55216&&e<=55238||e>=55243&&e<=55291||e>=63744&&e<=64255||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=65281&&e<=65376||e>=65504&&e<=65510}i.implement(this,u),this.setDocument=function(e){this.doc&&this.doc.removeListener("change",this.$onChange),this.doc=e,e.on("change",this.$onChange),this.bgTokenizer&&this.bgTokenizer.setDocument(this.getDocument()),this.resetCaches()},this.getDocument=function(){return this.doc},this.$resetRowCache=function(e){if(!e){this.$docRowCache=[],this.$screenRowCache=[];return}var t=this.$getRowCacheIndex(this.$docRowCache,e)+1,n=this.$docRowCache.length;this.$docRowCache.splice(t,n),this.$screenRowCache.splice(t,n)},this.$getRowCacheIndex=function(e,t){var n=0,r=e.length-1;while(n<=r){var i=n+r>>1,s=e[i];if(t>s)n=i+1;else{if(!(t=t)break}return r=n[s],r?(r.index=s,r.start=i-r.value.length,r):null},this.setUndoManager=function(e){this.$undoManager=e,this.$deltas=[],this.$deltasDoc=[],this.$deltasFold=[],this.$informUndoManager&&this.$informUndoManager.cancel();if(e){var t=this;this.$syncInformUndoManager=function(){t.$informUndoManager.cancel(),t.$deltasFold.length&&(t.$deltas.push({group:"fold",deltas:t.$deltasFold}),t.$deltasFold=[]),t.$deltasDoc.length&&(t.$deltas.push({group:"doc",deltas:t.$deltasDoc}),t.$deltasDoc=[]),t.$deltas.length>0&&e.execute({action:"aceupdate",args:[t.$deltas,t]}),t.$deltas=[]},this.$informUndoManager=s.deferredCall(this.$syncInformUndoManager)}},this.$defaultUndoManager={undo:function(){},redo:function(){},reset:function(){}},this.getUndoManager=function(){return this.$undoManager||this.$defaultUndoManager},this.getTabString=function(){return this.getUseSoftTabs()?s.stringRepeat(" ",this.getTabSize()):" "},this.$useSoftTabs=!0,this.setUseSoftTabs=function(e){if(this.$useSoftTabs===e)return;this.$useSoftTabs=e},this.getUseSoftTabs=function(){return this.$useSoftTabs},this.$tabSize=4,this.setTabSize=function(e){if(isNaN(e)||this.$tabSize===e)return;this.$modified=!0,this.$rowLengthCache=[],this.$tabSize=e,this._emit("changeTabSize")},this.getTabSize=function(){return this.$tabSize},this.isTabStop=function(e){return this.$useSoftTabs&&e.column%this.$tabSize==0},this.$overwrite=!1,this.setOverwrite=function(e){if(this.$overwrite==e)return;this.$overwrite=e,this._emit("changeOverwrite")},this.getOverwrite=function(){return this.$overwrite},this.toggleOverwrite=function(){this.setOverwrite(!this.$overwrite)},this.addGutterDecoration=function(e,t){this.$decorations[e]||(this.$decorations[e]=""),this.$decorations[e]+=" "+t,this._emit("changeBreakpoint",{})},this.removeGutterDecoration=function(e,t){this.$decorations[e]=(this.$decorations[e]||"").replace(" "+t,""),this._emit("changeBreakpoint",{})},this.getBreakpoints=function(){return this.$breakpoints},this.setBreakpoints=function(e){this.$breakpoints=[];for(var t=0;t0&&(r=!!n.charAt(t-1).match(this.tokenRe)),r||(r=!!n.charAt(t).match(this.tokenRe));if(r)var i=this.tokenRe;else if(/^\s+$/.test(n.slice(t-1,t+1)))var i=/\s/;else var i=this.nonTokenRe;var s=t;if(s>0){do s--;while(s>=0&&n.charAt(s).match(i));s++}var o=t;while(oo){a=s.end.row+1;if(a>=u)break;s=this.$foldData[i++],o=s?s.start.row:Infinity}n[a]==null&&(n[a]=this.$getStringScreenWidth(t[a])[0]),n[a]>r&&(r=n[a])}this.screenWidth=r}},this.getLine=function(e){return this.doc.getLine(e)},this.getLines=function(e,t){return this.doc.getLines(e,t)},this.getLength=function(){return this.doc.getLength()},this.getTextRange=function(e){return this.doc.getTextRange(e||this.selection.getRange())},this.insert=function(e,t){return this.doc.insert(e,t)},this.remove=function(e){return this.doc.remove(e)},this.undoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;var n=null;for(var r=e.length-1;r!=-1;r--){var i=e[r];i.group=="doc"?(this.doc.revertDeltas(i.deltas),n=this.$getUndoSelection(i.deltas,!0,n)):i.deltas.forEach(function(e){this.addFolds(e.folds)},this)}return this.$fromUndo=!1,n&&this.$undoSelect&&!t&&this.selection.setSelectionRange(n),n},this.redoChanges=function(e,t){if(!e.length)return;this.$fromUndo=!0;var n=null;for(var r=0;r=this.doc.getLength()-1)return 0;var n=this.doc.removeLines(e,t);return this.doc.insertLines(e+1,n),1},this.duplicateLines=function(e,t){var e=this.$clipRowToDocument(e),t=this.$clipRowToDocument(t),n=this.getLines(e,t);this.doc.insertLines(e,n);var r=t-e+1;return r},this.$clipRowToDocument=function(e){return Math.max(0,Math.min(e,this.doc.getLength()-1))},this.$clipColumnToRow=function(e,t){return t<0?0:Math.min(this.doc.getLine(e).length,t)},this.$clipPositionToDocument=function(e,t){t=Math.max(0,t);if(e<0)e=0,t=0;else{var n=this.doc.getLength();e>=n?(e=n-1,t=this.doc.getLine(n-1).length):t=Math.min(this.doc.getLine(e).length,t)}return{row:e,column:t}},this.$clipRangeToDocument=function(e){e.start.row<0?(e.start.row=0,e.start.column=0):e.start.column=this.$clipColumnToRow(e.start.row,e.start.column);var t=this.doc.getLength()-1;return e.end.row>t?(e.end.row=t,e.end.column=this.doc.getLine(t).length):e.end.column=this.$clipColumnToRow(e.end.row,e.end.column),e},this.$wrapLimit=80,this.$useWrapMode=!1,this.$wrapLimitRange={min:null,max:null},this.setUseWrapMode=function(e){if(e!=this.$useWrapMode){this.$useWrapMode=e,this.$modified=!0,this.$resetRowCache(0);if(e){var t=this.getLength();this.$wrapData=[];for(var n=0;n0?(this.$wrapLimit=t,this.$modified=!0,this.$useWrapMode&&(this.$updateWrapData(0,this.getLength()-1),this.$resetRowCache(0),this._emit("changeWrapLimit")),!0):!1},this.$constrainWrapLimit=function(e){var t=this.$wrapLimitRange.min;t&&(e=Math.max(t,e));var n=this.$wrapLimitRange.max;return n&&(e=Math.min(n,e)),Math.max(1,e)},this.getWrapLimit=function(){return this.$wrapLimit},this.getWrapLimitRange=function(){return{min:this.$wrapLimitRange.min,max:this.$wrapLimitRange.max}},this.$updateInternalDataOnChange=function(e){var t=this.$useWrapMode,n,r=e.data.action,i=e.data.range.start.row,s=e.data.range.end.row,o=e.data.range.start,u=e.data.range.end,a=null;r.indexOf("Lines")!=-1?(r=="insertLines"?s=i+e.data.lines.length:s=i,n=e.data.lines?e.data.lines.length:s-i):n=s-i;if(n!=0)if(r.indexOf("remove")!=-1){this[t?"$wrapData":"$rowLengthCache"].splice(i,n);var f=this.$foldData;a=this.getFoldsInRange(e.data.range),this.removeFolds(a);var l=this.getFoldLine(u.row),c=0;if(l){l.addRemoveChars(u.row,u.column,o.column-u.column),l.shiftRow(-n);var h=this.getFoldLine(i);h&&h!==l&&(h.merge(l),l=h),c=f.indexOf(l)+1}for(c;c=u.row&&l.shiftRow(-n)}s=i}else{var p;if(t){p=[i,0];for(var d=0;d=i&&l.shiftRow(n)}}else{n=Math.abs(e.data.range.start.column-e.data.range.end.column),r.indexOf("remove")!=-1&&(a=this.getFoldsInRange(e.data.range),this.removeFolds(a),n=-n);var l=this.getFoldLine(i);l&&l.addRemoveChars(i,o.column,n)}return t&&this.$wrapData.length!=this.doc.getLength()&&console.error("doc.getLength() and $wrapData.length have to be the same!"),t?this.$updateWrapData(i,s):this.$updateRowLengthCache(i,s),a},this.$updateRowLengthCache=function(e,t,n){this.$rowLengthCache[e]=null,this.$rowLengthCache[t]=null},this.$updateWrapData=function(e,t){var n=this.doc.getAllLines(),r=this.getTabSize(),i=this.$wrapData,u=this.$wrapLimit,f,l,c=e;t=Math.min(t,n.length-1);while(c<=t){l=this.getFoldLine(c,l);if(!l)f=this.$getDisplayTokens(s.stringTrimRight(n[c])),i[c]=this.$computeWrapSplits(f,u,r),c++;else{f=[],l.walk(function(e,t,r,i){var s;if(e!=null){s=this.$getDisplayTokens(e,f.length),s[0]=o;for(var u=1;u=d)f.pop();i[l.start.row]=this.$computeWrapSplits(f,u,r),c=l.end.row+1}}};var t=1,n=2,o=3,a=4,c=9,d=10,v=11,m=12;this.$computeWrapSplits=function(e,t){function u(t){var r=e.slice(i,t),o=r.length;r.join("").replace(/12/g,function(){o-=1}).replace(/2/g,function(){o-=1}),s+=o,n.push(s),i=t}if(e.length==0)return[];var n=[],r=e.length,i=0,s=0;while(r-i>t){var f=i+t;if(e[f]>=d){while(e[f]>=d)f++;u(f);continue}if(e[f]==o||e[f]==a){for(f;f!=i-1;f--)if(e[f]==o)break;if(f>i){u(f);continue}f=i+t;for(f;fl&&e[f]l&&e[f]==c)f--;if(f>l){u(++f);continue}f=i+t,u(f)}return n},this.$getDisplayTokens=function(e,r){var i=[],s;r=r||0;for(var o=0;o39&&u<48||u>57&&u<64?i.push(c):u>=4352&&g(u)?i.push(t,n):i.push(t)}return i},this.$getStringScreenWidth=function(e,t,n){if(t==0)return[0,0];t==null&&(t=Infinity),n=n||0;var r,i;for(i=0;i=4352&&g(r)?n+=2:n+=1;if(n>t)break}return[n,i]},this.getRowLength=function(e){return!this.$useWrapMode||!this.$wrapData[e]?1:this.$wrapData[e].length+1},this.getScreenLastRowColumn=function(e){var t=this.screenToDocumentPosition(e,Number.MAX_VALUE);return this.documentToScreenColumn(t.row,t.column)},this.getDocumentLastRowColumn=function(e,t){var n=this.documentToScreenRow(e,t);return this.getScreenLastRowColumn(n)},this.getDocumentLastRowColumnPosition=function(e,t){var n=this.documentToScreenRow(e,t);return this.screenToDocumentPosition(n,Number.MAX_VALUE/10)},this.getRowSplitData=function(e){return this.$useWrapMode?this.$wrapData[e]:undefined},this.getScreenTabSize=function(e){return this.$tabSize-e%this.$tabSize},this.screenToDocumentRow=function(e,t){return this.screenToDocumentPosition(e,t).row},this.screenToDocumentColumn=function(e,t){return this.screenToDocumentPosition(e,t).column},this.screenToDocumentPosition=function(e,t){if(e<0)return{row:0,column:0};var n,r=0,i=0,s,o=0,u=0,a=this.$screenRowCache,f=this.$getRowCacheIndex(a,e),l=a.length;if(l&&f>=0)var o=a[f],r=this.$docRowCache[f],c=e>a[l-1];else var c=!l;var h=this.getLength()-1,p=this.getNextFoldLine(r),d=p?p.start.row:Infinity;while(o<=e){u=this.getRowLength(r);if(o+u-1>=e||r>=h)break;o+=u,r++,r>d&&(r=p.end.row+1,p=this.getNextFoldLine(r,p),d=p?p.start.row:Infinity),c&&(this.$docRowCache.push(r),this.$screenRowCache.push(o))}if(p&&p.start.row<=r)n=this.getFoldDisplayLine(p),r=p.start.row;else{if(o+u<=e||r>h)return{row:h,column:this.getLine(h).length};n=this.getLine(r),p=null}if(this.$useWrapMode){var v=this.$wrapData[r];v&&(s=v[e-o],e>o&&v.length&&(i=v[e-o-1]||v[v.length-1],n=n.substring(i)))}return i+=this.$getStringScreenWidth(n,t)[1],this.$useWrapMode&&i>=s&&(i=s-1),p?p.idxToPosition(i):{row:r,column:i}},this.documentToScreenPosition=function(e,t){if(typeof t=="undefined")var n=this.$clipPositionToDocument(e.row,e.column);else n=this.$clipPositionToDocument(e,t);e=n.row,t=n.column;var r=0,i=null,s=null;s=this.getFoldAt(e,t,1),s&&(e=s.start.row,t=s.start.column);var o,u=0,a=this.$docRowCache,f=this.$getRowCacheIndex(a,e),l=a.length;if(l&&f>=0)var u=a[f],r=this.$screenRowCache[f],c=e>a[l-1];else var c=!l;var h=this.getNextFoldLine(u),p=h?h.start.row:Infinity;while(u=p){o=h.end.row+1;if(o>e)break;h=this.getNextFoldLine(o,h),p=h?h.start.row:Infinity}else o=u+1;r+=this.getRowLength(u),u=o,c&&(this.$docRowCache.push(u),this.$screenRowCache.push(r))}var d="";h&&u>=p?(d=this.getFoldDisplayLine(h,e,t),i=h.start.row):(d=this.getLine(e).substring(0,t),i=e);if(this.$useWrapMode){var v=this.$wrapData[i],m=0;while(d.length>=v[m])r++,m++;d=d.substring(v[m-1]||0,d.length)}return{row:r,column:this.$getStringScreenWidth(d)[0]}},this.documentToScreenColumn=function(e,t){return this.documentToScreenPosition(e,t).column},this.documentToScreenRow=function(e,t){return this.documentToScreenPosition(e,t).row},this.getScreenLength=function(){var e=0,t=null;if(!this.$useWrapMode){e=this.getLength();var n=this.$foldData;for(var r=0;ro&&(s=t.end.row+1,t=this.$foldData[r++],o=t?t.start.row:Infinity)}return e}}).call(d.prototype),e("./edit_session/folding").Folding.call(d.prototype),e("./edit_session/bracket_match").BracketMatch.call(d.prototype),t.EditSession=d}),define("ace/config",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/lib/net","ace/lib/event_emitter"],function(e,t,n){"no use strict";function f(e){return e.replace(/-(.)/g,function(e,t){return t.toUpperCase()})}var r=e("./lib/lang"),i=e("./lib/oop"),s=e("./lib/net"),o=e("./lib/event_emitter").EventEmitter,u=function(){return this}(),a={packaged:!1,workerPath:null,modePath:null,themePath:null,basePath:"",suffix:".js",$moduleUrls:{}};t.get=function(e){if(!a.hasOwnProperty(e))throw new Error("Unknown config key: "+e);return a[e]},t.set=function(e,t){if(!a.hasOwnProperty(e))throw new Error("Unknown config key: "+e);a[e]=t},t.all=function(){return r.copyObject(a)},i.implement(t,o),t.moduleUrl=function(e,t){if(a.$moduleUrls[e])return a.$moduleUrls[e];var n=e.split("/");t=t||n[n.length-2]||"";var r=n[n.length-1].replace(t,"").replace(/(^[\-_])|([\-_]$)/,"");!r&&n.length>1&&(r=n[n.length-2]);var i=a[t+"Path"];return i==null&&(i=a.basePath),i&&i.slice(-1)!="/"&&(i+="/"),i+t+"-"+r+this.get("suffix")},t.setModuleUrl=function(e,t){return a.$moduleUrls[e]=t},t.loadModule=function(n,r){var i,o;Array.isArray(n)&&(o=n[0],n=n[1]);try{i=e(n)}catch(u){}if(i)return r(i);var a=function(){e([n],function(e){t._emit("load.module",{name:n,module:e}),r(e)})};if(!t.get("packaged"))return a();s.loadScript(t.moduleUrl(n,o),a)},t.init=function(){a.packaged=e.packaged||n.packaged||u.define&&define.packaged;if(!u.document)return"";var r={},i="",s=document.getElementsByTagName("script");for(var o=0;ot.row||e.row==t.row&&e.column>t.column},this.getRange=function(){var e=this.anchor,t=this.lead;return this.isEmpty()?o.fromPoints(t,t):this.isBackwards()?o.fromPoints(t,e):o.fromPoints(e,t)},this.clearSelection=function(){this.$isEmpty||(this.$isEmpty=!0,this._emit("changeSelection"))},this.selectAll=function(){var e=this.doc.getLength()-1;this.setSelectionAnchor(0,0),this.moveCursorTo(e,this.doc.getLine(e).length)},this.setRange=this.setSelectionRange=function(e,t){t?(this.setSelectionAnchor(e.end.row,e.end.column),this.selectTo(e.start.row,e.start.column)):(this.setSelectionAnchor(e.start.row,e.start.column),this.selectTo(e.end.row,e.end.column)),this.$desiredColumn=null},this.$moveSelection=function(e){var t=this.lead;this.$isEmpty&&this.setSelectionAnchor(t.row,t.column),e.call(this)},this.selectTo=function(e,t){this.$moveSelection(function(){this.moveCursorTo(e,t)})},this.selectToPosition=function(e){this.$moveSelection(function(){this.moveCursorToPosition(e)})},this.selectUp=function(){this.$moveSelection(this.moveCursorUp)},this.selectDown=function(){this.$moveSelection(this.moveCursorDown)},this.selectRight=function(){this.$moveSelection(this.moveCursorRight)},this.selectLeft=function(){this.$moveSelection(this.moveCursorLeft)},this.selectLineStart=function(){this.$moveSelection(this.moveCursorLineStart)},this.selectLineEnd=function(){this.$moveSelection(this.moveCursorLineEnd)},this.selectFileEnd=function(){this.$moveSelection(this.moveCursorFileEnd)},this.selectFileStart=function(){this.$moveSelection(this.moveCursorFileStart)},this.selectWordRight=function(){this.$moveSelection(this.moveCursorWordRight)},this.selectWordLeft=function(){this.$moveSelection(this.moveCursorWordLeft)},this.getWordRange=function(e,t){if(typeof t=="undefined"){var n=e||this.lead;e=n.row,t=n.column}return this.session.getWordRange(e,t)},this.selectWord=function(){this.setSelectionRange(this.getWordRange())},this.selectAWord=function(){var e=this.getCursor(),t=this.session.getAWordRange(e.row,e.column);this.setSelectionRange(t)},this.getLineRange=function(e,t){var n=typeof e=="number"?e:this.lead.row,r,i=this.session.getFoldLine(n);return i?(n=i.start.row,r=i.end.row):r=n,t?new o(n,0,r,this.session.getLine(r).length):new o(n,0,r+1,0)},this.selectLine=function(){this.setSelectionRange(this.getLineRange())},this.moveCursorUp=function(){this.moveCursorBy(-1,0)},this.moveCursorDown=function(){this.moveCursorBy(1,0)},this.moveCursorLeft=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,-1))this.moveCursorTo(t.start.row,t.start.column);else if(e.column==0)e.row>0&&this.moveCursorTo(e.row-1,this.doc.getLine(e.row-1).length);else{var n=this.session.getTabSize();this.session.isTabStop(e)&&this.doc.getLine(e.row).slice(e.column-n,e.column).split(" ").length-1==n?this.moveCursorBy(0,-n):this.moveCursorBy(0,-1)}},this.moveCursorRight=function(){var e=this.lead.getPosition(),t;if(t=this.session.getFoldAt(e.row,e.column,1))this.moveCursorTo(t.end.row,t.end.column);else if(this.lead.column==this.doc.getLine(this.lead.row).length)this.lead.row0&&(t.column=r)}}this.moveCursorTo(t.row,t.column)},this.moveCursorFileEnd=function(){var e=this.doc.getLength()-1,t=this.doc.getLine(e).length;this.moveCursorTo(e,t)},this.moveCursorFileStart=function(){this.moveCursorTo(0,0)},this.moveCursorLongWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i;this.session.nonTokenRe.lastIndex=0,this.session.tokenRe.lastIndex=0;var s=this.session.getFoldAt(e,t,1);if(s){this.moveCursorTo(s.end.row,s.end.column);return}if(i=this.session.nonTokenRe.exec(r))t+=this.session.nonTokenRe.lastIndex,this.session.nonTokenRe.lastIndex=0,r=n.substring(t);if(t>=n.length){this.moveCursorTo(e,n.length),this.moveCursorRight(),e0&&this.moveCursorWordLeft();return}if(o=this.session.tokenRe.exec(s))t-=this.session.tokenRe.lastIndex,this.session.tokenRe.lastIndex=0;this.moveCursorTo(e,t)},this.$shortWordEndIndex=function(e){var t,n=0,r,i=/\s/,s=this.session.tokenRe;s.lastIndex=0;if(t=this.session.tokenRe.exec(e))n=this.session.tokenRe.lastIndex;else{while((r=e[n])&&i.test(r))n++;if(n<=1){s.lastIndex=0;while((r=e[n])&&!s.test(r)){s.lastIndex=0,n++;if(i.test(r)){if(n>2){n--;break}while((r=e[n])&&i.test(r))n++;if(n>2)break}}}}return s.lastIndex=0,n},this.moveCursorShortWordRight=function(){var e=this.lead.row,t=this.lead.column,n=this.doc.getLine(e),r=n.substring(t),i=this.session.getFoldAt(e,t,1);if(i)return this.moveCursorTo(i.end.row,i.end.column);if(t==n.length){var s=this.doc.getLength();do e++,r=this.doc.getLine(e);while(e0&&/^\s*$/.test(r));t=r.length,/\s+$/.test(r)||(r="")}var s=i.stringReverse(r),o=this.$shortWordEndIndex(s);return this.moveCursorTo(e,t-o)},this.moveCursorWordRight=function(){this.session.$selectLongWords?this.moveCursorLongWordRight():this.moveCursorShortWordRight()},this.moveCursorWordLeft=function(){this.session.$selectLongWords?this.moveCursorLongWordLeft():this.moveCursorShortWordLeft()},this.moveCursorBy=function(e,t){var n=this.session.documentToScreenPosition(this.lead.row,this.lead.column);t===0&&(this.$desiredColumn?n.column=this.$desiredColumn:this.$desiredColumn=n.column);var r=this.session.screenToDocumentPosition(n.row+e,n.column);this.moveCursorTo(r.row,r.column+t,t===0)},this.moveCursorToPosition=function(e){this.moveCursorTo(e.row,e.column)},this.moveCursorTo=function(e,t,n){var r=this.session.getFoldAt(e,t,1);r&&(e=r.start.row,t=r.start.column),this.$keepDesiredColumnOnChange=!0,this.lead.setPosition(e,t),this.$keepDesiredColumnOnChange=!1,n||(this.$desiredColumn=null)},this.moveCursorToScreen=function(e,t,n){var r=this.session.screenToDocumentPosition(e,t);this.moveCursorTo(r.row,r.column,n)},this.detach=function(){this.lead.detach(),this.anchor.detach(),this.session=this.doc=null},this.fromOrientedRange=function(e){this.setSelectionRange(e,e.cursor==e.start),this.$desiredColumn=e.desiredColumn||this.$desiredColumn},this.toOrientedRange=function(e){var t=this.getRange();return e?(e.start.column=t.start.column,e.start.row=t.start.row,e.end.column=t.end.column,e.end.row=t.end.row):e=t,e.cursor=this.isBackwards()?e.start:e.end,e.desiredColumn=this.$desiredColumn,e}}).call(u.prototype),t.Selection=u}),define("ace/range",["require","exports","module"],function(e,t,n){var r=function(e,t,n,r){this.start={row:e,column:t},this.end={row:n,column:r}};(function(){this.isEqual=function(e){return this.start.row==e.start.row&&this.end.row==e.end.row&&this.start.column==e.start.column&&this.end.column==e.end.column},this.toString=function(){return"Range: ["+this.start.row+"/"+this.start.column+"] -> ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?tthis.end.column?1:0:ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};if(this.start.row>t)var i={row:t+1,column:0};if(this.start.row1&&(/\\\d/.test(a.regex)?f=a.regex.replace(/\\([0-9]+)/g,function(e,t){return"\\"+(parseInt(t,10)+s+1)}):(l=1,f=this.removeCapturingGroups(a.regex)),a.splitRegex||(a.splitRegex=this.createSplitterRegexp(a.regex,t))),o[s]=u,s+=l,i.push(f)}this.regExps[n]=new RegExp("("+i.join(")|(")+")|($)",t)}};(function(){this.$arrayTokens=function(e){if(!e)return[];var t=e.split(this.splitRegex),n=[],r=this.tokenArray;if(r.length!=t.length-2)return window.console&&console.error(r.length,t.length-2,e,this.splitRegex),[{type:"error.invalid",value:e}];for(var i=0;if){var v=e.substring(f,d-p.length);l.type==c?l.value+=v:(l.type&&a.push(l),l={type:c,value:v})}for(var m=0;m=t&&(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length),e},this.insert=function(e,t){if(!t||t.length===0)return e;e=this.$clipPosition(e),this.getLength()<=1&&this.$detectNewLine(t);var n=this.$split(t),r=n.splice(0,1)[0],i=n.length==0?null:n.splice(n.length-1,1)[0];return e=this.insertInLine(e,r),i!==null&&(e=this.insertNewLine(e),e=this.insertLines(e.row,n),e=this.insertInLine(e,i||"")),e},this.insertLines=function(e,t){if(t.length==0)return{row:e,column:0};if(t.length>65535){var n=this.insertLines(e,t.slice(65535));t=t.slice(0,65535)}var r=[e,0];r.push.apply(r,t),this.$lines.splice.apply(this.$lines,r);var i=new s(e,0,e+t.length,0),o={action:"insertLines",range:i,lines:t};return this._emit("change",{data:o}),n||i.end},this.insertNewLine=function(e){e=this.$clipPosition(e);var t=this.$lines[e.row]||"";this.$lines[e.row]=t.substring(0,e.column),this.$lines.splice(e.row+1,0,t.substring(e.column,t.length));var n={row:e.row+1,column:0},r={action:"insertText",range:s.fromPoints(e,n),text:this.getNewLineCharacter()};return this._emit("change",{data:r}),n},this.insertInLine=function(e,t){if(t.length==0)return e;var n=this.$lines[e.row]||"";this.$lines[e.row]=n.substring(0,e.column)+t+n.substring(e.column);var r={row:e.row,column:e.column+t.length},i={action:"insertText",range:s.fromPoints(e,r),text:t};return this._emit("change",{data:i}),r},this.remove=function(e){e.start=this.$clipPosition(e.start),e.end=this.$clipPosition(e.end);if(e.isEmpty())return e.start;var t=e.start.row,n=e.end.row;if(e.isMultiLine()){var r=e.start.column==0?t:t+1,i=n-1;e.end.column>0&&this.removeInLine(n,0,e.end.column),i>=r&&this.removeLines(r,i),r!=t&&(this.removeInLine(t,e.start.column,this.getLine(t).length),this.removeNewLine(e.start.row))}else this.removeInLine(t,e.start.column,e.end.column);return e.start},this.removeInLine=function(e,t,n){if(t==n)return;var r=new s(e,t,e,n),i=this.getLine(e),o=i.substring(t,n),u=i.substring(0,t)+i.substring(n,i.length);this.$lines.splice(e,1,u);var a={action:"removeText",range:r,text:o};return this._emit("change",{data:a}),r.start},this.removeLines=function(e,t){var n=new s(e,0,t+1,0),r=this.$lines.splice(e,t-e+1),i={action:"removeLines",range:n,nl:this.getNewLineCharacter(),lines:r};return this._emit("change",{data:i}),r},this.removeNewLine=function(e){var t=this.getLine(e),n=this.getLine(e+1),r=new s(e,t.length,e+1,0),i=t+n;this.$lines.splice(e,2,i);var o={action:"removeText",range:r,text:this.getNewLineCharacter()};this._emit("change",{data:o})},this.replace=function(e,t){if(t.length==0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);if(t)var n=this.insert(e.start,t);else n=e.start;return n},this.applyDeltas=function(e){for(var t=0;t=0;t--){var n=e[t],r=s.fromPoints(n.range.start,n.range.end);n.action=="insertLines"?this.removeLines(r.start.row,r.end.row-1):n.action=="insertText"?this.remove(r):n.action=="removeLines"?this.insertLines(r.start.row,n.lines):n.action=="removeText"&&this.insert(r.start,n.text)}},this.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;ithis.row)return;if(n.start.row==this.row&&n.start.column>this.column)return;var r=this.row,i=this.column;t.action==="insertText"?n.start.row===r&&n.start.column<=i?n.start.row===n.end.row?i+=n.end.column-n.start.column:(i-=n.start.column,r+=n.end.row-n.start.row):n.start.row!==n.end.row&&n.start.row=i?i=n.start.column:i=Math.max(0,i-(n.end.column-n.start.column)):n.start.row!==n.end.row&&n.start.row=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define("ace/background_tokenizer",["require","exports","module","ace/lib/oop","ace/lib/event_emitter"],function(e,t,n){var r=e("./lib/oop"),i=e("./lib/event_emitter").EventEmitter,s=5e3,o=function(e,t){this.running=!1,this.lines=[],this.states=[],this.currentLine=0,this.tokenizer=e;var n=this;this.$worker=function(){if(!n.running)return;var e=new Date,t=n.currentLine,r=n.doc,i=0,s=r.getLength();while(n.currentLine20){n.fireUpdateEvent(t,n.currentLine-1),n.running=setTimeout(n.$worker,20);return}}n.running=!1,n.fireUpdateEvent(t,s-1)}};(function(){r.implement(this,i),this.setTokenizer=function(e){this.tokenizer=e,this.lines=[],this.states=[],this.start(0)},this.setDocument=function(e){this.doc=e,this.lines=[],this.states=[],this.stop()},this.fireUpdateEvent=function(e,t){var n={first:e,last:t};this._emit("update",{data:n})},this.start=function(e){this.currentLine=Math.min(e||0,this.currentLine,this.doc.getLength()),this.lines.splice(this.currentLine,this.lines.length),this.states.splice(this.currentLine,this.states.length),this.stop(),this.running=setTimeout(this.$worker,700)},this.$updateOnChange=function(e){var t=e.range,n=t.start.row,r=t.end.row-n;if(r===0)this.lines[n]=null;else if(e.action=="removeText"||e.action=="removeLines")this.lines.splice(n,r+1,null),this.states.splice(n,r+1,null);else{var i=Array(r+1);i.unshift(n,1),this.lines.splice.apply(this.lines,i),this.states.splice.apply(this.states,i)}this.currentLine=Math.min(n,this.currentLine,this.doc.getLength()),this.stop(),this.running=setTimeout(this.$worker,700)},this.stop=function(){this.running&&clearTimeout(this.running),this.running=!1},this.getTokens=function(e){return this.lines[e]||this.$tokenizeRow(e)},this.getState=function(e){return this.currentLine==e&&this.$tokenizeRow(e),this.states[e]||"start"},this.$tokenizeRow=function(e){var t=this.doc.getLine(e),n=this.states[e-1];if(t.length>s){var r={value:t.substr(s),type:"text"};t=t.slice(0,s)}var i=this.tokenizer.getLineTokens(t,n);return r&&(i.tokens.push(r),i.state="start"),this.states[e]+""!=i.state+""?(this.states[e]=i.state,this.lines[e+1]=null,this.currentLine>e+1&&(this.currentLine=e+1)):this.currentLine==e&&(this.currentLine=e+1),this.lines[e]=i.tokens}}).call(o.prototype),t.BackgroundTokenizer=o}),define("ace/search_highlight",["require","exports","module","ace/lib/lang","ace/lib/oop","ace/range"],function(e,t,n){var r=e("./lib/lang"),i=e("./lib/oop"),s=e("./range").Range,o=function(e,t,n){this.setRegexp(e),this.clazz=t,this.type=n||"text"};(function(){this.MAX_RANGES=500,this.setRegexp=function(e){if(this.regExp+""==e+"")return;this.regExp=e,this.cache=[]},this.update=function(e,t,n,i){if(!this.regExp)return;var o=i.firstRow,u=i.lastRow;for(var a=o;a<=u;a++){var f=this.cache[a];f==null&&(f=r.getMatchOffsets(n.getLine(a),this.regExp),f.length>this.MAX_RANGES&&(f=f.slice(0,this.MAX_RANGES)),f=f.map(function(e){return new s(a,e.offset,a,e.offset+e.length)}),this.cache[a]=f.length?f:"");for(var l=f.length;l--;)t.drawSingleLineMarker(e,f[l].toScreenRange(n),this.clazz,i,null,this.type)}}}).call(o.prototype),t.SearchHighlight=o}),define("ace/edit_session/folding",["require","exports","module","ace/range","ace/edit_session/fold_line","ace/edit_session/fold","ace/token_iterator"],function(e,t,n){function u(){this.getFoldAt=function(e,t,n){var r=this.getFoldLine(e);if(!r)return null;var i=r.folds;for(var s=0;s=e)return i;if(i.end.row>e)return null}return null},this.getNextFoldLine=function(e,t){var n=this.$foldData,r=0;t&&(r=n.indexOf(t)),r==-1&&(r=0);for(r;r=e)return i}return null},this.getFoldedRowCount=function(e,t){var n=this.$foldData,r=t-e+1;for(var i=0;i=t){u=e?r-=t-u:r=0);break}o>=e&&(u>=e?r-=o-u:r-=o-e+1)}return r},this.$addFoldLine=function(e){return this.$foldData.push(e),this.$foldData.sort(function(e,t){return e.start.row-t.start.row}),e},this.addFold=function(e,t){var n=this.$foldData,r=!1,o;e instanceof s?o=e:o=new s(t,e),this.$clipRangeToDocument(o.range);var u=o.start.row,a=o.start.column,f=o.end.row,l=o.end.column;if(u==f&&l-a<2)throw"The range has to be at least 2 characters width";var c=this.getFoldAt(u,a,1),h=this.getFoldAt(f,l,-1);if(c&&h==c)return c.addSubFold(o);if(c&&!c.range.isStart(u,a)||h&&!h.range.isEnd(f,l))throw"A fold can't intersect already existing fold"+o.range+c.range;var p=this.getFoldsInRange(o.range);p.length>0&&(this.removeFolds(p),o.subFolds=p);for(var d=0;dthis.endRow)throw"Can't add a fold to this FoldLine as it has no connection";this.folds.push(e),this.folds.sort(function(e,t){return-e.range.compareEnd(t.start.row,t.start.column)}),this.range.compareEnd(e.start.row,e.start.column)>0?(this.end.row=e.end.row,this.end.column=e.end.column):this.range.compareStart(e.end.row,e.end.column)<0&&(this.start.row=e.start.row,this.start.column=e.start.column)}else if(e.start.row==this.end.row)this.folds.push(e),this.end.row=e.end.row,this.end.column=e.end.column;else{if(e.end.row!=this.start.row)throw"Trying to add fold to FoldRow that doesn't have a matching row";this.folds.unshift(e),this.start.row=e.start.row,this.start.column=e.start.column}e.foldLine=this},this.containsRow=function(e){return e>=this.start.row&&e<=this.end.row},this.walk=function(e,t,n){var r=0,i=this.folds,s,o,u,a=!0;t==null&&(t=this.end.row,n=this.end.column);for(var f=0;f=this.$rowTokens.length){this.$row+=1;if(this.$row>=e)return this.$row=e-1,null;this.$rowTokens=this.$session.getTokens(this.$row),this.$tokenIndex=0}return this.$rowTokens[this.$tokenIndex]},this.getCurrentToken=function(){return this.$rowTokens[this.$tokenIndex]},this.getCurrentTokenRow=function(){return this.$row},this.getCurrentTokenColumn=function(){var e=this.$rowTokens,t=this.$tokenIndex,n=e[t].start;if(n!==undefined)return n;n=0;while(t>0)t-=1,n+=e[t].value.length;return n}}).call(r.prototype),t.TokenIterator=r}),define("ace/edit_session/bracket_match",["require","exports","module","ace/token_iterator","ace/range"],function(e,t,n){function s(){this.findMatchingBracket=function(e,t){if(e.column==0)return null;var n=t||this.getLine(e.row).charAt(e.column-1);if(n=="")return null;var r=n.match(/([\(\[\{])|([\)\]\}])/);return r?r[1]?this.$findClosingBracket(r[1],e):this.$findOpeningBracket(r[2],e):null},this.getBracketRange=function(e){var t=this.getLine(e.row),n=!0,r,s=t.charAt(e.column-1),o=s&&s.match(/([\(\[\{])|([\)\]\}])/);o||(s=t.charAt(e.column),e={row:e.row,column:e.column+1},o=s&&s.match(/([\(\[\{])|([\)\]\}])/),n=!1);if(!o)return null;if(o[1]){var u=this.$findClosingBracket(o[1],e);if(!u)return null;r=i.fromPoints(e,u),n||(r.end.column++,r.start.column--),r.cursor=r.end}else{var u=this.$findOpeningBracket(o[2],e);if(!u)return null;r=i.fromPoints(u,e),n||(r.start.column++,r.end.column--),r.cursor=r.start}return r},this.$brackets={")":"(","(":")","]":"[","[":"]","{":"}","}":"{"},this.$findOpeningBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp("(\\.?"+u.type.replace(".","\\.").replace("rparen",".paren")+")+"));var a=t.column-o.getCurrentTokenColumn()-2,f=u.value;for(;;){while(a>=0){var l=f.charAt(a);if(l==i){s-=1;if(s==0)return{row:o.getCurrentTokenRow(),column:a+o.getCurrentTokenColumn()}}else l==e&&(s+=1);a-=1}do u=o.stepBackward();while(u&&!n.test(u.type));if(u==null)break;f=u.value,a=f.length-1}return null},this.$findClosingBracket=function(e,t,n){var i=this.$brackets[e],s=1,o=new r(this,t.row,t.column),u=o.getCurrentToken();u||(u=o.stepForward());if(!u)return;n||(n=new RegExp("(\\.?"+u.type.replace(".","\\.").replace("lparen",".paren")+")+"));var a=t.column-o.getCurrentTokenColumn();for(;;){var f=u.value,l=f.length;while(aw&&o[c].end.row==n.end.row)c--;return o.slice(m,c+1)}return o},this.replace=function(e,t){var n=this.$options,r=this.$assembleRegExp(n);if(n.$isMultiLine)return t;if(!r)return;var i=r.exec(e);if(!i||i[0].length!=e.length)return null;t=e.replace(r,t);if(n.preserveCase){t=t.split("");for(var s=Math.min(e.length,e.length);s--;){var o=e[s];o&&o.toLowerCase()!=o?t[s]=t[s].toUpperCase():t[s]=t[s].toLowerCase()}t=t.join("")}return t},this.$matchIterator=function(e,t){var n=this.$assembleRegExp(t);if(!n)return!1;var i=this,o,u=t.backwards;if(t.$isMultiLine)var a=n.length,f=function(t,r,i){var u=t.search(n[0]);if(u==-1)return;for(var f=1;f=0;u--)if(o(s[u],t,i))return!0};else var f=function(e,t,i){var s=r.getMatchOffsets(e,n);for(var u=0;u=o;r--)if(n(e.getLine(r),r))return;if(t.wrap==0)return;for(r=u,o=s.row;r>=o;r--)if(n(e.getLine(r),r))return}:function(n){var r=s.row,i=e.getLine(r).substr(s.column);if(n(i,r,s.column))return;for(r+=1;r<=u;r++)if(n(e.getLine(r),r))return;if(t.wrap==0)return;for(r=o,u=s.row;r<=u;r++)if(n(e.getLine(r),r))return};return{forEach:a}}}).call(o.prototype),t.Search=o}),define("ace/commands/command_manager",["require","exports","module","ace/lib/oop","ace/keyboard/hash_handler","ace/lib/event_emitter"],function(e,t,n){var r=e("../lib/oop"),i=e("../keyboard/hash_handler").HashHandler,s=e("../lib/event_emitter").EventEmitter,o=function(e,t){this.platform=e,this.commands=this.byName={},this.commmandKeyBinding={},this.addCommands(t),this.setDefaultHandler("exec",function(e){return e.command.exec(e.editor,e.args||{})})};r.inherits(o,i),function(){r.implement(this,s),this.exec=function(e,t,n){typeof e=="string"&&(e=this.commands[e]);if(!e)return!1;if(t&&t.$readOnly&&!e.readOnly)return!1;var r=this._emit("exec",{editor:t,command:e,args:n});return r===!1?!1:!0},this.toggleRecording=function(e){if(this.$inReplay)return;return e&&e._emit("changeStatus"),this.recording?(this.macro.pop(),this.removeEventListener("exec",this.$addCommandToMacro),this.macro.length||(this.macro=this.oldMacro),this.recording=!1):(this.$addCommandToMacro||(this.$addCommandToMacro=function(e){this.macro.push([e.command,e.args])}.bind(this)),this.oldMacro=this.macro,this.macro=[],this.on("exec",this.$addCommandToMacro),this.recording=!0)},this.replay=function(e){if(this.$inReplay||!this.macro)return;if(this.recording)return this.toggleRecording(e);try{this.$inReplay=!0,this.macro.forEach(function(t){typeof t=="string"?this.exec(t,e):this.exec(t[0],e,t[1])},this)}finally{this.$inReplay=!1}},this.trimMacro=function(e){return e.map(function(e){return typeof e[0]!="string"&&(e[0]=e[0].name),e[1]||(e=e[0]),e})}}.call(o.prototype),t.CommandManager=o}),define("ace/keyboard/hash_handler",["require","exports","module","ace/lib/keys"],function(e,t,n){function i(e,t){this.platform=t,this.commands={},this.commmandKeyBinding={},this.addCommands(e)}var r=e("../lib/keys");(function(){this.addCommand=function(e){this.commands[e.name]&&this.removeCommand(e),this.commands[e.name]=e,e.bindKey&&this._buildKeyHash(e)},this.removeCommand=function(e){var t=typeof e=="string"?e:e.name;e=this.commands[t],delete this.commands[t];var n=this.commmandKeyBinding;for(var r in n)for(var i in n[r])n[r][i]==e&&delete n[r][i]},this.bindKey=function(e,t){if(!e)return;if(typeof t=="function"){this.addCommand({exec:t,bindKey:e,name:e});return}var n=this.commmandKeyBinding;e.split("|").forEach(function(e){var r=this.parseKeys(e,t),i=r.hashId;(n[i]||(n[i]={}))[r.key]=t},this)},this.addCommands=function(e){e&&Object.keys(e).forEach(function(t){var n=e[t];if(typeof n=="string")return this.bindKey(n,t);typeof n=="function"&&(n={exec:n}),n.name||(n.name=t),this.addCommand(n)},this)},this.removeCommands=function(e){Object.keys(e).forEach(function(t){this.removeCommand(e[t])},this)},this.bindKeys=function(e){Object.keys(e).forEach(function(t){this.bindKey(t,e[t])},this)},this._buildKeyHash=function(e){var t=e.bindKey;if(!t)return;var n=typeof t=="string"?t:t[this.platform];this.bindKey(n,e)},this.parseKeys=function(e){var t=e.toLowerCase().split(/[\-\+]([\-\+])?/).filter(function(e){return e}),n=t.pop(),i=r[n];if(r.FUNCTION_KEYS[i])n=r.FUNCTION_KEYS[i].toLowerCase();else{if(!t.length)return{key:n,hashId:-1};if(t.length==1&&t[0]=="shift")return{key:n.toUpperCase(),hashId:-1}}var s=0;for(var o=t.length;o--;){var u=r.KEY_MODS[t[o]];if(u==null)throw"invalid modifier "+t[o]+" in "+e;s|=u}return{key:n,hashId:s}},this.findKeyCommand=function(t,n){var r=this.commmandKeyBinding;return r[t]&&r[t][n]},this.handleKeyboard=function(e,t,n,r){return{command:this.findKeyCommand(t,n)}}}).call(i.prototype),t.HashHandler=i}),define("ace/commands/default_commands",["require","exports","module","ace/lib/lang","ace/config"],function(e,t,n){function s(e,t){return{win:e,mac:t}}var r=e("../lib/lang"),i=e("../config");t.commands=[{name:"selectall",bindKey:s("Ctrl-A","Command-A"),exec:function(e){e.selectAll()},readOnly:!0},{name:"centerselection",bindKey:s(null,"Ctrl-L"),exec:function(e){e.centerSelection()},readOnly:!0},{name:"gotoline",bindKey:s("Ctrl-L","Command-L"),exec:function(e){var t=parseInt(prompt("Enter line number:"),10);isNaN(t)||e.gotoLine(t)},readOnly:!0},{name:"fold",bindKey:s("Alt-L|Ctrl-F1","Command-Alt-L|Command-F1"),exec:function(e){e.session.toggleFold(!1)},readOnly:!0},{name:"unfold",bindKey:s("Alt-Shift-L|Ctrl-Shift-F1","Command-Alt-Shift-L|Command-Shift-F1"),exec:function(e){e.session.toggleFold(!0)},readOnly:!0},{name:"foldall",bindKey:s("Alt-0","Command-Option-0"),exec:function(e){e.session.foldAll()},readOnly:!0},{name:"unfoldall",bindKey:s("Alt-Shift-0","Command-Option-Shift-0"),exec:function(e){e.session.unfold()},readOnly:!0},{name:"findnext",bindKey:s("Ctrl-K","Command-G"),exec:function(e){e.findNext()},readOnly:!0},{name:"findprevious",bindKey:s("Ctrl-Shift-K","Command-Shift-G"),exec:function(e){e.findPrevious()},readOnly:!0},{name:"find",bindKey:s("Ctrl-F","Command-F"),exec:function(e){i.loadModule("ace/ext/searchbox",function(t){t.Search(e)})},readOnly:!0},{name:"overwrite",bindKey:"Insert",exec:function(e){e.toggleOverwrite()},readOnly:!0},{name:"selecttostart",bindKey:s("Ctrl-Shift-Home","Command-Shift-Up"),exec:function(e){e.getSelection().selectFileStart()},multiSelectAction:"forEach",readOnly:!0},{name:"gotostart",bindKey:s("Ctrl-Home","Command-Home|Command-Up"),exec:function(e){e.navigateFileStart()},multiSelectAction:"forEach",readOnly:!0},{name:"selectup",bindKey:s("Shift-Up","Shift-Up"),exec:function(e){e.getSelection().selectUp()},multiSelectAction:"forEach",readOnly:!0},{name:"golineup",bindKey:s("Up","Up|Ctrl-P"),exec:function(e,t){e.navigateUp(t.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selecttoend",bindKey:s("Ctrl-Shift-End","Command-Shift-Down"),exec:function(e){e.getSelection().selectFileEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"gotoend",bindKey:s("Ctrl-End","Command-End|Command-Down"),exec:function(e){e.navigateFileEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"selectdown",bindKey:s("Shift-Down","Shift-Down"),exec:function(e){e.getSelection().selectDown()},multiSelectAction:"forEach",readOnly:!0},{name:"golinedown",bindKey:s("Down","Down|Ctrl-N"),exec:function(e,t){e.navigateDown(t.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selectwordleft",bindKey:s("Ctrl-Shift-Left","Option-Shift-Left"),exec:function(e){e.getSelection().selectWordLeft()},multiSelectAction:"forEach",readOnly:!0},{name:"gotowordleft",bindKey:s("Ctrl-Left","Option-Left"),exec:function(e){e.navigateWordLeft()},multiSelectAction:"forEach",readOnly:!0},{name:"selecttolinestart",bindKey:s("Alt-Shift-Left","Command-Shift-Left"),exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",readOnly:!0},{name:"gotolinestart",bindKey:s("Alt-Left|Home","Command-Left|Home|Ctrl-A"),exec:function(e){e.navigateLineStart()},multiSelectAction:"forEach",readOnly:!0},{name:"selectleft",bindKey:s("Shift-Left","Shift-Left"),exec:function(e){e.getSelection().selectLeft()},multiSelectAction:"forEach",readOnly:!0},{name:"gotoleft",bindKey:s("Left","Left|Ctrl-B"),exec:function(e,t){e.navigateLeft(t.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selectwordright",bindKey:s("Ctrl-Shift-Right","Option-Shift-Right"),exec:function(e){e.getSelection().selectWordRight()},multiSelectAction:"forEach",readOnly:!0},{name:"gotowordright",bindKey:s("Ctrl-Right","Option-Right"),exec:function(e){e.navigateWordRight()},multiSelectAction:"forEach",readOnly:!0},{name:"selecttolineend",bindKey:s("Alt-Shift-Right","Command-Shift-Right"),exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"gotolineend",bindKey:s("Alt-Right|End","Command-Right|End|Ctrl-E"),exec:function(e){e.navigateLineEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"selectright",bindKey:s("Shift-Right","Shift-Right"),exec:function(e){e.getSelection().selectRight()},multiSelectAction:"forEach",readOnly:!0},{name:"gotoright",bindKey:s("Right","Right|Ctrl-F"),exec:function(e,t){e.navigateRight(t.times)},multiSelectAction:"forEach",readOnly:!0},{name:"selectpagedown",bindKey:"Shift-PageDown",exec:function(e){e.selectPageDown()},readOnly:!0},{name:"pagedown",bindKey:s(null,"Option-PageDown"),exec:function(e){e.scrollPageDown()},readOnly:!0},{name:"gotopagedown",bindKey:s("PageDown","PageDown|Ctrl-V"),exec:function(e){e.gotoPageDown()},readOnly:!0},{name:"selectpageup",bindKey:"Shift-PageUp",exec:function(e){e.selectPageUp()},readOnly:!0},{name:"pageup",bindKey:s(null,"Option-PageUp"),exec:function(e){e.scrollPageUp()},readOnly:!0},{name:"gotopageup",bindKey:"PageUp",exec:function(e){e.gotoPageUp()},readOnly:!0},{name:"scrollup",bindKey:s("Ctrl-Up",null),exec:function(e){e.renderer.scrollBy(0,-2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"scrolldown",bindKey:s("Ctrl-Down",null),exec:function(e){e.renderer.scrollBy(0,2*e.renderer.layerConfig.lineHeight)},readOnly:!0},{name:"selectlinestart",bindKey:"Shift-Home",exec:function(e){e.getSelection().selectLineStart()},multiSelectAction:"forEach",readOnly:!0},{name:"selectlineend",bindKey:"Shift-End",exec:function(e){e.getSelection().selectLineEnd()},multiSelectAction:"forEach",readOnly:!0},{name:"togglerecording",bindKey:s("Ctrl-Alt-E","Command-Option-E"),exec:function(e){e.commands.toggleRecording(e)},readOnly:!0},{name:"replaymacro",bindKey:s("Ctrl-Shift-E","Command-Shift-E"),exec:function(e){e.commands.replay(e)},readOnly:!0},{name:"jumptomatching",bindKey:s("Ctrl-P","Ctrl-Shift-P"),exec:function(e){e.jumpToMatching()},multiSelectAction:"forEach",readOnly:!0},{name:"selecttomatching",bindKey:s("Ctrl-Shift-P",null),exec:function(e){e.jumpToMatching(!0)},readOnly:!0},{name:"cut",exec:function(e){var t=e.getSelectionRange();e._emit("cut",t),e.selection.isEmpty()||(e.session.remove(t),e.clearSelection())},multiSelectAction:"forEach"},{name:"removeline",bindKey:s("Ctrl-D","Command-D"),exec:function(e){e.removeLines()},multiSelectAction:"forEach"},{name:"duplicateSelection",bindKey:s("Ctrl-Shift-D","Command-Shift-D"),exec:function(e){e.duplicateSelection()},multiSelectAction:"forEach"},{name:"sortlines",bindKey:s("Ctrl-Alt-S","Command-Alt-S"),exec:function(e){e.sortLines()},multiSelectAction:"forEach"},{name:"togglecomment",bindKey:s("Ctrl-/","Command-/"),exec:function(e){e.toggleCommentLines()},multiSelectAction:"forEach"},{name:"modifyNumberUp",bindKey:s("Ctrl-Shift-Up","Alt-Shift-Up"),exec:function(e){e.modifyNumber(1)},multiSelectAction:"forEach"},{name:"modifyNumberDown",bindKey:s("Ctrl-Shift-Down","Alt-Shift-Down"),exec:function(e){e.modifyNumber(-1)},multiSelectAction:"forEach"},{name:"replace",bindKey:s("Ctrl-H","Command-Option-F"),exec:function(e){i.loadModule("ace/ext/searchbox",function(t){t.Search(e,!0)})}},{name:"undo",bindKey:s("Ctrl-Z","Command-Z"),exec:function(e){e.undo()}},{name:"redo",bindKey:s("Ctrl-Shift-Z|Ctrl-Y","Command-Shift-Z|Command-Y"),exec:function(e){e.redo()}},{name:"copylinesup",bindKey:s("Alt-Shift-Up","Command-Option-Up"),exec:function(e){e.copyLinesUp()}},{name:"movelinesup",bindKey:s("Alt-Up","Option-Up"),exec:function(e){e.moveLinesUp()}},{name:"copylinesdown",bindKey:s("Alt-Shift-Down","Command-Option-Down"),exec:function(e){e.copyLinesDown()}},{name:"movelinesdown",bindKey:s("Alt-Down","Option-Down"),exec:function(e){e.moveLinesDown()}},{name:"del",bindKey:s("Delete","Delete|Ctrl-D"),exec:function(e){e.remove("right")},multiSelectAction:"forEach"},{name:"backspace",bindKey:s("Command-Backspace|Option-Backspace|Shift-Backspace|Backspace","Ctrl-Backspace|Command-Backspace|Shift-Backspace|Backspace|Ctrl-H"),exec:function(e){e.remove("left")},multiSelectAction:"forEach"},{name:"removetolinestart",bindKey:s("Alt-Backspace","Command-Backspace"),exec:function(e){e.removeToLineStart()},multiSelectAction:"forEach"},{name:"removetolineend",bindKey:s("Alt-Delete","Ctrl-K"),exec:function(e){e.removeToLineEnd()},multiSelectAction:"forEach"},{name:"removewordleft",bindKey:s("Ctrl-Backspace","Alt-Backspace|Ctrl-Alt-Backspace"),exec:function(e){e.removeWordLeft()},multiSelectAction:"forEach"},{name:"removewordright",bindKey:s("Ctrl-Delete","Alt-Delete"),exec:function(e){e.removeWordRight()},multiSelectAction:"forEach"},{name:"outdent",bindKey:s("Shift-Tab","Shift-Tab"),exec:function(e){e.blockOutdent()},multiSelectAction:"forEach"},{name:"indent",bindKey:s("Tab","Tab"),exec:function(e){e.indent()},multiSelectAction:"forEach"},{name:"blockoutdent",bindKey:s("Ctrl-[","Ctrl-["),exec:function(e){e.blockOutdent()},multiSelectAction:"forEach"},{name:"blockindent",bindKey:s("Ctrl-]","Ctrl-]"),exec:function(e){e.blockIndent()},multiSelectAction:"forEach"},{name:"insertstring",exec:function(e,t){e.insert(t)},multiSelectAction:"forEach"},{name:"inserttext",exec:function(e,t){e.insert(r.stringRepeat(t.text||"",t.times||1))},multiSelectAction:"forEach"},{name:"splitline",bindKey:s(null,"Ctrl-O"),exec:function(e){e.splitLine()},multiSelectAction:"forEach"},{name:"transposeletters",bindKey:s("Ctrl-T","Ctrl-T"),exec:function(e){e.transposeLetters()},multiSelectAction:function(e){e.transposeSelections(1)}},{name:"touppercase",bindKey:s("Ctrl-U","Ctrl-U"),exec:function(e){e.toUpperCase()},multiSelectAction:"forEach"},{name:"tolowercase",bindKey:s("Ctrl-Shift-U","Ctrl-Shift-U"),exec:function(e){e.toLowerCase()},multiSelectAction:"forEach"}]}),define("ace/undomanager",["require","exports","module"],function(e,t,n){var r=function(){this.reset()};(function(){this.execute=function(e){var t=e.args[0];this.$doc=e.args[1],this.$undoStack.push(t),this.$redoStack=[]},this.undo=function(e){var t=this.$undoStack.pop(),n=null;return t&&(n=this.$doc.undoChanges(t,e),this.$redoStack.push(t)),n},this.redo=function(e){var t=this.$redoStack.pop(),n=null;return t&&(n=this.$doc.redoChanges(t,e),this.$undoStack.push(t)),n},this.reset=function(){this.$undoStack=[],this.$redoStack=[]},this.hasUndo=function(){return this.$undoStack.length>0},this.hasRedo=function(){return this.$redoStack.length>0}}).call(r.prototype),t.UndoManager=r}),define("ace/virtual_renderer",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/useragent","ace/config","ace/lib/net","ace/layer/gutter","ace/layer/marker","ace/layer/text","ace/layer/cursor","ace/scrollbar","ace/renderloop","ace/lib/event_emitter"],function(e,t,n){var r=e("./lib/oop"),i=e("./lib/dom"),s=e("./lib/event"),o=e("./lib/useragent"),u=e("./config"),a=e("./lib/net"),f=e("./layer/gutter").Gutter,l=e("./layer/marker").Marker,c=e("./layer/text").Text,h=e("./layer/cursor").Cursor,p=e("./scrollbar").ScrollBar,d=e("./renderloop").RenderLoop,v=e("./lib/event_emitter").EventEmitter,m=".ace_editor {position: relative;overflow: hidden;font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', 'Consolas', 'source-code-pro', monospace;font-size: 12px;line-height: normal;}.ace_scroller {position: absolute;overflow: hidden;top: 0;bottom: 0;}.ace_content {position: absolute;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;cursor: text;}.ace_gutter {position: absolute;overflow : hidden;width: auto;top: 0;bottom: 0;left: 0;cursor: default;z-index: 4;}.ace_gutter-active-line {position: absolute;left: 0;right: 0;}.ace_scroller.ace_scroll-left {box-shadow: 17px 0 16px -16px rgba(0, 0, 0, 0.4) inset;}.ace_gutter-cell {padding-left: 19px;padding-right: 6px;background-repeat: no-repeat;}.ace_gutter-cell.ace_error {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM2OEZDQTQ4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM2OEZDQTU4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzY4RkNBMjhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzY4RkNBMzhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkgXxbAAAAJbSURBVHjapFNNaBNBFH4zs5vdZLP5sQmNpT82QY209heh1ioWisaDRcSKF0WKJ0GQnrzrxasHsR6EnlrwD0TagxJabaVEpFYxLWlLSS822tr87m66ccfd2GKyVhA6MMybgfe97/vmPUQphd0sZjto9XIn9OOsvlu2nkqRzVU+6vvlzPf8W6bk8dxQ0NPbxAALgCgg2JkaQuhzQau/El0zbmUA7U0Es8v2CiYmKQJHGO1QICCLoqilMhkmurDAyapKgqItezi/USRdJqEYY4D5jCy03ht2yMkkvL91jTTX10qzyyu2hruPRN7jgbH+EOsXcMLgYiThEgAMhABW85oqy1DXdRIdvP1AHJ2acQXvDIrVHcdQNrEKNYSVMSZGMjEzIIAwDXIo+6G/FxcGnzkC3T2oMhLjre49sBB+RRcHLqdafK6sYdE/GGBwU1VpFNj0aN8pJbe+BkZyevUrvLl6Xmm0W9IuTc0DxrDNAJd5oEvI/KRsNC3bQyNjPO9yQ1YHcfj2QvfQc/5TUhJTBc2iM0U7AWDQtc1nJHvD/cfO2s7jaGkiTEfa/Ep8coLu7zmNmh8+dc5lZDuUeFAGUNA/OY6JVaypQ0vjr7XYjUvJM37vt+j1vuTK5DgVfVUoTjVe+y3/LxMxY2GgU+CSLy4cpfsYorRXuXIOi0Vt40h67uZFTdIo6nLaZcwUJWAzwNS0tBnqqKzQDnjdG/iPyZxo46HaKUpbvYkj8qYRTZsBhge+JHhZyh0x9b95JqjVJkT084kZIPwu/mPWqPgfQ5jXh2+92Ay7HedfAgwA6KDWafb4w3cAAAAASUVORK5CYII=\");background-repeat: no-repeat;background-position: 2px center;}.ace_gutter-cell.ace_warning {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUM2OEZDQTg4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUM2OEZDQTk4RTU0MTFFMUEzM0VFRTM2RUY1M0RBMjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQzY4RkNBNjhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQzY4RkNBNzhFNTQxMUUxQTMzRUVFMzZFRjUzREEyNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pgd7PfIAAAGmSURBVHjaYvr//z8DJZiJgUIANoCRkREb9gLiSVAaQx4OQM7AAkwd7XU2/v++/rOttdYGEB9dASEvOMydGKfH8Gv/p4XTkvRBfLxeQAP+1cUhXopyvzhP7P/IoSj7g7Mw09cNKO6J1QQ0L4gICPIv/veg/8W+JdFvQNLHVsW9/nmn9zk7B+cCkDwhL7gt6knSZnx9/LuCEOcvkIAMP+cvto9nfqyZmmUAksfnBUtbM60gX/3/kgyv3/xSFOL5DZT+L8vP+Yfh5cvfPvp/xUHyQHXGyAYwgpwBjZYFT3Y1OEl/OfCH4ffv3wzc4iwMvNIsDJ+f/mH4+vIPAxsb631WW0Yln6ZpQLXdMK/DXGDflh+sIv37EivD5x//Gb7+YWT4y86sl7BCCkSD+Z++/1dkvsFRl+HnD1Rvje4F8whjMXmGj58YGf5zsDMwcnAwfPvKcml62DsQDeaDxN+/Y0qwlpEHqrdB94IRNIDUgfgfKJChGK4OikEW3gTiXUB950ASLFAF54AC94A0G9QAfOnmF9DCDzABFqS08IHYDIScdijOjQABBgC+/9awBH96jwAAAABJRU5ErkJggg==\");background-position: 2px center;}.ace_gutter-cell.ace_info {background-image: url(\"data:image/gif;base64,R0lGODlhEAAQAMQAAAAAAEFBQVJSUl5eXmRkZGtra39/f4WFhYmJiZGRkaampry8vMPDw8zMzNXV1dzc3OTk5Orq6vDw8P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABQALAAAAAAQABAAAAUuICWOZGmeaBml5XGwFCQSBGyXRSAwtqQIiRuiwIM5BoYVbEFIyGCQoeJGrVptIQA7\");background-position: 2px center;}.ace_dark .ace_gutter-cell.ace_info {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGRTk5MTVGREIxNDkxMUUxOTc5Q0FFREQyMTNGMjBFQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGRTk5MTVGRUIxNDkxMUUxOTc5Q0FFREQyMTNGMjBFQyI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkZFOTkxNUZCQjE0OTExRTE5NzlDQUVERDIxM0YyMEVDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkZFOTkxNUZDQjE0OTExRTE5NzlDQUVERDIxM0YyMEVDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+SIDkjAAAAJ1JREFUeNpi/P//PwMlgImBQkB7A6qrq/+DMC55FkIGKCoq4pVnpFkgTp069f/+/fv/r1u37r+tre1/kg0A+ptn9uzZYLaRkRHpLvjw4cNXWVlZhufPnzOcO3eOdAO0tbVPAjHDmzdvGA4fPsxIsgGSkpJmv379Ynj37h2DjIyMCMkG3LhxQ/T27dsMampqDHZ2dq/pH41DxwCAAAMAFdc68dUsFZgAAAAASUVORK5CYII=\");}.ace_scrollbar {position: absolute;overflow-x: hidden;overflow-y: scroll;right: 0;top: 0;bottom: 0;}.ace_scrollbar-inner {position: absolute;width: 1px;left: 0;}.ace_print-margin {position: absolute;height: 100%;}.ace_text-input {position: absolute;z-index: 0;width: 0.5em;height: 1em;opacity: 0;background: transparent;-moz-appearance: none;appearance: none;border: none;resize: none;outline: none;overflow: hidden;font: inherit;}.ace_text-input.ace_composition {background: #f8f8f8;color: #111;z-index: 1000;opacity: 1;border: solid lightgray 1px;margin: -1px;padding: 0 1px;}.ace_layer {z-index: 1;position: absolute;overflow: hidden;white-space: nowrap;height: 100%;width: 100%;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;/* setting pointer-events: auto; on node under the mouse, which changesduring scroll, will break mouse wheel scrolling in Safari */pointer-events: none;}.ace_gutter-layer {position: relative;width: auto;text-align: right;pointer-events: auto;}.ace_text-layer {color: black;font: inherit !important;}.ace_cjk {display: inline-block;text-align: center;}.ace_cursor-layer {z-index: 4;}.ace_cursor {z-index: 4;position: absolute;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;}.ace_hidden-cursors .ace_cursor {opacity: 0.2;}.ace_smooth-blinking .ace_cursor {-moz-transition: opacity 0.18s;-webkit-transition: opacity 0.18s;-o-transition: opacity 0.18s;-ms-transition: opacity 0.18s;transition: opacity 0.18s;}.ace_cursor[style*=\"opacity: 0\"]{-ms-filter: \"progid:DXImageTransform.Microsoft.Alpha(Opacity=0)\";}.ace_editor.ace_multiselect .ace_cursor {border-left-width: 1px;}.ace_line {white-space: nowrap;}.ace_marker-layer .ace_step {position: absolute;z-index: 3;}.ace_marker-layer .ace_selection {position: absolute;z-index: 5;}.ace_marker-layer .ace_bracket {position: absolute;z-index: 6;}.ace_marker-layer .ace_active-line {position: absolute;z-index: 2;}.ace_marker-layer .ace_selected-word {position: absolute;z-index: 4;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;}.ace_line .ace_fold {-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;display: inline-block;height: 11px;margin-top: -2px;vertical-align: middle;background-image:url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%3AIDAT8%11c%FC%FF%FF%7F%18%03%1A%60%01%F2%3F%A0%891%80%04%FF%11-%F8%17%9BJ%E2%05%B1ZD%81v%26t%E7%80%F8%A3%82h%A12%1A%20%A3%01%02%0F%01%BA%25%06%00%19%C0%0D%AEF%D5%3ES%00%00%00%00IEND%AEB%60%82\");background-repeat: no-repeat, repeat-x;background-position: center center, top left;color: transparent;border: 1px solid black;-moz-border-radius: 2px;-webkit-border-radius: 2px;border-radius: 2px;cursor: pointer;pointer-events: auto;}.ace_dark .ace_fold {}.ace_fold:hover{background-image:url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%11%00%00%00%09%08%06%00%00%00%D4%E8%C7%0C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%00%B5IDAT(%15%A5%91%3D%0E%02!%10%85ac%E1%05%D6%CE%D6%C6%CE%D2%E8%ED%CD%DE%C0%C6%D6N.%E0V%F8%3D%9Ca%891XH%C2%BE%D9y%3F%90!%E6%9C%C3%BFk%E5%011%C6-%F5%C8N%04%DF%BD%FF%89%DFt%83DN%60%3E%F3%AB%A0%DE%1A%5Dg%BE%10Q%97%1B%40%9C%A8o%10%8F%5E%828%B4%1B%60%87%F6%02%26%85%1Ch%1E%C1%2B%5Bk%FF%86%EE%B7j%09%9A%DA%9B%ACe%A3%F9%EC%DA!9%B4%D5%A6%81%86%86%98%CC%3C%5B%40%FA%81%B3%E9%CB%23%94%C16Azo%05%D4%E1%C1%95a%3B%8A'%A0%E8%CC%17%22%85%1D%BA%00%A2%FA%DC%0A%94%D1%D1%8D%8B%3A%84%17B%C7%60%1A%25Z%FC%8D%00%00%00%00IEND%AEB%60%82\"),url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%007%08%06%00%00%00%C4%DD%80C%00%00%03%1EiCCPICC%20Profile%00%00x%01%85T%DFk%D3P%14%FE%DAe%9D%B0%E1%8B%3Ag%11%09%3Eh%91ndStC%9C%B6kW%BA%CDZ%EA6%B7!H%9B%A6m%5C%9A%C6%24%ED~%B0%07%D9%8Bo%3A%C5w%F1%07%3E%F9%07%0C%D9%83o%7B%92%0D%C6%14a%F8%AC%88%22L%F6%22%B3%9E%9B4M'S%03%B9%F7%BB%DF%F9%EE9'%E7%E4%5E%A0%F9qZ%D3%14%2F%0F%14USO%C5%C2%FC%C4%E4%14%DF%F2%01%5E%1CC%2B%FChM%8B%86%16J%26G%40%0F%D3%B2y%EF%B3%F3%0E%1E%C6lt%EEo%DF%AB%FEc%D5%9A%95%0C%11%F0%1C%20%BE%945%C4%22%E1Y%A0i%5C%D4t%13%E0%D6%89%EF%9D15%C2%CDLsX%A7%04%09%1Fg8oc%81%E1%8C%8D%23%96f45%40%9A%09%C2%07%C5B%3AK%B8%408%98i%E0%F3%0D%D8%CE%81%14%E4'%26%A9%92.%8B%3C%ABER%2F%E5dE%B2%0C%F6%F0%1Fs%83%F2_%B0%A8%94%E9%9B%AD%E7%10%8Dm%9A%19N%D1%7C%8A%DE%1F9%7Dp%8C%E6%00%D5%C1%3F_%18%BDA%B8%9DpX6%E3%A35~B%CD%24%AE%11%26%BD%E7%EEti%98%EDe%9A%97Y)%12%25%1C%24%BCbT%AE3li%E6%0B%03%89%9A%E6%D3%ED%F4P%92%B0%9F4%BF43Y%F3%E3%EDP%95%04%EB1%C5%F5%F6KF%F4%BA%BD%D7%DB%91%93%07%E35%3E%A7)%D6%7F%40%FE%BD%F7%F5r%8A%E5y%92%F0%EB%B4%1E%8D%D5%F4%5B%92%3AV%DB%DB%E4%CD%A6%23%C3%C4wQ%3F%03HB%82%8E%1Cd(%E0%91B%0Ca%9Ac%C4%AA%F8L%16%19%22J%A4%D2itTy%B28%D6%3B(%93%96%ED%1CGx%C9_%0E%B8%5E%16%F5%5B%B2%B8%F6%E0%FB%9E%DD%25%D7%8E%BC%15%85%C5%B7%A3%D8Q%ED%B5%81%E9%BA%B2%13%9A%1B%7Fua%A5%A3n%E17%B9%E5%9B%1Bm%AB%0B%08Q%FE%8A%E5%B1H%5Ee%CAO%82Q%D7u6%E6%90S%97%FCu%0B%CF2%94%EE%25v%12X%0C%BA%AC%F0%5E%F8*l%0AO%85%17%C2%97%BF%D4%C8%CE%DE%AD%11%CB%80q%2C%3E%AB%9ES%CD%C6%EC%25%D2L%D2%EBd%B8%BF%8A%F5B%C6%18%F9%901CZ%9D%BE%24M%9C%8A9%F2%DAP%0B'%06w%82%EB%E6%E2%5C%2F%D7%07%9E%BB%CC%5D%E1%FA%B9%08%AD.r%23%8E%C2%17%F5E%7C!%F0%BE3%BE%3E_%B7o%88a%A7%DB%BE%D3d%EB%A31Z%EB%BB%D3%91%BA%A2%B1z%94%8F%DB'%F6%3D%8E%AA%13%19%B2%B1%BE%B1~V%08%2B%B4%A2cjJ%B3tO%00%03%25mN%97%F3%05%93%EF%11%84%0B%7C%88%AE-%89%8F%ABbW%90O%2B%0Ao%99%0C%5E%97%0CI%AFH%D9.%B0%3B%8F%ED%03%B6S%D6%5D%E6i_s9%F3*p%E9%1B%FD%C3%EB.7U%06%5E%19%C0%D1s.%17%A03u%E4%09%B0%7C%5E%2C%EB%15%DB%1F%3C%9E%B7%80%91%3B%DBc%AD%3Dma%BA%8B%3EV%AB%DBt.%5B%1E%01%BB%0F%AB%D5%9F%CF%AA%D5%DD%E7%E4%7F%0Bx%A3%FC%06%A9%23%0A%D6%C2%A1_2%00%00%00%09pHYs%00%00%0B%13%00%00%0B%13%01%00%9A%9C%18%00%00%003IDAT8%11c%FC%FF%FF%7F%3E%03%1A%60%01%F2%3F%A3%891%80%04%FFQ%26%F8w%C0%B43%A1%DB%0C%E2%8F%0A%A2%85%CAh%80%8C%06%08%3C%04%E8%96%18%00%A3S%0D%CD%CF%D8%C1%9D%00%00%00%00IEND%AEB%60%82\");background-repeat: no-repeat, repeat-x;background-position: center center, top left;}.ace_editor.ace_dragging .ace_content {cursor: move;}.ace_gutter-tooltip {background-color: #FFF;background-image: -webkit-linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));background-image: linear-gradient(to bottom, transparent, rgba(0, 0, 0, 0.1));border: 1px solid gray;border-radius: 1px;box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3);color: black;display: inline-block;max-width: 500px;padding: 4px;position: fixed;z-index: 300;-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;cursor: default;white-space: pre-line;word-wrap: break-word;line-height: normal;font-style: normal;font-weight: normal;letter-spacing: normal;}.ace_folding-enabled > .ace_gutter-cell {padding-right: 13px;}.ace_fold-widget {-moz-box-sizing: border-box;-webkit-box-sizing: border-box;box-sizing: border-box;margin: 0 -12px 0 1px;display: inline-block;width: 11px;vertical-align: top;background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAe%8A%B1%0D%000%0C%C2%F2%2CK%96%BC%D0%8F9%81%88H%E9%D0%0E%96%C0%10%92%3E%02%80%5E%82%E4%A9*-%EEsw%C8%CC%11%EE%96w%D8%DC%E9*Eh%0C%151(%00%00%00%00IEND%AEB%60%82\");background-repeat: no-repeat;background-position: center;border-radius: 3px;border: 1px solid transparent;}.ace_fold-widget.ace_end {background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%05%00%00%00%05%08%06%00%00%00%8Do%26%E5%00%00%004IDATx%DAm%C7%C1%09%000%08C%D1%8C%ECE%C8E(%8E%EC%02)%1EZJ%F1%C1'%04%07I%E1%E5%EE%CAL%F5%A2%99%99%22%E2%D6%1FU%B5%FE0%D9x%A7%26Wz5%0E%D5%00%00%00%00IEND%AEB%60%82\");}.ace_fold-widget.ace_closed {background-image: url(\"data:image/png,%89PNG%0D%0A%1A%0A%00%00%00%0DIHDR%00%00%00%03%00%00%00%06%08%06%00%00%00%06%E5%24%0C%00%00%009IDATx%DA5%CA%C1%09%000%08%03%C0%AC*(%3E%04%C1%0D%BA%B1%23%A4Uh%E0%20%81%C0%CC%F8%82%81%AA%A2%AArGfr%88%08%11%11%1C%DD%7D%E0%EE%5B%F6%F6%CB%B8%05Q%2F%E9tai%D9%00%00%00%00IEND%AEB%60%82\");}.ace_fold-widget:hover {border: 1px solid rgba(0, 0, 0, 0.3);background-color: rgba(255, 255, 255, 0.2);-moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);-webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.7);}.ace_fold-widget:active {border: 1px solid rgba(0, 0, 0, 0.4);background-color: rgba(0, 0, 0, 0.05);-moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);-webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.8);}/*** Dark version for fold widgets*/.ace_dark .ace_fold-widget {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHklEQVQIW2P4//8/AzoGEQ7oGCaLLAhWiSwB146BAQCSTPYocqT0AAAAAElFTkSuQmCC\");}.ace_dark .ace_fold-widget.ace_end {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAH0lEQVQIW2P4//8/AxQ7wNjIAjDMgC4AxjCVKBirIAAF0kz2rlhxpAAAAABJRU5ErkJggg==\");}.ace_dark .ace_fold-widget.ace_closed {background-image: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAFCAYAAACAcVaiAAAAHElEQVQIW2P4//+/AxAzgDADlOOAznHAKgPWAwARji8UIDTfQQAAAABJRU5ErkJggg==\");}.ace_dark .ace_fold-widget:hover {box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);background-color: rgba(255, 255, 255, 0.1);}.ace_dark .ace_fold-widget:active {-moz-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);-webkit-box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);box-shadow: 0 1px 1px rgba(255, 255, 255, 0.2);}.ace_fold-widget.ace_invalid {background-color: #FFB4B4;border-color: #DE5555;}.ace_fade-fold-widgets .ace_fold-widget {-moz-transition: opacity 0.4s ease 0.05s;-webkit-transition: opacity 0.4s ease 0.05s;-o-transition: opacity 0.4s ease 0.05s;-ms-transition: opacity 0.4s ease 0.05s;transition: opacity 0.4s ease 0.05s;opacity: 0;}.ace_fade-fold-widgets:hover .ace_fold-widget {-moz-transition: opacity 0.05s ease 0.05s;-webkit-transition: opacity 0.05s ease 0.05s;-o-transition: opacity 0.05s ease 0.05s;-ms-transition: opacity 0.05s ease 0.05s;transition: opacity 0.05s ease 0.05s;opacity:1;}.ace_underline {text-decoration: underline;}.ace_bold {font-weight: bold;}.ace_nobold .ace_bold {font-weight: normal;}.ace_italic {font-style: italic;}";i.importCssString(m,"ace_editor");var g=function(e,t){var n=this;this.container=e||i.createElement("div"),this.$keepTextAreaAtCursor=!o.isIE,i.addCssClass(this.container,"ace_editor"),this.setTheme(t),this.$gutter=i.createElement("div"),this.$gutter.className="ace_gutter",this.container.appendChild(this.$gutter),this.scroller=i.createElement("div"),this.scroller.className="ace_scroller",this.container.appendChild(this.scroller),this.content=i.createElement("div"),this.content.className="ace_content",this.scroller.appendChild(this.content),this.setHighlightGutterLine(!0),this.$gutterLayer=new f(this.$gutter),this.$gutterLayer.on("changeGutterWidth",this.onGutterResize.bind(this)),this.$markerBack=new l(this.content);var r=this.$textLayer=new c(this.content);this.canvas=r.element,this.$markerFront=new l(this.content),this.$cursorLayer=new h(this.content),this.$horizScroll=!1,this.$horizScrollAlwaysVisible=!1,this.$animatedScroll=!1,this.scrollBar=new p(this.container),this.scrollBar.addEventListener("scroll",function(e){n.$inScrollAnimation||n.session.setScrollTop(e.data)}),this.scrollTop=0,this.scrollLeft=0,s.addListener(this.scroller,"scroll",function(){var e=n.scroller.scrollLeft;n.scrollLeft=e,n.session.setScrollLeft(e)}),this.cursorPos={row:0,column:0},this.$textLayer.addEventListener("changeCharacterSize",function(){n.updateCharacterSize(),n.onResize(!0)}),this.$size={width:0,height:0,scrollerHeight:0,scrollerWidth:0},this.layerConfig={width:1,padding:0,firstRow:0,firstRowScreen:0,lastRow:0,lineHeight:1,characterWidth:1,minHeight:1,maxHeight:1,offset:0,height:1},this.$loop=new d(this.$renderChanges.bind(this),this.container.ownerDocument.defaultView),this.$loop.schedule(this.CHANGE_FULL),this.updateCharacterSize(),this.setPadding(4)};(function(){this.showGutter=!0,this.CHANGE_CURSOR=1,this.CHANGE_MARKER=2,this.CHANGE_GUTTER=4,this.CHANGE_SCROLL=8,this.CHANGE_LINES=16,this.CHANGE_TEXT=32,this.CHANGE_SIZE=64,this.CHANGE_MARKER_BACK=128,this.CHANGE_MARKER_FRONT=256,this.CHANGE_FULL=512,this.CHANGE_H_SCROLL=1024,r.implement(this,v),this.updateCharacterSize=function(){this.$textLayer.allowBoldFonts!=this.$allowBoldFonts&&(this.$allowBoldFonts=this.$textLayer.allowBoldFonts,this.setStyle("ace_nobold",!this.$allowBoldFonts)),this.characterWidth=this.$textLayer.getCharacterWidth(),this.lineHeight=this.$textLayer.getLineHeight(),this.$updatePrintMargin()},this.setSession=function(e){this.session=e,this.scroller.className="ace_scroller",this.$cursorLayer.setSession(e),this.$markerBack.setSession(e),this.$markerFront.setSession(e),this.$gutterLayer.setSession(e),this.$textLayer.setSession(e),this.$loop.schedule(this.CHANGE_FULL)},this.updateLines=function(e,t){t===undefined&&(t=Infinity),this.$changedLines?(this.$changedLines.firstRow>e&&(this.$changedLines.firstRow=e),this.$changedLines.lastRowthis.layerConfig.lastRow||this.$changedLines.lastRow2)return;this.resizing>1?this.resizing++:this.resizing=e?1:0,r||(r=i.getInnerHeight(this.container)),r&&(e||o.height!=r)&&(o.height=r,o.scrollerHeight=this.scroller.clientHeight,this.scrollBar.setHeight(o.scrollerHeight),this.session&&(this.session.setScrollTop(this.getScrollTop()),s|=this.CHANGE_FULL)),n||(n=i.getInnerWidth(this.container));if(n&&(e||this.resizing>1||o.width!=n)){o.width=n;var t=this.showGutter?this.$gutter.offsetWidth:0;this.scroller.style.left=t+"px",o.scrollerWidth=Math.max(0,n-t-this.scrollBar.getWidth()),this.scroller.style.right=this.scrollBar.getWidth()+"px";if(this.session.getUseWrapMode()&&this.adjustWrapLimit()||e)s|=this.CHANGE_FULL}e?this.$renderChanges(s,!0):this.$loop.schedule(s),e&&delete this.resizing},this.onGutterResize=function(){var e=this.$size.width,t=this.showGutter?this.$gutter.offsetWidth:0;this.scroller.style.left=t+"px",this.$size.scrollerWidth=Math.max(0,e-t-this.scrollBar.getWidth()),this.session.getUseWrapMode()&&this.adjustWrapLimit()&&this.$loop.schedule(this.CHANGE_FULL)},this.adjustWrapLimit=function(){var e=this.$size.scrollerWidth-this.$padding*2,t=Math.floor(e/this.characterWidth);return this.session.adjustWrapLimit(t)},this.setAnimatedScroll=function(e){this.$animatedScroll=e},this.getAnimatedScroll=function(){return this.$animatedScroll},this.setShowInvisibles=function(e){this.$textLayer.setShowInvisibles(e)&&this.$loop.schedule(this.CHANGE_TEXT)},this.getShowInvisibles=function(){return this.$textLayer.showInvisibles},this.getDisplayIndentGuides=function(){return this.$textLayer.displayIndentGuides},this.setDisplayIndentGuides=function(e){this.$textLayer.setDisplayIndentGuides(e)&&this.$loop.schedule(this.CHANGE_TEXT)},this.$showPrintMargin=!0,this.setShowPrintMargin=function(e){this.$showPrintMargin=e,this.$updatePrintMargin()},this.getShowPrintMargin=function(){return this.$showPrintMargin},this.$printMarginColumn=80,this.setPrintMarginColumn=function(e){this.$printMarginColumn=e,this.$updatePrintMargin()},this.getPrintMarginColumn=function(){return this.$printMarginColumn},this.getShowGutter=function(){return this.showGutter},this.setShowGutter=function(e){if(this.showGutter===e)return;this.$gutter.style.display=e?"block":"none",this.showGutter=e,this.onResize(!0)},this.getFadeFoldWidgets=function(){return i.hasCssClass(this.$gutter,"ace_fade-fold-widgets")},this.setFadeFoldWidgets=function(e){e?i.addCssClass(this.$gutter,"ace_fade-fold-widgets"):i.removeCssClass(this.$gutter,"ace_fade-fold-widgets")},this.$highlightGutterLine=!1,this.setHighlightGutterLine=function(e){if(this.$highlightGutterLine==e)return;this.$highlightGutterLine=e;if(!this.$gutterLineHighlight){this.$gutterLineHighlight=i.createElement("div"),this.$gutterLineHighlight.className="ace_gutter-active-line",this.$gutter.appendChild(this.$gutterLineHighlight);return}this.$gutterLineHighlight.style.display=e?"":"none",this.$cursorLayer.$pixelPos&&this.$updateGutterLineHighlight()},this.getHighlightGutterLine=function(){return this.$highlightGutterLine},this.$updateGutterLineHighlight=function(){this.$gutterLineHighlight.style.top=this.$cursorLayer.$pixelPos.top-this.layerConfig.offset+"px",this.$gutterLineHighlight.style.height=this.layerConfig.lineHeight+"px"},this.$updatePrintMargin=function(){if(!this.$showPrintMargin&&!this.$printMarginEl)return;if(!this.$printMarginEl){var e=i.createElement("div");e.className="ace_layer ace_print-margin-layer",this.$printMarginEl=i.createElement("div"),this.$printMarginEl.className="ace_print-margin",e.appendChild(this.$printMarginEl),this.content.insertBefore(e,this.content.firstChild)}var t=this.$printMarginEl.style;t.left=this.characterWidth*this.$printMarginColumn+this.$padding+"px",t.visibility=this.$showPrintMargin?"visible":"hidden"},this.getContainerElement=function(){return this.container},this.getMouseEventTarget=function(){return this.content},this.getTextAreaContainer=function(){return this.container},this.$moveTextAreaToCursor=function(){if(!this.$keepTextAreaAtCursor)return;var e=this.layerConfig,t=this.$cursorLayer.$pixelPos.top,n=this.$cursorLayer.$pixelPos.left;t-=e.offset;if(t<0||t>e.height-this.lineHeight)return;var r=this.characterWidth;if(this.$composition){var i=this.textarea.value.replace(/^\x01+/,"");r*=this.session.$getStringScreenWidth(i)[0]}n-=this.scrollLeft,n>this.$size.scrollerWidth-r&&(n=this.$size.scrollerWidth-r),n-=this.scrollBar.width,this.textarea.style.height=this.lineHeight+"px",this.textarea.style.width=r+"px",this.textarea.style.right=this.$size.scrollerWidth-n-r+"px",this.textarea.style.bottom=this.$size.height-t-this.lineHeight+"px"},this.getFirstVisibleRow=function(){return this.layerConfig.firstRow},this.getFirstFullyVisibleRow=function(){return this.layerConfig.firstRow+(this.layerConfig.offset===0?0:1)},this.getLastFullyVisibleRow=function(){var e=Math.floor((this.layerConfig.height+this.layerConfig.offset)/this.layerConfig.lineHeight);return this.layerConfig.firstRow-1+e},this.getLastVisibleRow=function(){return this.layerConfig.lastRow},this.$padding=null,this.setPadding=function(e){this.$padding=e,this.$textLayer.setPadding(e),this.$cursorLayer.setPadding(e),this.$markerFront.setPadding(e),this.$markerBack.setPadding(e),this.$loop.schedule(this.CHANGE_FULL),this.$updatePrintMargin()},this.getHScrollBarAlwaysVisible=function(){return this.$horizScrollAlwaysVisible},this.setHScrollBarAlwaysVisible=function(e){this.$horizScrollAlwaysVisible!=e&&(this.$horizScrollAlwaysVisible=e,(!this.$horizScrollAlwaysVisible||!this.$horizScroll)&&this.$loop.schedule(this.CHANGE_SCROLL))},this.$updateScrollBar=function(){this.scrollBar.setInnerHeight(this.layerConfig.maxHeight),this.scrollBar.setScrollTop(this.scrollTop)},this.$renderChanges=function(e,t){if(!t&&(!e||!this.session||!this.container.offsetWidth))return;(e&this.CHANGE_FULL||e&this.CHANGE_SIZE||e&this.CHANGE_TEXT||e&this.CHANGE_LINES||e&this.CHANGE_SCROLL)&&this.$computeLayerConfig();if(e&this.CHANGE_H_SCROLL){this.scroller.scrollLeft=this.scrollLeft;var n=this.scroller.scrollLeft;this.scrollLeft=n,this.session.setScrollLeft(n),this.scroller.className=this.scrollLeft==0?"ace_scroller":"ace_scroller ace_scroll-left"}if(e&this.CHANGE_FULL){this.$textLayer.checkForSizeChanges(),this.$updateScrollBar(),this.$textLayer.update(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig),this.$markerBack.update(this.layerConfig),this.$markerFront.update(this.layerConfig),this.$cursorLayer.update(this.layerConfig),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight();return}if(e&this.CHANGE_SCROLL){this.$updateScrollBar(),e&this.CHANGE_TEXT||e&this.CHANGE_LINES?this.$textLayer.update(this.layerConfig):this.$textLayer.scrollLines(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig),this.$markerBack.update(this.layerConfig),this.$markerFront.update(this.layerConfig),this.$cursorLayer.update(this.layerConfig),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight();return}e&this.CHANGE_TEXT?(this.$textLayer.update(this.layerConfig),this.showGutter&&this.$gutterLayer.update(this.layerConfig)):e&this.CHANGE_LINES?(this.$updateLines()||e&this.CHANGE_GUTTER&&this.showGutter)&&this.$gutterLayer.update(this.layerConfig):(e&this.CHANGE_TEXT||e&this.CHANGE_GUTTER)&&this.showGutter&&this.$gutterLayer.update(this.layerConfig),e&this.CHANGE_CURSOR&&(this.$cursorLayer.update(this.layerConfig),this.$moveTextAreaToCursor(),this.$highlightGutterLine&&this.$updateGutterLineHighlight()),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_FRONT)&&this.$markerFront.update(this.layerConfig),e&(this.CHANGE_MARKER|this.CHANGE_MARKER_BACK)&&this.$markerBack.update(this.layerConfig),e&this.CHANGE_SIZE&&this.$updateScrollBar()},this.$computeLayerConfig=function(){var e=this.session,t=this.scrollTop%this.lineHeight,n=this.$size.scrollerHeight+this.lineHeight,r=this.$getLongestLine(),i=this.$horizScrollAlwaysVisible||this.$size.scrollerWidth-r<0,s=this.$horizScroll!==i;this.$horizScroll=i,s&&(this.scroller.style.overflowX=i?"scroll":"hidden",i||this.session.setScrollLeft(0));var o=this.session.getScreenLength()*this.lineHeight;this.session.setScrollTop(Math.max(0,Math.min(this.scrollTop,o-this.$size.scrollerHeight)));var u=Math.ceil(n/this.lineHeight)-1,a=Math.max(0,Math.round((this.scrollTop-t)/this.lineHeight)),f=a+u,l,c,h=this.lineHeight;a=e.screenToDocumentRow(a,0);var p=e.getFoldLine(a);p&&(a=p.start.row),l=e.documentToScreenRow(a,0),c=e.getRowLength(a)*h,f=Math.min(e.screenToDocumentRow(f,0),e.getLength()-1),n=this.$size.scrollerHeight+e.getRowLength(f)*h+c,t=this.scrollTop-l*h,this.layerConfig={width:r,padding:this.$padding,firstRow:a,firstRowScreen:l,lastRow:f,lineHeight:h,characterWidth:this.characterWidth,minHeight:n,maxHeight:o,offset:t,height:this.$size.scrollerHeight},this.$gutterLayer.element.style.marginTop=-t+"px",this.content.style.marginTop=-t+"px",this.content.style.width=r+2*this.$padding+"px",this.content.style.height=n+"px",s&&this.onResize(!0)},this.$updateLines=function(){var e=this.$changedLines.firstRow,t=this.$changedLines.lastRow;this.$changedLines=null;var n=this.layerConfig;if(e>n.lastRow+1)return;if(ti?(t&&(i-=t*this.$size.scrollerHeight),this.session.setScrollTop(i)):this.scrollTop+this.$size.scrollerHeightr?(r0)return!0;if(t>0&&this.session.getScrollTop()+this.$size.scrollerHeight0?1:-1}},this.screenToTextCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=Math.round((e+this.scrollLeft-n.left-this.$padding)/this.characterWidth),i=Math.floor((t+this.scrollTop-n.top)/this.lineHeight);return this.session.screenToDocumentPosition(i,Math.max(r,0))},this.textToScreenCoordinates=function(e,t){var n=this.scroller.getBoundingClientRect(),r=this.session.documentToScreenPosition(e,t),i=this.$padding+Math.round(r.column*this.characterWidth),s=r.row*this.lineHeight;return{pageX:n.left+i-this.scrollLeft,pageY:n.top+s-this.scrollTop}},this.visualizeFocus=function(){i.addCssClass(this.container,"ace_focus")},this.visualizeBlur=function(){i.removeCssClass(this.container,"ace_focus")},this.showComposition=function(e){this.$composition||(this.$composition={keepTextAreaAtCursor:this.$keepTextAreaAtCursor,cssText:this.textarea.style.cssText}),this.$keepTextAreaAtCursor=!0,i.addCssClass(this.textarea,"ace_composition"),this.textarea.style.cssText="",this.$moveTextAreaToCursor()},this.setCompositionText=function(e){this.$moveTextAreaToCursor()},this.hideComposition=function(){if(!this.$composition)return;i.removeCssClass(this.textarea,"ace_composition"),this.$keepTextAreaAtCursor=this.$composition.keepTextAreaAtCursor,this.textarea.style.cssText=this.$composition.cssText,this.$composition=null},this._loadTheme=function(e,t){},this.setTheme=function(e){function r(e){i.importCssString(e.cssText,e.cssClass,t.container.ownerDocument),t.theme&&i.removeCssClass(t.container,t.theme.cssClass),t.$theme=e.cssClass,t.theme=e,i.addCssClass(t.container,e.cssClass),i.setCssClass(t.container,"ace_dark",e.isDark);var n=e.padding||4;t.$padding&&n!=t.$padding&&t.setPadding(n),t.$size&&(t.$size.width=0,t.onResize()),t._dispatchEvent("themeLoaded",{theme:e})}var t=this;this.$themeValue=e,t._dispatchEvent("themeChange",{theme:e});if(!e||typeof e=="string"){var n=e||"ace/theme/textmate";u.loadModule(["theme",n],r)}else r(e)},this.getTheme=function(){return this.$themeValue},this.setStyle=function(t,n){i.setCssClass(this.container,t,n!=0)},this.unsetStyle=function(t){i.removeCssClass(this.container,t)},this.destroy=function(){this.$textLayer.destroy(),this.$cursorLayer.destroy()}}).call(g.prototype),t.VirtualRenderer=g}),define("ace/layer/gutter",["require","exports","module","ace/lib/dom","ace/lib/oop","ace/lib/lang","ace/lib/event_emitter"],function(e,t,n){var r=e("../lib/dom"),i=e("../lib/oop"),s=e("../lib/lang"),o=e("../lib/event_emitter").EventEmitter,u=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_gutter-layer",e.appendChild(this.element),this.setShowFoldWidgets(this.$showFoldWidgets),this.gutterWidth=0,this.$annotations=[],this.$updateAnnotations=this.$updateAnnotations.bind(this)};(function(){i.implement(this,o),this.setSession=function(e){this.session&&this.session.removeEventListener("change",this.$updateAnnotations),this.session=e,e.on("change",this.$updateAnnotations)},this.addGutterDecoration=function(e,t){window.console&&console.warn&&console.warn("deprecated use session.addGutterDecoration"),this.session.addGutterDecoration(e,t)},this.removeGutterDecoration=function(e,t){window.console&&console.warn&&console.warn("deprecated use session.removeGutterDecoration"),this.session.removeGutterDecoration(e,t)},this.setAnnotations=function(e){this.$annotations=[];var t,n;for(var r=0;ru&&(i=o.end.row+1,o=this.session.getNextFoldLine(i,o),u=o?o.start.row:Infinity);if(i>s)break;var h=this.$annotations[i]||t;n.push("

",c=i+1);if(a){var p=a[i];p==null&&(p=a[i]=this.session.getFoldWidget(i)),p&&n.push("")}n.push("
"),i++}this.element=r.setInnerHtml(this.element,n.join("")),this.element.style.height=e.minHeight+"px",this.session.$useWrapMode&&(c=this.session.getLength());var d=(""+c).length*e.characterWidth,v=this.$padding||this.$computePadding();d+=v.left+v.right,d!==this.gutterWidth&&(this.gutterWidth=d,this.element.style.width=Math.ceil(this.gutterWidth)+"px",this._emit("changeGutterWidth",d))},this.$showFoldWidgets=!0,this.setShowFoldWidgets=function(e){e?r.addCssClass(this.element,"ace_folding-enabled"):r.removeCssClass(this.element,"ace_folding-enabled"),this.$showFoldWidgets=e,this.$padding=null},this.getShowFoldWidgets=function(){return this.$showFoldWidgets},this.$computePadding=function(){if(!this.element.firstChild)return{left:0,right:0};var e=r.computedStyle(this.element.firstChild);return this.$padding={},this.$padding.left=parseInt(e.paddingLeft)+1,this.$padding.right=parseInt(e.paddingRight),this.$padding},this.getRegion=function(e){var t=this.$padding||this.$computePadding(),n=this.element.getBoundingClientRect();if(e.xn.right-t.right)return"foldWidgets"}}).call(u.prototype),t.Gutter=u}),define("ace/layer/marker",["require","exports","module","ace/range","ace/lib/dom"],function(e,t,n){var r=e("../range").Range,i=e("../lib/dom"),s=function(e){this.element=i.createElement("div"),this.element.className="ace_layer ace_marker-layer",e.appendChild(this.element)};(function(){this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setMarkers=function(e){this.markers=e},this.update=function(e){var e=e||this.config;if(!e)return;this.config=e;var t=[];for(var n in this.markers){var r=this.markers[n];if(!r.range){r.update(t,this,this.session,e);continue}var s=r.range.clipRows(e.firstRow,e.lastRow);if(s.isEmpty())continue;s=s.toScreenRange(this.session);if(r.renderer){var o=this.$getTop(s.start.row,e),u=this.$padding+s.start.column*e.characterWidth;r.renderer(t,s,u,o,e)}else r.type=="fullLine"?this.drawFullLineMarker(t,s,r.clazz,e):s.isMultiLine()?r.type=="text"?this.drawTextMarker(t,s,r.clazz,e):this.drawMultiLineMarker(t,s,r.clazz,e):this.drawSingleLineMarker(t,s,r.clazz+" ace_start",e)}this.element=i.setInnerHtml(this.element,t.join(""))},this.$getTop=function(e,t){return(e-t.firstRowScreen)*t.lineHeight},this.drawTextMarker=function(e,t,n,i){var s=t.start.row,o=new r(s,t.start.column,s,this.session.getScreenLastRowColumn(s));this.drawSingleLineMarker(e,o,n+" ace_start",i,1,"text"),s=t.end.row,o=new r(s,0,s,t.end.column),this.drawSingleLineMarker(e,o,n,i,0,"text");for(s=t.start.row+1;s"),u=this.$getTop(t.end.row,r);var f=t.end.column*r.characterWidth;e.push("
"),o=(t.end.row-t.start.row-1)*r.lineHeight;if(o<0)return;u=this.$getTop(t.start.row+1,r),e.push("
")},this.drawSingleLineMarker=function(e,t,n,r,i){var s=r.lineHeight,o=(t.end.column+(i||0)-t.start.column)*r.characterWidth,u=this.$getTop(t.start.row,r),a=this.$padding+t.start.column*r.characterWidth;e.push("
")},this.drawFullLineMarker=function(e,t,n,r){var i=this.$getTop(t.start.row,r),s=r.lineHeight;t.start.row!=t.end.row&&(s+=this.$getTop(t.end.row,r)-i),e.push("
")}}).call(s.prototype),t.Marker=s}),define("ace/layer/text",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/lang","ace/lib/useragent","ace/lib/event_emitter"],function(e,t,n){var r=e("../lib/oop"),i=e("../lib/dom"),s=e("../lib/lang"),o=e("../lib/useragent"),u=e("../lib/event_emitter").EventEmitter,a=function(e){this.element=i.createElement("div"),this.element.className="ace_layer ace_text-layer",e.appendChild(this.element),this.$characterSize={width:0,height:0},this.checkForSizeChanges(),this.$pollSizeChanges()};(function(){r.implement(this,u),this.EOF_CHAR="¶",this.EOL_CHAR="¬",this.TAB_CHAR="→",this.SPACE_CHAR="·",this.$padding=0,this.setPadding=function(e){this.$padding=e,this.element.style.padding="0 "+e+"px"},this.getLineHeight=function(){return this.$characterSize.height||1},this.getCharacterWidth=function(){return this.$characterSize.width||1},this.checkForSizeChanges=function(){var e=this.$measureSizes();if(e&&(this.$characterSize.width!==e.width||this.$characterSize.height!==e.height)){this.$measureNode.style.fontWeight="bold";var t=this.$measureSizes();this.$measureNode.style.fontWeight="",this.$characterSize=e,this.allowBoldFonts=t&&t.width===e.width&&t.height===e.height,this._emit("changeCharacterSize",{data:e})}},this.$pollSizeChanges=function(){var e=this;this.$pollSizeChangesTimer=setInterval(function(){e.checkForSizeChanges()},500)},this.$fontStyles={fontFamily:1,fontSize:1,fontWeight:1,fontStyle:1,lineHeight:1},this.$measureSizes=o.isIE||o.isOldGecko?function(){var e=1e3;if(!this.$measureNode){var t=this.$measureNode=i.createElement("div"),n=t.style;n.width=n.height="auto",n.left=n.top=-e*40+"px",n.visibility="hidden",n.position="fixed",n.overflow="visible",n.whiteSpace="nowrap",t.innerHTML=s.stringRepeat("Xy",e);if(this.element.ownerDocument.body)this.element.ownerDocument.body.appendChild(t);else{var r=this.element.parentNode;while(!i.hasCssClass(r,"ace_editor"))r=r.parentNode;r.appendChild(t)}}if(!this.element.offsetWidth)return null;var n=this.$measureNode.style,o=i.computedStyle(this.element);for(var u in this.$fontStyles)n[u]=o[u];var a={height:this.$measureNode.offsetHeight,width:this.$measureNode.offsetWidth/(e*2)};return a.width==0||a.height==0?null:a}:function(){if(!this.$measureNode){var e=this.$measureNode=i.createElement("div"),t=e.style;t.width=t.height="auto",t.left=t.top="-100px",t.visibility="hidden",t.position="fixed",t.overflow="visible",t.whiteSpace="nowrap",e.innerHTML="X";var n=this.element.parentNode;while(n&&!i.hasCssClass(n,"ace_editor"))n=n.parentNode;if(!n)return this.$measureNode=null;n.appendChild(e)}var r=this.$measureNode.getBoundingClientRect(),s={height:r.height,width:r.width};return s.width==0||s.height==0?null:s},this.setSession=function(e){this.session=e,this.$computeTabString()},this.showInvisibles=!1,this.setShowInvisibles=function(e){return this.showInvisibles==e?!1:(this.showInvisibles=e,this.$computeTabString(),!0)},this.displayIndentGuides=!0,this.setDisplayIndentGuides=function(e){return this.displayIndentGuides==e?!1:(this.displayIndentGuides=e,this.$computeTabString(),!0)},this.$tabStrings=[],this.onChangeTabSize=this.$computeTabString=function(){var e=this.session.getTabSize();this.tabSize=e;var t=this.$tabStrings=[0];for(var n=1;n"+this.TAB_CHAR+s.stringRepeat(" ",n-1)+""):t.push(s.stringRepeat(" ",n));if(this.displayIndentGuides){this.$indentGuideRe=/\s\S| \t|\t |\s$/;var r="ace_indent-guide";if(this.showInvisibles){r+=" ace_invisible";var i=s.stringRepeat(this.SPACE_CHAR,this.tabSize),o=this.TAB_CHAR+s.stringRepeat(" ",this.tabSize-1)}else var i=s.stringRepeat(" ",this.tabSize),o=i;this.$tabStrings[" "]=""+i+"",this.$tabStrings[" "]=""+o+""}},this.updateLines=function(e,t,n){(this.config.lastRow!=e.lastRow||this.config.firstRow!=e.firstRow)&&this.scrollLines(e),this.config=e;var r=Math.max(t,e.firstRow),s=Math.min(n,e.lastRow),o=this.element.childNodes,u=0;for(var a=e.firstRow;al&&(a=f.end.row+1,f=this.session.getNextFoldLine(a,f),l=f?f.start.row:Infinity);if(a>s)break;var c=o[u++];if(c){var h=[];this.$renderLine(h,a,!this.$useLineGroups(),a==l?f:!1),i.setInnerHtml(c,h.join(""))}a++}},this.scrollLines=function(e){var t=this.config;this.config=e;if(!t||t.lastRow0;r--)n.removeChild(n.firstChild);if(t.lastRow>e.lastRow)for(var r=this.session.getFoldedRowCount(e.lastRow+1,t.lastRow);r>0;r--)n.removeChild(n.lastChild);if(e.firstRowt.lastRow){var i=this.$renderLinesFragment(e,t.lastRow+1,e.lastRow);n.appendChild(i)}},this.$renderLinesFragment=function(e,t,n){var r=this.element.ownerDocument.createDocumentFragment(),s=t,o=this.session.getNextFoldLine(s),u=o?o.start.row:Infinity;for(;;){s>u&&(s=o.end.row+1,o=this.session.getNextFoldLine(s,o),u=o?o.start.row:Infinity);if(s>n)break;var a=i.createElement("div"),f=[];this.$renderLine(f,s,!1,s==u?o:!1),a.innerHTML=f.join("");if(this.$useLineGroups())a.className="ace_line_group",r.appendChild(a);else{var l=a.childNodes;while(l.length)r.appendChild(l[0])}s++}return r},this.update=function(e){this.config=e;var t=[],n=e.firstRow,r=e.lastRow,s=n,o=this.session.getNextFoldLine(s),u=o?o.start.row:Infinity;for(;;){s>u&&(s=o.end.row+1,o=this.session.getNextFoldLine(s,o),u=o?o.start.row:Infinity);if(s>r)break;this.$useLineGroups()&&t.push("
"),this.$renderLine(t,s,!1,s==u?o:!1),this.$useLineGroups()&&t.push("
"),s++}this.element=i.setInnerHtml(this.element,t.join(""))},this.$textToken={text:!0,rparen:!0,lparen:!0},this.$renderToken=function(e,t,n,r){var i=this,o=/\t|&|<|( +)|([\x00-\x1f\x80-\xa0\u1680\u180E\u2000-\u200f\u2028\u2029\u202F\u205F\u3000\uFEFF])|[\u1100-\u115F\u11A3-\u11A7\u11FA-\u11FF\u2329-\u232A\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0-\u2FFB\u3000-\u303E\u3041-\u3096\u3099-\u30FF\u3105-\u312D\u3131-\u318E\u3190-\u31BA\u31C0-\u31E3\u31F0-\u321E\u3220-\u3247\u3250-\u32FE\u3300-\u4DBF\u4E00-\uA48C\uA490-\uA4C6\uA960-\uA97C\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFAFF\uFE10-\uFE19\uFE30-\uFE52\uFE54-\uFE66\uFE68-\uFE6B\uFF01-\uFF60\uFFE0-\uFFE6]/g,u=function(e,n,r,o,u){if(n)return i.showInvisibles?""+s.stringRepeat(i.SPACE_CHAR,e.length)+"":s.stringRepeat(" ",e.length);if(e=="&")return"&";if(e=="<")return"<";if(e==" "){var a=i.session.getScreenTabSize(t+o);return t+=a-1,i.$tabStrings[a]}if(e==" "){var f=i.showInvisibles?"ace_cjk ace_invisible":"ace_cjk",l=i.showInvisibles?i.SPACE_CHAR:"";return t+=1,""+l+""}return r?""+i.SPACE_CHAR+"":(t+=1,""+e+"")},a=r.replace(o,u);if(!this.$textToken[n.type]){var f="ace_"+n.type.replace(/\./g," ace_"),l="";n.type=="fold"&&(l=" style='width:"+n.value.length*this.config.characterWidth+"px;' "),e.push("",a,"")}else e.push(a);return t+r.length},this.renderIndentGuide=function(e,t){var n=t.search(this.$indentGuideRe);return n<=0?t:t[0]==" "?(n-=n%this.tabSize,e.push(s.stringRepeat(this.$tabStrings[" "],n/this.tabSize)),t.substr(n)):t[0]==" "?(e.push(s.stringRepeat(this.$tabStrings[" "],n)),t.substr(n)):t},this.$renderWrappedLine=function(e,t,n,r){var i=0,s=0,o=n[0],u=0;for(var a=0;a=o)u=this.$renderToken(e,u,f,l.substring(0,o-i)),l=l.substring(o-i),i=o,r||e.push("","
"),s++,u=0,o=n[s]||Number.MAX_VALUE;l.length!=0&&(i+=l.length,u=this.$renderToken(e,u,f,l))}}},this.$renderSimpleLine=function(e,t){var n=0,r=t[0],i=r.value;this.displayIndentGuides&&(i=this.renderIndentGuide(e,i)),i&&(n=this.$renderToken(e,n,r,i));for(var s=1;s");if(i.length){var s=this.session.getRowSplitData(t);s&&s.length?this.$renderWrappedLine(e,i,s,n):this.$renderSimpleLine(e,i)}this.showInvisibles&&(r&&(t=r.end.row),e.push("",t==this.session.getLength()-1?this.EOF_CHAR:this.EOL_CHAR,"")),n||e.push("
")},this.$getFoldLineTokens=function(e,t){function i(e,t,n){var i=0,s=0;while(s+e[i].value.lengthn-t&&(o=o.substring(0,n-t)),r.push({type:e[i].type,value:o}),s=t+o.length,i+=1}while(sn?r.push({type:e[i].type,value:o.substring(0,n-s)}):r.push(e[i]),s+=o.length,i+=1}}var n=this.session,r=[],s=n.getTokens(e);return t.walk(function(e,t,o,u,a){e!=null?r.push({type:"fold",value:e}):(a&&(s=n.getTokens(t)),s.length&&i(s,u,o))},t.end.row,this.session.getLine(t.end.row).length),r},this.$useLineGroups=function(){return this.session.getUseWrapMode()},this.destroy=function(){clearInterval(this.$pollSizeChangesTimer),this.$measureNode&&this.$measureNode.parentNode.removeChild(this.$measureNode),delete this.$measureNode}}).call(a.prototype),t.Text=a}),define("ace/layer/cursor",["require","exports","module","ace/lib/dom"],function(e,t,n){var r=e("../lib/dom"),i=function(e){this.element=r.createElement("div"),this.element.className="ace_layer ace_cursor-layer",e.appendChild(this.element),this.isVisible=!1,this.isBlinking=!0,this.blinkInterval=1e3,this.smoothBlinking=!1,this.cursors=[],this.cursor=this.addCursor(),r.addCssClass(this.element,"ace_hidden-cursors")};(function(){this.$padding=0,this.setPadding=function(e){this.$padding=e},this.setSession=function(e){this.session=e},this.setBlinking=function(e){e!=this.isBlinking&&(this.isBlinking=e,this.restartTimer())},this.setBlinkInterval=function(e){e!=this.blinkInterval&&(this.blinkInterval=e,this.restartTimer())},this.setSmoothBlinking=function(e){e!=this.smoothBlinking&&(this.smoothBlinking=e,e?r.addCssClass(this.element,"ace_smooth-blinking"):r.removeCssClass(this.element,"ace_smooth-blinking"),this.restartTimer())},this.addCursor=function(){var e=r.createElement("div");return e.className="ace_cursor",this.element.appendChild(e),this.cursors.push(e),e},this.removeCursor=function(){if(this.cursors.length>1){var e=this.cursors.pop();return e.parentNode.removeChild(e),e}},this.hideCursor=function(){this.isVisible=!1,r.addCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.showCursor=function(){this.isVisible=!0,r.removeCssClass(this.element,"ace_hidden-cursors"),this.restartTimer()},this.restartTimer=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId),this.smoothBlinking&&r.removeCssClass(this.element,"ace_smooth-blinking");for(var e=this.cursors.length;e--;)this.cursors[e].style.opacity="";if(!this.isBlinking||!this.blinkInterval||!this.isVisible)return;this.smoothBlinking&&setTimeout(function(){r.addCssClass(this.element,"ace_smooth-blinking")}.bind(this));var t=function(){this.timeoutId=setTimeout(function(){for(var e=this.cursors.length;e--;)this.cursors[e].style.opacity=0}.bind(this),.6*this.blinkInterval)}.bind(this);this.intervalId=setInterval(function(){for(var e=this.cursors.length;e--;)this.cursors[e].style.opacity="";t()}.bind(this),this.blinkInterval),t()},this.getPixelPosition=function(e,t){if(!this.config||!this.session)return{left:0,top:0};e||(e=this.session.selection.getCursor());var n=this.session.documentToScreenPosition(e),r=this.$padding+n.column*this.config.characterWidth,i=(n.row-(t?this.config.firstRowScreen:0))*this.config.lineHeight;return{left:r,top:i}},this.update=function(e){this.config=e;var t=this.session.$selectionMarkers,n=0,r=0;if(t===undefined||t.length===0)t=[{cursor:null}];for(var n=t.length;n--;){var i=this.getPixelPosition(t[n].cursor,!0);if((i.top>e.height+e.offset||i.top<-e.offset)&&n>1)continue;var s=(this.cursors[r++]||this.addCursor()).style;s.left=i.left+"px",s.top=i.top+"px",s.width=e.characterWidth+"px",s.height=e.lineHeight+"px"}while(this.cursors.length>r)this.removeCursor();var o=this.session.getOverwrite();this.$setOverwrite(o),this.$pixelPos=i,this.restartTimer()},this.$setOverwrite=function(e){e!=this.overwrite&&(this.overwrite=e,e?r.addCssClass(this.element,"ace_overwrite-cursors"):r.removeCssClass(this.element,"ace_overwrite-cursors"))},this.destroy=function(){clearInterval(this.intervalId),clearTimeout(this.timeoutId)}}).call(i.prototype),t.Cursor=i}),define("ace/scrollbar",["require","exports","module","ace/lib/oop","ace/lib/dom","ace/lib/event","ace/lib/event_emitter"],function(e,t,n){var r=e("./lib/oop"),i=e("./lib/dom"),s=e("./lib/event"),o=e("./lib/event_emitter").EventEmitter,u=function(e){this.element=i.createElement("div"),this.element.className="ace_scrollbar",this.inner=i.createElement("div"),this.inner.className="ace_scrollbar-inner",this.element.appendChild(this.inner),e.appendChild(this.element),this.width=i.scrollbarWidth(e.ownerDocument),this.element.style.width=(this.width||15)+5+"px",s.addListener(this.element,"scroll",this.onScroll.bind(this))};(function(){r.implement(this,o),this.onScroll=function(){this.skipEvent||(this.scrollTop=this.element.scrollTop,this._emit("scroll",{data:this.scrollTop})),this.skipEvent=!1},this.getWidth=function(){return this.width},this.setHeight=function(e){this.element.style.height=e+"px"},this.setInnerHeight=function(e){this.inner.style.height=e+"px"},this.setScrollTop=function(e){this.scrollTop!=e&&(this.skipEvent=!0,this.scrollTop=this.element.scrollTop=e)}}).call(u.prototype),t.ScrollBar=u}),define("ace/renderloop",["require","exports","module","ace/lib/event"],function(e,t,n){var r=e("./lib/event"),i=function(e,t){this.onRender=e,this.pending=!1,this.changes=0,this.window=t||window};(function(){this.schedule=function(e){this.changes=this.changes|e;if(!this.pending){this.pending=!0;var t=this;r.nextFrame(function(){t.pending=!1;var e;while(e=t.changes)t.changes=0,t.onRender(e)},this.window)}}}).call(i.prototype),t.RenderLoop=i}),define("ace/multi_select",["require","exports","module","ace/range_list","ace/range","ace/selection","ace/mouse/multi_select_handler","ace/lib/event","ace/lib/lang","ace/commands/multi_select_commands","ace/search","ace/edit_session","ace/editor"],function(e,t,n){function h(e,t,n){return c.$options.wrap=!0,c.$options.needle=t,c.$options.backwards=n==-1,c.find(e)}function v(e,t){return e.row==t.row&&e.column==t.column}function m(e){e.$onAddRange=e.$onAddRange.bind(e),e.$onRemoveRange=e.$onRemoveRange.bind(e),e.$onMultiSelect=e.$onMultiSelect.bind(e),e.$onSingleSelect=e.$onSingleSelect.bind(e),t.onSessionChange.call(e,e),e.on("changeSession",t.onSessionChange.bind(e)),e.on("mousedown",o),e.commands.addCommands(f.defaultCommands),g(e)}function g(e){function i(){n&&(r.style.cursor="",n=!1)}var t=e.textInput.getElement(),n=!1,r=e.renderer.content;u.addListener(t,"keydown",function(e){e.keyCode==18&&!(e.ctrlKey||e.shiftKey||e.metaKey)?n||(r.style.cursor="crosshair",n=!0):n&&(r.style.cursor="")}),u.addListener(t,"keyup",i),u.addListener(t,"blur",i)}var r=e("./range_list").RangeList,i=e("./range").Range,s=e("./selection").Selection,o=e("./mouse/multi_select_handler").onMouseDown,u=e("./lib/event"),a=e("./lib/lang"),f=e("./commands/multi_select_commands");t.commands=f.defaultCommands.concat(f.multiSelectCommands);var l=e("./search").Search,c=new l,p=e("./edit_session").EditSession;(function(){this.getSelectionMarkers=function(){return this.$selectionMarkers}}).call(p.prototype),function(){this.ranges=null,this.rangeList=null,this.addRange=function(e,t){if(!e)return;if(!this.inMultiSelectMode&&this.rangeCount==0){var n=this.toOrientedRange();if(e.intersects(n))return t||this.fromOrientedRange(e);this.rangeList.add(n),this.$onAddRange(n)}e.cursor||(e.cursor=e.end);var r=this.rangeList.add(e);return this.$onAddRange(e),r.length&&this.$onRemoveRange(r),this.rangeCount>1&&!this.inMultiSelectMode&&(this._emit("multiSelect"),this.inMultiSelectMode=!0,this.session.$undoSelect=!1,this.rangeList.attach(this.session)),t||this.fromOrientedRange(e)},this.toSingleRange=function(e){e=e||this.ranges[0];var t=this.rangeList.removeAll();t.length&&this.$onRemoveRange(t),e&&this.fromOrientedRange(e)},this.substractPoint=function(e){var t=this.rangeList.substractPoint(e);if(t)return this.$onRemoveRange(t),t[0]},this.mergeOverlappingRanges=function(){var e=this.rangeList.merge();e.length?this.$onRemoveRange(e):this.ranges[0]&&this.fromOrientedRange(this.ranges[0])},this.$onAddRange=function(e){this.rangeCount=this.rangeList.ranges.length,this.ranges.unshift(e),this._emit("addRange",{range:e})},this.$onRemoveRange=function(e){this.rangeCount=this.rangeList.ranges.length;if(this.rangeCount==1&&this.inMultiSelectMode){var t=this.rangeList.ranges.pop();e.push(t),this.rangeCount=0}for(var n=e.length;n--;){var r=this.ranges.indexOf(e[n]);this.ranges.splice(r,1)}this._emit("removeRange",{ranges:e}),this.rangeCount==0&&this.inMultiSelectMode&&(this.inMultiSelectMode=!1,this._emit("singleSelect"),this.session.$undoSelect=!0,this.rangeList.detach(this.session)),t=t||this.ranges[0],t&&!t.isEqual(this.getRange())&&this.fromOrientedRange(t)},this.$initRangeList=function(){if(this.rangeList)return;this.rangeList=new r,this.ranges=[],this.rangeCount=0},this.getAllRanges=function(){return this.rangeList.ranges.concat()},this.splitIntoLines=function(){if(this.rangeCount>1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var n=this.getRange(),r=this.isBackwards(),s=n.start.row,o=n.end.row;if(s==o){if(r)var u=n.end,a=n.start;else var u=n.start,a=n.end;this.addRange(i.fromPoints(a,a)),this.addRange(i.fromPoints(u,u));return}var f=[],l=this.getLineRange(s,!0);l.start.column=n.start.column,f.push(l);for(var c=s+1;c1){var e=this.rangeList.ranges,t=e[e.length-1],n=i.fromPoints(e[0].start,t.end);this.toSingleRange(),this.setSelectionRange(n,t.cursor==t.start)}else{var r=this.session.documentToScreenPosition(this.selectionLead),s=this.session.documentToScreenPosition(this.selectionAnchor),o=this.rectangularRangeBlock(r,s);o.forEach(this.addRange,this)}},this.rectangularRangeBlock=function(e,t,n){var r=[],s=e.column0)d--;if(d>0){var m=0;while(r[m].isEmpty())m++}for(var g=d;g>=m;g--)r[g].isEmpty()&&r.splice(g,1)}return r}}.call(s.prototype);var d=e("./editor").Editor;(function(){this.updateSelectionMarkers=function(){this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.addSelectionMarker=function(e){e.cursor||(e.cursor=e.end);var t=this.getSelectionStyle();return e.marker=this.session.addMarker(e,"ace_selection",t),this.session.$selectionMarkers.push(e),this.session.selectionMarkerCount=this.session.$selectionMarkers.length,e},this.removeSelectionMarker=function(e){if(!e.marker)return;this.session.removeMarker(e.marker);var t=this.session.$selectionMarkers.indexOf(e);t!=-1&&this.session.$selectionMarkers.splice(t,1),this.session.selectionMarkerCount=this.session.$selectionMarkers.length},this.removeSelectionMarkers=function(e){var t=this.session.$selectionMarkers;for(var n=e.length;n--;){var r=e[n];if(!r.marker)continue;this.session.removeMarker(r.marker);var i=t.indexOf(r);i!=-1&&t.splice(i,1)}this.session.selectionMarkerCount=t.length},this.$onAddRange=function(e){this.addSelectionMarker(e.range),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onRemoveRange=function(e){this.removeSelectionMarkers(e.ranges),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelect=function(e){if(this.inMultiSelectMode)return;this.inMultiSelectMode=!0,this.setStyle("ace_multiselect"),this.keyBinding.addKeyboardHandler(f.keyboardHandler),this.commands.on("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onSingleSelect=function(e){if(this.session.multiSelect.inVirtualMode)return;this.inMultiSelectMode=!1,this.unsetStyle("ace_multiselect"),this.keyBinding.removeKeyboardHandler(f.keyboardHandler),this.commands.removeEventListener("exec",this.$onMultiSelectExec),this.renderer.updateCursor(),this.renderer.updateBackMarkers()},this.$onMultiSelectExec=function(e){var t=e.command,n=e.editor;if(!n.multiSelect)return;t.multiSelectAction?t.multiSelectAction=="forEach"?n.forEachSelection(t,e.args):t.multiSelectAction=="single"?(n.exitMultiSelectMode(),t.exec(n,e.args||{})):t.multiSelectAction(n,e.args||{}):(t.exec(n,e.args||{}),n.multiSelect.addRange(n.multiSelect.toOrientedRange()),n.multiSelect.mergeOverlappingRanges()),e.preventDefault()},this.forEachSelection=function(e,t){if(this.inVirtualSelectionMode)return;var n=this.session,r=this.selection,i=r.rangeList,o=r._eventRegistry;r._eventRegistry={};var u=new s(n);this.inVirtualSelectionMode=!0;for(var a=i.ranges.length;a--;)u.fromOrientedRange(i.ranges[a]),this.selection=n.selection=u,e.exec(this,t||{}),u.toOrientedRange(i.ranges[a]);u.detach(),this.selection=n.selection=r,this.inVirtualSelectionMode=!1,r._eventRegistry=o,r.mergeOverlappingRanges(),this.onCursorChange(),this.onSelectionChange()},this.exitMultiSelectMode=function(){if(this.inVirtualSelectionMode)return;this.multiSelect.toSingleRange()},this.getCopyText=function(){var e="";if(this.inMultiSelectMode){var t=this.multiSelect.rangeList.ranges;e=[];for(var n=0;nn.length||t.length<=2||!t[1])return this.commands.exec("insertstring",this,e);for(var r=n.length;r--;){var i=n[r];i.isEmpty()||this.session.remove(i),this.session.insert(i.start,t[r])}},this.findAll=function(e,t,n){t=t||{},t.needle=e||t.needle,this.$search.set(t);var r=this.$search.findAll(this.session);if(!r.length)return 0;this.$blockScrolling+=1;var i=this.multiSelect;n||i.toSingleRange(r[0]);for(var s=r.length;s--;)i.addRange(r[s],!0);return this.$blockScrolling-=1,r.length},this.selectMoreLines=function(e,t){var n=this.selection.toOrientedRange(),r=n.cursor==n.end,s=this.session.documentToScreenPosition(n.cursor);this.selection.$desiredColumn&&(s.column=this.selection.$desiredColumn);var o=this.session.screenToDocumentPosition(s.row+e,s.column);if(!n.isEmpty())var u=this.session.documentToScreenPosition(r?n.end:n.start),a=this.session.screenToDocumentPosition(u.row+e,u.column);else var a=o;if(r){var f=i.fromPoints(o,a);f.cursor=f.start}else{var f=i.fromPoints(a,o);f.cursor=f.end}f.desiredColumn=s.column;if(!this.selection.inMultiSelectMode)this.selection.addRange(n);else if(t)var l=n.cursor;this.selection.addRange(f),l&&this.selection.substractPoint(l)},this.transposeSelections=function(e){var t=this.session,n=t.multiSelect,r=n.ranges;for(var i=r.length;i--;){var s=r[i];if(s.isEmpty()){var o=t.getWordRange(s.start.row,s.start.column);s.start.row=o.start.row,s.start.column=o.start.column,s.end.row=o.end.row,s.end.column=o.end.column}}n.mergeOverlappingRanges();var u=[];for(var i=r.length;i--;){var s=r[i];u.unshift(t.getTextRange(s))}e<0?u.unshift(u.pop()):u.push(u.shift());for(var i=r.length;i--;){var s=r[i],o=s.clone();t.replace(s,u[i]),s.start.row=o.start.row,s.start.column=o.start.column}},this.selectMore=function(e,t){var n=this.session,r=n.multiSelect,i=r.toOrientedRange();if(i.isEmpty()){var i=n.getWordRange(i.start.row,i.start.column);i.cursor=i.end,this.multiSelect.addRange(i)}var s=n.getTextRange(i),o=h(n,s,e);o&&(o.cursor=e==-1?o.start:o.end,this.multiSelect.addRange(o)),t&&this.multiSelect.substractPoint(i.cursor)},this.alignCursors=function(){var e=this.session,t=e.multiSelect,n=t.ranges;if(!n.length){var r=this.selection.getRange(),s=r.start.row,o=r.end.row,u=this.session.doc.removeLines(s,o);u=this.$reAlignText(u),this.session.doc.insertLines(s,u),r.start.column=0,r.end.column=u[u.length-1].length,this.selection.setRange(r)}else{var f=-1,l=n.filter(function(e){if(e.cursor.row==f)return!0;f=e.cursor.row});t.$onRemoveRange(l);var c=0,h=Infinity,p=n.map(function(t){var n=t.cursor,r=e.getLine(n.row),i=r.substr(n.column).search(/\S/g);return i==-1&&(i=0),n.column>c&&(c=n.column),io?e.insert(r,a.stringRepeat(" ",s-o)):e.remove(new i(r.row,r.column,r.row,r.column-s+o)),t.start.column=t.end.column=c,t.start.row=t.end.row=r.row,t.cursor=t.end}),t.fromOrientedRange(n[0]),this.renderer.updateCursor(),this.renderer.updateBackMarkers()}},this.$reAlignText=function(e){function o(e){return a.stringRepeat(" ",e)}function u(e){return e[2]?o(r)+e[2]+o(i-e[2].length+s)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function f(e){return e[2]?o(r+i-e[2].length)+e[2]+o(s," ")+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}function l(e){return e[2]?o(r)+e[2]+o(s)+e[4].replace(/^([=:])\s+/,"$1 "):e[0]}var t=!0,n=!0,r,i,s;return e.map(function(e){var o=e.match(/(\s*)(.*?)(\s*)([=:].*)/);return o?r==null?(r=o[1].length,i=o[2].length,s=o[3].length,o):(r+i+s!=o[1].length+o[2].length+o[3].length&&(n=!1),r!=o[1].length&&(t=!1),r>o[1].length&&(r=o[1].length),io[3].length&&(s=o[3].length),o):[e]}).map(t?n?f:u:l)}}).call(d.prototype),t.onSessionChange=function(e){var t=e.session;t.multiSelect||(t.$selectionMarkers=[],t.selection.$initRangeList(),t.multiSelect=t.selection),this.multiSelect=t.multiSelect;var n=e.oldSession;n&&(n.multiSelect&&n.multiSelect.editor==this&&(n.multiSelect.editor=null),t.multiSelect.removeEventListener("addRange",this.$onAddRange),t.multiSelect.removeEventListener("removeRange",this.$onRemoveRange),t.multiSelect.removeEventListener("multiSelect",this.$onMultiSelect),t.multiSelect.removeEventListener("singleSelect",this.$onSingleSelect)),t.multiSelect.on("addRange",this.$onAddRange),t.multiSelect.on("removeRange",this.$onRemoveRange),t.multiSelect.on("multiSelect",this.$onMultiSelect),t.multiSelect.on("singleSelect",this.$onSingleSelect),this.inMultiSelectMode!=t.selection.inMultiSelectMode&&(t.selection.inMultiSelectMode?this.$onMultiSelect():this.$onSingleSelect())},t.MultiSelect=m}),define("ace/range_list",["require","exports","module"],function(e,t,n){var r=function(){this.ranges=[]};(function(){this.comparePoints=function(e,t){return e.row-t.row||e.column-t.column},this.pointIndex=function(e,t){var n=this.ranges;for(var r=t||0;r0)continue;return s==0?r:(s=this.comparePoints(e,i.start),s>=0?r:-r-1)}return-r-1},this.add=function(e){var t=this.pointIndex(e.start);t<0&&(t=-t-1);var n=this.pointIndex(e.end,t);return n<0?n=-n-1:n++,this.ranges.splice(t,n-t,e)},this.addList=function(e){var t=[];for(var n=e.length;n--;)t.push.call(t,this.add(e[n]));return t},this.substractPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges.splice(t,1)},this.merge=function(){var e=[],t=this.ranges,n=t[0],r;for(var i=1;i=0},this.containsPoint=function(e){return this.pointIndex(e)>=0},this.rangeAtPoint=function(e){var t=this.pointIndex(e);if(t>=0)return this.ranges[t]},this.clipRows=function(e,t){var n=this.ranges;if(n[0].start.row>t||n[n.length-1].start.rowi)break;c.start.row==i&&c.start.column>=n.column&&(c.start.column+=u,c.start.row+=o),c.end.row==i&&c.end.column>=n.column&&(c.end.column+=u,c.end.row+=o)}if(o!=0&&f=0?i=e.nameToUrl("ace/worker/worker_sourcemint"):(e.nameToUrl&&!e.toUrl&&(e.toUrl=e.nameToUrl),i=o(e.toUrl("ace/worker/worker",null,"_")));var u={};t.forEach(function(t){u[t]=o(e.toUrl(t,null,"_").replace(/.js(\?.*)?$/,""))})}this.$worker=new Worker(i),this.$worker.postMessage({init:!0,tlns:u,module:n,classname:r}),this.callbackId=1,this.callbacks={},this.$worker.onerror=this.onError,this.$worker.onmessage=this.onMessage};(function(){r.implement(this,i),this.onError=function(e){throw window.console&&console.log&&console.log(e),e},this.onMessage=function(e){var t=e.data;switch(t.type){case"log":window.console&&console.log&&console.log.apply(console,t.data);break;case"event":this._emit(t.name,{data:t.data});break;case"call":var n=this.callbacks[t.id];n&&(n(t.data),delete this.callbacks[t.id])}},this.$normalizePath=function(e){return location.host?(e=e.replace(/^[a-z]+:\/\/[^\/]+/,""),e=location.protocol+"//"+location.host+(e.charAt(0)=="/"?"":location.pathname.replace(/\/[^\/]*$/,""))+"/"+e.replace(/^[\/]+/,""),e):e},this.terminate=function(){this._emit("terminate",{}),this.$worker.terminate(),this.$worker=null,this.$doc.removeEventListener("change",this.changeListener),this.$doc=null},this.send=function(e,t){this.$worker.postMessage({command:e,args:t})},this.call=function(e,t,n){if(n){var r=this.callbackId++;this.callbacks[r]=n,t.push(r)}this.send(e,t)},this.emit=function(e,t){try{this.$worker.postMessage({event:e,data:{data:t.data}})}catch(n){}},this.attachToDocument=function(e){this.$doc&&this.terminate(),this.$doc=e,this.call("setValue",[e.getValue()]),e.on("change",this.changeListener)},this.changeListener=function(e){e.range={start:e.data.range.start,end:e.data.range.end},this.emit("change",e)}}).call(o.prototype);var u=function(t,n,r){this.changeListener=this.changeListener.bind(this),this.callbackId=1,this.callbacks={},this.messageBuffer=[];var s=null,o=Object.create(i),u=this;this.$worker={},this.$worker.postMessage=function(e){u.messageBuffer.push(e),s&&setTimeout(a)};var a=function(){var e=u.messageBuffer.shift();e.command?s[e.command].apply(s,e.args):e.event&&o._emit(e.event,e.data)};o.postMessage=function(e){u.onMessage({data:e})},o.callback=function(e,t){this.postMessage({type:"call",id:t,data:e})},o.emit=function(e,t){this.postMessage({type:"event",name:e,data:t})},e([n],function(e){s=new e[r](o);while(u.messageBuffer.length)a()})};u.prototype=o.prototype,t.UIWorkerClient=u,t.WorkerClient=o}),define("ace/placeholder",["require","exports","module","ace/range","ace/lib/event_emitter","ace/lib/oop"],function(e,t,n){var r=e("./range").Range,i=e("./lib/event_emitter").EventEmitter,s=e("./lib/oop"),o=function(e,t,n,r,i,s){var o=this;this.length=t,this.session=e,this.doc=e.getDocument(),this.mainClass=i,this.othersClass=s,this.$onUpdate=this.onUpdate.bind(this),this.doc.on("change",this.$onUpdate),this.$others=r,this.$onCursorChange=function(){setTimeout(function(){o.onCursorChange()})},this.$pos=n;var u=e.getUndoManager().$undoStack||e.getUndoManager().$undostack||{length:-1};this.$undoStackDepth=u.length,this.setup(),e.selection.on("changeCursor",this.$onCursorChange)};(function(){s.implement(this,i),this.setup=function(){var e=this,t=this.doc,n=this.session,i=this.$pos;this.pos=t.createAnchor(i.row,i.column),this.markerId=n.addMarker(new r(i.row,i.column,i.row,i.column+this.length),this.mainClass,null,!1),this.pos.on("change",function(t){n.removeMarker(e.markerId),e.markerId=n.addMarker(new r(t.value.row,t.value.column,t.value.row,t.value.column+e.length),e.mainClass,null,!1)}),this.others=[],this.$others.forEach(function(n){var r=t.createAnchor(n.row,n.column);e.others.push(r)}),n.setUndoSelect(!1)},this.showOtherMarkers=function(){if(this.othersActive)return;var e=this.session,t=this;this.othersActive=!0,this.others.forEach(function(n){n.markerId=e.addMarker(new r(n.row,n.column,n.row,n.column+t.length),t.othersClass,null,!1),n.on("change",function(i){e.removeMarker(n.markerId),n.markerId=e.addMarker(new r(i.value.row,i.value.column,i.value.row,i.value.column+t.length),t.othersClass,null,!1)})})},this.hideOtherMarkers=function(){if(!this.othersActive)return;this.othersActive=!1;for(var e=0;e=this.pos.column&&n.start.column<=this.pos.column+this.length+1){var s=n.start.column-this.pos.column;this.length+=i;if(!this.session.$fromUndo){if(t.action==="insertText")for(var o=this.others.length-1;o>=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};u.row===n.start.row&&n.start.column=0;o--){var u=this.others[o],a={row:u.row,column:u.column+s};u.row===n.start.row&&n.start.column=this.pos.column&&t.column<=this.pos.column+this.length?(this.showOtherMarkers(),this._emit("cursorEnter",e)):(this.hideOtherMarkers(),this._emit("cursorLeave",e))},this.detach=function(){this.session.removeMarker(this.markerId),this.hideOtherMarkers(),this.doc.removeEventListener("change",this.$onUpdate),this.session.selection.removeEventListener("changeCursor",this.$onCursorChange),this.pos.detach();for(var e=0;ef){var h=e.getLine(l).length;return new r(f,u,l,h)}},this.openingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i+1},u=e.$findClosingBracket(t,o,s);if(!u)return;var a=e.foldWidgets[u.row];return a==null&&(a=this.getFoldWidget(e,u.row)),a=="start"&&u.row>o.row&&(u.row--,u.column=e.getLine(u.row).length),r.fromPoints(o,u)},this.closingBracketBlock=function(e,t,n,i,s){var o={row:n,column:i},u=e.$findOpeningBracket(t,o);if(!u)return;return u.column++,o.column--,r.fromPoints(u,o)}}).call(i.prototype)}); - (function() { - window.require(["ace/ace"], function(a) { - a && a.config.init(); - if (!window.ace) - window.ace = {}; - for (var key in a) if (a.hasOwnProperty(key)) - ace[key] = a[key]; - }); - })(); - \ No newline at end of file diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/ext-searchbox.js b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/ext-searchbox.js deleted file mode 100644 index e265f546eb7..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/ext-searchbox.js +++ /dev/null @@ -1 +0,0 @@ -define("ace/ext/searchbox",["require","exports","module","ace/lib/dom","ace/lib/lang","ace/lib/event","ace/keyboard/hash_handler","ace/lib/keys"],function(e,t,n){var r=e("../lib/dom"),i=e("../lib/lang"),s=e("../lib/event"),o="/* ------------------------------------------------------------------------------------------* Editor Search Form* --------------------------------------------------------------------------------------- */.ace_search {background-color: #ddd;border: 1px solid #cbcbcb;border-top: 0 none;max-width: 297px;overflow: hidden;margin: 0;padding: 4px;padding-right: 6px;padding-bottom: 0;position: absolute;top: 0px;z-index: 99;}.ace_search.left {border-left: 0 none;border-radius: 0px 0px 5px 0px;left: 0;}.ace_search.right {border-radius: 0px 0px 0px 5px;border-right: 0 none;right: 0;}.ace_search_form, .ace_replace_form {border-radius: 3px;border: 1px solid #cbcbcb;float: left;margin-bottom: 4px;overflow: hidden;}.ace_search_form.ace_nomatch {outline: 1px solid red;}.ace_search_field {background-color: white;border-right: 1px solid #cbcbcb;border: 0 none;-webkit-box-sizing: border-box;-moz-box-sizing: border-box;box-sizing: border-box;display: block;float: left;height: 22px;outline: 0;padding: 0 7px;width: 214px;margin: 0;}.ace_searchbtn,.ace_replacebtn {background: #fff;border: 0 none;border-left: 1px solid #dcdcdc;cursor: pointer;display: block;float: left;height: 22px;margin: 0;padding: 0;position: relative;}.ace_searchbtn:last-child,.ace_replacebtn:last-child {border-top-right-radius: 3px;border-bottom-right-radius: 3px;}.ace_searchbtn:disabled {background: none;cursor: default;}.ace_searchbtn {background-position: 50% 50%;background-repeat: no-repeat;width: 27px;}.ace_searchbtn.prev {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADFJREFUeNpiSU1NZUAC/6E0I0yACYskCpsJiySKIiY0SUZk40FyTEgCjGgKwTRAgAEAQJUIPCE+qfkAAAAASUVORK5CYII=); }.ace_searchbtn.next {background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADRJREFUeNpiTE1NZQCC/0DMyIAKwGJMUAYDEo3M/s+EpvM/mkKwCQxYjIeLMaELoLMBAgwAU7UJObTKsvAAAAAASUVORK5CYII=); }.ace_searchbtn_close {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAcCAYAAABRVo5BAAAAZ0lEQVR42u2SUQrAMAhDvazn8OjZBilCkYVVxiis8H4CT0VrAJb4WHT3C5xU2a2IQZXJjiQIRMdkEoJ5Q2yMqpfDIo+XY4k6h+YXOyKqTIj5REaxloNAd0xiKmAtsTHqW8sR2W5f7gCu5nWFUpVjZwAAAABJRU5ErkJggg==) no-repeat 50% 0;border-radius: 50%;border: 0 none;color: #656565;cursor: pointer;display: block;float: right;font-family: Arial;font-size: 16px;height: 14px;line-height: 16px;margin: 5px 1px 9px 5px;padding: 0;text-align: center;width: 14px;}.ace_searchbtn_close:hover {background-color: #656565;background-position: 50% 100%;color: white;}.ace_replacebtn.prev {width: 54px}.ace_replacebtn.next {width: 27px}.ace_button {margin-left: 2px;cursor: pointer;-webkit-user-select: none;-moz-user-select: none;-o-user-select: none;-ms-user-select: none;user-select: none;overflow: hidden;opacity: 0.7;border: 1px solid rgba(100,100,100,0.23);padding: 1px;-moz-box-sizing: border-box;box-sizing: border-box;color: black;}.ace_button:hover {background-color: #eee;opacity:1;}.ace_button:active {background-color: #ddd;}.ace_button.checked {border-color: #3399ff;opacity:1;}.ace_search_options{margin-bottom: 3px;text-align: right;-webkit-user-select: none;-moz-user-select: none;-o-user-select: none;-ms-user-select: none;user-select: none;}",u=e("../keyboard/hash_handler").HashHandler,a=e("../lib/keys");r.importCssString(o,"ace_searchbox");var f=''.replace(/>\s+/g,">"),l=function(e,t,n){var i=r.createElement("div");i.innerHTML=f,this.element=i.firstChild,this.$init(),this.setEditor(e)};(function(){this.setEditor=function(e){e.searchBox=this,e.container.appendChild(this.element),this.editor=e},this.$initElements=function(e){this.searchBox=e.querySelector(".ace_search_form"),this.replaceBox=e.querySelector(".ace_replace_form"),this.searchOptions=e.querySelector(".ace_search_options"),this.regExpOption=e.querySelector("[action=toggleRegexpMode]"),this.caseSensitiveOption=e.querySelector("[action=toggleCaseSensitive]"),this.wholeWordOption=e.querySelector("[action=toggleWholeWords]"),this.searchInput=this.searchBox.querySelector(".ace_search_field"),this.replaceInput=this.replaceBox.querySelector(".ace_search_field")},this.$init=function(){var e=this.element;this.$initElements(e);var t=this;s.addListener(e,"mousedown",function(e){setTimeout(function(){t.activeInput.focus()},0),s.stopPropagation(e)}),s.addListener(e,"click",function(e){var n=e.target||e.srcElement,r=n.getAttribute("action");r&&t[r]?t[r]():t.$searchBarKb.commands[r]&&t.$searchBarKb.commands[r].exec(t),s.stopPropagation(e)}),s.addCommandKeyListener(e,function(e,n,r){var i=a.keyCodeToString(r),o=t.$searchBarKb.findKeyCommand(n,i);o&&o.exec&&(o.exec(t),s.stopEvent(e))}),this.$onChange=i.delayedCall(function(){t.find(!1,!1)}),s.addListener(this.searchInput,"input",function(){t.$onChange.schedule(20)}),s.addListener(this.searchInput,"focus",function(){t.activeInput=t.searchInput,t.searchInput.value&&t.highlight()}),s.addListener(this.replaceInput,"focus",function(){t.activeInput=t.replaceInput,t.searchInput.value&&t.highlight()})},this.$closeSearchBarKb=new u([{bindKey:"Esc",name:"closeSearchBar",exec:function(e){e.searchBox.hide()}}]),this.$searchBarKb=new u,this.$searchBarKb.bindKeys({"Ctrl-f|Command-f|Ctrl-H|Command-Option-F":function(e){var t=e.isReplace=!e.isReplace;e.replaceBox.style.display=t?"":"none",e[t?"replaceInput":"searchInput"].focus()},"Ctrl-G|Command-G":function(e){e.findNext()},"Ctrl-Shift-G|Command-Shift-G":function(e){e.findPrev()},esc:function(e){setTimeout(function(){e.hide()})},Return:function(e){e.activeInput==e.replaceInput&&e.replace(),e.findNext()},"Shift-Return":function(e){e.activeInput==e.replaceInput&&e.replace(),e.findPrev()},Tab:function(e){(e.activeInput==e.replaceInput?e.searchInput:e.replaceInput).focus()}}),this.$searchBarKb.addCommands([{name:"toggleRegexpMode",bindKey:{win:"Alt-R|Alt-/",mac:"Ctrl-Alt-R|Ctrl-Alt-/"},exec:function(e){e.regExpOption.checked=!e.regExpOption.checked,e.$syncOptions()}},{name:"toggleCaseSensitive",bindKey:{win:"Alt-C|Alt-I",mac:"Ctrl-Alt-R|Ctrl-Alt-I"},exec:function(e){e.caseSensitiveOption.checked=!e.caseSensitiveOption.checked,e.$syncOptions()}},{name:"toggleWholeWords",bindKey:{win:"Alt-B|Alt-W",mac:"Ctrl-Alt-B|Ctrl-Alt-W"},exec:function(e){e.wholeWordOption.checked=!e.wholeWordOption.checked,e.$syncOptions()}}]),this.$syncOptions=function(){r.setCssClass(this.regExpOption,"checked",this.regExpOption.checked),r.setCssClass(this.wholeWordOption,"checked",this.wholeWordOption.checked),r.setCssClass(this.caseSensitiveOption,"checked",this.caseSensitiveOption.checked),this.find(!1,!1)},this.highlight=function(e){this.editor.session.highlight(e||this.editor.$search.$options.re),this.editor.renderer.updateBackMarkers()},this.find=function(e,t){var n=this.editor.find(this.searchInput.value,{skipCurrent:e,backwards:t,wrap:!0,regExp:this.regExpOption.checked,caseSensitive:this.caseSensitiveOption.checked,wholeWord:this.wholeWordOption.checked}),i=!n&&this.searchInput.value;r.setCssClass(this.searchBox,"ace_nomatch",i),this.editor._emit("findSearchBox",{match:!i}),this.highlight()},this.findNext=function(){this.find(!0,!1)},this.findPrev=function(){this.find(!0,!0)},this.replace=function(){this.editor.getReadOnly()||this.editor.replace(this.replaceInput.value)},this.replaceAndFindNext=function(){this.editor.getReadOnly()||(this.editor.replace(this.replaceInput.value),this.findNext())},this.replaceAll=function(){this.editor.getReadOnly()||this.editor.replaceAll(this.replaceInput.value)},this.hide=function(){this.element.style.display="none",this.editor.keyBinding.removeKeyboardHandler(this.$closeSearchBarKb),this.editor.focus()},this.show=function(e,t){this.element.style.display="",this.replaceBox.style.display=t?"":"none",this.isReplace=t,e&&(this.searchInput.value=e),this.searchInput.focus(),this.searchInput.select(),this.editor.keyBinding.addKeyboardHandler(this.$closeSearchBarKb)}}).call(l.prototype),t.SearchBox=l,t.Search=function(e,t){var n=e.searchBox||new l(e);n.show(e.session.getTextRange(),t)}}) \ No newline at end of file diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/mode-json.js b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/mode-json.js deleted file mode 100644 index 27248af8f97..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/mode-json.js +++ /dev/null @@ -1 +0,0 @@ -define("ace/mode/json",["require","exports","module","ace/lib/oop","ace/mode/text","ace/tokenizer","ace/mode/json_highlight_rules","ace/mode/matching_brace_outdent","ace/mode/behaviour/cstyle","ace/mode/folding/cstyle","ace/worker/worker_client"],function(e,t,n){var r=e("../lib/oop"),i=e("./text").Mode,s=e("../tokenizer").Tokenizer,o=e("./json_highlight_rules").JsonHighlightRules,u=e("./matching_brace_outdent").MatchingBraceOutdent,a=e("./behaviour/cstyle").CstyleBehaviour,f=e("./folding/cstyle").FoldMode,l=e("../worker/worker_client").WorkerClient,c=function(){this.$tokenizer=new s((new o).getRules()),this.$outdent=new u,this.$behaviour=new a,this.foldingRules=new f};r.inherits(c,i),function(){this.getNextLineIndent=function(e,t,n){var r=this.$getIndent(t);if(e=="start"){var i=t.match(/^.*[\{\(\[]\s*$/);i&&(r+=n)}return r},this.checkOutdent=function(e,t,n){return this.$outdent.checkOutdent(t,n)},this.autoOutdent=function(e,t,n){this.$outdent.autoOutdent(t,n)},this.createWorker=function(e){var t=new l(["ace"],"ace/mode/json_worker","JsonWorker");return t.attachToDocument(e.getDocument()),t.on("error",function(t){e.setAnnotations([t.data])}),t.on("ok",function(){e.clearAnnotations()}),t}}.call(c.prototype),t.Mode=c}),define("ace/mode/json_highlight_rules",["require","exports","module","ace/lib/oop","ace/mode/text_highlight_rules"],function(e,t,n){var r=e("../lib/oop"),i=e("./text_highlight_rules").TextHighlightRules,s=function(){this.$rules={start:[{token:"variable",regex:'["](?:(?:\\\\.)|(?:[^"\\\\]))*?["]\\s*(?=:)'},{token:"string",regex:'"',next:"string"},{token:"constant.numeric",regex:"0[xX][0-9a-fA-F]+\\b"},{token:"constant.numeric",regex:"[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"},{token:"constant.language.boolean",regex:"(?:true|false)\\b"},{token:"invalid.illegal",regex:"['](?:(?:\\\\.)|(?:[^'\\\\]))*?[']"},{token:"invalid.illegal",regex:"\\/\\/.*$"},{token:"paren.lparen",regex:"[[({]"},{token:"paren.rparen",regex:"[\\])}]"},{token:"text",regex:"\\s+"}],string:[{token:"constant.language.escape",regex:/\\(?:x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|["\\\/bfnrt])/},{token:"string",regex:'[^"\\\\]+'},{token:"string",regex:'"',next:"start"},{token:"string",regex:"",next:"start"}]}};r.inherits(s,i),t.JsonHighlightRules=s}),define("ace/mode/matching_brace_outdent",["require","exports","module","ace/range"],function(e,t,n){var r=e("../range").Range,i=function(){};(function(){this.checkOutdent=function(e,t){return/^\s+$/.test(e)?/^\s*\}/.test(t):!1},this.autoOutdent=function(e,t){var n=e.getLine(t),i=n.match(/^(\s*\})/);if(!i)return 0;var s=i[1].length,o=e.findMatchingBracket({row:t,column:s});if(!o||o.row==t)return 0;var u=this.$getIndent(e.getLine(o.row));e.replace(new r(t,0,t,s-1),u)},this.$getIndent=function(e){var t=e.match(/^(\s+)/);return t?t[1]:""}}).call(i.prototype),t.MatchingBraceOutdent=i}),define("ace/mode/behaviour/cstyle",["require","exports","module","ace/lib/oop","ace/mode/behaviour","ace/token_iterator","ace/lib/lang"],function(e,t,n){var r=e("../../lib/oop"),i=e("../behaviour").Behaviour,s=e("../../token_iterator").TokenIterator,o=e("../../lib/lang"),u=["text","paren.rparen","punctuation.operator"],a=["text","paren.rparen","punctuation.operator","comment"],f=0,l=-1,c="",h=0,p=-1,d="",v="",m=function(){m.isSaneInsertion=function(e,t){var n=e.getCursorPosition(),r=new s(t,n.row,n.column);if(!this.$matchTokenType(r.getCurrentToken()||"text",u)){var i=new s(t,n.row,n.column+1);if(!this.$matchTokenType(i.getCurrentToken()||"text",u))return!1}return r.stepForward(),r.getCurrentTokenRow()!==n.row||this.$matchTokenType(r.getCurrentToken()||"text",a)},m.$matchTokenType=function(e,t){return t.indexOf(e.type||e)>-1},m.recordAutoInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isAutoInsertedClosing(r,i,c[0])||(f=0),l=r.row,c=n+i.substr(r.column),f++},m.recordMaybeInsert=function(e,t,n){var r=e.getCursorPosition(),i=t.doc.getLine(r.row);this.isMaybeInsertedClosing(r,i)||(h=0),p=r.row,d=i.substr(0,r.column)+n,v=i.substr(r.column),h++},m.isAutoInsertedClosing=function(e,t,n){return f>0&&e.row===l&&n===c[0]&&t.substr(e.column)===c},m.isMaybeInsertedClosing=function(e,t){return h>0&&e.row===p&&t.substr(e.column)===v&&t.substr(0,e.column)==d},m.popAutoInsertedClosing=function(){c=c.substr(1),f--},m.clearMaybeInsertedClosing=function(){h=0,p=-1},this.add("braces","insertion",function(e,t,n,r,i){var s=n.getCursorPosition(),u=r.doc.getLine(s.row);if(i=="{"){var a=n.getSelectionRange(),f=r.doc.getTextRange(a);if(f!==""&&f!=="{"&&n.getWrapBehavioursEnabled())return{text:"{"+f+"}",selection:!1};if(m.isSaneInsertion(n,r))return/[\]\}\)]/.test(u[s.column])?(m.recordAutoInsert(n,r,"}"),{text:"{}",selection:[1,1]}):(m.recordMaybeInsert(n,r,"{"),{text:"{",selection:[1,1]})}else if(i=="}"){var l=u.substring(s.column,s.column+1);if(l=="}"){var c=r.$findOpeningBracket("}",{column:s.column+1,row:s.row});if(c!==null&&m.isAutoInsertedClosing(s,u,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}else if(i=="\n"||i=="\r\n"){var p="";m.isMaybeInsertedClosing(s,u)&&(p=o.stringRepeat("}",h),m.clearMaybeInsertedClosing());var l=u.substring(s.column,s.column+1);if(l=="}"||p!==""){var d=r.findMatchingBracket({row:s.row,column:s.column},"}");if(!d)return null;var v=this.getNextLineIndent(e,u.substring(0,s.column),r.getTabString()),g=this.$getIndent(u);return{text:"\n"+v+"\n"+g+p,selection:[1,v.length,1,v.length]}}}}),this.add("braces","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="{"){var o=r.doc.getLine(i.start.row),u=o.substring(i.end.column,i.end.column+1);if(u=="}")return i.end.column++,i;h--}}),this.add("parens","insertion",function(e,t,n,r,i){if(i=="("){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"("+o+")",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,")"),{text:"()",selection:[1,1]}}else if(i==")"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f==")"){var l=r.$findOpeningBracket(")",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("parens","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="("){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==")")return i.end.column++,i}}),this.add("brackets","insertion",function(e,t,n,r,i){if(i=="["){var s=n.getSelectionRange(),o=r.doc.getTextRange(s);if(o!==""&&n.getWrapBehavioursEnabled())return{text:"["+o+"]",selection:!1};if(m.isSaneInsertion(n,r))return m.recordAutoInsert(n,r,"]"),{text:"[]",selection:[1,1]}}else if(i=="]"){var u=n.getCursorPosition(),a=r.doc.getLine(u.row),f=a.substring(u.column,u.column+1);if(f=="]"){var l=r.$findOpeningBracket("]",{column:u.column+1,row:u.row});if(l!==null&&m.isAutoInsertedClosing(u,a,i))return m.popAutoInsertedClosing(),{text:"",selection:[1,1]}}}}),this.add("brackets","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&s=="["){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u=="]")return i.end.column++,i}}),this.add("string_dquotes","insertion",function(e,t,n,r,i){if(i=='"'||i=="'"){var s=i,o=n.getSelectionRange(),u=r.doc.getTextRange(o);if(u!==""&&u!=="'"&&u!='"'&&n.getWrapBehavioursEnabled())return{text:s+u+s,selection:!1};var a=n.getCursorPosition(),f=r.doc.getLine(a.row),l=f.substring(a.column-1,a.column);if(l=="\\")return null;var c=r.getTokens(o.start.row),h=0,p,d=-1;for(var v=0;vo.start.column)break;h+=c[v].value.length}if(!p||d<0&&p.type!=="comment"&&(p.type!=="string"||o.start.column!==p.value.length+h-1&&p.value.lastIndexOf(s)===p.value.length-1)){if(!m.isSaneInsertion(n,r))return;return{text:s+s,selection:[1,1]}}if(p&&p.type==="string"){var g=f.substring(a.column,a.column+1);if(g==s)return{text:"",selection:[1,1]}}}}),this.add("string_dquotes","deletion",function(e,t,n,r,i){var s=r.doc.getTextRange(i);if(!i.isMultiLine()&&(s=='"'||s=="'")){var o=r.doc.getLine(i.start.row),u=o.substring(i.start.column+1,i.start.column+2);if(u==s)return i.end.column++,i}})};r.inherits(m,i),t.CstyleBehaviour=m}),define("ace/mode/folding/cstyle",["require","exports","module","ace/lib/oop","ace/range","ace/mode/folding/fold_mode"],function(e,t,n){var r=e("../../lib/oop"),i=e("../../range").Range,s=e("./fold_mode").FoldMode,o=t.FoldMode=function(){};r.inherits(o,s),function(){this.foldingStartMarker=/(\{|\[)[^\}\]]*$|^\s*(\/\*)/,this.foldingStopMarker=/^[^\[\{]*(\}|\])|^[\s\*]*(\*\/)/,this.getFoldWidgetRange=function(e,t,n){var r=e.getLine(n),i=r.match(this.foldingStartMarker);if(i){var s=i.index;return i[1]?this.openingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s+i[0].length,1)}if(t!=="markbeginend")return;var i=r.match(this.foldingStopMarker);if(i){var s=i.index+i[0].length;return i[1]?this.closingBracketBlock(e,i[1],n,s):e.getCommentFoldRange(n,s,-1)}}}.call(o.prototype)}) \ No newline at end of file diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/theme-jsoneditor.js b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/theme-jsoneditor.js deleted file mode 100644 index 3e658b83438..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/theme-jsoneditor.js +++ /dev/null @@ -1,144 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: - * - * Copyright (c) 2010, Ajax.org B.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Ajax.org B.V. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ - -define('ace/theme/jsoneditor', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) { - -exports.isDark = false; -exports.cssClass = "ace-jsoneditor"; -exports.cssText = ".ace-jsoneditor .ace_gutter {\ -background: #ebebeb;\ -color: #333\ -}\ -\ -.ace-jsoneditor.ace_editor {\ -font-family: droid sans mono, monospace, courier new, courier, sans-serif;\ -line-height: 1.3;\ -}\ -.ace-jsoneditor .ace_print-margin {\ -width: 1px;\ -background: #e8e8e8\ -}\ -.ace-jsoneditor .ace_scroller {\ -background-color: #FFFFFF\ -}\ -.ace-jsoneditor .ace_text-layer {\ -color: gray\ -}\ -.ace-jsoneditor .ace_variable {\ -color: #1a1a1a\ -}\ -.ace-jsoneditor .ace_cursor {\ -border-left: 2px solid #000000\ -}\ -.ace-jsoneditor .ace_overwrite-cursors .ace_cursor {\ -border-left: 0px;\ -border-bottom: 1px solid #000000\ -}\ -.ace-jsoneditor .ace_marker-layer .ace_selection {\ -background: #D5DDF6\ -}\ -.ace-jsoneditor.ace_multiselect .ace_selection.ace_start {\ -box-shadow: 0 0 3px 0px #FFFFFF;\ -border-radius: 2px\ -}\ -.ace-jsoneditor .ace_marker-layer .ace_step {\ -background: rgb(255, 255, 0)\ -}\ -.ace-jsoneditor .ace_marker-layer .ace_bracket {\ -margin: -1px 0 0 -1px;\ -border: 1px solid #BFBFBF\ -}\ -.ace-jsoneditor .ace_marker-layer .ace_active-line {\ -background: #FFFBD1\ -}\ -.ace-jsoneditor .ace_gutter-active-line {\ -background-color : #dcdcdc\ -}\ -.ace-jsoneditor .ace_marker-layer .ace_selected-word {\ -border: 1px solid #D5DDF6\ -}\ -.ace-jsoneditor .ace_invisible {\ -color: #BFBFBF\ -}\ -.ace-jsoneditor .ace_keyword,\ -.ace-jsoneditor .ace_meta,\ -.ace-jsoneditor .ace_support.ace_constant.ace_property-value {\ -color: #AF956F\ -}\ -.ace-jsoneditor .ace_keyword.ace_operator {\ -color: #484848\ -}\ -.ace-jsoneditor .ace_keyword.ace_other.ace_unit {\ -color: #96DC5F\ -}\ -.ace-jsoneditor .ace_constant.ace_language {\ -color: darkorange\ -}\ -.ace-jsoneditor .ace_constant.ace_numeric {\ -color: red\ -}\ -.ace-jsoneditor .ace_constant.ace_character.ace_entity {\ -color: #BF78CC\ -}\ -.ace-jsoneditor .ace_invalid {\ -color: #FFFFFF;\ -background-color: #FF002A;\ -}\ -.ace-jsoneditor .ace_fold {\ -background-color: #AF956F;\ -border-color: #000000\ -}\ -.ace-jsoneditor .ace_storage,\ -.ace-jsoneditor .ace_support.ace_class,\ -.ace-jsoneditor .ace_support.ace_function,\ -.ace-jsoneditor .ace_support.ace_other,\ -.ace-jsoneditor .ace_support.ace_type {\ -color: #C52727\ -}\ -.ace-jsoneditor .ace_string {\ -color: green\ -}\ -.ace-jsoneditor .ace_comment {\ -color: #BCC8BA\ -}\ -.ace-jsoneditor .ace_entity.ace_name.ace_tag,\ -.ace-jsoneditor .ace_entity.ace_other.ace_attribute-name {\ -color: #606060\ -}\ -.ace-jsoneditor .ace_markup.ace_underline {\ -text-decoration: underline\ -}\ -.ace-jsoneditor .ace_indent-guide {\ -background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y\ -}"; - -var dom = require("../lib/dom"); -dom.importCssString(exports.cssText, exports.cssClass); -}); diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/theme-textmate.js b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/theme-textmate.js deleted file mode 100644 index f25d0f54e88..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/theme-textmate.js +++ /dev/null @@ -1,163 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Distributed under the BSD license: - * - * Copyright (c) 2010, Ajax.org B.V. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Ajax.org B.V. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * ***** END LICENSE BLOCK ***** */ - -define('ace/theme/textmate', ['require', 'exports', 'module' , 'ace/lib/dom'], function(require, exports, module) { - - -exports.isDark = false; -exports.cssClass = "ace-tm"; -exports.cssText = ".ace-tm .ace_gutter {\ -background: #f0f0f0;\ -color: #333;\ -}\ -.ace-tm .ace_print-margin {\ -width: 1px;\ -background: #e8e8e8;\ -}\ -.ace-tm .ace_fold {\ -background-color: #6B72E6;\ -}\ -.ace-tm .ace_scroller {\ -background-color: #FFFFFF;\ -}\ -.ace-tm .ace_cursor {\ -border-left: 2px solid black;\ -}\ -.ace-tm .ace_overwrite-cursors .ace_cursor {\ -border-left: 0px;\ -border-bottom: 1px solid black;\ -}\ -.ace-tm .ace_invisible {\ -color: rgb(191, 191, 191);\ -}\ -.ace-tm .ace_storage,\ -.ace-tm .ace_keyword {\ -color: blue;\ -}\ -.ace-tm .ace_constant {\ -color: rgb(197, 6, 11);\ -}\ -.ace-tm .ace_constant.ace_buildin {\ -color: rgb(88, 72, 246);\ -}\ -.ace-tm .ace_constant.ace_language {\ -color: rgb(88, 92, 246);\ -}\ -.ace-tm .ace_constant.ace_library {\ -color: rgb(6, 150, 14);\ -}\ -.ace-tm .ace_invalid {\ -background-color: rgba(255, 0, 0, 0.1);\ -color: red;\ -}\ -.ace-tm .ace_support.ace_function {\ -color: rgb(60, 76, 114);\ -}\ -.ace-tm .ace_support.ace_constant {\ -color: rgb(6, 150, 14);\ -}\ -.ace-tm .ace_support.ace_type,\ -.ace-tm .ace_support.ace_class {\ -color: rgb(109, 121, 222);\ -}\ -.ace-tm .ace_keyword.ace_operator {\ -color: rgb(104, 118, 135);\ -}\ -.ace-tm .ace_string {\ -color: rgb(3, 106, 7);\ -}\ -.ace-tm .ace_comment {\ -color: rgb(76, 136, 107);\ -}\ -.ace-tm .ace_comment.ace_doc {\ -color: rgb(0, 102, 255);\ -}\ -.ace-tm .ace_comment.ace_doc.ace_tag {\ -color: rgb(128, 159, 191);\ -}\ -.ace-tm .ace_constant.ace_numeric {\ -color: rgb(0, 0, 205);\ -}\ -.ace-tm .ace_variable {\ -color: rgb(49, 132, 149);\ -}\ -.ace-tm .ace_xml-pe {\ -color: rgb(104, 104, 91);\ -}\ -.ace-tm .ace_entity.ace_name.ace_function {\ -color: #0000A2;\ -}\ -.ace-tm .ace_markup.ace_heading {\ -color: rgb(12, 7, 255);\ -}\ -.ace-tm .ace_markup.ace_list {\ -color:rgb(185, 6, 144);\ -}\ -.ace-tm .ace_meta.ace_tag {\ -color:rgb(0, 22, 142);\ -}\ -.ace-tm .ace_string.ace_regex {\ -color: rgb(255, 0, 0)\ -}\ -.ace-tm .ace_marker-layer .ace_selection {\ -background: rgb(181, 213, 255);\ -}\ -.ace-tm.ace_multiselect .ace_selection.ace_start {\ -box-shadow: 0 0 3px 0px white;\ -border-radius: 2px;\ -}\ -.ace-tm .ace_marker-layer .ace_step {\ -background: rgb(252, 255, 0);\ -}\ -.ace-tm .ace_marker-layer .ace_stack {\ -background: rgb(164, 229, 101);\ -}\ -.ace-tm .ace_marker-layer .ace_bracket {\ -margin: -1px 0 0 -1px;\ -border: 1px solid rgb(192, 192, 192);\ -}\ -.ace-tm .ace_marker-layer .ace_active-line {\ -background: rgba(0, 0, 0, 0.07);\ -}\ -.ace-tm .ace_gutter-active-line {\ -background-color : #dcdcdc;\ -}\ -.ace-tm .ace_marker-layer .ace_selected-word {\ -background: rgb(250, 250, 255);\ -border: 1px solid rgb(200, 200, 250);\ -}\ -.ace-tm .ace_indent-guide {\ -background: url(\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAACCAYAAACZgbYnAAAAE0lEQVQImWP4////f4bLly//BwAmVgd1/w11/gAAAABJRU5ErkJggg==\") right repeat-y;\ -}\ -"; - -var dom = require("../lib/dom"); -dom.importCssString(exports.cssText, exports.cssClass); -}); diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/worker-json.js b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/worker-json.js deleted file mode 100644 index 1f8010e97c1..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/ace/worker-json.js +++ /dev/null @@ -1 +0,0 @@ -"no use strict";function initBaseUrls(e){require.tlns=e}function initSender(){var e=require(null,"ace/lib/event_emitter").EventEmitter,t=require(null,"ace/lib/oop"),n=function(){};return function(){t.implement(this,e),this.callback=function(e,t){postMessage({type:"call",id:t,data:e})},this.emit=function(e,t){postMessage({type:"event",name:e,data:t})}}.call(n.prototype),new n}if(typeof window!="undefined"&&window.document)throw"atempt to load ace worker into main window instead of webWorker";var console={log:function(){var e=Array.prototype.slice.call(arguments,0);postMessage({type:"log",data:e})},error:function(){var e=Array.prototype.slice.call(arguments,0);postMessage({type:"log",data:e})}},window={console:console},normalizeModule=function(e,t){if(t.indexOf("!")!==-1){var n=t.split("!");return normalizeModule(e,n[0])+"!"+normalizeModule(e,n[1])}if(t.charAt(0)=="."){var r=e.split("/").slice(0,-1).join("/");t=r+"/"+t;while(t.indexOf(".")!==-1&&i!=t){var i=t;t=t.replace(/\/\.\//,"/").replace(/[^\/]+\/\.\.\//,"")}}return t},require=function(e,t){if(!t.charAt)throw new Error("worker.js require() accepts only (parentId, id) as arguments");t=normalizeModule(e,t);var n=require.modules[t];if(n)return n.initialized||(n.initialized=!0,n.exports=n.factory().exports),n.exports;var r=t.split("/");r[0]=require.tlns[r[0]]||r[0];var i=r.join("/")+".js";return require.id=t,importScripts(i),require(e,t)};require.modules={},require.tlns={};var define=function(e,t,n){arguments.length==2?(n=t,typeof e!="string"&&(t=e,e=require.id)):arguments.length==1&&(n=e,e=require.id);if(e.indexOf("text!")===0)return;var r=function(t,n){return require(e,t,n)};require.modules[e]={factory:function(){var e={exports:{}},t=n(r,e.exports,e);return t&&(e.exports=t),e}}},main,sender;onmessage=function(e){var t=e.data;if(t.command){if(!main[t.command])throw new Error("Unknown command:"+t.command);main[t.command].apply(main,t.args)}else if(t.init){initBaseUrls(t.tlns),require(null,"ace/lib/fixoldbrowsers"),sender=initSender();var n=require(null,t.module)[t.classname];main=new n(sender)}else t.event&&sender&&sender._emit(t.event,t.data)},define("ace/lib/fixoldbrowsers",["require","exports","module","ace/lib/regexp","ace/lib/es5-shim"],function(e,t,n){e("./regexp"),e("./es5-shim")}),define("ace/lib/regexp",["require","exports","module"],function(e,t,n){function o(e){return(e.global?"g":"")+(e.ignoreCase?"i":"")+(e.multiline?"m":"")+(e.extended?"x":"")+(e.sticky?"y":"")}function u(e,t,n){if(Array.prototype.indexOf)return e.indexOf(t,n);for(var r=n||0;r1&&u(t,"")>-1&&(a=RegExp(this.source,r.replace.call(o(this),"g","")),r.replace.call(e.slice(t.index),a,function(){for(var e=1;et.index&&this.lastIndex--}return t},s||(RegExp.prototype.test=function(e){var t=r.exec.call(this,e);return t&&this.global&&!t[0].length&&this.lastIndex>t.index&&this.lastIndex--,!!t})}),define("ace/lib/es5-shim",["require","exports","module"],function(e,t,n){function r(){}function w(e){try{return Object.defineProperty(e,"sentinel",{}),"sentinel"in e}catch(t){}}function j(e){return e=+e,e!==e?e=0:e!==0&&e!==1/0&&e!==-1/0&&(e=(e>0||-1)*Math.floor(Math.abs(e))),e}function F(e){var t=typeof e;return e===null||t==="undefined"||t==="boolean"||t==="number"||t==="string"}function I(e){var t,n,r;if(F(e))return e;n=e.valueOf;if(typeof n=="function"){t=n.call(e);if(F(t))return t}r=e.toString;if(typeof r=="function"){t=r.call(e);if(F(t))return t}throw new TypeError}Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!="function")throw new TypeError("Function.prototype.bind called on incompatible "+n);var i=u.call(arguments,1),s=function(){if(this instanceof s){var e=n.apply(this,i.concat(u.call(arguments)));return Object(e)===e?e:this}return n.apply(t,i.concat(u.call(arguments)))};return n.prototype&&(r.prototype=n.prototype,s.prototype=new r,r.prototype=null),s});var i=Function.prototype.call,s=Array.prototype,o=Object.prototype,u=s.slice,a=i.bind(o.toString),f=i.bind(o.hasOwnProperty),l,c,h,p,d;if(d=f(o,"__defineGetter__"))l=i.bind(o.__defineGetter__),c=i.bind(o.__defineSetter__),h=i.bind(o.__lookupGetter__),p=i.bind(o.__lookupSetter__);if([1,2].splice(0).length!=2)if(!function(){function e(e){var t=new Array(e+2);return t[0]=t[1]=0,t}var t=[],n;t.splice.apply(t,e(20)),t.splice.apply(t,e(26)),n=t.length,t.splice(5,0,"XXX"),n+1==t.length;if(n+1==t.length)return!0}())Array.prototype.splice=function(e,t){var n=this.length;e>0?e>n&&(e=n):e==void 0?e=0:e<0&&(e=Math.max(n+e,0)),e+ta)for(h=l;h--;)this[f+h]=this[a+h];if(s&&e===c)this.length=c,this.push.apply(this,i);else{this.length=c+s;for(h=0;h>>0;if(a(t)!="[object Function]")throw new TypeError;while(++s>>0,s=Array(i),o=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var u=0;u>>0,s=[],o,u=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var f=0;f>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0,s=arguments[1];if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");for(var o=0;o>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduce of empty array with no initial value");var s=0,o;if(arguments.length>=2)o=arguments[1];else do{if(s in r){o=r[s++];break}if(++s>=i)throw new TypeError("reduce of empty array with no initial value")}while(!0);for(;s>>0;if(a(t)!="[object Function]")throw new TypeError(t+" is not a function");if(!i&&arguments.length==1)throw new TypeError("reduceRight of empty array with no initial value");var s,o=i-1;if(arguments.length>=2)s=arguments[1];else do{if(o in r){s=r[o--];break}if(--o<0)throw new TypeError("reduceRight of empty array with no initial value")}while(!0);do o in this&&(s=t.call(void 0,s,r[o],o,n));while(o--);return s});if(!Array.prototype.indexOf||[0,1].indexOf(1,2)!=-1)Array.prototype.indexOf=function(t){var n=g&&a(this)=="[object String]"?this.split(""):q(this),r=n.length>>>0;if(!r)return-1;var i=0;arguments.length>1&&(i=j(arguments[1])),i=i>=0?i:Math.max(0,r+i);for(;i>>0;if(!r)return-1;var i=r-1;arguments.length>1&&(i=Math.min(i,j(arguments[1]))),i=i>=0?i:r-Math.abs(i);for(;i>=0;i--)if(i in n&&t===n[i])return i;return-1};Object.getPrototypeOf||(Object.getPrototypeOf=function(t){return t.__proto__||(t.constructor?t.constructor.prototype:o)});if(!Object.getOwnPropertyDescriptor){var y="Object.getOwnPropertyDescriptor called on a non-object: ";Object.getOwnPropertyDescriptor=function(t,n){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(y+t);if(!f(t,n))return;var r,i,s;r={enumerable:!0,configurable:!0};if(d){var u=t.__proto__;t.__proto__=o;var i=h(t,n),s=p(t,n);t.__proto__=u;if(i||s)return i&&(r.get=i),s&&(r.set=s),r}return r.value=t[n],r}}Object.getOwnPropertyNames||(Object.getOwnPropertyNames=function(t){return Object.keys(t)});if(!Object.create){var b;Object.prototype.__proto__===null?b=function(){return{__proto__:null}}:b=function(){var e={};for(var t in e)e[t]=null;return e.constructor=e.hasOwnProperty=e.propertyIsEnumerable=e.isPrototypeOf=e.toLocaleString=e.toString=e.valueOf=e.__proto__=null,e},Object.create=function(t,n){var r;if(t===null)r=b();else{if(typeof t!="object")throw new TypeError("typeof prototype["+typeof t+"] != 'object'");var i=function(){};i.prototype=t,r=new i,r.__proto__=t}return n!==void 0&&Object.defineProperties(r,n),r}}if(Object.defineProperty){var E=w({}),S=typeof document=="undefined"||w(document.createElement("div"));if(!E||!S)var x=Object.defineProperty}if(!Object.defineProperty||x){var T="Property description must be an object: ",N="Object.defineProperty called on non-object: ",C="getters & setters can not be defined on this javascript engine";Object.defineProperty=function(t,n,r){if(typeof t!="object"&&typeof t!="function"||t===null)throw new TypeError(N+t);if(typeof r!="object"&&typeof r!="function"||r===null)throw new TypeError(T+r);if(x)try{return x.call(Object,t,n,r)}catch(i){}if(f(r,"value"))if(d&&(h(t,n)||p(t,n))){var s=t.__proto__;t.__proto__=o,delete t[n],t[n]=r.value,t.__proto__=s}else t[n]=r.value;else{if(!d)throw new TypeError(C);f(r,"get")&&l(t,n,r.get),f(r,"set")&&c(t,n,r.set)}return t}}Object.defineProperties||(Object.defineProperties=function(t,n){for(var r in n)f(n,r)&&Object.defineProperty(t,r,n[r]);return t}),Object.seal||(Object.seal=function(t){return t}),Object.freeze||(Object.freeze=function(t){return t});try{Object.freeze(function(){})}catch(k){Object.freeze=function(t){return function(n){return typeof n=="function"?n:t(n)}}(Object.freeze)}Object.preventExtensions||(Object.preventExtensions=function(t){return t}),Object.isSealed||(Object.isSealed=function(t){return!1}),Object.isFrozen||(Object.isFrozen=function(t){return!1}),Object.isExtensible||(Object.isExtensible=function(t){if(Object(t)===t)throw new TypeError;var n="";while(f(t,n))n+="?";t[n]=!0;var r=f(t,n);return delete t[n],r});if(!Object.keys){var L=!0,A=["toString","toLocaleString","valueOf","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","constructor"],O=A.length;for(var M in{toString:null})L=!1;Object.keys=function R(e){if(typeof e!="object"&&typeof e!="function"||e===null)throw new TypeError("Object.keys called on a non-object");var R=[];for(var t in e)f(e,t)&&R.push(t);if(L)for(var n=0,r=O;n=t&&(e.row=Math.max(0,t-1),e.column=this.getLine(t-1).length),e},this.insert=function(e,t){if(!t||t.length===0)return e;e=this.$clipPosition(e),this.getLength()<=1&&this.$detectNewLine(t);var n=this.$split(t),r=n.splice(0,1)[0],i=n.length==0?null:n.splice(n.length-1,1)[0];return e=this.insertInLine(e,r),i!==null&&(e=this.insertNewLine(e),e=this.insertLines(e.row,n),e=this.insertInLine(e,i||"")),e},this.insertLines=function(e,t){if(t.length==0)return{row:e,column:0};if(t.length>65535){var n=this.insertLines(e,t.slice(65535));t=t.slice(0,65535)}var r=[e,0];r.push.apply(r,t),this.$lines.splice.apply(this.$lines,r);var i=new s(e,0,e+t.length,0),o={action:"insertLines",range:i,lines:t};return this._emit("change",{data:o}),n||i.end},this.insertNewLine=function(e){e=this.$clipPosition(e);var t=this.$lines[e.row]||"";this.$lines[e.row]=t.substring(0,e.column),this.$lines.splice(e.row+1,0,t.substring(e.column,t.length));var n={row:e.row+1,column:0},r={action:"insertText",range:s.fromPoints(e,n),text:this.getNewLineCharacter()};return this._emit("change",{data:r}),n},this.insertInLine=function(e,t){if(t.length==0)return e;var n=this.$lines[e.row]||"";this.$lines[e.row]=n.substring(0,e.column)+t+n.substring(e.column);var r={row:e.row,column:e.column+t.length},i={action:"insertText",range:s.fromPoints(e,r),text:t};return this._emit("change",{data:i}),r},this.remove=function(e){e.start=this.$clipPosition(e.start),e.end=this.$clipPosition(e.end);if(e.isEmpty())return e.start;var t=e.start.row,n=e.end.row;if(e.isMultiLine()){var r=e.start.column==0?t:t+1,i=n-1;e.end.column>0&&this.removeInLine(n,0,e.end.column),i>=r&&this.removeLines(r,i),r!=t&&(this.removeInLine(t,e.start.column,this.getLine(t).length),this.removeNewLine(e.start.row))}else this.removeInLine(t,e.start.column,e.end.column);return e.start},this.removeInLine=function(e,t,n){if(t==n)return;var r=new s(e,t,e,n),i=this.getLine(e),o=i.substring(t,n),u=i.substring(0,t)+i.substring(n,i.length);this.$lines.splice(e,1,u);var a={action:"removeText",range:r,text:o};return this._emit("change",{data:a}),r.start},this.removeLines=function(e,t){var n=new s(e,0,t+1,0),r=this.$lines.splice(e,t-e+1),i={action:"removeLines",range:n,nl:this.getNewLineCharacter(),lines:r};return this._emit("change",{data:i}),r},this.removeNewLine=function(e){var t=this.getLine(e),n=this.getLine(e+1),r=new s(e,t.length,e+1,0),i=t+n;this.$lines.splice(e,2,i);var o={action:"removeText",range:r,text:this.getNewLineCharacter()};this._emit("change",{data:o})},this.replace=function(e,t){if(t.length==0&&e.isEmpty())return e.start;if(t==this.getTextRange(e))return e.end;this.remove(e);if(t)var n=this.insert(e.start,t);else n=e.start;return n},this.applyDeltas=function(e){for(var t=0;t=0;t--){var n=e[t],r=s.fromPoints(n.range.start,n.range.end);n.action=="insertLines"?this.removeLines(r.start.row,r.end.row-1):n.action=="insertText"?this.remove(r):n.action=="removeLines"?this.insertLines(r.start.row,n.lines):n.action=="removeText"&&this.insert(r.start,n.text)}},this.indexToPosition=function(e,t){var n=this.$lines||this.getAllLines(),r=this.getNewLineCharacter().length;for(var i=t||0,s=n.length;i ["+this.end.row+"/"+this.end.column+"]"},this.contains=function(e,t){return this.compare(e,t)==0},this.compareRange=function(e){var t,n=e.end,r=e.start;return t=this.compare(n.row,n.column),t==1?(t=this.compare(r.row,r.column),t==1?2:t==0?1:0):t==-1?-2:(t=this.compare(r.row,r.column),t==-1?-1:t==1?42:0)},this.comparePoint=function(e){return this.compare(e.row,e.column)},this.containsRange=function(e){return this.comparePoint(e.start)==0&&this.comparePoint(e.end)==0},this.intersects=function(e){var t=this.compareRange(e);return t==-1||t==0||t==1},this.isEnd=function(e,t){return this.end.row==e&&this.end.column==t},this.isStart=function(e,t){return this.start.row==e&&this.start.column==t},this.setStart=function(e,t){typeof e=="object"?(this.start.column=e.column,this.start.row=e.row):(this.start.row=e,this.start.column=t)},this.setEnd=function(e,t){typeof e=="object"?(this.end.column=e.column,this.end.row=e.row):(this.end.row=e,this.end.column=t)},this.inside=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)||this.isStart(e,t)?!1:!0:!1},this.insideStart=function(e,t){return this.compare(e,t)==0?this.isEnd(e,t)?!1:!0:!1},this.insideEnd=function(e,t){return this.compare(e,t)==0?this.isStart(e,t)?!1:!0:!1},this.compare=function(e,t){return!this.isMultiLine()&&e===this.start.row?tthis.end.column?1:0:ethis.end.row?1:this.start.row===e?t>=this.start.column?0:-1:this.end.row===e?t<=this.end.column?0:1:0},this.compareStart=function(e,t){return this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.compareEnd=function(e,t){return this.end.row==e&&this.end.column==t?1:this.compare(e,t)},this.compareInside=function(e,t){return this.end.row==e&&this.end.column==t?1:this.start.row==e&&this.start.column==t?-1:this.compare(e,t)},this.clipRows=function(e,t){if(this.end.row>t)var n={row:t+1,column:0};if(this.start.row>t)var i={row:t+1,column:0};if(this.start.rowthis.row)return;if(n.start.row==this.row&&n.start.column>this.column)return;var r=this.row,i=this.column;t.action==="insertText"?n.start.row===r&&n.start.column<=i?n.start.row===n.end.row?i+=n.end.column-n.start.column:(i-=n.start.column,r+=n.end.row-n.start.row):n.start.row!==n.end.row&&n.start.row=i?i=n.start.column:i=Math.max(0,i-(n.end.column-n.start.column)):n.start.row!==n.end.row&&n.start.row=this.document.getLength()?(n.row=Math.max(0,this.document.getLength()-1),n.column=this.document.getLine(n.row).length):e<0?(n.row=0,n.column=0):(n.row=e,n.column=Math.min(this.document.getLine(n.row).length,Math.max(0,t))),t<0&&(n.column=0),n}}).call(s.prototype)}),define("ace/lib/lang",["require","exports","module"],function(e,t,n){t.stringReverse=function(e){return e.split("").reverse().join("")},t.stringRepeat=function(e,t){var n="";while(t>0){t&1&&(n+=e);if(t>>=1)e+=e}return n};var r=/^\s\s*/,i=/\s\s*$/;t.stringTrimLeft=function(e){return e.replace(r,"")},t.stringTrimRight=function(e){return e.replace(i,"")},t.copyObject=function(e){var t={};for(var n in e)t[n]=e[n];return t},t.copyArray=function(e){var t=[];for(var n=0,r=e.length;n="0"&&i<="9")t+=i,a();if(i==="."){t+=".";while(a()&&i>="0"&&i<="9")t+=i}if(i==="e"||i==="E"){t+=i,a();if(i==="-"||i==="+")t+=i,a();while(i>="0"&&i<="9")t+=i,a()}e=+t;if(!isNaN(e))return e;u("Bad number")},l=function(){var e,t,n="",r;if(i==='"')while(a()){if(i==='"')return a(),n;if(i==="\\"){a();if(i==="u"){r=0;for(t=0;t<4;t+=1){e=parseInt(a(),16);if(!isFinite(e))break;r=r*16+e}n+=String.fromCharCode(r)}else{if(typeof s[i]!="string")break;n+=s[i]}}else n+=i}u("Bad string")},c=function(){while(i&&i<=" ")a()},h=function(){switch(i){case"t":return a("t"),a("r"),a("u"),a("e"),!0;case"f":return a("f"),a("a"),a("l"),a("s"),a("e"),!1;case"n":return a("n"),a("u"),a("l"),a("l"),null}u("Unexpected '"+i+"'")},p,d=function(){var e=[];if(i==="["){a("["),c();if(i==="]")return a("]"),e;while(i){e.push(p()),c();if(i==="]")return a("]"),e;a(","),c()}}u("Bad array")},v=function(){var e,t={};if(i==="{"){a("{"),c();if(i==="}")return a("}"),t;while(i){e=l(),c(),a(":"),Object.hasOwnProperty.call(t,e)&&u('Duplicate key "'+e+'"'),t[e]=p(),c();if(i==="}")return a("}"),t;a(","),c()}}u("Bad object")};return p=function(){c();switch(i){case"{":return v();case"[":return d();case'"':return l();case"-":return f();default:return i>="0"&&i<="9"?f():h()}},function(e,t){var n;return o=e,r=0,i=" ",n=p(),c(),i&&u("Syntax error"),typeof t=="function"?function s(e,n){var r,i,o=e[n];if(o&&typeof o=="object")for(r in o)Object.hasOwnProperty.call(o,r)&&(i=s(o,r),i!==undefined?o[r]=i:delete o[r]);return t.call(e,n,o)}({"":n},""):n}}) \ No newline at end of file diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/jsonlint/README.md b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/jsonlint/README.md deleted file mode 100644 index e31e1906241..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/jsonlint/README.md +++ /dev/null @@ -1,62 +0,0 @@ -JSON Lint -========= - -A pure [JavaScript version](http://zaach.github.com/jsonlint/) of the service provided at [jsonlint.com](http://jsonlint.com). - -## Command line interface -Install jsonlint with npm to use the command line interface: - - npm install jsonlint -g - -Validate a file like so: - - jsonlint myfile.json - -or pipe input into stdin: - - cat myfile.json | jsonlint - -jsonlint will either report a syntax error with details or pretty print the source if it is valid. - -### Options - - $ jsonlint -h - - usage: jsonlint [options] - - file file to parse; otherwise uses stdin - - options: - -v, --version print version and exit - -s, --sort-keys sort object keys - -i, --in-place overwrite the file - -t CHAR, --indent CHAR character(s) to use for indentation - -c, --compact compact error display - -V, --validate a JSON schema to use for validation - -e, --environment which specification of JSON Schema the validation file uses - - -## Module interface - -I'm not sure why you wouldn't use the built in `JSON.parse` but you can use jsonlint from a CommonJS module: - - var jsonlint = require("jsonlint"); - - jsonlint.parse('{"creative?": false}'); - -It returns the parsed object or throws an `Error`. - -## Vim Plugins - -* [Syntastic](http://www.vim.org/scripts/script.php?script_id=2736) -* [sourcebeautify](http://www.vim.org/scripts/script.php?script_id=4079) - -## MIT License - -Copyright (C) 2012 Zachary Carter - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/jsonlint/jsonlint.js b/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/jsonlint/jsonlint.js deleted file mode 100644 index 598c18c2a64..00000000000 --- a/application/extensions/yii-jsoneditor/jsoneditor-2.3.6/lib/jsonlint/jsonlint.js +++ /dev/null @@ -1,432 +0,0 @@ -/* Jison generated parser */ -var jsonlint = (function(){ -var parser = {trace: function trace() { }, -yy: {}, -symbols_: {"error":2,"JSONString":3,"STRING":4,"JSONNumber":5,"NUMBER":6,"JSONNullLiteral":7,"NULL":8,"JSONBooleanLiteral":9,"TRUE":10,"FALSE":11,"JSONText":12,"JSONValue":13,"EOF":14,"JSONObject":15,"JSONArray":16,"{":17,"}":18,"JSONMemberList":19,"JSONMember":20,":":21,",":22,"[":23,"]":24,"JSONElementList":25,"$accept":0,"$end":1}, -terminals_: {2:"error",4:"STRING",6:"NUMBER",8:"NULL",10:"TRUE",11:"FALSE",14:"EOF",17:"{",18:"}",21:":",22:",",23:"[",24:"]"}, -productions_: [0,[3,1],[5,1],[7,1],[9,1],[9,1],[12,2],[13,1],[13,1],[13,1],[13,1],[13,1],[13,1],[15,2],[15,3],[20,3],[19,1],[19,3],[16,2],[16,3],[25,1],[25,3]], -performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { - -var $0 = $$.length - 1; -switch (yystate) { -case 1: // replace escaped characters with actual character - this.$ = yytext.replace(/\\(\\|")/g, "$"+"1") - .replace(/\\n/g,'\n') - .replace(/\\r/g,'\r') - .replace(/\\t/g,'\t') - .replace(/\\v/g,'\v') - .replace(/\\f/g,'\f') - .replace(/\\b/g,'\b'); - -break; -case 2:this.$ = Number(yytext); -break; -case 3:this.$ = null; -break; -case 4:this.$ = true; -break; -case 5:this.$ = false; -break; -case 6:return this.$ = $$[$0-1]; -break; -case 13:this.$ = {}; -break; -case 14:this.$ = $$[$0-1]; -break; -case 15:this.$ = [$$[$0-2], $$[$0]]; -break; -case 16:this.$ = {}; this.$[$$[$0][0]] = $$[$0][1]; -break; -case 17:this.$ = $$[$0-2]; $$[$0-2][$$[$0][0]] = $$[$0][1]; -break; -case 18:this.$ = []; -break; -case 19:this.$ = $$[$0-1]; -break; -case 20:this.$ = [$$[$0]]; -break; -case 21:this.$ = $$[$0-2]; $$[$0-2].push($$[$0]); -break; -} -}, -table: [{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],12:1,13:2,15:7,16:8,17:[1,14],23:[1,15]},{1:[3]},{14:[1,16]},{14:[2,7],18:[2,7],22:[2,7],24:[2,7]},{14:[2,8],18:[2,8],22:[2,8],24:[2,8]},{14:[2,9],18:[2,9],22:[2,9],24:[2,9]},{14:[2,10],18:[2,10],22:[2,10],24:[2,10]},{14:[2,11],18:[2,11],22:[2,11],24:[2,11]},{14:[2,12],18:[2,12],22:[2,12],24:[2,12]},{14:[2,3],18:[2,3],22:[2,3],24:[2,3]},{14:[2,4],18:[2,4],22:[2,4],24:[2,4]},{14:[2,5],18:[2,5],22:[2,5],24:[2,5]},{14:[2,1],18:[2,1],21:[2,1],22:[2,1],24:[2,1]},{14:[2,2],18:[2,2],22:[2,2],24:[2,2]},{3:20,4:[1,12],18:[1,17],19:18,20:19},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:23,15:7,16:8,17:[1,14],23:[1,15],24:[1,21],25:22},{1:[2,6]},{14:[2,13],18:[2,13],22:[2,13],24:[2,13]},{18:[1,24],22:[1,25]},{18:[2,16],22:[2,16]},{21:[1,26]},{14:[2,18],18:[2,18],22:[2,18],24:[2,18]},{22:[1,28],24:[1,27]},{22:[2,20],24:[2,20]},{14:[2,14],18:[2,14],22:[2,14],24:[2,14]},{3:20,4:[1,12],20:29},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:30,15:7,16:8,17:[1,14],23:[1,15]},{14:[2,19],18:[2,19],22:[2,19],24:[2,19]},{3:5,4:[1,12],5:6,6:[1,13],7:3,8:[1,9],9:4,10:[1,10],11:[1,11],13:31,15:7,16:8,17:[1,14],23:[1,15]},{18:[2,17],22:[2,17]},{18:[2,15],22:[2,15]},{22:[2,21],24:[2,21]}], -defaultActions: {16:[2,6]}, -parseError: function parseError(str, hash) { - throw new Error(str); -}, -parse: function parse(input) { - var self = this, - stack = [0], - vstack = [null], // semantic value stack - lstack = [], // location stack - table = this.table, - yytext = '', - yylineno = 0, - yyleng = 0, - recovering = 0, - TERROR = 2, - EOF = 1; - - //this.reductionCount = this.shiftCount = 0; - - this.lexer.setInput(input); - this.lexer.yy = this.yy; - this.yy.lexer = this.lexer; - if (typeof this.lexer.yylloc == 'undefined') - this.lexer.yylloc = {}; - var yyloc = this.lexer.yylloc; - lstack.push(yyloc); - - if (typeof this.yy.parseError === 'function') - this.parseError = this.yy.parseError; - - function popStack (n) { - stack.length = stack.length - 2*n; - vstack.length = vstack.length - n; - lstack.length = lstack.length - n; - } - - function lex() { - var token; - token = self.lexer.lex() || 1; // $end = 1 - // if token isn't its numeric value, convert - if (typeof token !== 'number') { - token = self.symbols_[token] || token; - } - return token; - } - - var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected; - while (true) { - // retreive state number from top of stack - state = stack[stack.length-1]; - - // use default actions if available - if (this.defaultActions[state]) { - action = this.defaultActions[state]; - } else { - if (symbol == null) - symbol = lex(); - // read action for current state and first input - action = table[state] && table[state][symbol]; - } - - // handle parse error - _handle_error: - if (typeof action === 'undefined' || !action.length || !action[0]) { - - if (!recovering) { - // Report error - expected = []; - for (p in table[state]) if (this.terminals_[p] && p > 2) { - expected.push("'"+this.terminals_[p]+"'"); - } - var errStr = ''; - if (this.lexer.showPosition) { - errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'"; - } else { - errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + - (symbol == 1 /*EOF*/ ? "end of input" : - ("'"+(this.terminals_[symbol] || symbol)+"'")); - } - this.parseError(errStr, - {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); - } - - // just recovered from another error - if (recovering == 3) { - if (symbol == EOF) { - throw new Error(errStr || 'Parsing halted.'); - } - - // discard current lookahead and grab another - yyleng = this.lexer.yyleng; - yytext = this.lexer.yytext; - yylineno = this.lexer.yylineno; - yyloc = this.lexer.yylloc; - symbol = lex(); - } - - // try to recover from error - while (1) { - // check for error recovery rule in this state - if ((TERROR.toString()) in table[state]) { - break; - } - if (state == 0) { - throw new Error(errStr || 'Parsing halted.'); - } - popStack(1); - state = stack[stack.length-1]; - } - - preErrorSymbol = symbol; // save the lookahead token - symbol = TERROR; // insert generic error symbol as new lookahead - state = stack[stack.length-1]; - action = table[state] && table[state][TERROR]; - recovering = 3; // allow 3 real symbols to be shifted before reporting a new error - } - - // this shouldn't happen, unless resolve defaults are off - if (action[0] instanceof Array && action.length > 1) { - throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); - } - - switch (action[0]) { - - case 1: // shift - //this.shiftCount++; - - stack.push(symbol); - vstack.push(this.lexer.yytext); - lstack.push(this.lexer.yylloc); - stack.push(action[1]); // push state - symbol = null; - if (!preErrorSymbol) { // normal execution/no error - yyleng = this.lexer.yyleng; - yytext = this.lexer.yytext; - yylineno = this.lexer.yylineno; - yyloc = this.lexer.yylloc; - if (recovering > 0) - recovering--; - } else { // error just occurred, resume old lookahead f/ before error - symbol = preErrorSymbol; - preErrorSymbol = null; - } - break; - - case 2: // reduce - //this.reductionCount++; - - len = this.productions_[action[1]][1]; - - // perform semantic action - yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 - // default location, uses first token for firsts, last for lasts - yyval._$ = { - first_line: lstack[lstack.length-(len||1)].first_line, - last_line: lstack[lstack.length-1].last_line, - first_column: lstack[lstack.length-(len||1)].first_column, - last_column: lstack[lstack.length-1].last_column - }; - r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); - - if (typeof r !== 'undefined') { - return r; - } - - // pop off stack - if (len) { - stack = stack.slice(0,-1*len*2); - vstack = vstack.slice(0, -1*len); - lstack = lstack.slice(0, -1*len); - } - - stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) - vstack.push(yyval.$); - lstack.push(yyval._$); - // goto new state = table[STATE][NONTERMINAL] - newState = table[stack[stack.length-2]][stack[stack.length-1]]; - stack.push(newState); - break; - - case 3: // accept - return true; - } - - } - - return true; -}}; -/* Jison generated lexer */ -var lexer = (function(){ -var lexer = ({EOF:1, -parseError:function parseError(str, hash) { - if (this.yy.parseError) { - this.yy.parseError(str, hash); - } else { - throw new Error(str); - } - }, -setInput:function (input) { - this._input = input; - this._more = this._less = this.done = false; - this.yylineno = this.yyleng = 0; - this.yytext = this.matched = this.match = ''; - this.conditionStack = ['INITIAL']; - this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; - return this; - }, -input:function () { - var ch = this._input[0]; - this.yytext+=ch; - this.yyleng++; - this.match+=ch; - this.matched+=ch; - var lines = ch.match(/\n/); - if (lines) this.yylineno++; - this._input = this._input.slice(1); - return ch; - }, -unput:function (ch) { - this._input = ch + this._input; - return this; - }, -more:function () { - this._more = true; - return this; - }, -less:function (n) { - this._input = this.match.slice(n) + this._input; - }, -pastInput:function () { - var past = this.matched.substr(0, this.matched.length - this.match.length); - return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); - }, -upcomingInput:function () { - var next = this.match; - if (next.length < 20) { - next += this._input.substr(0, 20-next.length); - } - return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); - }, -showPosition:function () { - var pre = this.pastInput(); - var c = new Array(pre.length + 1).join("-"); - return pre + this.upcomingInput() + "\n" + c+"^"; - }, -next:function () { - if (this.done) { - return this.EOF; - } - if (!this._input) this.done = true; - - var token, - match, - tempMatch, - index, - col, - lines; - if (!this._more) { - this.yytext = ''; - this.match = ''; - } - var rules = this._currentRules(); - for (var i=0;i < rules.length; i++) { - tempMatch = this._input.match(this.rules[rules[i]]); - if (tempMatch && (!match || tempMatch[0].length > match[0].length)) { - match = tempMatch; - index = i; - if (!this.options.flex) break; - } - } - if (match) { - lines = match[0].match(/\n.*/g); - if (lines) this.yylineno += lines.length; - this.yylloc = {first_line: this.yylloc.last_line, - last_line: this.yylineno+1, - first_column: this.yylloc.last_column, - last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length} - this.yytext += match[0]; - this.match += match[0]; - this.yyleng = this.yytext.length; - this._more = false; - this._input = this._input.slice(match[0].length); - this.matched += match[0]; - token = this.performAction.call(this, this.yy, this, rules[index],this.conditionStack[this.conditionStack.length-1]); - if (this.done && this._input) this.done = false; - if (token) return token; - else return; - } - if (this._input === "") { - return this.EOF; - } else { - this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), - {text: "", token: null, line: this.yylineno}); - } - }, -lex:function lex() { - var r = this.next(); - if (typeof r !== 'undefined') { - return r; - } else { - return this.lex(); - } - }, -begin:function begin(condition) { - this.conditionStack.push(condition); - }, -popState:function popState() { - return this.conditionStack.pop(); - }, -_currentRules:function _currentRules() { - return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; - }, -topState:function () { - return this.conditionStack[this.conditionStack.length-2]; - }, -pushState:function begin(condition) { - this.begin(condition); - }}); -lexer.options = {}; -lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { - -var YYSTATE=YY_START -switch($avoiding_name_collisions) { -case 0:/* skip whitespace */ -break; -case 1:return 6 -break; -case 2:yy_.yytext = yy_.yytext.substr(1,yy_.yyleng-2); return 4 -break; -case 3:return 17 -break; -case 4:return 18 -break; -case 5:return 23 -break; -case 6:return 24 -break; -case 7:return 22 -break; -case 8:return 21 -break; -case 9:return 10 -break; -case 10:return 11 -break; -case 11:return 8 -break; -case 12:return 14 -break; -case 13:return 'INVALID' -break; -} -}; -lexer.rules = [/^(?:\s+)/,/^(?:(-?([0-9]|[1-9][0-9]+))(\.[0-9]+)?([eE][-+]?[0-9]+)?\b)/,/^(?:"(?:\\[\\"bfnrt/]|\\u[a-fA-F0-9]{4}|[^\\\0-\x09\x0a-\x1f"])*")/,/^(?:\{)/,/^(?:\})/,/^(?:\[)/,/^(?:\])/,/^(?:,)/,/^(?::)/,/^(?:true\b)/,/^(?:false\b)/,/^(?:null\b)/,/^(?:$)/,/^(?:.)/]; -lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13],"inclusive":true}}; - - -; -return lexer;})() -parser.lexer = lexer; -return parser; -})(); -if (typeof require !== 'undefined' && typeof exports !== 'undefined') { -exports.parser = jsonlint; -exports.parse = function () { return jsonlint.parse.apply(jsonlint, arguments); } -exports.main = function commonjsMain(args) { - if (!args[1]) - throw new Error('Usage: '+args[0]+' FILE'); - if (typeof process !== 'undefined') { - var source = require('fs').readFileSync(require('path').join(process.cwd(), args[1]), "utf8"); - } else { - var cwd = require("file").path(require("file").cwd()); - var source = cwd.join(args[1]).read({charset: "utf-8"}); - } - return exports.parser.parse(source); -} -if (typeof module !== 'undefined' && require.main === module) { - exports.main(typeof process !== 'undefined' ? process.argv.slice(1) : require("system").args); -} -} \ No newline at end of file diff --git a/application/helpers/common_helper.php b/application/helpers/common_helper.php index fc558a93c36..4f0e2732584 100644 --- a/application/helpers/common_helper.php +++ b/application/helpers/common_helper.php @@ -3868,137 +3868,6 @@ function getArrayFilterExcludesCascadesForGroup($surveyid, $gid="", $output="qid -/** -* getArrayFiltersForQuestion($qid) finds out if a question has an array_filter attribute and what codes where selected on target question -* @return returns an array of codes that were selected else returns false -*/ -function getArrayFiltersForQuestion($qid) -{ - static $cache = array(); - - $session = App()->surveySessionManager->current; - // TODO: Check list_filter values to make sure questions are previous? - $qid=sanitize_int($qid); - if (isset($cache[$qid])) return $cache[$qid]; - - $attributes = \QuestionAttribute::model()->getQuestionAttributes($qid); - if (isset($attributes['array_filter'])) { - $val = $attributes['array_filter']; // Get the Value of the Attribute ( should be a previous question's title in same group ) - foreach ($session->getFieldArray() as $fields) - { - if ($fields[2] == $val) - { - // we found the target question, now we need to know what the answers where, we know its a multi! - $fields[0]=sanitize_int($fields[0]); - //$query = "SELECT title FROM ".db_table_name('questions')." where parent_qid='{$fields[0]}' AND language='".Yii::app()->session[$surveyid]['s_lang']."' order by question_order"; - $qresult=Question::model()->findAllByAttributes(array("parent_qid"=> $fields[0]), array('order' => "question_order")); - $selected = array(); - //while ($code = $qresult->fetchRow()) - foreach ($qresult->readAll() as $code) - { - if (Yii::app()->session[$fields[1].$code['title']] == "Y" - || Yii::app()->session[$fields[1]] == $code['title']) array_push($selected,$code['title']); - } - - //Now we also need to find out if (a) the question had "other" enabled, and (b) if that was selected - //$query = "SELECT other FROM ".db_table_name('questions')." where qid='{$fields[0]}'"; - $qresult=Question::model()->findAllByAttributes(array("qid"=>$fields[0])); - foreach ($qresult->readAll() as $row) {$other=$row['other'];} - if($other == "Y") - { - if(Yii::app()->session[$fields[1].'other'] && Yii::app()->session[$fields[1].'other'] !="") {array_push($selected, "other");} - } - $cache[$qid] = $selected; - return $cache[$qid]; - } - } - $cache[$qid] = false; - return $cache[$qid]; - } - $cache[$qid] = false; - return $cache[$qid]; -} - -/** -* getArrayFilterExcludesForQuestion($qid) finds out if a question has an array_filter_exclude attribute and what codes where selected on target question -* @return returns an array of codes that were selected else returns false -*/ -function getArrayFilterExcludesForQuestion($qid) -{ - static $cascadesCache = array(); - static $cache = array(); - - $session = App()->surveySessionManager->current; - // TODO: Check list_filter values to make sure questions are previous? - // $surveyid = Yii::app()->getConfig('sid'); - $surveyid=returnGlobal('sid'); - $qid=sanitize_int($qid); - - if (isset($cache[$qid])) return $cache[$qid]; - - $attributes = \QuestionAttribute::model()->getQuestionAttributes($qid); - $excludevals=array(); - if (isset($attributes['array_filter_exclude'])) // We Found a array_filter_exclude attribute - { - $selected=array(); - $excludevals[] = $attributes['array_filter_exclude']; // Get the Value of the Attribute ( should be a previous question's title in same group ) - /* Find any cascades and place them in the $excludevals array*/ - if (!isset($cascadesCache[$surveyid])) { - $cascadesCache[$surveyid] = getArrayFilterExcludesCascadesForGroup($surveyid, "", "title"); - } - $array_filterXqs_cascades = $cascadesCache[$surveyid]; - - if(isset($array_filterXqs_cascades[$qid])) - { - foreach($array_filterXqs_cascades[$qid] as $afc) - { - $excludevals[]=array("value"=>$afc); - - } - } - /* For each $val (question title) that applies to this, check what values exist and add them to the $selected array */ - foreach ($excludevals as $val) - { - foreach ($session->getFieldArray() as $fields) //iterate through every question in the survey - { - if ($fields[2] == $val) - { - // we found the target question, now we need to know what the answers were! - $fields[0]=sanitize_int($fields[0]); - $query = "SELECT title FROM {{questions}} where parent_qid='{$fields[0]}' AND language='{$session->language}' order by question_order"; - $qresult = dbExecuteAssoc($query); //Checked - foreach ($qresult->readAll() as $code) - { - if (isset(Yii::app()->session[$fields[1]])) - if ((isset(Yii::app()->session[$fields[1].$code['title']]) && Yii::app()->session[$fields[1].$code['title']] == "Y") - || Yii::app()->session[$fields[1]] == $code['title']) - array_push($selected,$code['title']); - } - //Now we also need to find out if (a) the question had "other" enabled, and (b) if that was selected - $query = "SELECT other FROM {{questions}} where qid='{$fields[0]}'"; - $qresult = dbExecuteAssoc($query); - foreach ($qresult->readAll() as $row) {$other=$row['other'];} - if($other == "Y") - { - if(Yii::app()->session[$fields[1].'other'] != "") {array_push($selected, "other");} - } - } - } - } - if(count($selected) > 0) - { - $cache[$qid] = $selected; - return $cache[$qid]; - } else { - $cache[$qid] = false; - return $cache[$qid]; - } - } - $cache[$qid] = false; - return $cache[$qid]; -} - - function CSVEscape($sString) { diff --git a/composer.json b/composer.json index a5675ea6ea1..f5b9386d870 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,8 @@ "bower-asset/select2-bootstrap-css": "1.*", "bower-asset/jquery-ui": "1.*", "bower-asset/jqueryui-timepicker-addon": "1.5.*", - "studio-42/elfinder": "2.1.x-dev" + "studio-42/elfinder": "2.1.x-dev", + "bower-asset/jsoneditor": "4.*" }, "require-dev" : { diff --git a/composer.lock b/composer.lock index f103d5571e5..003d2e3e2fa 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "d5fed6c890dda620cb2393357d9a0c03", + "hash": "47ce42255ade3527f70aeb2af975cfe4", "packages": [ { "name": "2amigos/yiiwheels", @@ -304,6 +304,40 @@ ] } }, + { + "name": "bower-asset/jsoneditor", + "version": "v4.2.1", + "source": { + "type": "git", + "url": "https://github.com/josdejong/jsoneditor.git", + "reference": "c6642a7444bd92935fbfb0a71ca1e48c50444502" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/josdejong/jsoneditor/zipball/c6642a7444bd92935fbfb0a71ca1e48c50444502", + "reference": "c6642a7444bd92935fbfb0a71ca1e48c50444502", + "shasum": "" + }, + "type": "bower-asset-library", + "extra": { + "bower-asset-main": [ + "./dist/jsoneditor.min.js", + "./dist/jsoneditor.min.css" + ], + "bower-asset-ignore": [ + "misc", + "node_modules", + "test", + "tools", + "gulpfile.js", + "npm-debug.log", + ".idea", + ".npmignore", + ".gitignore" + ] + }, + "description": "A web-based tool to view, edit and format JSON" + }, { "name": "bower-asset/papaparse", "version": "4.1.0", @@ -1084,7 +1118,7 @@ }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/8a719102d2c3ad496530db6f524da222bccf01d4", + "url": "https://api.github.com/repos/PHPMailer/PHPMailer/zipball/f90669c7dd41a858c4202ee5f20d714a4f3a4d67", "reference": "8a719102d2c3ad496530db6f524da222bccf01d4", "shasum": "" },