which element contains #id idString return index - javascript

Multiple elements with "column" class.
Find which column element contains a id: idString, return index of the !column! that contains the id
This is the new (3rd) html I am searching:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Style-Type" content="text/css">
<meta name="generator" content="Amazon.com">
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css" class="dontsplit"> .column *{ padding: 20px; }
</style>
</head>
<body class="calibre" style="margin: 0px; padding: 0px; width: 101024px;">
<div class="calibre67">
<div class="last first column" style="width: 616px; float: left;">
<p class="calibre2" style="padding-top: 8px; padding-bottom: 8px;">
<span class="calibre3">bla , bla etc.</span>
</p>
</div>
<div class="column" style="width: 616px; float: left;">
<div class="calibre1 split">
<p class="calibre2" style="padding-top: 8px; padding-bottom: 8px;">
<span class="calibre3">bla bla etc.</span>
</p>
</div>
</div>
<!-- div contains the ID I want to find, structure of page varies with different files -->
<div class="column" style="width: 616px; float: left;">
<div class="calibre1 split">
</p>
<p class="calibre4" style="padding-top: 8px; padding-bottom: 8px;">
<!-- This is the id I want to find, so the function should return 2 (3rd column). -->
<span id="1P-09761e033cf14df8aeccf069ebe7886e" class="calibre6">Prologue:</span>
</p>
<p class="calibre5" style="padding-top: 8px; padding-bottom: 8px;">
<span class="calibre6">It had been bla, bla etc.</span>
</p>
</div>
</div>
</div>
</body>
</html>
My Code:
var idString = "O-09761e033cf14df8aeccf069ebe7886e";
function findID(idString) {
$(".column").each(function(index, element){
if ($(this).find('*').attr('id') == idString) {
console.log(index);
return index;
}
});
return;
}
var result = findID(idString);
// should return/log 2
// currently returns/logs nothing
Function should return 2 in this example.
I have tried very many combinations of your suggestions.
What am I doing wrong?

if ($idString) will always return true. Instead of that check, you'll want to check against the .attr() of each element with if ($(this).attr('id') == idString).
Note that the attribute doesn't actually contain the #, so you'll want to remove the # from the ID variable, or make use of .contains().
This can be seen in the following:
var idString = "O-09761e033cf14df8aeccf069ebe7886e";
function findID(idString) {
$(".column").each(function(index, element) {
if ($(this).attr('id') == idString) {
console.log(index);
return index;
}
});
return;
}
findID(idString);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p class="column">“When the grav emitters are charged"</p>
<p class="column">“It wasn’t that bad this time”</p>
<p class="column" id="O-09761e033cf14df8aeccf069ebe7886e">Chapter 1</p>
<p class="column">“I can monitor engineering from up here”</p>
Also note that the index is zero-based.

You could use the jQuery .index(selector) method. It will return the index of the matched element (on the left hand side) within the collection of the selector on the right hand side.
A selector representing a jQuery collection in which to look for an element.
var idString = "#O-09761e033cf14df8aeccf069ebe7886e";
function findID(idToSearch) {
return $(idToSearch).index(".column p");
}
var result = findID(idString);
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="column">
<p>“When the grav emitters are charged"</p>
</div>
<div class="column">
<p>“When the grav emitters are charged"</p>
</div>
<div class="column">
<p id="O-09761e033cf14df8aeccf069ebe7886e">Chapter 1</p>
<p>“I can monitor engineering from up here”</p>
</div>
<div class="column">
<p>“When the grav emitters are charged"</p>
</div>

Related

replace a div hidden intially by a click on a link from 3 other 3 linkes(3 other divs)

