Rectangle 27 632

Method 2b: Using a function

Content scripts are executed in an "isolated world" environment. You have to inject your state() method into the page itself.

When you want to use one of the chrome.* APIs in the script, you have to implement a special event handler, as described in this answer: Chrome extension - retrieving Gmail's original message.

Otherwise, if you don't have to use chrome.* APIs, I strongly recommend to inject all of your JS code in the page via adding a <script> tag:

  • Method 2b: Using a function
  • Dynamic values in the injected code
script.js
var s = document.createElement('script');
// TODO: add "script.js" to web_accessible_resources in manifest.json
s.src = chrome.extension.getURL('script.js');
s.onload = function() {
    this.remove();
};
(document.head || document.documentElement).appendChild(s);

Note: If you use this method, the injected script.js file has to be added to the "web_accessible_resources" section

Denying load of chrome-extension://[EXTENSIONID]/script.js. Resources must be listed in the web_accessible_resources manifest key in order to be loaded by pages outside the extension.

var actualCode = `// Code here.
// If you want to use a variable, use $ and curly braces.
// For example, to use a fixed random number:
var someFixedRandomValue = ${ Math.random() };
// NOTE: Do not insert unsafe variables in this way, see below
// at "Dynamic values in the injected code"
`;

var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.remove();

Note: template literals are only supported in Chrome 41 and above. If you want the extension to work in Chrome 40-, use:

var actualCode = ['/* Code here. Example: */' + 'alert(0);',
                  '// Beware! This array have to be joined',
                  '// using a newline. Otherwise, missing semicolons',
                  '// or single-line comments (//) will mess up your',
                  '// code ----->'].join('\n');

For a big chunk of code, quoting the string is not feasible. Instead of using an array, a function can be used, and stringified:

This method works, because the + operator on strings and a function converts all objects to a string. If you intend on using the code more than once, it's wise to create a function to avoid code repetition. An implementation might look like:

function injectScript(func) {
    var actualCode = '(' + func + ')();'
    ...
}
injectScript(function() {
   alert("Injected script");
});

Note: Since the function is serialized, the original scope, and all bound properties are lost!

var scriptToInject = function() {
    console.log(typeof scriptToInject);
};
injectScript(scriptToInject);
// Console output:  "undefined"

Sometimes, you want to run some code immediately, e.g. to run some code before the <head> element is created. This can be done by inserting a <script> tag with textContent (see method 2/2b).

An alternative, but not recommended is to use inline events. It is not recommended because if the page defines a Content Security policy that forbids inline scripts, then inline event listeners are blocked. Inline scripts injected by the extension, on the other hand, still run. If you still want to use inline events, this is how:

var actualCode = '// Some code example \n' + 
                 'console.log(document.documentElement.outerHTML);';

document.documentElement.setAttribute('onreset', actualCode);
document.documentElement.dispatchEvent(new CustomEvent('reset'));
document.documentElement.removeAttribute('onreset');

Note: This method assumes that there are no other global event listeners that handle the reset event. If there is, you can also pick one of the other global events. Just open the JavaScript console (F12), type document.documentElement.on, and pick on of the available events.

var GREETING = "Hi, I'm ";
var NAME = "Rob";
var scriptToInject = function() {
    alert(GREETING + NAME);
};

To inject this code, you need to pass the variables as arguments to the anonymous function. Be sure to implement it correctly! The following will not work:

var scriptToInject = function (GREETING, NAME) { ... };
var actualCode = '(' + scriptToInject + ')(' + GREETING + ',' + NAME ')';
// The previous will work for numbers and booleans, but not strings.
// To see why, have a look at the resulting string:
var actualCode = "(function(GREETING, NAME) {...})(Hi I'm,Rob)";
//                                                 ^^^^^^ ^^^ No string literals!

The solution is to use JSON.stringify before passing the argument. Example:

var actualCode = '(' + function(greeting, name) { ...
} + ')(' + JSON.stringify(GREETING) + ',' + JSON.stringify(NAME) + ')';

If you have many variables, it's worthwhile to use JSON.stringify once, to improve readability, as follows:

...
} + ')(' + JSON.stringify([arg1, arg2, arg3, arg4]) + ')';

This answer should be part of official docs. Official docs should ship with recommended way --> 3 ways to do the same thing... Wrong?

@Qantas94Heavy The extension's CSP does not affect content scripts. Only the page's CSP is relevant. Method 1 can be blocked by using a script-src directive that excludes the extension's origin, method 2 can be blocked by using a CSP that excludes "unsafe-inline"`.

Other method: use location.href = "javascript: alert('yeah')"; anywhere in your content script. It's easier for short snippets of code, and can also access the page's JS objects.

@ChrisP Be careful with using javascript:. Code spanning over multiple lines might not work as expected. A line-comment (//) will truncate the remainder, so this will fail: location.href = 'javascript:// Do something <newline> alert(0);';. This can be circumvented by ensuring that you use multi-line comments. Another thing to be careful of is that the result of the expression should be void. javascript:window.x = 'some variable'; will cause the document to unload, and be replaced with the phrase 'some variable'. If used properly, it's indeed an attractive alternative to <script>.

@Lai32290 Using events or HTML attributes, for example using document.currentScript.dataset.foo = 'only strings can be shared'; in the injected script, and then reading it back using script.dataset.foo (assuming that script is a reference to the <script> tag that you injected).

javascript - Insert code into the page context using a content script ...

javascript google-chrome google-chrome-extension youtube-api content-script
Rectangle 27 632

Method 2b: Using a function

Content scripts are executed in an "isolated world" environment. You have to inject your state() method into the page itself.

When you want to use one of the chrome.* APIs in the script, you have to implement a special event handler, as described in this answer: Chrome extension - retrieving Gmail's original message.

Otherwise, if you don't have to use chrome.* APIs, I strongly recommend to inject all of your JS code in the page via adding a <script> tag:

  • Method 2b: Using a function
  • Dynamic values in the injected code
script.js
var s = document.createElement('script');
// TODO: add "script.js" to web_accessible_resources in manifest.json
s.src = chrome.extension.getURL('script.js');
s.onload = function() {
    this.remove();
};
(document.head || document.documentElement).appendChild(s);

Note: If you use this method, the injected script.js file has to be added to the "web_accessible_resources" section

Denying load of chrome-extension://[EXTENSIONID]/script.js. Resources must be listed in the web_accessible_resources manifest key in order to be loaded by pages outside the extension.

var actualCode = `// Code here.
// If you want to use a variable, use $ and curly braces.
// For example, to use a fixed random number:
var someFixedRandomValue = ${ Math.random() };
// NOTE: Do not insert unsafe variables in this way, see below
// at "Dynamic values in the injected code"
`;

var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.remove();

Note: template literals are only supported in Chrome 41 and above. If you want the extension to work in Chrome 40-, use:

var actualCode = ['/* Code here. Example: */' + 'alert(0);',
                  '// Beware! This array have to be joined',
                  '// using a newline. Otherwise, missing semicolons',
                  '// or single-line comments (//) will mess up your',
                  '// code ----->'].join('\n');

For a big chunk of code, quoting the string is not feasible. Instead of using an array, a function can be used, and stringified:

This method works, because the + operator on strings and a function converts all objects to a string. If you intend on using the code more than once, it's wise to create a function to avoid code repetition. An implementation might look like:

function injectScript(func) {
    var actualCode = '(' + func + ')();'
    ...
}
injectScript(function() {
   alert("Injected script");
});

Note: Since the function is serialized, the original scope, and all bound properties are lost!

var scriptToInject = function() {
    console.log(typeof scriptToInject);
};
injectScript(scriptToInject);
// Console output:  "undefined"

Sometimes, you want to run some code immediately, e.g. to run some code before the <head> element is created. This can be done by inserting a <script> tag with textContent (see method 2/2b).

An alternative, but not recommended is to use inline events. It is not recommended because if the page defines a Content Security policy that forbids inline scripts, then inline event listeners are blocked. Inline scripts injected by the extension, on the other hand, still run. If you still want to use inline events, this is how:

var actualCode = '// Some code example \n' + 
                 'console.log(document.documentElement.outerHTML);';

document.documentElement.setAttribute('onreset', actualCode);
document.documentElement.dispatchEvent(new CustomEvent('reset'));
document.documentElement.removeAttribute('onreset');

Note: This method assumes that there are no other global event listeners that handle the reset event. If there is, you can also pick one of the other global events. Just open the JavaScript console (F12), type document.documentElement.on, and pick on of the available events.

var GREETING = "Hi, I'm ";
var NAME = "Rob";
var scriptToInject = function() {
    alert(GREETING + NAME);
};

To inject this code, you need to pass the variables as arguments to the anonymous function. Be sure to implement it correctly! The following will not work:

var scriptToInject = function (GREETING, NAME) { ... };
var actualCode = '(' + scriptToInject + ')(' + GREETING + ',' + NAME ')';
// The previous will work for numbers and booleans, but not strings.
// To see why, have a look at the resulting string:
var actualCode = "(function(GREETING, NAME) {...})(Hi I'm,Rob)";
//                                                 ^^^^^^ ^^^ No string literals!

The solution is to use JSON.stringify before passing the argument. Example:

var actualCode = '(' + function(greeting, name) { ...
} + ')(' + JSON.stringify(GREETING) + ',' + JSON.stringify(NAME) + ')';

If you have many variables, it's worthwhile to use JSON.stringify once, to improve readability, as follows:

...
} + ')(' + JSON.stringify([arg1, arg2, arg3, arg4]) + ')';

