<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>REST Archives - Michael Soriano</title>
	<atom:link href="https://michaelsoriano.com/tag/rest/feed/" rel="self" type="application/rss+xml" />
	<link>https://michaelsoriano.com/tag/rest/</link>
	<description>I turn code into captivating user experiences for the web</description>
	<lastBuildDate>Wed, 14 Feb 2024 18:36:26 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.7.4</generator>
	<item>
		<title>How to Build a Company Timeline using Bootstrap and WordPess REST API</title>
		<link>https://michaelsoriano.com/build-company-timeline-bootstrap-wp-rest-api/</link>
					<comments>https://michaelsoriano.com/build-company-timeline-bootstrap-wp-rest-api/#respond</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Fri, 27 Jul 2018 19:08:32 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Bootstrap]]></category>
		<category><![CDATA[REST]]></category>
		<guid isPermaLink="false">http://michaelsoriano.com/?p=6168</guid>

					<description><![CDATA[<p>So our Company wanted to build a Timeline. One that shows our projects throughout the years, decades even. One that is sleek, modern and responsive. We&#8217;re already running WordPress, and have Bootstrap installed. So this shouldn&#8217;t be too bad. It turns out &#8211; it was a pretty fun project to build. Our in house designers [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/build-company-timeline-bootstrap-wp-rest-api/">How to Build a Company Timeline using Bootstrap and WordPess REST API</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>So our Company wanted to build a Timeline. One that shows our projects throughout the years, decades even. One that is sleek, modern and responsive. We&#8217;re already running WordPress, and have Bootstrap installed. So this shouldn&#8217;t be too bad. It turns out &#8211; it was a pretty fun project to build.</p>



<p>Our in house designers are responsible for the design of this page. It&#8217;s a little bit of Facebook&#8217;s original timeline layout &#8211; but a lot simpler and minimalist. Here is a preview of how it looks:</p>



<p><img fetchpriority="high" decoding="async" width="875" height="506" class="alignnone size-full wp-image-6685" style="border: 1px solid #ededed;" src="https://michaelsoriano.com/wp-content/uploads/2017/10/timeline.gif" alt=""><br></p>



<p>In a nutshell, this is what we&#8217;re going to accomplish: We&#8217;re going to use custom post types (CPT) for each entry in the Timeline. We&#8217;re grabbing them via JavaScript &#8211; using the WP Rest API as the endpoint. We&#8217;re also using Boostrap&#8217;s grid system &#8211; so our timeline behaves well in mobile.</p>



<p>We are going to build everything as part of the theme. For more advanced users &#8211; you can also build it as a plugin.</p>



<p>Note that you have to be familiar with WordPress, PHP and Front end to follow. There is no download for this &#8211; you simply have to follow along.</p>



<p>Ready to get started? Let&#8217;s begin:</p>



<h3 class="wp-block-heading">The Back-End</h3>



<p>First off, let&#8217;s take care of the data. We need to register the CPT with WordPress and make sure we have the right custom fields. Actually, we only have one custom field necessary &#8211; and that is the year. The year is what the timeline is sorted by (newest to oldest).</p>



<p>Open up <strong>functions.php</strong> in your theme. First let&#8217;s add the CPT initialization.</p>



<pre class="wp-block-code"><code lang="php" class="language-php">function registerTimelineCPT() {
        $labels = array(
            'name' =&gt; __( 'Timeline' ),
            'singular_name' =&gt; __( 'Timeline' ),
            'add_new_item'       =&gt; __( 'Add New Timeline'),
            'new_item'           =&gt; __( 'Timeline'),
            'edit_item'          =&gt; __( 'Edit Timeline'),
            'view_item'          =&gt; __( 'View Timeline'),
            'all_items'          =&gt; __( 'View All'),
        );
        register_post_type( 'timeline',
            array(
                'labels' =&gt; $labels,
                'public' =&gt; true,
                'has_archive' =&gt; false,
                'rewrite' =&gt; false,
                'publicly_queriable' =&gt; true,
                'exclude_from_search' =&gt; true,
                'show_ui' =&gt; true,
                'show_in_nav_menus' =&gt; false,
                'show_in_menu' =&gt; true,
                'show_in_admin_bar' =&gt; false,
                'menu_icon' =&gt; 'dashicons-backup',
                'show_in_rest' =&gt; true,
                'public' =&gt; false, //removes the "permalink"
                'supports' =&gt; array(
                    'title',
                    'excerpt',
                    'thumbnail',
                    'custom-fields'
                )
            )
        );
        //REMOVES COMMENTS
        remove_post_type_support( 'timeline', 'comments' );
}
add_action( 'init', 'registerTimelineCPT' );</code></pre>



<p>Above, we&#8217;re simply creating our CPT called &#8220;Timeline&#8221;. We&#8217;re setting up the labels, what it supports and what it doesn&#8217;t support. Upon logging in you should see a &#8220;<strong>Timeline</strong>&#8221; in your admin area.</p>



<p>Now for the&nbsp; custom fields &#8211; you can easily add this the default way according to <a href="https://codex.wordpress.org/Custom_Fields">WordPress</a>. In my case, I wanted to make it easier for the users to update &#8211; so I&#8217;m using this plugin called &#8220;<a href="https://metabox.io">Meta Box</a>&#8220;. </p>



<p>Our custom field is now easier to set up and become much cleaner to the users.<br>If you have MetaBox installed, adding the field is as simple as below. This goes into your <strong>functions.php</strong>.</p>



<pre class="wp-block-code"><code lang="php" class="language-php">function createMetaBoxes($meta_boxes ){
	$prefix = 'tl_';
	$meta_boxes[] = array(
		'id' =&gt; 'timeline_metabox',
		'title' =&gt; esc_html__( 'Other', $prefix ),
		'post_types' =&gt; array( 'timeline' ),
		'context'    =&gt; 'normal',
		'priority'   =&gt; 'low',
		'autosave'   =&gt; true,
		'fields'     =&gt; array(
			array(
				'name' =&gt; esc_html__( 'Timeline',  $prefix  ),
				'id'   =&gt; 'timeline_year',
				'label_description' =&gt; esc_html__( 'Year', $prefix ),
				'type' =&gt; 'range',
				'min'  =&gt; '1930',
				'max'  =&gt; date("Y"),
				'step' =&gt; 1,
				'std'  =&gt; date("Y"),
			)
		)
	);
	return $meta_boxes;
}
add_filter( 'rwmb_meta_boxes', 'createMetaBoxes' );</code></pre>



<p>Now if you go to the Timeline page, you should see our nice range slider:</p>



<p><img decoding="async" width="545" height="449" class="alignnone size-full wp-image-6705" src="https://michaelsoriano.com/wp-content/uploads/2018/07/timeline-cfield.png" alt="timeline - cpt" srcset="https://michaelsoriano.com/wp-content/uploads/2018/07/timeline-cfield.png 545w, https://michaelsoriano.com/wp-content/uploads/2018/07/timeline-cfield-300x247.png 300w" sizes="(max-width: 545px) 100vw, 545px" /></p>



<p>We&#8217;re also using the following default WordPress fields:</p>



<ul class="wp-block-list">
<li>Title</li>



<li>Excerpt</li>



<li>Featured Image</li>
</ul>



<p>So as you&#8217;re following along, go ahead and add several timelines and make sure these fields are filled out.</p>



<h3 class="wp-block-heading">REST Endpoint</h3>



<p>Before we can call our Timelines through REST, we have to do some setup. Still in <strong>functions.php</strong>, add the code below:</p>



<pre class="wp-block-code"><code lang="php" class="language-php">function restProperties(){
	register_rest_field( 'timeline',
		'timeline_year',
		array(
		   'get_callback' =&gt; 'registerRestCb',
		   'update_callback' =&gt; null,
		   'schema'          =&gt; null,
		)
	 );
	function registerRestCb($object, $field_name, $request){
		return get_post_meta( $object[ 'id' ], $field_name, true );
	}
}
add_action( 'rest_api_init', 'restProperties');</code></pre>



<p>So the above makes the &#8216;timeline&#8217; available as and endpoint in REST. Also, we&#8217;re adding the &#8216;timeline_year&#8217; as a property in the response. To find out more about WP REST API, check their <a href="https://developer.wordpress.org/rest-api/">documentation</a>.</p>



<p>Now, when you hit the endpoint: YOURURL +&#8217;<strong>/wp-json/wp/v2/timeline?_embed&amp;per_page=100</strong>&#8216;, you should now see data as a JSON string. This is enough for us to work with in our Front End. Let&#8217;s go do that now.</p>



<h3 class="wp-block-heading">The Front-End</h3>



<p>Before we continue, I forgot to mention the libraries that we need to work with:</p>



<ul class="wp-block-list">
<li>jQuery</li>



<li>Bootstrap</li>



<li>Handlebars</li>
</ul>



<h4 class="wp-block-heading">Markup</h4>



<p>I&#8217;m going to add the markup first (the handlebar templates), then we&#8217;ll move on to the logic.</p>



<p>This is the <span style="text-decoration: underline;">main template</span>:</p>



<pre class="wp-block-code"><code lang="markup" class="language-markup">&lt;script id="timeline-template" type="text/x-handlebars-template"&gt;
    {{#each this}}
    &lt;div class="decade-wrap" id="decade-{{decade}}"&gt;            
    &lt;h1&gt;{{decade}}s&lt;/h1&gt;
    {{#each @this}}                    
        &lt;div class="col-lg-6 col-md-6 col-sm-6 col-xs-12 timeline-item timeline-index-{{@index}} timeline-{{leftOrRight @index}}"&gt;
            &lt;div class="timeline-year"&gt;{{year}}&lt;/div&gt;
            &lt;div class="timeline-inner-wrap col-lg-8 col-md-8 col-sm-8 col-lg-12 {{pull @index}}"&gt;                
                &lt;div class="timeline-thumbnail" style="background:url('{{img}}') no-repeat #ccc"&gt;                 
                &lt;/div&gt; 
                &lt;div class="timeline-title"&gt;{{title}}&lt;/div&gt;
                &lt;div class="timeline-excerpt"&gt;{{{excerpt}}}&lt;/div&gt;
            &lt;/div&gt;
        &lt;/div&gt;
        {{{closeWrap @index}}}
    {{/each}}
    &lt;/div&gt;
    {{/each}}
&lt;/script&gt;</code></pre>



<p>As you can see, we&#8217;re using the Bootstrap col classes to make each item responsive. We&#8217;re also using pull classes &#8211; so the alternate item will be pulled to the left.</p>



<p>The <span style="text-decoration: underline;">decades scroller</span>:</p>



<pre class="wp-block-code"><code lang="markup" class="language-markup">&lt;script id="timeline-decades-template" type="text/x-handlebars-template"&gt; 
{{#each this}}
    &lt;div class="timeline-decades-link-item decade-{{decade}} {{showingOrNot @index}}"&gt;
            &lt;a href="#decade-{{decade}}"&gt;{{decade}}s&lt;/a&gt;
    &lt;/div&gt;
{{/each}}
&lt;/script&gt;</code></pre>



<p>Nothing fancy here, just a list of decades that is clickable.</p>



<p>Lastly, let&#8217;s build the <span style="text-decoration: underline;">wrapper</span>:</p>



<pre class="wp-block-code"><code lang="markup" class="language-markup">&lt;div class="timeline-decade-links-wrapper"&gt;
  &lt;div class="timeline-decade-links"&gt;
       &lt;div class="getting-items"&gt;Getting Items&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class="timeline-wrapper"&gt;&lt;/div&gt; 
&lt;div class="show-more-wrap"&gt;
   &lt;a href="#"&gt;&lt;img src="showmore.png"&gt;&lt;/a&gt;
&lt;/div&gt;</code></pre>



<p>The above markup simply holds the timelines together. It also has the text &#8220;Getting Items&#8221; &#8211; which acts as our loader &#8211; until our AJAX call completes. Also, we have a &#8220;show more&#8221; button &#8211; so that when clicked &#8211; the rest of the items appear in the bottom.</p>



<p>So the above is our HTML. Now we need JavaScript, which is described below.</p>



<h3 class="wp-block-heading">Getting and Grouping the Items</h3>



<p>This is where we pull the data from our REST endpoint, and pass it on to the handlebars templates that we&#8217;ve created. We also need&nbsp;additional logic &#8211; specifically grouping the decades together to build the scroller.</p>



<p>Let&#8217;s grab our items via .ajax():</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">$(document).ready(function(){
	$.ajax({
		url : '/wp-json/wp/v2/timeline?_embed&amp;per_page=100',
		success : function(data){
                        console.log(JSON.parse(data));
			//TODO :compileTemplates();
			//TODO: bindDecadeScroller();
		},
		error : function(data){
			console.log('Error in fetching timeline...')
		}
	})
});</code></pre>



<p>All things are happening inside the document ready handler. Now if you refresh your browser, you shall see our data in a parsed JSON object.<br><img decoding="async" width="752" height="503" class="alignnone size-full wp-image-6723" src="https://michaelsoriano.com/wp-content/uploads/2018/07/timeline-object.png" alt="timeline object" srcset="https://michaelsoriano.com/wp-content/uploads/2018/07/timeline-object.png 752w, https://michaelsoriano.com/wp-content/uploads/2018/07/timeline-object-300x201.png 300w" sizes="(max-width: 752px) 100vw, 752px" /></p>



<p>Now that we have our objects in place, remove the console.log() line that we have. We have 2 TODOS: functions that we haven&#8217;t built yet, namely&nbsp;<strong>compileTemplates</strong>() and&nbsp;<strong>bindDecadeScroller</strong>(). You can guess what both of them do.</p>



<p>Let&#8217;s add the first function&nbsp;<strong>compileTemplates()</strong>:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">function compileTemplates(data){
	var parsed = JSON.parse(data);
	if(parsed.length &gt; 0){
		var obj = buildTimeline(parsed);
		var source  = $("#timeline-template").html();
		var source2 = $("#timeline-decades-template").html();
		var template = Handlebars.compile(source);
		var template2 =  Handlebars.compile(source2);
		$('.timeline-decade-links').html(template2(obj));
		$('.timeline-wrapper').html(template(obj));
	}
}</code></pre>



<p>The above simply compiles the JSON data and hands it over to our templates. This alone should get our views going. But don&#8217;t refresh the browser yet. There are plenty of logic that still needs to happen.</p>



<p>Notice the new function in line 4 called &#8220;<strong>buildTimeline()</strong>&#8220;.&nbsp; On top of that, we have Handlebar helpers that we haven&#8217;t registered &#8211; so the browser will actually throw a fit. This will be covered in the section below &#8220;<strong>View Helpers</strong>&#8220;.</p>



<p>Let&#8217;s build the function called&nbsp;<strong>buildTimeline()</strong>:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">function buildTimeline(data){
    function comp(a, b){
        return b - a;
    }
    function compYear(a,b) {
        if (b.year &lt; a.year)
            return -1;
        if (b.year &gt; a.year)
            return 1;
        return 0;
    }
    function grabImg(el){
        var src = '';
        if(el._embedded){
            if(el._embedded['wp:featuredmedia']){
                src = el._embedded['wp:featuredmedia'][0]['source_url'];
            }
        }
        return src;
    }
    $.each(data, function(){
        $(this)[0].timeline_year = parseInt($(this)[0].timeline_year);
    })
    //add decade:
    $.each(data, function(){
        var year = $(this)[0].timeline_year;
        $(this)[0].timeline_year_decade = Math.floor(year / 10) * 10;
    })
    //group decades:
    var decades = [];
    $.each(data, function(){
        decades.push($(this)[0].timeline_year_decade);
    })
    var uniqueDecades = [];
    $.each(decades, function(i, el){
        if($.inArray(el, uniqueDecades) === -1) uniqueDecades.push(el);
    });
    decades = uniqueDecades.sort(comp);
    var clean = Array();
    var final = Array();
    $.each(data, function(i, el){
        var obj = {};
        obj.id = el.id;
        obj.img = grabImg(el);
        obj.title = el.title.rendered;
        obj.excerpt = el.excerpt.rendered;
        obj.year = el.timeline_year;
        obj.year_decade = el.timeline_year_decade;
        clean.push(obj);
    });
    clean = clean.sort(compYear);
    $.each(decades,function(i,el){
        var key = i;
        final[key] = Array();
        $.each(clean,function(x,xel){
            final[key]['decade'] = el;
            if(xel.year_decade == el){
                final[key].push(xel);
            }
        })
    })
    return final;
}</code></pre>



<p>Okay this is the meat of our logic. We&#8217;re trying to grab all of the years in our timelines. And from each of those years, we need to calculate the decade, take out the duplicates and stuff them back to a final array, grouped by decade.</p>



<p>In lines 31-34 is where we calculate the decade, then stuffing it to a new property called &#8220;<strong>timeline_year_decade</strong>&#8220;. Then we&#8217;re doing a couple more loops to remove duplicates, sort and create a clean &#8220;<strong>decades</strong>&#8221; array &#8211; which we need for our final loop in lines 66-75.</p>



<p>Refresh your browser and see what our &#8220;<strong>final</strong>&#8221; array looks like.</p>



<p><img decoding="async" width="780" height="615" class="alignnone size-full wp-image-6729" src="https://michaelsoriano.com/wp-content/uploads/2018/07/timeline-object2.png" alt="timeline - object grouped" srcset="https://michaelsoriano.com/wp-content/uploads/2018/07/timeline-object2.png 780w, https://michaelsoriano.com/wp-content/uploads/2018/07/timeline-object2-300x237.png 300w, https://michaelsoriano.com/wp-content/uploads/2018/07/timeline-object2-768x606.png 768w" sizes="(max-width: 780px) 100vw, 780px" /></p>



<p>Now we our&nbsp;<strong>compileTemplates() </strong>is done, let&#8217;s go and register our <strong>helpers</strong> and do some <strong>CSS</strong>.</p>



<h3 class="wp-block-heading"><strong>View Helpers</strong></h3>



<p>Now we have to do add more scripting to determine additional classes that makes our timeline look the way it does.</p>



<p>In case you haven&#8217;t noticed, our templates are sprinkled with helpers for handlebars. Let&#8217;s register those helpers now.</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">Handlebars.registerHelper('leftOrRight', function(index) {
	return index %2 == 0 ? 'left' : 'right';
});
Handlebars.registerHelper('closeWrap', function(index) {
   return (index+1) %2 == 0 ? '&lt;div class="clearfix"&gt;&lt;/div&gt;' : '';
});
Handlebars.registerHelper('pull', function(index) {
   return index %2 == 0 ? '' : 'col-lg-push-4 col-md-push-4 col-sm-push-4';
});
Handlebars.registerHelper('showingOrNot', function(index) {
	if(index == 0){
		return 'showing';
	}
});</code></pre>



<p>The above are view helpers &#8211; that cooperates with the HTML templates that we just built. For instance, the &#8220;leftOrRight&#8221; helper &#8211; determines if a class of &#8220;left&#8221; or &#8220;right&#8221; is to be added. Below are the images for that:</p>



<p>Left Line:</p>



<p><br><img decoding="async" width="142" height="16" class="alignnone size-full wp-image-6713" src="https://michaelsoriano.com/wp-content/uploads/2018/07/left_line.png" alt="left line"><br></p>



<p>Right Line:</p>



<p><br><img decoding="async" width="141" height="16" class="alignnone size-full wp-image-6714" src="https://michaelsoriano.com/wp-content/uploads/2018/07/right_line.png" alt=""><br></p>



<p>Arrow up:<br></p>



<p><img decoding="async" width="12" height="8" class="alignnone size-full wp-image-6730" src="https://michaelsoriano.com/wp-content/uploads/2018/07/arrow-up.png" alt=""><br></p>



<p>Vertical Line:</p>



<p><br><img decoding="async" width="1" height="186" class="alignnone size-full wp-image-6734" src="https://michaelsoriano.com/wp-content/uploads/2018/07/vertical_line.png" alt=""><br></p>



<h3 class="wp-block-heading">The Styles</h3>



<p>Finally, the styles that make our timeline look good. I&#8217;m not going to walk through what each style does. I&#8217;m just going to add this as a reference for you to plugin. You might have a different style depending on your preference.</p>



<pre class="wp-block-code"><code lang="css" class="language-css">.timeline-wrapper {
    position:relative;
    z-index: 99;
}
.decade-wrap {
    overflow:hidden;
    clear:both;
    display:block;
    background:url('vertical_line.png') #fff repeat-y;
    background-position-x: center;
}
.decade-wrap:first-child {
    padding-top: 40px;
}
.decade-wrap:last-child{
    margin-bottom: 75px;
}
.decade-wrap h1 {
    text-align: center;
    background:#fff;
    padding:25px 0 35px;
    font-size:45px;
    color: #0077C8;
}
.timeline-thumbnail {
    background-position-x: center !important;
    background-position-y: center !important;
    background-size: cover !important;
    height:319px;
}
.timeline-item,
.timeline-inner-wrap {
    padding-left:0;
    padding-right:0;
}
.timeline-left {
    background:url('left_line.png') no-repeat right center;
    margin-left: 8px;
}
.timeline-right {
     margin-top: 100px;
    background:url('right_line.png') no-repeat left center;
    margin-left: -15px;
}
.timeline-inner-wrap {
    padding-top: 25px;
}
.timeline-year {
    position: absolute;
    top: 39%;
    font-size:30px;
    font-weight: 500;
    color: #0077C8;
}
.timeline-right .timeline-year {
    padding-left: 35px;
}
.timeline-left .timeline-year {
    right:0;
    padding-right: 34px;
}
.timeline-title {
    font-size: 19px;
    font-weight: 500;
    color: #000;
    padding-top: 15px;
    padding-bottom: 10px;
}
.timeline-decade-links {
    background:#ececec;
    min-height: 60px;
    display: flex;
}
.timeline-decades-link-item {
    width: 100px;
    margin: 0 auto;
    text-align: center;
    font-size: 18px;
    padding-top: 18px;
    height: 60px;
}
.timeline-decades-link-item a:hover,
.timeline-decades-link-item a:focus{
    text-decoration:none;
}
.timeline-decades-link-item.showing {
    background:url('arrow-up.png') transparent no-repeat center bottom;
}
.timeline-decade-links-wrapper {
    overflow: hidden;
}
.timeline-decade-links-wrapper.fixed {
    position: fixed;
    top: 0px;
    z-index: 110;
    left:0;
    width:100%;
}
.admin-bar .timeline-decade-links-wrapper.fixed {
    top:32px;
}
@media(max-width:1199px){
    .timeline-thumbnail {
        height:253px;
    }
    .timeline-item {
        background-position-y: 33%;
    }
    .timeline-year{
        top: 21%;
    }
}
@media(max-width:991px){
    .timeline-thumbnail {
        height:190px;
    }
    .timeline-item {
        background-position-y: 28%;
    }
    .timeline-year{
        top: 18%;
        font-size: 23px;
    }
    .decade-wrap h1 {
        padding: 14px 0 24px;
        font-size: 31px;
    }
}
@media(max-width:768px){
    .timeline-thumbnail {
        height:354px;
        width:410px;
    }
    .decade-wrap {
        background:none;
    }
    .decade-wrap:first-child {
        padding-top:0;
    }
    .decade-wrap h1 {
        padding: 0px 0px 0px 0px;
    }
    .timeline-right {
        margin-top: 0;
    }
    .timeline-item {
        background:#fff;
        margin-left: 0 !important;
        margin-right:0 !important;
    }
    .timeline-year {
        position: relative;
        padding-left: 0 !important;
        padding-right:0 !important;
    }
    .timeline-decade-links {
        display: none;
    }
}
@media(max-width:500px){
    .timeline-thumbnail {
        height:302px;
        width:auto;
    }
}
@media(max-width:375px){
    .timeline-thumbnail {
        height:242px;
    }
}</code></pre>



<p>&nbsp;<br>After our helpers apply the classes, our CSS and images in place &#8211; Bootstrap will take care of the rest. If you refresh, you should see your timeline. Inspect and you see our classes applied.</p>



<p><img decoding="async" width="1006" height="591" class="alignnone size-full wp-image-6718" src="https://michaelsoriano.com/wp-content/uploads/2018/07/timeline-classes.png" alt="timeline classes" srcset="https://michaelsoriano.com/wp-content/uploads/2018/07/timeline-classes.png 1006w, https://michaelsoriano.com/wp-content/uploads/2018/07/timeline-classes-300x176.png 300w, https://michaelsoriano.com/wp-content/uploads/2018/07/timeline-classes-768x451.png 768w" sizes="(max-width: 1006px) 100vw, 1006px" /></p>



<p>Finally, let&#8217;s go ahead and bind that scroller:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">function bindDecadeScroller(){
	 $('.timeline-decades-link-item a').on('click',function(){
		var id = $(this).attr('href');
		var offset = ($(id).offset().top - 150) ;
		$('html, body').stop().animate({
			scrollTop: offset
		}, 1000);
		return false;
	})
}</code></pre>



<p>This should have a smooth animating effect when you click on the decades on the scroller. Note that our timelines are grouped by decades, encapsulated in a DIV with the ID &#8211; of the decade. So when our scroller is cicked &#8211; it has the ID of the DIV in it&#8217;s href attribute. </p>



<p>So technically, even without our animation &#8211; it will know where to focus naturally.</p>



<p><img decoding="async" width="636" height="673" class="alignnone size-full wp-image-6737" src="https://michaelsoriano.com/wp-content/uploads/2018/07/timeline-responsive.gif" alt="timeline - responsive"></p>



<p>We&#8217;re using .animate() to make that jump smoother. Check jQuery&#8217;s <a href="http://api.jquery.com/animate/">documentation</a> on .animate for more information.</p>



<h3 class="wp-block-heading">Conclusion</h3>



<p>And there you have it. We&#8217;ve just build a pretty cool timeline &#8211; grouped by decades, with a scroller that focuses on the decade when clicked. This is also responsive &#8211; so it looks real good in a mobile device. </p>



<p>Note that this is a pretty basic timeline &#8211; which you can greatly enhance by adding other things. For example, you can add a modal for more details for each of the item. Or even multiple images per item &#8211; one that you can scroll left to right like a slideshow. There are many possibilities.</p>



<p>For the live page, check out the Parsons <a href="https://www.parsons.com/about/timeline/">timeline</a> page.&nbsp;I hope you enjoyed this tutorial. Leave your comments below.</p>
<p>The post <a href="https://michaelsoriano.com/build-company-timeline-bootstrap-wp-rest-api/">How to Build a Company Timeline using Bootstrap and WordPess REST API</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/build-company-timeline-bootstrap-wp-rest-api/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>New WordPress Starter Theme using VueJS</title>
		<link>https://michaelsoriano.com/wordpress-starter-theme-using-vuejs/</link>
					<comments>https://michaelsoriano.com/wordpress-starter-theme-using-vuejs/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Sat, 17 Feb 2018 19:21:18 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[vue]]></category>
		<guid isPermaLink="false">http://michaelsoriano.com/?p=6447</guid>

					<description><![CDATA[<p>I&#8217;ve been building WordPress themes for quite some time now. And with the advent of front-end frameworks and WP&#8217;s REST API, I thought it would be a good combination to build one that uses both. The benefits would be that the site&#8217;s user experience would be lightning fast. There wouldn&#8217;t be server page loads (except [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/wordpress-starter-theme-using-vuejs/">New WordPress Starter Theme using VueJS</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>I&#8217;ve been building WordPress themes for quite some time now. And with the advent of front-end frameworks and WP&#8217;s REST API, I thought it would be a good combination to build one that uses both. The benefits would be that the site&#8217;s user experience would be lightning fast. There wouldn&#8217;t be server page loads (except for the first one). </p>



<p>So all subsequent navigation will be done in the client side. This results to a smoother and better user experience.</p>



<p class="btn"><a href="https://github.com/michaelsoriano/wp-vue-starter">View in Github</a></p>



<p>I wanted to build several themes, but would like a base theme to start with. Enter <strong>wp-vue-starter. </strong>A starter theme that is built on a popular framework called Vue, and WP&#8217;s REST API in the background.</p>



<p><br><img decoding="async" width="850" height="332" class="alignnone size-full wp-image-6451" src="https://michaelsoriano.com/wp-content/uploads/2018/01/wp-vue.jpg" alt="wp vue logos" srcset="https://michaelsoriano.com/wp-content/uploads/2018/01/wp-vue.jpg 850w, https://michaelsoriano.com/wp-content/uploads/2018/01/wp-vue-300x117.jpg 300w, https://michaelsoriano.com/wp-content/uploads/2018/01/wp-vue-768x300.jpg 768w" sizes="(max-width: 850px) 100vw, 850px" /></p>



<p>Note that since all of the rendering is done in the client, SEO is not going to be available. But for sites that SEO will not matter, I think this is a good choice. Let me explain the theme design and structure and maybe you can use the theme in your next project.</p>



<h3 class="wp-block-heading">Traditional Blog Design</h3>



<p>If you do a search on WordPress Theme and Vue, there have been many attempts on it. This however, is slightly different. First of all, is the design. It uses the traditional blog design that many of us WordPress users have grown to like.</p>



<p>Here is a screenshot of the homepage:</p>



<p><img decoding="async" width="850" height="960" class="alignnone size-full wp-image-6448" src="https://michaelsoriano.com/wp-content/uploads/2018/01/home-page.png" alt="home" srcset="https://michaelsoriano.com/wp-content/uploads/2018/01/home-page.png 850w, https://michaelsoriano.com/wp-content/uploads/2018/01/home-page-266x300.png 266w, https://michaelsoriano.com/wp-content/uploads/2018/01/home-page-768x867.png 768w" sizes="(max-width: 850px) 100vw, 850px" /><br></p>



<p>As you can see, it has a &#8220;static&#8221; page that is called &#8220;home&#8221;. There is a big area (jumbotron) for your carousel or hero image, while the latest posts are directly below it. The CSS framework is Bootstrap (version 4). So editing the grid and elements is familiar to many. A sidebar is built in &#8211; which is pretty standard to most sites.</p>



<p>What is a site without &#8220;Search&#8221;. That of course is also included. A search form is in the header, and is a component called &#8220;search-form&#8221;. So this component can be used in the sidebar, footer &#8211; where ever you want the form to be.</p>



<p>The search results look look like below:</p>



<p><img decoding="async" width="850" height="1116" class="alignnone size-full wp-image-6449" src="https://michaelsoriano.com/wp-content/uploads/2018/01/search-results.png" alt="search template" srcset="https://michaelsoriano.com/wp-content/uploads/2018/01/search-results.png 850w, https://michaelsoriano.com/wp-content/uploads/2018/01/search-results-228x300.png 228w, https://michaelsoriano.com/wp-content/uploads/2018/01/search-results-780x1024.png 780w, https://michaelsoriano.com/wp-content/uploads/2018/01/search-results-768x1008.png 768w" sizes="(max-width: 850px) 100vw, 850px" /><br>Also notice the paging. The paging system is inside a component called &#8220;the-loop&#8221;. For many of us theme developers, the &#8220;Loop&#8221; is the basis of a template inside a theme. So I wanted to keep the same concept here. So you will see the &#8220;archive&#8221; and &#8220;search&#8221; is basically using &#8220;the-loop&#8221; component, because it shares the same properties.</p>



<h3 class="wp-block-heading">Single, Page and Comments Form</h3>



<p>The &#8220;single&#8221; post page is also a Vue component. This accessed using the slug:</p>



<p><strong>/post/post-name</strong></p>



<p>The &#8220;page&#8221; page is another component, and can be accessed by:</p>



<p><strong>/page/page-name</strong></p>



<p>So the urls are not exactly as the traditional WordPress urls, but is quite clean in my opinion. So you need to update your permalink structure in WordPress to <strong>/post/%postname%/:</strong></p>



<p><img decoding="async" width="959" height="259" class="alignnone size-full wp-image-6467" src="https://michaelsoriano.com/wp-content/uploads/2018/02/permalink.png" alt="permalink" srcset="https://michaelsoriano.com/wp-content/uploads/2018/02/permalink.png 959w, https://michaelsoriano.com/wp-content/uploads/2018/02/permalink-300x81.png 300w, https://michaelsoriano.com/wp-content/uploads/2018/02/permalink-768x207.png 768w" sizes="(max-width: 959px) 100vw, 959px" /></p>



<p>So you can still access most of the admin functionality such as viewing pages, posts and previewing.</p>



<p>Below is an example of the single page.</p>



<p><img decoding="async" width="850" height="2231" class="alignnone size-full wp-image-6450" src="https://michaelsoriano.com/wp-content/uploads/2018/01/single.png" alt="single template" srcset="https://michaelsoriano.com/wp-content/uploads/2018/01/single.png 732w, https://michaelsoriano.com/wp-content/uploads/2018/01/single-114x300.png 114w, https://michaelsoriano.com/wp-content/uploads/2018/01/single-390x1024.png 390w, https://michaelsoriano.com/wp-content/uploads/2018/01/single-768x2016.png 768w, https://michaelsoriano.com/wp-content/uploads/2018/01/single-585x1536.png 585w, https://michaelsoriano.com/wp-content/uploads/2018/01/single-780x2048.png 780w" sizes="(max-width: 850px) 100vw, 850px" /><br>In addition, to the content &#8211; is the comments. This theme is built with the comment responses and the form in it. It is pretty basic in design &#8211; very &#8220;Bootstrapy&#8221;. But again, this is a starter theme &#8211; so what do you expect.</p>



<h3 class="wp-block-heading">Theme Structure</h3>



<p>So if you&#8217;re going to use <strong>wp-vue-starter, </strong>chances are, you&#8217;re going to edit it. So let&#8217;s go over the structure briefly. Note that you need to know WordPress and Vue a little bit to dive into this.<br>Everything goes in through <strong>index.php. </strong></p>



<p>This is where your entire HTML wrapper is. From the opening HTML tag, header and footer is inside here. You will also see that all of the templates are included in this page as &#8220;template&#8221; tags.</p>



<p><img decoding="async" width="565" height="416" class="alignnone size-full wp-image-6469" src="https://michaelsoriano.com/wp-content/uploads/2018/02/indexphp.png" alt="index" srcset="https://michaelsoriano.com/wp-content/uploads/2018/02/indexphp.png 565w, https://michaelsoriano.com/wp-content/uploads/2018/02/indexphp-300x221.png 300w" sizes="(max-width: 565px) 100vw, 565px" /></p>



<p>This is also where the DIV called &#8220;<strong>app</strong>&#8221; is &#8211; so Vue is inserting the entire application into this DIV. The <strong>styles.css</strong> in the root is nothing but a marker. It just tells WordPress about the theme name and such.</p>



<p>There are actually no styles in here. Instead, the styles go into <strong>/css/dist/main.css</strong> The <strong>main.js </strong>is where all of the JavaScript logic is. This is where the components are declared, all of the methods as well the routing. If you want to change Vue or JS logic, this is the right file. Below shows a sample of the route mapping system.</p>



<p><img decoding="async" width="654" height="720" class="alignnone size-full wp-image-6471" src="https://michaelsoriano.com/wp-content/uploads/2018/02/routes.png" alt="routes" srcset="https://michaelsoriano.com/wp-content/uploads/2018/02/routes.png 654w, https://michaelsoriano.com/wp-content/uploads/2018/02/routes-273x300.png 273w" sizes="(max-width: 654px) 100vw, 654px" /></p>



<p>Normal WordPress functions go inside the <strong>functions.php</strong>. This is where you will see modifying REST responses and such. Note that by default, the theme is allowing anonymous comments &#8211; so you might want to change this.</p>



<p>Lastly, inside the &#8220;templates&#8221; folder &#8211; are the components. They&#8217;re PHP files, but there&#8217;s no PHP logic in them. I just left it like that for consistency &#8211; and just in case you want to add some PHP in it, you can. The files resemble a traditional WordPress theme. Like 404, page, single, search etc.</p>



<p><img decoding="async" width="515" height="550" class="alignnone size-full wp-image-6472" src="https://michaelsoriano.com/wp-content/uploads/2018/02/templates.png" alt="templates" srcset="https://michaelsoriano.com/wp-content/uploads/2018/02/templates.png 515w, https://michaelsoriano.com/wp-content/uploads/2018/02/templates-281x300.png 281w" sizes="(max-width: 515px) 100vw, 515px" /></p>



<p>Lastly, the &#8220;partials&#8221; are the files with the underscore prefix. So this the _header, _footer, _sidebar. Note that this &#8220;header&#8221; is the html header &#8211; not the &#8220;&lt;head>&#8221;.</p>



<h3 class="wp-block-heading">Installation</h3>



<p>Installation is the same as any other theme. Simply upload and activate (don&#8217;t forget to update the permalinks). You can also use SASS &#8211; for CSS preprocessing. This is included by default, and is the best way to edit CSS. The source files are inside /src and output is /dist.</p>



<p>Gulp is the default build tool, so you can run</p>



<pre class="wp-block-code"><code lang="bash" class="language-bash"><strong>npm i -D gulp gulp-sass gulp-sourcemaps gulp-clean-css</strong></code></pre>



<p>For the SASS compiler and CSS clean up.</p>



<p>The theme is under MIT license, and is available in <a href="https://github.com/michaelsoriano/wp-vue-starter">GithHub</a>. I will be adding more features such as additional templates etc., so stay tuned.</p>
<p>The post <a href="https://michaelsoriano.com/wordpress-starter-theme-using-vuejs/">New WordPress Starter Theme using VueJS</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/wordpress-starter-theme-using-vuejs/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Build a SharePoint Single-Page App using nothing but Front-End Code</title>
		<link>https://michaelsoriano.com/build-sharepoint-single-page-app-front-end-code/</link>
					<comments>https://michaelsoriano.com/build-sharepoint-single-page-app-front-end-code/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Wed, 15 Jun 2016 15:49:28 +0000</pubDate>
				<category><![CDATA[CSS]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[Handlebars]]></category>
		<category><![CDATA[REST]]></category>
		<guid isPermaLink="false">http://michaelsoriano.com/?p=5501</guid>

					<description><![CDATA[<p>For this session, I would like to show you how to build a &#8220;mini&#8221; single page application in SharePoint 2013. A single page application that is ALL Front-end code (JavaScript, HTML and CSS); while using SP&#8217;s REST services. We&#8217;re also using Bootstrap for the responsiveness and tab interface, Handlebars for the templating, as well as [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/build-sharepoint-single-page-app-front-end-code/">Build a SharePoint Single-Page App using nothing but Front-End Code</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>For this session, I would like to show you how to build a &#8220;mini&#8221; single page application in SharePoint 2013. A single page application that is ALL Front-end code (JavaScript, HTML and CSS); while using SP&#8217;s <a href="https://msdn.microsoft.com/en-us/library/office/fp142380.aspx">REST services</a>. We&#8217;re also using <a href="http://getbootstrap.com/">Bootstrap</a> for the responsiveness and tab interface, <a href="http://handlebarsjs.com/">Handlebars</a> for the templating, as well as <a href="https://jquery.com/">jQuery</a> for everything else.</p>



<h5 class="wp-block-heading"><a id="user-content-note-that-this-will-require-the-following-files" class="anchor" href="https://github.com/michaelsoriano/sp-tabbed-containers#note-that-this-will-require-the-following-files" aria-hidden="true"></a>Note that this will require the following files:</h5>



<ul class="wp-block-list">
<li>jquery.min.js</li>



<li>bootstrap.min.js</li>



<li>handlebars.min.js</li>



<li>moment.min.js</li>



<li>editor.js</li>



<li>editor.css</li>



<li>bootstrap.min.css</li>



<li>font-awesome.min.css</li>
</ul>



<h5 class="wp-block-heading">The plugin already includes the above files via CDN.</h5>



<p class="btn"><a href="https://github.com/michaelsoriano/sp-tabbed-containers">View in Github</a></p>



<p>We are building &#8220;<em>Tab Containers</em>&#8220;. Basically, content that is shown in different tabs in a page. The entire CRUD interface also comes with it &#8211; so we&#8217;ll be able to add, edit and delete tab content and items, all in one page (without refreshing).</p>



<h3 class="wp-block-heading">Why is this Useful?</h3>



<p>Well there really is no way to achieve this in SharePoint. If you want to add Tabs inside an SP page, you would have to paste the whole code inside their editor. But updating this is quite cumbersome to most users.</p>



<p>This solution provides you with a nice interface to manage your tab content, while the data is stored in an SP list. The good thing about this is, you can use multiple apps and utilize just one list. So if you convert this into a webpart or an app &#8211; you simply need one list per site to make it work.</p>



<p>Ready to get started? Also, I&#8217;m only going to discuss the meat of the logic. You will need some basic JavaScript and SharePoint to follow and complete this tutorial.</p>



<h3 class="wp-block-heading">Create the List</h3>



<p>The data for our application will be stored in a custom list. The list will basically contain four columns: 1) <strong>Title</strong>: which is the default title field, 2) <strong>content</strong> which is a Rich Text type 3) <strong>tab-order</strong> a single line text value 4) <strong>webpart-id</strong> &#8211; this will be the identifier for our webpart (in case you want multiple webparts in the site).</p>



<p><img decoding="async" width="509" height="474" class="alignnone size-full wp-image-5634" src="https://michaelsoriano.com/wp-content/uploads/2016/04/sp-tabs7.jpg" alt="sp-tabs7" srcset="https://michaelsoriano.com/wp-content/uploads/2016/04/sp-tabs7.jpg 509w, https://michaelsoriano.com/wp-content/uploads/2016/04/sp-tabs7-300x279.jpg 300w" sizes="(max-width: 509px) 100vw, 509px" /></p>



<p>The title column will hold tab title, content is the contents of the tab, tab order is for ordering the tabs from left to right. You can go ahead and fill it out with dummy data for now, so we can go ahead and fetch the data for our front end. Note that that I have the list template also included in the Github page.</p>



<h3 class="wp-block-heading">Fetch the Items</h3>



<p>We are going to use a slight variation of the &#8220;<a href="https://toddmotto.com/mastering-the-module-pattern/">Revealing Module</a>&#8221; pattern to construct our code. This is especially useful when you are expecting your code to be reused multiple times in a page. In our case, users might want multiple of these web parts in a page, so a &#8220;modularized&#8221; approach is needed.</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">var SpTabs = function(){
   //ENTER REST OF CODE HERE
return {
    init : init,
    getContent : getContent
  }
}</code></pre>



<p>As you can see, we are returning two public functions from our &#8220;SpTabs&#8221; object. The &#8220;init()&#8221; method will make the object unique per instance, while the &#8220;getContent()&#8221; will fetch the items for our view. Let&#8217;s build our init() function right below:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">var init = function(obj){
    setListName(obj.listName);
    setWebPartId(obj.webPartId);
    setListItemEntityTypeFullName();
    checkPermissions();
}</code></pre>



