问:
How to achieve accordion functionality with load more option?
I want to display categories as accordion with load more functionality.
First time, I want to display only 3-4 categories, want to displaying remaining categories after click on load more link. it should be load less if click again on link.

For Ref. please see screenshot : https://drive.google.com/file/d/0B4PokeydRXWebHJabmdXbFVtY2M/view

I am using below code :

```<code>    <div class="cat-dropdown" style="margin:25px 0; width:100%; float:left; clear:both">
        <?php
        $parentCatId = Mage::registry('current_category')->getId();
        $root = Mage::getModel('catalog/category')->load($parentCatId);
        $subCat = explode(',',$root->getChildren());

        $collection  = $root
                     ->getCollection()
                     ->addAttributeToSelect("*")
                     ->addFieldToFilter("entity_id", array("in", $subCat) );
        ?>
<div class="products-grid first odd brand_list1">
                <?php foreach($collection as $catname){
                    $qty = Mage::getModel('catalog/category')->load($catname->getId())->getProductCount();?>
                           <div class="selected item<?php if (($i - 1) % $_columnCount == 0): ?> first<?php elseif ($i % $_columnCount == 0): ?> last<?php endif; ?>">
                                <div class="cat-custom-img">
                                <h2 class="lavel-1"><a href="<?php echo $catname->getUrl(); ?>"><?php echo $catname->getName(); ?></a></h2>
                               <?php if($catname['sliderimage']) {  ?>
                                <img src="<?php echo Mage::getBaseUrl('media').'catalog/category/'.$catname['sliderimage']; ?>" alt= "" >
                               <?php } ?>
                               </div>
          <?php $_category = Mage::getModel('catalog/category')->load($catname->getId()) ?>
            <?php $_subcategories = $_category->getChildrenCategories() ?>
                                <?php if (count($_subcategories) > 0){ ?>
                                    <div class="catlist-toggle">
                                        <div class="catlist-toggle-inner">
                                        <ul class="second_level_cat myList">
                                            <?php $limit=1; ?>
                                             <?php foreach($_subcategories as $_subcategory){ ?>
                                                    <li class="hide">
                                                        <h2><a href="<?php echo $_subcategory->getUrl(); ?>">
                                                            <?php echo $_subcategory->getName(); ?>
                                                            </a>
                                                        </h2>
                                                        <?php $_subcategory1 = Mage::getModel('catalog/category')->load($_subcategory->getId()) ?>
                                                        <?php $_subsubcategories1 = $_subcategory1->getChildrenCategories() ?>
                                                        <?php if (count($_subsubcategories1) > 0){ ?>
                                                            <ul class="third_level_cat myList">
                                                                 <?php foreach($_subsubcategories1 as $_subsubcategory){ ?>
                                                                 <li class="hide">
                                                                    <h2><a href="<?php echo $_subsubcategory->getUrl(); ?>" >
                                                                        <?php echo $_subsubcategory->getName(); ?>
                                                                    </a></h2>
                                                                    <?php $_subcategory2 = Mage::getModel('catalog/category')->load($_subsubcategory->getId()) ?>
                                                                    <?php $_subsubcategories2 = $_subcategory2->getChildrenCategories() ?>
                                                                    <?php if (count($_subsubcategories2) > 0){ ?>
                                                                        <ul class="fourth_level_cat myList">
                                                                             <?php foreach($_subsubcategories2 as $_subsubcategory2){ ?>
                                                                             <li class="hide">
                                                                                <h2><a href="<?php echo $_subsubcategory2->getUrl(); ?>" >
                                                                                <?php echo $_subsubcategory2->getName(); ?>
                                                                                </a></h2>
                                                                             </li>
                                                                            <?php }  ?>
                                                                        </ul>
                                                                    <?php } ?>
                                                                 </li>
                                                                <?php }  ?>
                                                            </ul>
                                                        <?php } ?>
                                                    </li>
                                                    <?php $limit++; ?>
                                                    <?php // if($limit == 3){break;} ?>

                                             <?php } ?>
                                        <li class=""><div class="load-more">Load more</div></li>

                                        </ul>
                                        </div>
                                    </div>
                                <?php } ?>
                           </div>
                <?php   } ?>
            </div>
    </div>

<script>
    jQuery('.cat-dropdown').navAccordion({
     expandButtonText : "+",
      collapseButtonText: "-",
      selectedExpand: "true",
      selectedClass: "selected",
      buttonPosition: "right",
      headersOnly: false,
      headersOnlyCheck: false,
      delayLink: false,
      delayAmount: null
    });
    </script>

<script>
jQuery(document).ready(function(){
   jQuery(".load-more").click(function(){
    jQuery(this).closest('.selected').find('.catlist-toggle').toggleClass('expand');
   });
   jQuery(".accordion-btn").click(function(){
    jQuery(this).closest('.selected').find('.catlist-toggle').addClass('expand');
   });
});

</script>

<style>
.selected.item{width: 23%;float: left;margin: 0 10px 55px 10px;}
.catlist-toggle{position: relative; }
.catlist-toggle.expand{height:auto;overflow:initial;}
.catlist-toggle.expand .catlist-toggle-inner ul{height:auto;overflow:initial;}
.catlist-toggle .catlist-toggle-inner{position: relative;  width: 100%;    top:0;    left: 0; background:#fff; z-index:9999;}
.catlist-toggle .catlist-toggle-inner ul{ z-index:9999; height: 220px;overflow:hidden; width:100%;}
.catlist-toggle .load-more{position: absolute;  width: 100%;    bottom:0;    left: 0; background:#ddd; color:#000;}
.cat-custom-img .level-1{ width: 70%;}
.cat-custom-img img{ width: 20%;float: right; margin-top: -71px;}

</style>
</code>```

答:
Use below code:</p>

```<code><div class="" style="margin:25px 0; width:100%; float:left; clear:both">
    <?php
    $parentCatId = Mage::registry('current_category')->getId();
    $root = Mage::getModel('catalog/category')->load($parentCatId);
    $subCat = explode(',',$root->getChildren());

    $collection  = $root
                 ->getCollection()
                 ->addAttributeToSelect("*")
                 ->addFieldToFilter("entity_id", array("in", $subCat) );
    ?>
    <div class="accord-outer">
        <?php foreach($collection as $catname){  ?>
        <div class="accord-section">
            <div class="accord">
                <ul>
                    <?php $qty = Mage::getModel('catalog/category')->load($catname->getId())->getProductCount();?>
                    <li class="selected parent">
                        <a href="<?php echo $catname->getUrl(); ?>"><?php echo $catname->getName(); ?></a>
                       <?php if($catname['sliderimage']) {  ?>
                        <img src="<?php echo Mage::getBaseUrl('media').'catalog/category/'.$catname['sliderimage']; ?>" alt= "" >
                       <?php } ?>

                    </li>

                    <?php $_category = Mage::getModel('catalog/category')->load($catname->getId()) ?>
                    <?php $_subcategories = $_category->getChildrenCategories() ?>
                    <?php if (count($_subcategories) > 0){ ?>
                        <?php $limit=1; ?>
                        <?php foreach($_subcategories as $_subcategory){ ?>
                                <li class="parent">
                                    <a href="<?php echo $_subcategory->getUrl(); ?>">
                                        <?php echo $_subcategory->getName(); ?>
                                    </a>

                                    <?php $_subcategory1 = Mage::getModel('catalog/category')->load($_subcategory->getId()) ?>
                                    <?php $_subsubcategories1 = $_subcategory1->getChildrenCategories() ?>
                                    <?php if (count($_subsubcategories1) > 0){ ?>
                                        <ul class="">
                                             <?php foreach($_subsubcategories1 as $_subsubcategory){ ?>
                                             <li class="">
                                                <a href="<?php echo $_subsubcategory->getUrl(); ?>" >
                                                    <?php echo $_subsubcategory->getName(); ?>
                                                </a>
                                                <?php $_subcategory2 = Mage::getModel('catalog/category')->load($_subsubcategory->getId()) ?>
                                                <?php $_subsubcategories2 = $_subcategory2->getChildrenCategories() ?>
                                                <?php if (count($_subsubcategories2) > 0){ ?>
                                                    <ul class="">
                                                         <?php foreach($_subsubcategories2 as $_subsubcategory2){ ?>
                                                         <li class="">
                                                            <a href="<?php echo $_subsubcategory2->getUrl(); ?>" >
                                                                <?php echo $_subsubcategory2->getName(); ?>
                                                            </a>
                                                         </li>
                                                        <?php }  ?>
                                                    </ul>
                                                <?php } ?>
                                             </li>
                                            <?php }  ?>
                                        </ul>
                                    <?php } ?>
                                </li>
                                <?php $limit++; ?>

                         <?php } ?>
                    <?php } ?>
                   <li class="parent load"><span class="loadmore">Load More</span><span class="loadless">Load Less</span></li>
                </ul>
            </div>
        </div>
        <?php } ?>
    </div>
</div>

<script>
jQuery('document').ready(function(){
    jQuery('.accord').navAccordion({

    // Text inside of expand button
    expandButtonText : "+",

    // Text inside of collapse button
    collapseButtonText: "-",

    // Expand the selected channel
    selectedExpand: "true",

    // Class that will be used to detect the currently selected channel
    // This will check the "parentElement" for this class (the parent <li> by default)
    selectedClass: "selected",

    // Apply accordion to all levels
    // Setting this to false will apply the accordion only to the first level
    multipleLevels: "true",

    // Width of accordion expand/collapse button as a percentage or pixels
    buttonWidth: "20%",

    // Position of button
    buttonPosition: "right",

    // Speed of slide animation
    // "fast", "slow", or number in milliseconds such as 500
    slideSpeed: "fast",

    // Parent element type, class or ID
    // You don't need to change this if you're using a ul > li > ul pattern
    parentElement: "li",

    // Child element type, class or ID
    // You don't need to change this if you're using a ul > li > ul pattern
    childElement: "ul",

    // Setting to true will make any link with sub-nav behave as if it were set to header only, making the link inaccessible
    // This option is useful if you are using the plugin for a non-navigation area
    headersOnly: false,

    // Setting to true to apply the accordion only to links that are set as "header only" (have no href)
    headersOnlyCheck: false,

    // Delay following the href of links until after the accordion the has expanded
    delayLink: false,

    // Time in milliseconds to delay before following href - will use "slideSpeed" by default if nothing else is set
    delayAmount: null
    });

    function accord(ac){
        //console.log(ac);
        var total = jQuery(ac).find('ul li.parent').length;
        //console.log(total);
        if(total > 5){
            jQuery(ac).find('ul li.parent').each(function(i) {
                if(i==1){
                    jQuery( this ).toggleClass( "visible" );
                }
                else if(i<=3){
                    jQuery( this ).toggleClass( "visible" );
                }
                else if(i == (total-1)){
                    jQuery( this ).addClass( "button" );
                }
                else{
                    jQuery( this ).toggleClass( "hidden" );
                }
            });
        }
        else{
            jQuery(ac).find('ul li.parent.load').hide();
            //alert('afsdfdf');
        }
    }

    jQuery('.accord-outer .accord-section').each(function(){
        accord(jQuery(this).children('.accord'));
    })
    jQuery('.load').click(function(event){
        accord(jQuery(this).closest('.accord'));
        jQuery(this).find('.loadless').removeClass("accordion-active");
        jQuery(this).find('.loadless').toggleClass("active");
        jQuery(this).find('.loadmore').toggleClass("active");
    });
    jQuery(".loadless").click(function(){
        jQuery(this).closest('.accord').find('li.parent.active ul').css('display', 'none');
        jQuery(this).closest('.accord').find('li.parent.active .accordion-collapsed').css('display', 'inline-block');
        jQuery(this).closest('.accord').find('li.parent.active .accordion-expanded').css('display', 'none');

    });
});
</script>

<style>
    .accord-outer{width:100%; float:left;}
    .accord{width:25%; float:left; margin:0 0 20px;}
    .visible{display:block;}
    .hidden{display:none;}
    .loadmore{display:inline-block;}
    .loadless{display:none;}
    .loadmore.active{display:none;}
    .loadless.active{display:inline-block;}
    .accord { background: #46CFB0; width: 25%;}

    /* First Level */

    .accord ul {margin: 0; padding: 0; list-style: none; border-bottom: 1px solid #1ABC9C; }
    .accord ul li { border-top: 1px solid #1ABC9C; }
    .accord ul li a { color: #FFFFFF; display: block; font-size: 1.1em; line-height: normal; padding: 12px 20px; text-decoration: none; }
    .accord ul li a:hover { background: #E95546; text-decoration: none;

    /* Second Level */

    .accord ul ul { border-bottom: none }
    .accord ul ul li { border-top: 1px solid #46CFB0; background: #34BC9D; }
    .accord ul ul li a { color: #FFFFFF; display: block; font-size: 1em; line-height: normal; padding: 0.5em 1em 0.5em 2.5em; }
    .accord ul ul li a:hover { background: #E95546; }

    /* Third Level */

    .accord ul ul ul { border-top: 1px solid #46CFB0; }
    .accord ul ul ul li { border: none; }
    .accord ul ul ul li a {  padding-left: 3.5em; padding-top: 0.25em; padding-bottom: 0.25em; }

    /* Accordion Button */

    ul li.has-subnav .accordion-btn { color: #fff; background: rgba(255,255,255, 0.15);  font-size: 16px; }
</style>
</code>```