This answer should be part of official docs. Official docs should ship with recommended way --> 3 ways to do the same thing... Wrong?

@Qantas94Heavy The extension's CSP does not affect content scripts. Only the page's CSP is relevant. Method 1 can be blocked by using a script-src directive that excludes the extension's origin, method 2 can be blocked by using a CSP that excludes "unsafe-inline"`.

Other method: use location.href = "javascript: alert('yeah')"; anywhere in your content script. It's easier for short snippets of code, and can also access the page's JS objects.

@ChrisP Be careful with using javascript:. Code spanning over multiple lines might not work as expected. A line-comment (//) will truncate the remainder, so this will fail: location.href = 'javascript:// Do something <newline> alert(0);';. This can be circumvented by ensuring that you use multi-line comments. Another thing to be careful of is that the result of the expression should be void. javascript:window.x = 'some variable'; will cause the document to unload, and be replaced with the phrase 'some variable'. If used properly, it's indeed an attractive alternative to <script>.

@Lai32290 Using events or HTML attributes, for example using document.currentScript.dataset.foo = 'only strings can be shared'; in the injected script, and then reading it back using script.dataset.foo (assuming that script is a reference to the <script> tag that you injected).

javascript - Insert code into the page context using a content script ...

javascript google-chrome google-chrome-extension youtube-api content-script
Rectangle 27 633

Method 2b: Using a function

Content scripts are executed in an "isolated world" environment. You have to inject your state() method into the page itself.

When you want to use one of the chrome.* APIs in the script, you have to implement a special event handler, as described in this answer: Chrome extension - retrieving Gmail's original message.

Otherwise, if you don't have to use chrome.* APIs, I strongly recommend to inject all of your JS code in the page via adding a <script> tag:

  • Method 2b: Using a function
  • Dynamic values in the injected code
script.js
var s = document.createElement('script');
// TODO: add "script.js" to web_accessible_resources in manifest.json
s.src = chrome.extension.getURL('script.js');
s.onload = function() {
    this.remove();
};
(document.head || document.documentElement).appendChild(s);

Note: If you use this method, the injected script.js file has to be added to the "web_accessible_resources" section

Denying load of chrome-extension://[EXTENSIONID]/script.js. Resources must be listed in the web_accessible_resources manifest key in order to be loaded by pages outside the extension.

var actualCode = `// Code here.
// If you want to use a variable, use $ and curly braces.
// For example, to use a fixed random number:
var someFixedRandomValue = ${ Math.random() };
// NOTE: Do not insert unsafe variables in this way, see below
// at "Dynamic values in the injected code"
`;

var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.remove();

Note: template literals are only supported in Chrome 41 and above. If you want the extension to work in Chrome 40-, use:

var actualCode = ['/* Code here. Example: */' + 'alert(0);',
                  '// Beware! This array have to be joined',
                  '// using a newline. Otherwise, missing semicolons',
                  '// or single-line comments (//) will mess up your',
                  '// code ----->'].join('\n');

For a big chunk of code, quoting the string is not feasible. Instead of using an array, a function can be used, and stringified:

This method works, because the + operator on strings and a function converts all objects to a string. If you intend on using the code more than once, it's wise to create a function to avoid code repetition. An implementation might look like:

function injectScript(func) {
    var actualCode = '(' + func + ')();'
    ...
}
injectScript(function() {
   alert("Injected script");
});

Note: Since the function is serialized, the original scope, and all bound properties are lost!

var scriptToInject = function() {
    console.log(typeof scriptToInject);
};
injectScript(scriptToInject);
// Console output:  "undefined"

Sometimes, you want to run some code immediately, e.g. to run some code before the <head> element is created. This can be done by inserting a <script> tag with textContent (see method 2/2b).

An alternative, but not recommended is to use inline events. It is not recommended because if the page defines a Content Security policy that forbids inline scripts, then inline event listeners are blocked. Inline scripts injected by the extension, on the other hand, still run. If you still want to use inline events, this is how:

var actualCode = '// Some code example \n' + 
                 'console.log(document.documentElement.outerHTML);';

document.documentElement.setAttribute('onreset', actualCode);
document.documentElement.dispatchEvent(new CustomEvent('reset'));
document.documentElement.removeAttribute('onreset');

Note: This method assumes that there are no other global event listeners that handle the reset event. If there is, you can also pick one of the other global events. Just open the JavaScript console (F12), type document.documentElement.on, and pick on of the available events.

var GREETING = "Hi, I'm ";
var NAME = "Rob";
var scriptToInject = function() {
    alert(GREETING + NAME);
};

To inject this code, you need to pass the variables as arguments to the anonymous function. Be sure to implement it correctly! The following will not work:

var scriptToInject = function (GREETING, NAME) { ... };
var actualCode = '(' + scriptToInject + ')(' + GREETING + ',' + NAME ')';
// The previous will work for numbers and booleans, but not strings.
// To see why, have a look at the resulting string:
var actualCode = "(function(GREETING, NAME) {...})(Hi I'm,Rob)";
//                                                 ^^^^^^ ^^^ No string literals!

The solution is to use JSON.stringify before passing the argument. Example:

var actualCode = '(' + function(greeting, name) { ...
} + ')(' + JSON.stringify(GREETING) + ',' + JSON.stringify(NAME) + ')';

If you have many variables, it's worthwhile to use JSON.stringify once, to improve readability, as follows:

...
} + ')(' + JSON.stringify([arg1, arg2, arg3, arg4]) + ')';

This answer should be part of official docs. Official docs should ship with recommended way --> 3 ways to do the same thing... Wrong?