<p>Inside our &#8220;init()&#8221;, we have some setters. It simply sets our module up for execution. The setter functions are pretty self explanatory &#8211; and you can simply investigate what each of them does in the source code. Let&#8217;s continue getting our items:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">var getContent = function(obj){
    var endpoint = "/_api/web/lists/getbytitle('"+listName+"')/Items?";
    endpoint = _spPageContextInfo.webAbsoluteUrl + endpoint + '$orderby=tab_x002d_order asc';
    endpoint += "&amp;$filter=(webpart_x002d_id eq '"+webPartId+"')";
    var ajax = $.ajax({
      url: endpoint,
      method: "GET",
      headers: { "Accept": "application/json; odata=verbose" },
      success : function(data){
        items = data.d.results;
        buildTabsHtml();
        buildTabsContentHtml();
      },
      error : function(data){
        console.log(data);
      }
    });
    return ajax;
  }
</code></pre>



<p>This is the AJAX call that goes into our API to fetch our items. As you can see, we are returning the variable &#8220;ajax&#8221; from the getContent() function, in cases where we want to add additional stuff once the response is received. But the default behavior is inside the &#8220;success&#8221; method of jQuery&#8217;s $.ajax(). </p>



<p>Note the two methods <strong>buildTabsHtml()</strong> and <strong>buildTabsContentHtml()</strong>, and our results are in our global var &#8220;items&#8221;. So we&#8217;re ready to build some output.</p>



