npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@ftchinese/ftc-header

v2.1.2

Published

FTC Header

Downloads

58

Readme

ftc-header

The responsive header component for FTChinese. There are three kinds of headers to choose.

This package provides both js and sass APIs for building these headers.

Install

cd yourProject
npm install "@ftchinese/ftc-header"

NOTE: Please ensure there is a package.json and a bower.json in the root of your project, which can be generated by npm init and bower init

Prepare the html

Before using our APIs, you may first prepare the html code.

Learn about the structure and the components of our header

At this part, I will introduce the root element and the html code fragments of the components of our header. They are just help you to understand the structure and configuration of ftc-header.If you do are not interested in them, you can skip this part and go direct to the next part:The 3 kinds of headers we provide.

The Root

The root element of ftc-header is a header, which should have the attribute data-ftc-component="ftc-header" and the class class="ftc-header":

<header class="ftc-header" data-ftc-component="ftc-header" data-ftc-header--no-js>
</header>

This is the base structure of all kinds of our headers. All the other data are in this header element.

The Lang:

This is a little component for choosing the language of our website, which is at the left of the top line of our header when home page is showed.

The pure html:

<div class="ftc-header__lang" data-ftc-component="ftc-header-lang">
  <ul class="ftc-header__lang-list ftc-header__lang-listdefault">
    
    <li class="ftc-header__lang-item">
      <a href=#>
        简体中文
      </a>
    </li>
    
    <li class="ftc-header__lang-item">
      <a href=http://big5.ftchinese.com/>
        繁体中文
      </a>
    </li>
    
    <li class="ftc-header__lang-item">
      <a href=https://www.ft.com/>
        英文
      </a>
    </li>
    
  </ul>
</div>

Or, if you use template, here is the nunjucks template:

<div class="ftc-header__lang" data-ftc-component="ftc-header-lang">
  <ul class="ftc-header__lang-list ftc-header__lang-listdefault">
    {% for onelang in header.lang.list %}
    <li class="ftc-header__lang-item">
      <a href={{onelang.url}}>
        {{onelang.name}}
      </a>
    </li>
    {% endfor%}
  </ul>
</div>

The Sign

The menu about sign in ,sign up or sign out.And if the user has signed in, showing the menu for registered user.

Pure html:

<div data-ftc-component="ftc-header-sign">
  <div class="ftc-header__sign-readermenu ftc-header__sign-visitormenu">
    <a class="ftc-header__sign-signin" href=http://user.ftchinese.com/login>
      登录
    </a>
    <a href=http://user.ftchinese.com/register>
      免费注册
    </a>
  </div>
  <div class="ftc-header__sign-readermenu ftc-header__sign-memebermenu ftc-header__sign--hide">
    <a href=/users/mystories>
      我的FT
    </a>
    <a href=/users/cp>
      设置
    </a>
    <a href=http://user.ftchinese.com/logout>
      登出
    </a>
  </div>
</div>

The Nunjucks version is easy, so is omitted here.

And there is another component related to the Sign menu: the loginOverlay. And click the "登录" in Sign will show the loginOverlay instead of navigation to the href if there is loginOVerlay code segment.

The LoginOverlay

Pure html:

<!-- The loginOverlay -->
<div class="ftc-header__loginoverlay" data-ftc-component="ftc-header-loginoverlay">
  <div class="ftc-header__loginoverlay-window">

    <div class="ftc-header__loginoverlay-title">
      登录
      <span class="ftc-header__loginoverlay-close">×</span>
    </div>

    <form method="post" class="ftc-header__loginoverlay-form" action="/users/login"><!-- Add your php file to handle the login or find the password, the "/users/login" is my case -->
      <div class="ftc-header__loginoverlay-item ftc-header__loginoverlay-username">
        <label for="ftcLoginUsername">
            电子邮件/用户名
        </label>
        <input type="text" name="username" id="ftcLoginUsername">
      </div>

      <div class="ftc-header__loginoverlay-item">
        <label for="ftcLoginPassword">
          密码
        </label>
        <input type="password" class="ftc-header__loginoverlay-oneline" name="password" id="ftcLoginPassword">
      </div>
     
      <div class="ftc-header__loginoverlay-saveandsub">
        <input class="ftc-header__loginoverlay-saveme" type="checkbox" class="checkbox" value="1" checked="checked" name="saveme" id="ftcLoginSaveme" >
        <label for="ftcLoginSaveme">记住我</label>

        <input class="ftc-header__loginoverlay-submit" type="submit" value="提交">
      </div>
    </form>
    
    <div class="ftc-header__loginoverlay-bottom">
      <div class="ftc-header__loginoverlay-bottomline">
        <a href="/users/findpassword"> 
          找回密码
        </a>
      </div>
      <div class="ftc-header__loginoverlay-bottomline">
        <a href="http://user.ftchinese.com/register">
          免费注册
        </a>
      </div>
    </div>
  </div>
