Using knockoutjs to data-bind list data into bxslider - sharepoint

I have managed to get the code to display list data which is driven from a sharepoint list. The list only contains one column in each row item which is called Title. I need to display the titles through the bxslider, one item per slide.
Usual bxslider html
<ul class="bxslider">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
My html implementing data-bind
<ul class="bxslider" data-bind="foreach: items">
<li data-bind="text: Title"></li>
</ul>
For some reason the 'Titles' are all being generated in one li tag, rather than creating an li tag for each item in the list.
If anyone has come across this problem before or have any advice or suggestions it would be very much appreciated.
View Model
var items = ko.observable();
jQuery(document).ready(function () {
jQuery.getJSON( "ListURLHERE", {}, dataCallBack
);
ko.applyBindings();
});
function dataCallBack(data) {
items(data.d.results);
}

I have found the answer to the problem!
I was initiating the bxslider function before the knockout js code. I had to implement the bxslider function into the dataCallBack function and it worked.
function dataCallBack(data) {
News(data.d.results);
jQuery(document).ready(function(){
jQuery('.bxslider').bxSlider();
});
}
Thanks for your help everyone!

Related

Jsviews filter search

How do I create a filter search in JSViews? Usually I'd grab the html element by its class with the .getElementsByClassName() and .value() methods and add a === comparison to satisfy the right criteria. How can I do something similar in JsViews
I've already tried to add listItem in the IF to match the value of the html input (search bar), but I don't know how to grab the value of the search element (JQuery would be easy using $(".search")), or compare it to the listItems using regExp.
{^{if list && list.length}}
<ul autoselectitem="true" tabindex="-1" operationalindex="1" allindex="1">
{^{for list}}
{{include tmpl="listItem" /}}
{{/for}}
</ul>
{{else}}
<p>Nothing Found</p>
{{/if}}
This currently displays all items in the list, however I only want the elements in the list to be displayed that match with RegEx the .value of an search HTML element:
<input type="text" class="search" data-link="search" placeholder="Search...">
So for example, if I type in "e" into the search bar, all the items in the list that don't have the letter "e" should disappear.
The code linked all work, but what i've tried has given me null pointer errors because I'm not grabing the input element correctly by its class or data-link. How could I do this in the simplest way possible? Thanks
Here is one way of doing it:
<script id="myTmpl" type="text/x-jsrender">
<input type="text" class="search" data-link="search" placeholder="Search...">
{^{if list && list.length}}
<ul autoselectitem="true" tabindex="-1" operationalindex="1" allindex="1">
{^{for list filter=~flt depends="search"}}
<li data-link="#data"></li>
{{/for}}
</ul>
{{/if}}
</script>
<div id="page"></div>
<script>
var myTmpl = $.templates("#myTmpl"),
data = {
list: ["a", "b"],
search: ""
},
helpers = {
flt: function(item, index, items) {
return item.indexOf(data.search) > -1;
}};
myTmpl.link("#page", data, helpers);
</script>

If element hasClass, add another class to its title value

I'm using slick carousel, and once a div is active I want to open the corresponding description.
Problem I'm having is with this code:
if ($('div').hasClass('active')) {
var title = $(this).attr('title');
$('ul li').removeClass('open');
$(title).addClass('open');
}
What I'm trying to achieve:
Once a div gets class 'active', I want to take its title value, and use it as a id link to list element I want to display(add class to).
Here is a FIDDLE.
Use event handling, not class monitoring.
The slick carousel API has events for this, I believe you want to use the afterChange event to act on the active element after it has been made visible.
Check out the docs and examples, especially the section titled "Events" on Slick page: http://kenwheeler.github.io/slick/
And I think you don't want to use title attribute for this because that is for tooltips. I recommend data-* attributes instead. And element IDs should generally start with a letter and not a number (was required in HTML4 and makes life easier when mapping IDs to JavaScript variables; though if you are using HTML5 I think this requirement is no longer in effect).
HTML
<div id="carousel">
<div data-content-id="content1">
Selector 1 </div>
<div data-content-id="content2">
Selector 2 </div>
<div data-content-id="content3">
Selector 3 </div>
</div>
<ul class="content">
<li id="content1">Content 1</li>
<li id="content2">Content 2</li>
<li id="content3">Content 3</li>
</ul>
JavaScript
$('#carousel').on('afterChange', function(event, slick, currentSlide) {
// get the associated content id
var contentId = $(slick.$slides.get(currentSlide)).data("content-id");
if(contentId && contentId.length)
{
var $content = $("#" + contentId);
$(".content>li").removeClass("open"); // hide other content
$content.addClass("open"); // show target content, or whatever...
}
});
I have found a solution:
$('.slider').on('afterChange', function(event, slick, currentSlide, nextSlide){
var contentId= $(slick.$slides.get(currentSlide)).data('content');
if(contentId)
{
$(".content li").removeClass('open');
$('#' + contentId).addClass('open');
}
});
Working fiddle

