[!!!][TASK] Remove content object JSMENU 57/53457/4
authorGeorg Ringer <georg.ringer@gmail.com>
Wed, 12 Jul 2017 17:49:28 +0000 (19:49 +0200)
committerSusanne Moog <susanne.moog@typo3.org>
Mon, 17 Jul 2017 07:41:19 +0000 (09:41 +0200)
Using the JSMENU is outdated and therefore removed.

Resolves: #81847
Releases: master
Change-Id: Ifb9465194578efb56f3c8d229f09ef12e7893c3c
Reviewed-on: https://review.typo3.org/53457
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Hannes Lau <office@hanneslau.de>
Tested-by: Benjamin Kluge <b.kluge@neusta.de>
Reviewed-by: Benjamin Kluge <b.kluge@neusta.de>
Reviewed-by: Susanne Moog <susanne.moog@typo3.org>
Tested-by: Susanne Moog <susanne.moog@typo3.org>
typo3/sysext/core/Documentation/Changelog/master/Breaking-81847-RemoveJSMENU.rst [new file with mode: 0644]
typo3/sysext/frontend/Classes/ContentObject/Menu/JavaScriptMenuContentObject.php [deleted file]
typo3/sysext/frontend/Classes/ContentObject/Menu/MenuContentObjectFactory.php
typo3/sysext/frontend/Classes/Controller/TypoScriptFrontendController.php
typo3/sysext/frontend/Resources/Public/JavaScript/jsfunc.menu.js [deleted file]
typo3/sysext/t3editor/Resources/Private/tsref.xml
typo3/sysext/t3editor/Resources/Public/JavaScript/parse_typoscript/tokenizetyposcript.js

