Knockout JS: Conditional Switch Case - if-statement

My current task is to replace knockout js conditional if to switch case(or like multiple if case) to check more than two conditions. The scenario is if the user is authenticated then the toggle icon should be visible in green color and for un authenticated user the toggle icon should be in grey color. Below is the code for the scenario I stated here, IsAuthenticatedUser() is a bool value always have true or false. Now I have to change the bool(0 1) value to flag(0 1 2 3) value.
Bool representation is,
0 - Not Authenticated - grey icon
1 - Authenticated - green icon
Flag Value
0 - Not Authenticated - grey icon
1 - Authenticated - green icon
2 - Authenticated but expired - no icon
3 - Authenticated but not yet license period started - no icon
For bool value the Knockout JS conditional separation is like,
<!-- ko if: IsAuthenticatedUser() -->
<i class="fa fa-toggle-on faIcons green" title="Active"
data-bind="click: function (data, event) { $parent.functiongoeshere }"></i>
<!-- /ko -->
<!-- ko if: !IsNotAuthenticatedUser() -->
<i class="fa fa-toggle-on faIcons fa-rotate-180 toggleOff" title="Inactive"
data-bind="click: function (data, event) { $parent.functiongoeshere }"></i>
<!-- /ko -->
For Flag value, I have to do something like below,
<!-- ko if: UserFlag == 1 -->
<i class="fa fa-toggle-on faIcons green" title="Active"
data-bind="click: function (data, event) { $parent.functiongoeshere }"></i>
<!-- /ko -->
<!-- ko if: UserFlag == 0 -->
<i class="fa fa-toggle-on faIcons fa-rotate-180 toggleOff" title="Inactive"
data-bind="click: function (data, event) { $parent.functiongoeshere }"></i>
<!-- /ko -->
<!-- ko if: UserFlag == 2 -->
<!-- No ICON -->
<!-- /ko -->
<!-- ko if: UserFlag == 2 -->
<!-- No ICON -->
<!-- /ko -->
But this is not working, So is there another way to use if for multiple condition checking or how we can user switch control to handle this scenario.
Any suggestion would be helpful.