@Qantas94Heavy The extension's CSP does not affect content scripts. Only the page's CSP is relevant. Method 1 can be blocked by using a script-src directive that excludes the extension's origin, method 2 can be blocked by using a CSP that excludes "unsafe-inline"`.

Other method: use location.href = "javascript: alert('yeah')"; anywhere in your content script. It's easier for short snippets of code, and can also access the page's JS objects.

@ChrisP Be careful with using javascript:. Code spanning over multiple lines might not work as expected. A line-comment (//) will truncate the remainder, so this will fail: location.href = 'javascript:// Do something <newline> alert(0);';. This can be circumvented by ensuring that you use multi-line comments. Another thing to be careful of is that the result of the expression should be void. javascript:window.x = 'some variable'; will cause the document to unload, and be replaced with the phrase 'some variable'. If used properly, it's indeed an attractive alternative to <script>.

@Lai32290 Using events or HTML attributes, for example using document.currentScript.dataset.foo = 'only strings can be shared'; in the injected script, and then reading it back using script.dataset.foo (assuming that script is a reference to the <script> tag that you injected).

javascript - Insert code into the page context using a content script ...

javascript google-chrome google-chrome-extension youtube-api content-script
Rectangle 27 632

Method 2b: Using a function

Content scripts are executed in an "isolated world" environment. You have to inject your state() method into the page itself.

When you want to use one of the chrome.* APIs in the script, you have to implement a special event handler, as described in this answer: Chrome extension - retrieving Gmail's original message.

Otherwise, if you don't have to use chrome.* APIs, I strongly recommend to inject all of your JS code in the page via adding a <script> tag:

  • Method 2b: Using a function
  • Dynamic values in the injected code
script.js
var s = document.createElement('script');
// TODO: add "script.js" to web_accessible_resources in manifest.json
s.src = chrome.extension.getURL('script.js');
s.onload = function() {
    this.remove();
};
(document.head || document.documentElement).appendChild(s);

Note: If you use this method, the injected script.js file has to be added to the "web_accessible_resources" section

Denying load of chrome-extension://[EXTENSIONID]/script.js. Resources must be listed in the web_accessible_resources manifest key in order to be loaded by pages outside the extension.

var actualCode = `// Code here.
// If you want to use a variable, use $ and curly braces.
// For example, to use a fixed random number:
var someFixedRandomValue = ${ Math.random() };
// NOTE: Do not insert unsafe variables in this way, see below
// at "Dynamic values in the injected code"
`;

var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.remove();

Note: template literals are only supported in Chrome 41 and above. If you want the extension to work in Chrome 40-, use:

var actualCode = ['/* Code here. Example: */' + 'alert(0);',
                  '// Beware! This array have to be joined',
                  '// using a newline. Otherwise, missing semicolons',
                  '// or single-line comments (//) will mess up your',
                  '// code ----->'].join('\n');

For a big chunk of code, quoting the string is not feasible. Instead of using an array, a function can be used, and stringified:

This method works, because the + operator on strings and a function converts all objects to a string. If you intend on using the code more than once, it's wise to create a function to avoid code repetition. An implementation might look like:

function injectScript(func) {
    var actualCode = '(' + func + ')();'
    ...
}
injectScript(function() {
   alert("Injected script");
});

Note: Since the function is serialized, the original scope, and all bound properties are lost!

var scriptToInject = function() {
    console.log(typeof scriptToInject);
};
injectScript(scriptToInject);
// Console output:  "undefined"

Sometimes, you want to run some code immediately, e.g. to run some code before the <head> element is created. This can be done by inserting a <script> tag with textContent (see method 2/2b).

An alternative, but not recommended is to use inline events. It is not recommended because if the page defines a Content Security policy that forbids inline scripts, then inline event listeners are blocked. Inline scripts injected by the extension, on the other hand, still run. If you still want to use inline events, this is how:

var actualCode = '// Some code example \n' + 
                 'console.log(document.documentElement.outerHTML);';

document.documentElement.setAttribute('onreset', actualCode);
document.documentElement.dispatchEvent(new CustomEvent('reset'));
document.documentElement.removeAttribute('onreset');

Note: This method assumes that there are no other global event listeners that handle the reset event. If there is, you can also pick one of the other global events. Just open the JavaScript console (F12), type document.documentElement.on, and pick on of the available events.

var GREETING = "Hi, I'm ";
var NAME = "Rob";
var scriptToInject = function() {
    alert(GREETING + NAME);
};

To inject this code, you need to pass the variables as arguments to the anonymous function. Be sure to implement it correctly! The following will not work:

var scriptToInject = function (GREETING, NAME) { ... };
var actualCode = '(' + scriptToInject + ')(' + GREETING + ',' + NAME ')';
// The previous will work for numbers and booleans, but not strings.
// To see why, have a look at the resulting string:
var actualCode = "(function(GREETING, NAME) {...})(Hi I'm,Rob)";
//                                                 ^^^^^^ ^^^ No string literals!

The solution is to use JSON.stringify before passing the argument. Example:

var actualCode = '(' + function(greeting, name) { ...
} + ')(' + JSON.stringify(GREETING) + ',' + JSON.stringify(NAME) + ')';

If you have many variables, it's worthwhile to use JSON.stringify once, to improve readability, as follows:

...
} + ')(' + JSON.stringify([arg1, arg2, arg3, arg4]) + ')';

This answer should be part of official docs. Official docs should ship with recommended way --> 3 ways to do the same thing... Wrong?

@Qantas94Heavy The extension's CSP does not affect content scripts. Only the page's CSP is relevant. Method 1 can be blocked by using a script-src directive that excludes the extension's origin, method 2 can be blocked by using a CSP that excludes "unsafe-inline"`.

Other method: use location.href = "javascript: alert('yeah')"; anywhere in your content script. It's easier for short snippets of code, and can also access the page's JS objects.