diff --git a/typo3/sysext/core/Documentation/Changelog/master/Breaking-81847-RemoveJSMENU.rst b/typo3/sysext/core/Documentation/Changelog/master/Breaking-81847-RemoveJSMENU.rst
new file mode 100644 (file)
index 0000000..cc084f1
--- /dev/null
@@ -0,0 +1,49 @@
+.. include:: ../../Includes.txt
+
+================================
+Breaking: #81847 - Remove JSMENU
+================================
+
+See :issue:`81847`
+
+Description
+===========
+
+The content objects JSMENU and JSMENUITEM to create a jump menu have been removed. The used JavaScript is totally outdated and has not really been touched since its creation more than 10 years ago.
+
+If this kind of menu is needed it can be easily achieved with a TMENU as well:
+
+.. code-block:: typoscript
+
+   lib.menu = HMENU
+   lib.menu {
+      1 = TMENU
+      1 {
+         wrap = <select onchange="window.location=this.options[this.selectedIndex].value">|</select>
+
+         NO {
+            doNotLinkIt = 1
+            stdWrap.cObject = COA
+               stdWrap.cObject {
+               10 = TEXT
+               10 {
+                  wrap = <option value="{getIndpEnv:TYPO3_SITE_URL}|">
+                  insertData = 1
+                  typolink {
+                     parameter.field = uid
+                     returnLast = url
+                     htmlSpecialChars = 1
+                  }
+               }
+               20 = TEXT
+               20 {
+                  field = subtitle//title
+                  htmlSpecialChars = 1
+                  wrap =  |</option>
+               }
+            }
+         }
+      }
+   }
+
+.. index:: Frontend, TypoScript
diff --git a/typo3/sysext/frontend/Classes/ContentObject/Menu/JavaScriptMenuContentObject.php b/typo3/sysext/frontend/Classes/ContentObject/Menu/JavaScriptMenuContentObject.php
deleted file mode 100644 (file)
index 3912586..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-<?php
-namespace TYPO3\CMS\Frontend\ContentObject\Menu;
-
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
-use TYPO3\CMS\Core\Utility\GeneralUtility;
-use TYPO3\CMS\Core\Utility\MathUtility;
-
-/**
- * JavaScript/Selectorbox based menus
- */
-class JavaScriptMenuContentObject extends AbstractMenuContentObject
-{
-    /**
-     * @var int
-     */
-    public $levels = 0;
-
-    /**
-     * @var string
-     */
-    public $JSVarName = '';
-
-    /**
-     * @var string
-     */
-    public $JSMenuName = '';
-
-    /**
-     * Creates the HTML (mixture of a <form> and a JavaScript section) for the JavaScript menu (basically an array of selector boxes with onchange handlers)
-     *
-     * @return string The HTML code for the menu
-     */
-    public function writeMenu()
-    {
-        if (!$this->id) {
-            return '';
-        }
-
-        $levels = MathUtility::forceIntegerInRange($this->mconf['levels'], 1, 5);
-        $this->levels = $levels;
-        $uniqueParam = GeneralUtility::shortMD5(microtime(), 5);
-        $this->JSVarName = 'eid' . $uniqueParam;
-        $this->JSMenuName = $this->mconf['menuName'] ?: 'JSmenu' . $uniqueParam;
-        $JScode = '
-var ' . $this->JSMenuName . ' = new JSmenu(' . $levels . ', ' . GeneralUtility::quoteJSvalue($this->JSMenuName . 'Form') . ');';
-        for ($a = 1; $a <= $levels; $a++) {
-            $JScode .= '
-var ' . $this->JSVarName . $a . '=0;';
-        }
-        $JScode .= $this->generate_level($levels, 1, $this->id, $this->menuArr, $this->MP_array) . LF;
-        $GLOBALS['TSFE']->additionalHeaderData['JSMenuCode'] = '<script type="text/javascript" src="' . $GLOBALS['TSFE']->absRefPrefix . ExtensionManagementUtility::siteRelPath('frontend') . 'Resources/Public/JavaScript/jsfunc.menu.js"></script>';
-        $GLOBALS['TSFE']->additionalJavaScript['JSCode'] .= $JScode;
-        // Printing:
-        $allFormCode = '';
-        for ($a = 1; $a <= $this->levels; $a++) {
-            $formCode = '';
-            $levelConf = $this->mconf[$a . '.'];
-            $length = $levelConf['width'] ?: 14;
-            $lengthStr = '';
-            for ($b = 0; $b < $length; $b++) {
-                $lengthStr .= '_';
-            }
-            $height = $levelConf['elements'] ?: 5;
-            $formCode .= '<select name="selector' . $a . '" onchange="' . $this->JSMenuName . '.act(' . $a . ');"' . ($levelConf['additionalParams'] ? ' ' . $levelConf['additionalParams'] : '') . '>';
-            for ($b = 0; $b < $height; $b++) {
-                $formCode .= '<option value="0">';
-                if ($b === 0) {
-                    $formCode .= $lengthStr;
-                }
-                $formCode .= '</option>';
-            }
-            $formCode .= '</select>';
-            $allFormCode .= $this->WMcObj->wrap($formCode, $levelConf['wrap']);
-        }
-        $formContent = $this->WMcObj->wrap($allFormCode, $this->mconf['wrap']);
-        $formCode = '<form action="" method="post" style="margin: 0 0 0 0;" name="' . $this->JSMenuName . 'Form">' . $formContent . '</form>';
-        $formCode .= '<script type="text/javascript"> /*<![CDATA[*/ ' . $this->JSMenuName . '.writeOut(1,' . $this->JSMenuName . '.openID,1); /*]]>*/ </script>';
-        return $this->WMcObj->wrap($formCode, $this->mconf['wrapAfterTags']);
-    }
-
-    /**
-     * Generates a number of lines of JavaScript code for a menu level.
-     * Calls itself recursively for additional levels.
-     *
-     * @param int $levels Number of levels to generate
-     * @param int $count Current level being generated - and if this number is less than $levels it will call itself recursively with $count incremented
-     * @param int $pid Page id of the starting point.
-     * @param array|string $menuItemArray $this->menuArr passed along
-     * @param array $MP_array Previous MP vars
-     * @return string JavaScript code lines.
-     * @access private
-     */
-    public function generate_level($levels, $count, $pid, $menuItemArray = '', $MP_array = [])
-    {
-        $count = (int)$count;
-        $levelConf = $this->mconf[$count . '.'];
-        // Translate PID to a mount page, if any:
-        $mount_info = $this->sys_page->getMountPointInfo($pid);
-        if (is_array($mount_info)) {
-            $MP_array[] = $mount_info['MPvar'];
-            $pid = $mount_info['mount_pid'];
-        }
-        // UIDs to ban:
-        $banUidArray = $this->getBannedUids();
-        // Initializing variables:
-        $var = $this->JSVarName;
-        $menuName = $this->JSMenuName;
-        $parent = $count === 1 ? 0 : $var . ($count - 1);
-        $prev = 0;
-        $c = 0;
-        $codeLines = '';
-        $menuItems = is_array($menuItemArray) ? $menuItemArray : $this->sys_page->getMenu($pid);
-        foreach ($menuItems as $uid => $data) {
-            // $data['_MP_PARAM'] contains MP param for overlay mount points (MPs with "substitute this page" set)
-            // if present: add param to copy of MP array (copy used for that submenu branch only)
-            $MP_array_sub = $MP_array;
-            if (array_key_exists('_MP_PARAM', $data) && $data['_MP_PARAM']) {
-                $MP_array_sub[] = $data['_MP_PARAM'];
-            }
-            // Set "&MP=" var:
-            $MP_var = implode(',', $MP_array_sub);
-            $MP_params = $MP_var ? '&MP=' . rawurlencode($MP_var) : '';
-            // If item is a spacer, $spacer is set
-            $spacer = GeneralUtility::inList($this->spacerIDList, $data['doktype']);
-            // If the spacer-function is not enabled, spacers will not enter the $menuArr
-            if ($this->mconf['SPC'] || !$spacer) {
-                // Page may not be 'not_in_menu' or 'Backend User Section' + not in banned uid's
-                if (!GeneralUtility::inList($this->doktypeExcludeList, $data['doktype']) && (!$data['nav_hide'] || $this->conf['includeNotInMenu']) && !in_array($uid, $banUidArray, false)) {
-                    if ($count < $levels) {
-                        $addLines = $this->generate_level($levels, $count + 1, $data['uid'], '', $MP_array_sub);
-                    } else {
-                        $addLines = '';
-                    }
-                    $title = $data['title'];
-                    $url = '';
-                    $target = '';
-                    if (!$addLines && !$levelConf['noLink'] || $levelConf['alwaysLink']) {
-                        $LD = $this->menuTypoLink($data, $this->mconf['target'], '', '', [], $MP_params, $this->mconf['forceTypeValue']);
-                        // If access restricted pages should be shown in menus, change the link of such pages to link to a redirection page:
-                        $this->changeLinksForAccessRestrictedPages($LD, $data, $this->mconf['target'], $this->mconf['forceTypeValue']);
-                        $url = $this->getTypoScriptFrontendController()->baseUrlWrap($LD['totalURL']);
-                        $target = $LD['target'];
-                    }
-                    $codeLines .= LF . $var . $count . '=' . $menuName . '.add(' . $parent . ',' . $prev . ',0,' . GeneralUtility::quoteJSvalue($title) . ',' . GeneralUtility::quoteJSvalue($url) . ',' . GeneralUtility::quoteJSvalue($target) . ');';
-                    // If the active one should be chosen...
-                    $active = $levelConf['showActive'] && $this->isActive($data['uid'], $MP_var);
-                    // If the first item should be shown
-                    $first = !$c && $levelConf['showFirst'];
-                    // do it...
-                    if ($active || $first) {
-                        if ($count === 1) {
-                            $codeLines .= LF . $menuName . '.openID = ' . $var . $count . ';';
-                        } else {
-                            $codeLines .= LF . $menuName . '.entry[' . $parent . '].openID = ' . $var . $count . ';';
-                        }
-                    }
-                    // Add submenu...
-                    $codeLines .= $addLines;
-                    $prev = $var . $count;
-                    $c++;
-                }
-            }
-        }
-        if ($this->mconf['firstLabelGeneral'] && !$levelConf['firstLabel']) {
-            $levelConf['firstLabel'] = $this->mconf['firstLabelGeneral'];
-        }
-        if ($levelConf['firstLabel'] && $codeLines) {
-            $codeLines .= LF . $menuName . '.defTopTitle[' . $count . '] = ' . GeneralUtility::quoteJSvalue($levelConf['firstLabel']) . ';';
-        }
-        return $codeLines;
-    }
-}
index 48fdb43..6458eaa 100644 (file)
@@ -33,7 +33,6 @@ class MenuContentObjectFactory implements SingletonInterface
         'GMENU' => GraphicalMenuContentObject::class,
         'TMENU' => TextMenuContentObject::class,
         'IMGMENU' => ImageMenuContentObject::class,
