in wordpress, I am fetching menu using wp_nav_menu() function. It will list menus in following form.
<ul>
<li>AA</li>
<li>BB</li>
<li>CC</li>
</ul>
I want to add one more property to tag. I want it in following form.
<a href="url" name="aa">AA</li>
<a href="url" name="bb">BB</li>
<a href="url" name="cc">CC</li>
name property should have value equal to link text but in lower case. i.e. is menu text is AA then name property should have aa
You can do this with Wordpress Walkers. They can be a bit tricky at first, but very powerful. This is a rough implementation, you would probably need to improve it.
First, you extend the Walker_Nav_Menu to your needs:
class my_nav_menu extends Walker_Nav_Menu
{
function start_el(&$output, $item, $depth, $args)
{
$output .= '<li><a href="' . get_post_link($item->ID) . '" name="' . $item->post_name .'" >';
$output .= apply_filters( 'the_title', $item->post_title, $item->ID ) ;
$output .= '</a></li>';
}
}
Then you pass an instance of your class to wp_nav_menu:
wp_nav_menu( array( 'container_class' => 'menu-header', 'theme_location' => 'primary' , 'walker' => new my_nav_menu() ) );
This will output menu elements like this:
<li><a name="test-page" href="http://mydomain.foo/?page_id=1">Test Page</a></li>
Related
I'm very beginner with Timber.
I want to redo (reproduce) one of my wordpress themes with Timber.
I try to call a theme_mod in my template but nothing is showing up.
Any answer or advise would be appréciate.
My original wp header.php
//***********************************Phone******************************************************//
$idbbase_very_top_header_phone = get_theme_mod( 'idbbase_very_top_header_phone', esc_html__( '(+9) 0999.500.400', 'idweb' ) );
$idbbase_very_top_header_phone = apply_filters( 'idbbase_translate_single_string', $idbbase_very_top_header_phone, 'Very Top Header' );
$idbbase_very_top_header_phone_text = get_theme_mod( 'idbbase_very_top_header_phone_text', esc_html__( 'Call us: ', 'idweb' ) );
$idbbase_very_top_header_phone_text = apply_filters( 'idbbase_translate_single_string', $idbbase_very_top_header_phone_text, 'Very Top Header' );
if ( ! empty( $idbbase_very_top_header_phone ) || ! empty( $idbbase_very_top_header_phone_text ) ) {
echo '<div class='.$class.'><i class="fa fa-phone"></i>';
echo '<span><strong class="idbbase_very_top_header_phone_text">';
echo $idbbase_very_top_header_phone_text.'</strong>';
echo '<p class="idbbase_very_top">' .wp_kses( $idbbase_very_top_header_phone, 'post', $allowed_protocols ) . '</p></span>';
echo '</div>';
} elseif ( isset( $wp_customize ) ) {
echo '<div id="idbbase_very_top_header_phone" class="idbbase_only_customizer '.$class.'"><span><strong>'.$idbbase_very_top_header_phone_text.'</strong><p class="idbbase_very_top_header_phone_text">' .wp_kses( $idbbase_very_top_header_phone, 'post', $allowed_protocols ) . '</p></span></div>';
}
My Timber header.php
//*************Phone******************************************************//
$idagency_very_top_header_phone = get_theme_mod(
'idagency_very_top_header_phone', esc_html__( '(+9) 0999.500.400', 'idweb' )
);
$idagency_very_top_header_phone2 = apply_filters(
'idagency_translate_single_string', $idagency_very_top_header_phone, 'Very
Top Header' );
$idagency_very_top_header_phone_text = get_theme_mod(
'idagency_very_top_header_phone_text', esc_html__( 'Call us: ', 'idweb' ) );
$idagency_very_top_header_phone_text2 = apply_filters(
'idagency_translate_single_string', $idagency_very_top_header_phone_text,
'Very Top Header' );
$context['idagency_very_top_header_phone'] =
$idagency_very_top_header_phone;
$context['idagency_very_top_header_phone'] =
$idagency_very_top_header_phone2;
$context['idagency_very_top_header_phone_text'] =
$idagency_very_top_header_phone_text;
$context['idagency_very_top_header_phone_text'] =
$idagency_very_top_header_phone_text2;
$GLOBALS['timberContext'] = Timber::get_context();
ob_start();
Timber::render( 'base.twig', $context );
My base.twig
{% if idbbase_very_top_header_phone %}
<div class="col-md-3">
<a href="#">
<i class="fa fa-phone"></i>
</a>
<span>
<strong>{{ idbbase_very_top_header_phone_text }}</strong>
<p>{{ idbbase_very_top_header_phone }}</p>
</span>
</div>
{% endif %}
Timber's philosophy of separating data from markup requires a significant conceptual shift when compared to the standard Wordpress template architecture.
The root of your problem is that you are treating your header like a template when it is actually a partial.
In Timber terms, a template corresponds to a post or an archive and consists of two files:
A Twig file with your html markup mixed with some variables and logic, and a PHP file that, at minimum, defines the following:
The Timber context for a given post generated with Timber::context() (formerly get_context(), which has been deprecated)
Which twig file (or files) should be used to render the template
The very simplest Timber PHP template file could look like this:
<?php
/*
* This is the `single.php` template
*/
$context = Timber::context();
Timber::render( 'single.twig', $context );
This would generate the rendered contents of single.twig along with some global context values. In order to pass real values to the template, you have to assign them to $context, as you have attempted to do with $context['idagency_very_top_header_phone'], etc. However, these values cannot be assigned at the level of a partial — they must be assigned at the template level or higher.
To do what you are trying to do, you're going to need to set up a template (e.g. single.php and single.twig), and then include the header.twig file inside your template Twig file using {% include 'header.twig' %}.
Then you need to define your context values so that they are available to single.twig and all of its included partials, which in this case would include header.twig. You can define these directly inside the single.php file, after $context is defined. For simplicity, I'm only defining one of your values:
/* single.php */
$context = Timber::context();
$idagency_very_top_header_phone = get_theme_mod(
'idagency_very_top_header_phone',
esc_html__( '(+9) 0999.500.400', 'idweb')
);
$context['idagency_very_top_header_phone'] = $idagency_very_top_header_phone;
Timber::render( 'single.twig', $context );
If you need these values to be global across all templates, you can also define them in your theme's functions.php using the (poorly documented) timber/context filter. Then the values will be available in any template where that Timber::context() is used:
/* This would be placed in your functions.php file
* (or a separate file that's been included in functions.php)
*/
add_filter( 'timber/context', function( $context ) {
$idagency_very_top_header_phone = get_theme_mod(
'idagency_very_top_header_phone',
esc_html__( '(+9) 0999.500.400', 'idweb')
);
$context['idagency_very_top_header_phone'] = $idagency_very_top_header_phone;
return $context;
} );
This leaves out some key steps for setting up a full template, like including the data from the actual post, but that is all decently documented in Timber's Getting Started guide.
The key, TL;DR points are:
The Timber context is defined once per post
The context and all of its values are passed directly from the post's PHP template to its Twig template
Twig partials are not tied directly to partial-specific PHP files.
Partials included within a Twig template inherit the Timber context from that template. The same goes for partials nested within those partials.
This is late, but for any future dwellers, the above answers only show how to do it the WordPress way in timber, whereas, there's a simpler native way to achieve this in timber.
This is how you can get any current theme mod in timber twig view files natively:
{{ site.theme.theme_mod('mod_name_here') }}
How it works: Timber supplies the current theme object in the default global object (you don't need to add this manually, anywhere).
From Timber's documentation (here), timber theme object has this method: theme_mod
Hope this helps anyone stuck in future.
We have a selectize field where multiple values can be selected. These values are grouped in optgroups. To ease understanding, some values can be in multiple optgroups, we would like to see the name of the optgroup in the labels for the selected fields, too. How can we accomplish this?
See following fiddle, if you select "First Item" you do not know which one was selected, Store or Warehouse.
Thanks!
https://jsfiddle.net/4t8fjj7g/1/
HTML:
<select name="test" id="test-select" multiple="multiple">
<optgroup label="Store">
<option data-type="stores" value="1">First item</option>
<option data-type="stores" value="2">Second item</option>
</optgroup>
<optgroup label="Warehouse">
<option data-type="warehouses" value="3">First item</option>
<option data-type="warehouses" value="4">Second item</option>
</optgroup>
</select>
And this is the javascript code:
$('select#test-select').selectize({
searchField: ['text', 'type']
});
Basically, what Daffy has suggested, BUT...
You can use custom rendering functions for dropdown options and for selected items:
$('select#test-select').selectize({
searchField: ['text', 'type'],
render: {
item: itemRenderFunction,
option: optionRenderFunction
}
});
This will allow you to avoid label multiplication in selected items list.
What I did is have the values have the optgroup then the value like optgroup_value then when the form gets submitted on the server or doing something in JS I can get it by exploding the string like:
<select multiple class="my-select">
<optgroup label="taxes">
<?php foreach ( $taxes as $tax) : ?>
<option value="tax_<?php echo $tax->slug; ?>"><?php echo $tax->name; ?></option>
<?php endforeach; ?>
</optgroup>
<optgroup label="Version">
<?php foreach ( $my_versions as $version ) : ?>
<option value="version_<?php echo $version->slug; ?>"><?php echo $version->name; ?></option>
<?php endforeach; ?>
</optgroup>
<optgroup label="Language">
<?php foreach ( $my_languages as $language ) : ?>
<option value="language_<?php echo $language->slug; ?>"><?php echo $language->name; ?></option>
<?php endforeach; ?>
</optgroup>
</select>
then
<?php
foreach ( $_POST['taxes'] as $val ) {
if ( ! empty( $val ) ) {
// $val_parts is an array with
// $val_parts[0] = optgroup only
// $val_parts[1] = the value of the option minus optgroup
$val_parts = explode( "_", $val );
// My use case to add a meta_query to a WP_Query so add filter based on both values
$meta_arg = array(
'taxonomy' => "my_" . $val_parts[0], // custom prefix then optgroup
'field' => 'slug',
'terms' => $val_parts[1] // value
);
// Add to running array and possibly do again
array_push( $args['tax_query'], $meta_arg );
}
}
When using an asset publisher, you can change Display Settings in the asset publisher configuration panel. If you select the Abstracts display template, a new option will be available for you (Abstract Length). How can I add an option like that to my Application Display Templates (ADT) ?
Example for the Abstracts template :
Example for my custom template (Abstract Length not available):
You can use substring in velocity code written inside ADT built for news asset publisher, check below code to display 100 character only of about us page
#if (!$entries.isEmpty())
<div class="news">
#foreach ($entry in $entries)
#set($renderer = $entry.getAssetRenderer() )
#set($className = $renderer.getClassName() )
#if( $className == "com.liferay.portlet.journal.model.JournalArticle" )
#set( $journalArticle = $renderer.getArticle() )
#set( $document = $saxReaderUtil.read($journalArticle.getContent()) )
#set( $rootElement = $document.getRootElement() )
#set( $xPathSelector = $saxReaderUtil.createXPath("dynamic-element[#name='country-portal-image']") )
#set( $countryPortalImage = $xPathSelector.selectSingleNode($rootElement).getStringValue() )
#set( $xPathSelector = $saxReaderUtil.createXPath("dynamic-element[#name='country-portal-title']") )
#set( $countryPortalTitle = $xPathSelector.selectSingleNode($rootElement).getStringValue() )
#set( $xPathSelector = $saxReaderUtil.createXPath("dynamic-element[#name='country-flag-icon']") )
#set( $countryFlagIcon = $xPathSelector.selectSingleNode($rootElement).getStringValue() )
#set( $xPathSelector = $saxReaderUtil.createXPath("dynamic-element[#name='country-portal-about-us']") )
#set( $countryPortalAboutUs = $xPathSelector.selectSingleNode($rootElement).getStringValue().substring(0,100) )
#set( $link = $renderer.getURLViewInContext($renderRequest, $renderResponse, '') )
#set( $viewURL = $assetPublisherHelper.getAssetViewURL($renderRequest, $renderResponse, $entry))
#set($news-summary =$entry.getSummary($locale))
#set($date = $dateTool.format("dd/MM/yyyy hh:mm:ss", $dateTool.toDate( "EEE, dd MMM yyyy hh:mm:ss Z" , $entry.getPublishDate())))
<div class="new">
<h1 class="title">$entry.getTitle($locale)</h1>
$date
<img src="$countryFlagIcon"/>
<img src="$countryPortalImage"/>
<h3 class="sub-title">$countryPortalAboutUs</h3>
<p class="read-more">
Read More
</p>
</div>
#end
#end
</div>
#end
You can create JSP hook to customize Asset Publisher configuration.
The original configuration is rendered by /html/portlet/asset_publisher/configuration.portal.jsp.
In your hook, you can include the original jsp and then add your own preferences.
Example:
<%-- Include the original Asset Publisher configuration JSP. --%>
<%#include file="/html/portlet/asset_publisher/configuration.portal.jsp"%>
<%-- Read current value from portlet preferences. --%>
<% String abstractLength = portletPreferences.getValue("abstractLength", "100"); %>
<%-- Hidden div with custom input fields. --%>
<div id="customPreferences" style="display: none;">
<aui:fieldset label="fieldset.abstractLength">
<aui:input name="abstractLength" label="abstractLength" value="<%= abstractLength %>">
<aui:validator name="number"/>
<aui:validator name="min">1</aui:validator>
</aui:input>
</aui:fieldset>
</div>
<%-- JS code to place custom preferences at the end of Display Settings tab. --%>
<%-- It uses jQuery, but it's not a requirement. --%>
<script>
$(document).ready(function () {
// find div with custom preferences
var $customPreferences = $("#customPreferences");
// find the last fieldset on Display Settings tab
var displaySettingsLastFieldset = $(".nav-tabs:eq(1)").siblings("div:eq(1)").children().filter("fieldset").last();
// insert custom preferences after the last fieldset on Display Settings tab
$customPreferences.insertAfter(displaySettingsLastFieldset);
// show custom preferences
$customPreferences.show();
});
</script>
It is a good approach to extend the original JSPs - ie. include the original and then make the customization. This way, there's a good chance of a painless update to next Liferay versions.
For general guidelines on how to implement JSP hooks, see Liferay Developer's Guide.
You can get a list of all the available portletPreference values available to the asset publisher ADT using:
<#list portletPreferences?keys as prop >
<li>
${prop}
</li>
</#list>
So, for your example, you could get the abstract length value set by the user using:
abstractLength: ${portletPreferences.abstractLength[0]}
best way if you creating your own ADT then manage content length in ADT instead of unnecessarily hooking of AP jsp.
I am using this function to create a date input
public static function date($name, $value = null, $options = array()) {
$input = '<input type="date" name="' . $name . '" value="' . $value . '"';
foreach ($options as $key => $value) {
$input .= ' ' . $key . '="' . $value . '"';
}
$input .= '>';
return $input;
}
And then in my view
<div class="form-group">
{{ Form::label('sgs', Lang::get('messages.sgs').'*', array('class'=>'control-label col-lg-4')) }}
<div class="col-lg-8">
{{ Helpers\Helper::date('sgs', isset($v->sgs) ? $v->sgs : '' , array(
'class' => 'form-control'))
}}
</div>
</div>
In Google Chrome it works, and displays datepicker which is displayed by clicking at a arrow, the problem is with Mozilla Firefox which doesnt displays datepicker and just displays it as a simple input field. Why is happening this
The HTML5 DatePicker is not supported in Firefox. Therefore, you will need to use some custom DatePicker plugin. You can see this for the compatibility reference:
http://caniuse.com/#feat=input-datetime
i am new to concrete 5, i search alot for theming of Menu (i.e: sub menu's) navigation with image icon and description but not found any related material. i have the following Html:
<div class="menu">
<ul>
<li><span>Hem</span></li>
<ul>
<li><span>New</span><img href="images/first.jpg" /><span class='short-description'>some description</span></li>
<li><span>Nice</span></li>
</ul>
<li><span>Om oss</span></li>
<ul>
<li><span>Om Shine</span><img href="images/second.jpg" /><span class='short-description'>some description</span></li>
<li><span>Uom</span></li>
<li><span>Opasd</span><img href="images/third.jpg" /><span class='short-description'>some description</span></li>
<li><span>Hem</span></li>
</ul>
<li><span>Tjänster</span></li>
<li><span>Referenser</span></li>
<li><span> Kontakt</span></li>
</ul>
</div>
So how i can theme for this in concrete 5. or use like.
<div id="headerNav">
<?php
$a = new Area('Header Nav');
$a->display($c);
?>
</div>
Any idea about it, that how to theme for this in concrete 5 for sub menus with description and image icon.... Thanx.
Open file concrete\concrete\blocks\autonav, and changed line
if ($c->getCollectionID() == $_c->getCollectionID()) {
echo('<li class="nav-selected nav-path-selected"><a class="nav-selected nav-path-selected" ' . $target . ' href="' . $pageLink . '">' . $ni->getName() . '</a>');
}
Apply your active class in " tag like
if ($c->getCollectionID() == $_c->getCollectionID()) {
echo('<li class="nav-selected nav-path-selected"><a class="active" ' . $target . ' href="' . $pageLink . '">' . $ni->getName() . '</a>');
}