</div>

The Search

It is for searching articles in our web.

<div class="ftc-header__search ftc-header__search-default  ftc-header__row" data-ftc-component="ftc-header-search" data-ftc--sticky >
  <div class="ftc-header__container">
  
    <form class="ftc-header__search-formregion" action=/search/ role="search"><!-- Add your php file to handle the search, in my case it is "/search/"-->
      <button class="ftc-header__search-searchbtn"></button>
      <div class="ftc-header__search-inputarea">
        <input class="ftc-header__search-input" type="search" placeholder=输入年月日‘xxxx-xx-xx’可搜索该日存档 >
      </div>
      </form>
    </form>
    <div class="ftc-header__search-switch">
    </div>
  </div>
</div>

The Nav

This is the most complicated part. And There are dynamic and static two modes you can choose.

1. dynamic version

The dynamic version is that the data about nav and the actions of nav are both written by js. So after you adding the js, you can change the channel and see the changing effect on a single page. The related js will be discussed later, and the html are very simple:

<nav class="ftc-header__nav" data-ftc-component="ftc-channelnav" role="navigation" aria-label="Main navigation">
  <ul class="ftc-header__nav-list ftc-header__nav-toplist" data-ftc--sticky>
  </ul>
  <ul class="ftc-header__nav-list ftc-header__nav-sublist">
  </ul>
</nav>
2. static version

The static version is that the data about nav are computed directly in html template. So I can only provide the templete and the data.

The Nunjucks template:

<nav class="ftc-header__nav" data-ftc-component="ftc-channelnav" role="navigation" aria-label="Main navigation">
  <ul class="ftc-header__nav-list ftc-header__nav-toplist" data-ftc--sticky>
    {% set subChannels = {} %} 
   
    {% for topChannel in header.nav.topChannels %}
     <li class={{'"ftc-header__nav-item ftc-header__nav-topitem ftc-header__nav-topitem-selected"' if header.nav.indexForSelectedTopChannel==topChannel.index else '"ftc-header__nav-item ftc-header__nav-topitem"'}} data-index={{topChannel.index}}>
        <a data-ftc--target-top href={{topChannel.url}} >{{topChannel.name}}</a>
        <ul class="ftc-header__nav-pushdownlist">
          {% for pushdownChannel in topChannel.subChannels %}
            <li class="ftc-header__nav-pushdownitem" data-index={{pushdownChannel.index}}><a data-ftc--target-pushdown href={{pushdownChannel.url}}>{{pushdownChannel.name}}</a></li>
          {% endfor %}
        </ul>
    </li>
      {% if header.nav.indexForSelectedTopChannel==topChannel.index %}
        {% set subChannels = topChannel.subChannels %}
      {% endif %}
    {% endfor %}
  </ul>
  <ul class="ftc-header__nav-list ftc-header__nav-sublist">
    {% for subChannel in subChannels %}
      <li class={{ '"ftc-header__nav-item ftc-header__nav-subitem ftc-header__nav-subitem-selected"' if header.nav.indexForSelectedSubChannel==subChannel.index else '"ftc-header__nav-item ftc-header__nav-subitem"' }} data-index={{subChannel.index}}>
          <a href={{subChannel.url}}>{{subChannel.name}}</a>
      </li>
    {% endfor %}
  </ul>
</nav>

And the data:

	"nav": {
    "indexForSelectedTopChannel": 0, //The index of top channel which is default selected.This "0" means the top channel "首页" is default selected.
    "indexForSelectedSubChannel": 8, //The index of sub channel which is default selected.This "8" means the sub channel "数据新闻" of the top channel "首页" is default selected.And if there are no subchannel selected ,it should be -1
    "topChannels": [
      {
        "name": "首页",
        "url": "#",
        "index":0,
        "subChannels":[
          {
            "name":"特别报道",
            "url":"http://www.ftchinese.com/channel/special.html",
            "index":0
          },
          {
            "name":"热门文章",
            "url":"http://www.ftchinese.com/channel/special.html",
            "index":1
          },
          ...
          {
            "name":"数据新闻",
            "url":"http://www.ftchinese.com/channel/datanews.html",
            "index":8
          },
          {
            "name":"FT研究院",
            "url":"http://www.ftchinese.com/m/marketing/intelligence.html",
            "index":9
          },
          {
            "name":"FT商城",
            "url":"https://shop193762308.taobao.com/",
            "index":10
          }
        ]  
      },
      {
        "name": "中国",
        "url": "http://www.ftchinese.com/channel/china.html",
        "index":1,
        "subChannels":[
          {
            "name":"政经",
            "url":"http://www.ftchinese.com/channel/chinareport.html",
            "index":0
          },
          ...
        ]
      },
      {
        "name": "全球",
        "url": "http://www.ftchinese.com/channel/world.html",
        "index":2
      },
	  ...
    ]
  }

