Jump to content

Extending UIKit 3 markup functions based on Ryans site profile


Juergen
 Share

Recommended Posts

Hello @all,

I am using UIKit now for over a year and I am totally satisfied. Ryan has created a site profile with UIKit 3 (https://processwire.com/blog/posts/introducing-a-new-processwire-site-profile/) where he uses a lot of markup functions to simplify content creation.

Here is the function file of Ryan: https://github.com/ryancramerdesign/regular/blob/master/site-regular/templates/_uikit.php

I want to start this topic for all users, who are also using UIKit 3 and want to share additional markup functions to extend Ryans function file. So everyone who use the new UIKit 3 framework can benefit from it.

I want to start with functions to render different types of buttons:

 

Render UIKit buttons

Render UIKit buttons corresponding to https://getuikit.com/docs/button

/**
 * Render a uikit button
 * 
 * @param string $text Text for the button
 * @param string $style Specify one of: default, primary, secondary, danger, text, link. 
 * @param array $options Optionally specify different options to the button. 
 * @return string
 * 
 */
 
function ukButton($text, $style = '', $options = array()) {
  if(!$text) return;
  $defaultoptions = array(
    'tag' => 'button', //button or a tag
    'type' => '', //optional button type attribute fe submit
    'name' => '', //optional name attribute fe if button is inside form
    'disabled' => false, //optional true or false
    'href' => '', //optional href attribute; works with button and a tag, but recommended only with a tag
    'rel' => '', //optional rel attribute fe nofollow
    'icon' => '', //optional icon fe user, unlock
    'class' => '', //optional additional class attribute fe uk-width-1-1, uk-button-small or uk-margin-small-bottom
    'id' => '', //optional id attribute
    'wrapper' => false, //optional add a wrapper div arround the button
    'wrapperclass' => '' //optional add a class to the wrapper div fe alignment or margin
  );
  $options  = _ukMergeOptions($defaultoptions, $options);
  $out = '';
  if($options['wrapper'] == true){   
    $out .= (!empty($options['wrapperclass'])) ? '<div class="'.$options['wrapperclass'].'">' : '<div>';
  }
  $out .= ($options['tag']) ? '<'.$options['tag'].' class="uk-button' : '<button class="uk-button';
  $out .= (!empty($style)) ? ' '.$style : ' uk-button-default'; 
  $out .= (!empty($options['class'])) ? ' '.$options['class'].'"' : '"';
  if(!empty($options['id'])) $out .= ' id="'.$options['id'].'"';
  if($options['disabled'] == true) $out .= ' disabled';
  if(!empty($options['name'])) $out .= ' name="'.$options['name'].'"';
  if($options['tag'] == 'a'){
  if(!empty($options['href'])) $out.= ' href="'.$options['href'].'"';
  } else {
    $out .= ' onclick="window.location.href=\''.$options['href'].'\'"';
  }
  if((!empty($options['href'])) && (!empty($options['rel']))) $out .= ' rel="'.$options['rel'].'"';
  if(!empty($options['type'])) $out .= ' type="'.$options['type'].'"';
  $out .= '>';
  if(!empty($options['icon'])) $out .= ukIcon($options['icon']) . ' ';
  $out .= $text;
  $out .= ($options['tag']) ? '</'.$options['tag'].'>' : '</button>';
  if($options['wrapper'] == true) $out .= '</div>';
  return $out;
}

/**
 * Render a primary button; 
 * 
 * @param string $text
 * @param array $options
 * @return string
 * 
 */ 
function ukButtonPrimary($text, $options = array()) {
	return ukButton($text, 'uk-button-primary', $options); 
}

/**
 * Render a secondary button; 
 * 
 * @param string $text
 * @param array $options
 * @return string
 * 
 */ 
function ukButtonSecondary($text, $options = array()) {
	return ukButton($text, 'uk-button-secondary', $options); 
}

/**
 * Render a danger button; 
 * 
 * @param string $text
 * @param array $options
 * @return string
 * 
 */ 
function ukButtonDanger($text, $options = array()) {
	return ukButton($text, 'uk-button-danger', $options); 
}

/**
 * Render a text button; 
 * 
 * @param string $text
 * @param array $options
 * @return string
 * 
 */ 
function ukButtonText($text, $options = array()) {
	return ukButton($text, 'uk-button-text', $options); 
}

/**
 * Render a link button; 
 * 
 * @param string $text
 * @param array $options
 * @return string
 * 
 */ 
function ukButtonLink($text, $options = array()) {
	return ukButton($text, 'uk-button-link', $options); 
}

This code snippet uses functions from Ryans code (ukIcon() and _ukMergeOptions()), so please be sure that this functions are included in your function file as well.

It would be great if other users can also post their UIKit markup functions (if you have created ones) to extend the collection. :)