<h3 class="wp-block-heading">Output with Handlebars</h3>



<p>Let&#8217;s create our <a href="http://handlebarsjs.com/">Handlebars</a> templates so we can use it to produce our content. In case you haven&#8217;t used it, Handlebars is a minimal template language for JavaScript. It just makes life easier. Note that we have to include our handlebars source to make it work. Also, we are using <a href="http://getbootstrap.com/">Bootstrap </a>for our tab styles. So you have to include that in your source as well.</p>



<p>The code that will make this work is inside our two methods <strong>buildTabsHtml()</strong> and <strong>buildTabsContentHtml()</strong>. Let&#8217;s go ahead and build that now:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">function buildTabsHtml(){
    var source = $("#tabs-navigation-template").html();
    var template = Handlebars.compile(source);
    $(getId() + '.tabs-navigation').html(template(items));
    //atach handlers
    $(getId()+'.tabs-navigation li a').on('click',function(){
      $(getId()+'.tabs-navigation li').removeClass('active');
      $(this).closest('li').addClass('active');
      var id = $(this).attr('data-id');
      $(getId()+'.tab-item').addClass('hidden');
      $(getId()+'div.tab-item[data-id="'+id+'"]').removeClass('hidden');
      if(id === 'addNew'){
        addNewForm();
      }
    })
  }