Hi I want to replace a div that is already displayed with another Hidden div choosed when i click on one of them(3 other divs(hidden) initially). the 4 links related to the 4 divs and in same way i can do that in each link clicked. below is the code:
<script type="text/javascript">
#4 Id of divs
var models = document.getElementById('models')
var geometry = document.getElementById('geometry')
var assembly = document.getElementById('assembly')
var loads = document.getElementById('loads')
#4 ID OF links (related to each div)
var models1 = document.getElementById('models1')
var geometryy = document.getElementById('geometryy')
var assemblyy = document.getElementById('assemblyy')
var loads1 = document.getElementById('loads1')
geometryy.addEventListener("click", function () {
models.style.display = "none"
loads.style.display = "none"
assembly.style.display = "none"
geometry.style.display = "block"
})
assemblyy.addEventListener("click", function () {
geometry.style.display = "none"
models.style.display = "none"
loads.style.display = "none"
assembly.style.display = "block"
})
loads1.addEventListener("click", function () {
geometry.style.display = "none"
models.style.display = "none"
assembly.style.display = "none"
loads.style.display = "block"
})
models1.addEventListener("click", function () {
models.style.display = "block"
geometry.style.display = "none"
assembly.style.display = "none"
loads.style.display = "none"
})
</script>
CSS:
<style>
#loads {
display: none;
}
#geometry {
display: none;
}
#assembly {
display: none;
}
#models {
display: block;
}
</style>
some Html code about the 4 divs:
<form action="{% url 'results' %}" method="post" id="gallery" novalidate onsubmit="return mySubmitFunction(event)">
<div style="padding-top: 10px; margin-left:138px;" class="parallax-window tm-section tm-section-gallery tm-flex background " id="models" >
<div style=" background-color: white; font-size:89%; width: 62rem; height: 32rem; margin-left:2.5rem; ">
<div class="card-warning" style="background-color: #C0C0C0;">
<nav class="navbar">
<a class="floated" style="font-weight: bolder; border-style: solid;" id="models1">Models</a>
Geometry
Assembly
Loads
</nav>
</div>
.......... some fields related to the div id="models"
</div>
</div>
----------------About the second div
<div style="padding-top: 10px;" class="parallax-window tm-section tm-section-gallery tm-flex" id="geometry" >
<div style=" background-color: white; font-size:89%; width: 62rem; height: 32rem; margin-left:2.5rem; ">
<div class="card-warning" style="background-color: #C0C0C0;">
<nav class="navbar">
Models
<a class="floated" style=" font-weight: bolder; border-style: solid;">Geometry</a>
Assembly
Loads
</nav>
</div>
<div style="display: flex;">
<div>
<img style="height: 372px; width:270px; margin-left: 25px;">
</div>
<div style="line-height: 0.001; margin-left: 10px; margin-top: 12px;">
------ some code for some fields
</div>
</div>
...... </div>
---- </div>
----------------About the third div
<div style="padding-top: 10px;" class="parallax-window tm-section tm-section-gallery tm-flex" id="assembly" >
<div style="background-color: white; font-size:89%; width: 62rem; height: 32rem; margin-left:2.5rem; ">
<div class="card-warning" style="background-color: #C0C0C0;">
<nav class="navbar">
Models
Geometry
<a class="floated" style=" font-weight: bolder; border-style: solid;">Assembly</a>
<a href="#loads" class="floated" style=" font-weight: bolder;" id="loads3" >Loads</a>
</nav>
</div>
<div style="display: flex;">
<div>
<img style="height: 372px; width:270px; margin-left: 25px;">
</div>
<div style="line-height: 0.001; margin-left: 10px; margin-top: 12px;">
------ some code for some fields
</div>
</div>
...... </div>
---- </div>
----------------About the fourth div
<div style="padding-top: 10px; " class="parallax-window tm-section tm-section-gallery tm-flex" id="loads" >
<div style="background-color: white; font-size:89%; width: 62rem; height: 32rem; margin-left:2.5rem;">
<div class="card-warning" style="background-color: #C0C0C0;">
<nav class="navbar">
<a href="#models" class="floated" style="font-weight: bolder;" >Models</a>
Geometry
Assembly
<a style=" font-weight: bolder; border-style: solid;">Loads</a>
</nav>
</div>
<div style="display: flex;">
<div>
<img style="height: 372px; width:270px; margin-left: 25px;">
</div>
<div style="line-height: 0.001; margin-left: 10px; margin-top: 12px;">
------ some code for some fields
</div>
</div>
...... </div>
---- </div>
</form>
what i want :at first the "models" div is shown and the other 3 divs("geometry",assembly","loads") are hidden , so i want when i click on "geometry" div , the first div "models" become hidden and the other divs ("assembly" and "loads" still hidden) and so on if click on assembly... i i want to apply that on every div(because evry div has the 4 links)
But it doesn't give me any result!
<html>
<head>
<style>
#div2, #div3, #div4{
display: none;
}
</style>
</head>
<body>
<div style="background-color: #C0C0C0 ;padding-top: 10px;width: 62rem; height: 32rem; ">
<div>
<a href="#models" class="geo wy" style="border-style: solid;" >Models</a>
Geometry
Assembly
Loads
</div>
<div id="div1" class="wy hid">
Models and other stuffs here
</div>
<div id="div2" class="pk hid">
Geometry and other stuffs here
</div>
<div id="div3" class="fk hid">
Assembly and other stuffs here
</div>
<div id="div4" class="gk hid">
Loads and other stuffs here
</div>
</div>
<script>
window.onload = btn() ;
function btn() {
var query = document.querySelectorAll(".geo") ; //No of hrefs
var pts = document.querySelectorAll(".hid"); //No of divs
for(var i=0;i<query.length;i++){
query[i].addEventListener("click", function() { //know which href is being clicked currently
var cla = this.getAttribute('class').split(' ')[1] ; //get second class of current href which would be wy, pk, fk, gk respectively.
var point = document.querySelectorAll("."+cla)[1]; //selecting the div as, [0] would select the href
for(var j=0;j<pts.length;j++){
pts[j].style.display = "none"; //hid all the div
query[j].style.border= "none"; //remove all the href border
}
this.style.border= "solid"; //Add currently clicked href border
point.style.display = "block"; //display currently clicked div
})
}
}
</script>
</body>
</html>
Sorry the id and classes name are given random i am not good at naming. Please don't hesitate to ask if you are confused

