Head and body
The <head> used to belong entirely to the theme. Core could not put a title, a
description or a canonical on a page, not even on a page core rendered itself,
unless the theme happened to print one. Every theme therefore reimplemented the
same block, and a theme that got it slightly wrong got it wrong on every page.
osc_head()
Section titled “osc_head()”Call it as the first thing inside <head>:
<head><?php osc_head(); ?><meta name="theme-color" content="#1b2c5e"></head>It prints, in order:
| Part | What |
|---|---|
charset |
<meta charset="utf-8"> |
viewport |
<meta name="viewport" content="width=device-width, initial-scale=1"> |
title |
<title> from meta_title(), escaped |
description |
<meta name="description">, omitted when there is none |
keywords |
<meta name="keywords">, omitted when there is none |
canonical |
<link rel="canonical">, omitted when there is none |
pagination |
<link rel="prev"> / <link rel="next"> on a search results page, omitted elsewhere |
feed |
<link rel="alternate" type="application/rss+xml">: the current search’s feed on a results page, the site’s elsewhere |
api |
<meta name="shopclass-api">: the REST API address and this page’s page token |
and then runs the header hook, which is where enqueued styles and scripts, the
robots meta, and everything plugins add come from.
Do not also call osc_run_hook('header'). osc_head() runs it, and a second
call prints every enqueued asset twice.
Keeping a part for yourself
Section titled “Keeping a part for yourself”Every part is opt-out. Declare only what you want to keep:
osc_add_theme_support('head', array('feed' => false));Anything not named stays on, so osc_add_theme_support('head') on its own means
“core owns all of it”. The declaration is also how core knows your head is
core-managed; osc_head() itself works whether or not you declared anything.
A theme that does not call osc_head() still gets the api tag from the header hook, unless it
declares 'api' => false.
A theme with no comments
Section titled “A theme with no comments”A theme that never shows listing comments says so:
osc_add_theme_support('comments', false);Settings → Comments then tells the owner the active theme shows no comments.
osc_body_class()
Section titled “osc_body_class()”<body <?php osc_body_class(); ?>>Prints the whole attribute, so a page with no classes prints nothing rather than
an empty class="". Core names the page for you:
- the page itself:
home,search,search-category,item,item-post,item-edit,item-contact,contact,custom,login,register,recover,forgot-password,user-public-profile,error-404 - an account view: its own class and a shared
user, so one selector reaches the whole signed-in area:user-dashboard,user-profile,user-items,user-alerts,user-change-email,user-change-password,user-change-username - a static page:
pageandpage-{internal name} - the visitor:
logged-inorlogged-out - the context:
lang-{locale},theme-{theme}, andrtlon a right-to-left locale
Pass your own alongside them, as a string or a list:
<body <?php osc_body_class('has-sidebar'); ?>>osc_body_class_list() returns the same classes as an array. Both pass through
the body_class filter, which receives the computed list and whatever the caller
passed. That is where a plugin adds one.
Every class is lowercased and reduced to [a-z0-9_-]; a static page’s internal
name is typed by an admin and lands in an attribute, so it is not trusted.
osc_language_attributes()
Section titled “osc_language_attributes()”<html <?php osc_language_attributes(); ?>>Prints lang="en-US" dir="ltr", with dir="rtl" on a right-to-left locale.
Filterable through language_attributes. Pass false to get the string back
instead of printing it.
None of this is required
Section titled “None of this is required”A theme that calls none of these behaves exactly as it did. They exist so a theme stops reimplementing them, and so core can describe a page it renders itself.
The place field
Section titled “The place field”<?php osc_place_field(); ?>Prints the Location field in the style the site chose (see below). Core owns the markup and the script; the
theme only places and styles it. On an edit page pass the listing:
osc_place_field(['item' => osc_item()]). Other keys: id, label, required,
class, part_class, hint_class, error_class, req_class, saved, account, style, error, errors and plain_ids (admin only).
required defaults to the Required location setting.
style is single, fields or dropdown. It defaults to the Location field
setting (osc_item_place_style()), and to single in the admin. part_class goes on each
level block of fields and dropdown. errors is a message per level (country, region,
city); the default is the form’s own. error wins over errors and shows under City.
single: one box that suggests cities fromGET /api/v1/citiesand sets the place when one is picked.fields: a country select, then a region box and a city box that suggest places.dropdown: country, region and city selects; each fills from the one before.
A theme that styles only the one box passes 'style' => 'single', so the site’s setting cannot
switch it to markup the theme has no CSS for.
On a one-country site fields and dropdown have no country control; a hidden countryId
holds the code. A level whose parent has no places is a text box when Only places from the
list is off, and an empty disabled select when it is on.
The form posts city (the text), cityId, regionId and countryId. An old
listing with a typed place also posts region and country as text. Read them
as before; nothing changes for the listing input.
fields and dropdown post countryId, regionId and cityId. region and city text are posted by fields, and by dropdown for a level that falls back to a text box. Their controls have ids {id}-country, {id}-region and {id}-city, never the bare
countryId, regionId or cityId.
Style these classes: oe-place (with oe-place--single, --fields or --dropdown, and is-picked), oe-place__part (one per level, with data-level), oe-place__legend, oe-place__select, oe-place__text (a dropdown level drawn as a text box), oe-place__live, oe-place__req, oe-place__box,
oe-place__input, oe-place__pin, oe-place__clear, oe-place__spin,
oe-place__hint, oe-place__note (and oe-place__note--picked),
oe-place__end, oe-place__saved, oe-field-error, and in the list
osc-ac-list, osc-ac-option, is-active, oe-place__name,
oe-place__region, oe-place__cc, oe-place__tick, oe-place__status (with
--more and --error) and the Try again button oe-place__retry. The list sits inside
the box at the input’s width.
When Only places from the list refuses a save, the error is one entry on
/city with the text “Pick your location from the list.”. In fields and dropdown the
entry is on /country, /region or /city, whichever level failed, and shows under that
level as {id}-{level}-error. The helper prints it itself; a theme that prints its own errors reads it with osc_form_error('/city').
With the option off, typed text is accepted and the field only suggests; the ids are then not checked against each other.