-        'JSMENU' => JavaScriptMenuContentObject::class,
     ];
 
     /**
index a12ddbb..5b0ecdc 100644 (file)
@@ -392,10 +392,6 @@ class TypoScriptFrontendController
      *
      * Keys in use:
      *
-     * JSFormValidate: <script type="text/javascript" src="'.$GLOBALS["TSFE"]->absRefPrefix.'typo3/sysext/frontend/Resources/Public/JavaScript/jsfunc.validateform.js"></script>
-     * JSMenuCode, JSMenuCode_menu: JavaScript for the JavaScript menu
-     * JSCode: reserved
-     *
      * used to accumulate additional HTML-code for the header-section,
      * <head>...</head>. Insert either associative keys (like
      * additionalHeaderData['myStyleSheet'], see reserved keys above) or num-keys
diff --git a/typo3/sysext/frontend/Resources/Public/JavaScript/jsfunc.menu.js b/typo3/sysext/frontend/Resources/Public/JavaScript/jsfunc.menu.js
deleted file mode 100644 (file)
index b055ce4..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * This file is part of the TYPO3 CMS project.
- *
- * It is free software; you can redistribute it and/or modify it under
- * the terms of the GNU General Public License, either version 2
- * of the License, or any later version.
- *
- * For the full copyright and license information, please read the
- * LICENSE.txt file that was distributed with this source code.
- *
- * The TYPO3 project - inspiring people to share!
- */
-
-
-function JSmenuItem (owner, id, nextItem, parent, openID, title, url, target) {
-       this.owner = owner;
-       this.id = id;
-       this.nextItem = nextItem;
-       this.child = 0;
-       this.openID = openID;
-       this.parent = parent;
-       this.title = title;
-       this.url = url;
-       this.target = target;
-}
-function JSmenu (levels,formname) {
-       this.name = name,
-       this.levels = levels;
-       this.formname = formname;
-
-       this.openID = 0;
-
-       this.entry = new JSmenuItem (this);
-       this.count = 0;
-       this.defTopTitle = new Array();
-       this.add = JSmenuAddItem;                       // Tilføjer Item
-       this.writeOut = JSmenuWrite;
-       this.act = JSactivate;
-}
-function JSmenuAddItem (parent,prevItem,openID,title,url,target) {
-       this.count++;
-       var entryID = this.count;
-       this.entry[entryID] = new JSmenuItem (this, entryID, 0, parent, openID, title, url, target);
-       if (prevItem) {
-               this.entry[prevItem].nextItem = entryID;
-       } else if(parent) {
-               this.entry[parent].child = entryID;
-       }
-       return entryID;
-}
-function JSmenuWrite(theEntryID,openID,theLevel) {
-       var level=theLevel;
-       if (level<=this.levels) {
-               var entryID = theEntryID;
-               var firstEntryID = theEntryID;
-               var selectorBox = document[this.formname]["selector"+level];
-               var index=0;
-               selectorBox.length=0;
-               selectorBox.length++;
-               selectorBox.options[index].text = this.defTopTitle[theLevel] ? this.defTopTitle[theLevel] : "                   ";
-               selectorBox.options[index].value = 0;
-               index++;
-               var indexSet=0;
-               if (entryID && this.entry[entryID])     {
-                       var ids = "";
-                       while(entryID)  {
-                       ids+="-"+entryID;
-                               selectorBox.length++;
-                               selectorBox.options[index].text = this.entry[entryID].title;
-                               selectorBox.options[index].value = entryID;
-                               if (openID==entryID)    {
-                                       var indexSet = 1;
-                                       selectorBox.selectedIndex = index;
-                                       if (level<this.levels)  {
-                                               this.writeOut(this.entry[entryID].child, this.entry[entryID].openID,level+1);
-                                       }
-                               }
-                               index++;
-                               entryID=this.entry[entryID].nextItem;
-                       }
-                       if (!indexSet) {
-                               selectorBox.selectedIndex=0;
-                               this.writeOut(this.entry[firstEntryID].child, this.entry[firstEntryID].openID,level+1);
-                       }
-               } else if (level<this.levels)   {
-                       this.writeOut(0, 0,level+1);
-               }
-       }
-}
-function JSactivate(level) {
-       var selectorBox = document[this.formname]["selector"+level];
-       var entryID = selectorBox.options[selectorBox.selectedIndex].value;
-       if (this.entry[entryID])        {
-               this.writeOut(this.entry[entryID].child,this.entry[entryID].openID,level+1);
-               if (this.entry[this.entry[entryID].parent])     {
-                       this.entry[this.entry[entryID].parent].openID = entryID;
-               }
-               if (this.entry[entryID].url)    {
-                       var baseURLs = document.getElementsByTagName('base');
-                       if (baseURLs.length && baseURLs[0].href.length > 0) {
-                               if (this.entry[entryID].url.search(/^http[s]?:\/\//))   {
-                                       this.entry[entryID].url = baseURLs[0].href + this.entry[entryID].url;
-                               }
-                       }
-                       if (!this.entry[entryID].target || this.entry[entryID].target=="_self") {
-                               window.location.href = this.entry[entryID].url;
-                       } else if (this.entry[entryID].target=="_top") {
-                               top.location.href = this.entry[entryID].url;
-                       } else {
-                               var test = eval ("parent."+this.entry[entryID].target);
-                               if (!test) {
-                                       test = eval ("top."+this.entry[entryID].target);
-                               }
-                               if (test && test.document) {
-                                       test.location.href = this.entry[entryID].url;
-                               } else {
-                                       window.open(this.entry[entryID].url,this.entry[entryID].target,"status=yes,menubar=yes,resizable=yes,location=yes,directories=yes,scrollbars=yes,toolbar=yes");
-                               }
-                       }
-               }
-       }
-}
index 938dfca..46fc1c0 100644 (file)
@@ -2926,8 +2926,7 @@ Will overrule any setting for ".useLargestItemY"]]></description>
 
 .params is the list of parameters sent to the JavaScript open-window function, eg:
 width=200,height=300,status=0,menubar=0