</code></pre>



<p>The above will output the content of our tabs. It also attaches the handlers to the tab navigation elements. Next up is the <strong>buildTabsContentHtml()</strong> method:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">function buildTabsContentHtml(){
    var source = $("#tabs-content-template").html();
    var template = Handlebars.compile(source);
    Handlebars.registerPartial("tabForm", $("#tabs-content-form-template").html());
    $(getId() + '.tabs-content').html(template(items));
    $.each(items,function(i,item){
      $(getId()+'[data-id="'+item.Id+'"] .editable-content').Editor(EditorOptions);
      $(getId()+'[data-id="'+item.Id+'"] .Editor-editor').html(item.content);
    })
    $(getId()+'.save-changes').on('click',function(){
      var id =$(this).closest('.tab-item').attr('data-id');
      if(validateFields(id)){
        $(this).addClass('fetching').html('<i class="fa fa-refresh fa-spin"></i> Saving...');
        $(getId()+'.editmode').css({'opacity':'.4'});
        setTimeout(function(){
          var ajax = submitChanges(id);
          ajax.done(function(data, xhr){
              var ajax2 = getContent();
              ajax2.done(function(){
                $(getId()+'.tabs-navigation li a[data-id="'+id+'"]').trigger('click');
                addButton();
              });
          });
        },1000);
      }else{
        showErrorMessage(id);
      }
      return false;
    })
</code></pre>



<p>Now things got a bit hairy. First you&#8217;ll notice our handlebars compile &#8211; which is normal, but note the &#8220;registerPartial()&#8221; method. This means that we&#8217;re adding another handlebars template into our existing template. This is the form that handles our inline editing. I&#8217;m not going to post the code on here, instead you can see the #tabs-content-form-template from our <a href="https://github.com/michaelsoriano/sp-tabbed-containers/blob/master/sp-tabbed-containers.txt">text</a> file &#8211; which simply contains a few input forms for our app.</p>



<h3 class="wp-block-heading">Why use partials within templates?</h3>



<p>This is another powerful feature of handlebars. This allows for more re-usability and &#8220;modularity&#8221; for your applications. In other words, we write once and re-use multiple times. In our case, the form can be reused multiple times across our application &#8211; in &#8220;edit&#8221; and &#8220;new&#8221; mode. This will become evident as you write along.</p>



<p>We&#8217;re also using a lightweight WYSWG editor called &#8220;<a href="http://suyati.github.io/line-control">Line Control</a>&#8220;. Since we&#8217;re already using Bootstrap and FontAwesome, it just makes sense that we use a plugin that requires the same libraries. So this is what&#8217;s happening on lines 8-9 above: &#8220;.Editor(EditorOptions)&#8221;, where &#8220;<em>EditorOptions</em>&#8221; is declared on top of of our file as an array.</p>



<h3 class="wp-block-heading">Insert, Update and Delete</h3>



<p>Finally, we attach our &#8220;Save&#8221; and &#8220;Delete&#8221; buttons to do a couple of REST calls to our server when clicked. First our &#8220;Save&#8221; button is connected to our &#8220;<em>submitChanges</em>(id)&#8221; method (which takes care of both &#8220;edits&#8221; and &#8220;inserts&#8221;), while the next call is to &#8220;<em>getContent</em>()&#8221; &#8211; which is our main function to grab the tab items.</p>



<p>The &#8220;Delete&#8221; will also consist of two main REST calls, which is to delete and fetch the records. Our &#8220;<em>deleteRecord</em>()&#8221; function is shown below:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">function deleteRecord(tab){
    var ajax = $.ajax({
       url: tab.__metadata.uri,
       type: "POST",
       headers: {
           "Accept": "application/json;odata=verbose",
           "X-RequestDigest": $("#__REQUESTDIGEST").val(),
           "X-HTTP-Method": "DELETE",
           "If-Match": tab.__metadata.etag
       },
       success: function (data) {
          console.log('record has been deleted');
       },
       error: function (data) {
          console.log('there was a problem with deleting the record');
       }
   });
   return ajax;
  }</code></pre>