@ChrisP Be careful with using javascript:. Code spanning over multiple lines might not work as expected. A line-comment (//) will truncate the remainder, so this will fail: location.href = 'javascript:// Do something <newline> alert(0);';. This can be circumvented by ensuring that you use multi-line comments. Another thing to be careful of is that the result of the expression should be void. javascript:window.x = 'some variable'; will cause the document to unload, and be replaced with the phrase 'some variable'. If used properly, it's indeed an attractive alternative to <script>.

@Lai32290 Using events or HTML attributes, for example using document.currentScript.dataset.foo = 'only strings can be shared'; in the injected script, and then reading it back using script.dataset.foo (assuming that script is a reference to the <script> tag that you injected).

javascript - Insert code into the page context using a content script ...

javascript google-chrome google-chrome-extension youtube-api content-script
Rectangle 27 618

Proper uses of IMG

  • Use IMG if you intend to have people print your page and you want the image to be included by default. JayTee
  • Use IMG (with alt text) when the image has an important semantic meaning, such as a warning icon. This ensures that the meaning of the image can be communicated in all user-agents, including screen readers.
  • Use IMG plus alt attribute if the image is part of the content such as a logo or diagram or person (real person, not stock photo people). sanchothefat
  • Use IMG if you rely on browser scaling to render an image in proportion to text size.
IMG
z-index
  • Using img instead of background-image can dramatically improve performance of animations over a background.
  • Use CSS background images when doing image-replacement of text eg. paragraphs/headers. sanchothefat
  • Use background-image if you intend to have people print your page and you do not want the image to be included by default. JayTee
  • Use background-image if you need for only a portion of the image to be visible, as with CSS sprites.
  • Use background-image with background-size:cover in order to stretch a background image to fill its entire window.

I'm still iffy on the background images for text replacement part. I see people using background-images then using text-indent: -9999px for the text. However I know having text indents like this used to be bad for SEO and I'd imagine it still must be for some search engines. But most important, if you turn images off but leave css on the image dissapears but the text is still off the screen. As far as I am concerned the alt text on an image is for if images are not displays so img tags are better.

Pragmatic Use of backbround image: When you don't want to loose hair about vertical centering problems (of images of varying vertical size) ;)

Yes, vertical centering problems - bring on Flexbox!

@BinaryFunt - <div class="my-css-page-styles" style="background-image:url(blah.png);"></div> That way you can style it in your CSS stylesheet but if the background image is more a question of content than style then you're still editing it from the HTML side of things.

There seems to be a clickbait in point 5 of pragmatic uses of IMG - pointing to a japanese blog post about cosmetics. the link is www.ajaxline.com/browsers-performance-in-dependence-of-html-coding [DO NOT CLICK THIS]

html - When to use IMG vs. CSS background-image? - Stack Overflow

html css image background-image
Rectangle 27 613

Proper uses of IMG

  • Use IMG if you intend to have people print your page and you want the image to be included by default. JayTee
  • Use IMG (with alt text) when the image has an important semantic meaning, such as a warning icon. This ensures that the meaning of the image can be communicated in all user-agents, including screen readers.
  • Use IMG plus alt attribute if the image is part of the content such as a logo or diagram or person (real person, not stock photo people). sanchothefat
  • Use IMG if you rely on browser scaling to render an image in proportion to text size.
IMG
z-index
  • Using img instead of background-image can dramatically improve performance of animations over a background.
  • Use CSS background images when doing image-replacement of text eg. paragraphs/headers. sanchothefat
  • Use background-image if you intend to have people print your page and you do not want the image to be included by default. JayTee
  • Use background-image if you need for only a portion of the image to be visible, as with CSS sprites.
  • Use background-image with background-size:cover in order to stretch a background image to fill its entire window.

I'm still iffy on the background images for text replacement part. I see people using background-images then using text-indent: -9999px for the text. However I know having text indents like this used to be bad for SEO and I'd imagine it still must be for some search engines. But most important, if you turn images off but leave css on the image dissapears but the text is still off the screen. As far as I am concerned the alt text on an image is for if images are not displays so img tags are better.

Pragmatic Use of backbround image: When you don't want to loose hair about vertical centering problems (of images of varying vertical size) ;)

Yes, vertical centering problems - bring on Flexbox!

@BinaryFunt - <div class="my-css-page-styles" style="background-image:url(blah.png);"></div> That way you can style it in your CSS stylesheet but if the background image is more a question of content than style then you're still editing it from the HTML side of things.

There seems to be a clickbait in point 5 of pragmatic uses of IMG - pointing to a japanese blog post about cosmetics. the link is www.ajaxline.com/browsers-performance-in-dependence-of-html-coding [DO NOT CLICK THIS]

html - When to use IMG vs. CSS background-image? - Stack Overflow

html css image background-image
Rectangle 27 25

Output which theme template file a post/page is using in the header

add_action('wp_head', 'show_template');
function show_template() {
    global $template;
    print_r($template);
}
<div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>

You can have crazy long divs in your source that might look like this or even longer:

This can really start to clutter your source and seem rather unnecessary in most cases, going 3-4 deep is good enough.

For the top example we can slice the output like so:

// slice crazy long div outputs
    function category_id_class($classes) {
        global $post;
        foreach((get_the_category($post->ID)) as $category)
            $classes[] = $category->category_nicename;
            return array_slice($classes, 0,5);
    }
    add_filter('post_class', 'category_id_class');

this slices the output to only include the first 5 values, so the above example becomes:

<div id="post-4" class="post-4 post type-post hentry category-uncategorized">
function any_ptype_on_cat($request) {
 if ( isset($request['category_name']) )
  $request['post_type'] = 'any';

 return $request;
}
add_filter('request', 'any_ptype_on_cat');

This was already posted but it did not have the full list of items. Especially those annoying "incoming links!"

add_action('wp_dashboard_setup', 'my_custom_dashboard_widgets');

function my_custom_dashboard_widgets() {
global $wp_meta_boxes;
 //Right Now - Comments, Posts, Pages at a glance
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_right_now']);
//Recent Comments
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_recent_comments']);
//Incoming Links
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_incoming_links']);
//Plugins - Popular, New and Recently updated Wordpress Plugins
unset($wp_meta_boxes['dashboard']['normal']['core']['dashboard_plugins']);

//Wordpress Development Blog Feed
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_primary']);
//Other Wordpress News Feed
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_secondary']);
//Quick Press Form
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_quick_press']);
//Recent Drafts List
unset($wp_meta_boxes['dashboard']['side']['core']['dashboard_recent_drafts']);
}

instead return to the top of the page. You know how when you click "read more" it will jump to the spot in the page which can be annoying, this makes it just load the page normally, no jumping!

function remove_more_jump_link($link) { 
$offset = strpos($link, '#more-');
if ($offset) {
$end = strpos($link, '"',$offset);
}
if ($end) {
$link = substr_replace($link, '', $offset, $end-$offset);
}
return $link;
}
add_filter('the_content_more_link', 'remove_more_jump_link');
function remove_menus()
{
    global $menu;
    global $current_user;
    get_currentuserinfo();

    if($current_user->user_login == 'username')
    {
        $restricted = array(__('Posts'),
                            __('Media'),
                            __('Links'),
                            __('Pages'),
                            __('Comments'),
                            __('Appearance'),
                            __('Plugins'),
                            __('Users'),
                            __('Tools'),
                            __('Settings')
        );
        end ($menu);
        while (prev($menu)){
            $value = explode(' ',$menu[key($menu)][0]);
            if(in_array($value[0] != NULL?$value[0]:"" , $restricted)){unset($menu[key($menu)]);}
        }// end while

    }// end if
}
add_action('admin_menu', 'remove_menus');

//alternatively you can use if($current_user->user_login != 'admin') instead, probably more useful

//tag cloud custom
add_filter('widget_tag_cloud_args','style_tags');
function style_tags($args) {
$args = array(
     'largest'    => '10',
     'smallest'   => '10',
     'format'     => 'list',
     );
return $args;
}

( default is 6 or 12 hours I forget (1800 =30min).

add_filter( 'wp_feed_cache_transient_lifetime', create_function('$fixrss', 'return 1800;') );

could you please split up each of these into seperate answers within the next few weeks. I was going to do it for you but did not want to make it seem like I am taking credit for your answers. In any case - I am trying to keep this organized so users can easily find the information they are looking for. Thanks in advance

I was just using the code "Restrict ADMIN menu items based on username, replace username with an actual user's name" which is great but could you update the code to also show how this can be done for a specific "user role". I think this would be very useful!

plugins functions customization admin pluggable
Rectangle 27 1

1) Using the while (recommended)

You indeed doubled the posts using two loop structures: both the while and the foreach. Thing is: when WP calls your category-3.php page, the WP_Query is already populated with posts from category ID 3. Therefore, you do not need to perform a new query to fetch those posts.

So you could use one of each solutions separately, but not together:

<?php 
$number = 0;
global $post;
if ( have_posts() ) while ( have_posts() ) : the_post() ; 
  setup_postdata($post); 
  $number++;
endwhile;
?>
<?php           
$myposts = get_posts('posts_per_page=-1&category=3');
$number = 0;

if($myposts):
    foreach($myposts as $post) :
       setup_postdata($post); 
       $number++;
    endforeach;
endif;
?>

Thanks, Solution 1 works! I didn't know where to place the number iterator at start, and the global $post was also new to me. Cheers!!!

Wordpress category template page doubling the posts - Stack Overflow

wordpress-theming wordpress
Rectangle 27 186

Using native localStorage (old reply from 2011)

It is pretty easy to use like the other Chrome APIs and you can use it from any page context within Chrome.

// Save it using the Chrome extension storage API.
    chrome.storage.sync.set({'foo': 'hello', 'bar': 'hi'}, function() {
      console.log('Settings saved');
    });

    // Read it using the storage API
    chrome.storage.sync.get(['foo', 'bar'], function(items) {
      message('Settings retrieved', items);
    });

To use it, make sure you define it in the manifest:

"permissions": [
      "storage"
    ],

There are methods to "remove", "clear", "getBytesInUse", and an event listener to listen for changed storage "onChanged"

Content scripts run in the context of webpages, not extension pages. Therefore, if you're accessing localStorage from your contentscript, it will be the storage from that webpage, not the extension page storage.

The first thing you do is tell your content script to send a request to your extension to fetch some data, and that data can be your extension localStorage:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.method == "getStatus")
      sendResponse({status: localStorage['status']});
    else
      sendResponse({}); // snub them.
});

