Airshow 416

Pretty simple, start with array [1, 2, 3] (representing offsets from current month) and map it to the array you want.

function getNext3Months() {
    const currentMonth = (new Date()).getMonth() + 1; // getMonth() is zero-indexed; add 1 to give conventional month number.
    return [1, 2, 3].map(n => (currentMonth + n) % 12); // returns array of next three conventional month numbers; %12 caters for end of year wrap-around.

Airshow 416

@Luke_4, no worries. As you probably already discovered, that pattern is totally flexible. Once you have grasped the basic idea, you can "play tunes" with it to control the content/layout to print whatever you want.

Good luck.


Airshow 416

I posted a link to a fiddle back in the original post

Luke_4 commented: Airshow!!! Thank YOU!!! It is PERFECT!!! +0

Airshow 416

diafol commented: Lovely :) +15

Airshow 416

An approach (not the only one) would be to have two main child divs within your <body></body> tags

  • <div id="screen"></div> styled to be displayed under @media screen and hidden under @media print.
  • <div id="print"></div> styled to be displayed under @media print and hidden under @media screen.

When the "Print" button is clicked, dynamically populate the "print" div with content drawn from the "screeen" div, before calling window.print().

I have never needed to do this but it may be the line-of-least-resistance here. I can see no reason why it could not be made to work.

Luke_4 commented: Would like to have you elaborate with example +0

Airshow 416


It's very odd that printing is not WYSIWYG.

Theory 1: (Physical) .autocomplete() creates the widget by replacing the original input element and/or creating one or more hidden elements. You may need to find some element other than the obvious one, which holds the final string, and establish an @media print rule that shows only that element. Use your browser's console to inpect the DOM.

Theory 2: (Temporal) It's a matter of timing. You may need to issue some command on the widget and/or wait for some widget event before printing. Have a look at autocomplete's API documentation for clues.

Airshow 416

The days of generating a special page for print purposes are long gone.

Instead of composing HTML on the fly, try mastering CSS @media rules :

If there's going to be any dynamically generated content, you will still need some javascript; but more typically @media rules alone allow you to specify a "print" version of a "screen" page.

I admit, I've never tried @media with an autocomplete element but can't immediately see any reason why it should not be successful. From what I understand, it's more about not printing the rest of the page.

Airshow 416

Neither the pictures nor the words are speaking to me.

Until such time that the question is properly expressed, I have to admit defeat.

Airshow 416

As it stands, the question is not 100% self-explanatory, in particular the relationships and juxtapositions of the various input elements.

Maybe it would be clearer if you posted an (annotated) screenshot of the original spreadsheet and/or the HTML version.

Airshow 416

You are expecting javascript arrays to behave like PHP arrays. They don't!

Elements of a JS array are indexed exclusively by integer.

Confusingly, JS arrays can also be given properties, so tmp[14]['G'] = foo is quite legal but not what you might expect from knowledge of PHP. ['G'] is a property of tmp[14] without being an array element!

This all stems from the way JS implements arrays. Array is heavily based on Object but gives special status only to integer keys.

Straightforwardly you could do as follows :

// change
tmp[i] = [];
// to
tmp[i] = {}; // a js plain object

// change
tmp[i]['"'+letters[j]+'"'] = val;
// to
tmp[i][letters[j]] = val;

However, JS plain objects are just collections of properties ... without order ..., which may suffice.

But if order is important, and you want to convey both a key (letter) and a value (val), then you need an array of objects, each containing a key|value pair.

// keep
tmp[i] = []; // arrays have order.

// change
tmp[i]['"'+letters[j]+'"'] = val;
// to
tmp[i].push({ 'key':letters[j], 'value':val });

Love it or loath it, that's javascript.

diafol commented: Masterclass :) +15

Airshow 416

The formula will simplify enormously.


can be written :

lcost1 + (epay1 - dp1) / 24

And you probably want to display :

(lcost1 + (epay1 - dp1) / 24).toFixed(2)

ie rounded to 2 decimal places.

Airshow 416

Why is this tagged "jQuery" when everything is written in POJS?

Airshow 416

Dawbin, results of your benchmark are inconclusive here. Most runs I get 0ms for both sets of code, but with a random sprinkling of higher values up to 45ms. I expect that anything other than 0ms is due to other processes grabbing my processor.

I would guess that your revised crawl() will give best performance of all. If so, then we can both take some credit - co-operative effort.

Will be interesting to see if anyone comes up with better ideas. Could happen.

Airshow 416

OK, here's a jQuery solution in 11 lines.

