I have a double-sided document as two separate pdf files — front-facing pages in one document and rear-facing pages in the second.
front.pdf
rear.pdf
I have also combined them into a single document with all the pages but with all the front-facing pages before the rear-facing pages. The page ordering is of the form, {1,3,5,7,...,[n],2,4,6,8,...,[n-1 OR n+1]}
all.pdf
I wish to write a simple javascript that can be run from inside Adobe Abrobat X Pro. Ideally, it would count the pages of the document all.pdf, handle both occasion when there are either an odd or even number of total pages and then reorder them such that they are in their original order:
page [1>3>4>2] => page [1>2>3>4]
The tiny leading code snippet above is from the answer by user171577 on SuperUser in this question: https://superuser.com/questions/181596/software-that-merges-pdf-every-other-page
I was able to accomplish this following advice from NullUserException :
This script requires a document composed of all the odd pages followed by all the even pages. It will cope with cases where there are n even pages and n+1 odd pages.
I entered a 'Document JavaScript' called InterleavePages, with the following code:
function InterleavePages() {
var n = this.numPages;
var nOdd = Math.floor(n / 2);
var nEven = n - nOdd;
var x;
var y;
var i;
for(i = 0; i < nEven; i++) {
// movePage x, toAfterPage y
// note page numbers are 0-indexed
x = nOdd + (i); //
y = i * 2 ; //
this.movePage(x,y);
}
}
InterleavePages();
Thanks, this was a great help. Just wanted to point out the limitation I found is it only works as written with an even number of pages. Although it's probably possible to write a more sophisticated calculation script, I took the easy way out and just added a blank page to the end of my 17-page test document. I did, however, add an alert so I wouldn't forget to add an extra page when necessary...
function InterleavePages() {
var n = this.numPages;
var nOdd = Math.floor(n / 2);
var nEven = n - nOdd;
var x;
var y;
var i;
app.alert({
cMsg: "Total pages must be an even number",
cTitle: "Even Number of Pages Required!",
nIcon: 1, nType: 1
});
this.pageNum = 0;
for(i = 0; i < nEven; i++) {
// movePage x, toAfterPage y
// note page numbers are 0-indexed
x = nOdd + (i); //
y = i * 2 ; //
this.movePage(x,y);
}
}
InterleavePages();
As mentioned in some other exchanges, to interweave the pages two pdfs, you can use the Java console.
The first step is to combine the pdfs into a single document. I would do this by highlighting both files, and then right-clicking on one of them. There should be an option to "Combine supported files in Acrobat".
Then, once they are combined, open the combined file, where you want to run the code
for (i = 0; i <= this.numPages/2-1; i++) this.movePage(this.numPages-1,this.numPages/2-i-1);
The step-by-step details for running such code are:
1) Open the pdf.
2) Go to the second page. Doing this way will allow you to notice whether the change has taken place. You don't have to do this step, but it helps.
2) Press Control + J
3) In the window that pops up, I always go to the "View" Dropdown menu, and set it to "Script and Console".
4) In the bottom window, replace the text that should read something like
"Acrobat EScript Built-in Functions Version 10.0
Acrobat SOAP 10.0"
with
for (i = 0; i <= this.numPages/2-1; i++) this.movePage(this.numPages-1,this.numPages/2-i-1);
5) Press enter once. Pressing twice might run the code again (which you do not want).
6) Check you pdf to see if the pages have been interlaced. If not, try step 5 again.
7) You are now a Java wizard. Congratulations.
I had the same issue, my scanner was single sided only, and the scanner software, after being done with the auto-feeder, asked if there's more to scan. If you grab the stack, turn it over and feed it again, you'll end up with a single PDF where the n-page document is arranged as 1f, 2f, 3f ... nb, (n-1)b, (n-2)b ... 1b (f=front, b=back, 1-based page numbers). By definition you'd have an even number of scanned pages, the javascript for re-arranging the whole thing (careful, only works with even number of pages in this context!) is:
// rearrange the pages from single-side scanner, 0-based page# where
// pages 0 .. n/2-1 are front, pages n/2 .. n-1 are back
function Rearrange() {
var tpn=0; // target page number
for (count = 0; count < this.numPages/2; count++) {
this.movePage(this.numPages-1,tpn);
tpn=tpn+2;
}
}
Rearrange();
Related
I would like to make a visual random number genarator. That means in Cell F4 should random numbers shuffle trough until it stops with a random number.
My Problem is now, that i can only see the last number generated and not the shuffeling.
function Wuerfeln() {
var Upperbound = 60;
var Lowerbound = 1;
var i = Math.floor(Math.random() * (50 - 10 + 1) + 10);
var RandomNummber = 0;
var range = SpreadsheetApp.getActiveSpreadsheet().getRange("F4");
while(i>0)
{
RandomNummber = Math.floor(Math.random() * (Upperbound - Lowerbound + 1) + Lowerbound);
range.setValue(RandomNummber);
i--;
Utilities.sleep(200);
};
};
Google Sheets has a minimum refresh time, you're not going to make it change super fast by design.
Many requests from a script get batched together and run at the same time, so when the edits are all in the same cell you do not see them change and only the last one is displayed.
The only way to force a cell to change is using SpreadsheetApp.flush() as suggested by Sergey. This forces all pending sheet changes to be pushed. As you have noted however, this is slow.
To do this at all you would need to have an HTML dialog or sidebar which can run JavaScript that directly changes the HTML elements rather than a cell in the spreadsheet.
I would suggest you define a few things and then try it out until it looks like you want, or what you could do is create a pop up which shows a .gif of a dice.
The first approach would look like this
function wurfel(){
const timeDelay = 200
const numbersToShowUntilFinal = 20 // or do a random num
// then your code here,
// but using the variables above to test around until you found a cool
}
If I add an element to the DOM, are the changes immediate? If I remove the same element in the next line of my code, will the element appear on the screen (for a short period of time)? Or does the display get updated when the current browser cycle ends?
It will NEVER show no matter how fast your machine is. Javascript will run to completion blocking the UI until its done.
Try this
HTML
<div id='d'></div>
JS
var d = document.getElementById('d');
var p = document.createElement('p');
p.innerText = "One";
d.appendChild(p);
for (i = 0; i < 1000000; i++) {
for (z = 0; z < 10; z++){
// this is nonsense that runs for a sec or two to block the JS thread
// please never do this in production
}
}
p.innerText = "Two"
will pause your browser and then show Two ... never One
Obviously appearance of elements depends on the power of CPU, browser algorithms, graphic card render time, monitor frequency and many other factors. However The programs (e.g JavaScript) may continue the actions by considering virtual elements without errors.
On the other hand the browser algorithm may decide to render the code line by line or not. As an experience if you run a heavy loop to append items to the body, the Opera browser displays the items one by one however the Chrome will render the page at the end of loop. However if you do the loop using the JavaScript setTimeout, in all browsers you will see the elements appearing one by one.
Im trying to do code in javascript a ruzzle solver. For now it just dig through the maze and find every possible path ( in the future I will match them against a dictionary to find the real valid words in it)
You can see it here : http://178.239.177.105/ruzzle/
I wanted to do it with an animation that show how the algorithm works on it, but im issuing a problem.
If you load it, the page just dont show anything, and my browser crash after a while.
BUT...
if you set an alert("") function, somewhere in the middle of the recursion function, you would be able to go through any step in the algorithm.
Especially if you set the browser to prevent to show any further alert messages, you'll finally see the animation working on the maze.
I was actually trying to do this via setInterval(), but is not working.
So I have two questions:
- Why do the script cause the page to crash, or not if there's an alert?
- How can I properly show the animation using some kind on wait() mechanism?
Thanks
You can see all the code by going on the page and look at the source code, however for the sake of clarity I'll paste the relevant code here:
You can also play with the code here : http://jsfiddle.net/Gcw2U/
(you will have to uncomment the last line in the to make it run)
//this matrix of chars rapresent the 4x4 puzzle
var ruzle_model = [["w","a","l","k"],["m","o","o","n"],["h","a","t","e"],["r","o","p","e"]];
// ""offsets" rapresent the four motion vector(up,down,left,right)
// used to visit the matrix
var offsets = [[1,0],[0,1],[-1,0],[0,-1]];
//recursive function to dig the maze
function path(m,i,j,paths,checkeds){
alert("SET BROWSER TO AVOID NEXT ALERTS MSGs!");
//base case, if not hitting a wall or already checked cell
if ( ! (i<=3 && i>=0 && j>=0 && j<=3) || isChecked(checkeds,i,j)){
terminal.innerHTML = terminal.innerHTML + "-"+ paths;
uncheckAllCells();
return paths;
}
//call path for every direction (up,down,left,right) stored in offsets
var tmp = [];
for (var c=0; c<offsets.length;++c){
var offset = offsets[c];
checkCells(i,j);
checkeds.push(new Array(i,j));
tmp.push(path(m,i+offset[0],j+offset[1],paths + m[i][j],copy(checkeds)));
}
return tmp;
}
//call path on every cell in the maze
function ruzzle(r){
var sol = []
for(var i=0; i<4; ++i){
for(var j=0; j<4; ++j){
var checkeds = new Array();
sol.push(path(r,i,j,'',checkeds));
}
}
terminal.innerHTML = sol;
return sol;
}
Javascript loops and recursions inhibit rendering of the page, so any changes made will stay invisible until the script stops executing, like when you spawn an alert. When a user sets "do not show alert messages", the alert still yields execution time to the underlying eventloop, which will update the page.
For as-fast-as-possible (high fps) animations, use requestAnimationFrame().
In your case, setTimeout() is the best way to go. Set a timeout on the recursive call to path.
function recursive(args) {
// do stuff to args
setTimeout(function () {
recursive(args);
}, 5);
}
Example
I regularly have two sets of pictures named the same way and I would like to script the process of checking for differences. I'm looking for a basic check, if there is no differences between the two images, discard one of them, if there is a single pixel difference, keep both. For those who question the wisdom of doing this in photoshop, this is an addition to another script that is already running and this optional check will help reduce the number of files I have to upload. I would appreciate the help.
If you really have to do this in Photoshop, this is how I'd propose it:
var doc1 = app.open(new File("~/Desktop/test1.bmp"));
var doc2 = app.open(new File("~/Desktop/test2.bmp"));
doc2.selection.selectAll();
doc2.selection.copy();
app.activeDocument = doc1;
var newLayer = doc1.paste();
newLayer.blendMode = BlendMode.DIFFERENCE;
var histogram = doc1.histogram;
for (var i = 1; i < histogram.length; ++i) {
if (histogram[i] > 0) {
alert('Different!');
break;
}
}
I paste the second picture into the first one and set the resulting layer's blend mode to difference. If the two pictures are identical, the resulting picture should be all black. I therefore check if any color values apart from 0 have any pixels in the histogram.
I assumed the two images have the same size.
JavaScript performance in Internet Explorer sucks. No news there. However there are some tips and tricks to speed it up. For example, there is this three part series. Still I find myself unable to squeeze decent performance out of it. Perhaps some of you have an idea what else to do so it was speedier?
What I want to do is create a medium-size table from scratch in Javascript. Say, 300 rows, 10 cells each. It takes at about 5-6 seconds on my computer to do this. OK, granted, it's a 5 year old rig, but that's still too much. Here's my dummy code:
<html>
<body>
<script type="text/javascript">
function MakeTable(parent)
{
var i, j;
var table = document.createElement('table');
var insertRow = table.insertRow;
for ( i = 0; i < 300; i++ )
{
var row = insertRow(-1);
for ( j = 0; j < 10; j++ )
{
var cell = row.insertCell(-1);
cell.innerHTML = i + ' - ' + j;
}
}
parent.appendChild(table);
}
</script>
<div onclick="MakeTable(this);">Click Me!</div>
</body>
</html>
Added: Hmm, apparently string-concatenation (with array.join) is the only way to go. Well, sad, of course. Was hoping to do it the "proper" DOM-way. :)
Here is an interesting link I found when looking for an answer on this:
The page uses five different scripts / methods to generate a table.
According to their tests, using strings is by far faster than using DOM / Table elements.
http://www.quirksmode.org/dom/innerhtml.html
One of the main reason's for IE's performance issues are DOM operations. You want to do your DOM operations as efficiently as possible. This can include, depending on your situation (benchmark!):
Offline creation of your DOM structure; keep the top level element out of the document (create, but not append) then appending it to the document when it's ready, instead of appending every element into the DOM as you create it
write innerHTML instead of DOM manipulation
You could try 'Duff's Device': Unwinding a loop by repeating the code a number of times:
for (var i = 0; i < count / 4; i++) {
doSomething();
doSomething();
doSomething();
doSomething();
}
Obviously this leaves the remainder when divided by 4, the original Duff's Device had a clever way of jumping to the middle of the loop using a switch statement mixed in with the loop. Javascript does not support this, but you could manually process the rest of your rows. Also the number 4 is random, the number itself can be derived by performance testing.
See also: http://www.websiteoptimization.com/speed/10/10-3.html