Best regards

  • Like 7
Link to comment
Share on other sites

Render UIKit list

Here is another function to create various types of lists corresponding to https://getuikit.com/docs/list

/**
 * Render a uikit list
 * 
 * @param array $listitems All list items as an array, you can also use html inside the array (fe links)
 * @param array $options Optionally specify different options to list. 
 * @return string
 * 
 */
function ukList($listitems = array(), $options = array()) {
  if(count($listitems) == 0) return;
    $defaults = array( 
        'divider' => false, 
        'bullet' => false, 
        'striped' => false,
        'large' => false,  
        'icon' => '', // icon to display before list items
        'class' => '' // add custom class to list item
    );
    $options = _ukMergeOptions($defaults, $options);
  $out = ''; 
    $classes = array();
    if($options['class']) $classes = explode(' ', $options['class']);    
    if($options['divider']) $classes[] = 'uk-list-divider';
    if($options['bullet']) $classes[] = 'uk-list-bullet';
  if($options['striped']) $classes[] = 'uk-list-striped';
  if($options['large']) $classes[] = 'uk-list-large';
    if(count($classes)) {
        $class = ' ' . implode(' ', $classes);
    } else {
        $class = '';
    }    
    $out .= '<ul class="uk-list'.$class.'">';
  foreach($listitems as $listitem) {
     $out .= '<li>';
     $icon = (!empty($options['icon'])) ? ukIcon($options['icon']).' ' : '';
     $out .= $icon.$listitem.'</li>';
  }
  $out .= '</ul>';
  return $out;
}

 

Usage examples:

echo ukList($page->children); //creates a simple unstyled list of all child pages ids

echo ukList($page->children, $options = array('icon' => 'heart', 'striped' => true, 'large' => true)); //creates a striped list, with heart icon in front and a larger margin

 

  • Like 4
  • Thanks 1
Link to comment
Share on other sites

  • 1 year later...

Hello!!!

This is great!!!

I use the uikit.php too! But i have one questions. If i customize the blog markup (i wanna add a featuredimage field) how to i get the image url, i only get the image name? I am new to use functions and i can not find a way.

Thank you very much for your help!!!

Edited by MateThemes
Link to comment
Share on other sites

If I understand you correctly, you have added a new image field to your template for the featured image and you need the url for the src attribute. ?

Lets assume the name of the new image field is 'featured_image' you will get the url of this image by using

$page->featured_image->url

So the code of the blog-post.php could look like this:

<?php 
	$img = $page->featured_image; 
	if($img) {
		$img = $img->width(600);
		echo "<p class='uk-text-center'><img src='$img->url' alt='$img->description'></p>";
	}
	?>

Image is an object, so you have to grab the different values (attributes) of the image by using the arrows (->) followed by the name of the attribute (size, url,...). You will find more information about getting image values here

If this was not the information you are asking for please post your code for better understanding.

Best regards

  • Like 1
Link to comment
Share on other sites

On 2/23/2019 at 7:28 PM, Juergen said:

If I understand you correctly, you have added a new image field to your template for the featured image and you need the url for the src attribute. ?

Lets assume the name of the new image field is 'featured_image' you will get the url of this image by using


$page->featured_image->url

So the code of the blog-post.php could look like this:


<?php 
	$img = $page->featured_image; 
	if($img) {
		$img = $img->width(600);
		echo "<p class='uk-text-center'><img src='$img->url' alt='$img->description'></p>";
	}
	?>

Image is an object, so you have to grab the different values (attributes) of the image by using the arrows (->) followed by the name of the attribute (size, url,...). You will find more information about getting image values here

If this was not the information you are asking for please post your code for better understanding.

Best regards

Hello and thank you for your answer!

I have following function added to uikit.php