<p>While our &#8220;submitChanges()&#8221; method looks like so:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">function submitChanges(id){
      var item = {
        "__metadata": { "type": ListItemEntityTypeFullName },
        "Title" :   $(getId()+'[data-id="'+id+'"] input[name="title"]').val(),
        "content" : $(getId()+'[data-id="'+id+'"] .Editor-editor').html(),
        "tab_x002d_order" : $(getId()+'[data-id="'+id+'"] input[name="tab-order"]').val()
      };
      if(id === 'addNew'){
        item.webpart_x002d_id = webPartId;
        var endpoint = "/_api/web/lists/getbytitle('" + listName + "')/items";
        ajax = $.ajax({
           url: _spPageContextInfo.webAbsoluteUrl + endpoint,
           type: "POST",
           contentType: "application/json;odata=verbose",
           data: JSON.stringify(item),
           headers: {
               "Accept": "application/json;odata=verbose",
               "X-RequestDigest": $("#__REQUESTDIGEST").val()
           },
           error: function (data) {
              console.log(data);
           }
       });
       return ajax;
      } //end addNew;
      var tabItem = findItem(id);
      ajax = $.ajax({
         url: tabItem.__metadata.uri,
         type: "POST",
         contentType: "application/json;odata=verbose",
         data: JSON.stringify(item),
         headers: {
             "Accept": "application/json;odata=verbose",
             "X-RequestDigest": $("#__REQUESTDIGEST").val(),
             "X-HTTP-Method": "MERGE",
             "If-Match": tabItem.__metadata.etag
         },
         error: function (data) {
            console.log(data);
         }
     });
     return ajax;
  }
</code></pre>



<p>Note that all of the REST calls all look similar, with a select few nodes that changes. First you&#8217;ll notice the &#8220;X-HTTP-Method&#8221; for edits is &#8220;MERGE&#8221; and &#8220;DELETE&#8221; for deleting. The rest are pretty much SharePoint REST API requirements &#8211; which you can find more on <a href="https://msdn.microsoft.com/en-us/library/office/jj860569.aspx">this page</a>. Our &#8220;item&#8221; object is also mapped to the names of the list columns that we have. Depending on your list &#8211; you may need to modify this area as well.</p>



<p>In our UI, note the placement of our buttons and our form:<br><img decoding="async" width="509" height="557" class="alignnone size-full wp-image-5632" src="https://michaelsoriano.com/wp-content/uploads/2016/04/sp-tabs5.jpg" alt="sp-tabs5" srcset="https://michaelsoriano.com/wp-content/uploads/2016/04/sp-tabs5.jpg 509w, https://michaelsoriano.com/wp-content/uploads/2016/04/sp-tabs5-274x300.jpg 274w" sizes="(max-width: 509px) 100vw, 509px" /><br>Lastly, you notice a couple of helper functions &#8220;getId()&#8221; and &#8220;findItem()&#8221;. The <strong>getId()</strong> simply returns our current div &#8211; with the &#8220;#&#8221; and a space as a string (or the CSS selector for the current div), while our <strong>findItem()</strong> loops through our global <strong>items</strong> object and returns the current item.</p>



<p>Moving forward, let&#8217;s look at a couple of important internal methods which includes our validation and error messaging mechanism.</p>



<h3 class="wp-block-heading">Form Validation</h3>



<p>Since we&#8217;re entering our data into our SharePoint lists through client side, we can implement a validation method using JavaScript as well. The cool thing about SP&#8217;s REST API has it&#8217;s own validation in the server side so all we have to worry about is the user experience.</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">function validateFields(id){
    errors = [];
    $('.error').remove();
    var title = $(getId()+'[data-id="'+id+'"] input[name="title"]');
    var content = $(getId()+'[data-id="'+id+'"] .Editor-editor');
    var tabOrder = $(getId()+'[data-id="'+id+'"] input[name="tab-order"]');
    if(title.val() == ''){
      var obj = {};
      obj.field = 'title';
      obj.message = 'Title cannot be empty'
      errors.push(obj);
    }
    if(content.html() == ''){
      var obj = {};
      obj.field = 'content';
      obj.message = 'Content cannot be empty'
      errors.push(obj);
    }
    if(tabOrder.val() == ''){
      var obj = {};
      obj.field = 'tab-order';
      obj.message = 'Tab order cannot be empty'
      errors.push(obj);
    }
    if(errors.length &gt; 0){
      return false;
    }
    return true;
  }
</code></pre>



<p>Our very simple validation code is above. Note that this happens every time that &#8220;submit&#8221; button is clicked. So it simply goes through the fields &#8211; check for empty and puts the errors in an array. I&#8217;m not checking for anything else like valid data etc &#8211; and feel free to add your own rules. Simply keep pushing the error messages into our array when invalid. Our messaging is handled in the code below:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">function showErrorMessage(id){
    $.each(errors,function(i,er){
      var field = '';
      if(er.field === 'content'){
        field = $(getId()+'[data-id="'+id+'"] .Editor-container');
      }else{
        field = $(getId()+'[data-id="'+id+'"] input[name="'+er.field+'"]');
      }</code></pre>



<p><em>[the code above has been truncated due to an error w syntax highlighter&#8230; sorry]</em></p>



<p>The following screenshot shows our validation code in action. Error messaging is placed underneath each label and at the same time. This way, users can see where they had made an error and fix. Remember to add your own rules as necessary.</p>



<p><br><img decoding="async" width="516" height="502" class="alignnone size-full wp-image-5764" src="https://michaelsoriano.com/wp-content/uploads/2016/05/tabs-validation.png" alt="tabs-validation" srcset="https://michaelsoriano.com/wp-content/uploads/2016/05/tabs-validation.png 516w, https://michaelsoriano.com/wp-content/uploads/2016/05/tabs-validation-300x292.png 300w" sizes="(max-width: 516px) 100vw, 516px" /></p>



<h3 class="wp-block-heading">Checking Permissions</h3>



<p>Finally, since we&#8217;re not using the regular SharePoint process in updating a page with tabs, we need to come up with our own. See, the entity we&#8217;re updating is not the current page &#8211; but a list. So we need to check if the current user has permission to edit the list &#8211; and give them access to our newly created UI.<br>I found this <a href="http://www.lifeonplanetgroove.com/checking-user-permissions-from-the-sharepoint-2013-rest-api/">great article</a> on how to effectively do this &#8211; since Microsoft&#8217;s documentation is a bit vague. </p>



<p>We&#8217;re using the &#8220;effectiveBasePermissions&#8221; REST endpoint along with SP.BasePermissions() class &#8211; which we need from SP.ClientContext object. Yes, it&#8217;s a bit of a mess so simply check the code below:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">function checkPermissions() {
    SP.SOD.executeFunc('sp.js', 'SP.ClientContext', function () {
      var call = jQuery.ajax({
          url: _spPageContextInfo.webAbsoluteUrl +
              "/_api/Web/lists/getbytitle('"+listName+"')/effectiveBasePermissions",
          type: "GET",
          dataType: "json",
          headers: {
              Accept: "application/json;odata=verbose"
          }
      });
      call.done(function (data, textStatus, jqXHR) {
          var permissions = new SP.BasePermissions();
          permissions.initPropertiesFromJson(data.d.EffectiveBasePermissions);
          var permLevels = [];
          for(var permLevelName in SP.PermissionKind.prototype) {
              if (SP.PermissionKind.hasOwnProperty(permLevelName)) {
                  var permLevel = SP.PermissionKind.parse(permLevelName);
                  if(permissions.has(permLevel)){
                        permLevels.push(permLevelName);
                  }
              }
          }
          // console.log(permLevels);
          if($.inArray('editListItems',permLevels) != -1){
            userCanEdit = true;
            addButton();
          }else{
            console.log('You dont have "editListItems" permissions on '+ listName);
          }
      });  //end done
    });
  }
</code></pre>



<p>We&#8217;re still using jQuery&#8217;s ajax to get information, though it&#8217;s wrapped inside a &#8220;SP.SOD.executeFunc()&#8221; method &#8211; which is Microsoft&#8217;s way of loading and executing internal scripts. What we get back is an array we&#8217;re calling &#8220;permLevels&#8221; This array contains all the permissions a user has against our list. </p>



<p>We&#8217;re simply looking for the &#8220;editListItems&#8221; &#8211; and if found, we&#8217;re show the button and let the user edit.<br><img decoding="async" width="638" height="495" class="alignnone size-full wp-image-5767" src="https://michaelsoriano.com/wp-content/uploads/2016/05/tabs-45.jpg" alt="tabs-45" srcset="https://michaelsoriano.com/wp-content/uploads/2016/05/tabs-45.jpg 638w, https://michaelsoriano.com/wp-content/uploads/2016/05/tabs-45-300x233.jpg 300w" sizes="(max-width: 638px) 100vw, 638px" /></p>



<h3 class="wp-block-heading">Final Steps</h3>



<p>Our code is now complete. Note that there is not a single line of .NET code above &#8211; it&#8217;s all JavaScript, HTML and CSS. All server interactions are done through the REST API. This code can be applied whichever way you want to implement &#8211; may it be a custom web part, an app part or simply add the code to a Content Editor.</p>



<p>Remember to update the initialize settings like below: The important part is the &#8220;webPartId&#8221; and &#8220;listName&#8221; parameters &#8211; which connects the plugin to the data you need.</p>



<p><img decoding="async" width="432" height="330" class="alignnone size-full wp-image-5631" src="https://michaelsoriano.com/wp-content/uploads/2016/04/sp-tabs4.jpg" alt="sp-tabs4" srcset="https://michaelsoriano.com/wp-content/uploads/2016/04/sp-tabs4.jpg 432w, https://michaelsoriano.com/wp-content/uploads/2016/04/sp-tabs4-300x229.jpg 300w" sizes="(max-width: 432px) 100vw, 432px" /></p>



<p>Once that&#8217;s done, simply reload the page and you should see your SPA in action. Note that the code editor I used is very basic &#8211; so you might need to go to the list itself when updating content.</p>



<p><img decoding="async" width="581" height="597" class="alignnone size-full wp-image-5858" style="border: 1px solid #ebebeb;" src="https://michaelsoriano.com/wp-content/uploads/2016/06/sp-tabs2.gif" alt="sp-tabs2"></p>



<p>This editor was mostly designed for quick updates to your content.</p>



<p>Remember, the purpose of this article was really to expose you to the inner workings of REST and how to build a single page application right inside SharePoint with existing open technologies such as jQuery, Handlebars and Bootstrap. </p>



<p>Hope you enjoy this piece. Let me know your comments below.</p>
<p>The post <a href="https://michaelsoriano.com/build-sharepoint-single-page-app-front-end-code/">Build a SharePoint Single-Page App using nothing but Front-End Code</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/build-sharepoint-single-page-app-front-end-code/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
		<item>
		<title>Build a Better Photo Gallery for SharePoint using REST and Handlebars</title>
		<link>https://michaelsoriano.com/better-photo-gallery-sharepoint-rest-and-handlebars/</link>
					<comments>https://michaelsoriano.com/better-photo-gallery-sharepoint-rest-and-handlebars/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Mon, 21 Mar 2016 01:01:35 +0000</pubDate>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[Handlebars]]></category>
		<category><![CDATA[REST]]></category>
		<guid isPermaLink="false">http://michaelsoriano.com/?p=5473</guid>

					<description><![CDATA[<p>Working with SharePoint&#8217;s REST API is pretty cool. Lately, I&#8217;ve been writing plenty of applications where the entire CRUD is involved; all using SharePoint lists behind the scenes. Meaning, the entire front end is entirely up to me to build. This way, I can use different JavaScript libraries and frameworks when building these interfaces. Note [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/better-photo-gallery-sharepoint-rest-and-handlebars/">Build a Better Photo Gallery for SharePoint using REST and Handlebars</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Working with SharePoint&#8217;s REST API is pretty cool. Lately, I&#8217;ve been writing plenty of applications where the entire <a href="https://en.wikipedia.org/wiki/Create,_read,_update_and_delete">CRUD</a> is involved; all using SharePoint lists behind the scenes. Meaning, the entire front end is entirely up to me to build. This way, I can use different JavaScript libraries and frameworks when building these interfaces.</p>



<h4 class="wp-block-heading">Note that this will require the following files:</h4>



<ul class="wp-block-list"><li>bootstrap.css</li><li>magnific-popup.css</li><li>jquery-1.12.0.min.js</li><li>jquery.magnific-popup.min.js</li></ul>



<p><strong>The plugin already includes the above files via CDN. The Plugin JavaScript and CSS is also included via RawGit &#8211; so changes may affect your working files.</strong></p>



<p class="btn"><a href="https://github.com/michaelsoriano/sp-photo-gallery">View in Github</a></p>



<p><br>Today, let&#8217;s look at something pretty simple. Let&#8217;s build a photo gallery using <a href="https://products.office.com/en-us/sharepoint/collaboration">SharePoint</a> Picture library as the backend, together with <a href="http://handlebarsjs.com/">Handlebars.js</a> &#8211; a good Javascript templating system. With this knowledge, you will gain good understanding on how to select items with SharePoint&#8217;s REST API, which I happen to have a <a href="https://michaelsoriano.com/understanding-sharepoint-rest-api-part-1-selecting-items/">post</a> on.</p>



<p><br><img decoding="async" width="750" height="500" class="alignnone size-full wp-image-5868" src="https://michaelsoriano.com/wp-content/uploads/2015/02/bspg2.jpg" alt="bspg2" srcset="https://michaelsoriano.com/wp-content/uploads/2015/02/bspg2.jpg 750w, https://michaelsoriano.com/wp-content/uploads/2015/02/bspg2-300x200.jpg 300w" sizes="(max-width: 750px) 100vw, 750px" /></p>



<p>Ready to get started? Roll up your sleeves and let&#8217;s write some code. Note that I will not go over the entire code base in this tutorial &#8211; just the meat of the logic.</p>



<h3 class="wp-block-heading">Setup the Gallery</h3>



<p>First we need to make sure we have a gallery to connect to. In SharePoint, you do this by going to &#8220;View All Site Content&#8221; and adding a new Picture Library. Note that for this demo I&#8217;m using SharePoint 2010 &#8211; I believe in newer versions you have to &#8220;<em>Add an App</em>&#8221; &gt; &#8220;<em>Photo Library</em>&#8220;.</p>



<p>Be sure to note the name of your library:<br><img decoding="async" width="660" height="469" class="alignnone size-full wp-image-5483" src="https://michaelsoriano.com/wp-content/uploads/2016/02/sp-photo-gallery-3.jpg" alt="sp-photo-gallery-3" srcset="https://michaelsoriano.com/wp-content/uploads/2016/02/sp-photo-gallery-3.jpg 660w, https://michaelsoriano.com/wp-content/uploads/2016/02/sp-photo-gallery-3-300x213.jpg 300w" sizes="(max-width: 660px) 100vw, 660px" /><br>Upload some images to your newly created library. Now we can continue and pull our images in the front end.</p>



<h3 class="wp-block-heading">The Javascript</h3>



<p>Create a Javasript file and name it sp-gallery.js. You can place it inside any SharePoint document library &#8211; and simply map to it using Windows Explorer so you can write to it just like you would as if it was a local file.</p>



<p>Let&#8217;s setup the wrapper for our gallery. We&#8217;re using the &#8220;<a href="https://addyosmani.com/resources/essentialjsdesignpatterns/book/#revealingmodulepatternjavascript">Revealing Module</a>&#8221; pattern so we can have methods that are public and private, as well as we keep our logic real tidy. We&#8217;re adding private variables inside our class so we can use it all over our code.</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">var gallery = function(list){
  var webUrl = _spPageContextInfo.webAbsoluteUrl;
  var listName = list;
  var limit = 20;
  var skip = 0;
  var total = 0;
}</code></pre>



<h6 class="wp-block-heading">Get the List Count</h6>



<p>Our first method is to grab the number of photos in our library. This is important so we can decide whether to show our &#8220;show more&#8221; button or not. Note the use our our &#8220;webUrl&#8221; and &#8220;listName&#8221; variables in our method. Add this code inside our gallery wrapper. This method is internal, so we create a function declaration:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">function getListCount(webUrl,listName) {
    var url = webUrl + "/_vti_bin/listdata.svc/" + listName + '/$count';
    var ajax = $.ajax({
        url: url,
        method: "GET",
        headers: { "Accept": "application/json;odata=verbose,text/plain" },
        error: function (data) {
          console.log('error in fetching list count');
          console.log(data.responseJSON.error);
        }
    });
    return ajax;
}</code></pre>



<p>The above will return a &#8220;promise&#8221; object that we can use to manipulate later on. In the case above, it&#8217;s simply a number.</p>



<h3 class="wp-block-heading">Get the Gallery Items</h3>



<p>This method is the call to grab our list items. Again, we&#8217;re using jQuery&#8217;s &#8220;Ajax&#8221; method, returning a promise object.</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">function getListItems(webUrl,listName, itemId) {
    var url = webUrl + "/_vti_bin/listdata.svc/" + listName;
    if(itemId !== null){
      url += "(" + itemId + ")";
    }
    url += '?$top='+limit+'&amp;$skip='+skip;
    var ajax = $.ajax({
        url: url,
        method: "GET",
        headers: { "Accept": "application/json; odata=verbose" },
        error: function (data) {
          console.log(data.responseJSON.error);
        }
    });
    return ajax;
  }</code></pre>



<h3 class="wp-block-heading">Compile with HandleBars</h3>



<p>This method is taking the data that is returned from our ajax promise above, and compiling it with handlbars. We haven&#8217;t built our HTML yet &#8211; which contains the actual handebars template. Note that this is a public function, so we&#8217;re creating the function as a &#8220;function expression&#8221;:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">var buildGallery = function(data){
      var source   = $("#photogallery").html();
      var template = Handlebars.compile(source);
      $('.photo-gallery-wrap').append(template(data));
      $('.popup').magnificPopup({
          type: 'image',
          gallery:{
            preload: [0,5],
            enabled:true
          },
          removalDelay: 300,
          mainClass: 'mfp-fade'
      });
  }</code></pre>



