I am trying to write some userscripts in JavaScript to be used with browser extensions.
In a website, I tried overriding a function defined in an external javascript, with Object.defineProperty. but it seems that this breaks the external script, because other codes in the external scripts (that are essential to the original website) seems to be not executing as well.
<html>
<head>
<!-- injected script, injected via Userscript -->
<script>
Object.defineProperty(window, 'originalFunction', { get: function() { return overridingFunction; } });
</script>
<!-- injection end -->
</head>
<body>
<script src="/external-javascript.js">
<script> originalFunction(); </script>
<script> anotherEssentialFunction(); </script>
</body>
</html>
and http://domain/external-javascript.js looks like this"
...
function originalFunction() {
some codes here;
}
...
function anotherEssentialFunction() {
....
}
and this was preventing anotherEssentialFunction from running. In the console, I see TypeError: can't redefine non-configurable property originalFunction and ReferenceError: anotherEssentialFunction is not defined
Is this expected in this situation, or there should be other problem causing it that is not described here? How can I safely override original function without causing such an error?
Object.defineProperty takes the name of a function as a parameter, so you'd have to do this instead:
Object.defineProperty(window, 'originalFunction', {
get: function() {
return overridingFunction;
}
});
Or if that's all the getter does, simply:
window.originalFunction = overridingFunction;
But if the other functions need to call the original function, you can't really override it without breaking the functions that rely on its behavior. If you're just trying to execute custom code in addition to the original code, you can do this:
var origFn = window.originalFunction;
window.originalFunction = function () {
customFunction();
origFn.apply(this, [].slice.call(arguments));
};
Update:
Based on your comment, it sounds like you're wanting to not only override the original function but also prevent the external script from redefining that function. You can maybe add a no-op setter to avoid the external script from getting an error when trying to define it:
Object.defineProperty(window, 'originalFunction', {
get: function() {
return overridingFunction;
},
set: function(ignored) { }
});
Related
in a SPA, using options API, how (where) to define a function that will be called from an html href?
In the following codepen for demo, everything works fine.
CODEPEN
However, on my Single Page:
<template>
<div v-html="my_div" />
</template>
<script>
/* function MyFunction() {
alert();
}; */
const MyFunction = () => {
alert();
};
/* Just for explanation, because the data comes from the database
export default {
data() {
return {
my_div:'link call function ',
}
}
*/
}
</script>
call the function return the error:
Uncaught ReferenceError: MyFunction is not defined
Apparently, the function is defined after the call
Any idea how to solve this?
Not sure what you're trying to do here but don't evaluate some random string coming from nowhere into a weird format. It will not work, will be clunky, non-debuggable.
If your codebase is legacy and has a lot of debt, refacto it or use jQuery or whatever to hack it even further.
How can I use a javascript function globally in Drupal 7.
I have my javascript file set up like this and add it using drupal_add_js():
(function($) {
function add_if_country_is_not_usa() {
// Check what country it is
// Update text, image, etc.. of a block.
}
});
In my block WYSIWIG I added the following code (The reason I add it in the WYSIWIG is because I want it to update before the page is fully rendered):
<script type="text/javascript">
add_if_country_is_not_usa();
</script>
But I get the following error:
Uncaught ReferenceError: add_if_country_is_not_usa is not defined
(anonymous function)
I read about adding functions to Drupal behaviors but that happens on document ready. I want to run the function as soon as the block is shown.
Any ideas?
Either define in the global scope, or do like below:
(function($) {
function add_if_country_is_not_usa() {
// Check what country it is
// Update text, image, etc.. of a block.
}
// set as a property of the global object `window`
window.add_if_country_is_not_usa = add_if_country_is_not_usa;
});
Not sure if this is the best way but I ended up being able to get it work using a namespaces. I call myGlobalObject.add_if_country_is_not_usa() from my block and it works now.
var myGlobalObject = mySingleGlobalObject || { 'country': {} };
(function ($) {
myGlobalObject.country = '';
myGlobalObject.add_if_country_is_not_usa = function() {
// Check what country it is
// myGlobalObject.country = 'US';
}
})(jQuery);
I found the following definition
$.fn.flex = function ( options ) {
var p = this.data("flex"),
opts = options || {};
if (p) return p;
this.each(function () {
p = new Flex( this, opts );
$(this).data("flex", p);
});
return opts.api ? p : this;
};
which defines function flex() in original code.
Unfortunately, it stops defining this function in my environment, i.e. function call causes an error that flex is not a function.
What is critical here for flex being a function?
UPDATE
Sorry, actually I didn't modify anything. I just put this javascript https://github.com/jasonenglish/jquery-flex/ into my environment (Liferay) and the code to run script
<script type="text/javascript">
$(function() {
$(".flex").flex();
});
</script>
caused an error. So I replaced $ to jQuery everywhere as I did before and it is still not working.
UPDATE 2
Hmmm. Error occurs in widget.js from Twitter. Says
TypeError: jQuery(...).flex is not a function
If I rename flex to flex1 everywhere, it says "flex1" is not a function.
Sorry, actually I didn't modify anything. I just put this javascript ... into my environment (Liferay) and the code to run script
Because that's a jQuery plug-in, you need to make sure you include that script after jQuery on the page. So
<script src="/path/to/jquery.js"></script>
<script src="/path/to/the-plugin.js"></script>
If you put them in the other order, the first script will fail because it will try to take the value of the jQuery symbol, which doesn't exist yet, throwing a ReferenceError (in both loose and strict mode).
First of all in $.fn.flex $ and fn are jQuery variables. they are not native to JavaScript. $.fn provided by jQuery to attach method/property to jquery object
I am creating a function alerts() and call it in my script tag, that is in <head>
Actully currenty i am woking on live editor,so i have to put users code in head,normally all function call in head but here ,it shows error !
I want to hold the user code and run when DOM completes!
like:
HTML
<head>
<script src='alertResource.js' type ='text/javascript' ></script>
<script>
alerts();
<script>
</head>
alertResource.js
function alerts(msg) {
var _M_DoWn = { x: '', y: '', isdown: '' };
var _A = document.createElement('HTML_alert');
_A.id = "codeit_HTML_alert";
insertAfter(document.body, _A);
}
function insertAfter(refrNode, newNode) {
refrNode.parentNode.insertBefore(newNode, refrNode.nextSibling);
}
So, whenever I call the alerts() it shows me an error in my console :
Error
Uncaught TypeError: Cannot read property 'parentNode' of null
I guess the error appears because my function gets called before DOM is loaded. Now I want to do something like: delay any function call until DOM is ready. I know how to check readystate but not able to implement it, as per my case.
Any idea? What I need to do to achieve this?
When you call to "alerts" the document is not fully loaded and "refrNode.parentNode" return null.
Try this, without jQuery
<body onLoad="alerts();">
....
</body>
call your function after page is completely loaded by using this:
Using JavaScriopt
document.addEventListener('DOMContentLoaded', function() {
alerts();
}, false);
Using JQuery
$(function(){
alerts();
});
Please use this. (Javascript way)
window.onload=function(){SomeJavaScriptCode};
<body onload="SomeJavaScriptCode">
Depending on if you need to support IE8 or not, you could do this:
document.addEventListener('DOMContentLoaded', function(){
alerts();
});
In trying to namespace my js/jquery code, I have come up against the following problem.
Basically, I used to write all my JS code in each html/php file, and I want to abstract that away to a single js file with namespaces.
So, in my html file I have:
<script type="text/javascript">
$(document).ready(productActions.init());
</script>
And in my js file I have:
var productActions = {
init: function() {
alert('initialsed');
$('#field_id').change(function() {
alert('ok!');
});
}
The productActions init function is definitely running, because I get the first alert (initialised). However, it seems that none of the jquery binding functions do anything at all. Stepping through the init function shows that the above change function is being registered, but actually changing the value in the field does absolutely nothing.
Am I missing something obvious here?
$(document).ready(productActions.init());
This code calls init() immediately and passes its return value to ready(...). (just like any other function call)
Instead, you can write
$(document).ready(productActions.init);
To pass the function itself. Howeverm this will call it with the wrong this; if you need this, write
$(document).ready(function() { productActions.init() });