Instead of 4 <!-- ko if --> I would instead move the logic to the view model.
From my experience, it's always better to have as few logic as possible in the view.
Moving logic to view model allows you to unit-test your behavior, while it's difficult to test the view rendering. In addition, complex views tend to be far less readable than complex view model, because of verbose syntax which has to be used, such as <!-- ko if --> or complex data-bind.
I tried to make a simplified example matching your needs, in which the same template is displayed differently depending on the user's status. To do that, I make use of the css binding.
click on the page to change user's status.
var myVM = function() {
var _this = this;
_this.status = ko.observable(2);
_this.authenticationStyle = ko.computed(function() {
if (_this.status() == 0) return "anonymous";
if (_this.status() == 1) return "expired";
return "authenticated";
}, this);
_this.statusText = ko.computed(function() {
if (_this.status() == 0) return "please log in";
if (_this.status() == 1) return "please refresh";
return "welcome";
}, this);
};
var vm = new myVM();
ko.applyBindings(vm);
window.onclick = function() {
var newStatus = vm.status() + 1;
if (newStatus > 2)
newStatus = 0;
vm.status(newStatus);
};
.anonymous {
display: none;
}
.expired {
color: lightgrey;
background-color: yellow;
}
.authenticated {
color: black;
background-color: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<div data-bind="css: authenticationStyle">
<div data-bind="text: statusText"></div>
</div>

Your ko if: UserFlag should work, although I would change it to userFlag and you might need it to be ko if: userFlag()
Also, why not keep it simple and create a getAuthClass() function, and bind the element attributes and calculate all the icons in the viewModel?

Related

How can I scroll down to bottom of a specific div on page load in a chat conversation using Nuxt.js?

I want scroll down to the last div
<div v-for="(message, message_index) in messageArray" :key="message_index">
<div class="chatList">
</div>
</div>
I'm assuming you have a chat component where you want to scroll down to the last message on page load.
Although there are many ways to achieve this, I found this is the simplest one.
scrollIntoView() inside this.$nextTick(function () {}) gets the job done.
Bind your every div inside the loop with unique id. :id="`m-(some_unique_id)`">
<div v-for="(message, message_index) in messageArray" :key="message_index">
<div :id="`m-${message.id}`">
</div>
</div>
and get the element of the last index of messageArray. And tell the scrollIntoView to scroll down to that div.
script
<script>
mounted: {
this.getChatBoxUsersChats();
},
methods: {
getChatBoxUsersChats() {
this.$nextTick(function () {
let length = this.messageArray.length;
if (length > 0) {
let id = this.messageArray0[length - 1].id;
let element = document.getElementById("m-" + id);
element.scrollIntoView({ behavior: "smooth", block: "end" });
});
},
},
}
</script>

How to re-direct to a print template using Knockout js

I'm using templates in my view and I'd like to direct the user to a print template. Common usage:
<div data-bind="template: { name: 'print' }"></div>
but I want this script to appear alone and not with other content.
Is it possible to go to my print script instead of pulling the script into a div, which is what the code above does. Thank you.
You could put a boolean around the "normal" content that hides everything else whenever the print template is active.
<div data-bind="visible: noprint()">main site</div>
Redirect to a different file that holds the print layout with its own styling.
Create your page as such that the print-css actually renders the page as expected. Make sure the print styles are always at the bottom of your css
#media print {
body {
color: #000;
background-color: #fff;
}
}
A bit more advanced is working with components, you could use the same data for displaying everything you need but when the user expects a printable view just switch out the screenlayout-component to the printlayout-component
screen
print
<div data-bind="component: layoutType"></div>
Here's what I ended up doing...
var viewModel = {
selectedTemplate: ko.observable('ViewContent'),
subTemplate: function (item) {
this.selectedTemplate(item);
},
goBack: function () {
this.selectedTemplate('ViewContent');
},
printLandscape: function () {
this.selectedTemplate('PrintContent');
alert("Please change page orientation to Landscape");
javascript: window.print();
},
}
ko.applyBindings(viewModel);
.print {
margin: 0px;
padding: 0px;
width: 900px; /* or width: 9.5in; */
height: 670px; /* height: 7in; */
clear: both;
page-break-after: always;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<script id="getContent" type="text/html">
<!-- ko if: ($root.selectedTemplate() == "ViewContent") -->
<div data-bind="template: { name: 'viewContent' }"></div>
<!-- /ko -->
<!-- ko if: ($root.selectedTemplate() == "PrintContent") -->
<div data-bind="template: { name: 'printContent' }"></div>
<!-- /ko -->
</script>
<script id="viewContent" type="text/html">
<div>Here's the view or display content</div>
Print
</script>
<script id="printContent" type="text/html">
<div>Print | Back</div>
<div class="print">Here's the print content</div>
</script>
<div data-bind="template: { name: 'getContent' }"></div>

Spreadjs references from iframe

We use an iframe in the parent page, that is dynamically replaced with other pages.
Spread is loaded in the parent. Is there some type of plugin that will allow me to access the spread core that is loaded in the parent from the iframe pages without including spread(language="JavaScript" src="http://cdn.wijmo.com/spreadjs/gcspread.sheets.all.8.40.20151.0.min.js") in the multiple child (iframe) pages? Jquery is loaded fine.
Home page iframe with references
<iframe name="mainWindow" src="includes/View.asp frameborder="0" />
<link href="http://cdn.wijmo.com/spreadjs/gcspread.sheets.8.40.20151.0.css" rel="stylesheet" type="text/css" />
<script src="http://code.jquery.com/jquery-1.8.2.min.js" type="text/javascript"></script>
<script type="text/javascript" src="http://cdn.wijmo.com/spreadjs/gcspread.sheets.all.8.40.20151.0.min.js"></script>
We just replace the iframe source at run time.
I use following code but spread is not initialized any suggestions ?
<script type="text/javascript">
var parentWindow = window.parent;// This refers to parent's window object
if (parentWindow && parentWindow.jQuery) { // Check to see if parentWindow and parentWindow.jQuery is truly
window.jQuery = parentWindow.jQuery;
window.$ = parentWindow.jQuery;
}
else {
var jScript = document.createElement('script');
jScript.setAttribute("type", "text/javascript");
jScript.setAttribute("src", "http://code.jquery.com/jquery-1.8.2.min.js"); // load jQuery here
}
if (parentWindow && parentWindow.wijmo && parentWindow.GcSpread) { // Check to see if parentWindow and parentWindow.wijmo and parentWindow.GcSpread is truly
window.GcSpread = parentWindow.GcSpread;
window.wijmo = parentWindow.wijmo;
}
else {
var jScript = document.createElement('script');
jScript.setAttribute("type", "text/javascript");
jScript.setAttribute("src", "http://cdn.wijmo.com/spreadjs/gcspread.sheets.all.8.40.20151.0.min.js"); // load gcspread here
}
$(document).ready(function () {
var test = window;
alert("JQuery loaded");
var spread = new GcSpread.Sheets.Spread(document.getElementById("ss"));
var spreadNS = GcSpread.Sheets;
spread.setSheetCount(3);
spread.bind(spreadNS.Events.ActiveSheetChanged, function (e, args) {
$("#activeSheetIndex").val(spread.getActiveSheetIndex());
});
$("#btnAddSheet").click(function () {
spread.addSheet(spread.getSheetCount());
});
$("#btnRemoveSheet").click(function () {
var activeIndex = spread.getActiveSheetIndex();
if (activeIndex >= 0) {
spread.removeSheet(activeIndex);
}
});
$("#btnClearSheets").click(function () {
spread.clearSheets();
});
$("#btnSetActiveSheetIndex").click(function () {
var index = $("#activeSheetIndex").val();
if (!isNaN(index)) {
index = parseInt(index);
if (0 <= index && index < spread.getSheetCount()) {
spread.setActiveSheetIndex(index);
}
}
});
});
</script>
<div class="sample-turtorial">
<div id="ss" style="width:100%; height:580px;border: 1px solid gray;"></div>
<div class="demo-options">
<div class="option-row">
<input type="button" style="width: 100px" value="Add Sheet" id="btnAddSheet" />
<input type="button" style="width: 100px" value="Remove Sheet" id="btnRemoveSheet" />
<input type="button" style="width: 100px" value="Clear Sheets" id="btnClearSheets" />
</div>
<div class="option-row">
<label>ActiveSheetIndex:</label>
<input type="text" id="activeSheetIndex" value="0" />
<input type="button" id="btnSetActiveSheetIndex" value="Set" />
</div>
</div>
</div>
I don't think what you're attempting work, how would the code execute without having a reference to the library (SpreadJS).
Can you please explain what your use case might be, may be we can help you find a different way of accomplishing what you need.

Facebook Like Button gets cropped at the bottom

I am trying to align the Facebook like button along with the G+1 and Tweet's one, but I can't figure out what is wrong. The facebook button gets cropped at the bottom.
You can see my issue at the top of the website Mobilise IT
Here's my code
<div id="fb-root"></div>
<script type="text/javascript">
(function () {
var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
})();
</script>
<script> (function (d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = "//connect.facebook.net/en_US/all.js#xfbml=1&appId=438999086139815";
fjs.parentNode.insertBefore(js, fjs);
} (document, 'script', 'facebook-jssdk'));
</script>
<div id="social">
<!-- +1 -->
<div class="plusone">
<!-- Place this tag where you want the +1 button to render -->
<g:plusone size="medium" annotation="none"></g:plusone>
<!-- Place this render call where appropriate -->
</div>
<!-- end +1 -->
<!-- twitter -->
<div class="twitter">
Tweet<script type="text/javascript" src="//platform.twitter.com/widgets.js"></script>
</div>
<!-- end twitter -->
<!-- like -->
<div style="vertical-align: top;padding-top:2px;width:46px;overflow:hidden;" class="fb-like" data-href="http://www.facebook.com/pages/Mobilise-IT/166950133340282" data-send="false" data-layout="button_count" data-width="100" data-show-faces="true" data-font="segoe ui"></div>
<!-- end like -->
</div>
And this is the CSS
.social-icon
{
background-image:url(images/social-icons.png);
margin-left:-2px;
padding-left:25px;
background-repeat:no-repeat;
}
.twitter
{
background-position:left 2px;
}
.facebook
{
background-position:left -14px;
margin-right:5px;
}
.linkedin
{
background-position:left -29px;
}
Any ideas on how to fix this?
Thanks in advance
PS: I can't upload an image yet, need more rep , when i can i will so you can have a better view of my issue.
You could align the facebook button by using: in your CSS
.fb-like{ padding: 0 0 4px 0 !important; }

jQueryUI Slider is not scrolling div

I am new to jquery, so apologies if this is a lengthy question. The following is what I have come up with for a horizontal slider to scroll a div containing lists of images.
The result is the slider not scrolling the div. Any help would be great.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
var slideDrag,
slideWidth = 330,
slideSpeed = 200;
animated = false;
$(".scroll-slider").slider({
animate: slideSpeed,
start: checkType,
slide: doSlide,
max: slideWidth
});
// Set each slider to a value
$(".scroll-slider").each(function(index){
$(this).slider("value", 330 / 5 * index);
});
// You can also change a slider at any time like so:
// $(".scroll-slider:eq(0)").slider("value", value);
//
// That would move the first slider to a value, along with its content
function checkType(e){
slideDrag = $(e.originalEvent.target).hasClass("ui-slider-handle");
}
function doSlide(e, ui){
var target = $(e.target).prev(".scroll-content"),
// If sliders were above the content instead of below, we'd use:
// target = $(e.target).next(".scroll-content")
maxScroll = target.attr("scrollWidth") - target.width();
// Need to check type now to prevent the new change handler from firing twice when user clicks on slider,
// because both 'slide' and 'change' events are fired on a click, but only a 'change' when setting slider
// value manually via code.
if (e.type == 'slide'){
// Was it a click or drag?
if (slideDrag === true){
// User dragged slider head, match position
target.attr({scrollLeft: ui.value * (maxScroll / slideWidth) });
}
else{
// User clicked on slider itself, animate to position
target.stop().animate({scrollLeft: ui.value * (maxScroll / slideWidth) }, slideSpeed);
}
animated = true;
}
else{
if (animated === false){
target.stop().animate({scrollLeft: ui.value * (maxScroll / slideWidth) }, slideSpeed);
}
animated = false;
}
}
});
</script>
</script>
<style>
/* Styling the scroll elements */
.scroll-container{padding-bottom:30px}
.scroll-content{width:330px;height:110px;overflow:hidden;margin-bottom:10px}
.scroll-content ul{
width:880px;
height:110px;
margin-bottom:5px
}
.scroll-content li{
float:left;
}
.ui-slider .ui-slider-handle{width:16px;height:12px;position:absolute;top:-3px;background:#234786;border:none}
</style>
<body>
<div id="wrapper">
<h2>Multiple Slider Control Demo</h2>
<div id="left">
<div class="scroll-container">
<div class="scroll-content">
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
</ul>
</div>
</div>
<div class="scroll-slider"></div>
</div>
</div>
Are you trying to work from this demo?
http://cnanney.com/journal/demo/div-slide/
I had the same error, and replaced the version of jQuery I was using with the one used in the demo and it worked.