<p>Also note that I&#8217;ve added a &#8220;popup&#8221; functionality which we&#8217;ve instantiated in the code above. We&#8217;re using <a href="http://dimsemenov.com/plugins/magnific-popup/">magnificpopup.js</a> for this awesome feature.</p>



<h3 class="wp-block-heading">The &#8220;Show More&#8221; button</h3>



<p>We&#8217;re only loading a certain subset of photos in our gallery. We will have a button in the bottom of our images that when clicked, will do another fetch to our list and add them below. Again, this is public, so it&#8217;s a &#8220;function expression&#8221;.</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">var showmore = function (){
      $('#showmore').addClass('fetching').html('Loading images...');
      skip = skip+limit;
      var ajax2 = getListItems(webUrl,listName, null);
      ajax2.done(function(data){
        buildGallery(data);
        $('#showmore').removeClass('fetching').html('Show More');
        if($('.thumbnail-wrap').length &gt;= total){
            $('#showmore').hide();
        }
      });
      return false;
  }</code></pre>



<p>This sort of acts like an &#8220;infinite scroll&#8221; functionality &#8211; but with a button. I&#8217;m not particularly fond of that automatic loading.</p>



<h3 class="wp-block-heading">Initializing the Gallery</h3>



<p>Now that our methods are in place, it is time to tie them all together and returning them so we can call them outside of our class. We do this by creating an &#8220;init&#8221; function.</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">var gallery = function(list){
//our private vars here...
var init = function(){
      var ajax1 = getListCount(webUrl,listName);
      var ajax2 = getListItems(webUrl,listName, null);
      ajax1.done(function(data){
        total = data;
        if(total &lt;= limit){
          $('#showmore').hide();
        }
      });
      ajax2.done(function(data){
        buildGallery(data);
      });
  }
//the rest of the methods here...
//below returns our public methods for use:
 return {
    init : init,
    showmore : showmore,
    buildGallery : buildGallery
  }</code></pre>



<p>Notice that we are only returning the public functions above. So we are keeping our variables and private functions inaccessible from the outside world. Let&#8217;s move on to our helpers:</p>



<h3 class="wp-block-heading">HandleBar Helpers</h3>



<p>These methods doesn&#8217;t have to be our gallery code. This can live outside, so it can be accessed by Handlebars. The code is namespaced using the Handlebars object. I&#8217;ll explain what the do below:</p>



<pre class="wp-block-code"><code lang="javascript" class="language-javascript">Handlebars.registerHelper('findGroup', function(data) {
    var remove = _spPageContextInfo.webServerRelativeUrl;
    var str = data.Path;
    return str.replace(remove+'/','');
});
Handlebars.registerHelper('imgSrc', function(data) {
    var url = _spPageContextInfo.siteAbsoluteUrl;
    url += data.Path;
    url += '/' + data.Name
    return url;
});
Handlebars.registerHelper('imgSrcThumb', function(data) {
    var thumb = data.Name;
    thumb = thumb.replace('.jpg', '_jpg.jpg');
    var url = _spPageContextInfo.siteAbsoluteUrl;
    url += data.Path;
    url += '/_t/' + thumb;
    return url;
});</code></pre>



<p>We will use a &#8220;<em>findGroup</em>&#8221; helper inside our templates so we can &#8220;group&#8221; our photos together. This is what our &#8220;<em>Magnificpopup</em>&#8221; plugin requires &#8211; so when you click &#8220;next&#8221; or &#8220;previous&#8221; &#8211; it knows which photo to show.</p>



<p>The &#8220;imgSrc&#8221; helper simply returns the source of the images, while the &#8220;imgSrcThumb&#8221; returns the thumbnail path. Note that this helper only supports jpegs at the moment.</p>



<h3 class="wp-block-heading">The CSS</h3>



<p>We are simply displaying the thumbnails in a grid fashion, so our styles are quite basic. I&#8217;m using this inside a Bootstrap wrapper, so you can see the &#8220;.col&#8221; classes in our HTML later. Create a file and name it sp-gallery.css and add the code below:</p>



<pre class="wp-block-code"><code lang="css" class="language-css">.photo-gallery-wrap {
  overflow: hidden;
  margin-right: -30px;
}
.thumbnail {
  display: inline-block;
  width: 100%;
  height: 100px;
  background-position: center center !important;
  text-indent: -9999px;
}
.thumbnailHidden {
  display:none;
}
.showMoreWrap {
  clear:both;
  display:block;
}
#showmore {
  color:#fff;
}
#showmore.fetching {
  background:#AAD3AA;
  border:#9AC39A;
}
.thumbnail-wrap {
  margin-bottom: 25px;
}
.thumbnail-wrap.col-lg-3 {
  padding-left:0;
  padding-right: 30px;
}
@media(max-width:387px){
  .thumbnail-wrap.col-lg-3 {
    padding-right: 15px;
  }
  .col-xxs-6 {
    width:50%;
  }
  #showmore {
    display:block;
  }
}
@media(max-width:240px){
  .col-xxxs-12 {
    width:100%;
  }
}
/* overlay at start */
.mfp-fade.mfp-bg {
  opacity: 0;
  -webkit-transition: all 0.15s ease-out;
  -moz-transition: all 0.15s ease-out;
  transition: all 0.15s ease-out;
}
/* overlay animate in */
.mfp-fade.mfp-bg.mfp-ready {
  opacity: 0.8;
}
/* overlay animate out */
.mfp-fade.mfp-bg.mfp-removing {
  opacity: 0;
}
/* content at start */
.mfp-fade.mfp-wrap .mfp-content {
  opacity: 0;
  -webkit-transition: all 0.15s ease-out;
  -moz-transition: all 0.15s ease-out;
  transition: all 0.15s ease-out;
}
/* content animate it */
.mfp-fade.mfp-wrap.mfp-ready .mfp-content {
  opacity: 1;
}
/* content animate out */
.mfp-fade.mfp-wrap.mfp-removing .mfp-content {
  opacity: 0;
}</code></pre>



<p>I&#8217;ve also added extra &#8220;col&#8221; classes for my own grid styles when the viewport is decreased. Also notice the .mfp classes are necessary for our magnific popup to work &#8220;magnificently&#8221;.</p>



<h3 class="wp-block-heading">The HTML</h3>



<p>Finally, this is the file that we add to any page of our SharePoint site. Create a text file &#8211; name it &#8220;sp-gallery.txt&#8221; and add the code below:</p>



<pre class="wp-block-code"><code lang="markup" class="language-markup">&lt;script src="https://code.jquery.com/jquery-1.12.0.min.js"&gt;&lt;/script&gt;
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/4.0.5/handlebars.min.js"&gt;&lt;/script&gt;
&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/magnific-popup.js/1.0.1/jquery.magnific-popup.min.js"&gt;&lt;/script&gt;
&lt;script src="ADD-YOUR-PATH-HERE/sp-gallery.js"&gt;&lt;/script&gt;
&lt;script&gt;
$(document).ready(function(){
  var photos = gallery('TestPhotoLib'); //change to your document library name
  photos.init();
  $('#showmore').on('click', photos.showmore);
})
&lt;/script&gt;
&lt;div class="photo-gallery-wrap"&gt;&lt;/div&gt;
&lt;div class="showMoreWrap"&gt;
&lt;a id="showmore" class="btn btn-sm btn-success" href="#"&gt;Show More&lt;/a&gt;&lt;/div&gt;</code></pre>



<p>&nbsp;<br>The above contains the references to the files we need.</p>



<p>We went ahead and create our gallery and pass in the name of our Photo Gallery above. We then initialize and add the &#8220;showmore&#8221; handler when our button is clicked.</p>



<p>Add our Handlebars template to the text file:</p>