function ukBlogPostOverview(Page $page, $options = array()) {
	
	$defaults = array(
		'summarize' => null, // Display blog post summary rather than full post? (null=auto-detect)
		'metaIcon' => 'info',
		'moreIcon' => 'arrow-right',
		'moreText' => __('Read more'), 
		'categoryIcon' => 'hashtag',
		'bylineText' => __('%2$s'), 
	);

	$options = _ukMergeOptions($defaults, $options);
	$title = $page->title;
	$date = $page->get('date|createdStr');
	$datePublished = $page->get('date');
	$name = $page->createdUser->name;
	$featuredImage = $page->get('featured_blogpost_image'); 
	$body = $page->get('body');
	$metaIcon = ukIcon($options['metaIcon']);
	$moreIcon = ukIcon($options['moreIcon']);
	$categoryIcon = ukIcon($options['categoryIcon']);
	$n = $page->get('comments')->count();
	$numComments = $n ? "<a href='$page->url#comments'>" . ukIcon('comments') . " $n</a>" : "";
	
	if($options['summarize'] === null) {
		// auto-detect: summarize if current page is not the same as the blog post
		$options['summarize'] = page()->id != $page->id;
	}

	$categories = $page->get('categories')->each($categoryIcon . 
		"<a class='uk-button uk-button-text' href='{url}'>{title}</a> "
	);

	if($options['summarize']) {
		// link to post in title, and use just the first paragraph in teaser mode
		$title = "<a href='$page->url'>$title</a>";
		$body = explode('</p>', $body); 
		$body = reset($body) . ' ';
		$more = "<a href='$page->url' class='uk-button uk-button-text'>$options[moreText]</a>";
		$class = 'blog-post-summary';
	} else {
		$class = 'blog-post-full';
	}

	if($options['summarize']) {
		$heading = "<h2 class='uk-margin-medium-top uk-margin-remove-bottom uk-h4'>$title</h2>";
	} else {
		$heading = "<h1 class='uk-margin-medium-top uk-margin-remove-bottom'>$title</h1>";
	}
	
	$byline = sprintf($options['bylineText'], $name, $date); 

	if($page->get('featured_blogpost_image')) {
		$img = $featuredImage($page->featured_blogpost_image->url);
		if($img) $featuredImage = "<div class='uk-width-auto'><img class='uk-comment-avatar' src='{$img->url}' alt='$cite'></div>";
	}
	
	// return the blog post article markup
	return "
		<div>
			<article class='uk-article blog-post $class'>
				<meta property='name' content=''>
				<meta property='author' typeof='Person' content='Arra Lifte Harmanschlag'>
				<meta property='dateModified' content='2018-12-14T11:08:44+00:00'>
				<meta property='datePublished' content='$datePublished'>
				<meta class='uk-margin-remove-adjacent' property='articleSection' content='News'>
				<div class='uk-text-center uk-margin-top' property='image' typeof='ImageObject'>
				 $featuredImage
				</div>
				$heading
				<ul class='uk-margin-small-top uk-margin-remove-bottom uk-subnav uk-subnav-divider'>
					<li class='uk-article-meta'>
					<time datetime='2019-02-08T14:45:39+00:00'>$byline</time>
					</li>
					<li class='categories'>
						$categories
					</li>
				</ul>
				<div class='uk-margin-small-top' property='text'>
					$body
				</div>
			</article>
		</div>
	";	
}

I wann add a featuredimage, as i added the $featuredImage but on my Page it only displayed the file name of the image. I don't know how to display the Image url.

Thanks for your help!

Link to comment
Share on other sites

15 minutes ago, MateThemes said:

if($page->get('featured_blogpost_image')) {

$img = $featuredImage($page->featured_blogpost_image->url); 
    if($img) $featuredImage = "<div class='uk-width-auto'><img class='uk-comment-avatar' src='{$img->url}' alt='$cite'></div>";
}

variable $img is already set to ->url, and then on the next line you use $img->url again... Use one or the other ?

btw, where do you define $cite? It's been used but never declared/defined?

  • Like 1
Link to comment
Share on other sites

11 hours ago, dragan said:

variable $img is already set to ->url, and then on the next line you use $img->url again... Use one or the other ?

btw, where do you define $cite? It's been used but never declared/defined?

Now I get it!!!

This is my code that i