You can do an API around that to get generic localStorage data to your content script, or perhaps, get the whole localStorage array.

To be fancy and generic ...

chrome.runtime.sendMessage({method: "getLocalStorage", key: "status"}, function(response) {
  console.log(response.data);
});
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.method == "getLocalStorage")
      sendResponse({data: localStorage[request.key]});
    else
      sendResponse({}); // snub them.
});

Obviously, request could also be {method:'getStorage', key: 'status'}, and the listener would respond with the corresponding data.

What if I want everything from the localStorage to be transferred to the extension? Can I write sendResponse({data: localStorage}); ?

The background page and options page belong to the same extension context, so you don't need content scripts or messaging. You can call localStorage directly from the options page or use chrome.extension.getBackgroundPage from the options page.

Thats strange. I'm setting few options in options page and creating context menus based on them in background page. The thing is, if I set a variable in localStorage from options page, it doesnt get reflected to the background page immediately(i.e. No new contextmenu), unless I disable and re-enable the extension. Any reason you can think of?

local storage - Chrome extension: accessing localStorage in content sc...

google-chrome-extension local-storage content-script
Rectangle 27 186

Using native localStorage (old reply from 2011)

It is pretty easy to use like the other Chrome APIs and you can use it from any page context within Chrome.

// Save it using the Chrome extension storage API.
    chrome.storage.sync.set({'foo': 'hello', 'bar': 'hi'}, function() {
      console.log('Settings saved');
    });

    // Read it using the storage API
    chrome.storage.sync.get(['foo', 'bar'], function(items) {
      message('Settings retrieved', items);
    });

To use it, make sure you define it in the manifest:

"permissions": [
      "storage"
    ],

There are methods to "remove", "clear", "getBytesInUse", and an event listener to listen for changed storage "onChanged"

Content scripts run in the context of webpages, not extension pages. Therefore, if you're accessing localStorage from your contentscript, it will be the storage from that webpage, not the extension page storage.

The first thing you do is tell your content script to send a request to your extension to fetch some data, and that data can be your extension localStorage:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.method == "getStatus")
      sendResponse({status: localStorage['status']});
    else
      sendResponse({}); // snub them.
});

You can do an API around that to get generic localStorage data to your content script, or perhaps, get the whole localStorage array.

To be fancy and generic ...

chrome.runtime.sendMessage({method: "getLocalStorage", key: "status"}, function(response) {
  console.log(response.data);
});
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.method == "getLocalStorage")
      sendResponse({data: localStorage[request.key]});
    else
      sendResponse({}); // snub them.
});

Obviously, request could also be {method:'getStorage', key: 'status'}, and the listener would respond with the corresponding data.

What if I want everything from the localStorage to be transferred to the extension? Can I write sendResponse({data: localStorage}); ?

The background page and options page belong to the same extension context, so you don't need content scripts or messaging. You can call localStorage directly from the options page or use chrome.extension.getBackgroundPage from the options page.

Thats strange. I'm setting few options in options page and creating context menus based on them in background page. The thing is, if I set a variable in localStorage from options page, it doesnt get reflected to the background page immediately(i.e. No new contextmenu), unless I disable and re-enable the extension. Any reason you can think of?

local storage - Chrome extension: accessing localStorage in content sc...

google-chrome-extension local-storage content-script
Rectangle 27 180

Using native localStorage (old reply from 2011)

It is pretty easy to use like the other Chrome APIs and you can use it from any page context within Chrome.

// Save it using the Chrome extension storage API.
    chrome.storage.sync.set({'foo': 'hello', 'bar': 'hi'}, function() {
      console.log('Settings saved');
    });

    // Read it using the storage API
    chrome.storage.sync.get(['foo', 'bar'], function(items) {
      message('Settings retrieved', items);
    });

To use it, make sure you define it in the manifest:

"permissions": [
      "storage"
    ],

There are methods to "remove", "clear", "getBytesInUse", and an event listener to listen for changed storage "onChanged"

Content scripts run in the context of webpages, not extension pages. Therefore, if you're accessing localStorage from your contentscript, it will be the storage from that webpage, not the extension page storage.

The first thing you do is tell your content script to send a request to your extension to fetch some data, and that data can be your extension localStorage:

chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.method == "getStatus")
      sendResponse({status: localStorage['status']});
    else
      sendResponse({}); // snub them.
});

You can do an API around that to get generic localStorage data to your content script, or perhaps, get the whole localStorage array.

To be fancy and generic ...

chrome.runtime.sendMessage({method: "getLocalStorage", key: "status"}, function(response) {
  console.log(response.data);
});
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
    if (request.method == "getLocalStorage")
      sendResponse({data: localStorage[request.key]});
    else
      sendResponse({}); // snub them.
});

Obviously, request could also be {method:'getStorage', key: 'status'}, and the listener would respond with the corresponding data.

What if I want everything from the localStorage to be transferred to the extension? Can I write sendResponse({data: localStorage}); ?

The background page and options page belong to the same extension context, so you don't need content scripts or messaging. You can call localStorage directly from the options page or use chrome.extension.getBackgroundPage from the options page.

Thats strange. I'm setting few options in options page and creating context menus based on them in background page. The thing is, if I set a variable in localStorage from options page, it doesnt get reflected to the background page immediately(i.e. No new contextmenu), unless I disable and re-enable the extension. Any reason you can think of?

local storage - Chrome extension: accessing localStorage in content sc...

google-chrome-extension local-storage content-script
Rectangle 27 1

Manual Creation using the same method Visual Studio uses

If building from scratch and don't care about how Visual Studio does it, you can start with some basics from this solution here, as well as the other links referenced in the accepted solution on the same page.

For reference, some of the files generated by the Visual Studio add reference method below, are stored within a subfolder Web References/Example (where Example is the name of the variable used to access the reference) and contains the following :

<?xml version="1.0" encoding="utf-8"?>
<DiscoveryClientResultsFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Results>
    <DiscoveryClientResult referenceType="System.Web.Services.Discovery.ContractReference" url="http://example.com/api/index.php?wsdl" filename="index.wsdl" />
  </Results>
</DiscoveryClientResultsFile>

This file is the complete raw wsdl source file (well formatted xml).

This file contains code to initialize all the methods and properties and is the base class which extends System.Web.Services.Protocols.SoapHttpClientProtocol

