jQuery code not working when migrating from SP2013 to SP2019 - javascript

I have a code that is working perfectly on SP2013 as a page layout. What the code does is to load items from a list, it show the first 4 items and then when you clicked the load more button it loads 4 more items until it reaches the total number of items; when you click the reset button it goes back to 4 items. When I migrated the code to SP2019 and converted it into a web part the items don't show, the are in the DOM but not showing. I have a class of .content set to display: none; when I remove it all the items show but this is not the expected result; I expect just the 4 first items to show by default and when the load more is clicked to show 4 more. What is strange is that it is working correctly on SP2013 but not in 2019, and the console does not show any errors.
<div class="content col-md-6"></div>
.content {
display: none;
}
$(document).ready(function() {
$(".content").slice(0, 4).show();
$(".resetBtn").hide();
var items = $(".content").length;
var shown;
$(".loadMore").click(function() {
$(".resetBtn").show();
shown = $(".content:visible").length + 4;
if (shown < items) {
$(".content:lt(" + shown + ")").show(300);
} else {
$(".content:lt(" + items + ")").show(300);
$(".loadMore").hide();
}
});
$(".resetBtn").click(function() {
var end = $(".content").length;
console.log(end);
$(".content").slice(4, end).hide(300);
$(".loadMore").show();
$(".resetBtn").hide();
});
});

I just had to move the script into the ajax call
var buildManagersCards = function(items) {
var managersContent = $("#managersContent");
for (let i = 0; i < items.length; i++) {
//build cards
var managersCards =
'<div class="content col-md-6"><div class="single-news mb-4"><div class="row"><div class="col-md-3"><div class="view overlay rounded z-depth-1 mb-4"><img class="img-fluid" src="' + items[i].Image.Url +'" alt="' + items[i].Title + '" /><a><div class="mask rgba-white-slight waves-effect waves-light"></div></a></div></div><div class="col-md-9"><p class="font-weight-bold dark-grey-text">' + items[i].Title +
'</p><div class="d-flex justify-content-between"><div class="col-11 pl-0 mb-3 managerDescription"><div>' + items[i].Description+'</div><div class="managerDate"><small>' + items[i].date+'</small></div><a data-toggle="modal" data-target=#basicExample'+items[i].ID+'><span class="modalButton" >Read More</span></a></div><a data-toggle="modal" data-target=#basicExample'+items[i].ID+'><i class="fas fa-angle-double-right modalArrow"></i></a></div></div></div></div></div>';
managersContent.prepend(managersCards);
}
};
var buildModal = function(items) {
var modalContent = $('#modalContent');
for (let i = 0; i < items.length; i++) {
var modalContentCard = '<div class="modal fade" id=basicExample'+ items[i].ID+' tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true"><div class="modal-dialog modal-lg" role="document"><div class="modal-content"><div class="modal-header"><h5 class="modal-title" id="exampleModalLabel"><strong>' + (items[i].Title || ' ') +
'</strong></h5><button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button></div><div class="modal-body"><h5>Personal:</h5><p><strong>A dream I have is to:</strong> '+ (items[i].Dream || ' ') +'</p><p><strong>You would be surprised to learn that I:</strong>'+ (items[i].Learn || ' ') +'</p><p><strong>My motto is:</strong>'+( items[i].Motto || ' ') +
'</p><p><strong>The mission of our agency is:</strong>'+ (items[i].Mission || ' ') +'</p><hr><h5>Our current priorities are:</h5><p>'+ (items[i].Priorities || ' ') +'</p><h5>Our biggest accomplishments in the past year include:</h5><p>'+ (items[i].Accomplishments || ' ') +'</p><div class="agency"><h5>One thing you did not know about our agency is:</h5><p>'+ (items[i].Agency || ' ')+'</p></div><div class="mt-3 mb-3">'+ (items[i].Website || ' ') +'</div><div class="modal-footer"><button type="button" class="btn btn-primary" data-dismiss="modal">Close</button></div></div></div></div></div>';
modalContent.prepend(modalContentCard);
}
};
//ajax call
var url1 =
"/ManagersMoments/_api/web/lists/GetByTitle('managersMoments')/items";
var handle_ajax = function(url) {
$.ajax({
url: url,
method: "GET",
headers: {
Accept: "application/json; odata=verbose"
},
success: function(data) {
var items = data.d.results;
console.log(items);
buildManagersCards(items);
buildModal(items);
$(".content").slice(0, 4).show();
$(".resetBtn").hide();
var items = $(".content").length;
var shown;
$(".loadMore").click(function() {
$(".resetBtn").show();
shown = $(".content:visible").length + 4;
if (shown < items) {
$(".content:lt(" + shown + ")").show(300);
} else {
$(".content:lt(" + items + ")").show(300);
$(".loadMore").hide();
}
});
$(".resetBtn").click(function() {
var end = $(".content").length;
console.log(end);
$(".content").slice(4, end).hide(300);
$(".loadMore").show();
$(".resetBtn").hide();
});
},
error: function(data) {
console.log("Error: " + data);
}
});
};
handle_ajax(url1);

