How can I select the Nth PreviousSibling in Javascript? - javascript

In Google Tag Manager it's quite easy to use the element, element classes, element parent classes to fire tags. Unfortunately in this case I want to scrape an element which is only available in the same .
So, when people click on the link "delete" (class=deleteItem) I want to scrape the url_product_id (in bold).
I've tried so much but can't figure out how to achieve this. I hope somebody can help me out.
<td align="center">
<span class="selquantity menosdis"></span>
<span class="selquantity plus"></span>
<input class="urlProductId" type="hidden" name="url_product_id" value="113293">
<input class="urlQuantity" type="text" name="url_quantity" value="1" readonly="readonly">
<br>
<a style="cursor: pointer" class="deleteItem">delete</a>
</td>

Assuming you are wanting to accomplish this within an event handler, you could use parentNode and querySelector to accomplish your goal:
var myClickHandler = function(event) {
var productId = event.target.parentNode.querySelector('. urlProductId').value;
// do stuff with productId
}
Or with jQuery:
$('.deleteItem').on('click', function() {
var productId = $(this).prev('.urlProductId').val();
});

This is similar to Rob's answer, but also takes into account if code is moved around into additional divs, etc.. Since people update their UI all the time. This should be more sustainable as the product matures. Of course you'll want to watch the .closest() call if you ever change to something like BootStrap data tables.
$(".deleteItem").on("click", function() {
var getClosestProdID = $(event.target).closest('td').find('.urlProductId');
// Just for display of the value
alert("Our closest selected value is: " + getClosestProdID.val());
});
JS Fiddle

Here is a jQuery method (modify and test on your own), and you could do this in a GTM Custom Javascript variable:
function(){
var ce = {{Click Element}}; // get the clicked element
if ($(ce).length > 0){
return $(ce).closest('td').find('.urlProductId').attr('name');
}
return undefined;
}
The premise here being that your elements are all nested under the <td> element, and all you're doing is taking the clicked element and scraping for the element you're interested in.

Related

Remove any specific html code using javascript