The properties assigned to the class (sorry I am stripping from an old VB.NET project: look like the following :

<System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.6.1586.0"),  _
 System.Diagnostics.DebuggerStepThroughAttribute(),  _
 System.ComponentModel.DesignerCategoryAttribute("code"),  _
 System.Web.Services.WebServiceBindingAttribute(Name:="ExampleAPIBinding", [Namespace]:="urn:ExampleAPI"),  _
 System.Xml.Serialization.SoapIncludeAttribute(GetType(MyCustomType1)),  _
 System.Xml.Serialization.SoapIncludeAttribute(GetType(MyCustomType2)),  _

 Partial Public Class ExampleAPI
    Inherits System.Web.Services.Protocols.SoapHttpClientProtocol

 End Class
<?xml version="1.0" encoding="utf-8"?>
<!--
    This file is automatically generated by Visual Studio .Net. It is
    used to store generic object data source configuration information.
    Renaming the file extension or editing the content of this file may
    cause the file to be unrecognizable by the program.
-->
<GenericObjectDataSource DisplayName="MyMethodName" Version="1.0" xmlns="urn:schemas-microsoft-com:xml-msdatasource">
   <TypeInfo>ExampleAPI.SOAP.ClientMerchant, Web References.SOAP.Reference.vb.dll, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null</TypeInfo>
</GenericObjectDataSource>

Right-click your project in Project explorer, and select Add > Service Reference..

If successful (well formatted WSDL is found), the [Add Reference] button will be enabled. Click that, and it will add the reference to your project.

Hehe, that's awesome, mate but I suspect that you missed the disclaimer. I don't have Project Explorer because I'm working with Visual Studio Code (i.e. VS Code not VS 20xx). It's a new, lightweight IDE from MS. Check this out.

@KonradViltersten - I did miss that tag as it's tagged Visual Studio as well. However I am pretty sure you can simply copy the output from that. I don't know if there is a quick way (in either case) to embed a reference as SOAP is quite old (while many still use) I do not believe a natural way was implemented in VSCode.

I fear that you're right. As for the "quite old" part - well, our banking system seems to believe that working with NET 2.0 is okay and NET 3.5 feel too hasty to upgrade to, so I need to work with this dino tech.

@KonradViltersten - I added some sample code from an old VB.NET project which hopefully can assist when building it if doing so from scratch (might be able to do much cleaner than Visual Studio's generated version which imho is rather bloated).

c# - How to reference a WSDL file using Visual Studio Code? - Stack Ov...

c# visual-studio web-services asp.net-core visual-studio-code
Rectangle 27 6

Are you using a CMS? They tend to like changing urls which could break your application.

With it, you can register components and they automatically get exposed to the dom.

container.register('AnimalBox', AnimalBox);
container.register('AnimalSearchBox', AnimalSearchBox);

The above will be automatically replaced with your react components.

You can then automatically pass properties (or props) to your components too:

<div data-component="AnimalBox" data-prop-size="small"></div>

This will expose size as a prop to your component. There are additional options for passing other types such as json, array's, ints, floats etc.

javascript - Using React in a multi-page app - Stack Overflow

javascript node.js reactjs
Rectangle 27 1

I try to call a list of products from a CMS page.

Although I have tried in many ways, I didn't find a solution for this. Either you can call a list of products via some attribute but can't sort that list it in a way or you can sort the products of a givenn category but you can't escape the toolbar then.

But I found something else which I find quite noteworthy: when I call for a category by using

{{block type="catalog/product_list" category_id="10" template="catalog/product/list.phtml"}}

Here, a product list is created with the toolbar. However, there's no pager! Although is says for example "product 1 to 12 of 35", there's no page navigation! This I found in 3 different Magento shops to be the case.

Can anybody approve this? Is there a way to get the pager included, when calling category products from a CMS page?

magento-1.7 products toolbar pager cms-block
Rectangle 27 17

I've used Dust-Me Selectors before, which is a Firefox plugin. It's very easy to use and versatile as it maintains a combined list across a number of pages of which CSS values are used.

The downside is that I wasn't able to automate it to spider an entire site, so I ended up using it just on key pages/tempates of my site. It is very useful nonetheless.

Contrary to the comment above Dust-Me Selectors 2.2 is compatible with Firefox 3.6 (I've just installed it).

Does it have a way to export a copy of a specified css file with all the unused stuff removed?

@rraallw Yep. This was the only tool that would work and still respect media queries. It has an annoying bug where it litters the output CSS file with the word "undefined," but a quick find 'n replace fixes that. Once the tool runs, hit the "clean" button on the "Unused selectors" tab for each file sheet. It will generate the CSS you can export.

Extracting only the css used in a specific page - Stack Overflow

css
Rectangle 27 119

Are you using Perl's built in features to help you find problems?

This answer is intended as a general framework for working through problems with Perl CGI scripts and originally appeared on Perlmonks as Troubleshooting Perl CGI Scripts. It is not a complete guide to every problem that you may encounter, nor a tutorial on bug squashing. It is just the culmination of my experience debugging CGI scripts for ten (plus!) years. This page seems to have had many different homes, and I seem to forget it exists, so I'm adding it to the StackOverflow. You can send any comments or suggestions to me at bdfoy@cpan.org. It's also community wiki, but don't go too nuts. :)

Turn on warnings to let Perl warn you about questionable parts of your code. You can do this from the command line with the -w switch so you don't have to change any code or add a pragma to every file:

% perl -w program.pl

However, you should force yourself to always clear up questionable code by adding the warnings pragma to all of your files:

use warnings;

If you need more information than the short warning message, use the diagnostics pragma to get more information, or look in the perldiag documentation:

use diagnostics;

The server is expecting the first output from a CGI script to be the CGI header. Typically that might be as simple as print "Content-type: text/plain\n\n"; or with CGI.pm and its derivatives, print header(). Some servers are sensitive to error output (on STDERR) showing up before standard output (on STDOUT).

Add the line

use CGI::Carp 'fatalsToBrowser';

to your script. This also sends compilation errors to the browser window. Be sure to remove this before moving to a production environment, as the extra information can be a security risk.

Servers keep error logs (or they should, at least). Error output from the server and from your script should show up there. Find the error log and see what it says. There isn't a standard place for log files. Look in the server configuration for their location, or ask the server admin. You can also use tools such as CGI::Carp to keep your own log files.

If you see errors like "Permission denied" or "Method not implemented", it probably means that your script is not readable and executable by the web server user. On flavors of Unix, changing the mode to 755 is recommended: chmod 755 filename. Never set a mode to 777!

Remember that Perl automatically creates variables when you first use them. This is a feature, but sometimes can cause bugs if you mistype a variable name. The pragma use strict will help you find those sorts of errors. It's annoying until you get used to it, but your programming will improve significantly after awhile and you will be free to make different mistakes.

You can check for compilation errors by using the -c switch. Concentrate on the first errors reported. Rinse, repeat. If you are getting really strange errors, check to ensure that your script has the right line endings. If you FTP in binary mode, checkout from CVS, or something else that does not handle line end translation, the web server may see your script as one big line. Transfer Perl scripts in ASCII mode.

If your script complains about insecure dependencies, you are probably using the -T switch to turn on taint mode, which is a good thing since it keeps you have passing unchecked data to the shell. If it is complaining it is doing its job to help us write more secure scripts. Any data originating from outside of the program (i.e. the environment) is considered tainted. Environment variables such as PATH and LD_LIBRARY_PATH are particularly troublesome. You have to set these to a safe value or unset them completely, as I recommend. You should be using absolute paths anyway. If taint checking complains about something else, make sure that you have untainted the data. See perlsec man page for details.

Does the script output what you expect when run from the command line? Is the header output first, followed by a blank line? Remember that STDERR may be merged with STDOUT if you are on a terminal (e.g. an interactive session), and due to buffering may show up in a jumbled order. Turn on Perl's autoflush feature by setting $| to a true value. Typically you might see $|++; in CGI programs. Once set, every print and write will immediately go to the output rather than being buffered. You have to set this for each filehandle. Use select to change the default filehandle, like so:

$|++;                            #sets $| for STDOUT
$old_handle = select( STDERR );  #change to STDERR
$|++;                            #sets $| for STDERR
select( $old_handle );           #change back to STDOUT

Either way, the first thing output should be the CGI header followed by a blank line.

The web server environment is usually a lot more limited than your command line environment, and has extra information about the request. If your script runs fine from the command line, you might try simulating a web server environment. If the problem appears, you have an environment problem.

PATH
LD_LIBRARY_PATH
ORACLE_*
REQUEST_METHOD
GET
HEAD
POST
SERVER_PORT
  • REMOTE_USER (if you are doing protected access stuff)

Recent versions of CGI.pm ( > 2.75 ) require the -debug flag to get the old (useful) behavior, so you might have to add it to your CGI.pm imports.

use CGI qw(-debug)

Those functions print to STDERR unless you have redefined them. They don't output a CGI header, either. You can get the same functionality with packages such as CGI::Carp

If you think your script is doing the right thing, and when you perform the request manually you get the right output, the browser might be the culprit. Clear the cache and set the cache size to zero while testing. Remember that some browsers are really stupid and won't actually reload new content even though you tell it to do so. This is especially prevalent in cases where the URL path is the same, but the content changes (e.g. dynamic images).

The file system path to a script is not necessarily directly related to the URL path to the script. Make sure you have the right directory, even if you have to write a short test script to test this. Furthermore, are you sure that you are modifying the correct file? If you don't see any effect with your changes, you might be modifying a different file, or uploading a file to the wrong place. (This is, by the way, my most frequent cause of such trouble ;)

If your problem is related to parsing the CGI input and you aren't using a widely tested module like CGI.pm, CGI::Request, CGI::Simple or CGI::Lite, use the module and get on with life. CGI.pm has a cgi-lib.pl compatibility mode which can help you solve input problems due to older CGI parser implementations.

If you are running external commands with system, back ticks, or other IPC facilities, you should use an absolute path to the external program. Not only do you know exactly what you are running, but you avoid some security problems as well. If you are opening files for either reading or writing, use an absolute path. The CGI script may have a different idea about the current directory than you do. Alternatively, you can do an explicit chdir() to put you in the right place.

Most Perl functions will tell you if they worked or not and will set $! on failure. Did you check the return value and examine $! for error messages? Did you check $@ if you were using eval?

The latest stable version of Perl is 5.16.2. Are you using an older version? Different versions of Perl may have different ideas of warnings.

Different servers may act differently in the same situation. The same server product may act differently with different configurations. Include as much of this information as you can in any request for help.

Serious CGI programmers should know as much about the server as possible - including not only the server features and behavior, but also the local configuration. The documentation for your server might not be available to you if you are using a commercial product. Otherwise, the documentation should be on your server. If it isn't, look for it on the web.

It's likely that someone has had your problem before, and that someone (possibly me) has answered it in this newsgroup. Although this newsgroup has passed its heyday, the collected wisdom from the past can sometimes be useful.

In large systems, it may be difficult to track down a bug since so many things are happening. Try to reproduce the problem behavior with the shortest possible script. Knowing the problem is most of the fix. This may be certainly time-consuming, but you haven't found the problem yet and you're running out of options. :)

Seriously. Sometimes we can get so wrapped up in the problem that we develop "perceptual narrowing" (tunnel vision). Taking a break, getting a cup of coffee, or blasting some bad guys in [Duke Nukem,Quake,Doom,Halo,COD] might give you the fresh perspective that you need to re-approach the problem.

Seriously again. Sometimes explaining the problem aloud leads us to our own answers. Talk to the penguin (plush toy) because your co-workers aren't listening. If you are interested in this as a serious debugging tool (and I do recommend it if you haven't found the problem by now), you might also like to read The Psychology of Computer Programming.

Seems like you might want to remove the link to the CGI meta FAQ. Is 5.12.1 considered "stable"?

Why not $|=1 instead of $|++?

Why $|=1 instead of $|++? It doesn't really make a difference, and even then, $| is magical.

Nice answer, I think it might be worth mentioning that some of these solutions should be purely for troubleshooting and not put into production code. use strict is generally good to use at all times, whereas using fatalsToBrowser may not be advised in production, especially if you're using die.

How can I troubleshoot my Perl CGI script? - Stack Overflow

perl cgi
Rectangle 27 118

Are you using Perl's built in features to help you find problems?

This answer is intended as a general framework for working through problems with Perl CGI scripts and originally appeared on Perlmonks as Troubleshooting Perl CGI Scripts. It is not a complete guide to every problem that you may encounter, nor a tutorial on bug squashing. It is just the culmination of my experience debugging CGI scripts for ten (plus!) years. This page seems to have had many different homes, and I seem to forget it exists, so I'm adding it to the StackOverflow. You can send any comments or suggestions to me at bdfoy@cpan.org. It's also community wiki, but don't go too nuts. :)

Turn on warnings to let Perl warn you about questionable parts of your code. You can do this from the command line with the -w switch so you don't have to change any code or add a pragma to every file:

% perl -w program.pl

However, you should force yourself to always clear up questionable code by adding the warnings pragma to all of your files:

use warnings;

If you need more information than the short warning message, use the diagnostics pragma to get more information, or look in the perldiag documentation:

use diagnostics;

The server is expecting the first output from a CGI script to be the CGI header. Typically that might be as simple as print "Content-type: text/plain\n\n"; or with CGI.pm and its derivatives, print header(). Some servers are sensitive to error output (on STDERR) showing up before standard output (on STDOUT).

Add the line

use CGI::Carp 'fatalsToBrowser';

to your script. This also sends compilation errors to the browser window. Be sure to remove this before moving to a production environment, as the extra information can be a security risk.

Servers keep error logs (or they should, at least). Error output from the server and from your script should show up there. Find the error log and see what it says. There isn't a standard place for log files. Look in the server configuration for their location, or ask the server admin. You can also use tools such as CGI::Carp to keep your own log files.

If you see errors like "Permission denied" or "Method not implemented", it probably means that your script is not readable and executable by the web server user. On flavors of Unix, changing the mode to 755 is recommended: chmod 755 filename. Never set a mode to 777!

Remember that Perl automatically creates variables when you first use them. This is a feature, but sometimes can cause bugs if you mistype a variable name. The pragma use strict will help you find those sorts of errors. It's annoying until you get used to it, but your programming will improve significantly after awhile and you will be free to make different mistakes.

You can check for compilation errors by using the -c switch. Concentrate on the first errors reported. Rinse, repeat. If you are getting really strange errors, check to ensure that your script has the right line endings. If you FTP in binary mode, checkout from CVS, or something else that does not handle line end translation, the web server may see your script as one big line. Transfer Perl scripts in ASCII mode.

If your script complains about insecure dependencies, you are probably using the -T switch to turn on taint mode, which is a good thing since it keeps you have passing unchecked data to the shell. If it is complaining it is doing its job to help us write more secure scripts. Any data originating from outside of the program (i.e. the environment) is considered tainted. Environment variables such as PATH and LD_LIBRARY_PATH are particularly troublesome. You have to set these to a safe value or unset them completely, as I recommend. You should be using absolute paths anyway. If taint checking complains about something else, make sure that you have untainted the data. See perlsec man page for details.

Does the script output what you expect when run from the command line? Is the header output first, followed by a blank line? Remember that STDERR may be merged with STDOUT if you are on a terminal (e.g. an interactive session), and due to buffering may show up in a jumbled order. Turn on Perl's autoflush feature by setting $| to a true value. Typically you might see $|++; in CGI programs. Once set, every print and write will immediately go to the output rather than being buffered. You have to set this for each filehandle. Use select to change the default filehandle, like so:

$|++;                            #sets $| for STDOUT
$old_handle = select( STDERR );  #change to STDERR
$|++;                            #sets $| for STDERR
select( $old_handle );           #change back to STDOUT

Either way, the first thing output should be the CGI header followed by a blank line.

The web server environment is usually a lot more limited than your command line environment, and has extra information about the request. If your script runs fine from the command line, you might try simulating a web server environment. If the problem appears, you have an environment problem.

PATH
LD_LIBRARY_PATH
ORACLE_*
REQUEST_METHOD
GET
HEAD
POST
SERVER_PORT
  • REMOTE_USER (if you are doing protected access stuff)

Recent versions of CGI.pm ( > 2.75 ) require the -debug flag to get the old (useful) behavior, so you might have to add it to your CGI.pm imports.

use CGI qw(-debug)

Those functions print to STDERR unless you have redefined them. They don't output a CGI header, either. You can get the same functionality with packages such as CGI::Carp

If you think your script is doing the right thing, and when you perform the request manually you get the right output, the browser might be the culprit. Clear the cache and set the cache size to zero while testing. Remember that some browsers are really stupid and won't actually reload new content even though you tell it to do so. This is especially prevalent in cases where the URL path is the same, but the content changes (e.g. dynamic images).

The file system path to a script is not necessarily directly related to the URL path to the script. Make sure you have the right directory, even if you have to write a short test script to test this. Furthermore, are you sure that you are modifying the correct file? If you don't see any effect with your changes, you might be modifying a different file, or uploading a file to the wrong place. (This is, by the way, my most frequent cause of such trouble ;)

If your problem is related to parsing the CGI input and you aren't using a widely tested module like CGI.pm, CGI::Request, CGI::Simple or CGI::Lite, use the module and get on with life. CGI.pm has a cgi-lib.pl compatibility mode which can help you solve input problems due to older CGI parser implementations.

If you are running external commands with system, back ticks, or other IPC facilities, you should use an absolute path to the external program. Not only do you know exactly what you are running, but you avoid some security problems as well. If you are opening files for either reading or writing, use an absolute path. The CGI script may have a different idea about the current directory than you do. Alternatively, you can do an explicit chdir() to put you in the right place.

Most Perl functions will tell you if they worked or not and will set $! on failure. Did you check the return value and examine $! for error messages? Did you check $@ if you were using eval?

The latest stable version of Perl is 5.16.2. Are you using an older version? Different versions of Perl may have different ideas of warnings.

Different servers may act differently in the same situation. The same server product may act differently with different configurations. Include as much of this information as you can in any request for help.

Serious CGI programmers should know as much about the server as possible - including not only the server features and behavior, but also the local configuration. The documentation for your server might not be available to you if you are using a commercial product. Otherwise, the documentation should be on your server. If it isn't, look for it on the web.

It's likely that someone has had your problem before, and that someone (possibly me) has answered it in this newsgroup. Although this newsgroup has passed its heyday, the collected wisdom from the past can sometimes be useful.

In large systems, it may be difficult to track down a bug since so many things are happening. Try to reproduce the problem behavior with the shortest possible script. Knowing the problem is most of the fix. This may be certainly time-consuming, but you haven't found the problem yet and you're running out of options. :)

