I have a pdf From which a user needs to fill out. There will need to be a replication of the fields based on a number entered into an earlier field (see screenshot below)
For example, if a user enters the number 3 in the voyages box, I want to be able to create 3 'copies' of the complete table below it.
Is this something that is able to be done with Javascript within the pdf? MY thinking is that it should be possible, but i cant find anything on the adobe forums that indicates how.
You can duplicate form fields in a PDF using JavaScript (Acrobat DC SDK) like this (example shows creating a button on each page):
var aPage = this.getPageBox();
var w = 45; // Width of each button
var h = 12 // Height of each button
var nNavi = 4; // Number of buttons to be placed
var g = 6; // Gap between buttons
var totalWidth = nNavi * w + (nNavi - 1) * g; // total width of navi bar
var widthPage = aPage[2] - aPage[0];
// Horizontal offset to center navi bar
var hoffset = (widthPage - totalWidth) / 2;
var voffset = 12; // vertical offset from bottom
for (var nPage = 0; nPage < this.numPages; nPage++) {
// Create the fields
var pp = this.addField("PrevPage", "button", nPage,
[ hoffset, voffset, hoffset + w, voffset + h ] );
pp.buttonSetCaption(pp.name);
pp.fillColor=color.ltGray;
pp.setAction("MouseUp", "this.pageNum--");
var np = this.addField("NextPage", "button", nPage,
[ hoffset + w + g, voffset, hoffset + 2*w + g, voffset + h ] );
np.buttonSetCaption(np.name);
np.fillColor=color.ltGray;
np.setAction("MouseUp", "this.pageNum++");
var pv = this.addField("PrevView", "button", nPage,
[ hoffset + 2*w + 2*g, voffset, hoffset + 3*w + 2*g, voffset + h ] );
pv.buttonSetCaption(pv.name);
pv.fillColor=color.ltGray;
pv.setAction("MouseUp", "app.goBack()");
var nv = this.addField("NextView", "button", nPage,
[ hoffset + 3*w + 3*g, voffset, hoffset + 4*w + 3*g, voffset + h ] );
nv.buttonSetCaption(nv.name);
nv.fillColor=color.ltGray;
nv.setAction("MouseUp", "app.goForward()");
}
[Source]
The documentation also notes the following:
Multiple customized forms within a form based on user input
Subforms may also be subject to conditions. For example, form fields for dependent children would become visible if the user checks a box indicating that there are dependent children. In addition, XFA allows multiple form fields with the same name and multiple copies of the same form.
This page lists XFA specific methods that you may find useful in this effort.
Related
Here is a link to the tip calculator - it's hosted on netlify.
I created a tip calculator using html, scss, javascript. no tutorials used, so I'm pretty proud. It took me waaayyyyy longer than I had planned on, but it's done. needless to say, I am a complete beginner.
In any event, I need some help.
I need to know how to make the numbers auto-update if I input a new dollar amount into the billing input.
For instance, if the bill is $50, and the tip percent is 50% that's a $25 tip Amount. for a total bill of $75 dollars.
But let's say I mistyped the bill, so I go back to put in $60, 50% of $60 is $30. so the total bill amount should auto-update to $90. But I can't figure out how to get all of that to happen instantaneously when I change the dollar amount in the billing input.
I have a feeling that it has something to do with using a "change" event listener. but I don't understand how to best implement it, or if that's even the answer here.
// Upper Box Selections
const tipPercent = document.querySelector(".tip-percent");
const tipSlider = document.querySelector("#tip-slider");
tipSlider.oninput = function () {
billInput = Number(document.querySelector("#bill-amt").value);
tipPercent.innerHTML = this.value + "%";
//Discovered that number input type still returns a string
//You can wrap multiple variables in parenthesis in order to append methods
let tipAmount = document.querySelector(".tip-amount");
// if a variable is referenced but not defined, it will be added to the window element - can now use in second function
tipTotal = Number((billInput * Number(this.value / 100)).toFixed(2));
tipAmount.innerHTML = "$" + tipTotal.toFixed(2);
const billTotal = document.querySelector(".bill-total");
billForSplit = Number(billInput + tipTotal).toFixed(2);
billTotal.innerHTML =
"<strong>$</strong>" + "<strong>" + billForSplit + "</strong>";
};
// Bottom Box Selections
// -Grab slider value
const splitSlider = document.querySelector("#split-slider");
splitSlider.oninput = function () {
// -Grab split person value-split PERSON for 1, people for more than 1
const splitPeople = document.querySelector(".split-people");
if (splitSlider.value <= 1) {
splitPeople.innerHTML = splitSlider.value + " person";
} else {
splitPeople.innerHTML = splitSlider.value + " people";
}
// -grab tip per person value
const splitTip = document.querySelector(".split-tip");
// -grab total bill per person value
const splitTotal = document.querySelector(".split-total");
// - tip per person equals tipTotal / split slider value
splitTip.innerHTML = "$" + (tipTotal / splitSlider.value).toFixed(2);
// -total bill/person = billTotal / splitSlider.value
splitTotal.innerHTML =
"<strong>$</strong>" +
"<strong>" +
(billForSplit / splitSlider.value).toFixed(2) +
"</strong>";
};
https://wonderful-meninsky-e0b1c7.netlify.app/
You should declare the function with a name like calcTotal() which will be run every time there is an input for the bill and tip:
const tipPercent = document.querySelector(".tip-percent");
const tipSlider = document.querySelector("#tip-slider");
function calcTotal() {
billInput = Number(document.querySelector("#bill-amt").value);
tipPercent.innerHTML = this.value + "%";
//Discovered that number input type still returns a string
//You can wrap multiple variables in parenthesis in order to append methods
let tipAmount = document.querySelector(".tip-amount");
// if a variable is referenced but not defined, it will be added to the window element - can now use in second function
tipTotal = Number((billInput * Number(this.value / 100)).toFixed(2));
tipAmount.innerHTML = "$" + tipTotal.toFixed(2);
const billTotal = document.querySelector(".bill-total");
billForSplit = Number(billInput + tipTotal).toFixed(2);
billTotal.innerHTML =
"<strong>$</strong>" + "<strong>" + billForSplit + "</strong>";
};
tipSlider.oninput = calcTotal;
document.querySelector("#bill-amt").oninput = calcTotal;
I'm trying to figure out what will be the JavaScript formula if I have a data in my database and this is i want to be the output:
if the data = 10 I want to be output that in a 100% in which I will be going to use in an div element height
if the data = 65 I want to be output that in a 0% in which I will be going to use in an div element height
and this is my code right now but I can't figure it out:
var datas = JSON.parse(data);
var ID, Bio, Non_Bio, Recy, Extra;
var div = 10;
ID = datas[0].ID;
Bio = datas[0].Bio;
Non_Bio = datas[0].Non_Bio;
Recy = datas[0].Recy;
Extra = datas[0]. Extra;
var obtained = Bio;
var obtained2 = Non_Bio;
var obtained3 = Recy;
var obt = obtained*100/div;
var obt2 = obtained2*100/div;
var obt3 = obtained3*100/div;
var water1 = $("#water1").height() + obt;
var water2 = $("#water2").height() + obt2;
var water3 = $("#water3").height() + obt3;
If the math can't be solved in one's head, doing it on paper can help, particularly when solving a pair of simultaneous equations using high school maths.
Assuming the ultrasound value to height relationship is linear you can write it as the equation of a line:
h = a * u + b ... 1)
where h is height, u is the ultrasound sensor reading, and a and b are constants.
Now take two calibration values of sensor readings taken for an empty and a full bin and call them c0 and c100 respectively.
From 1)
0 = a * c0 + b ... 2) using the c0 value , and
100 = a * c100 + b ... 3) using c100
Solving this pair of simultaneous equations proceeds along the lines of
b = 0 -a*c0 ... from 2)
b = 100 -a*c100 ... 4) from 3)
Hence
0 -a*c0 = 100 -a*c100
a*c100 - a*c0 = 100
a = 100/(c100-c0) ... 5)
and now substituting 4) back into 2) gives
b = 100 - a*c100 ... 6)
In this test example, the equations are converted into a factory function that returns an object with calibrate and height functions calibrate(c0, c100) and height( sensor). The height returned is rounded to the nearest quarter due to an overall lack of precision in the data.
function createBin() {
var a, b;
function calibrate( c0, c100) {
a = 100/(c100-c0);
b = 100 - a*c100;
}
function height( sensor) {
let h = a * sensor + b;
return Math.round( 4*h)/4;
}
return {calibrate, height};
}
const bin = createBin();
bin.calibrate (65, 10);
var readings = [67, 65, 37, 10, 5];
readings.forEach(
reading => console.log( "height( %s) = %s%", reading, bin.height(reading))
);
Note that when dealing with real world sensors, calibration data can vary between sensors and installations - hard coding equations that need to be calibrated against hardware variability is something to be avoided.
var datas=[{
ID :10,
Bio :7,
Non_Bio: 65,
Recy :75,
Extra :20
}]
var obt=[];
datas.map((data,index)=>{
console.log(data)
Object.values(data).map(item=>{
console.log(item)
if(item===10){
obt.push("100%");
}
else{
obt.push("0%");
}
})})
console.log("required output:");
console.log(obt);
Assumed: ID = datas[0].ID; since you are fetching from array 0th index and then its key.It mus be array of object (you have not given the proper inputs.) and the if logic can be changed accordingly as you mentioned if its 10 it must be 100%.
Logic: Just iterating each object of the array and then getting the object values (of each key i.e. id,bio etc..) and checking the value if divisible by 10 then pushing that data into empty array so you can use it further. You can also insert the output data into map.
I'm pretty new to JavaScript, and want to code something that will generate a series of data for a given function. For example, if the user types in a rule such as y = x + 2, i would like to have a table that would show the value of y when x equals 1 - 10.
Is there anyway I can do this?
Use eval: http://www.w3schools.com/jsref/jsref_eval.asp
// Remove variable "y = " to get just the expression
var userExpression = str.replace(/y\s*=\s*/i, document.getElementById('textbox_id').value);
for (var i = 1; i < 11; i++) {
var x = i;
var y = eval(userExpression);
console.log("x: " + x + "\t y: " + y);
}
EDIT
This is if you were running it on the same page within the same browser. If you planned on storing the evaluation expression and then evaluating it later
for other users and browser sessions this can easily open up security exploits. So you would need to be careful on how you plan on using this.
I'm trying to get the height of a div, then position it based on the height. I've read various articles on this, but I always seem to be getting NaN as a result. Yes the javascript is loaded at the end of the body, after the divs are drawn.
I'm using asp.net to create this javascript dynamically. What I have output so far is:
var resultsDiv = document.getElementById('resultsDiv');
var resultsInnerDiv = document.getElementById('resultsInnerDiv');
resultsInnerDiv.innerHTML = "test";
var h = parseInt(resultsInnerDiv.style.offsetHeight);
alert(parseInt(resultsInnerDiv.style.offsetHeight));
resultsInnerDiv.style.top = ((h / 2) -125) + 'px';
I need to get the actual height, instead of NaN. NaN pixels is obviously not valid.
I think this what you need:
var resultsDiv = document.getElementById('resultsDiv');
var resultsInnerDiv = document.getElementById('resultsInnerDiv');
resultsInnerDiv.innerHTML = "test";
var h = parseInt(resultsInnerDiv.offsetHeight);
alert(parseInt(resultsInnerDiv.offsetHeight));
resultsInnerDiv.style.top = ((h / 2) -125) + 'px';
offsetHeight is not a property of element.style, but the element itself (see here).
Try this:
var resultsDiv = document.getElementById('resultsDiv');
var resultsInnerDiv = document.getElementById('resultsInnerDiv');
resultsInnerDiv.innerHTML = "test";
var h = parseInt(resultsInnerDiv.offsetHeight);
alert(h);
resultsInnerDiv.style.top = ((h / 2) -125) + 'px';
I've created a plugin for Raphael JS. It basically allows you to call
paper.connect(obj1,obj2,colour)
That draws a line between the two objects and maintains the line when the objects are animated.
This is what I've come up with so far. It works but its not very performant, any suggestions on what else I could do to achieve the same thing.
Raphael.fn.connect = function(obj1, obj2, colour) {
// list of paths each object has
obj1.connections = []
obj2.connections = []
// get the bounding box of each object
var box1 = obj1.getBBox()
var box2 = obj2.getBBox()
// create a line/path from object 1 to object 2
var p = this.path("M" + (box1.x + box1.width / 2) + ","
+ (box1.y + box1.height / 2) + "L" + (box2.x + box2.width / 2)
+ "," + (box2.y + box2.height / 2))
// adjust attributes of the path
p.attr({
stroke : colour,
"stroke-linecap" : "round",
"stroke-opacity" : Math.max(obj1.attr('opacity'), obj2.attr('opacity'))
})
// set the start and end element for this path
p.startElement = obj1;
p.endElement = obj2;
// add the path to each of the object
obj1.connections.push(p)
obj2.connections.push(p)
// mark each object as being connected
obj1.connected = true;
obj2.connected = true;
// listen for the Raphael frame event
eve.on("raphael.anim.frame.*", function(obj) {
// if the object the frame event is fired on is connected
if (this.connected) {
// for each connection on this object
for ( var c in this.connections) {
var path = this.connections[c]; // temp path
var b1 = path.startElement.getBBox(); // get the current
// location of start
// element
var b2 = path.endElement.getBBox();// get the current location
// of end element
// move the path to the new locations
path.attr({
path : "M " + (b1.x + b1.width / 2) + " "
+ (b1.y + b1.height / 2) + "L "
+ (b2.x + b2.width / 2) + " "
+ (b2.y + b2.height / 2),
opacity : Math.max(path.startElement.attr('opacity'),
path.endElement.attr('opacity'))
});
}
}
});
}
Not convinced this is the best way at all, but this is my first time using Raphael so I just did all that from looking at the Raphael source code...
In our app we have a line tool. We drop a line with 2 movable end points onto our paper.
All shapes in our app have an associated VisualModel that contains all the geometric data inside of them. These VisualModels also double as Actors. Any Actor can subscribe to any other Actor and when changes occur all interested parties respond.
A system like this allows for a line's path to change via a redraw function that gets called anytime the 2 connected objects modify their X/Y coordinates.
connecting_line.js (redraw)
redraw: function() {
var x1 = this.shapeView1.visualModel.get('x'),
y1 = this.shapeView1.visualModel.get('y'),
x2 = this.shapeView2.visualModel.get('x'),
y2 = this.shapeView2.visualModel.get('y'),
pathData;
pathData = 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2;
this.line.attr({
path: pathData,
fill: '#000000',
stroke: LineConstants.COLOR,
'stroke-width': LineConstants.THICKNESS
});
}
We created "movable" mixin. This mixin would allow you to add movability to your shapes. This mixin would update the x/y coordinates in and in turn trigger a 'change' event that your line class would pick up.
movable.js
handleDraggging: function(delta) {
this.shape.move(delta);
}
move: function(delta) {
//... compute movement based on delta
this.visualModel.set('x', xPosition);
this.visualModel.set('y', yPosition);
}
connecting_line.js
initialize: function(shapeView1, shapeView2) {
// ...
this.shapeView1 = shapeView1;
this.shapeView2 = shapeView2;
this.listenTo(shapeView1.visualModel, 'change:x change:y', this.redraw);
this.listenTo(shapeView2.visualModel, 'change:x change:y', this.redraw);
}
Performance for this is great. You can take a look at it in action by going to eventbrite.com, create an event, enabling reserved seating (step 2), add a new map, click 'objects' on the left and drop a line on the paper.