Go here to see the nav prop to get the completed json data about ftc nav.

The 3 kinds of headers we provide

Full Header:

This is a kind of header which contains the full components of ftc header. And its nav is static, which is the same as our true header in our website.

This is the template (using nunjucks) for full header :

<header class="ftc-header" data-ftc-component="ftc-header" data-ftc-header--no-js>
  <!-- The top -->
	<div class="ftc-header__top ">
		<div class="ftc-header__container">
			{% if header.nav.indexForSelectedTopChannel == 0 and  header.nav.indexForSelectedSubChannel < 0 %}
				{% set isHome = "yes" %}
			{% else %}
				{% set isHome = "no" %}
			{% endif %}

			<div class={{'"ftc-header__top-column ftc-header__top-center ftc-header-hometitle"' if isHome == "yes" else '"ftc-header__top-column ftc-header__top-center ftc-header-tagtitle"'}} data-ftc-component="ftc-header-title">
          {{header.myTitle if isHome == "no" else " "}}
			</div>

    
			<div class="ftc-header__top-column ftc-header__top-left">
				{% if isHome == "yes" %}
					{% include "partials/lang.html" %}
				{% else %}
					<div class="ftc-header__brand">
					</div>
				{% endif %}
				
				<div class="ftc-header__hamburg" data-ftc-component="ftc-header-hamburg">
				</div>
			</div>
      
			<div class="ftc-header__top-column ftc-header__top-right">
				{% include "partials/sign.html" %}
			</div>
			
		</div>
	</div>

	{% if header.nav %}
   {% include "partials/navStatic.html" %}
	{% endif %}

	{% if header.search %}
		{% include "partials/search.html" %}
	{% endif %}

	{% include "partials/loginOverlay.html" %}

</header>

Using above template, you can write both home header and tag header.

If you use the home data, you may build a header which is just like the real header of the home page of our website. The data are like:

{
  "lang" :{
		"default":"简体中文",
		"list": [
			{ 
				"name":"简体中文",
				"url":"#"
			},
			{
				"name":"繁体中文",
				"url":"http://big5.ftchinese.com/"
			},
			{
				"name":"英文",
				"url":"https://www.ft.com/"
			}
		]
	},
	"signIn":{
		"url":"http://user.ftchinese.com/login",
		"word":"登录"
	},
	...
	"nav": {
    "indexForSelectedTopChannel": 0,
    "indexForSelectedSubChannel": -1,
    "topChannels": [
      {
        "name": "首页",
        "url": "http://www.ftchinese.com",
        "index":0,
        "subChannels":[
          {
            "name":"特别报道",
            "url":"http://www.ftchinese.com/channel/special.html",
            "index":0
          },
          {
            "name":"热门文章",
            "url":"http://www.ftchinese.com/channel/special.html",
            "index":1
          },
          ...
        ]
      },
      ...
    ]
  }
  ...

But in most cases, you may use the tag data as you are more likely to write another page with a special title which may belong to a top channel and a sub channel. The data are like this:

{
  "myTitle":"我的页面",

	"signIn":{
		"url":"http://user.ftchinese.com/login",
		"word":"登录"
	},
	...
	"nav": {
    "indexForSelectedTopChannel": 0,
    "indexForSelectedSubChannel": 8,
    "topChannels": [
      {
        "name": "首页",
        "url": "http://www.ftchinese.com",
        "index":0,
        "subChannels":[
          ...
        ]
      },
      ...
    ]
  }
  ...

The difference between the home and the tag data is the "indexForSelectedTopChannel" and the "indexForSelectedSubChannel"—— you can to go the part The nave > 2. static version to see more details, and you should provide the field **"myTitle" if you write the tag data.

Go to To home data and tag data to get the full json data of this two cases.

And if you do not want to use the template, go to html results to see the final html.

Simple Header

The Simple Header only contains the core part of FTC's header.

The template:

<header class="ftc-header" data-ftc-component="ftc-header" data-ftc-header--no-js>
  <!-- The top -->
	<div class="ftc-header__top ">
		<div class="ftc-header__container">

			<div class={{ '"ftc-header__top-column ftc-header__top-center ftc-header-tagtitle"'if header.myTitle else '"ftc-header__top-column ftc-header__top-center ftc-header-hometitle"' }} data-ftc-component="ftc-header-title">
				{{header.myTitle if header.myTitle }}
			</div>

			<div class="ftc-header__top-column ftc-header__top-right">
				{% include "partials/sign.html" %}
			</div>
			
		</div>
	</div>

	{% include "partials/loginOverlay.html" %}

</header>

The data:

{	
	"signIn":{
		"url":"http://user.ftchinese.com/login",
		"word":"登录"
	},
	"signUp":{
		"url":"http://user.ftchinese.com/register",
		"word":"免费注册"
	},
	"myFT":{
		"url":"/users/mystories",
		"word":"我的FT"
	},
	"mySet":{
		"url":"/users/cp",
		"word":"设置"
	},
	"signOut":{
		"url":"http://user.ftchinese.com/logout",
		"word":"登出"
	}

}

And if you want a Simple Header for tag data, you should only add the "myTitle" field.

Dynamic Header

The dynamic header is with the dynamic nav, which is not the real case with our website. But if you what to make a custom single page, the nav of which doesn't need to do some interactive with our website, you may choose this header.

The tempate:

<header class="ftc-header" data-ftc-component="ftc-header" data-ftc-header--no-js>

	<!-- The top -->
	<div class="ftc-header__top ">
		<div class="ftc-header__container">

			<div class="ftc-header__top-column ftc-header__top-center  ftc-header-hometitle" data-ftc-component="ftc-header-title">
			</div>

			<div class="ftc-header__top-column ftc-header__top-left">
				{% include "partials/lang.html" %}
				<div class="ftc-header__brand ftc-header--hide">
				</div>
				<div class="ftc-header__hamburg" data-ftc-component="ftc-header-hamburg">
				</div>
			</div>

			<div class="ftc-header__top-column ftc-header__top-right">
				{% include "partials/sign.html" %}
			</div>
			
		</div>
	</div>

	{% if header.nav %}
	  {% include "partials/navDynamic.html" %}
	{% endif %}

	{% if header.search %}
		{% include "partials/search.html" %}
	{% endif %}
</header>

{% include "partials/loginOverlay.html" %}

The data:

{
	"lang" :{
		"default":"简体中文",
		"list": [
			{ 
				"name":"简体中文",
				"url":"#"
			},
			{
				"name":"繁体中文",
				"url":"http://big5.ftchinese.com/"
			},
			{
				"name":"英文",
				"url":"https://www.ft.com/"
			}
		]
	},
	
	"signIn":{
		"url":"http://user.ftchinese.com/login",
		"word":"登录"
	},
	"signUp":{
		"url":"http://user.ftchinese.com/register",
		"word":"免费注册"
	},
	"myFT":{
		"url":"/users/mystories",
		"word":"我的FT"
	},
	"mySet":{
		"url":"/users/cp",
		"word":"设置"
	},
	"signOut":{
		"url":"http://user.ftchinese.com/logout",
		"word":"登出"
	},

	"nav": true, 

	"search": {
		"actionUrl":"/search/",
		"placeholderText":"输入年月日‘xxxx-xx-xx’可搜索该日存档"
	}

}

And go here to see the final html.

API for JS

For Full Header

import {FullHeader} from '@ftchinese/ftc-header';

FullHeader.init();

For Simple Header

import {SimpleHeader} from '@ftchinese/ftc-header';

SimpleHeader.init();

For Dynamic Header

import {DynamicHeader} from '@ftchinese/ftc-header';

DynamicHeader.init();

The above method will use the default provided nav data.

If you want to define the nav data by your self, please set the navData to cover the default data before calling DynamicHeader.init() :

import {DynamicHeader} from '@ftchinese/ftc-header';

//Set the navData constant for the nav's js dynamic generation. The navData should be set  by this pattern:
var navData = {
	"indexForSelectedTopChannel": 0, // The default selected top channel index.
  "topChannels": [
    {
      "name": "首页",
      "url": "#",
      "index":0,
      "subChannels":[
        {
          "name":"特别报道",
          "url":"#",
          "index":0
        },
        {
          "name":"热门文章",
          "url":"#",
          "index":1
        },
        ...
      ]  
    },
    {
      "name": "中国",
      "url": "#",
      "index":1,
      "subChannels":[
        {
          "name":"政经",
          "url":"#",
          "index":0
        },
        ...
      ]
    },
    {
      "name": "全球",
      "url": "#",
      "index":2
    },
    {
      "name": "经济",
      "url": "#",
      "index":3
    },
		...
  ]
}

DynamicHeader.init();

API for SCSS

The simplest way is to set the $ftc-header-is-silent to be false, and what you need to do is just import the main.scss

$ftc-header-is-silent: false;

@import '@ftchinese/ftc-header/main.scss';

These is propably suitbale for the Full Header and the Dynamic Header.

As for Simple Header, you may choose to include the mixin as you need:

$ftc-header-is-silent: true;

@import '@ftchinese/ftc-header/main.scss';

@include ftcHeaderBase;
@include ftcHeaderTop;
@include ftcHeaderLoginOverlay;