Related

Sharepoint: How to filter FAQ List based on search keyword

I have a SharePoint custom FAQ List (columns: Questions, Answers, Category).
I want to filter this FAQ based on the user selecting the category in the front-end (A UI something like this should work for me: JSFiddle)
UPDATE:
I have used the above JS Fiddle code into my code in the SharePoint "Modern Script editor web part".
Here, the FAQ is showing only the last record from the SharePoint List.
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.0/css/bootstrap.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.1.0/js/bootstrap.min.js">
</script>
<script type="text/javascript">
$(document).ready(function(){
$("#search-filter").on("keyup", function() {
var unicode = event.charCode ? event.charCode : event.keyCode;
if (unicode == 27) {
$(this).val("");
}
var searchKey = $(this).val().toLowerCase();
$('.accord-toggle').each(function() {
var cellText = $(this).text().toLowerCase();
var accordion = $('#accordion panel');
if (cellText.indexOf(searchKey) >= 0) {
$(this).parent().parent().show();
}
else {
$(this).parent().parent().hide();
$('.panel-collapse.in').collapse('hide');
}
}
);
}
);
}
);
</script>
<br/>
<div class="row-fluid text-left">
<span class="clearable">
<input type="text" id="search-filter" placeholder="Type to Search" />
<span class="icon_clear">x
</span>
</span>
</div>
<br/>
<script type="text/javascript">
$(document).ready(function(){
GetItems();
$(".collapse")
.on('show.bs.collapse', function(){
alert("ss");
$(this).siblings(".card-header").find(".fa").removeClass("fa-plus").addClass("fa-minus");
}
)
.on('hide.bs.collapse', function(){
alert("aa");
$(this).siblings(".card-header").find(".fa").removeClass("fa-minus").addClass("fa-plus");
}
);
}
);
function GetItems(){
var siteURL = _spPageContextInfo.webServerRelativeUrl;
$.ajax({
url: siteURL + "/_api/web/lists/GetByTitle('EPTFAQ')/items", //change the list name
type: "GET",
dataType: "json",
headers: {
Accept: "application/json;odata=verbose"
}
,
success: function(data) {
if (data.d.results.length > 0 )
{
$('#accordion').append(GenerateAccordionFromJson(data.d.results));
console.log(data.d.results);
}
else{
$('#accordion').append("<span>No Records Found.</span>");
}
}
,
error: function(error){
alert(JSON.stringify(error));
}
}
);
}
function GenerateAccordionFromJson(objArray) {
var accordionContent = "";
for (var i = 0; i < objArray.length; i++) {
var varHref= "#collapse"+i
var varBodyId = "collapse"+i
accordionContent ='<div class="panel-group" id="accord">' +
'<div class="panel panel-default">' +
'<div class="panel-heading">' +
'<h4 class="panel-title">' +
'<a class="accord-toggle" data-toggle="collapse" href='+varHref+'>' +
'<span class="glyphicon glyphicon-bed">'+objArray[i].Title+'<span class="badge">1</span></span>' +
'</a>' +
'</h4>' +'</div>' +
'<div id='+varBodyId+' class="panel-collapse collapse" data-parent="#accordion">' +
' <div class="panel-body">' +
'<div class="list-group">' +
' <div type="button" class="list-group-item">'+objArray[i].Answer+'</div>' +
'</div>' +
'</div>' +
'</div>' +
'</div>' +
' </div>';
}
console.log(accordionContent);
return accordionContent;
}
</script>
</head>
<body>
<div class="container">
<div id="accordion">
</div>
</div>
</body>
OUTPUT:
SharePoint List view:
Resulting Output with Error:
Expected Output:
Should show all the 3 Lists and I should be able to filter the results (like in the JS Fiddle example).
In the function GenerateAccordionFromJson, this line
change to accordionContent = accordionContent +'<div class="panel-group" id="accord">' + ....