Body:
I want to display categories as accordion with load more functionality.
First time, I want to display only 3-4 categories, want to displaying remaining categories after click on load more link. it should be load less if click again on link.

For Ref. please see screenshot : https://drive.google.com/file/d/0B4PokeydRXWebHJabmdXbFVtY2M/view

I am using below code :

        <?php
        $parentCatId = Mage::registry('current_category')->getId();
        $root = Mage::getModel('catalog/category')->load($parentCatId);
        $subCat = explode(',',$root->getChildren());

        $collection  = $root
                     ->getCollection()
                     ->addAttributeToSelect("*")
                     ->addFieldToFilter("entity_id", array("in", $subCat) );
        ?>

                <?php foreach($collection as $catname){
                    $qty = Mage::getModel('catalog/category')->load($catname->getId())->getProductCount();?>
                           <div class="selected item<?php if (($i - 1) % $_columnCount == 0): ?> first<?php elseif ($i % $_columnCount == 0): ?> last<?php endif; ?>">

<a href="<?php echo $catname->getUrl(); ?>"><?php echo $catname->getName(); ?>

                               <?php if($catname['sliderimage']) {  ?>
                                <img src="<?php echo Mage::getBaseUrl('media').'catalog/category/'.$catname['sliderimage']; ?>" alt= "" >
                               <?php } ?>

          <?php $_category = Mage::getModel('catalog/category')->load($catname->getId()) ?>
            <?php $_subcategories = $_category->getChildrenCategories() ?>
                                <?php if (count($_subcategories) > 0){ ?>

                                            <?php $limit=1; ?>
                                             <?php foreach($_subcategories as $_subcategory){ ?>

<a href="<?php echo $_subcategory->getUrl(); ?>">
                                                            <?php echo $_subcategory->getName(); ?>

                                                        <?php $_subcategory1 = Mage::getModel('catalog/category')->load($_subcategory->getId()) ?>
                                                        <?php $_subsubcategories1 = $_subcategory1->getChildrenCategories() ?>
                                                        <?php if (count($_subsubcategories1) > 0){ ?>

                                                                 <?php foreach($_subsubcategories1 as $_subsubcategory){ ?>

<a href="<?php echo $_subsubcategory->getUrl(); ?>" >
                                                                        <?php echo $_subsubcategory->getName(); ?>

                                                                    <?php $_subcategory2 = Mage::getModel('catalog/category')->load($_subsubcategory->getId()) ?>
                                                                    <?php $_subsubcategories2 = $_subcategory2->getChildrenCategories() ?>
                                                                    <?php if (count($_subsubcategories2) > 0){ ?>

                                                                             <?php foreach($_subsubcategories2 as $_subsubcategory2){ ?>

<a href="<?php echo $_subsubcategory2->getUrl(); ?>" >
                                                                                <?php echo $_subsubcategory2->getName(); ?>

                                                                            <?php }  ?>

                                                                    <?php } ?>

                                                                <?php }  ?>

                                                        <?php } ?>

                                                    <?php $limit++; ?>
                                                    <?php // if($limit == 3){break;} ?>

                                             <?php } ?>

Load more

                                <?php } ?>

                <?php   } ?>

Body:
Use below code:

<div class="" style="margin:25px 0; width:100%; float:left; clear:both">
    <?php
    $parentCatId = Mage::registry('current_category')->getId();
    $root = Mage::getModel('catalog/category')->load($parentCatId);
    $subCat = explode(',',$root->getChildren());

    $collection  = $root
                 ->getCollection()
                 ->addAttributeToSelect("*")
                 ->addFieldToFilter("entity_id", array("in", $subCat) );
    ?>
    <div class="accord-outer">
        <?php foreach($collection as $catname){  ?>
        <div class="accord-section">
            <div class="accord">
                <ul>
                    <?php $qty = Mage::getModel('catalog/category')->load($catname->getId())->getProductCount();?>
                    <li class="selected parent">
                        <a href="<?php echo $catname->getUrl(); ?>"><?php echo $catname->getName(); ?></a>
                       <?php if($catname['sliderimage']) {  ?>
                        <img src="<?php echo Mage::getBaseUrl('media').'catalog/category/'.$catname['sliderimage']; ?>" alt= "" >
                       <?php } ?>

                    </li>

                    <?php $_category = Mage::getModel('catalog/category')->load($catname->getId()) ?>
                    <?php $_subcategories = $_category->getChildrenCategories() ?>
                    <?php if (count($_subcategories) > 0){ ?>
                        <?php $limit=1; ?>
                        <?php foreach($_subcategories as $_subcategory){ ?>
                                <li class="parent">
                                    <a href="<?php echo $_subcategory->getUrl(); ?>">
                                        <?php echo $_subcategory->getName(); ?>
                                    </a>

                                    <?php $_subcategory1 = Mage::getModel('catalog/category')->load($_subcategory->getId()) ?>
                                    <?php $_subsubcategories1 = $_subcategory1->getChildrenCategories() ?>
                                    <?php if (count($_subsubcategories1) > 0){ ?>
                                        <ul class="">
                                             <?php foreach($_subsubcategories1 as $_subsubcategory){ ?>
                                             <li class="">
                                                <a href="<?php echo $_subsubcategory->getUrl(); ?>" >
                                                    <?php echo $_subsubcategory->getName(); ?>
                                                </a>
                                                <?php $_subcategory2 = Mage::getModel('catalog/category')->load($_subsubcategory->getId()) ?>
                                                <?php $_subsubcategories2 = $_subcategory2->getChildrenCategories() ?>
                                                <?php if (count($_subsubcategories2) > 0){ ?>
                                                    <ul class="">
                                                         <?php foreach($_subsubcategories2 as $_subsubcategory2){ ?>
                                                         <li class="">
                                                            <a href="<?php echo $_subsubcategory2->getUrl(); ?>" >
                                                                <?php echo $_subsubcategory2->getName(); ?>
                                                            </a>
                                                         </li>
                                                        <?php }  ?>
                                                    </ul>
                                                <?php } ?>
                                             </li>
                                            <?php }  ?>
                                        </ul>
                                    <?php } ?>
                                </li>
                                <?php $limit++; ?>

                         <?php } ?>
                    <?php } ?>
                   <li class="parent load"><span class="loadmore">Load More</span><span class="loadless">Load Less</span></li>
                </ul>
            </div>
        </div>
        <?php } ?>
    </div>
</div>

<script>
jQuery('document').ready(function(){
    jQuery('.accord').navAccordion({

    // Text inside of expand button
    expandButtonText : "+",

    // Text inside of collapse button
    collapseButtonText: "-",

    // Expand the selected channel
    selectedExpand: "true",

    // Class that will be used to detect the currently selected channel
    // This will check the "parentElement" for this class (the parent <li> by default)
    selectedClass: "selected",

    // Apply accordion to all levels
    // Setting this to false will apply the accordion only to the first level
    multipleLevels: "true",

    // Width of accordion expand/collapse button as a percentage or pixels
    buttonWidth: "20%",

    // Position of button
    buttonPosition: "right",

    // Speed of slide animation
    // "fast", "slow", or number in milliseconds such as 500
    slideSpeed: "fast",

    // Parent element type, class or ID
    // You don't need to change this if you're using a ul > li > ul pattern
    parentElement: "li",

    // Child element type, class or ID
    // You don't need to change this if you're using a ul > li > ul pattern
    childElement: "ul",

    // Setting to true will make any link with sub-nav behave as if it were set to header only, making the link inaccessible
    // This option is useful if you are using the plugin for a non-navigation area
    headersOnly: false,

    // Setting to true to apply the accordion only to links that are set as "header only" (have no href)
    headersOnlyCheck: false,

    // Delay following the href of links until after the accordion the has expanded
    delayLink: false,

    // Time in milliseconds to delay before following href - will use "slideSpeed" by default if nothing else is set
    delayAmount: null
    });

    function accord(ac){
        //console.log(ac);
        var total = jQuery(ac).find('ul li.parent').length;
        //console.log(total);
        if(total > 5){
            jQuery(ac).find('ul li.parent').each(function(i) {
                if(i==1){
                    jQuery( this ).toggleClass( "visible" );
                }
                else if(i<=3){
                    jQuery( this ).toggleClass( "visible" );
                }
                else if(i == (total-1)){
                    jQuery( this ).addClass( "button" );
                }
                else{
                    jQuery( this ).toggleClass( "hidden" );
                }
            });
        }
        else{
            jQuery(ac).find('ul li.parent.load').hide();
            //alert('afsdfdf');
        }
    }

    jQuery('.accord-outer .accord-section').each(function(){
        accord(jQuery(this).children('.accord'));
    })
    jQuery('.load').click(function(event){
        accord(jQuery(this).closest('.accord'));
        jQuery(this).find('.loadless').removeClass("accordion-active");
        jQuery(this).find('.loadless').toggleClass("active");
        jQuery(this).find('.loadmore').toggleClass("active");
    });
    jQuery(".loadless").click(function(){
        jQuery(this).closest('.accord').find('li.parent.active ul').css('display', 'none');
        jQuery(this).closest('.accord').find('li.parent.active .accordion-collapsed').css('display', 'inline-block');
        jQuery(this).closest('.accord').find('li.parent.active .accordion-expanded').css('display', 'none');

    });
});
</script>

