Access coffeescript function in another file - coffeescript

I have this main coffeescript code:
<script src="libs/coffeeScript.js"> </script>
<script src="maths.coffee"> </script>
<script type="text/coffeescript">
document.write math.cube 2
</script>
and this code in the "maths.coffee" file:
math ={}
math.cube=(x)->x*x*x
Why can I not access the cube function?
I already tried a lot of solutions found on this site, without success.

The Problem:
When a CoffeeScript file is compiled into JavaScript it is wrapped in an IIFE. So the JS code you end up with looks something like this:
(function () {
var math = {};
math.cube = function(x) {
return x * x * x;
};
})();
What this means is that the function is only scoped within that IIFE, which prevents polution of the global namespace.
The solution:
Because you are including your CoffeeScript inline, you need to explicitly expose any functions you want to use in other files onto a global object, e.g. window
math = {}
math.cube = (x) -> x * x * x
window.math = math
Alternatively, you could compile your CoffeeScript before hand, and pass in the --bare option. Then just include the JavaScript file with your page.

Related

Is it possible to access webpack config properties through the preview-head.html file for storybook.js?

I am trying to add storybook.js into my react project and there is a pre-requisite script I need to add to every storybook page so as to render some custom components.
The script's URL needs to be auto generated on the fly in webpack configuration.
This Story rendering section of storybook's documentation mentioned a preview-head.html through which script tags can be injected into the final index HTML file.
I am wondering whether it supports EJS syntax like below for me to access a config option value of the HtmlWebpackPlugin.
<script src="<%= htmlWebpackPlugin.options.foobar %>"></script>
As a workaround, I wrote a decorator in the preview.js file to purposely insert the <script /> tag into the storybook iframe with dynamically generated src field.
const loadAssets = () => {
const scriptElement = document.createElement('script');
// scriptElement.src = /* dynamically generated from dependencies */;
document.querySelector('head').appendChild(scriptElement);
};
const AssetLoader = props => {
React.useEffect(() => loadAssets(), []);
return <>{props.children}</>;
};
const assetLoaderDecorator = storyFn => (
<AssetLoader>{storyFn()}</AssetLoader>
);
addDecorator(assetLoaderDecorator);
It's a bit clumsy but it serves the purpose at the moment.
Inspired by https://github.com/jhta/storybook-external-links.

karma-runner: load scripts (and CSS) via DOM

I want to inject some CSS and JavaScript files via a preprocessor.
In my preprocessor I inject the html template to the body element.
I printed the result out via console.log(document.body) - you can see the result at the bottom. It looks good, but the script is not evaluated.
If I run console.log(window.foobar) in my test, it's undefined.
Actually I don't want to to inject simple scripts, I want to load some files via
<script src="build/app.js"></script>
I need it in every test, so I don't want to refactor every single test for the same code injection, that's the reason why I tried to put it into the html generated by karma.
<body><script> window.foobar = 'miau!';</script>
<!-- The scripts need to be at the end of body, so that some test running frameworks
(Angular Scenario, for example) need the body to be loaded so that it can insert its magic
into it. If it is before body, then it fails to find the body and crashes and burns in an epic
manner. -->
<script type="text/javascript">
// sets window.__karma__ and overrides console and error handling
// Use window.opener if this was opened by someone else - in a new window
if (window.opener) {
window.opener.karma.setupContext(window);
} else {
window.parent.karma.setupContext(window);
}
// All served files with the latest timestamps
window.__karma__.files = {
'/base/node_modules/mocha/mocha.js': '253e2fdce43a4b2eed46eb25139b784adbb5c47f',
'/base/node_modules/karma-mocha/lib/adapter.js': '3664759c75e6f4e496fef20ad115ce8233a0f7b5',
'/base/test/custom-test.js': 'abf5b0b3f4dbb62653c816b264a251c7fc264fb9',
'/base/test/build/build.css': 'df7e943e50164a1fc4b66e0a0c46fc86efdef656',
'/base/test/build/build.js': '9f0a39709e073846c73481453cdee8d37e528856',
'/base/test/build/test.js': '0ccd4711b9c887458f81cf1dedc04c6ed59abe43'
};
</script>
<!-- Dynamically replaced with <script> tags -->
<script type="text/javascript" src="/base/node_modules/mocha/mocha.js?253e2fdce43a4b2eed46eb25139b784adbb5c47f"></script>
<script type="text/javascript" src="/base/node_modules/karma-mocha/lib/adapter.js?3664759c75e6f4e496fef20ad115ce8233a0f7b5"></script>
<script type="text/javascript" src="/base/test/custom-test.js?abf5b0b3f4dbb62653c816b264a251c7fc264fb9"></script></body>
Karma introduces the page scripts/html just like ajax, so it wont execute once the append has finished.
You will need to append the files for each spec. I have a helper for this job:
function appendCSS(path){
var link = document.createElement('link');
link.rel = 'stylesheet';
link.href='base/' + path;
document.body.appendChild(link)
}
function appendScript(path){
var link = document.createElement('script');
link.type = 'javascript';
link.src='base/' + path;
document.body.appendChild(link)
}
function loadAssets(page){
document.body.innerHTML = __html__['_site/' + (page || 'index') + '.html'];
appendCSS('_site/styles/demo.css');
appendCSS('_site/styles/' + page + '.css');
appendScript('_site/scripts/vendor.js');
appendScript('_site/scripts/' + page + '.js');
}
module.exports = {
loadAssets: loadAssets
};
In my spec i then simply call the helper, passing the name of the html page to be tested.
require('../helper').loadAssets('tested-page-name');
As you can see, i use the borwserify plugin, but i hope this helps.