In the past I used Google Developer Console to delete some specific divs on a page. I could do it manually of course but in some cases where the divs where many I had to use the console. I had a single line code that did the job (I found it while searching the internet) but I lost my note.
So how can I delete using javascript any html code (by copy pasting the code).
Something like:
elements = $('<div ... </div>');
elements.remove();
OR
$('<div ... </div>').remove();
Any ideas? I am not an expert in javascript (obviously) and I've been searching stackoverflow for hours without finding anything that works.
UPDATE: I think some people might get confused with my question. Google developer console accepts javascript command lines. So even though I ask for javascript I will use the code on the google developer console.
UPDATE 2 :
Here is an example of a div I need to delete. Keep in mind I want to copy paste the entire code in the javascript code. Not just identify the div.
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
It's the data-entry-status="declined" that makes that div unique so I can't just identify the div using an id selector or a class selector. I need to put the entrire thing there and remove it.
I tried:
$('<div class="entry-status-overlay" data-entry-status="declined"><div class="entry-status-overlay__inner"><span class="entry-status-overlay__title">Declined</span></div></div>').remove();
It didn't remove the div.
Try to search the dom by its outerHTML.
function deleteDomByHtml(html){
html=html.replace(/\s/g,'');
$("*").each(function(){
if(this.outerHTML.replace(/\s/g,'')===html){
$(this).remove();
}
});
}
And try this line on this page:
deleteDomByHtml(`<span class="-img _glyph">Stack Overflow</span>`);
You cannot do by simply pasting the code. That will remove all the div element.
You may need a specific selector like id,class or child to specific parent to remove the element from the dom.
Consider this case the divs have common class but the data-entry-status is different. So you can get the dom using a selector and then check the dataset property.
For demo I have put it inside setTimeout to show the difference. In application you can avoid it
setTimeout(function() {
document.querySelectorAll('.entry-status-overlay').forEach(function(item) {
let getStatus = item.dataset.entryStatus;
if (getStatus === 'declined') {
item.remove()
}
})
}, 2000)
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
<div class="entry-status-overlay" data-entry-status="accepted">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">accepted</span>
</div>
</div>
Just add any attribute with [] and it will remove the element.
$('[class="entry-status-overlay"]').remove();
/*OR*/
$('[data-entry-status="declined"]').remove();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
function del(){
var h = document.body.outerHTML;
h = h.match('<div>...</div>');
h.length--;
return h;
}
I guess this will work just give it a try... i tried on browser console and it worked, this way you can match the exact you want.
I might as well add my take on this. Try running this in your console and see the question vanish.
// convert the whole page into string
let thePage = document.body.innerHTML,
string = [].map.call( thePage, function(node){
return node.textContent || node.innerText || "";
}).join("");
// I get some string. in this scenario the Question or you can set one yourself
let replacableCode = document.getElementsByClassName('post-layout')[0].innerHTML,
string2 = [].map.call( replacableCode, function(node){
return node.textContent || node.innerText || "";
}).join("");
// replace whole page with the removed innerHTML string with blank
document.body.innerHTML = thePage.replace(replacableCode,'');
If you want to identify divs with that particular data attribute, you can use a data-attribute selector. In the example below, I've used a button and click event to make the demo more visual, but in the console the only line you'd need would be:
$('div[data-entry-status="declined"]').remove();
$(function() {
$("#testbutton").click(function() {
$('div[data-entry-status="declined"]').remove();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="entry-status-overlay" data-entry-status="declined">
<div class="entry-status-overlay__inner">
<span class="entry-status-overlay__title">Declined</span>
</div>
</div>
<div id="x">Some other div</div>
<button type="button" id="testbutton">Click me to test removing the div</button>
See https://api.jquery.com/category/selectors/attribute-selectors/ for documentation of attribute selectors.
P.S. Your idea to paste some raw HTML into the jQuery constructor and then execute "remove" on it cannot work - you're telling jQuery to create an object based on a HTML string, which is, as far as it's concerned, a new set of HTML. It does not try to match that to something existing on the page, even if that exact HTML is in the DOM somewhere, it pays it no attention. It treats what you just gave it as being totally independent. So then when you run .remove() on that new HTML...that HTML was never added to the page, so it cannot be removed. Therefore .remove() has no effect in that situation.

Is it possible to write a js variable into plain html?

I am counting my user specificated and dynamically appearing divs...
My situation:
<div class="grid-stack" data-bind="foreach: {data: widgets, afterRender: afterAddWidget}">
<div id="streamcontainer1" class="streamcontainer grid-stack-item" data-bind="attr: {'data-gs-x': $data.x, 'data-gs-y': $data.y, 'data-gs-width': $data.width, 'data-gs-height': $data.height, 'data-gs-auto-position': $data.auto_position}">
</div>
</div>
In PHP i can simply write my COUNT variable inside the html. That would look something like this:
<div id="streamcontainer<?php echo $count ?>" class="" ... and so on...>
How can i archive the same with JS/Jquery?
It's a DOM manipulation question. What do we have to work with? We're adding divs to the page, they have a particular class, and we want to give them an ID.
function assignIds(){
var list = document.getElementsByClassName('streamcontainer');
for(var i=0; i<list.length;i++){
if(list[i].id == undefined) // skip the ones that have already been done.
list[i].id = 'streamContainer' + i.toString();
}
}
Now we just have to run that function on some event so it will keep updating. If you just want to do it on an interval, that's simplest. (setInterval) But that could give you a bug, where there's a small amount of time where that ID hasn't been assigned yet. You could try listening to whatever AJAX/websocket process is streaming these things onto the page.
We'd need to know a bit more about your use case to know which event to attach it to.
Without a Javascript Reactive Framework (Vue.js, React, AngularJS) you can't do this.
What you can do with JS is set a content in element when DOM is loaded, example:
document.getElementById("myElement").textContent = "Hello World!";
Or
document.getElementById("myElement").innerHTML = "<span>Hello World!</span>";
OBS: .innerHTML can insert HTML tags and .textContent just insert texts.
You can make use of the text bindings in knockoutjs to display the javascript value in the HTML. There are lot of ko bindings which can help you. More reference here
var viewModel = {
javascriptVariable: "I am javascript string"
};
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<span data-bind="text: javascriptVariable"></span>

Add to favorites, jquery

I am creating a 'favorites' style system for a property webiste where users can save a property to be viewed later. The system works using Jquery so the page doesn't have to refresh. The details page of a property contains a 'add to favorites button' and this works fine:
$("#addFavorites").click(function() {
var locationID = $("#locationID").val();
But how would I code this when all of the properties are listed together on one page, each 'add to favorites' button would have to use a unique id or something but not sure how to approach this.
Well the most precise way would be a default HTML-Formular. I'll make it a short one:
<form ...>
<label for="fav1">Fav1</label>
<input type="checkbox" name="favorites[]" id="fav1" value="1" />
<label for="fav2">Fav2</label>
<input type="checkbox" name="favorites[]" id="fav2" value="2" />
<submit>
</form>
Now that's the ugly form, you can make this beautiful with CSS. With jQuery you now always submit the form when the user checks any of the checkboxes, like:
$('input[type=checkbox]').change(//do ajax submit);
In the AJAX File you simply read the array:
foreach($_POST['favorites'] as $fav) {
addFavToUser($fav, $user);
}
This is like simply explained to give you an idea, not the whole "clean" solution. But i hope this helps you - if it does, i always appreciate the vote for it ;)
Each of your 'favorites' would need a unique id
...
...
Then..
$('.favorite').click(function(){
$(this).whateveryouwanttodo();
});
$(this) will contain the clicked anchor tag. from that you can get the id, and call your ajax post or whatever you want to do with it.
In jQuery you can use relative positioning to select the item of interest. So, for example, if each item was followed by a favorite button, you can traverse the DOM from the clicked item to find the related item. You can then post this back via AJAX to store it an update the element as needed to reflect the updated status.
HTML (assumes you use styling to show the icon and favorite status)
<span class="normal" data-location="A">Location A</span> <span class="icon-favorite"></span>
JS
$('.favorite').click( function() {
var data = [],
newClass = 'favorite',
oldClass = 'normal',
$this = $(this),
$location = $(this).prev('span');
// if already favorited, reverse the sense of classes
// being applied
if ($location.hasClass('favorite')) {
newClass = 'normal';
oldClass = 'favorite';
}
data['location'] = $location.attr('data-location');
$.post('/toggle_favorite', data, function(result) {
if (result.Success) {
$location.removeClass(oldClass).addClass(newClass);
$this.removeClass('icon-'+newClass).addClass('icon-'+oldClass);
}
else {
alert('could not mark as favorite');
}
},'json');
});

How to make a list in a web page that can be edited without reloading

Here's some low-hanging fruit for those more comfortable with Javascript than I...
I want to improve a Moodle plugin's admin UI. (Moodle is a PHP-based web app). What I need to do is take what is currently a text box, with semi-colon delimited entries and replace that with a editable list.
The HTML elements I would use is a select list, a text input field and another hidden textfield. I guess a couple of submit buttons too, one for adding, and the other for removing of entries.
The behaviour would be:
Entries can be added to the select list from the visible textbox upon some kind of submit (this cannot reload the page).
The hidden textbox would contain all the entries from the select list, just semi-colon delimited
There's a function to remove entries from the select list that also does not reload the page.
The hidden textbox is updated with add/remove actions
This seems to me like something that's easy enough. Though I'm having a hard time finding a close enough example to rip off.
This sample code is as close as I've found thus far. There's got to be some good examples of precisely this sort of thing out there. Any decent pointers will be rewarded with + votes.
What you want to do is use JavaScript and manipulate with the DOM of the webpage. Basically, the HTML of a webpage is parsed and rendered by the browser into a tree of elements. Each HTML tag like <select> is an element in the tree. You use JavaScript to interact with this tree by performing operations like removing elements from this tree or adding elements to this tree. (Note that preforming operations on the tree will not refresh the page.)
The standardized API to do these sorts of manipulation in JavaScript is known as the DOM. However, many people, myself included, think that this API is very clunky and not nearly expressive enough. Doing even trivial things require tons of lines of code. For this reason, many developers do not use the DOM directly instead using more powerful libraries, such as jQuery, to make their lives easier.
Below is an example of some HTML + JavaScript that I think mimics most of your requirements. Ideally for learning purposes, this would be written purely using the standard W3C DOM API, but since your problem is not that trivial, I resorted to using jQuery instead.
The HTML:
<select id="list" multiple="multiple"></select>
<input id="removeButton" type="button" value="Remove"></input>
<div>
<input id="optionAdder" type="text"></input>
<input id="addButton" type="button" value="Add"></input>
</div>
<br>
<input id="clearButton" type="button" value="Clear All"></input>
<div>Not So Hidden: <input id="hidden" type="text"></input></div>
The JavaScript:
// Uses jQuery to define an on document ready call back function
$(function(){
// The code in this function runs when the page is loaded
var options = []; // contains all the options
// add new option to drop-down
var addOption = function(optText) {
// Create new option element and add it to the <select> tag
$('<option></option>')
.attr('value', optText).text(optText)
.appendTo( $('#list') );
};
// writes the names of all the options in the "hidden" text box
var fillHidden = function() {
$('#hidden').val('');
var hiddenText = "";
for(var i=0; i< options.length; i++) {
if(hiddenText) {
hiddenText += "; ";
}
hiddenText += options[i];
}
$('#hidden').val(hiddenText);
}
// Bind the click event of the "Add" button to add an option on click
$('#addButton')
.click(function(){
var optText = $('#optionAdder').val();
if(optText) {
addOption(optText);
}
$('#optionAdder').val('');
options.push(optText);
fillHidden();
});
// Bind the click event of the "Remove" button to remove the selected options on click
$('#removeButton')
.click(function(){
$('#list option:selected').each(function(){
var optIndex = $.inArray($(this).val(), options);
if(optIndex > -1) {
options.splice(optIndex, 1);
$(this).remove();
}
fillHidden();
});
});
// Bind the click event of the "Clear" button to clear all options on click
$('#clearButton')
.click(function(){
$('#list').children().remove();
options = [];
fillHidden();
});
});
Here is a jsfiddle demonstrating the code

How do I get the cell value from a table using JavaScript?

<td> <input type="button" name="buton" id="x2" value="2" onclick="swap(id)";/> </td>
This is the button in a table when it is clicked it's id is passed as parameter to function "swap" as below:
function swap(x)
{
document.write(x);
}
It is successful in getting the id but not the value;when i am trying in this way:
function swap(x)
{
document.write(x.value);
}
The output is shown as undefined. Can you tell me how to get the cell value using the cell id?
I believe that what you are looking for is document.getElementById(x).value;
Also if you want the button just pass this to the function like this:
<button onclick="foo(this)"/>
I guess use jQuery for the purpose,it allows to traverse in DOM very easily.
<table id="mytable">
<tr><th>Customer Id</th><th>Result</th></tr>
<tr><td>123</td><td></td></tr>
<tr><td>456</td><td></td></tr>
<tr><td>789</td><td></td></tr>
</table>
If you can, it might be worth using a class attribute on the TD containing the customer ID so you can write:
$('#mytable tr').each(function() {
var customerId = $(this).find(".customerIDCell").html();
}
Essentially this is the same as the other solutions (possibly because I copypasted), but has the advantage that you won't need to change the structure of your code if you move around the columns, or even put the customer ID into a < span >, provided you keep the class attribute with it.
By the way, I think you could do it in one selector:
$('#mytable .customerIDCell').each(function()
{
alert($(this).html());
});
If that makes things easier
Code will be more or less more reliable on cross bowser issue
z = document.getElementById(id); first, and then you should be able to use z.firstChild.textContent
You need to get the cell using var cell = document.getElementById(x). Then use cell.firstChild.nodeValue.
function swap(x)
{
var cell = document.getElementById(x);
document.write(cell.firstChild.nodeValue);
}
EDIT: Tested this on both FF3.5 and IE8 and it works.
If you are passing the id of the element you might want to use document.getElementById(x) to access it.

Categories