I met such a problem recently and do not how to figure it out. I have an HTML image table:
The number of table rows will change dynamically without page refresh according to user input
Each row in the table contains one special image in the database
I want to load image for rows that're displayer (many other rows are hidden so I don't want to load image for them)
I found a snippet like the following:
var img = $("<img />").attr('src', 'http://somedomain.com/image.jpg')
.load(function() {
if (!this.complete || typeof this.naturalWidth == "undefined" || this.naturalWidth == 0) {
alert('broken image!');
} else {
$("#something").append(img);
}
});
but the problem is that, on the .load method, the image itself will forget where it should be placed (because I use for loop to load the image row by row in the table)
Is there anybody know how to resolve this issue?
You will need to correlate the image with its row. If you have the row at hand when creating the image, you can use it in the callback to .load. For example, if at some point you have a list of new rows, you can do something like this:
var loadImageForRow = function(row) {
var img = $("<img/>").attr('src', 'my-image-source.png')
.load(function() {
if (!this.complete || typeof this.naturalWidth == 'undefined' || this.naturalWidth == 0) {
// handle broken image
} else {
row.find('.image-cell').append(img);
}
});
});
newRows.each(function() { loadImageForRow($(this)); }
This uses the row parameter from the enclosing closure inside the callback. Alternatively, you can correlate the two using data attributes on the image or on the row (e.g. put something like data-row-index='17' on the img element) or any equivalent mechanism.
Related
I'm trying to append a path to a cell value inside of Tabulator v3.2 ( http://tabulator.info/docs/3.2 ) that gets pulled from a mySQL table and then display that image represented by the full image path in the Tabulator cell. I have this in the attributes for the .tabulator call:
formatter: function(cell, formatterParams) {
var celli=cell.getValue();
if ((celli.indexOf("blankimg") == -1) && (messages["custimgpath"] != "")) {
var cellf = messages["custimgpath"] + celli + ",\"image\""
}
else {
var cellf = celli
}
return cellf;
}
As you can see I tried to set the format to 'image' w/in the function.
The variables in the if statement do resolve to true.
Currently it just enters the full path + formatter in the cell, instead of generating the image tag and putting it in src.
How do I modify it to insert the full path in image tag and also set the formatter to image?
The problem is because you are only returning the string for the path, which is what is displayed.
In order to show an image you need to return an image element with the path set as its source:
formatter: function(cell, formatterParams) {
var celli=cell.getValue();
var imgEl = document.createElement("img"); //create image element
if ((celli.indexOf("blankimg") == -1) && (messages["custimgpath"] != "")) {
imgEl.src = messages["custimgpath"] + celli; //set src of image element
}
else {
imgEl.src = celli; //set src of image element
}
return imgEl; //return image element
}
Mutation Alternative
As an alternative I would suggest using a mutator to update the path value as it come into the table, and then the built in image formatter to display the data.
In the example below i will aassume that the path is contained on the demo field of the row data
we start by defining a mutator
var pathMutator = (value, data, type, mutatorParams, cell){
if ((value.indexOf("blankimg") == -1) && (messages["custimgpath"] != "")) {
return messages["custimgpath"] + value
}
else {
return imgEl.src = value;
}
}
And then in the column definition for that column we bind the mutator and the formatter
{title:"Demo Column", field:"demo", formatter:"image", mutator:pathMutator },
Would anyone be so kind as to advise me how to amend this JavaScript please? I'll admit I don't have much experience working with JavaScript and I've tried myself but ended up a bit lost.
To explain, WooCommerce outputs products on my site in .columns-3 and .columns-4, and assigns .first and .last classes accordingly.
If the site is loaded on mobile, the script below will remove the .first and .last tags, and re-assign them to display the products in two columns.
The script currently only targets .columns-3 within function defaultProductRows and function adjustProductRows. I need to also target .columns 4 within the same script, but I'm not sure how to go about adding it.
<script>
$(window).on('load resize', function (){
var windowWidth = $(window).width();
if(windowWidth < 753){ // this is my screen size break point for the rows
adjustProductRows(); // call the function to adjust add last and first classes
} else {
defaultProductRows(); // else if large screen size then get everything back to defalut
}
});
function defaultProductRows(){
var products = $('ul.products.columns-3 li.type-product');
products.each(function(idx, li) {
var product = $(li);
// remove all classes we added
$('ul.products li.adjusted-row.first').removeClass('adjusted-row first');
$('ul.products li.adjusted-row.last').removeClass('adjusted-row last');
if(idx == 0) { // make sure first li tag gets first class
product.addClass('first');
}
else if((idx+1) % 3 == 0) //this will make sure we have 3 rows by adding last classes after each 3 products
{
product.addClass('last');
}
else if(idx % 3 == 0)
{
product.addClass('first'); // make sure all products divided by 3 will have first class
}
else
{
console.log(idx); // just checking for the index
}
});
}
function adjustProductRows() {
var products = $('ul.products.columns-3 li.type-product');
products.each(function(idx, li) {
var product = $(li);
if(idx % 2 == 0) // we are even
{
product.addClass('adjusted-row first');
product.removeClass('last');
}
else // we are odd
{
product.addClass('adjusted-row last');
product.removeClass('first');
}
});
}</script>
Change your selector to include columns-4
From:
var products = $('ul.products.columns-3 li.type-product');
To:
var products = $('ul.products.columns-3 li.type-product, ul.products.columns-4 li.type-product');
This tells jQuery to select li.type-products that are part of either columns-3 or columns-4
I try to think up function which can replace links to text. Image inside a tag should be moved to the wrapper, the original a should be removed.
JS:
var selectors = 'a.mark-video;a.sp5;a>img[alt!=""]'
selectors = selectors.split(";").join(", ");
$(selectors).each(function() {
var current = this;
if (this.nodeName == "IMG") {
current = this.parentNode;
if (current.nodeName != "A")
current = this.parentNode;
if (current.nodeName != "A")
return false;
current = $(current);
}
var wrapper = current.parent();
var new_context = $().append(current.html());
current.remove();
wrapper.append(new_context);
}
);
The problem is
1) that the image is not inserted into the wrapper
2) if it would be inserted it would not have correct position.
I am experimenting using webextensions API (Firefox addon) and I injected the code to site:
http://zpravy.idnes.cz/zahranicni.aspx
In the debugger you can see two wrappers with class="art ". I have removed the first link but image is not inserted. The second one has not been removed yet when debugger was paused after first iteraction.
I hope you can find out why the image is not appended and how to append it to the original position of the element a. I need to find out position of the element a first, and then to move the image into to correct position - that is before div.art-info.
Note: please do not change the selectors string. This is the users input from form field.
Edit:
Almost there:
function(){
if (this.parentNode.nodeName == "A")
$(this.parentNode).replaceWith($(this));
else
$(this).html().replaceWith($(this)); // error: html() result does not have replaceWith...
}
Is this what you're looking for?
https://jsfiddle.net/4tmz92to/
var images = $('a > img');
$.each(images, function(key, image) {
$(this).parent().replaceWith(image);
});
First select all the images that you want to remove the link from, then loop through them and simply replace the parent() with the image.
I have finally solved the problem:
$(selectors).each(
function(){
if (this.parentNode.nodeName == "A")
$(this.parentNode).replaceWith($(this));
else
$(this).replaceWith(
$(this).html()
);
}
);
This works similar. Novocaine suggested not to use $(this).html() but this would skip some images so I prefer to use it.
I have a div containing initially a loader image tag.
<img src="/images/indicator_big.gif" style="display:block;margin:auto">
I want to check if the DIV contains only the loader image then the function should trigger an Ajax Request.
If i do some thing like div.innerHTML I get it as a string.
What will be the best way to test if the innerHTML is only a loader image?
This method will do what you ask, although I'm not sure the general approach is the best to be honest.
function hasOnlyImg(div) {
if (div.children.length != 1)
return false;
return div.children[0].tagName == "IMG";
}
You can check how many elements are inside your element
var children = document.querySelector("#yourDiv > *");
if (children.length == 1 && children[0].tagName.toLowerCase() == "img") {
//you only have one child in here, and that's an image
}
This will be 1 if it only contains your initial image.
Be wary of the browser support, though: http://www.quirksmode.org/dom/w3c_core.html#t13
I'm assuming your 'style.display' of that loader image will change? You could just check for that?
function checkDiv(div,func) {
var thisDiv = div;
var imgLink = thisDiv.getElementsByTagName("img");
if (imgLink.length == 1 && imgLink[0].style.display !== "block") {
func();
}
}
checkDiv(document.getElementById("mydiv"),function() {
//call ajax code
});
Or if you still would like to check the number of HTML tags within your div, just do something like:
var allDivTags = mydiv.getElementsByTagName("*");
if (allDivTags.length == 1 && allDivTags.nodeName.toLowerCase() == "img") {
//only 1 html element exists in the div, and it's an image.
//run code
}
Hope this helps.
When a user enters a bookmark using form['f3'] (a url and a title) it is immediately entered in via the dom - visually the title and the favicon are seen by the user. Each bookmark is a link and and image under div Bb1c. The insert is done alphabetically. Basically, I need to insert the new image and link after the previous one.
The loop portion was created before I had added in favicons so it loops through all the child elements, but it only needs to loop through the tags. How do I check to make sure that it is an element of type a before doing a compare? My for loop needs an && added to it.
This is rough draft code so if there anything else - contstructive criticism
var a=document.getElementById('Bb1c'),
b=document.createElement('a'),
e=document.createElement('img');
c=document.forms['f3'].elements,
d=a.firstChild,
b.innerHTML=c[1].value;
b.href=c[2].value;
b.name="a1";
b.className="b";
e.src=b.hostname + '/favicon.ico';
e.onerror=function()
{
e.src = 'http://www.archemarks.com/favicon.ico';
}
while(d=d.nextSibling)
{
if(b.innerHTML<d.innerHTML)
{
break;
}
}
a.insertBefore(b,d);
return 1;
}
You want the tagName (or nodeName) property.:
if(ele.id === "foo" && ele.tagName.toLowerCase() === "span") {
// do something
}