function ukBlogPostOverview(Page $page, $options = array()) {
	
	$defaults = array(
		'summarize' => null, // Display blog post summary rather than full post? (null=auto-detect)
		'metaIcon' => 'info',
		'moreIcon' => 'arrow-right',
		'moreText' => __('Read more'), 
		'categoryIcon' => 'hashtag',
		'bylineText' => __('%2$s'), 
	);

	$options = _ukMergeOptions($defaults, $options);
	$title = $page->title;
	$date = $page->get('date|createdStr');
	$datePublished = $page->get('date');
	$name = $page->createdUser->name;
	$featuredBlogPostImage = $page->featured_blogpost_image; 
	$body = $page->get('body');
	$metaIcon = ukIcon($options['metaIcon']);
	$moreIcon = ukIcon($options['moreIcon']);
	$categoryIcon = ukIcon($options['categoryIcon']);
	$n = $page->get('comments')->count();
	$numComments = $n ? "<a href='$page->url#comments'>" . ukIcon('comments') . " $n</a>" : "";
	
	if($options['summarize'] === null) {
		// auto-detect: summarize if current page is not the same as the blog post
		$options['summarize'] = page()->id != $page->id;
	}

	$categories = $page->get('categories')->each($categoryIcon . 
		"<a class='uk-button uk-button-text' href='{url}'>{title}</a> "
	);

	if($options['summarize']) {
		// link to post in title, and use just the first paragraph in teaser mode
		$title = "<a href='$page->url'>$title</a>";
		$body = explode('</p>', $body); 
		$body = reset($body) . ' ';
		$more = "<a href='$page->url' class='uk-button uk-button-text'>$options[moreText]</a>";
		$class = 'blog-post-summary';
	} else {
		$class = 'blog-post-full';
	}

	if($options['summarize']) {
		$heading = "<h2 class='uk-margin-medium-top uk-margin-remove-bottom uk-h4'>$title</h2>";
	} else {
		$heading = "<h1 class='uk-margin-medium-top uk-margin-remove-bottom'>$title</h1>";
	}
	
	$byline = sprintf($options['bylineText'], $name, $date); 

	if($page->get('featured_blogpost_image')) {
		$featuredBlogPostImage = "<div class='uk-width-auto'><img class='uk-comment-avatar' src='{$featuredBlogPostImage->url}' alt='{$featuredBlogPostImage->description}'></div>"; 
	}
	
	// return the blog post article markup
	return "
		<div>
			<article class='uk-article blog-post $class'>
				<meta property='name' content=''>
				<meta property='author' typeof='Person' content='Arra Lifte Harmanschlag'>
				<meta property='dateModified' content='2018-12-14T11:08:44+00:00'>
				<meta property='datePublished' content='$datePublished'>
				<meta class='uk-margin-remove-adjacent' property='articleSection' content='News'>
				<div class='uk-text-center uk-margin-top' property='image' typeof='ImageObject'>
					$featuredBlogPostImage
				</div>
				$heading
				<ul class='uk-margin-small-top uk-margin-remove-bottom uk-subnav uk-subnav-divider'>
					<li class='uk-article-meta'>
					<time datetime='2019-02-08T14:45:39+00:00'>$byline</time>
					</li>
					<li class='categories'>
						$categories
					</li>
				</ul>
				<div class='uk-margin-small-top' property='text'>
					$body
				</div>
			</article>
		</div>
	";	
}

Thanks for the help!!! Processwire has the greatest community, that is also a reason why I like this CMF so much!!!

Have a nice day!

  • Like 1
Link to comment
Share on other sites

Hello again!!!

May someone can help me again!!! I have this to variables in my uikit.php

$body = explode('</p>', $body); 
$body = reset($body) . ' ';

what means explode and reset?

And you see my funtion above, how can I summarize the text in the body field only with e.g. 10 Words?

Thank you in advance!

Link to comment
Share on other sites

Maybe you can use the truncate method https://processwire.com/api/ref/sanitizer/truncate/ ?

// Truncate string to closest word within 150 characters
$s = $sanitizer->truncate($str, 150);

Here is another example of how to use a hook to add a "summarize" method to all the $page objects

https://processwire.com/blog/posts/pw-3.0.28/

Here is reset https://secure.php.net/manual/en/function.reset.php

Here is explode https://secure.php.net/manual/en/function.explode.php

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

On 2/28/2019 at 11:04 PM, gmclelland said:

Maybe you can use the truncate method https://processwire.com/api/ref/sanitizer/truncate/ ?


// Truncate string to closest word within 150 characters
$s = $sanitizer->truncate($str, 150);

Here is another example of how to use a hook to add a "summarize" method to all the $page objects

https://processwire.com/blog/posts/pw-3.0.28/

Here is reset https://secure.php.net/manual/en/function.reset.php

Here is explode https://secure.php.net/manual/en/function.explode.php

Thank you very much for your answer!!! This helps me a alot!!!

I am still new to Processwire but I love it more and more!!!

Link to comment
Share on other sites

Hello everybody!!!

It is me again with a beginner question.

I have following function defined in uikit.php and used in my search-template

<?php
	// did we find any matches?
	if(count($matches)) {
	// yes we did, render them
	echo ukAlert("Found $matches->count page(s)", "default", "list");
	echo ukDescriptionListPages($matches);
} else {
	// we didn't find any
	echo ukAlert("Sorry, no results were found.", "danger", "warning");
}
?>

