I’m using the package Cheerio to webscrape from a website (https://www.realmeye.com/items/misc). However, they have made this awkward and I don’t know how to get the values. How would I get the “data alternatives” and then format them so it only says the Server Names.
Here is my code and the website source:
request(options, function(err, resp, html) {
if (!err) {
const $ = cheerio.load(html);
console.log(html);
$('span', '#i3180').each(function() {
var url = $(this).text();
urls.push(url);
})
}
<td><span class="item" data-item="3180" id="i3180"></span></td>
<td></td>
<td><span class="cheapest-server" data-alternatives="[["USWest2 Nexus",100,67,26],["USWest Nexus",100,76,25],["USMidWest2 Nexus",100,71,25],["USSouth2 Nexus",100,50,25],["USWest3 Nexus",100,88,24],["EUSouthWest Nexus",100,70,24],["USMidWest Nexus",100,50,24],["USEast3 Nexus",100,92,16],["EUSouth Nexus",100,63,12],["USNorthWest Nexus",100,60,12],["EUNorth2 Nexus",100,88,11],["EUWest2 Nexus",100,72,9],["USSouthWest Nexus",100,54,9],["USSouth Nexus",100,52,9],["USSouth3 Nexus",100,93,7],["USEast2 Nexus",100,61,3],["AsiaSouthEast Nexus",100,99,0],["USEast Nexus",100,67,0]]">Australia Nexus</span></td>
In Cheerio, you get access to an element's attribute with the attr method:
$('selector').attr('attribute')
The data in data-alternatives is a JSON, so all you need to do is to parse it, but before, replace the " with "
The complete solution would look like this:
let servers = $('.cheapest-server').attr('data-alternatives')
let parsedServers = JSON.parse(servers.replace(/"/g,'"');
There are two options for getting data attributes
Option 1
$('.cheapest-server').attr('data-alternatives')
Option 2
$('.cheapest-server').data('alternatives')
Documentation:
https://cheerio.js.org doesn't have section links but on the frontpage they have two headlines named
.attr( name, value )
.data( name, value )
They refer to the jQuery docs for more examples
https://api.jquery.com/attr/
https://api.jquery.com/data/
Side note: In plain JS you'd write
option 1: document.querySelector(".cheapest-server").attr("data-alternatives")
option 2: document.querySelector(".cheapest-server").dataset.alternatives
I have created a dynamic table. DEMO to my project.
I have placed this dynamic table in the form under a div named 'box'
<div id="box">
</div>.
I am creating dynamic hidden variables table using Jquery which I need to store in DB. This is how I am creating the hash to submit to server.
criteria = $('form_name').serialize(true);
criteria = Object.toJSON(criteria);
// Build the object to store the parameters for the AJAX post request
parameters = {
title : $('report_title').value,
description : $('report_description').value,
criteria : criteria
}
// Make the AJAX post request
new Ajax.Request( URL, {
method: 'post',
parameters: parameters,
onSuccess: function( response ) {
$('messageSpan').innerHTML = response.responseText;
$('spinner').style.display='none';
}
});
I am not able to capture the dynamically created values in the criteria.
How to solve this?
In the dynamically created section, I tried adding a submit button and see if the values can be fetched. I am able to fetch and iterate all the hidden variables.
$('#jquerysaveButton').click(function(){
jsonObj = [];
$("input[id=rubric_cell]").each(function () {
var id = "cell_" + row + "_" + col;
item = {}
item["id"] = id;
item["selected_rubric"] = $(this).val();
jsonObj.push(item);
});
console.log(jsonObj); //I am getting the required values here
});
How to get these values in the criteria = $('form_name').serialize(true);. Am I doing some thing wrong? Please help me. thanks in advance.
DEMO to my project
You need to make sure that your hidden input fields have a name attribute set otherwise $.serialize will not process them.
I'm strugling with a jquery script inside a cshtml page. For short my question is how to use a var inside a # statement in a cshtml page?
below an example of what I'm trying:
<select id="DefaultText">
<option value="-1">-- select --</option>
#foreach( var d in Model.DefaultTexts )
{
<option value="#d.Id" >#d.Name</option>
}
</select>
<script type="text/javascript">
$('#DefaultText').change(function () {
var id = parseInt($('#DefaultText :selected').val());
var text = #Model.DefaultTexts.First( t => t.Id == id );
$('#CustomProductText').val(text);
});
</script>
I can't reach the var id. It's out of scope. I've also tryed it with a for loop and a if statement. But in the if statement I get the same error: out of scope.
The full story is this:
On my page I've a dropdown list. The items to select are short names for default text parts. Based on the id or name, I want to show the default text part in a textbox.
#CustomProductText is my textbox where the content should be placed (code not posted).
I've also tryed it with #: and statement but that did not work.
What am I doing wrong or maybe its not even possible what I'm trying to do.
As an alternative I've added a action to my controller to get the text form there. Below the code:
<script type="text/javascript">
$('#DefaultText').change(function () {
var id = parseInt($('#DefaultText :selected').val());
$.post("Categories/GetDefaultText", { Id: id }, function (data) {
alert(data);
});
//$('#CustomProductText').val(text);
});
</script>
controller code:
[HttpPost]
public ActionResult GetDefaultText(int id)
{
using( var context = new MyContext() )
{
var text = context.DefaultText.First( d => d.Id == id ).Text;
return this.Content( text );
}
}
This doesn't work. The action doesn't get hit in debug mode.
regards,
Daniel
The $.post that is not working for you, you should prefix the url with / sign and it will be hit as expected:
$.post("/Categories/GetDefaultText", { Id: id }, function (data) {
alert(data);
});
As for the razor solution, you can't use javascript variables in the razor code as it's not a scripting language. What razor does is simply rendering the strings (be it html or javascript or anything) into the page.
To do what you want you either need to request the server to pass the text to your page or render all the texts you have in the page and then access this rendered content in your javascript.
I'm completely stumped. Granted, in java script i'm like that kid trying to jam a square peg into a round hole.
My high level objective: The admins want the ability to edit text surrounding some text boxes, as well as the ability to add and remove 'paragraph'. The reporters and users want the values that are in the textboxes to be used in comparisons, etc (which is the original functionality).
My Solution: This project uses a pretty messy value - attribute table (called an EAV?), which now has fields with associated fields and is self referencing. I decided to leverage this to minimize changes to the database, so the admin essentially creates a string, denotes the places a text box belongs using '{}', and assigns a name to the attribute into text boxes that appear directly below the paragraph.
My Problem: Textboxes generate fine, as soon as the admin stops typing the "{}" count is checked client side, and the correct number of textboxes are added/removed in rows below. However, when the "change" mode (and thereby save the new string) I also want to save the attribute names they selected. I can't seem to get the actual value out of the input. The java script below sends null to elementList. Closer inspection indicates that var fieldNames is getting two elements of "undefined" so it makes sense that I'm getting null. Its also apparent that Its hitting something, becuase the number aligns with there being two 'nameField' rows.
DOM (Hemed down to the essentials)
<tr data-editMode="TextMode" data-ordinal="0">
....
<td>
<a class="changeMode">
<tr class="nameField">
<td colspan='4'>
<input type="text" value="Testing">
<tr class="nameField">
....
Javascript
function getAssociatedTr(row) {
var associatedRows = [];
associatedRows.push(row);
row = row.next('tr');
var hasAnother = true;
while (hasAnother == true) {
if (row != null && row.hasClass("nameField")) {
associatedRows.push(row);
row = row.next('tr');
} else {
hasAnother = false;
}
}
return associatedRows;
}
$(".changeMode").live("click", function () {
var options = $(this).data("options");
var theRow = $(this).closest('tr');
var rows = getAssociatedTr(theRow);
var fieldNames = new Array();
rows.splice(0, 1);
for (var index = 0; index < rows.length; index++) {
{
fieldNames.push(rows[index].next('.nameField').val());
}
}
$(".modal-header", c.rowsModal).html("<h3>Changing edit mode" + options.table + "</h3>");
c.rowsModal.modal("show");
$.ajax({
type: "POST",
traditional: true,
data: { "Name": options.table, "Ordinal": options.row, "EditMode": options.editMode, "ElementNames": fieldNames },
url: "/contracts/changeeditmode/" + c.id.val(),
success: function (data) {
theRow.replaceWith(data);
$.validator.unobtrusive.parse("#supplementForm");
c.rowsModal.modal("hide");
for (j = rows.length - 1 ; j >= 0; j--) {
rows[j].remove();
}
}
});
});
Server side
public ActionResult ChangeEditMode(long id, AddTrackedRowViewModel model,
string editMode, List<string> elementNames)
{
}
As a side note, I'm open to constructive criticism on the JavaScript.
EDIT
I have updated the line to
fieldNames.push(rows[index].nextAll('input').first().val());
But still getting undefined.
SOLUTION
fieldNames.push(rows[index].find("input[type=text]").val());
In this line:
fieldNames.push(rows[index].next('.nameField').val());
you are using the selector ".nameField", but this get a "tr" element, if you want the textbox you need this:
fieldNames.push(rows[index].next('.valid').val());
or using other selector that give you the textbox.
I'm using chap links library https://github.com/almende/chap-links-library/tree/master/js/src/network for drawing an area of objects.
I want to be able to use the id that I have set to an object upon click, I have this code
function onselect() {
var sel = network.getSelection();
console.log("selected "+sel[0].row);
}
It works fine, only it retrieves the row number from the dynamically created table. I want to retrieve a value from that row (an object id that I set) but I don't know how to access it.
I have tired things like
sel[0].row.id
sel[0].row.getId()
sel[0].row[0]
But I don't know how they structure the data in their thing...
Anyonw run into this before and solved it?
This is the way I set the data
nodesTable.addRow([45, "myObjectName", "image", "images/container_icons/icon.png"]);
For my app I solved it by creating a parallel array...
//rendera objekt
window.clickHelper = []; //keep track of container id in conjunction with hierarchy-canvas-object's id
var i = 0; //counter for above
Populating it upon every node creation...
nodesTable.addRow([{{ c.id }}, "{{ c.name }}", "image", "{{ asset('images/container_icons/'~c.icon~'.png') }}"]);
clickHelper[i]={{c.id}};
i++;
Then calling in data from that array on my onSelect event...
function onselect() {
//get selected node from network
var sel = network.getSelection();
sel = sel[0].row;
//get path base structure
var path = '{{ path('editGroup') }}';
//fix path with the DB id of the clicked object
path = path+clickHelper[sel];
window.location.href = path;
}
The double {{ }} are TWIG templating for those unfamiliar with that. Mixed javascript and TWIG ServerSide code here, sorry.