How to make it so that previous answer is displayed when number is clicked after equals in js calculator?

I need to make it so that the previous result is displayed when the user presses a num after pressing equals... how do I do it? And just fyi I am just helping my friend make the code for his calculator clean - his was very messy - if you want I can show you his code as well.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div class='container'>
<div class='answer'>
<p class='returnAnswer'>Answer Will Come Here</p>
</div>
<div class='buttonDiv'>
<div class='button'>0</div>
<div class='button'>1</div>
<div class='button'>2</div>
<div class='button'>3</div>
<div class='button'>4</div>
<div class='button'>5</div>
<div class='button'>6</div>
<div class='button'>7</div>
<div class='button'>8</div>
<div class='button'>9</div>
<div class='equals'>=</div>
<div class='button'>c</div>
<div class='button'>+</div>
<div class='button'>-</div>
<div class='button'>x</div>
<div class='button'>÷</div>
<div class='button'>.</div>
<div class='button'>%</div>
</div>
</div>
</body>
</html>
<script type="application/javascript" src="/share.js"></script>
<script>
var eq = "";
var ans = eval(eq);
$('.button').click(function() {
eq += $(this).text();
$('.returnAnswer').text(eq);
});
$('.equals').click(function() {
$('.returnAnswer').text(ans);
});
</script>
This was a fun thing to do.... Here is what I have done to your code
Added some styles to the button (not important, but makes it easier to click)
Added a class named num to each number button, that will be used to reset the display if any button is clicked following '=' button.
Removed 'equals' class from '=' button and added it as an ID
Added code to clear the display when 'C' is clicked
Changed buttons 'x' to ' * ' and '÷' to '/' as otherwise eval function will not work
Changed back to 'x' and '÷', and added 2 lines inside equals.clicked to replace these with correct operators
Check the Code snippet
var eq = "";
var ans = eval(eq);
var equalsCliked = false;
$('.button').not("#equals, #cbutton").click(function () {
if ($(this).hasClass('num') && equalsCliked)
eq = "";
eq += $(this).text();
$('.returnAnswer').text(eq);
equalsCliked = false;
});
$('#equals').click(function () {
equalsCliked = true;
eq = eq.split("÷").join("/");
eq = eq.split("x").join("*");
ans = eval(eq);
eq = ans;
$('.returnAnswer').text(ans);
});
$('#cbutton').click(function () {
equalsCliked = false;
eq = "";
ans = eval(eq);
//eq = ans;
$('.returnAnswer').text("");
});
.button {
border: 1px solid gray;
padding: 8px;
margin: 3px 3px;
float: left;
cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div class='container'>
<div class='answer'>
<p class='returnAnswer' style="width:330px; padding: 10px; min-height:20px; border: 1px solid gray; border-radius: 2px;">Answer Will Come Here</p>
</div>
<div class='buttonDiv' style="background-color:yellow; float:left; width: 330px;">
<div class='button num'>0</div>
<div class='button num'>1</div>
<div class='button num'>2</div>
<div class='button num'>3</div>
<div class='button num'>4</div>
<div class='button num'>5</div>
<div class='button num'>6</div>
<div class='button num'>7</div>
<div class='button num'>8</div>
<div class='button num'>9</div>
<div id="equals" class='button'>=</div>
<div id="cbutton" class='button'>C</div>
<div class='button'>+</div>
<div class='button'>-</div>
<div class='button'>x</div>
<div class='button'>÷</div>
<div class='button'>.</div>
<div class='button'>%</div>
</div>
</div>
</body>

How can I use event listeners and functions to add the key pressed to a string?

I am trying to create a keypad on my website that accepts 6 numbers and only 6 numbers. It should take the numbers that the user clicks and display them at the bottom, where it says "Enter Pass Code" otherwise. I have assigned event listeners to the div elements that need them, my question lies in how I am supposed to add the numbers to the string, so that I can display them at the bottom. Normally I use syntax like
var numString = "";
numString = numString + X;
I then add the values to numString, but in this case I am not sure what I am adding. My code currently looks like this:
var numString = "";
var doSomething = function(event) {
// console.log(event.type);
// console.log(event.target);
// stringCounter = stringCounter + ;
console.log(stringCounter);
};
var doSomethingElse = function(event) {
}
let a = document.getElementById("One");
a.addEventListener(
'click',
doSomething,
false
);
The third thing that is commented out is where my problem lies. I am not sure what it is that I am supposed to add to the numString so that it reads any numeric keys that I click on the webpage.
The HTML for the page is below.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title> Keypad </title>
<link rel = "stylesheet"
type = "text/css"
href = "css/keypad.css" />
<link rel="s
stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
</head>
<body>
<div id="overall">
<div id="accesspadtitle">
Access Keypad
</div>
<div id = "numRowOne">
<div id="One"> 1</div>
<div id="Two"> 2</div>
<div id="Three"> 3</div>
</div>
<div id = "numRowTwo">
<div id="Four"> 4</div>
<div id="Five"> 5</div>
<div id="Six"> 6</div>
</div>
<div id = "numRowThree">
<div id="Seven"> 7</div>
<div id="Eight"> 8</div>
<div id="Nine"> 9</div>
</div>
<div id = "numRowFour">
<div id="Enter"> Enter </div>
<div id="Zero"> 0 </div>
<div id="Clear"> Clear </div>
</div>
<div id="passCode">
<p> Enter Pass Code</p>
</div>
</div>
<script src="javascript/keypad.js"> </script>
</body>
</html>
Here is a perfect running example.
Run the following snippet
or
JSFiddle:https://jsfiddle.net/ymuxdvfb/3/
var numberOfEntries=0;
var passcode=document.querySelector(".code");
for(let i=1;i<=10;i++){
let btn=document.createElement('button');
btn.onclick=function(){
addPassCode((i!=10)?i:0);
};
btn.className="grid-item";
btn.innerHTML=(i!=10)?i:0;
document.querySelector('.grid-container').appendChild(btn);
}
document.querySelector("#clear").onclick=function(){
passcode.innerHTML="";
numberOfEntries=0;
}
document.querySelector("#delete").onclick=function(){
if(passcode.innerHTML.length!=0){
passcode.innerHTML=passcode.innerHTML.slice(0, -1);
numberOfEntries-=1;
}
}
function addPassCode(text){
if(numberOfEntries==6){
alert("Max 6 digits are allowed");
return;
}
passcode.innerHTML+=text;
numberOfEntries++;
}
.grid-container {
display: grid;
grid-template-columns: auto auto auto;
background-color: skyblue;
padding: 10px;
}
.grid-item {
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid rgba(0, 0, 0, 0.8);
padding-top: 5px;
margin:5px;
border-radius:5px;
padding-bottom:5px;
font-size: 20px;
text-align: center;
}
<div class="grid-container">
</div>
<br>
Your pass code is:<span class="code"></span>
<button id="clear">Clear</button>
<button id="delete">BackSpace</button>

How to save the details of range slider in the local storage?

I am replicating this webpage https://www.modsy.com/project/furniture and I wrote the code On every slide there will be changing of image and phrase like that there are three phrases and images now I want to store the image and phrase in the local storage what the user has finalized
My html code is:
<div class="image mt-3 mb-3" id="sliderImages">
<img src="../static/images/1.jpg" width="400" height="180">
<img src="../static/images/2.jpg" width="400" height="180">
<img src="../static/images/3.jpg" width="400" height="180">
</div><br>
<div class="rangeslider">
<input type="range" min="1" max="3" value="1" class="myslider" id="sliderRange">
<div id="sliderOutput">
<div class="container">
<div class="row mt-4">
<div class="col-4">
<h6 class="display-6">Starting From Scratch</h6>
<p> I'm designing the room </p>
</div>
<div class="col-4">
<h6 class="display-6">Somewhere in Between</h6>
<p>I'm designing around a few pieces I already own</p>
</div>
<div class="col-4">
<h6 class="display-6">Mostly Furnished</h6>
<p>I want to put the finishing touches on my room</p>
</div>
</div>
</div>
<div class="container">
<div class="row mt-4">
<div class="col-4">
<h6 class="display-6">Starting From Scratch</h6>
<p> I'm designing the room </p>
</div>
<div class="col-4">
<h6 class="display-6">Somewhere in Between</h6>
<p>I'm designing around a few pieces I already own</p>
</div>
<div class="col-4">
<h6 class="display-6">Mostly Furnished</h6>
<p>I want to put the finishing touches on my room</p>
</div>
</div>
</div>
<div class="container">
<div class="row mt-4">
<div class="col-4">
<h6 class="display-6">Starting From Scratch</h6>
<p> I'm designing the room </p>
</div>
<div class="col-4">
<h6 class="display-6">Somewhere in Between</h6>
<p>I'm designing around a few pieces I already own</p>
</div>
<div class="col-4">
<h6 class="display-6">Mostly Furnished</h6>
<p>I want to put the finishing touches on my room</p>
</div>
</div>
</div>
</div>
<div class="row mb-3 mt-3">
<div class="col-4 mr-5">
« Home
</div>
<div class="col-4 ml-5">
Next » </div>
</div>
</div>
My CSS code is:
<style>
.rangeslider {
width: 50%;
margin: 0 auto;
position: absolute;
}
.myslider {
-webkit-appearance: none;
background: white;
width: 100%;
height: 20px;
opacity: 0.8;
margin-top: 180px;
}
.myslider::-webkit-slider-thumb {
-webkit-appearance: none;
cursor: pointer;
background: #000080;
width: 33%;
height: 20px;
}
.col-4 {
text-align: center;
}
.myslider:hover {
opacity: 1;
}
.image {
position: relative;
width: 400px;
margin: 0 auto;
}
.image>img {
position: absolute;
display: none;
}
.image>img.visible,
.image>img:first-child {
display: block;
}
#sliderOutput>div {
display: none;
}
#sliderOutput>div.visible,
#sliderOutput>div:first-child {
display: block;
}
#p1{
height: 10px;
}
</style>
My JS code is:
<script>
window.addEventListener('load', function() {
var rangeslider = document.getElementById("sliderRange");
var output = document.getElementById("sliderOutput");
var images = document.getElementById("sliderImages");
rangeslider.addEventListener('input', function() {
for (var i = 0; i < output.children.length; i++) {
output.children[i].style.display = 'none';
images.children[i].style.display = 'none';
}
i = Number(this.value) - 1;
output.children[i].style.display = 'block';
images.children[i].style.display = 'block';
});
});
</script>
My main requirement if the slider is in the first that phrase and image should be stored in local storage like that if it is in second that details should store.
There is no enough details about what json you want to store in the localStorage so that's why i am giving you the basic idea of how you can store a json in localStorage.
Basically you can't store json in localStorage directly but you can store that json in form of a stringand then converting that string(json) into json. Here is the basic example :
// setting json to localStorage
var jsonToBeStoredInLocalStorae = {
sliderImages = [
{path : 'image-path-here'},
{path : 'image-path-here'}
],
phrase : 'your image phrase'
};
localStorage.setItem('slider_json',JSON.stringify(jsonToBeStoredInLocalStorae ));
When you want to get that json from localStorage so you will do like this
//Here you are getting that json in `string` form from `localStorage` and parsing it to `json`
var localStorageJson = JSON.parse(localStorage.getItem('slider_json'));
In localStorage you can only save text strings, so if you want to save it is only one value per record, you insert a name and value to localStorage, but if you want to save an object, you must transform it to a text string with the function JSON.stringify

