I've been trying for the last few days to make my code work, but I just can't find the problem.
I want to make communication with the Wikipedia server and get their JSON API so I can make a list of items corresponding to the input value of searchInput.
I've been looking into JSONP, finding in the end that I can add "&callback=?" to my API request and that it should work.
Now, even though I've added it, the communication still isn't happening.
I've noticed that the console on codepen.io returns "untitled" for a moment while initializing the code after processing the "#searchInput" input.
Perhaps the problem is in my for...in loop.
Do you have any idea what I should do?
The link to my code: http://codepen.io/nedsalk/pen/zqbqgW?editors=1010
(JQuery is already enabled in the "settings" menu)
If you prefer the .html edition of the code:
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="UTF-8">
<title> Object Oriented JavaScript </title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"> </script>
</head>
<body>
<h1> Wikipedia viewer </h1>
Go random!
<form>
<input type="text" name="searchInput" id="searchInput" placeholder="Search Wikipedia"
onkeydown = "if (event.keyCode == 13)
document.getElementById('submit-button').click()"/>
<input type="submit" id="submit-button"/>
</form>
<div id="list"></div>
<script>
$(document).ready(function() {
$("#submit-button").on("click",function (){
var input=$("#searchInput").val();
$.getJSON('https://en.wikipedia.org/w/api.php?action=query&generator=search&gsrsearch=' + encodeURIComponent(input) + '&prop=extracts&exlimit=10&exintro&exsentences=2&format=json&callback=?',
function(API){
$("#list").empty();
for (var id in API.query.pages)
{if(API.query.pages.hasOwnProperty(id){
$("#list").html('<a target="_blank" href="http://en.wikipedia.org/?curid=' + id + '">'
+'<div id="searchList">'
+ "<h2>" + id.title + "</h2>"
+ "<br>"
+ "<h3>" + id.extract + "</h3>"
+ "</div></a><br>")
}}
})
})
})
</script>
</body>
</html>
You have several issues in your code:
you should hook to the submit event of the form, not the click of the button, and use event.preventDefault() to stop the submission.
you loop through the keys of the returned object and attempt to access properties of those strings, instead of using the keys to access the underlying properties.
you set the html() in each loop, so only the final item will be visible. You should use append() instead.
Try this:
$("form").on("submit", function(e) {
e.preventDefault();
var input = $("#searchInput").val();
$.getJSON('https://en.wikipedia.org/w/api.php?action=query&generator=search&gsrsearch=' + encodeURIComponent(input) + '&prop=extracts&exlimit=10&exintro&exsentences=2&format=json&callback=?', function(response) {
var pages = response.query.pages;
$("#list").empty();
for (var id in pages) {
$("#list").append('<a target="_blank" href="http://en.wikipedia.org/?curid=' + id + '">' +
'<div id="searchList">' +
"<h2>" + pages[id].title + "</h2>" +
"<br>" +
"<h3>" + pages[id].extract + "</h3>" +
"</div></a><br>")
}
});
});
Working example
Related
Following the Reuters Ajax Solr tutorial I'm having an issue getting a fields length.
The issue is with the 'template' but I believe it may stem from another js file.
THE TUTORIALS 'TEMPLATE'
template: function (doc) {
var snippet = '';
if (doc.text.length > 300) {
snippet += doc.dateline + ' ' + doc.text.substring(0, 300);
snippet += '<span style="display:none;">' + doc.text.substring(300);
snippet += '</span> more';
}
else {
snippet += doc.dateline + ' ' + doc.text;
}
var output = '<div><h2>' + doc.title + '</h2>';
output += '<p id="links_' + doc.id + '" class="links"></p>';
output += '<p>' + snippet + '</p></div>';
return output;
},
MY 'TEMPLATE'
template: function (doc) {
var snippet = '';
if (doc.Solution.length > 200) {
snippet += doc.Solution.substring(0, 200) + ' ' + doc.date;
snippet += '<span style="display:none;">' + doc.Solution.substring(200);
snippet += '</span> more';
}
else {
snippet += doc.Solution.length + '<br>' + doc.date + '';
}
var output = '<div><br><b>' + doc.Problem + '</b><br>';
output += '' + snippet + '';
output += ' ID #' + doc.id + '</div>';
return output;
},
This section is supposed to allow for a 'more' button if a field is over a certain length. With my template, this is my output:
My 'Solution' field is a long text field which in my schema for solr (7.5) is defined as text_general.
I have tried String() and .toString but those gave me issues as well.
I'm very new to CS as a whole but it seems that my field is behaving as an array or boolean?
In the tutorial they have an older version of solr but the field they get the length on is text_general as well. I'm not exactly sure where I should look next.
PS: this is how the code is structured in the tutorial, a friend of mine was confused because it doesn't all seem to be best practices.
I my setup differs from the tutorial in a few ways, I use my version of JQuery (v3.3.1) and they use some style sheets that I do not.
The <head> of my html doc:
<title>Testing Solr</title>
<meta charset="UTF-8">
<!--style sheets and links in tutorial source code--
<link rel="stylesheet" href="reuters.css">
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.24/jquery-ui.min.js"></script>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.24/themes/smoothness/jquery-ui.css">
<!--my downloaded copy of jquery-->
<script src="script/jquery.js"></script>
<!-- mentioned in tutorial -->
<script src="script/our.js"></script>
<script src="script/Core.js"></script>
<script src="script/AbstractManager.js"></script>
<script src="script/Manager.jquery.js"></script>
<script src="script/Parameter.js"></script>
<script src="script/ParameterStore.js"></script>
<script src="script/AbstractWidget.js"></script>
<script src="script/ResultWidget.js"></script>
Switched to using their links other than the reuters.css, still displaying 1.
Using console.log(doc.Solution); this is indeed acting as an array.
["solution to unlock "]
0: "solution to unlock "
length: 1
__proto__: Array(0)
Adding console.log(doc.text); to the tutorial's ResultWidget.js returns plain text to the console. Whats a likely reason my field is being read as an array when theirs is read as a string?
I'm trying to dynamically generate a form after an ajax request. Below is the relevant code sample :
for (var i in response.responseJSON[0].fields) {
var field = response.responseJSON[0].fields[i];
$('#properties_form').append('<label for=' + i + '>' + i + '</label>' +
'<input id=' + i + ' value=' + field + '>');
}
My problem is that, when var i and var field are strings with blank spaces like "Hello world", my label and inputs will be like <label id="Hello" world=""> and <input value="Hello" world="">. However, the label text will be displayed correctly i.e. <label>Hello world</label>.
I've no idea what kind of sorcery that is, but I'll be very grateful for any help. Thanks in advance.
There's a much more robust way of doing this.
for (var i in response.responseJSON[0].fields) {
var field = response.responseJSON[0].fields[i];
$('#properties_form')
.append($('<label>').attr('for', i).text(i))
.append($('<input>').attr('id', i).val(field));
}
You won't have to worry about the content of the strings as jQuery and the DOM will handle it for you. Not to mention this is much easier to read.
Use " to enclose the attributes.
$('#properties_form')
.append('<label for="' + i + '">' + i + '</label>' +
'<input id="' + i + '" value="' + field + '">');
EDIT
This will break for the cases where the value for i is something like This "works". Best solution is to append as jQuery or JS objects rather than using HTML string just like Daniel's answer.
Following snippet contains the correct fix for this. Updated based on the answer from Daniel.
i = 'Hello "World"';
field = 'Hello "World"s';
$('#properties_form')
.append($('<label>').attr('for', i).text(i))
.append($('<input>').attr('id', i).val(field));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="properties_form"></div>
I have a problem(or problems) with my code, when I'm trying running the script in the developer kit trows the error
unexpected token u in JSON at position 0...
funciones.js
$(document).ready(function (){
$("#btn1").click(function(){
$.ajaxSetup({ cache: false });
var url = "productos.json";
var myData = JSON.parse(JSON.stringify(url.responseText || null, function(data){
for (var team in data) {
var html = []; //variable html
html = '<div class="item"><b>Nombre: </b>' + data[team].producto.nombre + '<br/>[\n]';
html += '<b>Precio: $</b>' +data[team].producto.precio + '<br/>';//precio
html += '<b>Marca: </b>' +data[team].producto.marca + '<br/>';
html += '<b>Presentación: </b>' + data[team].producto.presentacion + '<br/>';
html += '<b>Contenido: </b>' + data[team].producto.contenido + '<br/></div>';
$("#div1").append(html);
}
}));
});
});
function block(){
document.getElementById("btn1").disabled = true;
}
productos.json
[
{
"nombre":"Coca-Cola",
"precio":30,
"marca": "Cocacola",
"presentacion":"Familiar grande",
"contenido":"3Lt."
},
{
"nombre":"Coca-Cola",
"precio":25,
"marca": "Cocacola",
"presentacion":"Familiar",
"contenido":"2.5Lt."
},
{
"nombre":"Coca-Cola",
"precio":15,
"marca": "Cocacola",
"presentacion":"individual",
"contenido":"1Lt."
}
]
HTML
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.6.1.min.js"></script>
<script src="funciones.js" language="javascript" type="text/javascript"></script>
<script type="text/javascript" src="productos.json"></script>
<meta charset="utf-8">
<title>jQuery Ajax</title>
<link rel="stylesheet" href="stilo.css">
</head>
<body>
<div>
<div>Prueba basica de archivos</div>
<div id="div1"></div>
<button id="btn1" onclick="block()" type="button">Team location</button>
</div>
</body>
</html>
What is the problem here?Thanks in advance
There are several problems in your code. I have modified your code into a plunkr here You should visit the working plnkr to find what was corrected however I will put some snippets here also.
The line below does not do anything.
var myData = JSON.parse(JSON.stringify(url.responseText || null, function(data){
The actual ajax call was missing so I added it
$.ajax({
url: url
}).done(function(myData){
//your code here
}
Then the loop
html = 'Nombre: ' + data[team].producto.nombre + '[\n]';
Here data is an array so it needs to be treated as an array. Further each array item itself is producto.
So this is corrected to
for (var i = 0; i < data.length ; i++) {
var producto = data[i];
var html = []; //variable html
html = '<div class="item"><b>Nombre: </b>' + producto.nombre + '<br/>[\n]';
html += '<b>Precio: $</b>' + producto.precio + '<br/>'; //precio
html += '<b>Marca: </b>' + producto.marca + '<br/>';
html += '<b>Presentación: </b>' + producto.presentacion + '<br/>';
html += '<b>Contenido: </b>' + producto.contenido + '<br/></div>';
$("#div1").append(html);
}
There are several issues:
url.responseText is undefined, and so the error complains on the first character of that, i.e. the u of undefined. Look at how you defined url and notice how that does no have responseText.
There is no Ajax call in your code. Use $.getJSON for this.
Do not use JSON.parse nor JSON.stringify: they only make things worse. jQuery will have done the conversion for you already.
If html is supposed to be a string, then don't initialise it as an array with [].
the onclick attribute references a function block that is not in the global scope.
Either add a click handler via code, or via the onclick attribute, but not both. So combine the code in one single click handler via one method.
The property producto does not exist in your JSON, so all the references to it will fail. Remove that property from your code, unless your JSON is different from what you have in the question
Other remarks:
You mix jQuery and non-jQuery syntax. When you have jQuery, use it. So not document.getElementById().
[\n] is a strange thing to output. I would remove that.
The loop for (var team in data) can be written with of instead of in, that way team will be the object, not the index, which makes the rest of your code simpler.
A button element doesn't need a type="button" attribute
Here is code that corrects all these issues:
HTML:
<div>
<div>Prueba basica de archivos</div>
<div id="div1"></div>
<button id="btn1">Team location</button>
</div>
JavaScript:
$(document).ready(function (){
$("#btn1").click(function(){
$(this).disabled = true;
$.ajaxSetup({ cache: false });
$.getJSON("productos.json").done(function(data) {
for (var team of data) {
$("#div1").append(
$('<div>').addClass('item').append([
$('<b>').text('Nombre'), team.nombre, $('<br>'),
$('<b>').text('Precio: $'), team.precio, $('<br>'),
$('<b>').text('Marca: '), team.marca, $('<br>'),
$('<b>').text('Presentación: '), team.presentacion, $('<br>'),
$('<b>').text('Contenido: '), team.contenido, $('<br/>')
])
);
}
});
});
});
I'm trying to devise a method of when adding a simple div element with a class and some data-* in it, it will replace it or add into it some other elements. This method should not be called manually, but automatically by some kind of .live() jQuery method, a custom event or some kind like $('body').bind('create.custom'), etc.
I need it this way since I wouldn't know in advance what elements will be created since they will be served through ajax like single empty div's or p's .
<!DOCTYPE html>
<html>
<head>
<title >on create</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js" ></script>
<script type="text/javascript" >
jQuery(function($){
$("div.fancyInput").each(function(index,element){
var $div = $(this);
var dataId = $div.attr("data-input-id");
var inputId = '';
var labelId = '';
if(!!dataId){
inputId = 'id="' + dataId + '"';
labelId = 'id="' + dataId + 'Label"';
} // if
var dataValue = $div.attr();
$(
'<p class="fancyInput" >' +
' <label ' + labelId + ' for="' + inputId + '" >A fancy input</label>' +
' <input ' + inputId + ' name="' + inputId + '" value="A fancy input" />' +
'</p>'
).appendTo($div);
}); // .each()
}); // jQuery()
</script>
<script type="text/javascript" >
jQuery(function($){
var counter = 2;
var $form = $('#form');
$('#add').click(function(event){
$('<div class="fancyInput" data-input-id="fancyInput' + counter + '" ></div>').appendTo($form);
counter++;
}); // .click
}); // jQuery()
</script>
</head>
<body>
<a id="add" href="#" > add another one </a>
<form id="form" action="#" >
<p class="normalInput" >
<label id="normalInputLabel" for="normalInput" >A normal input</label>
<input id="normalInput" name="normalInput" value="A normal input" />
</p>
<div class="fancyInput" ></div>
</form>
</body>
</html>
Update:
I checked liveQuery beforehand, it's that kind of functionality that I need, but with the ability to modify DOM elements while the event callback is executed. So it's not just that I need events attached, but the ability to modify the DOM upon element creation. For example: whenever a new is created, it should be filled in (even better if replaced) with the p, label and input tags
You could use a DOM Level 3 Event, like DOMNodeInserted. This could look like:
$(document).bind('DOMNodeInserted', function(event) {
// A new node was inserted into the DOM
// event.target is a reference to the newly inserted node
});
As an alternative, you might checkout the .liveQueryhelp jQuery plugin.
update
In referrence to your comment, have a look at http://www.quirksmode.org/dom/events/index.html, only browser which do not support it are the Internet Explorers of this this world (I guess IE9 does at least).
I can't say much about the performance, but it should perform fairly well.
I am not sure why this works but not when I pass in numbers
<form id="form1" runat="server">
<div id="facebookPhotos-iFrameContent">
<div>
<p>Log in</p>
<p id="LoginButtonContainer"><input type="image" id="btnLogin" src="images/loginBtn.jpg" /></p>
<p><select id="facebookAlbumDropdown" /></p>
<div id="facebookPhotosContainer" />
</div>
</div>
</form>
AddDropdownItem("-Select something test-", "-1", "testDropdown");
function AddDropdownItem(sText, sValue, sDropdownID)
{
$("#" + sDropdownID).append("<option value=" + sValue + ">" + sText + "</option>");
}
that works
but this does not:
var id = 104388426283811;
AddDropdownItem("-Select something test-", id.toString(), "testDropdown");
What happens is the default option shows up but then when it tries to add the second option it bombs out with no errors that I can see in the firebug console and then in the end the list goes blank (no options) when my code is done running.
JavaScript will interpret integers as strings where needed, there is no need to use toString().
Try putting the value in single quotes, like this:
function AddDropdownItem(sText, sValue, sDropdownID)
{
$("#" + sDropdownID).append("<option value='" + sValue + "'>" + sText + "</option>");
}
You asked, "Why would that matter." The answer. It is a good practice and it prevents problems when your values start having spaces in them. I ALWAYS put attribute values in quotes.
Now, for your problem... I just tried it with the following code and it works like a charm!
<p><select name="MyTestDropdown" id="testDropdown"></select></p>
<script type="text/javascript">
$(document).ready(function () {
AddDropdownItem("-Select something test-", "-1", "testDropdown");
AddDropdownItem("something else", "1", "testDropdown");
AddDropdownItem("another thing", 2, "testDropdown");
var id = 104388426283811;
AddDropdownItem("test big value", id.toString(), "testDropdown");
AddDropdownItem("Profile Pictures", 100001379631246, "testDropdown");
AddDropdownItem("Test Test2", 104388426283811, "testDropdown");
});
function AddDropdownItem(sText, sValue, sDropdownID)
{
$("#" + sDropdownID).append("<option value='" + sValue + "'>" + sText + "</option>");
}
</script>
Your original code actually works, too. I don't think there was a problem with it. :) Maybe you have a problem elsewhere in your code?
Based on the comment thread in the original question, here's my sample page that incorporates your logic (along with wiring up a button to add options to the select):
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jQuery Test</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js"></script>
<script language="javascript">
$(document).ready(function() {
$("#btnClick").click(function(e) {
e.preventDefault();
var id = 104388426283811;
AddDropdownItem("-Select something test-", id.toString(), "testDropdown");
//AddDropdownItem("-Select something test-", "-1", "testDropdown");
});
});
function AddDropdownItem(sText, sValue, sDropdownID)
{
$("#" + sDropdownID).append("<option value='" + sValue + "'>" + sText + "</option>");
}
</script>
</head>
<body>
<input id='btnClick' type='submit' value='click'></input>
<p><select name="MyTestDropdown" id="testDropdown"></select></p>
</body>
</html>
I don't have the iframes that you mentioned, but I'm using an input submit element to add items in. I'm preventing the default behavior of a submit button by calling e.preventDefault();, which then prevents the post back. I'm then able to add items to the select element.
I hope this helps.