Now, how can I make the ukAlert translatable as a string?

I didn't find a way to get it work!

Thanks for your help in advance!!!

Link to comment
Share on other sites

<?php
	// did we find any matches?
	if(count($matches)) {
	// yes we did, render them
    echo ukAlert(sprintf(_n('Found %d page', 'Found %d pages', $matches->count), $matches->count), "default", "list");
	echo ukDescriptionListPages($matches);
} else {
	// we didn't find any
	echo ukAlert(__('Sorry, no results were found'), "danger", "warning");
}
?>

After that, edit your language on admin and translate the strings on the search.php file. 

https://processwire.com/docs/multi-language-support/code-i18n/#plurals

Edited by Sergio
Added docs link
  • Like 2
Link to comment
Share on other sites

35 minutes ago, Sergio said:

<?php
	// did we find any matches?
	if(count($matches)) {
	// yes we did, render them
    echo ukAlert(sprintf(_n('Found %d page', 'Found %d pages', $matches->count), $matches->count), "default", "list");
	echo ukDescriptionListPages($matches);
} else {
	// we didn't find any
	echo ukAlert(__('Sorry, no results were found'), "danger", "warning");
}
?>

After that, edit your language on admin and translate the strings on the search.php file. 

https://processwire.com/docs/multi-language-support/code-i18n/#plurals

Thank you very much!!! 

Now it works!

Link to comment
Share on other sites

3 hours ago, nfil said:

How do I limit the pagination numbers, just need 3 between the previous and next buttons?

You can pass a "numPageLinks" option to the $page->render method, like so:

$options = array(
		'numPageLinks' => 10, 
		'nextItemLabel' => '<i class="uk-icon-angle-double-right"></i>',
		// 'nextItemClass' => '',
		'previousItemLabel' => '<span><i class="uk-icon-angle-double-left"></i></span>',
		// 'previousItemClass' => '',
		// 'lastItemClass' => '',
		'currentItemClass' => 'bg-orange',
		'separatorItemLabel' => '<span>…</span>',
		'listMarkup' => "<ul>{out}</ul>",
		'itemMarkup' => "<li>{out}</li>",
		'linkMarkup' => "<a href='{url}' class=''>{out}</a>",
		'currentLinkMarkup' => "<span class=''>{out}</span>"
	);

echo $pager->render($posts, $options);

 

  • Like 1
Link to comment
Share on other sites

  • 2 months later...

Great topic!

I am somewhat familiar with processwire, and I love it, despite not being fully proficient.  The uikit integration adds a layer of complexity that I'm starting to figure out, but still struggling with.  That being said, I have a question, that hopefully someone can answer.  I am trying to render a canvas element within a modified blog-post template which in turn uses a modified version of the ukBlogPost and ukBlogPosts functions in _uikit.php.  The problem I'm running into is getting some Bablylon.js code to render on the page.  I'm wonder what is the best way to insert a canvas element on the pages in order to do some webgl using Bablylon.js.

Currently, I'm trying to insert the following into a textarea field with content type set to Unknown/Text

<canvas id="renderCanvas" touch-action="none"></canvas>
    
    <script>
        /// <reference path = "./ts/babylon.module.d.ts"/>
        var canvas = document.getElementById("renderCanvas");
        var engine = new BABYLON.Engine(canvas, true);

        var createScene = function () {
            var scene = new BABYLON.Scene(engine);
            var camera = new BABYLON.ArcRotateCamera("Camera", Math.PI/2, Math.PI/2, 2, new BABYLON.Vector3(0,0,5), scene);
            camera.attachControl(canvas, true);

            var light1 = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(1,1,0), scene);
            var light2 = new BABYLON.PointLight("light2", new BABYLON.Vector3(0,1,-1), scene);

            var sphere = BABYLON.MeshBuilder.CreateSphere("sphere", {diameter:2}, scene);

            return scene;
        }

        var scene = createScene();
         engine.runRenderLoop(function (){
             scene.render();
         });

         window.addEventListener("resize", function (){
             engine.resize();
         });
        
    </script>

No canvas is showing on the screen as is.

 

I've put all the Bablylon libraries in the header of the _main.php.

Where should I put a canvas element in the project should it be directly in the modified blog-post template?  Should it be in a custom field added to the template?  Or should it go in the _main.php file?

I also need to reference the canvas element for Bablylon.js and include some javascript.

 

I'm going to continue working towards the solution, but I thought I'd put this out there since there is such a great wealth of knowledge and experience on this forum.


Thanks!

 

Link to comment
Share on other sites

 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...