How to use KnockoutJS to observe data on server via AJAX?

I've played a little with knockoutjs and have produced the following example, enough to become excited by the idea of building these viewmodels in javascript so that the view can be written in much simpler, declarative manner, i.e. first you define what you want to observe, then with the data-bind attributes define what you want to happen when your viewmodel changes in certain ways.
But all of this is happening only on the client.
How could I extend this example to use knockoutjs to observe the state of objects on the server e.g. via AJAX calls?
index.htm:
<!doctype html>
<html>
<title>Knockout example</title>
<head>
<script type="text/javascript" src="js/knockout-1.1.1.debug.js"></script>
<script type="text/javascript" src="js/main.js"></script>
<link rel="stylesheet" href="css/main.css" type="text/css"/>
</head>
<body>
<!-- FIRST AREA -->
<div class="infobox">
<div data-bind="visible: noNamesFilled">
<p>This is an example with NO names filled.</p>
</div>
<div data-bind="visible: bothNamesFilled">
<p>This is an example with both names filled.</p>
</div>
<div data-bind="visible: firstNameOnlyFilled">
<p>This is an example with only the first name filled.</p>
</div>
<div data-bind="visible: lastNameOnlyFilled">
<p>This is an example with the last name filled but not the first name</p>
</div>
</div>
<!-- SECOND AREA -->
<p>First name: <input data-bind="value: firstName, valueUpdate:'afterkeydown'" /></p>
<p>Last name: <input data-bind="value: lastName, valueUpdate:'afterkeydown'" /></p>
<div data-bind="visible: bothNamesFilled">
<h2 class="normal">Hello, <span data-bind="text: fullName"></span>.</h2>
</div>
<div data-bind="visible: firstNameOnlyFilled">
<h2 class="informal">Hi there <span data-bind="text: fullName"></span>!</h2>
</div>
<div data-bind="visible: lastNameOnlyFilled">
<h2 class="formal">Hello, Mr. <span data-bind="text: fullName"></span>.</h2>
</div>
<!-- THIRD AREA -->
<div data-bind="visible: noNamesFilled">
<p><span class="bad">:-(</span> Please fill in both names.</p>
</div>
<div data-bind="visible: bothNamesFilled">
<p><span class="good">:-)</span> Good job, both names are filled!</p>
</div>
<div data-bind="visible: firstNameOnlyFilled">
<p><span class="ok">:-(</span> Please fill in the last name, too.</p>
</div>
<div data-bind="visible: lastNameOnlyFilled">
<p><span class="ko">:-(</span> Please fill in the first name as well.</p>
</div>
</body>
</html>
main.css:
* { margin: 0; padding: 0}
body { margin: 10px}
p { margin: 10px}
.infobox {
background-color: #eee;
width: 300px;
height: 100px;
padding: 10px;
}
.informal {
color: purple;
font-family: arial;
}
.normal {
color: black;
font-family: new courier;
}
.formal {
color: black;
font-size: 11pt;
font-family: times roman;
background-color: #eee;
}
.good {
width: 20px;
background-color: lightgreen;
}
.ok {
width: 20px;
background-color: yellow;
}
.bad {
width: 20px;
background-color: tomato;
}
main.js:
window.onload= function() {
var viewModel = {
firstName : ko.observable(''),
lastName : ko.observable('')
};
viewModel.fullName = ko.dependentObservable(function () {
return viewModel.firstName() + " " + viewModel.lastName();
});
viewModel.bothNamesFilled = ko.dependentObservable(function () {
return viewModel.firstName().length > 0 && viewModel.lastName().length > 0;
}, this);
viewModel.firstNameOnlyFilled = ko.dependentObservable(function () {
return viewModel.firstName().length > 0 && viewModel.lastName().length == 0;
}, this);
viewModel.lastNameOnlyFilled = ko.dependentObservable(function () {
return viewModel.firstName().length == 0 && viewModel.lastName().length > 0;
}, this);
viewModel.noNamesFilled = ko.dependentObservable(function () {
return viewModel.firstName().length == 0 && viewModel.lastName().length == 0;
}, this);
ko.applyBindings(viewModel);
}
I would use setTimeout to call a function that uses JQuery to make an $.ajax call. When it returns JSON data, set that data as your view model and finally, setTimeout again to call the function.
Here's an updated example that mainly updates main.js to work with JQuery to do the ajax call.
The HTML file includes Knockout 3 instead of 1. The HTML also includes JQuery latest to make the JQuery functionality work.
The js/server_data.js is there so you have some valid json data to start with. You can change the url in the $.ajax settings to any serverside script you have but try to set its content type to application/json. For example, PHP scripts could set the Content-type header like: header('Content-type: application/json'); before printing out the data in JSON format.
new main.html:
<!doctype html>
<html>
<title>Knockout example</title>
<head>
<script type="text/javascript" src="js/knockout-3.0.0.debug.js"></script>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript" src="js/main.js"></script>
<link rel="stylesheet" href="css/main.css" type="text/css"/>
</head>
<body>
<!-- FIRST AREA -->
<div class="infobox">
<div data-bind="visible: noNamesFilled">
<p>This is an example with NO names filled.</p>
</div>
<div data-bind="visible: bothNamesFilled">
<p>This is an example with both names filled.</p>
</div>
<div data-bind="visible: firstNameOnlyFilled">
<p>This is an example with only the first name filled.</p>
</div>
<div data-bind="visible: lastNameOnlyFilled">
<p>This is an example with the last name filled but not the first name</p>
</div>
</div>
<!-- SECOND AREA -->
<p>First name: <input data-bind="value: firstName, valueUpdate:'afterkeydown'" /></p>
<p>Last name: <input data-bind="value: lastName, valueUpdate:'afterkeydown'" /></p>
<div data-bind="visible: bothNamesFilled">
<h2 class="normal">Hello, <span data-bind="text: fullName"></span>.</h2>
</div>
<div data-bind="visible: firstNameOnlyFilled">
<h2 class="informal">Hi there <span data-bind="text: fullName"></span>!</h2>
</div>
<div data-bind="visible: lastNameOnlyFilled">
<h2 class="formal">Hello, Mr. <span data-bind="text: fullName"></span>.</h2>
</div>
<!-- THIRD AREA -->
<div data-bind="visible: noNamesFilled">
<p><span class="bad">:-(</span> Please fill in both names.</p>
</div>
<div data-bind="visible: bothNamesFilled">
<p><span class="good">:-)</span> Good job, both names are filled!</p>
</div>
<div data-bind="visible: firstNameOnlyFilled">
<p><span class="ok">:-(</span> Please fill in the last name, too.</p>
</div>
<div data-bind="visible: lastNameOnlyFilled">
<p><span class="ko">:-(</span> Please fill in the first name as well.</p>
</div>
</body>
</html>
js/main.js:
$(document).ready( function() {
var viewModel = {
firstName : ko.observable(''),
lastName : ko.observable('')
};
viewModel.fullName = ko.dependentObservable(function () {
return viewModel.firstName() + " " + viewModel.lastName();
});
viewModel.bothNamesFilled = ko.dependentObservable(function () {
return viewModel.firstName().length > 0 && viewModel.lastName().length > 0;
}, this);
viewModel.firstNameOnlyFilled = ko.dependentObservable(function () {
return viewModel.firstName().length > 0 && viewModel.lastName().length == 0;
}, this);
viewModel.lastNameOnlyFilled = ko.dependentObservable(function () {
return viewModel.firstName().length == 0 && viewModel.lastName().length > 0;
}, this);
viewModel.noNamesFilled = ko.dependentObservable(function () {
return viewModel.firstName().length == 0 && viewModel.lastName().length == 0;
}, this);
ko.applyBindings(viewModel);
// send request to the server to download the server's model information.
$.ajax(
{
'url': 'js/server_data.js',
'dataType': 'json',
'method': 'post',
'error': function(jqXHR, textStatus, errorThrown)
{
// error callback in case you play with this code and run into trouble.
alert('There was a problem handling the ajax request. The error information is: jqXHR: '
+jqXHR+", textStatus: "+textStatus+", errorThrown: "+errorThrown);
},
'success': function(data)
{
// when it is downloaded and parsed to create the "data" parameter, update the viewModel.
viewModel.firstName(data.firstName);
viewModel.lastName(data.lastName);
}
}
);
}
);
js/server_data.js representing dynamically generated data that might be from a database:
{
"firstName": "John",
"lastName": "Doe"
}
jsteve has the right general idea but don't use setTimeout if you just want to download the data when the page loads. Instead, use the JQuery's document ready callback and JQuery's ajax success callback so things run precisely when you want them to.
If you want to continually listen and react to changes to data in the server, look into long poller techniques. Long poller is more efficient and precisely timed than busy waiting that requires a frequent new request to the server.

Categories

Resources