function parse(xml) {
    var o = {};
    $(xml).find('*').andSelf().contents().filter(function() {
        return this.nodeType == 3 && $.trim(this.nodeValue);
    }).each(function() {
        var p = this.parentNode.nodeName;
        if (!o[p]) o[p] = [];
    return o;


You can delete .andSelf() if there's guaranteed to be no text nodes at root level.

I haven't run a performance comparison but would expect your own code to be faster despite its greater length. No need to pay the reward but I would be interested in the results of a performance comparison if you do one.

Airshow 416

Would you accept a jQuery solution?

Airshow 416

The double test for hasChildNodes(), at parent and child levels, looks a bit odd.

I would have thought you want the parse out the nodes that don't have children, in which case your loop will be as follows:

for (i=0; i<x.length; i++) {
    if (!x[i].hasChildNodes()) {
        alert(x[i].nodeName + '=' + x[i].childNodes[0].nodeValue);

Within the loop, you could put crawl(x[i]) in an else clause but it should be OK without, as any node without cildren will simply drop straight through the next recursion of crawl().

The only thing I'm not sure about is whether or not .hasChildNodes() detects text nodes. If it does, then the if (!x[i].hasChildNodes()) test needs to be more rigorous.

Airshow 416

Double_cola, +1 for your positive attitude.

Good luck.

Airshow 416

Double_cola, Broj1 is really trying to help you. Do what he says and ANSWER HIS QUESTIONS. Restating the problem and reposting large sections of code is not going to get you to a solution any faster.

Airshow 416

Gentlemedia, coooooool! Now Taywin and I can start breathing again ;-)

Airshow 416

Gentlemedia, it's not obvious what is causing this issue. You need to devise an investigation strategy to discover what's causing it. Simplify everything one aspect at a time and see when the problem disappears.

Airshow 416

Surely cc can be permanently appended to .news-grid and cd can be permanently appended to cc with .show() and .hide() controlling visibility? There doesn't appear to be any need to detach/reappend. Even better, cc/cd could be hard coded in HTML.

I'm not sure this will fix anything but should better guarantee that the behaviour is consistent and debugging should be simpler.

Airshow 416

Try jQuery-turtle, "a jQuery plugin for turtle graphics".

I've not used this plugin but assume that its "accurate collision-testing of turtles with arbitrary convex hulls" can be used for collision detection of turtles with each other, ie. turtlize each of your eggs.

You would need to more-or-less restart your coding from scratch but would benefit from many hours of good work put in by the plugin's author.

Airshow 416

Your function looks good though it will only work if this is an appropriate DOM elememt.

You might like to consider a generalised int verifier framed as a jQuery plugin :

jQuery.fn.isInSqlIntRange = function (options) {
    var settings = $.extend({
        'type': 'int',
        'unsigned': false
    }, options);
    var min, max, val = this.val();
    if (val === '' || Number(val) === NaN) {
        return false;
    val = Number(val);
    switch (settings.type) {
        case 'tinyint':
            min = settings.unsigned ? 0 : -128;
            max = settings.unsigned ? 255 : 127;
        case 'smallint':
            min = settings.unsigned ? 0 : -32768;
            max = settings.unsigned ? 65535 : 32767;
        case 'mediumint':
            min = settings.unsigned ? 0 : -8388608;
            max = settings.unsigned ? 16777215 : 8388607;
        case 'int':
        case 'integer':
            min = settings.unsigned ? 0 : -2147483648;
            max = settings.unsigned ? 4294967295 : 2147483647;
        case 'bigint':
            min = settings.unsigned ? 0 : -9223372036854775808;
            max = settings.unsigned ? 18446744073709551615 : 9223372036854775807;
            throw typeError('jQuery.isInIntRange() - type is undefined or invalid');
    return val >= min && val <= max;

Sample call :

var foo = $("#myInput").isInSqlIntRange({
    'type': 'tinyint',
    'unsigned': true


Airshow 416

signed or unsigned tinyint?

Airshow 416

We have solved the problem myself.

That's cool Razamughal67, well done.

Airshow 416

Text questions will most likely attract text answers. If you want code, then provide code.

Airshow 416

This is one of those questions that I will understand only when I've seen the answer.

Airshow 416

Terrymold, you missed the point.

What is the other PHP programmer writing :

  • some code for your page(s)?
  • other page(s) on the same site?
  • page(s) for some different site?
  • not a page at all but some data resource to be called via AJAX?

The precise scenario really matters!

Airshow 416

"Another PHP programmer" could be interpreted many different ways.

Airshow 416

Refresh very deliberately reloads the current document in its original state. The only (and very limited) control the user has (in most browsers) is to do a "soft" or "hard" refresh;

  • Soft: accepts data from cache(s)
  • Hard: ignores cache(s) and goes back to the original source (sever). Relies on caches conforming to the spec (complex area).

Browser history (forward and back buttons) should maintain page state. Browsers have a chequered past in this regard though the current crop of major browser (together with HTML5) does seem to have gotten it right.

HTTP cookies (and more recently "local storage") are means by which client-side data may be made to persist (ie to exist beyond the life of the page). However, cookies etc. do not "save a page" as such. They merely save some data which can be read (both server-side or client-side) and acted on for any of a number of reasons - including the restoration of page state. If you want this to happen, then you have to write your documents very deliberately - it won't just happen!