inject a javascript function into an Iframe

This link (archived version) describes how to inject code from a script into an iframe:
function injectJS() {
var iFrameHead = window.frames["myiframe"].document.getElementsByTagName("head")[0];
var myscript = document.createElement('script');
myscript.type = 'text/javascript';
myscript.src = 'myscript.js'; // replace this with your SCRIPT
iFrameHead.appendChild(myscript);
}
That's ok, but what if I want to insert a function object into an iframe and get it executed in the iframe context? Let's say I have:
function foo () {
console.log ("Look at me, executed inside an iframe!", window);
}
and I want to insert foo's code inside an iframe? (function foo could be something loaded dynamically, I can't just wrap it in quotes)
I naively tried:
var scriptFooString = "<script>" + foo.toString() + "</script>"
to get the code inside function, but
I don't know how to insert it in the iframe HEAD (maybe with jquery?)
I don't know if it's the right way
I don't know what happens when if function is way more complex than that
I don't know what happens with double and single quotes in scriptFooString
Any hint?
First of all you can only accomplish this if your frame and the page displaying it is within the same domain (Due to cross-domain rules)
secondly you can manipulate dom and window objects of the frame directly through JS:
frames[0].window.foo = function(){
console.log ("Look at me, executed inside an iframe!", window);
}
to get your frame from a DOMElement object you can use:
var myFrame = document.getElementById('myFrame');
myFrame.contentWindow.foo = function(){
console.log ("Look at me, executed inside an iframe!");
}
Note that the scope in foo is NOT changed, so window is still the parent window etc. inside foo.
If you want to inject some code that needs to be run in the context of the other frame you could inject a script tag, or eval it:
frames[0].window.eval('function foo(){ console.log("Im in a frame",window); }');
Though the general consensus is to never use eval, I think its a better alternative than DOM injection if you REALLY need to accomplish this.
So in your specific case you could do something like:
frames[0].window.eval(foo.toString());
This code is the result of my research. The accepted answer also helped me a lot.
First of all, I create a simple iframe:
<iframe id="myiframe" width="200" height="200" srcdoc="<h1 id='title'>Hello from Iframe</h1><button type='button' id='fire'>Click Me!</button>
"></iframe>
For access to iframe's window and document I used this code.
const iframe = document.getElementById('myiframe');
const iframeWin = iframe.contentWindow || iframe;
const iframeDoc = iframe.contentDocument || iframeWin.document;
Finally I injected js codes into iframe:
var script = iframeDoc.createElement("script");
script.append(`
window.onload = function() {
document.getElementById("fire").addEventListener('click', function() {
const text = document.getElementById('title').innerText;
alert(text);
})
}
`);
iframeDoc.documentElement.appendChild(script);
Demo:
https://jsfiddle.net/aliam/1z8f7awk/2/
Here's my solution. I'm using jquery to insert the content, then using eval to execute the script tags in the context of that iframe:
var content = $($.parseHTML(source, document, true));
$("#content").contents().find("html").html(content);
var cw = document.getElementById("content").contentWindow;
[].forEach.call(cw.document.querySelectorAll("script"), function (el, idx) {
cw.eval(el.textContent);
});