Seriously. Sometimes we can get so wrapped up in the problem that we develop "perceptual narrowing" (tunnel vision). Taking a break, getting a cup of coffee, or blasting some bad guys in [Duke Nukem,Quake,Doom,Halo,COD] might give you the fresh perspective that you need to re-approach the problem.

Seriously again. Sometimes explaining the problem aloud leads us to our own answers. Talk to the penguin (plush toy) because your co-workers aren't listening. If you are interested in this as a serious debugging tool (and I do recommend it if you haven't found the problem by now), you might also like to read The Psychology of Computer Programming.

Seems like you might want to remove the link to the CGI meta FAQ. Is 5.12.1 considered "stable"?

Why not $|=1 instead of $|++?

Why $|=1 instead of $|++? It doesn't really make a difference, and even then, $| is magical.

Nice answer, I think it might be worth mentioning that some of these solutions should be purely for troubleshooting and not put into production code. use strict is generally good to use at all times, whereas using fatalsToBrowser may not be advised in production, especially if you're using die.

How can I troubleshoot my Perl CGI script? - Stack Overflow

perl cgi
Rectangle 27 5

This page has a very good writeup on namespaces and the using-statement:

You want to read the part about "Creating Aliases" that will allow you to make an alias for one or both of the name spaces and reference them with that like this:

using ControlImage = System.Windows.Controls.Image;
using System.Drawing.Image;

ControlImage.Image myImage = new ControlImage.Image();
myImage.Width = 200;

How do you resolve .Net namespace conflicts with the 'using' keyword? ...

.net namespaces using
Rectangle 27 159

Here are 535 ways to reload a page using javascript, very cool:

Here are the first 20:

location = location
location = location.href
location = window.location
location = self.location
location = window.location.href
location = self.location.href
location = location['href']
location = window['location']
location = window['location'].href
location = window['location']['href']
location = window.location['href']
location = self['location']
location = self['location'].href
location = self['location']['href']
location = self.location['href']
location.assign(location)
location.replace(location)
window.location.assign(location)
window.location.replace(location)
self.location.assign(location)

and the last 10:

self['location']['replace'](self.location['href'])
location.reload()
location['reload']()
window.location.reload()
window['location'].reload()
window.location['reload']()
window['location']['reload']()
self.location.reload()
self['location'].reload()
self.location['reload']()
self['location']['reload']()

no, i did not test them all

All the ones setting window.location to a variable (not executing a function) won't refresh if your address bar has a #hashValue in it, it will simply move to that ID on the page if it exists.

alot of the entries in that list are simply the same thing with different syntax, such as [] vs . syntax for accessing object properties.

Wow, look at the webpages source code, the repeating list is repeated so long he just used javascript to generate all the possible permutations instead of writing out his own ideas of ways.

Refresh a page using JavaScript or HTML - Stack Overflow

javascript html page-refresh
Rectangle 27 159

Here are 535 ways to reload a page using javascript, very cool:

Here are the first 20:

location = location
location = location.href
location = window.location
location = self.location
location = window.location.href
location = self.location.href
location = location['href']
location = window['location']
location = window['location'].href
location = window['location']['href']
location = window.location['href']
location = self['location']
location = self['location'].href
location = self['location']['href']
location = self.location['href']
location.assign(location)
location.replace(location)
window.location.assign(location)
window.location.replace(location)
self.location.assign(location)

and the last 10:

self['location']['replace'](self.location['href'])
location.reload()
location['reload']()
window.location.reload()
window['location'].reload()
window.location['reload']()
window['location']['reload']()
self.location.reload()
self['location'].reload()
self.location['reload']()
self['location']['reload']()

no, i did not test them all

All the ones setting window.location to a variable (not executing a function) won't refresh if your address bar has a #hashValue in it, it will simply move to that ID on the page if it exists.

alot of the entries in that list are simply the same thing with different syntax, such as [] vs . syntax for accessing object properties.

Wow, look at the webpages source code, the repeating list is repeated so long he just used javascript to generate all the possible permutations instead of writing out his own ideas of ways.

Refresh a page using JavaScript or HTML - Stack Overflow

javascript html page-refresh