I've got a JavaScript file which is querying a SharePoint list. I'm querying two drop down lists. The first - LifeCycleStatus - comes back fine, but the Priority drop down comes back with screen grab [object OBJECT]. I think it has to do with the var query string. I've added the 'Priority' column to the var query but it doesn't seem to be making any difference
var query = "http://collaboration-
de.vxxx.com/sites/it/SystemInventory/_vti_bin/listdata.svc/Devices?$expand=LifeCycleStatus&Priority&$filter=Id eq " + window.DeviceId + "";
Full JavaScript below:
function getDeviceDetails() {
var txtTitle = "";
var txtOverview = "";
var txtAccessories = "";
var txtDevicetype = "";
var txtTypicalDeviceUsage ="";
var txtKnownSystemIssues ="";
var txtLifeCycles = "";
var txtTrafficlight = "";
var tempLCS2 = "";
var query = "http://collaboration-dev.xxx/sites/it/SystemInventory/_vti_bin/listdata.svc/Devices?$expand=LifeCycleStatus&Priority&$filter=Id eq " + window.DeviceId + "";
var call = $.ajax({
url: query,
type: "GET",
dataType: "json",
headers: {
Accept: "application/json;odata=verbose"
}
});
call.done(function (data,textStatus, jqXHR){
$.each(data.d.results, function(index, item) {
var tempID = item.Id;
var tempTitle = item.Title;
var LifeCycleStart = item.DeviceAvailableFrom;
var LifeCycleStatus = item.LifeCycleStatusValue;
var DeviceOverView = item.Description;
var AccessDetails = item.Accessories;
var DeviceKind = item.Devicetype;
var Usage = item.TypicalUsage;
var DevicePriority = item.Priority;
txtTitle = "<p>" + LifeCycleStart + "</p><p>" + LifeCycleStatus + "</p>";
txtOverview = "<p>" + DeviceOverView + "</p>";
txtAccessories = "<p>" + AccessDetails + "</p>";
txtDevicetype = "<p>" + DeviceKind + "</p>";
txtTypicalDeviceUsage = "<p>" + Usage + "</p>";
txtTrafficlight = "<p>" + DevicePriority + "</p>";
// txtKnownSystemIssues = "<p>" + KnownSystem + "</p>"
});
$('#devicedetails').append($(txtTitle));
$('#deviceoverview').append($(txtOverview));
$('#devicekind').append(txtDevicetype);
$('#deviceacc').append(txtAccessories);
$('#deviceuse').append(txtTypicalDeviceUsage);
$('#devicestatus').append(txtTrafficlight);
});
call.fail(function (jqXHR,textStatus,errorThrown){
alert("Error retrieving data: " + jqXHR.responseText);
});
}
"Priority" and "LifeCycleStatus" contains an object. You can use the debugger/console to see what the object is - I bet it contains a string with the Value, and the internal ID of the value, possibly other things. Converting an object to a string returns "[object Object]".
"PriorityValue" and "LifeCycleStatusValue" are probably shorthands to the value string.
Related
How do i show all the data by using the loop to display all the data from json to html ?
ATM , I am able to print one of the data. but if i am using data[i] the code will not display any data.
I think I mess up the the concept of object and array.
please advice me , how to loop thru object , like array?
thanks
var getWeather = document.getElementById('weather');
var requestWeather = new XMLHttpRequest();
//+'-31' +'&lon='+'150'
requestWeather.open('GET','https://fcc-weather-api.glitch.me/api/current?lat=-31&lon=150');
requestWeather.onload = function () {
var weatherData = JSON.parse(requestWeather.responseText);
console.log(weatherData);
getHTML(weatherData);
};
requestWeather.send();
function getHTML(data) {
var weatherString = "";
for(var i in data.weather ){
var x= data.weather[i].main;
weatherString+= "<p class='weather'>" + x + "</p>";
// weatherString+= "<p>" + data.currently.summary + "</p>";
// console.log(data[i].city);
}
getWeather.insertAdjacentHTML("beforeend", weatherString);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="weather"></div>
to get all data check for object and do recursive loop
var getWeather = document.getElementById('weather');
var requestWeather = new XMLHttpRequest();
//+'-31' +'&lon='+'150'
requestWeather.open('GET', 'https://fcc-weather-api.glitch.me/api/current?lat=-31&lon=150');
requestWeather.onload = function() {
var weatherData = JSON.parse(requestWeather.responseText);
//console.log(weatherData);
getHTML(weatherData);
};
requestWeather.send();
function getHTML(data) {
var weatherString = "";
for(var i in data) {
var x = data[i];
if(typeof(x) == "object") {
getHTML(x);
}
else {
weatherString += "<p class='weather'><b>" + i + "</b>: " + x + "</p>";
// weatherString+= "<p>" + data.currently.summary + "</p>";
// console.log(data[i].city);
}
}
getWeather.insertAdjacentHTML("beforeend", weatherString);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="weather"></div>
var getWeather = document.getElementById('weather');
var requestWeather = new XMLHttpRequest();
//+'-31' +'&lon='+'150'
requestWeather.open('GET', 'https://fcc-weather-api.glitch.me/api/current?lat=-31&lon=150');
requestWeather.onload = function() {
var weatherData = JSON.parse(requestWeather.responseText);
getHTML(weatherData);
};
requestWeather.send();
function getHTML(data) {
var weatherString = "";
for (var i in data.weather) {
var x = data.weather[i].main;
weatherString += "<p class='weather'>" + x + "</p>";
$.each(data.main, function(i, f) {
var main = "<div>" + i + ": " + f + "</div>";
$(main).appendTo("#main");
});
}
getWeather.insertAdjacentHTML("beforeend", weatherString);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="weather"></div>
<div id="main"></div>
use foreach loop to iterate over all object
read more from here
I apologize up front for the possible lack of clarity for this question, but I'm new to Angular.js and my knowledge of it is still slightly hazy. I have done the Angular.js tutorial and googled for answers, but I haven't found any.
I have multiple select/option html elements, not inside a form element, and I'm populating them using AJAX. Each form field is populated by values from a different SharePoint list. I'm wondering if there is a way to implement this using Angular.js?
I would like to consider building this using Angular because I like some of it features such as data-binding, routing, and organizing code by components. But I can't quite grasp how I could implement it in this situation while coding using the DRY principle.
Currently, I have a single AJAX.js file and I have a Javascript file that contains an array of the different endpoints I need to connect to along with specific query parameters. When my page loads, I loop through the arrays and for each element, I call the GET method and pass it the end-point details.
The code then goes on to find the corresponding select element on the page and appends the option element returned by the ajax call.
I'm new to Angular, but from what I understand, I could create a custom component for each select element. I would place the component on the page and all the select and options that are associated with that component would appear there. The examples I've seen demonstrated, associate the ajax call with the code for the component. I'm thinking that I could use a service and have each component dependent on that service and the component would pass it's specific query details to the service's ajax call.
My current code - Program flow: main -> data retrieval -> object creation | main -> form build.
Called from index.html - creates the multiple query strings that are passed to ajax calls - ajax calls are once for each query string - the very last function in the file is a call to another function to build the form elements.
var snbApp = window.snbApp || {};
snbApp.main = (function () {
var main = {};
main.loadCount = 0;
main.init = function () {
function buildSelectOptions(){
//***
//Build select options from multiple SharePoint lists
//***
var listsArray = snbApp.splistarray.getArrayOfListsForObjects();
for(var i = 0; i < listsArray.length; i++){
var listItem = listsArray[i];
var qryStrng = listItem.list +
"?$select=" + listItem.codeDigits + "," + listItem.codeDescription + "," + listItem.ItemStatus + "&$orderby=" + listItem.codeDescription + "&$filter="+listItem.ItemStatus+" eq true" + "&$inlinecount=allpages"
var listDetails = {
listName: listItem.list,
listObj: listItem,
url: "http://myEnv/_vti_bin/listdata.svc/" + listItem.list +
"?$select=" + listItem.codeDigits + "," + listItem.codeDescription + "," + listItem.ItemStatus + "&$orderby=" + listItem.codeDescription + "&$filter="+listItem.ItemStatus+" eq true" + "&$inlinecount=allpages"
};
var clientContext = new SP.ClientContext.get_current();
clientContext.executeQueryAsync(snbApp.dataretriever.letsBuild(listDetails), _onQueryFailed);
}
//***
//Build select option from other API endpoint
//***
var listDetails = {
listName:"SNB_SecondaryActivityCodes",
url: "http://myEnv/requests/odata/v1/Sites?$filter=(IsMajor eq true or IsMinor eq true) and IsActive eq true and IsPending eq false and CodePc ne null and IsSpecialPurpose eq false&$orderby=CodePc"
};
snbApp.dataretriever.letsBuild(listDetails);
}
buildSelectOptions();
//***
//Add delay to populate fields to ensure all data retrieved from AJAX calls
//***
var myObj = setTimeout(delayFieldPopulate,5000);
function delayFieldPopulate(){
var optObj = snbApp.optionsobj.getAllOptions();
var osType = $("input[name=os_platform]:checked").val();
snbApp.formmanager.buildForm(osType, optObj);
}
};
function _onQueryFailed(sender, args) {
alert('Request failed.\nError: ' + args.get_message() + '\nStackTrace: ' + args.get_stackTrace());
}
return main
})();
AJAX calls here - called from main/previous file:
var snbApp = window.snbApp || {};
snbApp.dataretriever = (function () {
var listsArray = snbApp.splistarray.getArrayOfListsForObjects();
function getListData(listItem) {
var eventType = event.type;
var baseURL = listItem.url;
$.ajax({
url: baseURL,
type: "GET",
headers: {
"accept": "application/json;odata=verbose",
}
})
.done(function(results){
snbApp.objectbuilderutility.buildObjectFields(results, listItem);
})
.fail(function(xhr, status, errorThrown){
//console.log("Error:" + errorThrown + ": " + myListName);
});
}
function _onQueryFailed(sender, args) {
alert('Request failed.\nError: ' + args.get_message() + '\nStackTrace: ' + args.get_stackTrace());
}
return{
letsBuild:function(item) {
getListData(item);
}
};
})();
Builds a item name object - called from recursive AJAX calls / previous file
var snbApp = window.snbApp || {};
snbApp.objectbuilderutility = (function () {
function formatItemCode(itemCode, eventType){
if(eventType !== 'change'){ //for load event
var pattern = /^CE/;
var result = pattern.test(itemCode);
if(result){
return itemCode.slice(2);
}else{
return itemCode.slice(0,3);
}
}else{ //for change event
var pattern = /^CE/;
var result = pattern.test(itemCode);
if(result){
return itemCode.slice(2);
}else{
return itemCode.slice(3);
}
}
}
return{
buildObjectFields: function(returnedObj, listItem){ //results:returnedObj, prevItem:listItem
//***
//For SharePoint list data
//***
if (listItem.listName !== "SNB_SecondaryActivityCodes") {
var theList = listItem.listName;
var firstQueryParam = listItem.listObj.codeDigits;
var secondQueryParam = listItem.listObj.codeDescription;
var returnedItems = returnedObj.d.results;
var bigStringOptions = "";
//regex to search for SecondaryFunctionCodes in list names
var pattern = /SecondaryFunctionCodes/;
var isSecFunction = pattern.test(theList);
if(isSecFunction){
bigStringOptions = "<option value='0' selected>Not Applicable</option>";
}else{
bigStringOptions = "<option value='0' disabled selected>Select Option</option>";
}
$.each(returnedItems, function (index, item) {
var first = "";
var second = "";
for (var key in item) {
if (item.hasOwnProperty(key)) {
if (key != "__metadata") {
if (key == firstQueryParam) {
first = item[key];
}
if (key == secondQueryParam) {
second = item[key];
}
}
}
}
bigStringOptions += "<option value=" + first + " data-code=" + first + ">" + second + "</option>";
});
var str = theList.toLowerCase();
snbApp.optionsobj.updateFunctionOrActivity(theList.toLowerCase(), bigStringOptions);
//***
//For other API
//***
} else {
var theList = listItem.listName;
var bigStringOptions = "<option value='0' disabled selected>Select Option</option>";
var returnedItems = returnedObj.value;
for(var i = 0; i < returnedItems.length; i++){
var item = returnedItems[i];
//***
//change event type means the user selected a field
//***
if(listItem.eventType === "change"){
var siteCodeChange = item.SiteCodePc;
if (typeof siteCodeChange === "string" & siteCodeChange != "null") {
siteCodeChange = siteCodeChange < 6 ? siteCodeChange : siteCodeChange.slice(3);
}
bigStringOptions += "<option value='" + item.Id + "' data-code='" + siteCodeChange + "' data-isDivSite='" + item.IsDivisionSite + "' data-isDistSite='" + item.IsDistrictSite + "' data-divID='" + item.DivisionSiteId + "' data-distID='" + item.DistrictSiteId + "'>(" + siteCodeChange + ") " + item.Name + "</option>";
snbApp.formmanager.buildSelectSiteLocations(bigStringOptions);
//***
//load event which means this happens when the page is loaded
//***
}else{
var siteCodeLoad = item.SiteCodePc;
if (typeof siteCodeLoad === "string" & siteCodeLoad != "null") {
var siteCodeLoad = siteCodeLoad.length < 4 ? siteCodeLoad : siteCodeLoad.slice(0, 3);
}
bigStringOptions += "<option value='" + item.Id + "' data-code='" + siteCodeLoad + "' data-isDivSite='" + item.IsDivisionSite + "' data-isDistSite='" + item.IsDistrictSite + "' data-divID='" + item.DivisionSiteId + "' data-distID='" + item.DistrictSiteId + "'>(" + siteCodeLoad + ") " + item.Name + "</option>";
snbApp.optionsobj.updateFunctionOrActivity(theList.toLowerCase(), bigStringOptions);
}
}
}
}
};
})();
Form management - called from previous file, gets all select elements on page and appends items from the object in previous file to each select element.
var snbApp = window.snbApp || {};
//Direct interface to the form on the page
snbApp.formmanager = (function(){
var form = {};
form.content_holder = document.getElementById("content_holder");
form.sec_act_codes = document.getElementById("snb_secondary_activity_codes");
form.prim_func_codes = document.getElementById("snb_primary_function_codes");
form.sec_func_codes = document.getElementById("snb_secondary_function_codes");
form.sec_func_nums = document.getElementById("snb_secondary_function_numbers");
form.host_options = document.getElementById("snb_host_options");
form.site_locs_div = document.getElementById("site_locations_div");
form.site_locs = document.getElementById("snb_site_locations");
form.dc_or_off_prem_div = document.getElementById("dc_or_off_premise_div");
form.dc_off_prem_codes = document.getElementById("snb_dc_offpremise_codes");
var snb_secondary_activity_codes = "";
var snb_primary_function_codes = "";
var snb_secondary_function_codes = "";
var snb_secondary_function_numbers = "";
var snb_host_options = "";
var snb_site_locations = "";
var snb_dc_op = "";
//builds the server location hosting options selection
function buildLocationTypeSelector() {
var locationOptionsString = "<option value='0' disabled selected>Select Option</option>";
for (var i = 0; i < locationOptions.length; i++) {
var location = locationOptions[i];
locationOptionsString += "<option value=" + location.hostLocale + " data-code=" + location.code + ">" + location.hostLocale + "</option>";
}
$("#snb_host_options").append(locationOptionsString);
}
function buildSiteLocations(bigString){
if(bigString === undefined){
var siteLocs = document.getElementById("snb_site_locations");
var newOption = document.createElement("option");
newOption.setAttribute("value", 0);
newOption.setAttribute("disabled","disabled");
newOption.setAttribute("checked","checked");
var newText = document.createTextNode("Select Option");
newOption.appendChild(newText);
siteLocs.appendChild(newOption);
} else{
var siteLocs = document.getElementById("snb_site_locations");
siteLocs.innerHTML = bigString;
}
}
return {
form:form,
buildSelectSiteLocations: function(bigString){
buildSiteLocations(bigString);
},
buildForm: function (osType, optObj) {
buildLocationTypeSelector();
buildSecondaryFunctionNumberSelector();
buildSiteLocations();
if(osType === 'windows'){
$("#snb_secondary_activity_codes").append(optObj.windows.secondary_activity);
$("#snb_primary_function_codes").append(optObj.windows.primary_function);
$("#snb_secondary_function_codes").append(optObj.windows.secondary_function);
$("#snb_site_locations").append(optObj.windows.site_location);
$("#snb_dc_offpremise_codes").append(optObj.windows.dc_offpremise);
}else{
$("#snb_secondary_activity_codes").append(optObj.unix.secondary_activity);
$("#snb_primary_function_codes").append(optObj.unix.primary_function);
$("#snb_secondary_function_codes").append(optObj.unix.secondary_function);
$("#snb_site_locations").append(optObj.unix.site_location);
$("#snb_dc_offpremise_codes").append(optObj.unix.dc_offpremise);
}
}
};
})();
Thanks in advance.
I've got some JavaScript which is querying a SharePoint Date Column. The format is: DD/MM/YYYY and the results come back fine except for the date which is coming back as pictured under Device Details.
I'm trying to use the Moment.js library to format it but I'm not having any luck.
I think it's either this line:
var LifeCycleStart = item.DeviceAvailableFrom;
or this line I need to use the Moment formatting on:
$('#devicedetails').append($(txtTitle));
Full code below:
function getDeviceDetails() {
var txtTitle = "";
var txtOverview = "";
var txtAccessories = "";
var txtDevicetype = "";
var txtTypicalDeviceUsage ="";
var txtKnownSystemIssues ="";
var txtLifeCycles = "";
var tempLCS2 = "";
var query = "http://collaboration-dev.xxx.com/sites/it/SystemInventory/_vti_bin/listdata.svc/Devices?$expand=LifeCycleStatus&$filter=Id eq " + window.DeviceId + "";
var call = $.ajax({
url: query,
type: "GET",
dataType: "json",
headers: {
Accept: "application/json;odata=verbose"
}
});
call.done(function (data,textStatus, jqXHR){
$.each(data.d.results, function(index, item) {
var tempID = item.Id;
var tempTitle = item.Title;
var LifeCycleStart = item.DeviceAvailableFrom;
var LifeCycleStatus = item.LifeCycleStatusValue;
var DeviceOverView = item.Description;
var AccessDetails = item.Accessories;
var DeviceKind = item.Devicetype;
var Usage = item.TypicalUsage;
//var KnownSystem = item.KnownSystemIssues
txtTitle = "<p>" + LifeCycleStart + "</p> <p>" +
LifeCycleStatus + "</p>";
txtOverview = "<p>" + DeviceOverView + "</p>";
txtAccessories = "<p>" + AccessDetails + "</p>";
txtDevicetype = "<p>" + DeviceKind + "</p>";
txtTypicalDeviceUsage = "<p>" + Usage + "</p>";
});
$('#devicedetails').append($(txtTitle));
$('#deviceoverview').append($(txtOverview));
$('#devicekind').append(txtDevicetype);
$('#deviceacc').append(txtAccessories);
$('#deviceuse').append(txtTypicalDeviceUsage);
});
call.fail(function (jqXHR,textStatus,errorThrown){
alert("Error retrieving data: " + jqXHR.responseText);
});
}
Momentjs can parse string like '/Date(1494460800000)/' as stated in the ASP.NET JSON Date section of the parsing doc.
In your case you can do something like:
var LifeCycleStart = moment(item.DeviceAvailableFrom).format('DD/MM/YYYY');
using format to convert moment object to string.
Here, i am trying to send a mail to replyEmail specified below. But it is giving as undefined value. Why its happening even though i am giving correct email id in google form? Some times its coming correct. But for another time its giving as undefined value.
function sendEmail(e) {
/**
var email = e.values[1];
var item = e.values[2];
var cost = e.values[3];
*/
var serviceInformation = e.values[1],
language = e.values[2],
meetingType = e.values[3],
eventDate = e.values[4],
clientName = e.values[5],
detailedDirections = e.values[6],
onSitePOCName = e.values[7],
onSitePOCNumber = e.values[8],
department = e.values[9],
contactPhoneNumber = e.values[10],
approval = e.values[11]; //the one we need to modif,
requestorEmail = e.values[12],
managerEmail = e.values[13],
Language2 = e.values[14],
interpreterName = e.values[15],
interpreterAgency = e.values[16],
dateConformationSent = e.values[17],
specialNotes = e.values[18];
var url = 'https://script.google.com/a/macros/richmond.k12.va.us/s/AKfycbwuRr1boKTH0v1mprWmc7PE66_mQ_dmPE0lyWb7vkfiyW3pn31b/exec';
// might be that the & needs to be a ?
var approve = url + '?approval=true' + '?reply=' + requestorEmail;
var reject = url + '?approval=false' + '?reply=' + requestorEmail;
var html = "<HTML><body>"+
"<h2>please review</h2><br />"
+"<P>" + language +" " + serviceInformation
+"<p>" + meetingType+ " on "+ eventDate + " for " +clientName
+"<p>" + "Location: "+ department
+"<p>" + "requester: "+ requestorEmail+ " "+
"<p>"+
"Approve<br />"+
"<p>"+
"Reject<br />"+
"</HTML></body>";
var html = [
"<html>",
"<body>",
"<h2>please review</h2> <br/>",
"<p>" + language +" " + serviceInformation,
"<p>" + meetingType + " on " + eventDate + " for " + clientName,
"<p>Location: " + department,
"<p>Requester: " + requestorEmail,
"<p>Approve<br/>",
"<p>Reject<br />",
"</body>",
"</html>";
].join('');
MailApp.sendEmail(managerEmail, "Approval Request", "what no html?", {
htmlBody: html
});
}
function doGet(e) {
var app = UiApp.createApplication(),
aprovalResponce = (e.parameter.approval == 'true') ? 'Approved.' : 'Sorry, you need to reschedule',
msg = "Your manager said :" + aprovalResponce;
var replyEmail = e.parameter.reply; // !!!
Logger.log(replyEmail);
MailApp.sendEmail(replyEmail, "Approval Request", msg);
var helloWorldLabel = app.createLabel(msg);
app.add(helloWorldLabel);
return app;
}
Its because space is not accepted while parsing the data in google script.It should be encoded and then the data is to be send.It can be encoded using encodeURIcomponent().
I have an HTML/CSS search bar where people can type a keyword and, on click, my Open States JSON API code returns New Jersey state bills that match that keyword.
Search Bar Screenshot
Screenshot of a Result
I want the bill titles that are returned to be hyperlinked to their page on the New Jersey state legislature site, but I can only find instructions for how to hyperlink a return with a static site.
Here is my JavaScript code so far (with API key removed):
e.preventDefault();
// console.log($("#billID").val());
var billSearchValue = $("#billID").val();
if(billSearchValue=='')
{
alert("Enter Desired Query Parameters");
} else{
// console.log(billSearchValue);
}
var searchQuery = "&q=" + billSearchValue;
var baseUrl = "http://openstates.org/api/v1/bills/?state=nj";
var apiKey = "";
var apiKeyParam = "&apikey=";
var apiKeyParams = apiKeyParam + apiKey;
var urlJSON = baseUrl + searchQuery + apiKeyParam + apiKey;
// console.log(urlJSON);
$.getJSON(urlJSON, function (data) {
var billsVar = [];
$.each(data, function(key, val) {
billsVar.push(val);
});
for (var i = 0; i < billsVar.length; i++) {
var billList = "<li>Bill <ul class=\"ul-sub\">"
var billTitle = "<li><strong>Bill Title</strong>: " + billsVar[i]['title'] + "</li>";
var billCreatedAt = "<li><strong>Bill Created</strong>: " + billsVar[i]['created_at'] + "</li>";
var billUpdatedAt = "<li><strong>Bill Updated</strong>: " + billsVar[i]['updated_at'] + "</li>";
var billID = "<li><strong>ID</strong>: " + billsVar[i]['id'] + "</li>";
var billChamber = "<li><strong>Bill Chamber</strong>: " + billsVar[i]['chamber'] + "</li>";
var billState = "<li><strong>Bill State (Probably Don't Want/Need This)</strong>: " + billsVar[i]['state'] + "</li>";
var billSession = "<li><strong>Bill Session</strong>: " + billsVar[i]['session'] + "</li>";
var billType = "<li><strong>Bill Type</strong>: " + billsVar[i]['type'] + "</li>";
var billSubjects = "<li><strong>Subjects</strong>: " + billsVar[i]['subjects'] + "</li>";
var billBillID = "<li><strong>Bill ID</strong>: " + billsVar[i]['bill_id'] + "</li>";
var billOutput = billList + billTitle + billCreatedAt + billUpdatedAt + billID + billChamber + billState + billSession + billType + billSubjects + billBillID + "</ul></li>";
$("#jsonlist").append(billOutput);
}
});
})
});
After a bit of research I see that a bill hyperlink is like this:
http://openstates.org/nj/bills/{Bill Session}/{Bill ID}/
I can't test my code because I have no API key, but the solution could be something like:
var billTitle = '<li><strong>Bill Title</strong>: '
+ '<a href="http://openstates.org/nj/bills/' +
billsVar[i]['session'] + '/' + billsVar[i]['bill_id'].split(' ').join('') + '/">'
+ billsVar[i]['title'] + '</a></li>';