Using JSON to display the data - asp.net-mvc

I am a new to JSON, I am trying to make the menu that can click and display the data.
All the objects are return from the Controller of my asp.net mvc project.
This is my code :
<script language="javascript" type="text/javascript">
function ViewProduct() {
var searchVal = $("#txtsearch").val();
$.getJSON(url, function (data) {
var mainMenu = $("#content ul#navmenu-v");
$.each(data, function (index, dataOption) {
var new_li = $("<li class='level1' id='select_list'><a href='javascript:void(0);' id='" + dataOption.ID + "' class ='selectedcategory'>" + dataOption.Name + "</a>");
mainMenu.append(new_li);
$('a#' + dataOption.ID).click(function () {
var urlGetProByDep = '<%: Url.Content("~/") %>' + "Products/GetProductsByDepList";
t = dataOption.ID;
var data = {};
if (searchVal != "") {
data.depID = t;
data.Q = searchVal;
} else {
data.depID = t;
}
$(".brand_id").empty();
$.getJSON("ProductListing/Index", data, function (product) {
$(".brand_id").empty();
$.getJSON("ProductListing/Index", data, function (product) {
$.each(product.ja, function (index, value) {
$(".brand_id").html( value.Name + "</br>" + value.PictureName + "</br>" + value.ID);
});
});
});
});
}
$(document).ready(function () {
ViewProduct();
});
The other block of menu code works very well , just have a problem with this block of my code above :
$.getJSON("ProductListing/Index", data, function (product) {
$(".brand_id").empty();
$.getJSON("ProductListing/Index", data, function (product) {
$.each(product.ja, function (index, value) {
$(".brand_id").html( value.Name + "</br>" + value.PictureName + "</br>" + value.ID);
});
});
});
It is the block that I take the the object of JSON to display the in my view, but when I click on the menu , It shows only the element at the last of JSON object.
This is my JSON :
{"ja":
[
{"Name":"ABC1","PictureName1":"my image name1","ID":1},
{"Name":"ABC2","PictureName2":"my image name2","ID":2}
]}
Each menu is the department of each product. And if I do not loop the product data in the menu block, I cannot take the ID of the department to query to get the product in each department.
Any idea or question are welcome, Thanks you for taking your time.

You seem to have a copy&paste-error in your code, you will do 2 request to exactly the same url after each other - not even using the results of the first request. I guess you only wanted something like
$(".brand_id").empty();
$.getJSON("ProductListing/Index", data, function (product) {
$.each(product.ja, function (index, value) {
$(".brand_id").html( value.Name + "</br>" + value.PictureName + "</br>" + value.ID);
});
});
But your problem is the .html() method. You are looping over your products, and in each turn you set the html of each .brand_id-element to a new value. So the result you see is what you have set to all elements in the last iteration. What you would need to do is set the HTML of each element on its own, each with a different content.
Yet, instead of emptying the list items and readding new contents to them (maybe the number of your products changes each query request), I'd rather remove all items and append new ones:
$(".brand_id").remove();
$.getJSON("ProductListing/Index", data, function (product) {
var $parent = $("#parent"); // the parent node of the product list
$.each(product.ja, function (index, value) {
$parent.append('<li class="brand_id">' + value.Name + '<br />' + value.PictureName + '<br />' + value.ID + '</li>');
});
});
(edit) ...or, if brand_id really is an id:
var $parent = $("#brand_id").empty();
$.getJSON("ProductListing/Index", data, function (product) {
$.each(product.ja, function (index, value) {
$parent.append('<div>' + value.Name + '<br />' + value.PictureName + '<br />' + value.ID + '</div>');
});
});

You are subscribing to the .click event of the anchor inside a $.each call. But since you have captured the dataOption variable you are using to prepare the AJAX request in a closure, it is obvious that by the time you click on the link, this dataOption variable is already pointing to the last element of the array you are looping over. So you could pass the argument to the click callback like this:
<script type="text/javascript">
function ViewProduct() {
// TODO: There's some url variable used here which is nowhere defined => define it
$.getJSON(url, function (data) {
var mainMenu = $("#content ul#navmenu-v");
$.each(data, function (index, dataOption) {
$(mainMenu)​.append(
$('<li/>', {
'class': 'level1',
// TODO: find an unique id or you get broken HTML
'id': 'select_list',
'html': $('<a/>', {
'href': '#',
'id': dataOption.ID,
'class': 'selectedcategory',
'text': dataOption.Name,
'click': function(arg) {
return menuClick(arg);
}({ dataOption: dataOption })
})
})
);​
});
});
}
function menuClick(arg) {
var urlGetProByDep = '<%= Url.Action("GetProductsByDepList", "Products") %>';
var t = arg.dataOption.ID;
var data = { };
var searchVal = $('#txtsearch').val();
if (searchVal != '') {
data.depID = t;
data.Q = searchVal;
} else {
data.depID = t;
}
$('.brand_id').empty();
var url = '<%= Url.Action("Index", "ProductListing") %>';
// TODO: Are those 2 nested AJAX calls really necessary here?
$.getJSON(url, data, function (product) {
$('.brand_id').empty();
$.getJSON(url, data, function (product) {
$.each(product.ja, function (index, value) {
$('.brand_id').html( value.Name + "</br>" + value.PictureName + "</br>" + value.ID);
});
});
});
}
$(document).ready(ViewProduct);
</script>
Also notice that I have moved the searchVal declaration inside the click callback in order to account for changes of its value between the time the page is loaded and the user actually clicking on the link.

Related

How to display viewCount YoutubeApi 3

I've got this code, I've try to change a little bit with var v = value.statistics.viewCount; but nothing work for me, I've try to find a answer but without any result...
$(document).ready(function () {
$( $grid ).masonry( 'reloadItems' );
$( $grid ).masonry( 'layout' );
$('.add1').click(function (event) {
event.preventDefault();
var searchTerm = $('#query').val();
getRequest(searchTerm);
});
});
function getRequest(searchTerm) {
url = 'https://www.googleapis.com/youtube/v3/search';
var params = {
part: 'snippet',
key: 'AIzaSyA8OmKcw2DMNkJicyCJ0vqvf90xgeH52zE',
q: searchTerm,
maxResults:10
};
$.getJSON(url, params, function (searchTerm) {
showResults(searchTerm);
});
}
function showResults(results) {
var html = "";
var entries = results.items;
$.each(entries, function (index, value) {
var title = value.snippet.title;
var thumbnail = value.snippet.thumbnails.high.url;
var v = value.statistics.viewCount;
var description = value.snippet.description;
var videoID = value.id.videoId;
html += '<div class="item" title="' + title + '">' + '<img class= "vidth" id="' + videoID + '" src="' + thumbnail + '" ><div class="info"><p1>' + title+'</p1><hr><p2>'+description+'</p2><hr><p3>'+v+'</p3></div></div>';
});
$('.masonry').append(html);
$( $grid ).masonry( 'reloadItems' );
$( $grid ).masonry( 'layout' );
}
any ideas ?
You are trying to get viewCount from the statistics part, but you only queried for the snippet part.
You can only query for the statistics from the videos.list endpoint - it is not available through the search endpoint.
You will have to take the ids from the search results and then do a videos.list query for those ids to get the statistics on each and therefore the viewCount. See https://developers.google.com/youtube/v3/docs/videos/list

Unable to show "Searching" when using select2 (Loading remote data)

Refer to https://select2.github.io/examples.html, text "Searching" is shown when the remote data is loading. However, I don't know why "undefined" is shown in my case.
This is the css file.
<div class="col-sm-9">
<select class="js-data-example-ajax form-control" style="width:100%;">
<option value="select2/select2" selected="selected">select2/select2</option>
</select>
</div>
And the setting of ajax call
$(".js-data-example-ajax").select2({
ajax: {
url: "/search/products",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term,
page: params.page
};
},
processResults: function (data, page) {
return {
results: data.items
};
},
cache: true
},
minimumInputLength: 1,
templateResult: formatProduct,
templateSelection: formatProductSelection
});
Result:
function formatRepo (repo) {
if (repo.loading) return repo.text;
var markup = '<div class="clearfix">' +
'<div class="col-sm-1">' +
'<img src="' + repo.owner.avatar_url + '" style="max-width: 100%" />' +
'</div>' +
'<div clas="col-sm-10">' +
'<div class="clearfix">' +
'<div class="col-sm-6">' + repo.full_name + '</div>' +
'<div class="col-sm-3"><i class="fa fa-code-fork"></i> ' + repo.forks_count + '</div>' +
'<div class="col-sm-2"><i class="fa fa-star"></i> ' + repo.stargazers_count + '</div>' +
'</div>';
if (repo.description) {
markup += '<div>' + repo.description + '</div>';
}
markup += '</div></div>';
return markup;
}
function formatRepoSelection (repo) {
return repo.full_name || repo.text;
}
$ajax.select2({
ajax: {
url: "https://api.github.com/search/repositories",
dataType: 'json',
delay: 250,
data: function (params) {
return {
q: params.term, // search term
page: params.page
};
},
processResults: function (data, params) {
// parse the results into the format expected by Select2
// since we are using custom formatting functions we do not need to
// alter the remote JSON data, except to indicate that infinite
// scrolling can be used
params.page = params.page || 1;
return {
results: data.items,
pagination: {
more: (params.page * 30) < data.total_count
}
};
},
cache: true
},
escapeMarkup: function (markup) { return markup; },
minimumInputLength: 1,
templateResult: formatRepo,
templateSelection: formatRepoSelection
});
complete code which loads repositories in select 2 you can alter this code according to your requirements
my select box with multiple select
<select id="to_users" name="to_users" class="form-control js-data-example-ajax" multiple="multiple">
</select>
you can format results
processResults: function(data, page) {
// parse the results into the format expected by Select2.
// since we are using custom formatting functions we do not need to
// alter the remote JSON data
return {
results: $.map(data, function(obj) {
return { id: obj.user_id, text: obj.name };
})
//results: data
};
},
if you are formatting results to select2 behaviour then disable code
/* escapeMarkup: function(markup) {
return markup;
}, // let our custom formatter work
templateResult: formatRepo, // omitted for brevity, see the source of this page
templateSelection: formatRepoSelection // omitted for brevity, see the source of this page*/
Please try
function formatRepo(repo) {
if (repo.value == undefined) {
repo.value = 'Loading...'
}
var markup = '<div class="clearfix">' + repo.value + '</div>'
return markup;
}
There is a possible workaround for the above issue. Feel free to make comments.
Here is the code I've written before, let say the return JSON is {"items":[{"id":1,"name":"Product1"},{"id":2,"name":"Product2"}]}
var formatProduct = function(data){
return '<div>'+(data.name)+'</div>';
}
I've modified the code as follow and the 'Searching...' text shows again:
var formatProduct = function(data){
return '<div>'+(data.name || data.text)+'</div>';
}
In select2.js, line 798, when the data is remotely loading
this.template(data, option);
this.template directs to select2.js line 1058
Results.prototype.template = function (result, container) {
var template = this.options.get('templateResult');
container.innerHTML = template(result);
};
// result is an object indicating whether the data is loading.
// {disabled: true, loading: true, text: "Searching…"}
the template here takes the custom parameter 'templateResult' and generate the text, therefore, the custom function must contain data.text, otherwise it returns underfined.
In my case it was the formatProduct function (it has a different name in my code, but it's the same thing).
Let's say you call formatProduct for templateResult:
templateResult: formatProduct
In this case you have to check what formatProduct returns, like:
function formatProduct(product) {
return product.name || product.text;
}
In my case I was returning always product.name and the "Searching" text was under product.text, so I had to check to display it when no product was being found yet.

jQuery UI menu inside a jqGrid cell

I have created a grid and customized a column to contain a jquery UI menu like in the Split Button example
Everything works fine except for the fact that the menu window appear inside the cell causing a bad visual effect, that is, the cell height increase to make room for the menu window.
Have a look at the following screenshot for a visual explanation (nevermind about the menu item in disabled state).
Is there any way way to make the menu window appear on top of the table element in term of z-index?
Thanks very much for your valuable help, community :)
EDIT as per comment request:
The code to create the splitbutton menu is the following. First the column model markup
{ name: 'act', index: 'act', width: 80, sortable: false, search: false, align: 'center',
formatter: function (cellvalue, options, rowObject) {
var markup = "<div>" +
"<div class='actionsButtonset'>" +
"<button class='dshbd_ConfirmMonth' rel='" + rowObject.UmltID + "' rev='" + rowObject.IsConfirmAvailable + "' plock='" + rowObject.IsPeriodLocked + "' alt='Confirm'>Confirm</button>" +
"<button class='btnSelectMenu' rev='" + rowObject.IsUmltLocked + "' " + ">Select</button>" +
"</div>" +
"<ul class='actionMenu'>" +
"<li><a class='dshbd_UnlockMonth' href='#' rel='" + rowObject.UmltID + "' alt='Unlock'>Unlock</a></li>" +
"</ul>" +
"</div>";
return markup;
}
}
Then, inside the gridComplete event I have the following code (please note that some code is needed to enable/disable menu items
var confirmMonthBtn = $('.dshbd_ConfirmMonth');
$.each(confirmMonthBtn, function (key, value) {
var button = $(this);
var umltID = button.attr('rel');
button.button().click(function (event) {
event.preventDefault();
});
var isPeriodLocked = (button.attr('plock') === 'true');
if (!isPeriodLocked) {
var isConfirmAvailable = ($(this).attr('rev') === 'true');
if (!isConfirmAvailable) {
button.button({ disabled: true });
}
} else {
button.button({ disabled: true });
}
});
var currentPeriod = GetCurrentPeriod();
var period = GetCurrentViewPeriod();
var isCurrent = false;
if (currentPeriod != null && period != null) {
isCurrent = period.PeriodID == currentPeriod.PeriodID;
}
var selectBtns = $('.btnSelectMenu');
$.each(selectBtns, function (key, value) {
var button = $(this);
button.button({ text: false, icons: { primary: 'ui-icon-triangle-1-s'} });
button.click(function (event) {
var menu = $(this).parent().next().show();
menu.position({
my: 'left top',
at: 'left bottom',
of: this
});
$(document).on('click', function () {
menu.hide();
});
return false;
});
$('div.actionsButtonset').buttonset();
var menuElement = button.parent().next();
menuElement.hide();
menuElement.menu({
select: function (event, ui) {
var umltID = ui.item.children().attr('rel');
event.preventDefault();
}
});
if (!isCurrent) {
var isPeriodLocked = ($(this).attr('plock') === 'true');
if (isPeriodLocked) {
menuElement.menu({ disabled: false });
} else {
var isUmltLocked = ($(this).attr('rev') === 'true');
menuElement.menu({ disabled: !isUmltLocked });
}
} else {
//The current period is always unlocked
menuElement.menu({ disabled: true });
}
});
I prepared the demo for you which demonstrates how Split Button can be used inside of jqGrid. It displays
More detailed explanation of the demo I'll post later. Probably you will understand all yourself after examining of the code.

add image to jQuery UI autocomplete remote source with cache

I am using jQuery autocomplete remote source with caching. As per demo by jQUery UI website javascript of remote source with caching is
<script>
$(function() {
var cache = {},
lastXhr;
$( "#birds" ).autocomplete({
minLength: 2,
source: function( request, response ) {
var term = request.term;
if ( term in cache ) {
response( cache[ term ] );
return;
}
lastXhr = $.getJSON( "search.php", request, function( data, status, xhr ) {
cache[ term ] = data;
if ( xhr === lastXhr ) {
response( data );
}
});
}
});
});
</script>
Now I want to add some code to above javascript to display image in autocomplete list. There is an excellent example for displaying image in jQuery autocomplete such as:
http://jsfiddle.net/3zSMG/ but it does not include caching part.
I have been trying but NOT able to integrate this example into the existing remote with caching javascript. Any help would be very much appreciated. Many thanks.
FOLLOW-UP: As suggested by Andrew Whitaker, I have updated my script as follow:
<script>
$(function() {
var cache = {},
lastXhr;
$( "#birds" ).autocomplete({
minLength: 2,
source: function( request, response ) {
var term = request.term;
if ( term in cache ) {
response(cache[term]);
return;
}
lastXhr = $.getJSON( "search.php", request, function( data, status, xhr ) {
var results;
if ( xhr === lastXhr ) {
results = $.map(data, function(item) {
return {
value: item.value,
avatar: item.avatar
};
});
cache[term] = results;
response(results);
}
});
},
}).data("autocomplete")._renderItem = function (ul, item) {
if ( item.value != null ) {
if ( item.avatar != null) {
return $("<li/>")
.data("item.autocomplete", item)
.append("<a><img src='images/" + item.avatar + "' />" + item.value + "</a>")
.appendTo(ul);
}
else {
return $("<li/>")
.data("item.autocomplete", item)
.append("<a>" + item.value + "</a>")
.appendTo(ul);
}
}
};
});
And content of search.php:
<?php
require_once "config.php";
$term = trim(strip_tags($_GET['term']));//retrieve the search term that autocomplete sends
$qstring = "select id, subject as value, avatar from Suggests where subject LIKE '%".$term."%'";
$result = mysql_query($qstring);//query the database for entries containing the term
while ($row = mysql_fetch_array($result,MYSQL_ASSOC))//loop through the retrieved values
{
$row['value']=htmlentities(stripslashes($row['value']));
$row['id']=(int)$row['id'];
$row['avatar']=$row['avatar'];
$row_set[] = $row;//build an array
}
echo json_encode($row_set);//format the array into json data
?>
I am able to see images in autocomplete list. But there is an issue: After keying in few letters, autocomplete list is shown up, if I continue adding some more random letters to expect autcomplete list to disappear (because the userinput no longer matches) but it does not. Andrew's example work well. Is there anything wrong with my javascript? Trying to debug by Firebug, I got error: TypeError element is null.
The key to the image portion of the demos is overriding the _renderItem function to change the li's that are generated to suggest items. This usually means that your source is an array with objects that have a label and/or value property, as well as a property that allows you to display the image correctly inside of _renderItem.
The caching code just stores the search term and results in a hash and looks in that hash before hitting the server.
Using the JSFiddle you linked as an example, here's something using StackOverflow's API that does caching and images:
$(document).ready(function() {
var cache = {},
lastXhr;
$("#auto").autocomplete({
source: function(request, response) {
var term = request.term;
if (term in cache) {
response(cache[term]);
return;
}
lastXhr = $.ajax({
url: "http://api.stackoverflow.com/1.1/users",
data: {
filter: request.term,
pagesize: 10
},
jsonp: "jsonp",
dataType: "jsonp",
success: function(data, status, xhr) {
var results;
if (xhr === lastXhr) {
results = $.map(data.users, function(el, index) {
return {
value: el.display_name,
avatar: "http://www.gravatar.com/avatar/" + el.email_hash
};
});
cache[term] = results;
response(results);
}
}
});
},
delay: 500
}).data("autocomplete")._renderItem = function(ul, item) {
return $("<li />")
.data("item.autocomplete", item)
.append("<a><img src='" + item.avatar + "' />" + item.value + "</a>")
.appendTo(ul);
};
});​
Notes:
This example is more complex than the examples on jQueryUI's website because the data from the API has to be transformed (to have avatar/value properties). The important thing to note is that we're caching the received values after the $.map call transforms the result array.
This looks complicated but just remember the two guidelines at the top of the answer and you should be good.
Example: http://jsfiddle.net/rK7TS/
Here's what I did:
lastXhr = $.getJSON( action, request, function( data, status, xhr ) {
if( data && data !== null ) {
var results;
if( xhr === lastXhr ) {
results = $.map(data, function(item) {
return {
value: item.value,
avatar: item.avatar
};
});
cache[term] = results;
response(results);
}
} else {
response([{ value: 'No results found.', avatar: null}]);
}
});

$.ajax({url:link}) and Jquery UI Droppable

I have a problem.
I drop element into #projectsActive. New element have been created there. Old element have been deleted with fadeOut
But ajax query sometimes isn't running.
What's the reason?
$("#projectsActive").droppable({
drop: function (event, elem)
{
var e = elem.draggable;
var linkToSend = "/Projects/Publish/" + $(e).attr("projectid");
$.ajax({ url: linkToSend });
var projectid = $(e).attr("projectid");
var innerText = "";
if ($(e).find("a").length > 0)
{
innerText = $(e).children("a").html();
}
else
{
innerText = $(e).html();
}
var newObject = '<li class="project dragg" projectid="' + projectid + '">' + innerText + '</li>';
$(e).fadeOut("fast", function ()
{
$("#projectsActive").append(newObject);
$(this).remove();
BindDrags();
});
}
});

Resources