$scope.$apply and ng-include

I'm using a $scope.$apply to trigger the view to update based on a changed variable in the scope. However, I have another line in the html that is an ng-include,
<div data-ng-include data-ng-src="'views/partials/_menubar.html'"></div>
error message
When I remove the ng-include and replace it with a static call there is no error. Here is the template that I'm including as well:
<div class="menu" ng-controller="MenuController">
<div style="display: inline-block">
Hello!
</div>
<ul class="menu_dropdown">
<li class="menu_item">Test1</li>
<li class="menu_item">Test2</li>
<li class="menu_item">Test3</li>
</ul>
</div>
The code for menu controller is
app.controller('MenuController', function($scope) {
});
ng-src is used to allow elements that usually have a src (like anchors or images) to apply the src tag only after angular's digest, not for inclusion of templates in ng-include. See ng-include docs and ng-src docs.
A safe way to specify the src using ng-include would be like this:
<div data-ng-include="src='views/partials/_menubar.html'"></div>
or
<div data-ng-include="'views/partials/_menubar.html'"></div>
If you must have the src separately, it's data-src and not data-ng-src:
<div data-ng-include data-src="'views/partials/_menubar.html'"></div>
see plnkr.
edit: To address your error message.. you'll see that message if you've bound a function to the scope which changes every time it is called.
For example, this will cause such an error:
// controller
$scope.getQuote = function(){
return 'someViewName' + Math.ceil(Math.random() * 10) + '.html';
};
// view
<div data-ng-include="{{getQuote}}"></div>
The problem with ng-include was actually a red herring. The real problem was trying to change the window.history, as seen in the thread here. My guess is because the ng-include directive references $location when it attempts to get resources.

How to check type of object in Handlebars?

