Tabulator Modify Image Path - javascript

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 },

Related

slickgrid - How to loop through rows which are outside canvas?

I am having some markers on map and same number of rows in slickgrid?
What I want is when a marker is clicked the id of marker is matched with all rows and corresponding row should get selected.
Here is my code:
var $canvas = $(grid.getCanvasNode());
var $allRows = $canvas.find('.slick-row');
$($allRows).each(function() {
if ($(this).rowID == selectedMarker) {
$(this).addClass("active-row");
grid.scrollRowIntoView($(this).index());
}
});
It works fine only when the row which I want is present in the grid but the grid DOM contains only 8 rows at a time (The grid has 30 rows).
How can I loop through all data?
You shouldn't be modifying SlickGrid's DOM at all. SlickGrid will overwrite any changes as it's only rendering the rows in view (with some buffer). When you scroll past that buffer any changes you made to the DOM are lost.
You have to change the row's data and allow SlickGrid to add the appropriate classes to the DOM when it's rendering.
Edit:
SlickGrid setup:
dataView.getItemMetadata = metadata(dataView.getItemMetadata);
function metadata(metadataProvider) {
return function(row) {
var item = this.getItem(row),
ret = metadataProvider(row);
if (item && item.isActive) {
ret = ret || {};
ret.cssClasses = (ret.cssClasses || '') + ' active-row';
}
return ret;
};
}
Then when you click on a marker:
var item = dataView.getItemById(selectedMarker);
var row = dataView.getRowById(selectedMarker);
item.isActive = true;
dataView.updateItem(item.id, item);
grid.scrollRowIntoView(row);

Check if contents of a DIV is only an Image

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.

How to set preload images to its corresponding place?

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.

Javascript tolower/ignoreCase in filter

Hi im trying to make a filter for a list of spans im having trouble putting what is in the spans to lower case or ignorecase.
Any ideas?
$("#filterinput2").keyup(function () {
var filter = ($(this).val()).toLowerCase(); // get the value of the input, which we filter on
console.log("lower filter" + filter);
if (filter) {
// hide tr's for songs not matching and show tr's for songs matching
$(".tonelist").find(".song:not(:contains(filter))").parent().parent().parent().fadeOut("slow");
$(".tonelist").find(".song:contains(filter)").parent().parent().parent().fadeIn();
if (window.console != undefined) {
console.log($(".tonelist").find(".song:not(:contains(" + filter + "))").parent().parent().parent().innerHTML);
}
$(".tonelist").find(".grouptitle:not(:contains(" + filter + "))").parent().fadeOut("slow");
$(".tonelist").find(".grouptitle:contains(" + filter + ")").parent().fadeIn();
if (window.console != undefined)
console.log($(".tonelist").find(".grouptitle:not(:contains(" + filter + "))").parent().parent().parent().innerHTML);
} else
// if input field is empty, show all tr's
$(".tonelist").find("tr").fadeIn();
ColorLines();
});
You're going to have to check the contents of each of those spans yourself. You can do that by using the .html() function to get the contents of each song/grouptitle as a string. Something like this might work (although I haven't tested it):
$("#filterinput2").keyup(function () {
var filter = ($(this).val()).toLowerCase(); // get the value of the input, which we filter on
console.log("lower filter" + filter);
if (filter) {
// hide tr's for songs not matching and show tr's for songs matching
spans = $(".tonelist").find(".song, .grouptitle")
for (s in spans) {
el = $(spans[s]);
if ( el.html().match( new RegExp(filter, "i") ) ) {
el.fadeIn();
} else {
el.fadeOut("slow");
}
}
} else
// if input field is empty, show all tr's
$(".tonelist").find("tr").fadeIn();
ColorLines();
});
The reason is that the :contains() css selector is case-sensitive, and there's no way I know of to change that.

Live edit text in an SVG that's embedded in a website

I'm doing some find and replace in embedded SVGs. Part of a web to print service I'm creating.
I have text tags inside the SVG like {name}, {title}, {phone}, etc.
I wrote a script to replace these values and it live updates the embedded SVG. It currently works alright.
It's using the jQuery SVG plugin to load the SVG.
// Callback after loading external document
function loadDone(svg, error) {
svg.configure({viewBox: '0 0 315 180', width: 579, height: 331}, true); //resize the svg. viewBox must be the same size as the initial width defined in the SVG
var textElems = document.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'tspan');
var doc = document.getElementById('svgload').contentDocument;
for (var i = 0; i < textElems.length; i++) {
var id = textElems[i].childNodes[0].nodeValue;
id = id.replace("{",""); //remove brackets {}
id = id.replace("}","");
alert(id);
$("#formContainer").append('<p>' + capitalize(id) + ': <input type="text" id="' + id + '" class="replace" />\n');
$("#formContainer").append('<input type="hidden" id="' + id + 'PrevVal" value="{' + id + '}" /></p>');
}
$('.replace').keyup(function() {
var prevValID = $(this).attr("id") + "PrevVal"; //determine the hidden input id
var oldVal = $("#"+prevValID).val(); //set oldVal to the hidden input value, first time it's {id}
var currentVal = $(this).val(); //set the currentVal to the user inputted value
changeText(oldVal,currentVal); //swap the oldVal with the currentVal
$('#'+prevValID).attr("value",currentVal); //set the hidden input value to the last inputted user value
svg.configure({viewBox: '0 0 315 180', width: 579, height: 331}, true); //"resize" to svg to clear the text. some browsers break the new text until the svg is "zoomed", or in this case, resized
});
function changeText(oldVal,newVal) { //swap the values inside the SVG file
for (var i = 0; i < textElems.length; i++) {
if (textElems[i].childNodes[0].nodeValue == oldVal) {
textElems[i].childNodes[0].nodeValue = newVal;
}
}
}
}
function capitalize(str) { //capitalize first letter of words
var firstLetter = str.slice(0,1);
return firstLetter.toUpperCase() + str.substring(1);
}
There are some bugs though. For example, since I'm creating hidden divs to store the previous value of the SVG text one can create a situation where typing the same thing into two text boxes creates two identical IDs and then further typing updates both text elements in the embedded SVG. It also doesn't like tags that have spaces in them, like {full name} versus {name}.
Any suggestions on how to clean this whole thing up? I know I should be able to detect tags (searching for {}) and then get the text or tspan id associated with them and update the node value that way, however, I've got severe coding block and can't quite start on it!
Managed to trim it down to this:
// Callback after loading external document
function loadDone(svg, error) {
svg.configure({viewBox: '0 0 315 180', width: 579, height: 331}, true); //resize the svg. viewBox must be the same size as the initial width defined in the SVG
var textElems = document.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'tspan');
var doc = document.getElementById('svgload').contentDocument;
for (var i = 0; i < textElems.length; i++) {
var textID = textElems[i].getAttribute('id');
var textValue = textElems[i].childNodes[0].nodeValue;
textValue = textValue.replace("{",""); //remove brackets {}
textValue = textValue.replace("}","");
$("#formContainer").append('<p style="text-transform:capitalize;">' + textValue + ': <input type="text" id="' + textID + '" class="replace" />\n');
}
$('.replace').keyup(function() {
var textToChange = document.getElementById($(this).attr('id'));
textToChange.childNodes[0].nodeValue = $(this).val();
svg.configure({viewBox: '0 0 315 180', width: 579, height: 331}, true); //"resize" to svg to clear the text. some browsers break the new text until the svg is "zoomed", or in this case, resized
});
}
And it's doing exactly what I want.
Hopefully that helps anyone else looking to do text replacements in embedded SVG's :)

Categories

Resources