Keep 2 columns next to each other in PDFMake? - pdfmake

I want to have a text s.calculatedQuantity and next to it an icon. But i want them to be always next to each other and not be separated. Sometimes when s.setDescription is long i have a bad result like in the image below. And i dont know why there is sometimes that space between the icon and the text s.calculatedQuantity. Can someone explain to me that ?
.
I Have my code like this :
function generateSetDescription(s, picto) {
return {
columns: [
{
text: `${s.setDescription} - `,
fillColor: '#000',
color: '#FFF'
},
{
text: `${s.calculatedQuantity}`,
fillColor: '#000',
color: '#FFF'
},
{
image: icon,
width: 10,
height: 10,
fillColor: '#000',
},
]
}
}

The problem you're having seems to be caused by too long words (not text) normal text seems to wrap correctly when a blank space is found.
My suggestion is to programmatically break your 'very long words' adding a - in between.
something like this should work in your case
const text = veryLongTextWithLongWords;
const wrappedText = text.split(' ').map(word => {
if(word.length > 80){
return `${word.substr(0, 40)}-${word.substr(41)}
}
return word;
})
const columns = [
{ text: wrappedText }
]
You can test it out here
http://pdfmake.org/playground.html

Related

How to truncate 'back' button for headerTitle in react-navigation?

I'm using react-navigation with StackNavigator. Is there a way to avoid the overlapping of the back button label and the headerTitle by truncating the back button label?
const MainNavigationOptions = {
headerStyle: {
backgroundColor: colors.CiPrimary
},
headerTitleStyle: {
color: 'white',
height: 50,
width: 140
},
headerTintColor: 'white',
headerTitle:
<Text>LONG TEXT FOR TESTING</Text>
}
Illustration of issue:
(This Answer takes into account that the viewer is using react-navigation 5.x)
In Your Screen component
export const screenOptions = (navData) => {
let title = navData.route.params.movieTitle;
if (title.length > 18) {
title = title.substr(0, 18) + "...";
}
return {
headerTitle: title,
};
};
Here, since we are using substr() , you can use it accordingly and truncate it to custom match your case, keeping in mind the edge cases.
Then you can import it in your AppNavigator.js or wherever you initialize your navigator (in my case below ;)
import {screenOptions as MoviesDetailScreenOptions} from
"../screens/MovieDetailScreen";
Here screenOptions is the named-export you are using MoviesDetailScreenOptions is the alias if i am not mistaken.
Create a style for your button label because it now left for you to style it your self and you can style it any way you want.
const styles = {
leftTouch: {
flexDirection: 'row',
...
},
customStyle: {
paddingLeft: 10,
...
}
textStyle: {
width: 60,
fontSize: 14,
......
}
}
const { leftTouch, customStyle, textStyle} = styles;
Instead of Icon you can use <Image /> but am assuming you are using an icon i.e react-native-vector-icon or likes.
N.B Now you have control of everything the button should do especially when pressed.
const MainNavigationOptions = {
headerStyle: {
backgroundColor: colors.CiPrimary
},
headerTitleStyle: {
color: 'white',
height: 50,
width: 140
},
.....
headerLeft: ( <TouchableOpacity style={leftTouch} onPress={() => goBack()} >
<Icon name="ios-arrow-dropleft-circle-outline" size={25} style={customStyle} color="#ffffff" />
<Text numberOfLines={1} style={textStyle}>A Longer Text for testing</Text>
</TouchableOpacity>
)
}
If you mean to shorten the back button label, why not use either:
headerBackTitle (change the Back label for the previous screen, put it in navigationOptions of the previous screen);
headerBackTitleStyle (change the Back label displayed on current screen, put it in navigationOptions of the current screen)

Fit a wider table into PDF

This is in continuation to the question asked in github, Fit a wider table into PDF #261.
I'm reusing the same method(doc.autoTable) to create PDF out of different HTML inputs.
So, If I define the column style of 0th column as columnWidth: 'wrap', then the same style will be applied for all the HTML tables that invoke this particular method.
I'm not sure If I can follow long text example, as both the column names & table body are coming from HTML page directly. Whereas in the long text example, I'm seeing the column names being declared/defined as shown below
var columnsLong = getColumns().concat([
{title: "Title with\nlinebreak", dataKey: "text2"},
{title: "Long text column", dataKey: "text"},
]);
Now there are 2 questions.
1. I dont want to apply 'WRAP' for all the columns, as the table gets cut.
2. Need to apply 'wrap' for certain columns alone by mentioning the column name that comes from HTML/GSP page.
This is my code
var res = doc.autoTableHtmlToJson($(".printReportsCaveat")[0]);
doc.autoTable(res.columns, res.data, {
columnStyles : {'Plant':{columnWidth: 'wrap'},
'Mine':{columnWidth: 'wrap'},
0:{textColor: [0,105,170]}
},
margin: {top: 55, bottom : 110},
headerStyles: {
overflow: 'linebreak',
// columnWidth: 'auto',
halign: 'center'
},
styles : {
overflow: 'linebreak',
halign: 'center',
fontSize: 8
},
createdCell: function(cell, data) {
var group = $('#groupByValue').val();
addColorToCell(group, level3Flag, level2Flag, data, cell);
},
addPageContent : function(data) {
printHeadNFoot(doc, userDtl, data);
},
drawCell: function(cell, data) {
designCell(data,doc);   
},
});
Kindly help!
If I understand your issue correctly you can try referencing a specific column by index instead of by key. I.e. columnWidth: {0: columnWidth: 'wrap'}.

Change HighCharts plotLine-value and -label

I have implemented a plot line that's showing an average of all values:
"yAxis": {
plotLines: [{
color: 'red',
value: 22,
width: '1',
label: {
text: 'Average: 22'
}
}]
},
I want to change the average-value on legendItemClick. Is it possible to change some plotLine-properties programatically?
What I tried so far is this:
plotOptions: {
series: {
events: {
legendItemClick: function (event) {
var average = 15;
event.target.chart.userOptions.yAxis.plotLines[0].value = average;
event.target.chart.userOptions.yAxis.plotLines[0].label.text = 'Average: ' + average;
}
},
}
},
The value and the label-text aren't changing in the chart. Also I tried to redraw the chart but it still isn't changing the plot line. Is there a way to accomplish this?
I now have found an acceptable answer to my own question:
var average = 15;
event.target.chart.yAxis[0].removePlotLine('average');
event.target.chart.yAxis[0].addPlotLine({
id: 'average',
color: 'red',
width: 1,
value: average,
zIndex: 200,
label: {
text: 'Average: ' + average
}
});
I have to specify an ID for the plotLine, destroy it and create a new one.

noData messsage not auto wrapping on window resize

When displaying a long noData message on High Chart, the text is not wrapping and is going out of screen/chart.
DEMO: http://jsfiddle.net/9xLyo7xj/
lang:{noData:'this is a really long sentence that is supposed to wrap around the window but somehow it is not - I would like it to wrap for easier reading'}
HTML
<button id="add">Add data</button>
<button id="remove">Remove data</button>
<button id="showCustom">Show custom message manually</button>
JS
$(function() {
var chart,
btnRemove = $('#remove'),
btnAdd = $('#add'),
btnShow = $('#showCustom');
btnAdd.click(function() {
chart.series[0].addPoint(Math.floor(Math.random() * 10 + 1)); // Return random integer between 1 and 10.
});
btnRemove.click(function() {
if (chart.series[0].points[0]) {
chart.series[0].points[0].remove();
}
});
btnShow.click(function() {
if (!chart.hasData()) {
chart.hideNoData();
chart.showNoData("Your custom error message");
}
});
$('#container').highcharts({
title: {
text: 'No data in line chart - with custom options'
},
series: [{
type: 'line',
name: 'Random data',
data: []
}],
lang: {
noData: "this is a really long sentence that is supposed to wrap around the window but somehow it is not - I would like it to wrap for easier reading"
},
noData: {
style: {
fontWeight: 'bold',
fontSize: '15px',
color: '#303030',
width: 400px
}
}
});
chart = $('#container').highcharts();
});

Function in Appcelerator causing issues when called quickly

I'm having a few issues with the last couple of pieces on my iOS app built with Appcelerator Titanium.
The app sample below shows one of my windows which allows the user to tap a view (which contains a word), which flips around to show the same word in a different language. The user can then tap the same view again and it animates back to the original position showing the original word.
When the user wants to move onto another word, they simple swipe on the view and it brings in the next word.
Here are the issues i'm experiencing;
If a user swipes super fast through loads of words, then taps to flip, it crashes.
If a user taps the view to flip the view around sometimes the second word flashes up before the animation takes place, it should only be seen as the view comes around into view.
and
3) The user can opt to drop the word, which when tapped performs a database update and then reloads the function and brings a new word in. Great for the first time you use it, but on the 2nd, 3rd, 4th time, the alertbox pops up multiple times rather than once.
Now, I suspect I'm doing something wrong here, but I can't work it out, i've moved code around to make sure labels aren't displaying before they should, but it keeps happening.
Can anyone shed any light on 1 or all of my points? I'm about to lose my mind!
I'm using Titanium 3.20 for iOS
Many thanks
Simon
var win = Titanium.UI.currentWindow;
var selectedlanguage = Ti.App.Properties.getString('langSelect');
// detect height
if (Titanium.Platform.displayCaps.platformHeight == 480) {
var MVTOP = 115;
var tapTOP = 83;
var swipeTOP = 275;
} else {
var MVTOP = 165;
var tapTOP = 133;
var swipeTOP = 325;
}
var masterView = Ti.UI.createView({
backgroundColor: '#FFF',
top: MVTOP,
width: 300,
height: 140,
opacity: 0.7
});
var state = true;
win.add(masterView);
var front = Ti.UI.createView({
backgroundColor: '#FFF',
top: 0,
left: 0,
width: 300,
height: 140,
opacity: 1.0,
touchEnabled: false
});
var back = Titanium.UI.createView({
backgroundColor: '#FFF',
top: 0,
left: 0,
width: 300,
height: 140,
opacity: 1.0,
touchEnabled: false
});
if (win.section == 'word_expressions') {
var label1 = Ti.UI.createLabel({
//text: verb_german,
text: '',
textAlign: 'center',
color: '#000',
font: {
fontSize: 20
},
top: 50
});
var label2 = Ti.UI.createLabel({
//text: verb_english,
text: '',
textAlign: 'center',
color: '#000',
font: {
fontSize: 20
},
top: 50
});
} else {
var label1 = Ti.UI.createLabel({
//text: verb_german,
text: '',
textAlign: 'center',
color: '#000',
font: {
fontSize: 30
},
top: 50
});
var label2 = Ti.UI.createLabel({
//text: verb_english,
text: '',
textAlign: 'center',
color: '#000',
font: {
fontSize: 30
},
top: 50
});
}
var dropButton = Ti.UI.createButton({
width: 120,
height: 41,
right: 15,
bottom: 15,
title: 'drop word',
backgroundColor: '#fd0100',
color: '#FFF',
font: {
fontSize: 15
},
opacity: 1.0
});
win.add(dropButton);
function loadWords() {
// get the section to query for the database
var wordSection = win.section;
// get a random pair of words
var db = Ti.Database.open('germanV6');
var rows = db.execute('SELECT * FROM Words WHERE ' + wordSection + ' = 1 AND word_dropped = 0 ORDER BY RANDOM() LIMIT 1');
var x = 0;
while (rows.isValidRow()) {
if (selectedlanguage == 'en') {
var word_1 = rows.fieldByName('word_english');
var word_2 = rows.fieldByName('word_german');
} else if (selectedlanguage == 'de') {
var word_2 = rows.fieldByName('word_english');
var word_1 = rows.fieldByName('word_german');
}
var word_id = rows.fieldByName('word_id');
rows.next();
}
// close database
rows.close();
var state = true;
label1.text = word_1;
front.add(label1);
masterView.add(front);
label2.text = word_2;
back.add(label2);
masterView.addEventListener('click', function (e) {
switch (state) {
case true:
Ti.API.info('true');
masterView.animate({
view: back,
transition: Ti.UI.iPhone.AnimationStyle.FLIP_FROM_LEFT
});
break;
case false:
Ti.API.info('false');
label1.text = word_1;
masterView.animate({
view: front,
transition: Ti.UI.iPhone.AnimationStyle.FLIP_FROM_RIGHT
});
break;
}
state = !state;
});
var eventListener = function () {
// update the DB to tell it the word has been dropped
var dbDelete = Ti.Database.open('germanV6');
var rowsDelete = dbDelete.execute('UPDATE Words SET word_dropped=1 WHERE word_id=' + word_id);
// pop an alert to notify the user the word has been dropped
var alertDialog = Titanium.UI.createAlertDialog({
title: 'Word Dropped',
message: 'This word has been dropped!' + word_id,
buttonNames: ['OK']
});
// show the message
alertDialog.show();
// load in a new word
//loadWords();
alertDialog.addEventListener('click', function (j) {
loadWords();
});
};
}
// fire the function and load our words into play
loadWords();
var tapLabel = Ti.UI.createLabel({
width: 200,
top: tapTOP,
text: 'tap to flip',
textAlign: 'center',
color: '#FFF',
font: {
fontSize: 15
}
});
var swipeLabel = Ti.UI.createLabel({
width: 320,
top: swipeTOP,
text: 'swipe for next word',
textAlign: 'center',
color: '#FFF',
font: {
fontSize: 15
}
});
win.add(tapLabel);
win.add(swipeLabel);
var grammarButton = Ti.UI.createButton({
width: 120,
height: 41,
left: 15,
bottom: 15,
title: 'verb tables',
backgroundColor: '#ffff01',
color: '#000',
font: {
fontSize: 15
},
opacity: 1.0
});
win.add(grammarButton);
swipeLabel.addEventListener('swipe', function (e) {
// reload the new word
loadWords();
});
masterView.addEventListener('swipe', function (e) {
// reload the new word
loadWords();
});
grammarButton.addEventListener('click', function (e) {
var newWin = Titanium.UI.createWindow({
url: 'verb_table.js',
backgroundImage: '/images/background_random.jpg',
backgroundColor: '#FFF',
barColor: '#000',
translucent: true,
color: '#FFF',
navTintColor: '#FFF',
titleControl: Ti.UI.createLabel({
text: 'Verb Table',
color: '#FFF'
}),
statusBarStyle: Titanium.UI.iPhone.StatusBar.LIGHT_CONTENT,
backButtonTitle: ''
});
newWin.nav = win.nav;
win.nav.openWindow(newWin, {
animated: true
});
});
loadWords() adds an event listener to masterView every time it is called. Probably the source of the crash. Do the Ti.API.info calls build up over time of using the app? I'd expect you should see it popping out 1 then 2 then 3... as it runs along.
Is there missing code? The eventListener function is defined, but I can't find where it is called. This function then has another listener that then calls loadWords again adding more listeners. the name of the function eventListener was difficult to look for because all the addEventListener references come up in a search because they match. I'd change the name of that function to something more distinct. It might be getting called in there, but I gave up looking for it.
There is something up with this code. I would expect that the var label1 and var label2 aren't the ones you are adding to the view later on, but I would expect them to go out of scope when they leave your blocks {}. I would move the var label1 and var label2 outside this if-else and just have label1 = Ti.UI... and the label2 = Ti.UI.. in there.
var label1;
var label2;
if (win.section == 'word_expressions') {
label1 = Ti.UI.createLabel({ // FIX
//text: verb_german,
text: '',
textAlign: 'center',
color: '#000',
font: {
fontSize: 20
},
top: 50
});
label2 = Ti.UI.createLabel({ // FIX
//text: verb_english,
text: '',
textAlign: 'center',
color: '#000',
font: {
fontSize: 20
},
top: 50
});
} else {
label1 = Ti.UI.createLabel({ // FIX
//text: verb_german,
text: '',
textAlign: 'center',
color: '#000',
font: {
fontSize: 30
},
top: 50
});
label2 = Ti.UI.createLabel({ // FIX
//text: verb_english,
text: '',
textAlign: 'center',
color: '#000',
font: {
fontSize: 30
},
top: 50
});
}
front.add(label1);
back.add(label2);
Variable Scrope
http://msdn.microsoft.com/en-us/library/bzt2dkta(v=vs.94).aspx
I would say you need to rethink the loadWords function. It is perhaps doing way too much and the source of all the issues. The masterView.addEventListener should be moved out. The alertDialog should be setup a different way as well. Perhaps moving that code to generate the alert outside of the omni function loadWords.
The database is opened repeatedly inside loadWords, but never closed. You did close the row, but forgot the db.
front.add and back.add aren't necessary in the loadWords function, you should have these after the If-Else statement where you are defining them. Keep the code in there that updates, their .text properties.
Looking closer at the label definitions you are defining them exactly the same aside from the font size. I would fix that to only change the font inside the IF-ELSE.
Fix the place where you detect height as well. Move all the var [variable names] out of the block and define them once. In the IF-ELSE then assign them the correct values.

Resources