<pre class="wp-block-code"><code lang="markup" class="language-markup">&lt;script id="photogallery" type="text/x-handlebars-template"&gt;
{{#each d}}
&lt;div class="col-lg-3 col-md-3 col-sm-3 col-xs-4 col-xxs-6 col-xxxs-12 thumbnail-wrap"&gt;
  &lt;a href="{{imgSrc this}}" group="{{findGroup this}}" class="thumbnail popup" style="background:url('{{imgSrcThumb this}}');" &gt;
    {{Name}}
  &lt;/a&gt;
&lt;/div&gt;
{{/each}}
&lt;/script&gt;</code></pre>



<p>&nbsp;<br>The above template is what we need for our gallery to work. This code represents each tile that we will produce in our gallery.</p>



<p>Save this text file (along with the .js and .css) and add it to any SharePoint page. Add a Content Editor WebPart, and add a link to an external file &#8211; to our .txt file.</p>



<p><br><img decoding="async" width="418" height="290" class="alignnone size-full wp-image-5482" src="https://michaelsoriano.com/wp-content/uploads/2016/02/sp-photo-gallery-2.jpg" alt="sp-photo-gallery-2" srcset="https://michaelsoriano.com/wp-content/uploads/2016/02/sp-photo-gallery-2.jpg 418w, https://michaelsoriano.com/wp-content/uploads/2016/02/sp-photo-gallery-2-300x208.jpg 300w" sizes="(max-width: 418px) 100vw, 418px" /><br>I usually edit the webpart to &#8220;NOT&#8221; show the chrome.</p>



<h3 class="wp-block-heading">Final Result</h3>



<p>Save the page and if everything works well, you should see something like below:</p>



<p><img decoding="async" width="602" height="480" class="alignnone size-full wp-image-5869" src="https://michaelsoriano.com/wp-content/uploads/2015/02/bspg.gif" alt="bspg"><br></p>



<p>A simple photo gallery with popup and paging functionality. It surely looks better than the &#8220;out of the box&#8221; photo gallery that SP provides. Furthermore, you have complete ability to change the look as much as you want.</p>



<p>But the real value is the introductory lesson to working with SharePoint&#8217;s REST api. Be sure to stay tuned for more stuff like this. </p>



<p>Leave your comments below.</p>
<p>The post <a href="https://michaelsoriano.com/better-photo-gallery-sharepoint-rest-and-handlebars/">Build a Better Photo Gallery for SharePoint using REST and Handlebars</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/better-photo-gallery-sharepoint-rest-and-handlebars/feed/</wfw:commentRss>
			<slash:comments>47</slash:comments>
		
		
			</item>
		<item>
		<title>Understanding SharePoint&#8217;s REST and Search API Part 1 &#8211; Selecting Items</title>
		<link>https://michaelsoriano.com/understanding-sharepoint-rest-api-part-1-selecting-items/</link>
					<comments>https://michaelsoriano.com/understanding-sharepoint-rest-api-part-1-selecting-items/#comments</comments>
		
		<dc:creator><![CDATA[Michael Soriano]]></dc:creator>
		<pubDate>Sat, 16 Jan 2016 19:44:12 +0000</pubDate>
				<category><![CDATA[SharePoint]]></category>
		<category><![CDATA[REST]]></category>
		<category><![CDATA[Search API]]></category>
		<guid isPermaLink="false">http://michaelsoriano.com/?p=5349</guid>

					<description><![CDATA[<p>SharePoint 2013 has a REST API that exposes plenty of information about users, lists and document libraries. For front end developers, this is a gold mine. A gold mine because of two things: 1) SharePoint&#8217;s out of the box UI is pretty bad, and 2) SharePoint&#8217;s out of the box UI is pretty bad. Update [&#8230;]</p>
<p>The post <a href="https://michaelsoriano.com/understanding-sharepoint-rest-api-part-1-selecting-items/">Understanding SharePoint&#8217;s REST and Search API Part 1 &#8211; Selecting Items</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>SharePoint 2013 has a REST API that exposes plenty of information about users, lists and document libraries. For front end developers, this is a gold mine. A gold mine because of two things: 1) SharePoint&#8217;s out of the box UI is pretty bad, and 2) SharePoint&#8217;s out of the box UI is pretty bad.</p>
<div style="padding: 15px 20px; background: #fcffe6; border-radius: 4px; border: 1px solid #e5e9cd; margin-top: 20px; margin-bottom: 25px;"><strong>Update 3/2017:</strong> I&#8217;ve added Search API to this post as well. Continue reading below.</div>
<p>So plenty of room for improvement here. Now we can basically recreate SharePoint&#8217;s front end: entire new CRUD interfaces and such. And the base of it all &#8211; is its REST API.<br />
It is important to recognize that SharePoint REST API is using <a href="http://www.odata.org/">OData</a>, which is a widely used convention when in comes to RESTful web services. You can learn more about the syntax from their website.<br />
For this post I would like to cover <strong>Selecting Items</strong>.<br />
Note that I prefer using jQuery&#8217;s <strong>$.ajax</strong> method. So all my calls will look like below:</p>
<pre>$.ajax({
   url: url, //THE ENDPOINT
   method: "GET",
   headers: { "Accept": "application/json; odata=verbose" },
   success: function (data) {
        console.log(data.d.results) //RESULTS HERE!!
   }
});
</pre>
<p>All we&#8217;re doing is replacing the <strong>url</strong><br />
<strong>A special note on SP 2010 users:</strong> the querystring section of the examples below may be the same. The only difference I&#8217;ve seen is the endpoint part of the url. SP 2010 has below:</p>
<pre class="">"/_vti_bin/listdata.svc/" + querystring</pre>
<h3>1) Selecting all items, all columns</h3>
<p>The simplest way to grab list items is to get everything. This is done by using the endpoint below. Simply change the &#8220;list&#8221; value to your own:</p>
<pre class="">/_api/web/lists/getbytitle('listname')/Items?$select=*</pre>
<p>Again, this will select &#8220;almost&#8221; all columns that are available to the list.  Note that I said &#8220;almost&#8221;, because SharePoint&#8217;s REST API doesn&#8217;t really bring back everything. Things such as author information and values of lookups have to be queried differently (more on this below).</p>
<h3>2) Selecting all items, custom columns</h3>
<p>)I find it good practice to only grab the columns that I need. This makes the payload as lean as possible.</p>
<pre class="">/_api/web/lists/getbytitle('listname')/Items?$select=ID,Title</pre>
<p>This also makes it easier to find things because each Javascript object only contain the columns &#8220;ID&#8221; and &#8220;Title&#8221;. What I don&#8217;t understand is why &#8220;ID&#8221; and &#8220;Id&#8221; is present &#8211; maybe a configuration error with the list. But nevertheless, the result is more manageable:<br />
<img decoding="async" class="alignnone size-full wp-image-5453" src="https://michaelsoriano.com/wp-content/uploads/2016/01/rest-select-1.jpg" alt="rest-select-1" width="449" height="181" srcset="https://michaelsoriano.com/wp-content/uploads/2016/01/rest-select-1.jpg 449w, https://michaelsoriano.com/wp-content/uploads/2016/01/rest-select-1-300x121.jpg 300w" sizes="(max-width: 449px) 100vw, 449px" /></p>
<h3>3) Getting the total items in a list</h3>
<p>To get the number of items in a list, append the &#8220;ItemCount&#8221; in the end of your query sting.</p>
<pre class="">/_api/web/lists/getbytitle('listName')/ItemCount
</pre>
<p>I know that you can simply do a &#8220;.length&#8221; from the a regular call which brings you all of your results, but the above is useful for filtered results, or when paging. The output looks like below:<br />
<img decoding="async" class="alignnone size-full wp-image-5470" src="https://michaelsoriano.com/wp-content/uploads/2016/01/item-count1.jpg" alt="item-count1" width="340" height="125" srcset="https://michaelsoriano.com/wp-content/uploads/2016/01/item-count1.jpg 340w, https://michaelsoriano.com/wp-content/uploads/2016/01/item-count1-300x110.jpg 300w" sizes="(max-width: 340px) 100vw, 340px" /></p>
<h3>4) Retrieving specific list items</h3>
<p>Now this endpoint will only get the list item with the ID of &#8220;4&#8221; (I&#8217;ve removed the &#8220;_spPageContextInfo.webAbsoluteUrl&#8221; component for easier read&#8230;</p>
<pre class="">/_api/web/lists/getbytitle('listname')/items(4)</pre>
<p>A more powerful solution is using the <strong>$filter</strong> key. Not that this option allows you to get items with more flexibility. Check out this example which grabs items with the title equals to &#8220;example 1&#8221;. Note the use of single quotes! Almost all values in SharePoint REST use single quotes!</p>
<pre class="">/_api/web/lists/getbytitle('listname')/Items?$select=Title&amp;$filter=Title eq 'example 1'</pre>
<h3>5) Multiple $filter keys + values</h3>
<p>To get items that have Title that is equal to multiple values, use the endpoint below:</p>
<pre class="">/_api/web/lists/getbytitle('listname')/Items?$select=Title&amp;$filter=((Title eq 'example 1') or (Title eq 'example 2'))</pre>
<p>Notice that I used parenthesis to enclose the multiple parameters. This is completely optional &#8211; but improves readability.<br />
In the case of multiple &#8220;ANDs&#8221; and &#8220;ORs&#8221;, for a stricter and finer result set, you need to use the parenthesis to enclose filter sets. This example below:</p>
<pre class="">/_api/web/lists/getbytitle('ListName')/Items?$&amp;$select=Title&amp;$filter=((ContentType eq 'Operating Policy') or (ContentType eq 'Procedure')) and (Subject eq 'Safety')</pre>
<p>You see how we&#8217;re grabbing items with &#8220;ContentType&#8221; equaling to &#8220;Operating Policy&#8221; OR &#8220;Procedure&#8221; AND &#8220;Subject&#8221; equaling to &#8220;Safety&#8221;.</p>
<h3>6) Using &#8220;startswith()&#8221; and &#8220;substringof()&#8221; functions with $filter</h3>
<p>At times you need a more powerful filter in SharePoint REST API. See &#8220;eq&#8221; will only retrieve exact matches. If you want to get everything that starts with &#8220;test&#8221;, you use the &#8220;<strong>startswith()</strong>&#8221; function:</p>
<pre class="lang:default decode:true">/_api/web/lists/getbytitle('ListName')/Items?$filter=((startswith(column,'test')))</pre>
<p>Note that the &#8220;column&#8221; is the first parameter, then the value! This is a mistake that I&#8217;ve done several times because the <a href="https://social.technet.microsoft.com/wiki/contents/articles/35796.sharepoint-2013-using-rest-api-for-selecting-filtering-sorting-and-pagination-in-sharepoint-list.aspx#Filtering_items">documentation</a> is pretty weak.<br />
Now, if you want to get items that &#8220;contains&#8221; specific characters, you use the &#8220;<strong>substringof()</strong>&#8221; function.</p>
<pre class="lang:default decode:true">/_api/web/lists/getbytitle('ListName')/Items?$filter=((substringof('test',column)))</pre>
<p>Unlike startswith(), the substring() takes the &#8220;value&#8221; first, then the &#8220;column&#8221;. Again, note the difference between the two.</p>
<h3>7) Limiting your results</h3>
<p>The <strong>$top</strong> parameter basically limits your items to a specified number. The syntax is below:</p>
<pre class="">/_api/web/lists/getbytitle('listname')/Items?$select=Title&amp;$top=10</pre>
<p>This is also useful for creating paging systems &#8211; in combination with an offset option (below).</p>
<h3>8) Offsetting results (for paging)</h3>
<p>So you know how to limit your results, and you know how to get the total items. All you need is to offset your results. You do this with the &#8220;$skip&#8221; parameter.</p>
<pre class="">/_api/web/lists/getbytitle('listname')/Items?$top='10'&amp;$skip='20'
</pre>
<p>Again, note the use of single quotes. The above will get a set of 10 items, starting from the 20th in the list. Combined with the total, you can create your own paging mechanism.<br />
<strong>Update 8/10/2016:</strong> I just found out that the <a href="http://sharepoint.stackexchange.com/questions/126565/issue-with-skip-in-rest-api">$skip parameter doesn&#8217;t work</a> with list items. There is a property in the REST response that you can use &#8211; for paging. This is known as the &#8220;___next&#8221;. I will do another tutorial strictly on this subject &#8211; so stay tuned.</p>
<h3>9) Getting the Author Information</h3>
<p>You have to specify that using the &#8220;$expand&#8221; key. Also an additional parameter to the &#8220;$select&#8221; key is needed. For example, to grab the Id and the name of the author, simply append to your query:</p>
<pre class="">/_api/web/lists/getbytitle('listname')/Items?$select=Author/Title,Comment&amp;$expand=Author/Title</pre>
<p>The above will return the author information in it&#8217;s own node called &#8220;Author&#8221;.<br />
<img decoding="async" class="alignnone size-full wp-image-5455" src="https://michaelsoriano.com/wp-content/uploads/2016/01/rest-select-2.jpg" alt="rest-select-2" width="396" height="155" srcset="https://michaelsoriano.com/wp-content/uploads/2016/01/rest-select-2.jpg 396w, https://michaelsoriano.com/wp-content/uploads/2016/01/rest-select-2-300x117.jpg 300w" sizes="(max-width: 396px) 100vw, 396px" /></p>
<h3>10) Document Libraries</h3>
<p>SharePoint REST API supports querying document libraries. Remember, doc libs are also lists and for the most part, are handled through the same endpoint.</p>
<pre class="">/_api/web/lists/getbytitle('Document Library Name')/Items?$select=Title,FileLeafRef,EncodedAbsThumbnailUrl,EncodedAbsUrl</pre>
<p>The example above returns information about your file such as the name, full url and the internal &#8220;Title&#8221;:<br />
<img decoding="async" class="alignnone size-full wp-image-5417" src="https://michaelsoriano.com/wp-content/uploads/2015/12/rest-select2.gif" alt="rest-select2" width="531" height="160" /><br />
For instances where you want to know the &#8220;type&#8221; of document library it is (example Picture Library vs Document Library), use:</p>
<pre class="">/_api/web/lists/getbytitle('Document Library Name')/BaseTemplate</pre>
<p>Although some information regarding document libraries require an entirely new endpoint. This includes file paths, subfolders, thumbnails and such.</p>
<pre class="">/_api/web/GetFolderByServerRelativeUrl('"Folder Name"')/Files</pre>
<p>The above contains an entire new set of information regarding your library.</p>
<h3>11) Getting Current User information:</h3>
<p>At times you want to grab the current user&#8217;s information. Use the endpoint below:</p>
<pre class="">/_api/SP.UserProfiles.PeopleManager/GetMyProperties</pre>
<p>I&#8217;ve also used the more current endpoint below:</p>
<pre class="lang:js decode:true">/_api/web/currentUser</pre>
<p>Again, there may be additional information that is not returned by the above, such as user groups (below) which requires a different endpoint.</p>
<h3>12) Getting Current User Groups</h3>
<p>For some reason, this information is separate from getting the current user information described above. But in order to get the current user groups, you need to pass the ID:</p>
<pre class="lang:js decode:true">/_api/web/GetUserById('"+ userId +"')/Groups</pre>
<p>So you need to get the &#8220;userId&#8221; first, then do the above ajax call. Something like below:</p>
<pre class="lang:default decode:true">function getCurrentUser(){
   var ajax = $.ajax({
       url:   _spPageContextInfo.siteAbsoluteUrl + "/_api/web/currentUser",
       method: "GET",
       headers: { "Accept": "application/json; odata=verbose" },
       error: function (data) {
           console.log(data);
          }
        });
       return ajax;
}
function getUserGroups (userId) {
   var ajax = $.ajax  ({
        url:  _spPageContextInfo.siteAbsoluteUrl + "/_api/web/GetUserById('"   + userId + "')/Groups",
        method: "GET",
           headers: { "Accept": "application/json; odata=verbose" }
     });
    return ajax;
    }