Javascript append keep adding elements

I am trying to append list[i].name and list[i].email once every time sponsorListTree li is being clicked. I can append the document.getElementById("name").appendChild(div_group); but the problem occurs when i click the div a few times, the same data will add up instead of displaying the result only once
$.ajax({
url: 'test.php',
method: 'GET',
success: function(data){
var list = data;
for (i = 0; i < list.length; i++) {
$('#sponsorListTree li').attr('id', function(i) {
return 'sponsorListTree'+(i+1);
});
$('#sponsorListTree').append('<li class="button"><tbody><tr><td><span id="information" class="details"><br/><br/> '+ 'Email: ' + list[i].email + '</br></br> '+ 'Contact No: ' + list[i].contact.phone + ' </br></br> '+ 'Joined date: ' + list[i].date + ' </br> </br>'+ 'InvestedAmount: ' + list[i].account.investedAmount + '</span></td></tr></tbody><table></li>');
}
$("#sponsorListTree li").click(function() {
var name = $(this)[0].innerHTML;
var details = $(this).find('span')[0].innerHTML
var div_name = document.createElement('div');
var div_details = document.createElement('div');
div_name.innerHTML = name;
div_details.innerHTML = details;
div_name.className ="nameDetail";
div_details.className ="detail";
var div_group = document.createElement('div');
div_group.append(div_name);
div_group.append(div_details);
document.getElementById("name").append(div_group);
});
$(".button").click(function() {
$("span").toggleClass("details");
});
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul style=" overflow-x: auto; width: 400%; height: 600px;">
<li>
<a id="root" href="#"></a>
<ul id ="sponsorListTree">
</ul>
</li>
</ul>
<div id = "name" class="control-label"></div>

How to render a List Element using VueJs from a json data

I have a javascript code which renders <ol><li></li></ol> , Using a json from the server . The code looks something like this
function loadWorkFlowRules() {
var wf_id = <?php echo $wf->id; ?>;
$.post("/api/wfengine/get_wf_rules/", {
wf_id: wf_id
}, function(result) {
var wf_rules = JSON.parse(result).data;
if (makeView(wf_rules)) {
toastr.success('The Rules are Successfully Loaded!');
} else
toastr.info('Welcome to Work Flow Editor');
});
}
function makeView(wf_rules) {
//console.log(wf_rules);
var html_str = '',
response = false;
$.each(wf_rules, function(key, value) {
if (value.length > 0) {
$.each(value, function(key1, value1) {
var ui_l1 = '<li class="alert mar" data-id="' + value1.id + '" data-name="' + value1.name + '" style=""><div class="dd-handle state-main">' + value1.name + '<span class="cust-close" data-dismiss="alert" aria-label="Close"><i class="fa fa-times"></i></span></div><ol>';
html_str = html_str + ui_l1;
if (value1.children.length > 0) {
$.each(value1.children, function(key2, value2) {
$.each(value2, function(key3, value3) {
var ui_l2 = '<li class="alert mar" data-id="' + value3.id + '" data-name="' + value3.name + '" style=""><div class="dd-handle state-main">' + value1.name + '<span class="cust-close" data-dismiss="alert" aria-label="Close"><i class="fa fa-times"></i></span></div><ol>';
html_str = html_str + ui_l2;
if (value3.children.length > 0) {
$.each(value3.children, function(key4, value4) {
if (value4.length > 0) {
var ui_l3 = '<li class="dd-item alert mar action" data-id="' + value4[0].id + '" data-name="' + value4[0].name + '" data-api="' + value4[0].api + '" data-url="' + value4[0].url + '" data-json="' + value4[0].json + '" style=""><div class="dd-handle">' + value4[0].name + '<span class="cust-close" data-dismiss="alert" aria-label="Close"><i class="fa fa-times"></i></span> <span class="edit cust-close" data-toggle="modal" data-target="#editAction" ><i class="fa fa-pencil"></i></span></div></li>';
html_str = html_str + ui_l3;
}
})
}
html_str = html_str + '</ol></li>';
});
})
}
html_str = html_str + '</ol></li>';
});
$('.contract_main').html(html_str);
response = true;
} else
response = false;
});
return response;
}
HTML
<div class="dd">
<ol class="dd-list simple_with_drop vertical contract_main">
</ol>
</div>
I got into a situation where Ill have to Bind the data element of the child <li> with an HTML MODAL popup , So that if the value in Modal is updated it shoud change in the Object/Dom also .
I was recommended to use VueJs.
I have went through! the basics of the VueJs , But that didn't cover how I ccan bind complete list from a Json ,
Any help in how I can do this would be great
Currently I don't see any structure of Vue.Js in your code and you are manipulating the JSON data and constructing the HTML in the JS code itself. You can do it in vue way, where you will create an Vue instance, do loading of data in Vue methods and use Vue syntax to iterate over data and other things. One Simple example you can see in this fiddle or in below code:
new Vue({
el: '#app',
data: {
jsonData: []
},
mounted () {
this.loadJsonData();
},
methods: {
loadJsonData(){
setTimeout(()=>{
this.jsonData = ["first", "Second", "Third", "And So On"]
}, 300)
}
}
})
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<div id="app">
<ul>
<li v-for="data in jsonData">{{data}}</li>
</ul>
</div>
You can look at vue-hackernews to understand more about structuring of code, How to fetch data from remote APIs in JSON format and display it.

Masonry sometimes lays out in one column straight line

I have masonry initialized on some "tiles" that include an image. Most of the time I am not having issues but sometimes the tiles lay out in one column when there should be 3 columns. Do you have any idea what the issue might be?
On ready initialization:
$(document).ready(function() {
var $container = $('#news');
$container.masonry({
itemSelector: '.pageNewsItem',
transitionDuration: 0
});
$container.masonry( 'on', 'layoutComplete', function( msnryInstance, laidOutItems ) {debounced = true;} )
});
Dynamically append tiles:
var count = 0;
function placeNewsTiles(news){ //places news tiles
var length = (news.data.length > 20) ? 20 : news.data.length;
var elems ="";
for(var i = 0; i < length; i++){
elems += '<div class="pageNewsItem inactive" id="'+ count + i + '">\
<div class="outerTextWrap">\
<div class="textWrap">\
<a href="' + news.data[i]._url + '">\
<strong>' + news.data[i]._title + '</strong>\
</a>\
<span class="source">' + news.data[i]._source + '</span>\
</div>\
</div>\
<div class="imageWrap"></div>\
<div class="thumbsOverlay" style="display:none">\
<div class="thumbs">\
<div>\
\
\
</div>\
</div>\
<div class="title">\
<div>\
<a href="' + news.data[i]._url + '">\
<div class="theTitle">Read Article</div>\
</a>\
</div>\
</div>\
</div>\
</div>';
getTileImage({total: news.count, i:count + "" + i, url:news.data[i]._url});
}
elems = $(elems);
$('#news').append(elems).imagesLoaded(function(){
//for(var i = 0; i < length; i++) $('.pageNewsItem').removeClass('inactive'); //$('.pageNewsItem').show(1000);
$('#news').masonry( 'appended', elems);
});
newsPage = 0;
count++;
hoverTiles();
}
getTileImage function is called to conduct an ajax call to obtain the tile image. Masonry layout happens on complete:
var cnt = 0;
function getTileImage(args){
var _t = localStorage.getItem("token"),
url = args.url,
i = args.i;
$.ajax({
type: "GET",
url: apiHost+'/api/tileImg?url=' + url + '&token='+_t,
dataType: "json",
success: function(data) {
var img = (data && data.image.src) ? data.img.src : (data && data.image) ? data.image: "";
if(img.indexOf("spacer") > -1|| img.indexOf("blank") > -1 || img === ""){ $('.pageNewsItem#' + i).hide(); }
else $('.pageNewsItem#' + i).find('.imageWrap').append('<img src="' + img + '" />');
},
error: function(e) {
if (e.status == 404) {
//need to get a new token
getToken(getTileImage, url);
}
}, complete: function(){
cnt++;
if ((cnt ==20) || cnt == args.total) {
var $container = $('#news');
$container.imagesLoaded( function() {
$container.masonry( 'layout' );
$('.pageNewsItem').removeClass('inactive');
//$('.pageNewsItem').show();
});
cnt = 0;
}
/*$('#news').imagesLoaded( function() {
$('.pageNewsItem#' + i + ' .thumbs').height($('.pageNewsItem#' + i).outerHeight() - $('.pageNewsItem#' + i + ' .title').height() - 5);
//$('.pageNewsItem').show();
});*/
}
});//end ajax call
}
CSS:
.pageNewsItem {
width: 33.333%;
padding: 10px;
min-height: 150px;
opacity: 1;
transition: opacity 1s ease;
}
#news {
margin-right: 20px;
margin-top: 25px;
}
Try using the console and manually initialize masonry:
$('#news').masonry();
If it is not working, masonry might be already initialized and therefore it's not repositioning the elements. In that case you have to remove masonry from the div and reinitialize it:
$('#news').masonry('destroy');
$('#news').masonry();

Generate JQM Popup Dynamically

I want to display a JQM PopUp based on the contents of my variable.
I have a variable that contains this.
924-1922, 928-3074, 928-8363
Then I perform .split so I can get the three phone numbers.
secNumber = res.rows.item(i).secondary_num.split(", ");
So my variable secNumber now has an array of three numbers: 924-1922,928-3074,928-8363
Now here is my code for displaying it (I am using for loop for this since there are many entries with phone numbers):
html += ' Tel. No.: ' + res.rows.item(i).tel_num + ' </span> <br> <span style="font-size: 15px;color: #778084;" onclick="window.open(\'tel:02'+secNumber+'\', \'_system\');"> ' + secondary +' </span> ';
The onclick on my last <span> is working. However, it only puts the first number on the phone's dialer. What I want to achieve on my onclick is, after show a popup onclick using this code from JQM website
Actions...
<div data-role="popup" id="popupMenu" data-theme="d">
<ul data-role="listview" data-inset="true" style="min-width:210px;" data-theme="d">
<li data-role="divider" data-theme="e">Choose an action</li>
<li>View details</li>
<li>Edit</li>
<li>Disable</li>
<li>Delete</li>
</ul>
</div>
When I click on my <span> the contents of the listview of the popup will be the contents of my array secNumber, then on the onclick of each element in the listview, I will call window.open to access the phone's dialer.
EDIT
This is my code.
article.emergency = function() {
var secNumber;
var telnum;
var html = '';
appDB.transaction(function(tx) {
tx.executeSql("SELECT * FROM emergency", [], function(tx, res) {
if (res.rows.length > 0) {
for (var i = 0; i < res.rows.length; i++) {
function openPopup(index) {
//reset its content
$('#popupMenu').find('ul').html('<li data-role="divider" data-theme="e">Choose an action</li>');
//loop on secondary_num items
$.each(res.rows.item(index).secondary_num.split(", "), function(k, v) {
$('#popupMenu').find('ul').append('<li>' + v + '</li>');
});
//refresh listView
$('#popupMenu').find('ul').listview("refresh");
//open popup
$('#popupMenu').popup("open", {"transition":"slideup"});
}
var secondary = (res.rows.item(i).secondary_num != 'null') ? 'Secondary Number: ' + res.rows.item(i).secondary_num : '';
secNumber = res.rows.item(i).secondary_num.split(", ");
console.log(secNumber);
/*secondary = secondary.replace(/-/g,"");
console.log("Secondary number string : "+secondary);*/
console.log(res.rows.item(i).tel_num);
telnum = res.rows.item(i).tel_num.split(" to");
console.log(telnum);
html += ' Tel. No.: ' + res.rows.item(i).tel_num + ' </span> <br> <span style="font-size: 15px;color: #778084;" onclick="window.open(\'tel:02'+secNumber+'\', \'_system\');"> ' + secondary +' </span> ';
//html += ' Tel. No.: ' + res.rows.item(i).tel_num + ' </span> <br> <span style="font-size: 15px;color: #778084;" onclick="window.open(\'tel:02'+secNumber+'\', \'_system\');"> ' + secondary +' </span> ';
}
$('.list-display').html(html);
}
});
}, article.onErr, article.onSuccess);
}
I hope someone can help me. Thanks.
Supposing your item array has multiple elements and you want to use a unique popup container you'll have to generate dynamically its content (refreshing the listView widget).
Your secondary span should look similar to
<span onclick="window.openPopup(' + index + ');"> ' + secondary +' </span>
and your openPopup function
function openPopup(index) {
//reset its content
$('#popupMenu').find('ul').html('<li data-role="divider" data-theme="e">Choose an action</li>');
//loop on secondary_num items
var secNumber = item[index].secondary_num.split(", ");
for (var i = 0; i < secNumber.length; i++) {
$('#popupMenu').find('ul').append('<li>' + secNumber[i] + '</li>');
}
//refresh listView
$('#popupMenu').find('ul').listview("refresh");
//open popup
$('#popupMenu').popup("open", {"transition":"slideup"});
}
Here you can fine a working example with a simplified structure: http://jsfiddle.net/phtzwxb6/5/
Update fixing your code with a possible solution:
// declared outside
function openPopup(index) {
//reset its content
$('#popupMenu').find('ul').html('<li data-role="divider" data-theme="e">Choose an action</li>');
//loop on secondary_num items
var secNumber = item[index].secondary_num.split(", ");
for (var i = 0; i < secNumber.length; i++) {
$('#popupMenu').find('ul').append('<li>' + secNumber[i] + '</li>');
}
//refresh listView
$('#popupMenu').find('ul').listview("refresh");
//open popup
$('#popupMenu').popup("open", {"transition":"slideup"});
}
//your enclosure...
article.emergency = function() {
var secNumber;
var telnum;
var html = '';
appDB.transaction(function(tx) {
tx.executeSql("SELECT * FROM emergency", [], function(tx, res) {
if (res.rows.length > 0) {
for (var i = 0; i < res.rows.length; i++) {
var secondary = (res.rows.item(i).secondary_num != 'null') ? 'Secondary Number: ' + res.rows.item(i).secondary_num : '';
secNumber = res.rows.item(i).secondary_num.split(", ");
telnum = res.rows.item(i).tel_num.split(" to");
html += ' Tel. No.: ' + res.rows.item(i).tel_num + ' </span> <br> <span style="font-size: 15px;color: #778084;" onclick="window.openPopup(' + i + ');"> ' + secondary +' </span> ';
}
$('.list-display').html(html);
}
});
}, article.onErr, article.onSuccess);
}

Categories

Resources