I'm trying to edit a page on Knack that allows JS modifications in combination with CSS formatting. The change I made was to lock the header on each page that uses an excel format. This seems to break when the user changes the number of rows in a drop down selection or navigates to the next page.
I'm sure there are a few ways to do this but I thought the easiest way to manage this would be to look at the first row's style and refresh the page if the minimum width is less than the desired length. Something like if the first entry in the header is not XXX amount of pixels, reload page using window.location.reload(); or similar.
Here is an example of the JS:
$( document ).on ('knack-page-render.any', (function(event, view, data) {
var $table = $('#view_60 > table');
var $bodyCells = $table.find('tbody tr:first').children();
var newWidths = [];
var colWidth = $bodyCells.map(function(index, val) {
/* Debug message*/
//console.log("Index: " + index + ". Value=" + $(this).width());
return $(this).width();
}).get();
var $headerCells = $table.find('thead tr').children();
//Evaluate new max width
$table.find('thead tr').children().each(function(i){
var headerWidth = $(this).width();
var bodyRowWidth = colWidth[i];
var newWidth = headerWidth;
if (bodyRowWidth > newWidth){
newWidth = bodyRowWidth;
}
newWidth++;
$(this).css("min-width", newWidth + "px");
newWidths[i] = newWidth;
/* Debug message*/
// console.log("Cell: " + i + ", header width=", headerWidth + ", bodyRowWidth=" + bodyRowWidth + ", idealWidth=" + newWidth + " Classes: " + $(this).attr('class'));
});
// Set new widths everywhere
$table.find('tbody tr:first').children().each(function(i){
//console.log("Setting new width to " + newWidths[i]);
$(this).css("min-width", ( newWidths[i]) + "px");
});
}));
Here is the associated CSS:
#view_52 table {border-collapse: collapse;}
#view_52 thead {display:block; padding: 2px; margin: 0px;}
#view_52 tbody {display:block; overflow:auto; width 100%; margin: 0px; height:500px; padding:2px;}
Change 'knack-page-render.any' to 'knack-view-render.any'
Related
I'm trying to write a simple script that looks at the active InDesign file and reports the page width and height. However, I have a multiple page document, and not all pages are the same size. So I cannot use the document page sizes. How do I read the individual page sizes?
here is my starting code:
#target "InDesign"
var doc=app.activeDocument;
// set in inches
doc.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.inches;
doc.viewPreferences.verticalMeasurementUnits = MeasurementUnits.inches;
for(var j =0;j<doc.pages.length;j++)
{
// gather data
var pageW=doc.documentPreferences.pageWidth;
var pageH=doc.documentPreferences.pageHeight;
// display
//$.writeln("w: " + pageW + " h: " + pageH );
$.writeln(doc.pages[j].name);
$.writeln(doc.pages[j].properties);
}
Strike that. Found it.
#target "InDesign"
var doc=app.activeDocument;
// set in inches
doc.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.inches;
doc.viewPreferences.verticalMeasurementUnits = MeasurementUnits.inches;
for(var j =0;j<doc.pages.length;j++)
{
// gather data
var pageW=doc.documentPreferences.pageWidth;
var pageH=doc.documentPreferences.pageHeight;
// display
//$.writeln("w: " + pageW + " h: " + pageH );
$.writeln(doc.pages[j].name);
$.writeln("Page Width : " + doc.pages[j].bounds[3] + "\rPage Height : " + doc.pages[j].bounds[2] );
}
Just a followup. The above answer only works if there is no content in your slug area. The following is a better answer.
#target "InDesign"
var doc=app.activeDocument;
// set in inches
doc.viewPreferences.horizontalMeasurementUnits = MeasurementUnits.inches;
doc.viewPreferences.verticalMeasurementUnits = MeasurementUnits.inches;
$.writeln(doc.pages.item(0).marginPreferences.top);
for(var j =0;j<doc.pages.length;j++)
{
// gather data
var pageW=doc.documentPreferences.pageWidth;
var pageH=doc.documentPreferences.pageHeight;
// write data
$.writeln("Page : " + doc.pages[j].name);
$.writeln(" Page Width : " + (doc.pages[j].bounds[3]-doc.pages[j].bounds[1]) + "\r Page Height : " + (doc.pages[j].bounds[2] - doc.pages[j].bounds[0] ));
}
I have this function to print the image dimensions of all <img> having the attribute [proto].
When I try the function with this each method, it only returns a function.
What is the mistake?
function size(){
var $img = $('img[proto]');
$($img).each(function(){
var height = $(this).height;
var width = $(this).width;
$(this).parent().find('p').remove();
$(this).parent().append('<p class="size">' + width + '-' + height + '</p>');
});
}
size();
These are functions not properties, height and width:
var height = $(this).height();
var width = $(this).width();
Change you elements declartion. Because you do it like this: $($('img[proto]')). This way you cast your elements two time into jQuery.
width and height are functions, not properties. So you need to add brackets.
function size() {
$('img[proto]').each(function() {
var height = $(this).height(),
width = $(this).width();
$(this).parent().find('p').remove();
$(this).parent().append('<p class="size">' + width + '-' + height + '</p>');
});
}
size();
I would even prefer to only get the elements you needed once. The way you did it casts this four times into an jQuery object and search two times for the parent. The performance could be saved.
var element = $(this),
parent = element.parent(),
height = element.height(),
width = element.width();
parent.find('p').remove();
parent.append('<p class="size">' + width + '-' + height + '</p>');
And if you want to execute the function directly, you can use an IIFE or just remove the function around and execute it directly.
(function() {
$('img[proto]').each(function() {
// ...
});
})();
So I have a several tables with several rows and columns. Since the information is huge I want to keep the table headers fixed on top when scrolling.
When the one header comes, the previous one will hide and the current one will stay fixed.
This is the js code I have so far:
function makeTableHeadersSticky(tableId) {
var thArr = $(tableId + " th");
var thWidthsArr = [];
var calcWidth = 0;
$(tableId + " th").each(function(){
calcWidth = $(this).css("width");
thWidthsArr.push(calcWidth);
});
var pos = $(tableId).offset();
var thTop = pos.top + "px";
var count = 0;
$(tableId + " tr:first-child > th").each(function(){
$(this).css("width", thWidthsArr[count]);
count++;
});
count = 0;
$(tableId + " tr:last-child > td").each(function(){
$(this).css("width", thWidthsArr[count]);
count++;
});
$(window).scroll(function() {
//var firstRow = $(tableId + " tr:first-child").offset();
var lastRow = $(tableId + " tr:last-child").offset();
var w = $(window);
//console.log("(first,last): ("+(firstRow.top-w.scrollTop())+","+(lastRow.top-w.scrollTop())+")");
if(($(window).scrollTop() > pos.top) && (lastRow.top-w.scrollTop() >= 0)) {
$(tableId + " tr:first-child").css("position", "fixed");
$(tableId + " tr:first-child").css("top", "0px");
$(tableId + " tr:first-child").css("left", "9px");
} else {
$(tableId + " tr:first-child").css("position", "static");
$(tableId + " tr:first-child").css("top", thTop);
}
});
}
makeTableHeadersSticky("#myTable");
If you see on my code I played with the positions of the table and the last row of the table to see where the table is. This way I can set the header position as fixed or static.
Here is my jsfiddle
Everything works just fine here. You just omitted to call the makeTableHeadersSticky function for the second table :
makeTableHeadersSticky("#myTable2");
demo
I have a simple question. I have this function:
function buildGallery(assets) {
var $target = $("#assets");
var containerWidth = $target.width();
var overallWidth = 0;
var items = "";
$.each(assets, function (i, asset) {
var percent = 300 / asset.Metadata.ImageHeight;
var width = percent * asset.Metadata.ImageWidth;
var item = "<img src=\"" + asset.ThumbNail + "\" />";
overallWidth += width;
items += item;
if (overallWidth >= containerWidth) {
var $items = $(items);
var padding = overallWidth - containerWidth;
var counter = $items.find("img").length;
var p = padding / counter;
$items.each(function (n, image) {
console.log(image);
var img = "<div style=\"float: left; width: " + p + "px; overflow: auto;\">" + image + "</div>";
$target.append(img);
});
overallWidth = 0; // reset
items = "";
}
});
$target.removeClass("ajax");
}
my problem is that when I try to add the div to my target it just shows [object HTMLDivElement] instead of actually showing the html.
I have seen this before, but whatever I try does not seem to work.
Can someone give me a hand please?
The problem is that you are trying to build the new div element with the image DOM element, rather than its HTML:
var img = "<div style=\"float: left; width: " + p + "px; overflow: auto;\">" + image + "</div>";
// this is a DOM object not a string ^
If you want to use the string form, you need to get the HTML string from the object:
var img = "<div style=\"float: left; width: " + p + "px; overflow: auto;\">" + image.innerHTML + "</div>";
Or you could create a jQuery object of the div and append the image element to it:
var img = $("<div style=\"float: left; width: " + p + "px; overflow: auto;\"></div>").append(image);
Though it might be easier to read if you wrap each of the images in a div in one step and then add all of them to the $target at once:
$items.wrap("<div style=\"float: left; width: " + p + "px; overflow: auto;\"></div>").appendTo($target);
I think that you might have another problem with your code: it looks like the if (overallWidth >= containerWidth) { statement should be outside of the $.each(assets, ...) loop. With it inside, you will be adding each element in the assets list to the DOM length - index times.
I am developing an slideshow application. So I have a checkboxes with the corresponding images. So when the user selects the checkboxes and click continue button, the corresponding images should be retrieved by javascript and set its height and width. If height/width is not specified for a particular image, it will be filled with height="" else it will be filled width the height=valuepx. how do I achieve do this.. I could get the array of images but how do I retrieve the same for height and width of corresponding images. Please help... I am a beginner to JS..
function insert_slide()
{ var height;
var width;
var img=new Array();
var count=0;
var names=document.getElementsByName('image_id');//name of checkboxes
for(i=0;i<names.length;i++)
{
if(names[i].checked)
{count=count+1;
img[i] = "<IMG SRC='" + names[i].value + "'";
if(height != '') {
img[i] += " height='" + height[i] + "'";
}
else{
img[i] += " height='"+""+ "'";
}
if(width != '') {
img[i] += " width='" + width[i] + "'";
}
else{
img[i] += " width='"+""+ "'";
}
}
}
}
You have just declared width/height so their values are undefined.
What do you want to do with width and height and what are their values ?