I am currently working on a search bar that lists three types of objects: users, records and locations. Each has its own model and such defined, with corresponding controllers. What I need to do is to check which type of object it is because I need the HTML that renders with it to be different.
{{#each mainUserSearchResults}}
{{#link-to 'user' this.userID}}
<div class="row mainListSeperator" {{action "getapplicantUserID" this target="view"}}>
<img class="applicantsIcon" src="">
<div class="applicantsName">
{{unbound this.firstName}} {{unbound this.lastName}}
</div>
<div class="applicantsTitle">
User
</div>
</div>
{{/link-to}}
{{/each}}
The only issue I am having is that I need it to print this.firstName & this.lastName if it is a user, but I cannot do that for records. For records, I would have to render another property - this.recordID - in the same manner as I did this.firstName. The way to do this would be an if conditional, but I cannot find anything in HandleBars that allows me to check whether the data coming in from mainUserSearchResults is a user or a record.
The mainUserSearchResults is a property in my controller that returns an array of objects: currently it return a concatenated array of user objects and record objects.
Handlebars is a logicless template, so you really can't perform computations, like type-checking. There are some pretty good reasons for this. If it were me, I'd push that responsibility elsewhere, probably all the way to your model, for two reasons:
Any conditionals you put in the DOM are SLOW. The problem only gets compounded when you're on slow devices (most notably, mobile).
Every time you add a new searchable thing, you're going to have to update your templates. Over time, you'll end up with:
{{#if ...}}
...
{{/if}}
{{#if ...}}
...
{{/if}}
{{#if ...}}
...
{{/if}}
{{#if ...}}
...
{{/if}}
Delegate instead. For example, in your User model, add
formattedName: (function() {
return [this.get('firstName'), this.get('lastName')].join(' ');
}).property('firstName', 'lastName')
Do the same for your records and locations.
Then, change your template from
{{unbound this.firstName}} {{unbound this.lastName}}
to
{{unbound this.formattedName}}
Now, if you add new types to your searches, you have a completely generic solution that only needs the model to implement the formattedName property.
Some would would say my suggestion is a bad one, because it mixes the business-logic responsibility of a model with display logic. In this case, I'm guessing you're displaying {{firstName}} {{lastName}} in more than one place, so I think the benefits of keeping your code DRY outweigh moving this to, e.g., a controller. Your call.
Assuming there is some way to easily distinguish between the 2+ types of objects, you can use an if statement and render a different template (or even use a different partial, http://emberjs.com/guides/templates/rendering-with-helpers/)
<script type="text/x-handlebars" data-template-name="index">
<ul>
{{#each item in model}}
<li>
{{#if item.foo}}
{{render 'foo' item}}
{{/if}}
{{#if item.cow}}
{{render 'cow' item}}
{{/if}}
</li>
{{/each}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="foo">
I'm a foo: {{foo}}
</script>
<script type="text/x-handlebars" data-template-name="cow">
I'm a cow: {{cow}}
</script>
http://emberjs.jsbin.com/qinilege/1/edit
Or if you need more advanced checking you can use an item controller and add the logic in there
{{#each item in model itemController='checker'}}
<li>
{{#if item.isFooBar}}
{{render 'foo' item.model}}
{{/if}}
{{#if item.isFooBaz}}
{{render 'fooz' item.model}}
{{/if}}
{{#if item.isCow}}
{{render 'cow' item.model}}
{{/if}}
</li>
{{/each}}
App.CheckerController = Em.ObjectController.extend({
isFooBar: Ember.computed.equal('foo', 'bar'),
isCow: Ember.computed.notEmpty('cow'),
isFooBaz: Ember.computed.equal('foo', 'baz')
});
http://emberjs.jsbin.com/qinilege/2/edit

link dont scroll to top of page issue

i need some help, please... I got a affixed menu on my page, and i want to when i click on any item of it, the page scrolls back to the top, i would use an anchor, but i already use it to call the pages on each button...
this is my code
<div class="span1 menu">
<ul class="nav">
<li id='gostou' class='menufixo' title="gostou do filme?"></li>
<li id='evolucao' class='menuacao' title="evolução"></li>
<li id='comentarios' class='menuacao' title="comentários"></li>
<li id='info' class='menuacao' title="informações"></li>
<li id='assistir' class='menuacao' title="cinemas"></li>
<li id='tags' class='menuacao' title="cloud tags"></li>
<div class='ferramentas'></div>
<script>
$(".menu ul").on("click", "li", function()
{
$(this).parent().find("li").removeClass("menufixo").addClass("menuacao");
$(this).toggleClass("menufixo").toggleClass("menuacao");
});
</script>
</ul>
</div>
Thanks in advance!!
from what I've understood based on your "short" requirements.
http://jsfiddle.net/Madthew/NRMhf/
This code is the code used to go to the top of the page (using jQuery):
$('html, body').animate({scrollTop:0}, 'slow');
If you add:
return false;
then your href stop working.
Take a look here regarding how to setup the duration:
http://api.jquery.com/animate/
Instead of using 'fast' and 'slow' you can enter directly the value in millisecond.
The default duration is 400 milliseconds. 'fast' = 200 and 'slow'= 600.
Lower values means faster execution.
In order to let you see that it's working, I just added a div with a fixed height and a black background. When you click to any of the item you scroll to the top.

Resources