getCurrentUser().done(function(userId){
   getUserGroups(userId.d.Id).done(function(groups){
       console.log(groups.d.results);
   });
});</pre>
<p>Above is an example of a &#8220;promise&#8221;. For more on that, read my <a href="https://michaelsoriano.com/working-with-jquerys-ajax-promises-and-deferred-objects/">Working with jQuery’s AJAX, Promises and Deferred objects.<br />
</a></p>
<h3>13) Retrieving&#8221;Choice Column&#8221; values</h3>
<p>There are times when you want to build an application that requires you to drill down to a choice column, and grab it&#8217;s values. A &#8220;choice column&#8221; in SharePoint is a type of column where you add values for users to choose from.<br />
<img decoding="async" class="alignnone size-full wp-image-6088" src="https://michaelsoriano.com/wp-content/uploads/2016/01/Capture.png" alt="Choice column" width="487" height="190" srcset="https://michaelsoriano.com/wp-content/uploads/2016/01/Capture.png 487w, https://michaelsoriano.com/wp-content/uploads/2016/01/Capture-300x117.png 300w" sizes="(max-width: 487px) 100vw, 487px" /><br />
You retrieve the values by doing an ajax call to the SharePoint REST API endpoint, specifying the column name you want. Below is an example:</p>
<pre class="lang:js decode:true">/_api/web/lists/GetByTitle('LISTNAME')/fields?$filter=EntityPropertyName eq 'Subjects'</pre>
<p>The above will query the choice column &#8220;Subjects&#8221; from the list &#8220;LISTNAME&#8221;.</p>
<h6>**The __metadata object</h6>
<p>You will notice that each result will have this <strong>__metadata</strong> object tied to it.<br />
<img decoding="async" class="alignnone size-full wp-image-5458" src="https://michaelsoriano.com/wp-content/uploads/2016/01/3rd-screenshot-rest.gif" alt="3rd-screenshot-rest" width="492" height="265" /><br />
This contains important material that will help you later in update and delete operations. I&#8217;ll cover that in the next chapter.</p>
<h2><span style="text-decoration: underline;">Bonus: SharePoint Search API</span></h2>
<p>If you have Search features turned on, you will be able to do powerful queries against any of your content inside your SharePoint farm. SharePoint search crawls through your material such as Word documents, Excel, PDF, Lists, Webpages &#8211; anything that you&#8217;ve configured to be searchable &#8211; you can query against in the <strong>SharePoint Search API</strong>.<br />
Your application will go up an extra level &#8211; simply by integrating this capability. Here are a few common Search API calls &#8211; for selecting / querying items:</p>
<h3>1) A Standard Search</h3>
<p>Doing a regular is as simple as passing your search term to the endpoint below:</p>
<pre class="lang:js decode:true">/_api/search/query?querytext='"+ TERM +"'</pre>
<p>The tricky part is parsing the results.<br />
<img decoding="async" class="alignnone wp-image-6090 size-full" style="padding: 20px; border: 1px solid #ebebeb;" src="https://michaelsoriano.com/wp-content/uploads/2016/01/Capture-1.png" alt="Search API result" width="537" height="640" srcset="https://michaelsoriano.com/wp-content/uploads/2016/01/Capture-1.png 537w, https://michaelsoriano.com/wp-content/uploads/2016/01/Capture-1-252x300.png 252w" sizes="(max-width: 537px) 100vw, 537px" /><br />
Are you ready for this? The results are buried under: <strong>data.d.query.PrimaryQueryResult.RelevantResults.Table.Rows.results</strong></p>
<div>The &#8220;results&#8221; property of &#8220;Rows&#8221; is an array of objects. This contains the data you want to display.</div>
<h3>2) Selecting specific Properties</h3>
<p>At times, you want the payload to remain small. The SharePoint Search API supports selecting only the properties you need. Below is a good way to achieve this:</p>
<pre class="lang:js decode:true">/_api/search/query?querytext='"+ TERM +"'&amp;selectproperties='Title,Path,FileExtension,IsContainer'</pre>
<p>Adding a &#8220;selectproperties&#8221; querystring along with a comma separated properties that we need will do the trick. Again, note the use of single-quotes.</p>
<h3>3) Offsetting Results (for paging)</h3>
<p>For instances where you want to return the set of rows that starts from a specific number:</p>
<pre class="lang:js decode:true">/_api/search/query?querytext='"+ TERM +"'&amp;startrow=10</pre>
<p>Adding the &#8220;startrow&#8221; querystring will do it. Note that SharePoint Search API has a complex algorithm of sorting and returning results. Therefore, the total and the actual values are approximates.</p>
<h3>4) Limiting Results</h3>
<p>You don&#8217;t want to return everything! You simply want to limit your search:</p>
<pre class="lang:js decode:true">/_api/search/query?querytext='"+ TERM +"'&amp;rowlimit=25</pre>
<p>The &#8220;rowlimit&#8221; querystring is your friend.</p>
<h3>5) Only Results from a Specific List or Document Library</h3>
<p>This one you will need the list Id. You can grab the list Id by going to your list / library, and clicking on &#8220;List Settings&#8221; or &#8220;Library Settings&#8221;. Once there, go to the URL and grab the value after &#8220;List=&#8221;. Note that this value is url encoded &#8211; with single quotes. So remove the leading &#8220;%7B&#8221;, and the trailing &#8220;%7D&#8221;. What you&#8217;re left with is the List Id.</p>
<pre class="lang:js decode:true">/_api/search/query?querytext='"+ TERM +"'&amp;sourceid='YOUR-LIST-ID'</pre>
<p>Remember to wrap your list id in single quotes. This query will only return items from the specific list that you&#8217;ve specified.</p>
<h3>6) Get People Results</h3>
<p>For this one, it&#8217;s exacly the same as above.</p>
<pre class="lang:js decode:true">/_api/search/query?querytext='"+ TERM +"'&amp;sourceid='b09a7990-05ea-4af9-81ef-edfab16c4e31'</pre>
<p>Simply replace the list id with this: &#8220;<strong>b09a7990-05ea-4af9-81ef-edfab16c4e31</strong>&#8220;. Yes it seems like it&#8217;s the same for everybody.</p>
<h3>7) Getting Best Bets</h3>
<p>&#8220;Best Bets&#8221; is SharePoint&#8217;s &#8220;elevated results&#8221;. These get pushed to the top of the result set, for specific queries. Note that these items are not included in the regular results &#8211; which means that it is not to be included in paging and filters and such.</p>
<pre class="lang:js decode:true">/_api/search/query?querytext='"+ TERM +"'&amp;processbestbets=true&amp;enablequeryrules=true</pre>
<p>The resultset you need to parse is in this property: <strong>data.d.query.SecondaryQueryResults.results[0].SpecialTermResults.Results.results</strong><br />
Haha! Ugly eh? Inside &#8220;results&#8221; is an array of objects you need. Note that the properties of each object may not be as complete as the primary results.</p>
<h3>8) Filtering Results</h3>
<p>Sometimes you don&#8217;t want the whole resultset to comeback. This is where filtering comes in. <strong>SharePoint Search API</strong> has &#8220;refinement filters&#8221; which does the job.</p>
<pre class="lang:default decode:true">/_api/search/query?querytext='TERM'&amp;refinementfilters='(FIELD:string("FILTERTERM", mode="phrase")'</pre>
<p>The above will search for &#8220;TERM&#8221;, filtered with the &#8220;FILTERTERM&#8221;  in the field called &#8220;FIELD&#8221;.</p>
<h3>9) Filtering Results in Multiple Fields</h3>
<p>So now we need to filter by many fields. Yes it&#8217;s possible, and we still use &#8220;refinement filters&#8221; in the Search API.</p>
<pre class="lang:default decode:true ">/_api/search/query?querytext='TERM'&amp;refinementfilters='and(COL1:string("COL1TERM", mode="phrase"),COL2:string("COL2TERM", mode="phrase"))'</pre>
<p>Just like the single filter, but instead we add &#8220;and&#8221; in the beginning (you can also use &#8220;or&#8221;), plus separating the columns and terms with a comma.</p>
<h3>10) Sorting Results</h3>
<p>At times, the sorting of SharePoint&#8217;s Search API is not what you&#8217;re looking for. Well we can sort it.</p>
<pre class="lang:default decode:true ">/_api/search/query?querytext='TERM'&amp;sortlist='LastName:ascending,FirstName:ascending'</pre>
<p>The example above shows the results being sorted by &#8220;LastName&#8221;, ascending first, then &#8220;FirstName&#8221; etc.</p>
<h3>Conclusion</h3>
<p>As I&#8217;ve mentioned, SharePoint&#8217;s REST AND SEARCH API has some very powerful features. And with OData&#8217;s standard&#8217;s, you can create quite advanced queries. I will try to keep this article updated with more <strong>Select</strong> related queries, but for now I have to go. Stay tuned for the next part.</p>
<p>The post <a href="https://michaelsoriano.com/understanding-sharepoint-rest-api-part-1-selecting-items/">Understanding SharePoint&#8217;s REST and Search API Part 1 &#8211; Selecting Items</a> appeared first on <a href="https://michaelsoriano.com">Michael Soriano</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://michaelsoriano.com/understanding-sharepoint-rest-api-part-1-selecting-items/feed/</wfw:commentRss>
			<slash:comments>35</slash:comments>
		
		
			</item>
	</channel>
</rss>