How to remove liftAjax.js?

Using lift 2.4, all my rendered templates end up including a script tag at the bottom for liftAjax.js. I am not using any ajax functionality, and removed the jquery stuff from my bootstrap. How can I get rid of this extra markup from my pages?
<script type="text/javascript" src="/ajax_request/liftAjax.js"></script>
<script type="text/javascript">
// <![CDATA[
jQuery(document).ready(function() {liftAjax.lift_successRegisterGC();});
var lift_page = "F2025216344212IYC4Z";
// ]]>
</script>
This handles lifts function cleanup so that Lift can determine when particular server side functions are in use on the page or not. Its essentially an optimisation and I would not encourage you to disable it.
If however, you insist on disabling it, then you need to add the following to your boot.scala:
LiftRules.autoIncludeAjax = session => false
A bit late, but I found this on the mailing list while trying to achieve the same.
For some page at /static/truly-static.html you could include this in Boot.scala and it will pass it on to Jetty/Tomcat/whatever
LiftRules.liftRequest.append {
case Req("static" :: "truly-static" :: Nil, "html", _) => false
}
On a more recent version of Lift (2.5 or 3.0), use
LiftRules.autoIncludeAjaxCalc.default.set(() => (session: LiftSession)
=> false )

Writing script src dynamically via wicket

I want my page to load javascript dynamically to my body:
<script type= "text/javascript" src="this path should be decided from wicket dynamically"/>
I am using wicket version 1.4 therefore JavaScriptResourceReference does not exist in my version (for my inspection it wasn't ' )
how can I solve this ?
thanks in advance :).
I specify my comment into an answer.
You can use this code snippet:
WebMarkupContainer scriptContainer = new WebMarkupContainer("scriptContainer ");
scriptContainer .add(new AttributeAppender("type", Model.of("text/javascript")));
scriptContainer .add(
new AttributeAppender("src", urlFor(
new JavaScriptResourceReference(
YourClass.class, "JavaScriptFile.js"), null).toString()));
add(scriptContainer );
and the corresponding html:
<script wicket:id="scriptContainer "></script>
Just change the string JavaScriptFile.js to load any other Javascript file.
JavascriptPackageResource.getHeaderContributor() does exactly what you need.
You need nothing in your markup, just add the HeaderContributor it returns to your page.
Update: For Wicket 1.5 see the migration guide, but it goes like this:
public class MyPage extends WebPage {
public MyPage() {
}
public void renderHead(IHeaderResponse response) {
response.renderJavaScriptReference(new PackageResourceReference(YuiLib.class,
"yahoo-dom-event/yahoo-dom-event.js"));
response.renderCSSReference(new PackageResourceReference(AbstractCalendar.class,
"assets/skins/sam/calendar.css"));
}
}
If you want to put your <script> element in the body, you can simply declare it as a WebMarkupContainer and add an AttributeModifier to set the src attribute. Although in that case wicket won't generate the relative URLs for you, you have to do it yourself.
I'm not sure I understood completely.
If you are trying to create and append a script to the body after the page is loaded you should do it this way:
<script type="text/javascript">
function load_js() {
var element = document.createElement("script");
element.src = "scripts/YOUR_SCRIPT_SRC.js"; // <---- HERE <-----
document.body.appendChild(element);
}
// Wait for the page to be loaded
if(window.addEventListener)
window.addEventListener("load",load_js,false);
else if(window.attachEvent)
window.attachEvent("onload",load_js);
else
window.onload = load_js;
</script>
What I did here is create a new script element, and then apply to it its source.
That way you can control dynamicaly the src. After that I append it to the body.
The last part is there so the new element is applied only after the page is loaded.