<style>
    .accord-outer{width:100%; float:left;}
    .accord{width:25%; float:left; margin:0 0 20px;}
    .visible{display:block;}
    .hidden{display:none;}
    .loadmore{display:inline-block;}
    .loadless{display:none;}
    .loadmore.active{display:none;}
    .loadless.active{display:inline-block;}
    .accord { background: #46CFB0; width: 25%;}

    /* First Level */

    .accord ul {margin: 0; padding: 0; list-style: none; border-bottom: 1px solid #1ABC9C; }
    .accord ul li { border-top: 1px solid #1ABC9C; }
    .accord ul li a { color: #FFFFFF; display: block; font-size: 1.1em; line-height: normal; padding: 12px 20px; text-decoration: none; }
    .accord ul li a:hover { background: #E95546; text-decoration: none;

    /* Second Level */

    .accord ul ul { border-bottom: none }
    .accord ul ul li { border-top: 1px solid #46CFB0; background: #34BC9D; }
    .accord ul ul li a { color: #FFFFFF; display: block; font-size: 1em; line-height: normal; padding: 0.5em 1em 0.5em 2.5em; }
    .accord ul ul li a:hover { background: #E95546; }

    /* Third Level */

    .accord ul ul ul { border-top: 1px solid #46CFB0; }
    .accord ul ul ul li { border: none; }
    .accord ul ul ul li a {  padding-left: 3.5em; padding-top: 0.25em; padding-bottom: 0.25em; }

    /* Accordion Button */

    ul li.has-subnav .accordion-btn { color: #fff; background: rgba(255,255,255, 0.15);  font-size: 16px; }
</style>


来源: stackexchange

问:
Antlr4 parsing jsp scriptlets expression directive
I want to parse jsp files to identify the directive tags, jsp action elements, scriptlet expression etc. For that I am trying to extend the existing html grammar.
I am facing problem in differentiating normal html tag opening and jsp tag opening. The existing grammar has the following lexer rules:

```<code>TAG_OPEN
    : '<' -> pushMode(TAG)
    ;
//
// tag declarations
//
mode TAG;

TAG_CLOSE
    : '>' -> popMode
    ;

TAG_SLASH_CLOSE
    : '/>' -> popMode
    ;

TAG_SLASH
    : '/'
    ;

//
// lexing mode for attribute values
//
TAG_EQUALS
    : '=' -> pushMode(ATTVALUE)
    ;

TAG_NAME
    : TAG_NameStartChar TAG_NameChar*
    | TAG_NameStartChar* ':' TAG_NameStartChar*
    ;

TAG_WHITESPACE
    : [ \t\r\n] -> skip
    ;
</code>```

And the correspoding parser rule for that:

```<code>htmlElement
    : TAG_OPEN htmlTagName htmlAttribute* TAG_CLOSE htmlContent TAG_OPEN TAG_SLASH htmlTagName TAG_CLOSE
    | TAG_OPEN htmlTagName htmlAttribute* TAG_SLASH_CLOSE
    | TAG_OPEN htmlTagName htmlAttribute* TAG_CLOSE
    | TAG_OPEN TAG_SLASH htmlTagName TAG_CLOSE
//  | jspDirective
//  | jspDeclaration
    | scriptlet
    | script
    | style
    ;
</code>```

I am trying to extend the above rules with the following:

```<code>scriptlet
    : JSP_TAG_OPEN jspElement jspElementName jspElementAttribute* JSP_TAG_CLOSE
    //|SCRIPTLET
    ;

jspElementName
    : TAG_NAME
    ;

jspElementAttribute
    : jspAttributeName TAG_EQUALS jspAttributeValue
    ;

jspAttributeName
    : TAG_NAME
    ;

jspAttributeValue
    : ATTVALUE_VALUE
    ;

jspElement
    : jspDirective
    | jspExpression
    | jspDeclaration
    | jspFragment
    ;

jspDirective
    : JSP_DIRECTIVE_SIGN
    ;

jspExpression
    : JSP_EXPRESSION_SIGN
    ;

jspDeclaration
    : JSP_DECLARATION_SIGN
    ;

jspFragment
    : JSP_FRAGMENT_SIGN
    ;
</code>```

The lexer rules are :

```<code>JSP_TAG_OPEN
    : '<%' ' '*
    ;

JSP_DIRECTIVE_SIGN
    : '@'
    ;

JSP_EXPRESSION_SIGN
    : '='
    ;

JSP_DECLARATION_SIGN
    : '!'
    ;

JSP_FRAGMENT_SIGN
    : [ ]+
    ;

JSP_TAG_CLOSE
    : '%>'
    ;
</code>```

But the problem I guess is that, whenever a < character is encountered the lexer rule for TAG_OPEN starts running, rather than waiting to see whether that is a jsp tag <%.

So when I am trying to parse a small html with the following content:

```<code><html>
<title>Statement Load page</title>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html"
    prefix="html"%>
</code>```

I am getting this error:

```<code>line 3:2 no viable alternative at input '@ taglib uri="http://jakarta.apache.org/struts/tags-html"\r\n\tprefix="html"%>\r\n'
</code>```

答:
Ok, I have come up with a grammar for jsp now. I am sharing this here if that helps other people. Also, I would be glad if someone suggest any update, points out issues or helps make the grammar better.

Lexer Grammar:

```<code>lexer grammar  HTMLLexer;

HTML_COMMENT
    : '<!--' .*? '-->'
    ;

HTML_CONDITIONAL_COMMENT
    : '<![' .*? ']>'
    ;

JSP_COMMENT
    : '<%--' .*? '--%>'
    ;

XML_DECLARATION
    : '<?xml' .*? '>'
    ;

SCRIPT_OPEN
    : '<script' ->pushMode(SCRIPT)
    ;

DIRECTIVE_TAG_OPEN
    : '<%@' -> pushMode(TAG)
    ;

SCRIPTLET_TAG_OPEN
    : ('<%!' | '<%=' | '<%') ->pushMode(SCRIPTVALUE)
    ;

//
//
CDATA
    : '<![CDATA[' .*? ']]>'
    ;

DTD
    : '<!' .*? '>'
    ;

//SCRIPTLET
//    : '<?' .*? '?>'
//    | '<%' .*? '%>'
//    ;

SEA_WS
    :  (' '|'\t'|'\r'? '\n')+
    ;

LINK_OPEN
    : '<link' ->pushMode(LINK)
    ;

STYLE_OPEN
    : '<style'  ->pushMode(STYLE)
    ;

TAG_OPEN
    : '<' ->pushMode(TAG)
    ;

HTML_TEXT
    : ~'<'+
    ;

//
// tag declarations
//
mode TAG;

JSP_TAG_CLOSE
    : '%>' -> popMode
    ;

TAG_CLOSE
    : '>' -> popMode
    ;

TAG_SLASH_CLOSE
    : '/>' -> popMode
    ;

TAG_SLASH
    : '/'
    ;

//
// lexing mode for attribute values
//
TAG_EQUALS
    : '=' -> pushMode(ATTVALUE)
    ;

TAG_NAME
    : TAG_NameStartChar TAG_NameChar*
//  | TAG_NameStartChar* ':' TAG_NameStartChar*
    ;

TAG_COLON
    : ':'
    ;

TAG_WHITESPACE
    : [ \t\r\n] -> channel(HIDDEN)
    ;

fragment
HEXDIGIT
    : [a-fA-F0-9]
    ;

fragment
DIGIT
    : [0-9]
    ;

TAG_NameChar
    : TAG_NameStartChar
//  | ':'
    | '-'
    | '_'
    | '.'
    | DIGIT
    |   '\u00B7'
    |   '\u0300'..'\u036F'
    |   '\u203F'..'\u2040'
    ;

TAG_NameStartChar
    :   [a-zA-Z]
    |   '\u2070'..'\u218F'
    |   '\u2C00'..'\u2FEF'
    |   '\u3001'..'\uD7FF'
    |   '\uF900'..'\uFDCF'
    |   '\uFDF0'..'\uFFFD'
    ;

//
// <scripts>
//
mode SCRIPT;

SCRIPT_TAG_FULL_CLOSE
    : '</script>' ->popMode
    ;

SCRIPT_TAG_CLOSE
    : '>' -> popMode
    ;

SCRIPT_TAG_SLASH_CLOSE
    : '/>' -> popMode
    ;

SCRIPT_EQUALS
    : ' '* '=' ' '*
    ;

SCRIPLET_INSIDE_SCRIPT
    : '<%' ->pushMode(SCRIPTVALUE)
    ;

SCRIPT_ATTRIBUTE
    : SCRIPT_ATTCHARS
    ;

fragment SCRIPT_ATTCHARS
    : SCRIPT_ATTCHAR+ ' '?
    ;

SCRIPT_WHITESPACE
    : [\r\n\t]+ -> channel(HIDDEN)
    ;

WORD
    : [ a-zA-Z]+
    ;

QUOTE
    : '"' ' '*
    ;

fragment SCRIPT_ATTCHAR
    : '-'
    | '_'
    | '.'
    | '/'
    | ','
    | ';'
    | '\''
    | '"'
    | [0-9a-zA-Z]
    ;

//
// <link>
//
mode LINK;

LINK_BODY
    : .*? '</link>' ->popMode
    ;

LINK_SHORT_BODY
    : '/>' ->popMode
    ;

LINK_WS
    : [ \r\n\t]+ -> channel(HIDDEN)
    ;

LINK_NONSLASH_BODY
    : .*? '>' ->popMode
    ;

//
// <styles>
//
mode STYLE;

STYLE_BODY
    : .*? '</style>' -> popMode
    ;

STYLE_SHORT_BODY
    : .*? '</>' -> popMode
    ;

//
// attribute values
//
mode ATTVALUE;

// an attribute value may have spaces b/t the '=' and the value
ATTVALUE_VALUE
    : [ ]* ATTRIBUTE -> popMode
    ;

ATTRIBUTE
    : DOUBLE_QUOTE_STRING
    | SINGLE_QUOTE_STRING
    | ATTCHARS
    | HEXCHARS
    | DECCHARS
    ;

fragment ATTCHAR
    : '-'
    | '_'
    | '.'
    | '/'
    | '+'
    | ','
    | '?'
    | '='
    | ':'
    | ';'
    | '#'
    | [0-9a-zA-Z]
    ;

fragment ATTCHARS
    : ATTCHAR+ ' '?
    ;

fragment HEXCHARS
    : '#' [0-9a-fA-F]+
    ;

fragment DECCHARS
    : [0-9]+ '%'?
    ;

fragment DOUBLE_QUOTE_STRING
    : '"' ~[<"]* '"'
    ;
fragment SINGLE_QUOTE_STRING
    : '\'' ~[<']* '\''
    ;

mode SCRIPTVALUE;

SCRIPTLET_TAG_CLOSE
    : '%>' ->popMode
    ;

VALID_JAVA_CHARS
    : SCRIPTCHARS+
    ;

SCRIPT_WS
    : [\r\n\t]+ -> channel(HIDDEN)
    ;

fragment SCRIPTCHARS
    : SCRIPTCHAR+ ' '?
    ;

fragment SCRIPTCHAR
    : '-'
    | '_'
    | '.'
    | '/'
    | '+'
    | ','
    | '?'
    | '='
    | ':'
    | ';'
    | '#'
    | '('
    | ')'
    | '}'
    | '{'
    | '@'
    | '*'
    | '!'
    | '%'[0-9]+
    | '&'
    | '['
    | ']'
    | '~'
    | '+'
    | '^'
    | '\r'
    | '\t'
    | '\n'
    | ' '
    | '"'
    | '\''
    | [0-9a-zA-Z]
    ;
</code>```

Parser Grammar:

```<code>parser grammar HTMLParser;

options { tokenVocab=HTMLLexer; }

htmlDocument
    : (scriptlet | SEA_WS)* xml? (scriptlet | SEA_WS)* dtd? (scriptlet | SEA_WS)* htmlElements*
    ;

htmlElements
    : htmlMisc* htmlElement htmlMisc*
    ;

htmlElement
    : script
    | link
    | style
    | scriptlet
    | TAG_OPEN htmlTagName htmlAttribute* TAG_CLOSE htmlContent TAG_OPEN TAG_SLASH htmlTagName TAG_CLOSE
    | TAG_OPEN htmlTagName htmlAttribute* TAG_SLASH_CLOSE
    | TAG_OPEN htmlTagName htmlAttribute* TAG_CLOSE
    | TAG_OPEN TAG_SLASH htmlTagName TAG_CLOSE
    ;

htmlContent
    : htmlChardata? ((htmlElement | xhtmlCDATA | htmlComment) htmlChardata?)*
    ;

htmlAttribute
    : htmlAttributeName TAG_EQUALS htmlAttributeValue
    | htmlAttributeName
    ;

htmlAttributeName
    : TAG_NAME
    ;

htmlAttributeValue
    : ATTVALUE_VALUE
    ;

htmlTagName
    : TAG_NAME
    | tagKey TAG_COLON tagVal
    ;

tagKey
    : TAG_NAME
    ;

tagVal
    : TAG_NAME
    ;

htmlChardata
    : HTML_TEXT
    | SEA_WS
    ;

htmlMisc
    : htmlComment
    | jspComment
    | SEA_WS
    ;

htmlComment
    : HTML_COMMENT
    | HTML_CONDITIONAL_COMMENT
    ;

jspComment
    : JSP_COMMENT
    ;

xhtmlCDATA
    : CDATA
    ;

dtd
    : DTD
    ;

xml
    : XML_DECLARATION
    ;

scriptlet
    : DIRECTIVE_TAG_OPEN jspElementName jspElementAttribute* JSP_TAG_CLOSE
    | SCRIPTLET_TAG_OPEN javaExpression SCRIPTLET_TAG_CLOSE
    ;

jspElementName
    : TAG_NAME
    ;

jspElementAttribute
    : jspAttributeName TAG_EQUALS jspAttributeValue
    ;

jspAttributeName
    : TAG_NAME
    ;

jspAttributeValue
    : ATTVALUE_VALUE
    ;

javaExpression
    : VALID_JAVA_CHARS | SEA_WS*
    ;

script
    : SCRIPT_OPEN scriptAttribute* SCRIPT_TAG_CLOSE htmlContent* SCRIPT_TAG_FULL_CLOSE
    | SCRIPT_OPEN scriptAttribute* SCRIPT_TAG_SLASH_CLOSE
    ;

scriptAttribute
    : scriptAttributeName SCRIPT_EQUALS QUOTE scriptlet scriptAttributeValue* QUOTE
    | scriptAttributeName SCRIPT_EQUALS scriptAttributeValue
    | scriptAttributeName
    ;

scriptAttributeName
    : WORD
    ;

scriptAttributeValue
    : SCRIPT_ATTRIBUTE
    ;

link
    : LINK_OPEN ( LINK_BODY | LINK_SHORT_BODY | LINK_NONSLASH_BODY)
    | LINK_OPEN scriptlet* ( LINK_BODY | LINK_SHORT_BODY | LINK_NONSLASH_BODY)
    ;

style
    : STYLE_OPEN ( STYLE_BODY | STYLE_SHORT_BODY)
    ;
</code>```

Edit: I have modified the Parser and Lexer grammar since my last entry. I am facing problem in parsing a jsp file now. A sample jsp is:

```<code><html>
<title>Statement Load page</title>

<script type="text/javascript" src="<%= request.getContextPath() %>"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/scripts/Main.js"></script>

<body>
</body>
</html>
</code>```

While parsing this file, I am getting :

```<code>line 4:0 mismatched input '<script' expecting '<'
line 5:31 no viable alternative at input '<script type="text/javascript" src'
</code>```

That is, while encountering "

ContentLicense: CC BY-SA 3.0

Body:
I want to parse jsp files to identify the directive tags, jsp action elements, scriptlet expression etc. For that I am trying to extend the existing html grammar.
I am facing problem in differentiating normal html tag opening and jsp tag opening. The existing grammar has the following lexer rules:

TAG_OPEN
    : '<' -> pushMode(TAG)
    ;
//
// tag declarations
//
mode TAG;

TAG_CLOSE
    : '>' -> popMode
    ;

TAG_SLASH_CLOSE
    : '/>' -> popMode
    ;

TAG_SLASH
    : '/'
    ;

//
// lexing mode for attribute values
//
TAG_EQUALS
    : '=' -> pushMode(ATTVALUE)
    ;

TAG_NAME
    : TAG_NameStartChar TAG_NameChar*
    | TAG_NameStartChar* ':' TAG_NameStartChar*
    ;

TAG_WHITESPACE
    : [ \t\r\n] -> skip
    ;

And the correspoding parser rule for that:

htmlElement
    : TAG_OPEN htmlTagName htmlAttribute* TAG_CLOSE htmlContent TAG_OPEN TAG_SLASH htmlTagName TAG_CLOSE
    | TAG_OPEN htmlTagName htmlAttribute* TAG_SLASH_CLOSE
    | TAG_OPEN htmlTagName htmlAttribute* TAG_CLOSE
    | TAG_OPEN TAG_SLASH htmlTagName TAG_CLOSE
//  | jspDirective
//  | jspDeclaration
    | scriptlet
    | script
    | style
    ;

I am trying to extend the above rules with the following:

scriptlet
    : JSP_TAG_OPEN jspElement jspElementName jspElementAttribute* JSP_TAG_CLOSE
    //|SCRIPTLET
    ;

jspElementName
    : TAG_NAME
    ;

jspElementAttribute
    : jspAttributeName TAG_EQUALS jspAttributeValue
    ;

jspAttributeName
    : TAG_NAME
    ;

jspAttributeValue
    : ATTVALUE_VALUE
    ;

jspElement
    : jspDirective
    | jspExpression
    | jspDeclaration
    | jspFragment
    ;

jspDirective
    : JSP_DIRECTIVE_SIGN
    ;

jspExpression
    : JSP_EXPRESSION_SIGN
    ;

jspDeclaration
    : JSP_DECLARATION_SIGN
    ;

jspFragment
    : JSP_FRAGMENT_SIGN
    ;

The lexer rules are :

JSP_TAG_OPEN
    : '<%' ' '*
    ;

JSP_DIRECTIVE_SIGN
    : '@'
    ;

JSP_EXPRESSION_SIGN
    : '='
    ;

JSP_DECLARATION_SIGN
    : '!'
    ;

JSP_FRAGMENT_SIGN
    : [ ]+
    ;

JSP_TAG_CLOSE
    : '%>'
    ;

But the problem I guess is that, whenever a < character is encountered the lexer rule for TAG_OPEN starts running, rather than waiting to see whether that is a jsp tag <%.

So when I am trying to parse a small html with the following content:

<title>Statement Load page</title>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html"
    prefix="html"%>

I am getting this error:

line 3:2 no viable alternative at input '@ taglib uri="http://jakarta.apache.org/struts/tags-html"\r\n\tprefix="html"%>\r\n'

Body:
Ok, I have come up with a grammar for jsp now. I am sharing this here if that helps other people. Also, I would be glad if someone suggest any update, points out issues or helps make the grammar better.

Lexer Grammar:

lexer grammar  HTMLLexer;

HTML_COMMENT
    : '<!--' .*? '-->'
    ;

HTML_CONDITIONAL_COMMENT
    : '<![' .*? ']>'
    ;

JSP_COMMENT
    : '<%--' .*? '--%>'
    ;

XML_DECLARATION
    : '<?xml' .*? '>'
    ;

SCRIPT_OPEN
    : '<script' ->pushMode(SCRIPT)
    ;

DIRECTIVE_TAG_OPEN
    : '<%@' -> pushMode(TAG)
    ;

SCRIPTLET_TAG_OPEN
    : ('<%!' | '<%=' | '<%') ->pushMode(SCRIPTVALUE)
    ;

//
//
CDATA
    : '<![CDATA[' .*? ']]>'
    ;

DTD
    : '<!' .*? '>'
    ;

//SCRIPTLET
//    : '<?' .*? '?>'
//    | '<%' .*? '%>'
//    ;

SEA_WS
    :  (' '|'\t'|'\r'? '\n')+
    ;

LINK_OPEN
    : '<link' ->pushMode(LINK)
    ;

STYLE_OPEN
    : '<style'  ->pushMode(STYLE)
    ;

TAG_OPEN
    : '<' ->pushMode(TAG)
    ;

HTML_TEXT
    : ~'<'+
    ;

//
// tag declarations
//
mode TAG;

JSP_TAG_CLOSE
    : '%>' -> popMode
    ;

TAG_CLOSE
    : '>' -> popMode
    ;

TAG_SLASH_CLOSE
    : '/>' -> popMode
    ;

TAG_SLASH
    : '/'
    ;

//
// lexing mode for attribute values
//
TAG_EQUALS
    : '=' -> pushMode(ATTVALUE)
    ;

TAG_NAME
    : TAG_NameStartChar TAG_NameChar*
//  | TAG_NameStartChar* ':' TAG_NameStartChar*
    ;

TAG_COLON
    : ':'
    ;

TAG_WHITESPACE
    : [ \t\r\n] -> channel(HIDDEN)
    ;

fragment
HEXDIGIT
    : [a-fA-F0-9]
    ;

fragment
DIGIT
    : [0-9]
    ;

TAG_NameChar
    : TAG_NameStartChar
//  | ':'
    | '-'
    | '_'
    | '.'
    | DIGIT
    |   '\u00B7'
    |   '\u0300'..'\u036F'
    |   '\u203F'..'\u2040'
    ;

TAG_NameStartChar
    :   [a-zA-Z]
    |   '\u2070'..'\u218F'
    |   '\u2C00'..'\u2FEF'
    |   '\u3001'..'\uD7FF'
    |   '\uF900'..'\uFDCF'
    |   '\uFDF0'..'\uFFFD'
    ;

//
// <scripts>
//
mode SCRIPT;

SCRIPT_TAG_FULL_CLOSE
    : '</script>' ->popMode
    ;

SCRIPT_TAG_CLOSE
    : '>' -> popMode
    ;

SCRIPT_TAG_SLASH_CLOSE
    : '/>' -> popMode
    ;

SCRIPT_EQUALS
    : ' '* '=' ' '*
    ;

SCRIPLET_INSIDE_SCRIPT
    : '<%' ->pushMode(SCRIPTVALUE)
    ;

SCRIPT_ATTRIBUTE
    : SCRIPT_ATTCHARS
    ;

fragment SCRIPT_ATTCHARS
    : SCRIPT_ATTCHAR+ ' '?
    ;

SCRIPT_WHITESPACE
    : [\r\n\t]+ -> channel(HIDDEN)
    ;

WORD
    : [ a-zA-Z]+
    ;

QUOTE
    : '"' ' '*
    ;

fragment SCRIPT_ATTCHAR
    : '-'
    | '_'
    | '.'
    | '/'
    | ','
    | ';'
    | '\''
    | '"'
    | [0-9a-zA-Z]
    ;

//
// <link>
//
mode LINK;

LINK_BODY
    : .*? '</link>' ->popMode
    ;

LINK_SHORT_BODY
    : '/>' ->popMode
    ;

LINK_WS
    : [ \r\n\t]+ -> channel(HIDDEN)
    ;

LINK_NONSLASH_BODY
    : .*? '>' ->popMode
    ;

//
// <styles>
//
mode STYLE;

STYLE_BODY
    : .*? '</style>' -> popMode
    ;

STYLE_SHORT_BODY
    : .*? '</>' -> popMode
    ;

//
// attribute values
//
mode ATTVALUE;

// an attribute value may have spaces b/t the '=' and the value
ATTVALUE_VALUE
    : [ ]* ATTRIBUTE -> popMode
    ;

ATTRIBUTE
    : DOUBLE_QUOTE_STRING
    | SINGLE_QUOTE_STRING
    | ATTCHARS
    | HEXCHARS
    | DECCHARS
    ;

fragment ATTCHAR
    : '-'
    | '_'
    | '.'
    | '/'
    | '+'
    | ','
    | '?'
    | '='
    | ':'
    | ';'
    | '#'
    | [0-9a-zA-Z]
    ;

fragment ATTCHARS
    : ATTCHAR+ ' '?
    ;

fragment HEXCHARS
    : '#' [0-9a-fA-F]+
    ;

fragment DECCHARS
    : [0-9]+ '%'?
    ;

fragment DOUBLE_QUOTE_STRING
    : '"' ~[<"]* '"'
    ;
fragment SINGLE_QUOTE_STRING
    : '\'' ~[<']* '\''
    ;

mode SCRIPTVALUE;

SCRIPTLET_TAG_CLOSE
    : '%>' ->popMode
    ;

VALID_JAVA_CHARS
    : SCRIPTCHARS+
    ;

SCRIPT_WS
    : [\r\n\t]+ -> channel(HIDDEN)
    ;

fragment SCRIPTCHARS
    : SCRIPTCHAR+ ' '?
    ;

fragment SCRIPTCHAR
    : '-'
    | '_'
    | '.'
    | '/'
    | '+'
    | ','
    | '?'
    | '='
    | ':'
    | ';'
    | '#'
    | '('
    | ')'
    | '}'
    | '{'
    | '@'
    | '*'
    | '!'
    | '%'[0-9]+
    | '&'
    | '['
    | ']'
    | '~'
    | '+'
    | '^'
    | '\r'
    | '\t'
    | '\n'
    | ' '
    | '"'
    | '\''
    | [0-9a-zA-Z]
    ;

Parser Grammar:

parser grammar HTMLParser;

options { tokenVocab=HTMLLexer; }

htmlDocument
    : (scriptlet | SEA_WS)* xml? (scriptlet | SEA_WS)* dtd? (scriptlet | SEA_WS)* htmlElements*
    ;

htmlElements
    : htmlMisc* htmlElement htmlMisc*
    ;

htmlElement
    : script
    | link
    | style
    | scriptlet
    | TAG_OPEN htmlTagName htmlAttribute* TAG_CLOSE htmlContent TAG_OPEN TAG_SLASH htmlTagName TAG_CLOSE
    | TAG_OPEN htmlTagName htmlAttribute* TAG_SLASH_CLOSE
    | TAG_OPEN htmlTagName htmlAttribute* TAG_CLOSE
    | TAG_OPEN TAG_SLASH htmlTagName TAG_CLOSE
    ;

htmlContent
    : htmlChardata? ((htmlElement | xhtmlCDATA | htmlComment) htmlChardata?)*
    ;

htmlAttribute
    : htmlAttributeName TAG_EQUALS htmlAttributeValue
    | htmlAttributeName
    ;

htmlAttributeName
    : TAG_NAME
    ;

htmlAttributeValue
    : ATTVALUE_VALUE
    ;

htmlTagName
    : TAG_NAME
    | tagKey TAG_COLON tagVal
    ;

tagKey
    : TAG_NAME
    ;

tagVal
    : TAG_NAME
    ;

htmlChardata
    : HTML_TEXT
    | SEA_WS
    ;

htmlMisc
    : htmlComment
    | jspComment
    | SEA_WS
    ;

htmlComment
    : HTML_COMMENT
    | HTML_CONDITIONAL_COMMENT
    ;

jspComment
    : JSP_COMMENT
    ;

xhtmlCDATA
    : CDATA
    ;

dtd
    : DTD
    ;

xml
    : XML_DECLARATION
    ;

scriptlet
    : DIRECTIVE_TAG_OPEN jspElementName jspElementAttribute* JSP_TAG_CLOSE
    | SCRIPTLET_TAG_OPEN javaExpression SCRIPTLET_TAG_CLOSE
    ;

jspElementName
    : TAG_NAME
    ;

jspElementAttribute
    : jspAttributeName TAG_EQUALS jspAttributeValue
    ;

jspAttributeName
    : TAG_NAME
    ;

jspAttributeValue
    : ATTVALUE_VALUE
    ;

javaExpression
    : VALID_JAVA_CHARS | SEA_WS*
    ;

script
    : SCRIPT_OPEN scriptAttribute* SCRIPT_TAG_CLOSE htmlContent* SCRIPT_TAG_FULL_CLOSE
    | SCRIPT_OPEN scriptAttribute* SCRIPT_TAG_SLASH_CLOSE
    ;

scriptAttribute
    : scriptAttributeName SCRIPT_EQUALS QUOTE scriptlet scriptAttributeValue* QUOTE
    | scriptAttributeName SCRIPT_EQUALS scriptAttributeValue
    | scriptAttributeName
    ;

scriptAttributeName
    : WORD
    ;

scriptAttributeValue
    : SCRIPT_ATTRIBUTE
    ;

link
    : LINK_OPEN ( LINK_BODY | LINK_SHORT_BODY | LINK_NONSLASH_BODY)
    | LINK_OPEN scriptlet* ( LINK_BODY | LINK_SHORT_BODY | LINK_NONSLASH_BODY)
    ;

style
    : STYLE_OPEN ( STYLE_BODY | STYLE_SHORT_BODY)
    ;

Edit: I have modified the Parser and Lexer grammar since my last entry. I am facing problem in parsing a jsp file now. A sample jsp is:

<html>
<title>Statement Load page</title>

<script type="text/javascript" src="<%= request.getContextPath() %>"></script>
<script type="text/javascript" src="<%= request.getContextPath() %>/scripts/Main.js"></script>

<body>
</body>
</html>

While parsing this file, I am getting :

line 4:0 mismatched input '<script' expecting '<'
line 5:31 no viable alternative at input '<script type="text/javascript" src'

That is, while encountering "<script" tag the parser is not entering the 'script' rule, but probably treating it as other 'htmlElement'. But I am not sure.

The relevant portion of the parser grammar is:

script
    : SCRIPT_OPEN scriptAttribute* SCRIPT_TAG_CLOSE htmlContent* SCRIPT_TAG_FULL_CLOSE
    | SCRIPT_OPEN scriptAttribute* SCRIPT_TAG_SLASH_CLOSE
    ;

scriptAttribute
    : scriptAttributeName SCRIPT_EQUALS QUOTE scriptlet scriptAttributeValue* QUOTE
    | scriptAttributeName SCRIPT_EQUALS scriptAttributeValue
    | scriptAttributeName
    ;

scriptAttributeName
    : WORD
    ;

scriptAttributeValue
    : SCRIPT_ATTRIBUTE
    ;


问:
Getting bundle identifier in Swift
I'm trying to get bundleID using app's directory and I'm getting an error:
    EXC_BAD_ACCESS(code=1, address=0xd8)

application.directory! is a String

```<code>let startCString = (application.directory! as NSString).UTF8String //Type: UnsafePointer<Int8>
let convertedCString = UnsafePointer<UInt8>(startCString) //CFURLCreateFromFileRepresentation needs <UInt8> pointer
let length = application.directory!.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
let dir = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, convertedCString, length, false)
let bundle = CFBundleCreate(kCFAllocatorDefault, dir)
let result = CFBundleGetIdentifier(bundle)
</code>```

and I get this error on the result line.

What am I doing wrong here?

答:
If you are trying to get it programmatically , you can use below line of code :

Objective-C:

```<code>NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];
</code>```

Swift 3.0:

```<code>let bundleIdentifier =  Bundle.main.bundleIdentifier
</code>```

(Updated for latest swift It will work for both iOS and Mac apps.)

For More Info, Check here :

Apple Docs:
https://developer.apple.com/documentation/foundation/bundle#//apple_ref/occ/instm/NSBundle/bundleIdentifier

Title: Getting bundle identifier in Swift

Body:
I'm trying to get bundleID using app's directory and I'm getting an error:
    EXC_BAD_ACCESS(code=1, address=0xd8)

application.directory! is a String

let startCString = (application.directory! as NSString).UTF8String //Type: UnsafePointer<Int8>
let convertedCString = UnsafePointer<UInt8>(startCString) //CFURLCreateFromFileRepresentation needs <UInt8> pointer
let length = application.directory!.lengthOfBytesUsingEncoding(NSUTF8StringEncoding)
let dir = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, convertedCString, length, false)
let bundle = CFBundleCreate(kCFAllocatorDefault, dir)
let result = CFBundleGetIdentifier(bundle)

and I get this error on the result line.

What am I doing wrong here?

Body:
If you are trying to get it programmatically , you can use below line of code :

Objective-C:

NSString *bundleIdentifier = [[NSBundle mainBundle] bundleIdentifier];

Swift 3.0:

let bundleIdentifier =  Bundle.main.bundleIdentifier

(Updated for latest swift It will work for both iOS and Mac apps.)

For More Info, Check here :

Apple Docs:
https://developer.apple.com/documentation/foundation/bundle#//apple_ref/occ/instm/NSBundle/bundleIdentifier

ContentLicense: CC BY-SA 4.0


问:
Adjust button text size with button height
I have a button that I set a particular height for and have the button text fill the entire button. I achieved this before by setting textSize to a specific dimension to fill the button.

But the problem is whenever the user changes the system font of his/her device, it affects the button text and the text overflows and gets cut in the button. How can I make the button text size match the height of the button?

Edit

The button's height is set to match_parent for it's parent widget

```<code>        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay">
            <RelativeLayout
                android:layout_marginEnd="16dp"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginRight="16dp">
                <Button
                    android:id="@+id/text_toolbar"
                    style="?android:attr/borderlessButtonStyle"
                    android:layout_centerInParent="true"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:textSize="36sp"
                    android:textColor="@color/white"
                    android:text="@string/k_i_n_e_c_t"/>
            </RelativeLayout>
        </android.support.v7.widget.Toolbar>
</code>```

答:
Just take the height from the button with:

```<code>button.getHeight();
</code>```

set your text size with:

```<code>button.setTextSize();
</code>```

Body:
I have a button that I set a particular height for and have the button text fill the entire button. I achieved this before by setting textSize to a specific dimension to fill the button.

But the problem is whenever the user changes the system font of his/her device, it affects the button text and the text overflows and gets cut in the button. How can I make the button text size match the height of the button?

Edit

The button's height is set to match_parent for it's parent widget

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay">
            <RelativeLayout
                android:layout_marginEnd="16dp"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginRight="16dp">
                <Button
                    android:id="@+id/text_toolbar"
                    style="?android:attr/borderlessButtonStyle"
                    android:layout_centerInParent="true"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:textSize="36sp"
                    android:textColor="@color/white"
                    android:text="@string/k_i_n_e_c_t"/>
            </RelativeLayout>
        </android.support.v7.widget.Toolbar>

Body:
Just take the height from the button with:

button.getHeight();

set your text size with:

button.setTextSize();


问:
How to check azure storage availability through SDK or Rest API?
In my application im trying to get the metrics of azure storage i.e metrics for each of its services(blob,queue,file,table) but before trying to get the metrics i want to check the availability of the storage ,can i do that please suggest.

i want to check if the storage status if its up or down before collecting metrics via SDK

答:
According to your description, I suggest you could send the request to management.azure.com to get your storage account current status by using rest api.

The request is as below:

Get Method:

```<code>https://management.azure.com/subscriptions/{yoursubscriptionsID}/resourceGroups/{resourceGroupname}/providers/Microsoft.Storage/storageAccounts/{Youraccount name}?api-version=2017-06-01
</code>```

Request header:

```<code>authorization: Bearer {accesstoken}
</code>```

More details about how to get the access token(Register your client application with Azure AD, Acquire an access token), you could refer to this article.

Result:

Notice: it will return a json which contains all your storage account current message.

In this json message it contains the statusofPrimary property, this is the status.

Result:

Body:
According to your description, I suggest you could send the request to management.azure.com to get your storage account current status by using rest api.

The request is as below:

Get Method:

https://management.azure.com/subscriptions/{yoursubscriptionsID}/resourceGroups/{resourceGroupname}/providers/Microsoft.Storage/storageAccounts/{Youraccount name}?api-version=2017-06-01

Request header:

authorization: Bearer {accesstoken}

More details about how to get the access token(Register your client application with Azure AD, Acquire an access token), you could refer to this article.

Result:

Notice: it will return a json which contains all your storage account current message.

In this json message it contains the statusofPrimary property, this is the status.

Result:


问:
Download 3000+ Images Using C#?
I have a list of around 3000 image URLs, where I need to download them to my desktop.

I'm a web dev, so naturally wrote a little asp.net c# download method to do this but the obvious problem happened and the page timed out before I got hardly any of them.

Was wondering if anyone else knew of a good, quick and robust way of me looping through all the image URL's and downloading them to a folder?  Open to any suggestions, WinForms, batch file although I'm a novice at both.

Any help greatly appreciated

答:
If this is just a one-time job, then one easy solution would be to write a HTML page with img tags pointing to the URLs.

Then browse it with FireFox and use an extension to save all of the images to a folder.

ContentLicense: CC BY-SA 2.5

Title: Download 3000+ Images Using C#?


问:
Proper way to add text on top of navbar bootstrap
I tried to add this code after a ul tag:

```<code><p class="navbar-text pull-right">
    <strong>Toll Free Num: 1 300 22 6868</strong>
</p>
</code>```

but I got these results

bootstrap navbar.

What is the proper way to add the text below or on top of contact?

答:
Try this code

html

```<code><nav class="navbar navbar-default">
  <div class="container-fluid">
    <div class="navbar-header">
      <a class="navbar-brand" href="#">WebSiteName</a>
    </div>
    <ul class="nav navbar-nav">
      <li class="active"><a href="#">Home</a></li>
      <li><a href="#">about</a></li>
      <li><a href="#">services</a></li>
      <li><a href="#">portfolio</a></li>
      <li>
        <div class="tollfree">toll free</div>
        <a href="#">contact</a>
    </li>
    </ul>
  </div>
</nav>
</code>```

css

```<code>ul.navbar-nav li
        {
        position:relative;
        }
        .tollfree
        {
        position:absolute;
        left:0;
        right:0;
        margin:auto;
        }
</code>```

style the navigation bar links accordingly
hope this helps

Body:
I tried to add this code after a ul tag:

    Toll Free Num: 1 300 22 6868

but I got these results

bootstrap navbar.

What is the proper way to add the text below or on top of contact?

Body:
Try this code

html

<nav class="navbar navbar-default">
  <div class="container-fluid">
    <div class="navbar-header">
      <a class="navbar-brand" href="#">WebSiteName</a>
    </div>
    <ul class="nav navbar-nav">
      <li class="active"><a href="#">Home</a></li>
      <li><a href="#">about</a></li>
      <li><a href="#">services</a></li>
      <li><a href="#">portfolio</a></li>
      <li>
        <div class="tollfree">toll free</div>
        <a href="#">contact</a>
    </li>
    </ul>
  </div>
</nav>

css

ul.navbar-nav li
        {
        position:relative;
        }
        .tollfree
        {
        position:absolute;
        left:0;
        right:0;
        margin:auto;
        }

style the navigation bar links accordingly
hope this helps


问:
Paperclip image not showing, unpermitted params and routing error
I'm trying to display images on the homepage with paperclip and I have unpermitted params and a routing error. I have tried various solutions including trying to pass in an array but I think this is happening because of my own lack of knowledge about rails.

```<code>Parameters: {"utf8"=>"✓", "authenticity_token"=>"Hdw1RzedMZdUE0cPrAXz0fkctQKfW9HX3S5ZwYh4lr0PwTJhHhVwcrglJv5qrMQF3T5YkcJZ9zBiRRRlCoNCNQ==", "document"=>{"doc"=>[#<ActionDispatch::Http::UploadedFile:0x007feaf2db80f0 @tempfile=#<Tempfile:/var/folders/1q/zfrk5kxj1015crsc13jwwrz40000gp/T/RackMultipart20170608-15326-1pcmtgl.jpg>, @original_filename="P1150645.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"document[doc][]\"; filename=\"P1150645.jpg\"\r\nContent-Type: image/jpeg\r\n">]}, "commit"=>"Upload Document"}
Unpermitted parameter: doc
   (1.9ms)  begin transaction
  SQL (2.0ms)  INSERT INTO "documents" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", 2017-06-08 04:47:55 UTC], ["updated_at", 2017-06-08 04:47:55 UTC]]
   (0.8ms)  commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 46ms (ActiveRecord: 4.8ms)

Started GET "/" for ::1 at 2017-06-08 12:47:55 +0800
Processing by PagesController#home as HTML
  User Load (1.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 3], ["LIMIT", 1]]
  User Load (0.3ms)  SELECT  "users".* FROM "users" LIMIT ?  [["LIMIT", 1]]
  Rendering pages/home.html.erb within layouts/application
  Document Load (3.1ms)  SELECT "documents".* FROM "documents" ORDER BY created_at
  Rendered documents/_documents.html.erb (56.7ms)
  Rendered documents/_new.html.erb (4.2ms)
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE ("users"."id" != 3)
  Conversation Load (0.2ms)  SELECT "conversations".* FROM "conversations" WHERE (conversations.sender_id = 3 OR conversations.recipient_id = 3)
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 3], ["LIMIT", 1]]
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   (0.2ms)  SELECT COUNT(*) FROM "messages" WHERE "messages"."conversation_id" = ?  [["conversation_id", 4]]
  Rendered conversations/_index.html.erb (18.5ms)
  Rendered pages/home.html.erb within layouts/application (141.2ms)
  Rendered shared/_navbar.html.erb (5.2ms)
Completed 200 OK in 426ms (Views: 401.3ms | ActiveRecord: 6.2ms)

Started GET "/docs/original/missing.png" for ::1 at 2017-06-08 12:47:56 +0800

ActionController::RoutingError (No route matches [GET] "/docs/original/missing.png"):
</code>```

I've tried nesting the params given that document => doc is passing to an array, even if I leave the params blank it still uploads to the database with null fields and routing error, DocumentsController:

```<code>def doc_params
    params.require(:document).permit(:id, :doc)
end
</code>```

I've tried multiple validations in here:

```<code>class Document < ApplicationRecord
  has_attached_file :doc
  do_not_validate_attachment_file_type :doc
end
</code>```

I wondering if rendering the index is causing the routing error as I got rid of temporarily by re-routing but the image was still null, documents/_index.html.erb

```<code><div class="container">
    <div class="row around-xs">
        <center>
        <% @documents.each do |document| %>

          <li class="col-xs-3" id="item-grid">
            <%= link_to image_tag(document.doc.url, class: 'media-object', size:"108x152"), document.doc.url, target: '_blank' %>
            <% if @users %>
                <% if current_user.is_admin? %>
                            <%= link_to 'Remove', document_path(document), class: 'btn btn-danger', method: :delete, data: {confirm: 'Are you sure?'} %>
                        <% end %>
                    <% end %>
                </li>

        <% end %>
        </center>
    </div>
</div>
</code>```

home.html.erb

```<code><section id="about" class="about-section">
  <div class="container" id="services">

    <div class="col-lg-8 col-md-offset-2" id="progpos"><h1>My Work</h1></div>

    <%= render 'documents/index' %>
    <br>
    <%= render 'documents/new' %>

  </div>
</section>
</code>```

Please please help! thanks! documents/_new.html.erb

```<code><% if @users %>
  <% if current_user.is_admin? %>

    <%= form_for @document, html: { multipart: true } do |f| %>
      <% if @document.errors.any? %>
        <div id="error_explanation">

          <h2>
            <%= "#{pluralize(@document.errors.count, "error")} prohibited this document from being saved:" %>
          </h2>

          <ul>
            <% @document.errors.full_messages.each do |msg| %>

              <li>
                <%= msg %>
              </li>
            <% end %>

          </ul>
        </div>
      <% end %>

      <div class="form-group" style="width: 20%">
        <%= f.file_field :doc, class: 'form-control', placeholder: "Document", multiple: true %>
      </div>

      <div class="form-group">
        <%= f.submit 'Upload Document', class: 'btn btn-default' %>
      </div>

    <% end %>
  <% end %>
<% end %>
</code>```

Here's the whole of the controller and I've edited documents/_new.html.erb to how it looks:

```<code>class DocumentsController < ApplicationController

    def index
        @documents = Document.order('created_at')
    end

    def new
        @document = Document.find(params[:id])
    end

    def create
      @document = Document.new(doc_params)
        if @document.save
            **params[:document][:doc].each do |d| #iterate over multiple attached files
            @document.create(doc: d)**
        end
            flash[:success] = "The document was added!"
            redirect_to root_path
        else
            render '_new'
        end
    end

    def destroy
    @document = Document.find(params[:id])
    if @document.destroy
      flash[:notice] = "Successfully deleted photo!"
      redirect_to root_path
    else
      flash[:alert] = "Error deleting photo!"
    end
  end

    private

    def doc_params
        params.require(:document).permit(:id, **document: {doc: []}**)
    end
end
</code>```

I've added Pavans code to mine and i've also changed the params at the bottom which now gives me undefined method `create' for #. I think that's progress?

答:
Unpermitted parameter: doc

You have multiple :true set for field doc, so doc should an array to accept the values. You should change the doc_params to below

```<code>def doc_params
  params.require(:document).permit(:id, doc: [])
end
</code>```

No handler found for
  [#,
  @original_filename="P1150645.jpg", @content_type="image/jpeg",
  @headers="Content-Disposition: form-data; name=\"document[doc][]\";
  filename=\"P1150645.jpg\"\r\nContent-Type: image/jpeg\r\n">]

You should also set multipart: true to the form to handle file uploads

```<code><%= form_for @document, html: { multipart: true } do |f| %>
</code>```

ActionController::RoutingError (No route matches [GET]
  "/docs/original/missing.png")

Paperclip will try to find missing.png when an object doesn't have an uploaded file and you have tell Paperclip where to find it!

```<code>class Document < ApplicationRecord
  has_attached_file :doc, :styles => { :medium => "250x250>", :thumb => "150x150>" }, :default_url => "/system/:attachment/:style/missing.jpg"
  do_not_validate_attachment_file_type :doc
end
</code>```

Update:

Your create action should look like below

```<code>def create
  @document = Document.new(doc_params)
  if @document.save
    params[:document][:doc].each do |d| #iterate over multiple attached files
      @doumnet.create(doc: d)
    end
    flash[:success] = "The document was added!"
    redirect_to root_path
  else
    render 'new'
  end
end
</code>```

Body:
I'm trying to display images on the homepage with paperclip and I have unpermitted params and a routing error. I have tried various solutions including trying to pass in an array but I think this is happening because of my own lack of knowledge about rails.

Parameters: {"utf8"=>"✓", "authenticity_token"=>"Hdw1RzedMZdUE0cPrAXz0fkctQKfW9HX3S5ZwYh4lr0PwTJhHhVwcrglJv5qrMQF3T5YkcJZ9zBiRRRlCoNCNQ==", "document"=>{"doc"=>[#<ActionDispatch::Http::UploadedFile:0x007feaf2db80f0 @tempfile=#<Tempfile:/var/folders/1q/zfrk5kxj1015crsc13jwwrz40000gp/T/RackMultipart20170608-15326-1pcmtgl.jpg>, @original_filename="P1150645.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"document[doc][]\"; filename=\"P1150645.jpg\"\r\nContent-Type: image/jpeg\r\n">]}, "commit"=>"Upload Document"}
Unpermitted parameter: doc
   (1.9ms)  begin transaction
  SQL (2.0ms)  INSERT INTO "documents" ("created_at", "updated_at") VALUES (?, ?)  [["created_at", 2017-06-08 04:47:55 UTC], ["updated_at", 2017-06-08 04:47:55 UTC]]
   (0.8ms)  commit transaction
Redirected to http://localhost:3000/
Completed 302 Found in 46ms (ActiveRecord: 4.8ms)

Started GET "/" for ::1 at 2017-06-08 12:47:55 +0800
Processing by PagesController#home as HTML
  User Load (1.1ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT ?  [["id", 3], ["LIMIT", 1]]
  User Load (0.3ms)  SELECT  "users".* FROM "users" LIMIT ?  [["LIMIT", 1]]
  Rendering pages/home.html.erb within layouts/application
  Document Load (3.1ms)  SELECT "documents".* FROM "documents" ORDER BY created_at
  Rendered documents/_documents.html.erb (56.7ms)
  Rendered documents/_new.html.erb (4.2ms)
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE ("users"."id" != 3)
  Conversation Load (0.2ms)  SELECT "conversations".* FROM "conversations" WHERE (conversations.sender_id = 3 OR conversations.recipient_id = 3)
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 3], ["LIMIT", 1]]
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   (0.2ms)  SELECT COUNT(*) FROM "messages" WHERE "messages"."conversation_id" = ?  [["conversation_id", 4]]
  Rendered conversations/_index.html.erb (18.5ms)
  Rendered pages/home.html.erb within layouts/application (141.2ms)
  Rendered shared/_navbar.html.erb (5.2ms)
Completed 200 OK in 426ms (Views: 401.3ms | ActiveRecord: 6.2ms)

Started GET "/docs/original/missing.png" for ::1 at 2017-06-08 12:47:56 +0800

ActionController::RoutingError (No route matches [GET] "/docs/original/missing.png"):

I've tried nesting the params given that document => doc is passing to an array, even if I leave the params blank it still uploads to the database with null fields and routing error, DocumentsController:

def doc_params
    params.require(:document).permit(:id, :doc)
end

I've tried multiple validations in here:

class Document < ApplicationRecord
  has_attached_file :doc
  do_not_validate_attachment_file_type :doc
end

I wondering if rendering the index is causing the routing error as I got rid of temporarily by re-routing but the image was still null, documents/_index.html.erb

        <% @documents.each do |document| %>

            <%= link_to image_tag(document.doc.url, class: 'media-object', size:"108x152"), document.doc.url, target: '_blank' %>
            <% if @users %>
                <% if current_user.is_admin? %>
                            <%= link_to 'Remove', document_path(document), class: 'btn btn-danger', method: :delete, data: {confirm: 'Are you sure?'} %>
                        <% end %>
                    <% end %>

        <% end %>

home.html.erb

My Work

    <%= render 'documents/index' %>

    <%= render 'documents/new' %>

Please please help! thanks! documents/_new.html.erb

<% if @users %>
  <% if current_user.is_admin? %>

    <%= form_for @document, html: { multipart: true } do |f| %>
      <% if @document.errors.any? %>

            <%= "#{pluralize(@document.errors.count, "error")} prohibited this document from being saved:" %>

            <% @document.errors.full_messages.each do |msg| %>

                <%= msg %>

            <% end %>

      <% end %>

        <%= f.file_field :doc, class: 'form-control', placeholder: "Document", multiple: true %>

        <%= f.submit 'Upload Document', class: 'btn btn-default' %>

    <% end %>
  <% end %>
<% end %>

Here's the whole of the controller and I've edited documents/_new.html.erb to how it looks:

class DocumentsController < ApplicationController

    def index
        @documents = Document.order('created_at')
    end

    def new
        @document = Document.find(params[:id])
    end

    def create
      @document = Document.new(doc_params)
        if @document.save
            **params[:document][:doc].each do |d| #iterate over multiple attached files
            @document.create(doc: d)**
        end
            flash[:success] = "The document was added!"
            redirect_to root_path
        else
            render '_new'
        end
    end

    def destroy
    @document = Document.find(params[:id])
    if @document.destroy
      flash[:notice] = "Successfully deleted photo!"
      redirect_to root_path
    else
      flash[:alert] = "Error deleting photo!"
    end
  end

    private

    def doc_params
        params.require(:document).permit(:id, **document: {doc: []}**)
    end
end

I've added Pavans code to mine and i've also changed the params at the bottom which now gives me undefined method `create' for #. I think that's progress?

Body:
Unpermitted parameter: doc

You have multiple :true set for field doc, so doc should an array to accept the values. You should change the doc_params to below

def doc_params
  params.require(:document).permit(:id, doc: [])
end

No handler found for
  [#,
  @original_filename="P1150645.jpg", @content_type="image/jpeg",
  @headers="Content-Disposition: form-data; name=\"document[doc][]\";
  filename=\"P1150645.jpg\"\r\nContent-Type: image/jpeg\r\n">]

You should also set multipart: true to the form to handle file uploads

<%= form_for @document, html: { multipart: true } do |f| %>

ActionController::RoutingError (No route matches [GET]
  "/docs/original/missing.png")

Paperclip will try to find missing.png when an object doesn't have an uploaded file and you have tell Paperclip where to find it!

class Document < ApplicationRecord
  has_attached_file :doc, :styles => { :medium => "250x250>", :thumb => "150x150>" }, :default_url => "/system/:attachment/:style/missing.jpg"
  do_not_validate_attachment_file_type :doc
end

Update:

Your create action should look like below

def create
  @document = Document.new(doc_params)
  if @document.save
    params[:document][:doc].each do |d| #iterate over multiple attached files
      @doumnet.create(doc: d)
    end
    flash[:success] = "The document was added!"
    redirect_to root_path
  else
    render 'new'
  end
end


问:
I want to get keys names from hash which has same values in ruby
```<code>{"Amar"=>20,"Benton"=>14,"John"=>32,"Sunny"=>28,"Edward"=>19,"Leon"=>12,"Ram"=>19,"David"=>28}
</code>```

the above hash has name and age ,i want to get the names which has same age in ruby

答:
```<code>hash = {"Amar"=>20,"Benton"=>14,"John"=>32,"Sunny"=>28,"Edward"=>19,"Leon"=>12,"Ram"=>19,"David"=>28}

hash.keys.group_by { |k| hash[k] }.values.select { |g| g.size > 1 }
# => [["Sunny", "David"], ["Edward", "Ram"]]
</code>```

Sunny and David have the same age, and so do Edward and Ram.

Body:
{"Amar"=>20,"Benton"=>14,"John"=>32,"Sunny"=>28,"Edward"=>19,"Leon"=>12,"Ram"=>19,"David"=>28}

the above hash has name and age ,i want to get the names which has same age in ruby

Body:
hash = {"Amar"=>20,"Benton"=>14,"John"=>32,"Sunny"=>28,"Edward"=>19,"Leon"=>12,"Ram"=>19,"David"=>28}

hash.keys.group_by { |k| hash[k] }.values.select { |g| g.size > 1 }
# => [["Sunny", "David"], ["Edward", "Ram"]]

Sunny and David have the same age, and so do Edward and Ram.


问:
LCDS - Expect List<Long>, get ArrayCollection of Integer
I have a POJO which declares a collection of List<Long>.

We're currently sending an ArrayCollection of Number, and it's arriving at the client as an ArrayCollection, populated with Integers.

Given the issues with Type Erasure & generics I understand how this is happening.  How do I fix it?

Unfortunately because of some internal limitations, the model cannot be changed.  Ie - we can't use a subtype, and we can't implement IExternalizable.

Are there other options for registering custom type converters in LCDS, other than IExternalizable?  Alternatively, are there any annotations we can use that indicate the type to be used for a collection?

Regards

Marty

答: It looks like https://bugs.adobe.com/jira/browse/BLZ-115. I would try using a custom marshaller, like this one. </p>


问:
How to detect key press with only single Alt modifier
I would like to detect a keypress event only when a non-modifier key has pressed.
I then also would like to know which modifier keys have been pressed at the same time.

For Instance:

When I press Shift:_______ I would like to output nothing.

When I press Shift+A:_____ I would like to output "Shift A".

When I press Shift+Alt+A:__ I would like to output "Shift+Alt A"

When I press Alt+A:_______ I would like to output "Alt A"

However, "Alt A" does not show because without Shift/Ctrl pressed, Alt key down can't be detected with Keyboard.IsKeyDown

Following is the part of my test code.

```<code>private void Window_KeyDown(object sender, KeyEventArgs e)
{
    Key key = e.Key;

    if (key.ToString().Contains("Ctrl") | key.ToString().Contains("Shift") | key.ToString().Contains("Alt"))
        return;

    Label_Test.Content = "";

    if (Keyboard.IsKeyDown(Key.LeftShift) | Keyboard.IsKeyDown(Key.RightShift))
    {
        if (Label_Test.Content.ToString() != "")
            Label_Test.Content += "+";
        Label_Test.Content += "Shift";
    }
    if (Keyboard.IsKeyDown(Key.LeftCtrl) | Keyboard.IsKeyDown(Key.RightCtrl))
    {
        if (Label_Test.Content.ToString() != "")
            Label_Test.Content += "+";
        Label_Test.Content += "Ctrl";
    }
    if (Keyboard.IsKeyDown(Key.LeftAlt) | Keyboard.IsKeyDown(Key.RightAlt))
    {
        if (Label_Test.Content.ToString() != "")
            Label_Test.Content += "+";
        Label_Test.Content += "Alt";
    }
    if (Keyboard.IsKeyDown(Key.System))
    {
        if (Label_Test.Content.ToString() != "")
            Label_Test.Content += "+";
        Label_Test.Content += "Alt";
    }
    if (Label_Test.Content.ToString() != "")
        Label_Test.Content += " ";
    Label_Test.Content += key.ToString();
}
</code>```

I also tried

```<code>if (e.KeyboardDevice.Modifiers.ToString().Contains("Alt"))
</code>```

but the result was same.
How could I detect "Alt + A"?

EDIT: Thanks, guys for your help. I edited the last if statement which checks for Key.System like this and It just worked as I wanted.

```<code>if (e.Key == Key.System)
{
    key = e.SystemKey;
    if (e.SystemKey.HasFlag(Key.LeftAlt) | e.SystemKey.HasFlag(Key.RightAlt))
        return;
    Label_Test.Content = "Alt";
}
</code>```

答:
To check if only modifiers pressed compare e.Key with all modifier keys and return empty string in this case.

If e.Key is not a modifier key then we need to print it along with modifiers currently pressed. To get these modifiers just iterate through all values of ModifierKeys enum except None and call HasFlag for each value on the Keyboard.Modifiers.

```<code>private void Window_KeyDown(object sender, KeyEventArgs e)
{
    var modifierKeys = new[]
    {
        Key.LeftCtrl, Key.RightCtrl,
        Key.LeftAlt, Key.RightAlt,
        Key.LeftShift, Key.RightShift,
        Key.LWin, Key.RWin
    };

    var key = e.Key;
    if (key == Key.System)
        key = e.SystemKey;
    else if (key == Key.ImeProcessed)
        key = e.ImeProcessedKey;

    if (modifierKeys.Contains(key))
    {
        Label_Test.Content = string.Empty;
        return;
    }

    var modifiers = Keyboard.Modifiers;
    var modifiersPressed = Enum.GetValues(typeof(ModifierKeys))
                               .OfType<ModifierKeys>()
                               .Where(k => k != ModifierKeys.None && modifiers.HasFlag(k));

    Label_Test.Content = string.Join("+", modifiersPressed.OfType<object>()
                                                          .Concat(new object[] { key }));
}
</code>```

Body:
I would like to detect a keypress event only when a non-modifier key has pressed.
I then also would like to know which modifier keys have been pressed at the same time.

For Instance:

When I press Shift:_______ I would like to output nothing.

When I press Shift+A:_____ I would like to output "Shift A".

When I press Shift+Alt+A:__ I would like to output "Shift+Alt A"

When I press Alt+A:_______ I would like to output "Alt A"

However, "Alt A" does not show because without Shift/Ctrl pressed, Alt key down can't be detected with Keyboard.IsKeyDown

Following is the part of my test code.

private void Window_KeyDown(object sender, KeyEventArgs e)
{
    Key key = e.Key;

    if (key.ToString().Contains("Ctrl") | key.ToString().Contains("Shift") | key.ToString().Contains("Alt"))
        return;

    Label_Test.Content = "";

    if (Keyboard.IsKeyDown(Key.LeftShift) | Keyboard.IsKeyDown(Key.RightShift))
    {
        if (Label_Test.Content.ToString() != "")
            Label_Test.Content += "+";
        Label_Test.Content += "Shift";
    }
    if (Keyboard.IsKeyDown(Key.LeftCtrl) | Keyboard.IsKeyDown(Key.RightCtrl))
    {
        if (Label_Test.Content.ToString() != "")
            Label_Test.Content += "+";
        Label_Test.Content += "Ctrl";
    }
    if (Keyboard.IsKeyDown(Key.LeftAlt) | Keyboard.IsKeyDown(Key.RightAlt))
    {
        if (Label_Test.Content.ToString() != "")
            Label_Test.Content += "+";
        Label_Test.Content += "Alt";
    }
    if (Keyboard.IsKeyDown(Key.System))
    {
        if (Label_Test.Content.ToString() != "")
            Label_Test.Content += "+";
        Label_Test.Content += "Alt";
    }
    if (Label_Test.Content.ToString() != "")
        Label_Test.Content += " ";
    Label_Test.Content += key.ToString();
}

I also tried

if (e.KeyboardDevice.Modifiers.ToString().Contains("Alt"))

but the result was same.
How could I detect "Alt + A"?

EDIT: Thanks, guys for your help. I edited the last if statement which checks for Key.System like this and It just worked as I wanted.

if (e.Key == Key.System)
{
    key = e.SystemKey;
    if (e.SystemKey.HasFlag(Key.LeftAlt) | e.SystemKey.HasFlag(Key.RightAlt))
        return;
    Label_Test.Content = "Alt";
}

Body:
To check if only modifiers pressed compare e.Key with all modifier keys and return empty string in this case.

If e.Key is not a modifier key then we need to print it along with modifiers currently pressed. To get these modifiers just iterate through all values of ModifierKeys enum except None and call HasFlag for each value on the Keyboard.Modifiers.

private void Window_KeyDown(object sender, KeyEventArgs e)
{
    var modifierKeys = new[]
    {
        Key.LeftCtrl, Key.RightCtrl,
        Key.LeftAlt, Key.RightAlt,
        Key.LeftShift, Key.RightShift,
        Key.LWin, Key.RWin
    };

    var key = e.Key;
    if (key == Key.System)
        key = e.SystemKey;
    else if (key == Key.ImeProcessed)
        key = e.ImeProcessedKey;

    if (modifierKeys.Contains(key))
    {
        Label_Test.Content = string.Empty;
        return;
    }

    var modifiers = Keyboard.Modifiers;
    var modifiersPressed = Enum.GetValues(typeof(ModifierKeys))
                               .OfType<ModifierKeys>()
                               .Where(k => k != ModifierKeys.None && modifiers.HasFlag(k));

    Label_Test.Content = string.Join("+", modifiersPressed.OfType<object>()
                                                          .Concat(new object[] { key }));
}


答:
If you use this wrap_content the text does't overflow    </p>

```<code><Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Upload Image"
            android:id="@+id/buttonUpload" />
</code>```

Title: Adjust button text size with button height

Body:
If you use this wrap_content the text does't overflow

<Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Upload Image"
            android:id="@+id/buttonUpload" />


问:
How to deploy an ionic2 application on a tomcat server
I have developed a web application using angular2 and ionic2. I wanted to deploy this application in a tomcat server. During development I have run this using the "ionic serve" command and the application will run on localhost. Now I wanted to move this application to a tomcat web sever, Can some one give the steps to deploy the same. Thanks in Advance.

Sathyan

答:
first, execute ionic platform add browser,

second, execute ionic build browser,

third, open the directory of '< your project name >/platforms/browser/www', and copy all the files to your tomcat server.


问:
Can anyone help we with these Xcode errors?
I'm trying to make an app for my church and am watching a bunch of YT tutorials but I'm getting a lot of errors:

```<code>import UIKit
import Firebase

class ViewController: UIViewController {
  @IBOutlet weak var emailField: UITextField!
  @IBOutlet weak var passwordField: UITextField!
  @IBOutlet weak var myWebView: UIWebView!

  @IBAction func Website(sender AnyObject) {

    if let url = NSURL(string: :"http://www.sermonaudio.com/source_detail.asp?sourceid=cfbc1")
    UIApplication.sharedApplication().openURL(url) {
    }

    var userUid: String!

    override func viewDidLoad() {
      super.viewDidLoad()
      // Do any additional setup after loading the view, typically from a nib.

      getVideo(videoCode: "qS6tvqL1N24")
    }

    override func didReceiveMemoryWarning() {
      super.didReceiveMemoryWarning()
      // Dispose of any resources that can be recreated.
    }

    func goToCreateUserVC(){
      performSegue(withIdentifier: "Feed", sender: nil)
    }
    func goToFeedVC() {
      performSegue(withIdentifier: "Feed", sender: nil)
    }
    func getVideo(videoCode:String!)
    {
      let url = URL(string: "https://www.youtube.com/embed/\(videoCode)")
      myWebView.loadRequest(URLRequest(url: url!))
    }
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
      if segue.identifier == "SignUp" {
        if let destination = segue.destination as? UserVC {
          if userUid != nil {
            destination.userUid = userUid
          }
          if emailField.text != nil {
            destination.emailField = emailField.text
          }
          if passwordField.text != nil {
            destination.passwordField = passwordField.text
          }
        }
      }
    }

    @IBAction func signInTapped(_ sender: Any){
      if let email = emailField.text, let password = passwordField.text {
        FIRAuth.auth()?.signIn(withEmail: email, password: password, completion:
          { (user,error) in
            if error == nil {
              if let user = user {
                self.userUid = user.uid
                self.goSignUpVC()
              }
            } else {
              self.goToCreateUserVC()
            }
        });
      }
    }
  }

}
</code>```

答:
Welcome to SO :) please post your code in the question next time, and you can embed your image file as well to help us see your question more easily.

You forgot to add an ":"
Website(sender: AnyObject)

On the next line down from that, you put your "{" one line down too far. It needs to go at the end of the if statement, not after the UIApplication.sharedApplication....

There are a couple of other punctuation errors too.

When you see an error saying "override can only be used in a class" that typically means you forgot a closing brace somewhere (which you did). You can select the whole program then do "Editor -> Structure -> Re-indent" which will help you to see where the scope issue is (this is how I fixed the override issue).

Make sure to read and pay attention to your error messages.. one of them clearly tells you that you are missing the "{" after your if statement, and when you see "expected expression" that means that whatever you wrote was gibberish to Swift (meaning you had a typo most likely, or left something incomplete).

I went ahead and edited your question for you, and fixed your code. I have not used hardly any of the stuff you are using (I program games), but I simply followed the directions Xcode gave me (the ones with the dot in the center tell you exactly how to fix it):

```<code>class ViewController: UIViewController {
  @IBOutlet weak var emailField: UITextField!
  @IBOutlet weak var passwordField: UITextField!
  @IBOutlet weak var myWebView: UIWebView!

  @IBAction func Website(sender: AnyObject) {

    if let url = URL(string: "http://www.sermonaudio.com/source_detail.asp?sourceid=cfbc1") {
      UIApplication.shared.openURL(url)
    }
  }
  var userUid: String!

  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    getVideo(videoCode: "qS6tvqL1N24")
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }

  func goToCreateUserVC(){
    performSegue(withIdentifier: "Feed", sender: nil)
  }
  func goToFeedVC() {
    performSegue(withIdentifier: "Feed", sender: nil)
  }
  func getVideo(videoCode:String!)
  {
    let url = URL(string: "https://www.youtube.com/embed/\(videoCode)")
    myWebView.loadRequest(URLRequest(url: url!))
  }
  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "SignUp" {
      if let destination = segue.destination as? UserVC {
        if userUid != nil {
          destination.userUid = userUid
        }
        if emailField.text != nil {
          destination.emailField = emailField.text
        }
        if passwordField.text != nil {
          destination.passwordField = passwordField.text
        }
      }
    }
  }

  @IBAction func signInTapped(_ sender: Any){
    if let email = emailField.text, let password = passwordField.text {
      FIRAuth.auth()?.signIn(withEmail: email, password: password, completion:
        { (user,error) in
          if error == nil {
            if let user = user {
              self.userUid = user.uid
              self.goSignUpVC()
            }
          } else {
            self.goToCreateUserVC()
          }
      });
    }
  }
}
</code>```

Also, it looks like this is older Swift code, hence why you are getting errors. Try to look for tutorials written in Swift 3 (or download an older Xcode).

Tutorials are great, but they seldom teach you how to solve problems. That is when you have to rely on the debugger and Xcode errors. Try searching here for your errors, and if you still struggle with it then you can always post a question :P

Good luck with your app!

Body:
I'm trying to make an app for my church and am watching a bunch of YT tutorials but I'm getting a lot of errors:

import UIKit
import Firebase

class ViewController: UIViewController {
  @IBOutlet weak var emailField: UITextField!
  @IBOutlet weak var passwordField: UITextField!
  @IBOutlet weak var myWebView: UIWebView!

  @IBAction func Website(sender AnyObject) {

    if let url = NSURL(string: :"http://www.sermonaudio.com/source_detail.asp?sourceid=cfbc1")
    UIApplication.sharedApplication().openURL(url) {
    }

    var userUid: String!

    override func viewDidLoad() {
      super.viewDidLoad()
      // Do any additional setup after loading the view, typically from a nib.

      getVideo(videoCode: "qS6tvqL1N24")
    }

    override func didReceiveMemoryWarning() {
      super.didReceiveMemoryWarning()
      // Dispose of any resources that can be recreated.
    }

    func goToCreateUserVC(){
      performSegue(withIdentifier: "Feed", sender: nil)
    }
    func goToFeedVC() {
      performSegue(withIdentifier: "Feed", sender: nil)
    }
    func getVideo(videoCode:String!)
    {
      let url = URL(string: "https://www.youtube.com/embed/\(videoCode)")
      myWebView.loadRequest(URLRequest(url: url!))
    }
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
      if segue.identifier == "SignUp" {
        if let destination = segue.destination as? UserVC {
          if userUid != nil {
            destination.userUid = userUid
          }
          if emailField.text != nil {
            destination.emailField = emailField.text
          }
          if passwordField.text != nil {
            destination.passwordField = passwordField.text
          }
        }
      }
    }

    @IBAction func signInTapped(_ sender: Any){
      if let email = emailField.text, let password = passwordField.text {
        FIRAuth.auth()?.signIn(withEmail: email, password: password, completion:
          { (user,error) in
            if error == nil {
              if let user = user {
                self.userUid = user.uid
                self.goSignUpVC()
              }
            } else {
              self.goToCreateUserVC()
            }
        });
      }
    }
  }

}

Body:
Welcome to SO :) please post your code in the question next time, and you can embed your image file as well to help us see your question more easily.

You forgot to add an ":"
Website(sender: AnyObject)

On the next line down from that, you put your "{" one line down too far. It needs to go at the end of the if statement, not after the UIApplication.sharedApplication....

There are a couple of other punctuation errors too.

When you see an error saying "override can only be used in a class" that typically means you forgot a closing brace somewhere (which you did). You can select the whole program then do "Editor -> Structure -> Re-indent" which will help you to see where the scope issue is (this is how I fixed the override issue).

Make sure to read and pay attention to your error messages.. one of them clearly tells you that you are missing the "{" after your if statement, and when you see "expected expression" that means that whatever you wrote was gibberish to Swift (meaning you had a typo most likely, or left something incomplete).

I went ahead and edited your question for you, and fixed your code. I have not used hardly any of the stuff you are using (I program games), but I simply followed the directions Xcode gave me (the ones with the dot in the center tell you exactly how to fix it):

class ViewController: UIViewController {
  @IBOutlet weak var emailField: UITextField!
  @IBOutlet weak var passwordField: UITextField!
  @IBOutlet weak var myWebView: UIWebView!

  @IBAction func Website(sender: AnyObject) {

    if let url = URL(string: "http://www.sermonaudio.com/source_detail.asp?sourceid=cfbc1") {
      UIApplication.shared.openURL(url)
    }
  }
  var userUid: String!

  override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    getVideo(videoCode: "qS6tvqL1N24")
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
  }

  func goToCreateUserVC(){
    performSegue(withIdentifier: "Feed", sender: nil)
  }
  func goToFeedVC() {
    performSegue(withIdentifier: "Feed", sender: nil)
  }
  func getVideo(videoCode:String!)
  {
    let url = URL(string: "https://www.youtube.com/embed/\(videoCode)")
    myWebView.loadRequest(URLRequest(url: url!))
  }
  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "SignUp" {
      if let destination = segue.destination as? UserVC {
        if userUid != nil {
          destination.userUid = userUid
        }
        if emailField.text != nil {
          destination.emailField = emailField.text
        }
        if passwordField.text != nil {
          destination.passwordField = passwordField.text
        }
      }
    }
  }

  @IBAction func signInTapped(_ sender: Any){
    if let email = emailField.text, let password = passwordField.text {
      FIRAuth.auth()?.signIn(withEmail: email, password: password, completion:
        { (user,error) in
          if error == nil {
            if let user = user {
              self.userUid = user.uid
              self.goSignUpVC()
            }
          } else {
            self.goToCreateUserVC()
          }
      });
    }
  }
}

Also, it looks like this is older Swift code, hence why you are getting errors. Try to look for tutorials written in Swift 3 (or download an older Xcode).

Tutorials are great, but they seldom teach you how to solve problems. That is when you have to rely on the debugger and Xcode errors. Try searching here for your errors, and if you still struggle with it then you can always post a question :P

Good luck with your app!