    001/*
    002    Licensed to the Apache Software Foundation (ASF) under one
    003    or more contributor license agreements.  See the NOTICE file
    004    distributed with this work for additional information
    005    regarding copyright ownership.  The ASF licenses this file
    006    to you under the Apache License, Version 2.0 (the
    007    "License"); you may not use this file except in compliance
    008    with the License.  You may obtain a copy of the License at
    009
    010       http://www.apache.org/licenses/LICENSE-2.0
    011
    012    Unless required by applicable law or agreed to in writing,
    013    software distributed under the License is distributed on an
    014    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015    KIND, either express or implied.  See the License for the
    016    specific language governing permissions and limitations
    017    under the License.
    018 */
    019
    020package org.apache.wiki.tags;
    021
    022import org.apache.wiki.util.TextUtil;
    023
    024import jakarta.servlet.jsp.JspTagException;
    025import java.io.IOException;
    026
    027/**
    028 *  Generates single tabbed page layout. Works together with the tabbedSection javascript.  Note that if you do not
    029 *  specify an url, the body contents of the tag are loaded by the tag itself.
    030 *
    031 *  <P><B>Attributes</B></P>
    032 *  <UL>
    033 *    <LI>id - ID for this tab. (mandatory)
    034 *    <LI>title - Title of this tab. (mandatory)
    035 *    <LI>accesskey - Single char usable as quick accesskey (alt- or ctrl-) (optional)
    036 *    <li>url - If you <i>don't</i> want to create a Javascript-enabled tag, you can use this
    037 *              to make the tab look just the usual tag, but instead, it will actually link
    038 *              to that page.  This can be useful in certain cases where you have something
    039 *              that you want to look like a part of a tag, but for example, due to it being
    040 *              very big in size, don't want to include it as a part of the page content
    041 *              every time.
    042 *  </UL>
    043 *
    044 *  @since v2.3.63
    045 */
    046public class TabTag extends WikiTagBase {
    047
    048    private static final long serialVersionUID = -8534125226484616489L;
    049    private String m_accesskey;
    050    private String m_tabTitle;
    051    private String m_url;
    052
    053    /**
    054     * {@inheritDoc}
    055     */
    056    @Override
    057    public void doFinally() {
    058        super.doFinally();
    059
    060        m_accesskey = null;
    061        m_tabTitle  = null;
    062        m_url       = null;
    063    }
    064
    065    /**
    066     * Sets the tab title.
    067     * @param aTabTitle the tab title
    068     */
    069    public void setTitle( final String aTabTitle ) {
    070        m_tabTitle = TextUtil.replaceEntities( aTabTitle );
    071    }
    072
    073    /**
    074     * Sets the tab access key.
    075     *
    076     * @param anAccesskey the access key
    077     */
    078    public void setAccesskey( final String anAccesskey ) {
    079        m_accesskey = TextUtil.replaceEntities( anAccesskey ); //take only the first char
    080    }
    081
    082    /**
    083     * Sets the tab URL.
    084     *
    085     * @param url the URL
    086     */
    087    public void setUrl( final String url ) {
    088        m_url = TextUtil.replaceEntities( url );
    089    }
    090
    091    // insert <u> ..accesskey.. </u> in title
    092    private boolean handleAccesskey() {
    093        if( ( m_tabTitle == null ) || ( m_accesskey == null ) ) return false;
    094
    095        final int pos = m_tabTitle.toLowerCase().indexOf( m_accesskey.toLowerCase() );
    096        if( pos > -1 ) {
    097            m_tabTitle = m_tabTitle.substring( 0, pos ) + "<span class='accesskey'>"
    098                    + m_tabTitle.charAt( pos ) + "</span>" + m_tabTitle.substring( pos + 1 );
    099        }
    100        return true;
    101    }
    102
    103    /**
    104     * {@inheritDoc}
    105     */
    106    @Override
    107    public int doWikiStartTag() throws JspTagException {
    108        final TabbedSectionTag parent = ( TabbedSectionTag ) findAncestorWithClass( this, TabbedSectionTag.class );
    109
    110        //  Sanity checks
    111        if( getId() == null ) {
    112            throw new JspTagException( "Tab Tag without \"id\" attribute" );
    113        }
    114        if( m_tabTitle == null ) {
    115            throw new JspTagException( "Tab Tag without \"tabTitle\" attribute" );
    116        }
    117        if( parent == null ) {
    118            throw new JspTagException( "Tab Tag without parent \"TabbedSection\" Tag" );
    119        }
    120        if( !parent.isStateGenerateTabBody() ) {
    121            return SKIP_BODY;
    122        }
    123
    124        final StringBuilder sb = new StringBuilder( 32 );
    125        sb.append( "<div id=\"" ).append( getId() ).append( "\"" );
    126        if( !parent.validateDefaultTab( getId() ) ) {
    127            sb.append( " class=\"hidetab\"" );
    128        }
    129        sb.append( " >\n" );
    130
    131        try {
    132            pageContext.getOut().write( sb.toString() );
    133        } catch( final IOException e ) {
    134            throw new JspTagException( "IO Error: " + e.getMessage() );
    135        }
    136
    137        return EVAL_BODY_INCLUDE;
    138    }
    139
    140    /**
    141     * {@inheritDoc}
    142     */
    143    @Override
    144    public int doEndTag() throws JspTagException {
    145        final TabbedSectionTag parent = ( TabbedSectionTag ) findAncestorWithClass( this, TabbedSectionTag.class );
    146        final StringBuilder sb = new StringBuilder();
    147        if( parent.isStateFindDefaultTab() ) {
    148            // inform the parent of each tab
    149            parent.validateDefaultTab( getId() );
    150        } else if( parent.isStateGenerateTabBody() ) {
    151            sb.append( "</div>\n" );
    152        } else if( parent.isStateGenerateTabMenu() ) {
    153            sb.append( "<a" );
    154            if( parent.validateDefaultTab( getId() ) ) {
    155                sb.append( " class=\"activetab\"" );
    156            }
    157
    158            sb.append( " id=\"menu-" ).append( getId() ).append( "\"" );
    159
    160            if( m_url != null ) {
    161                sb.append( " href='" ).append( m_url ).append( "'" );
    162            }
    163
    164            if( handleAccesskey() ) {
    165                sb.append( " accesskey=\"" ).append( m_accesskey ).append( "\"" );
    166            }
    167
    168            sb.append( " >" );
    169            sb.append( m_tabTitle );
    170            sb.append( "</a>" );
    171        }
    172
    173        try {
    174            pageContext.getOut().write( sb.toString() );
    175        } catch( final IOException e ) {
    176            throw new JspTagException( "IO Error: " + e.getMessage() );
    177        }
    178
    179        return EVAL_PAGE;
    180    }
    181
    182}