-
-NOTE: Does not work with JSMENU's]]></description>
+]]></description>
                        <default><![CDATA[
 ]]></default>
                </property>
@@ -3247,8 +3246,7 @@ Applies to GMENU, TMENU, IMGMENU]]></description>
 
 .params is the list of parameters sent to the JavaScript open-window function, eg:
 width=200,height=300,status=0,menubar=0
-
-NOTE: Does not work with JSMENU's]]></description>
+]]></description>
                        <default><![CDATA[
 ]]></default>
                </property>
@@ -3440,119 +3438,6 @@ In the future TypoScript may provide better ways to position GIFBUILDER-objects
 ]]></default>
                </property>
        </type>
-       <type id="JSMENU">
-               <property name="1" type="JSMENUITEM">
-                       <description><![CDATA[levels-config]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="2" type="JSMENUITEM">
-                       <description><![CDATA[levels-config]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="3" type="JSMENUITEM">
-                       <description><![CDATA[levels-config]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="4" type="JSMENUITEM">
-                       <description><![CDATA[levels-config]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="SPC" type="boolean">
-                       <description><![CDATA[If set, spacer can go into the menu, else not.]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="firstLabelGeneral" type="string">
-                       <description><![CDATA[General firstlabel. May be overridden by the one set in each JSMENUITEM]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="forceTypeValue" type="int">
-                       <description><![CDATA[If set, the &type parameter of the link is forced to this value regardless of target.]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="levels" type="int">
-                       <description><![CDATA[int, 1-5
-                       How many levels there are]]></description>
-                       <default><![CDATA[1]]></default>
-               </property>
-               <property name="menuName" type="string">
-                       <description><![CDATA[JavaScript menu name.
-If you have more than one JSMENU on the page, you should set this value for each one.]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="target" type="string">
-                       <description><![CDATA[target
-                       Decides target of the menu-links]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="wrap" type="wrap">
-                       <description><![CDATA[wrap around the selector-boxes]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="wrapAfterTags" type="wrap">
-                       <description><![CDATA[wrap around the selector-boxes with wrap and form-tags og JS-code.]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-       </type>
-       <type id="JSMENUITEM">
-               <property name="additionalParams" type="string">
-                       <description><![CDATA[Additional parameters to the <select> box. Eg, you could set the width with a style-parameter like this:
-style="width: 200px;"]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="alwaysLink" type="boolean">
-                       <description><![CDATA[If set an item in the menu selector will always link. This takes precedence over "noLink".]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="elements" type="int">
-                       <description><![CDATA[int+
-                       Initial number of elements in the menu.  This is of course overruled by the actual menu item texts.]]></description>
-                       <default><![CDATA[5]]></default>
-               </property>
-               <property name="firstLabel" type="string">
-                       <description><![CDATA[First label in top of the menu (default is blank)]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="noLink" type="boolean">
-                       <description><![CDATA[Normally the selection of a menu item in the selector box will update the selector on the next level (if there is a next level) and if there are no items for that selector (because there were no subpages), then the link jumps to the page of itself.
-If this flag is set, however, no menuitems in the selector box will ever link to anything. Only update the content of the next selector box on next level.]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="showActive" type="boolean">
-                       <description><![CDATA[if set, the active level will be selected, if present]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="showFirst" type="boolean">
-                       <description><![CDATA[if set, the first link will be shown when the menu is updated.]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-               <property name="width" type="int">
-                       <description><![CDATA[int+
-                       Initial width of the boxes set by a number of _ (underscores)]]></description>
-                       <default><![CDATA[14]]></default>
-               </property>
-               <property name="wrap" type="wrap">
-                       <description><![CDATA[wraps the selectorbox]]></description>
-                       <default><![CDATA[
-]]></default>
-               </property>
-       </type>
        <type id="TMENU" extends="mObj">
                <property name="ACT" type="TMENUITEM">
                        <description><![CDATA[Boolean / (config)
@@ -3711,8 +3596,7 @@ Applies to GMENU, TMENU, IMGMENU]]></description>
 
 .params is the list of parameters sent to the JavaScript open-window function, eg:
 width=200,height=300,status=0,menubar=0
-
-NOTE: Does not work with JSMENU's]]></description>
+]]></description>
                        <default><![CDATA[
 ]]></default>
                </property>
index 0925e4f..80f6802 100644 (file)
@@ -493,9 +493,6 @@ var typoscriptWords = {
        'itemsProcFunc': 'reserved',
        'iterations': 'reserved',
        'join': 'reserved',
-       'JSMENU': 'keyword',
-       'jsmenu': 'keyword2',
-       'JSMENUITEM': 'keyword',
        'JSwindow': 'keyword2',
        'JSWindow': 'reserved',
        'JSwindow_params': 'reserved',