Here's my ScrollView:
middle: SC.ScrollView.design({
layout: { top: 36, bottom: 32, left: 0, right: 0 },
backgroundColor: '#ccc',
contentView: SC.ListView.design({
contentBinding: 'Spanish.wordsController.arrangedObjects',
selectionBinding: 'Spanish.wordsController.selection',
contentValueKey: "word",
contentDisplayProperties: 'word english'.w(),
selectOnMouseDown: YES,
exampleView: Spanish.CustomListItemView
})
})
and here is my custom listView row:
Spanish.CustomListItemView = SC.View.extend({
render: function(context, firstTime){
var content = this.get('content');
var word = content.get('word');
var english = content.get('english');
context = context.begin().push(' %# (%#)'.fmt(word,english)).end();
return sc_super();
}
});
The above works as expected, except that I can no longer select views. When I comment out "exampleView: Spanish.CustomListItemView" I can select rows, but they are no longer formatted properly. Why can I no longer select rows when I use exampleView?
Subclass SC.ListItemView instead.
Remove the return sc_super(); line.
Change the context = context.begin().push(' %# (%#)'.fmt(word,english)).end(); line to:
context.push(' %# (%#)'.fmt(word,english));
It should work now.
After getting help on IRC, I made the following changes which fixed the problem:
Spanish.CustomListItemView = SC.ListItemView.extend({
render: function(context, firstTime){
var content = this.get('content');
var word = content.get('word');
var english = content.get('english');
context.push(' %# (%#)'.fmt(word,english));
}
});
I was subclassing the wrong class (note the first line)
Related
I am using jspdf autotable plugin (jspdf.plugin.autotable.js and jspdf.min.js)
to make table grid view in PDF document.
this is my code bellow:
var listpaket2 = '<?php echo json_encode($new_array_list_paket_min_15_persen); ?>'
var columns = ["Nama Balai","Kode Satker","Kode PPK","Nama "];
var rows = jQuery.parseJSON(listpaket2); //listpaket2 contains dynamic big data, it is about 5000 rows of record
doc.autoTable(columns, rows, {
styles: {fillColor: [100, 255, 255]},
columnStyles: {
id: {fillColor: 255}
},
addPageContent: function(data) {
}
});
alert(doc.height)
when I am doing alert(doc.height)I got "undefined". that is not as my expectation.
How to detect table height when table contains big data?
You can set the new table height each time a cell was drawn, using the provided hooks like this:
var height = 0;
doc.autoTable(columns, rows, {
styles: {fillColor: [100, 255, 255]},
columnStyles: {
id: {fillColor: 255}
},
addPageContent: function(data) {},
createdCell: function (cell, data) {
height = data.table.height
}
});
alert(height)
Now the above implementation works up to v2.3.5, v3 was pre-release only 4 days ago (at time of writing), then this hook will be removed. At this time it looks like you can use the new hook : didParseCell like this:
var height = 0;
doc.autoTable(columns, rows, {
styles: {fillColor: [100, 255, 255]},
columnStyles: {
id: {fillColor: 255}
},
didParseCell: function (HookData) {
height = HookData.table.height
}
});
alert(height)
Note that addPageContent will also be removed in v3. Other things might still change, check your implementation if you decide to upgrade.
Use the didDrawPage hook passing a function like below to get the ending height of the table.
autoTable(doc, {
...,
didDrawPage: (d) => console.log(d.cursor.y),
};
Trying to set the height within the didParseCell hook did not work. You can capture the data from that hook and get the height after the table finishes.
let height = 0;
let tableMeta = null;
doc.autoTable(columns, rows, {
styles: {fillColor: [100, 255, 255]},
columnStyles: {
id: {fillColor: 255}
},
didParseCell: (data) => {
if (!tableMeta) {
tableMeta = data.table;
height = data.table.height; // <- doesn't work, sets height to 0
}
}
});
// Calculate the table height
height = tableMeta.finalY - tableMeta.pageStartY;
// Or the final Y position after drawing the table if that's what you need
height = tableMeta.height;
alert(height);
I am using pdfMake to generate table reports. Some of the reports are very wide and dont fit on a standard page width, even in landscape mode. Currently, pdfMake is cutting off the table content when it overflows past the page margin.
I would like to page break the table when it is too wide, much like when the rows overflow to the next page.
Is this possible using pdfMake?
Can using pageBreakBefore callback function help for this?
Thank you
Yes, this is possible with pdfMake, even though not currently a feature.
To achieve this, you can just break overflowing columns into another table. We can put all the tables in an array, then just set them in the docDefinition as follows.
Any common attributes you want in the tables can be defined in the Template constructor.
for (var i = 0; i < tables.length;i++) {
docDefinition.content[i] = new Template();
docDefinition.content[i].table.body = tables[i];
docDefinition.content[i].table.widths = widths[i];
if (i > 0) {
docDefinition.content[i].pageBreak = 'before';
}
}
function Template(){
this.table = {
dontBreakRows: true
};
//zebra stripes layout
this.layout = {
fillColor: function (row, node, col) {
return (row % 2 === 0) ? '#CCCCCC' : null;
}
}
}
How do we determine if a column will overflow? We have two options:
If you are using bootstrap datatables, you can use the "width" attribute in the html.
pdfmake calculates the actual width, but you may have to dig around in pdfmake.js.
Then, just loop through, adding widths until you exceed your limit (my limit was for 8pt font). You can do this for THs then save those column splits and use those for the TDs.
If the final page is just barely overflowing, we don't want the final page to have just one column, we want each page to have roughly the same width. We calculate the number of pages needed, then find the desired break point from there. To link the pages together more easily, you can add a row number column at the beginning of each table.
var colSplits = [];
var tables = new Array();
function parseTHs(colSplits, tables) {
var colSum = 0;
var pageSize = 1120-7*rows.toString().length;
var paddingDiff = 11.9;
var columns = 0;
var prevSum;
var i = 0;
var width = $(".dataTables_scrollHeadInner > table").width();
var pages = Math.ceil(width/pageSize);
console.log("pages: "+pages);
var desiredBreakPoint = width/pages;
console.log("spread: "+desiredBreakPoint);
var limit = pageSize;
var row = ['#'];
var percent = '%';
widths.push(percent);
$(".dataTables_scrollHeadInner > table > thead > tr:first > th").each(function() {
prevSum = colSum;
colSum += $(this).outerWidth()-paddingDiff;
//if adding column brings us farther away from the desiredBreakPoint than before, kick it to next table
if (colSum > limit || desiredBreakPoint-colSum > desiredBreakPoint-prevSum) {
tables[i] = [row];
row = ['#'];
widths.push(percent);
colSplits.push(columns);
i++;
desiredBreakPoint += width/pages;
limit = prevSum+pageSize;
}
row.push({text: $(this).text(), style:'header'});
widths.push(percent);
columns++;
});
//add the final set of columns
tables[i] = [row];
}
function parseTDs(colSplits, tables) {
var currentRow = 0;
$("#"+tableId+" > tbody > tr").each(function() {
var i = 0;
var row = [currentRow+1];
var currentColumn = 0;
var split = colSplits[i];
$(this).find("td").each(function() {
if (currentColumn === split) {
tables[i].push(row);
row = [currentRow+1];
i++;
split = colSplits[i];
}
row.push({text: $(this).text()});
currentColumn++;
});
//add the final set of columns
tables[i].push(row);
currentRow++;
});
}
parseTHs(colSplits, tables);
parseTDs(colSplits, tables);
Note: If you want the columns to fill all the available page, there's a good implementation for that at this link.
I just added '%' for the widths and added that code to pdfmake.js.
Hope this helps!
Just add dontBreakRows property in your table object like this
table: {
dontBreakRows: true,
widths: [30,75,48,48,48,48,48,115],
body: []
}
Also, you can make the page wider and change the page orientation as landscape.
pageSize: "A2",
pageOrientation: "landscape",
what I'm doing is using jsPDF to create a PDF of the graph I generated. However, I am not sure how to wrap the title (added by using the text() function). The length of the title will vary from graph to graph. Currently, my titles are running off the page. Any help would be appreciated!
This is the code i have so far:
var doc = new jsPDF();
doc.setFontSize(18);
doc.text(15, 15, reportTitle);
doc.addImage(outputURL, 'JPEG', 15, 40, 180, 100);
doc.save(reportTitle);
Nothing to keep the reportTitle from running off the page
Okay I've solved this. I used the jsPDF function, splitTextToSize(text, maxlen, options). This function returns an array of strings. Fortunately, the jsPDF text() function, which is used to write to the document, accepts both strings and arrays of strings.
var splitTitle = doc.splitTextToSize(reportTitle, 180);
doc.text(15, 20, splitTitle);
You can just use the optional argument maxWidth from the text function.
doc.text(15, 15, reportTitle, { maxWidth: 40 });
That will split the text once it reaches the maxWidth and start on the next line.
Auto-paging and text wrap issue in JSPDF can achieve with following code
var splitTitle = doc.splitTextToSize($('#textarea').val(), 270);
var pageHeight = doc.internal.pageSize.height;
doc.setFontType("normal");
doc.setFontSize("11");
var y = 7;
for (var i = 0; i < splitTitle.length; i++) {
if (y > 280) {
y = 10;
doc.addPage();
}
doc.text(15, y, splitTitle[i]);
y = y + 7;
}
doc.save('my.pdf');
To wrap long string of text to page use this code:
var line = 25 // Line height to start text at
var lineHeight = 5
var leftMargin = 20
var wrapWidth = 180
var longString = 'Long text string goes here'
var splitText = doc.splitTextToSize(longString, wrapWidth)
for (var i = 0, length = splitText.length; i < length; i++) {
// loop thru each line and increase
doc.text(splitText[i], leftMargin, line)
line = lineHeight + line
}
If you need to dynamically add new lines you want to access the array returned by doc.splitTextToSize and then add more vertical space as you go through each line:
var y = 0, lengthOfPage = 500, text = [a bunch of text elements];
//looping thru each text item
for(var i = 0, textlength = text.length ; i < textlength ; i++) {
var splitTitle = doc.splitTextToSize(text[i], lengthOfPage);
//loop thru each line and output while increasing the vertical space
for(var c = 0, stlength = splitTitle.length ; c < stlength ; c++){
doc.text(y, 20, splitTitle[c]);
y = y + 10;
}
}
Working Helper function
Here's a complete helper function based on the answers by #KB1788 and #user3749946:
It includes line wrap, page wrap, and some styling control:
(Gist available here)
function addWrappedText({text, textWidth, doc, fontSize = 10, fontType = 'normal', lineSpacing = 7, xPosition = 10, initialYPosition = 10, pageWrapInitialYPosition = 10}) {
var textLines = doc.splitTextToSize(text, textWidth); // Split the text into lines
var pageHeight = doc.internal.pageSize.height; // Get page height, well use this for auto-paging
doc.setFontType(fontType);
doc.setFontSize(fontSize);
var cursorY = initialYPosition;
textLines.forEach(lineText => {
if (cursorY > pageHeight) { // Auto-paging
doc.addPage();
cursorY = pageWrapInitialYPosition;
}
doc.text(xPosition, cursorY, lineText);
cursorY += lineSpacing;
})
}
Usage
// All values are jsPDF global units (default unit type is `px`)
const doc = new jsPDF();
addWrappedText({
text: "'Twas brillig, and the slithy toves...", // Put a really long string here
textWidth: 220,
doc,
// Optional
fontSize: '12',
fontType: 'normal',
lineSpacing: 7, // Space between lines
xPosition: 10, // Text offset from left of document
initialYPosition: 30, // Initial offset from top of document; set based on prior objects in document
pageWrapInitialYPosition: 10 // Initial offset from top of document when page-wrapping
});
When we use linebreak in jsPDF we get an error stating b.match is not defined, to solve this error just unminify the js and replace b.match with String(b).match and u will get this error twice just replace both and then we get c.split is not defined just do the same in this case replace it with String(c).match and we are done. Now you can see line breaks in you pdf. Thank you
I am trying to show or hide a button based on the contents of a particular database field. I have the field defined as 'text', as the field may contain something like 1-1 or 1-20 or 0. If the field (arref1) is not equal to 0 then I want to show my button. Otherwise hide the button. Here is what I have so far but it dosen't work:
var resultRule = db.execute('SELECT arref1 FROM genrules WHERE title="'+client+'"');
if (resultRule!='0') {
var appliedRule1 = Ti.UI.createButton({
title:' Applied Rule ' + rows.fieldByName('arref1') + '',
bottom:120,
left: 80,
width: 'auto',
height:40,
borderRadius:5,
textAlign: 'center',
color:'#FFFFFF',
backgroundColor:'#7b4336',
backgroundSelectedColor:'#cc9933',
backgroundImage: 'NONE',
font:{fontSize:'20dp'}
});
win.add(appliedRule1);
appliedRule1.addEventListener('click',function(e)
{
var win = Ti.UI.createWindow({
url: 'appliedruledetail.js',
title:' Applied Rule' + rows.fieldByName('arref1') + ''
});
var client = '' + rows.fieldByName('genrule') + '' ;
win.client = client;
Ti.UI.currentTab.open(win);
}
);
} else{};
db.execute returns a Titanium.DB.ResultSet (which is an object) not a string.
Here is how you use a result set:
// Get the row with execute, returns a resultSet
var row = db.execute('SELECT * FROM genrules WHERE title="'+client+'"');
// Make sure its a valid row
if (row.isValidRow()){
// Now get the field from the current row
if(row.fieldByName('arref1') != '0') {
// Add your button here
}
}
row.close(); // Close the result set since were done with it
I heavily borrowed from this example in the documentation
Here's my simple code; I'm expecting my atom1 widget (row:0, column:0) to be righ aligned; but can't get it! Any suggestions?
var layout = new qx.ui.layout.Grid();
layout.setRowFlex(0, 1); // make row 0 flexible
layout.setColumnWidth(1, 200); // set with of column 1 to 200 pixel
var container = new qx.ui.container.Composite(layout);
this.getRoot().add(container, {left:200, top:200});
var atom1 = new qx.ui.basic.Atom("Icon Right1", "").set({alignX:'right', alignY:'middle'});
var atom2 = new qx.ui.basic.Atom("Icon Right2", "");
var button1 = new qx.ui.form.Button("First Button", "test/test.png");
container.add(atom1, {row: 0, column: 0});
container.add(atom2, {row: 0, column: 1});
container.add(button1, {row: 1, column: 0});
you have to prevent the atom from growing or it will just fill the cell and have no room to move.
add allowGrowX: false ...
see the qooxdoo playground for an example