I am trying to load some JavaScript files inside another JavaScript file in the following case:
js/script1.js
var script_1_method = function () {
console.log("Hello Script 1");
}
js/init-script.js
console.log("Initiating Scripts...");
loadScriptMethod('js/script1.js');
script_1_method();
console.log("Hello Script 2");
index.html
<!DOCTYPE HTML>
<html lang="en-US">
<head>
<meta charset="UTF-8">
<title></title>
<script type="text/javascript" src="js/init-script.js"></script>
</head>
<body>
</body>
</html>
The Console output should be
Initiating Scripts...
Hello Script 1
Hello Script 2
I have looked into many JavaScript loaders like curl.js, RequireJS, JSL almost all of them do an Asynchronous way of loading files requiring callbacks for my scenario.
Is there a library to load the scripts in a synchronous way as in the above case without requiring callbacks.
Please let me know if there are any JavaScript loader libraries which cater to the above case.
It's possible to load same-origin scripts using a synchronous XHR:
var scr = getViaSynchronousXHR('js/script1.js'),
el = document.createElement("script");
el.appendChild(document.createTextNode(scr));
document.documentElement.firstChild.appendChild(el);
script_1_method();
A script element without a source is parsed and executed synchronously, because there is no wait for the file to be downloaded/fetched from cache.
if all your scripts are on the same domain, you can run a synchronous ajax call to get the script, use eval to run it, and then continue
The thing you want to do is quite difficult. I had a lot of problems with synchronous AJAX requests to correctly load my javascript files dynamically.
Actually I implemented something that worked synchronously on my project which is the same as you want.
It is only possible if you have a server-side scripting engine (e.g. PHP) to generate your HTML page.
The idea is to parse the init-scripts.js on server side prior to include them into the html code.
Instead of writing echo <script type="text/javascript" src="js/init-script.js"></script> in my PHP script I write : JavascriptLoader::addJavascript('js/init-script.js');
JavascriptLoader is a PHP class which manages scripts to be loaded.
This addJavascript function parses the init-script.js and, each time it encounters a line which starts with "loadScriptMethod(",
it parses and uses the string between brackets (e.g loadScriptMethod('thisString')) as the scriptToLoad
and then calls recursively JavascriptLoader::addJavascript($scriptToLoad);
JavascriptLoader::addJavascript then do an echo '<script type="text/javascript" src="'.$scriptToLoad.'"></script>' to write
I cannot publish the JavascriptLoader code from my project, but here is a simplified example of PHP code:
class JavascriptLoader{
...
public static function addJavascript($filepath){
self::init(); //Init to write the javascript loadScriptMethod definition into HTML output
if (!self::isScriptAlreadyLoaded($filepath)){
self::parseFile($filepath);
echo '<script type="text/javascript" src="'.$urlScript.'"></script>',"\n";
self::ajouterScriptDejaCharge($chemin);
}
}
private static function parseFile($filepath){
if (file_exists($filepath)){
$lines = file($filepath, FILE_SKIP_EMPTY_LINES);
foreach($lines as $line){
$matches = array();
$test = preg_match ('/^loadScriptMethod\(\s*[\'\"](.+)[\'\"]\s*\)/' , $line , $matches);
if ($test > 0){
$scriptToLoad = $matches[1];
//On inclut le fichier
self::addJavascript($scriptToLoad);
}
}
}
else{
throw new Exception('javascript source file '.$filepath.' does not exist.');
}
This also stores the $scriptToLoad into an array to avoid loading twice the same script (functions isScriptAlreadyLoaded and addScriptToAlreadyLoadedList).
Related
I have a php file containing the following line;
$num= "<script type='text/javascript' src='hn_includes/common.js'>boo();</script>";
and of course have a javascript file common.js which contains a function boo()
This is never called...
In an attempt to debug, I've placed a console.log("common.js loaded"); at the top of the common.js file and this tells me that it is indeed being loaded but the call to function boo() never seems to happen.
Additionally, if I simply change my line of code above to;
$num= "<script>boo();</script>";
and add boo() to top of the php file as below;
<script>
console.log ("I'm here");
function boo()
{
console.log("boo");
}
</script>
I get both the "I'm here" and also the "boo".
Any suggestions on where I'm going wrong would be greatly appreciated...
You are only declaring variable in the PHP file. To make it valid accessible in page you need to echo it. like
$num= "<script type='text/javascript' src='hn_includes/common.js'>boo();</script>";
echo html_entity_decode($num);
I use CreateTemplateFromFile and push a variable inside my template. My template file is including another file, but I'm not able to push this variable in the second file embedded.
Here below what I've tried:
index.html:
<!DOCTYPE html>
<html>
<?!= include('header'); ?>
<?!= include('style'); ?>
<body>
...
</body>
<?!= include('script'); ?>
</html>
the script part of the index.html in a separate file:
<script>
function getData() {
$("#loadingMessage").html('Loading');
console.log('myContent:', <?= data ?>);
...
}
</script>
The doGet part of the Google apps script code:
var template = HtmlService.createTemplateFromFile('index');
template.data = myContent;
return template.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
the variable is correctly pushed in index.html but not reach the script part.
Any idea ? Maybe to include the script file as a template also ?
How to pass variables between Apps Script and Javascript.
Google Apps Script features the method google.script.run that can be called from the JS part of a Web App. The methods allows to pass parameters to an Apps Script function and to assign the return value of the GAS function back to a JS function.
Sample:
.gs file
function doGet() {
var template = HtmlService.createTemplateFromFile('index');
return template.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
function myContent(input) {
var myContent="foo"+input;
return myContent;
}
HTML/js file
<html>
<head>
<base target="_top">
</head>
<body onload="getData()">
<script>
function getData() {
google.script.run.withSuccessHandler(proceedData).myContent("bar");
...
}
function proccedData(returnValue) {
var data = returnValue;
}
</script>
</body>
</html>
If you want to use scriptlets
The documentation specifies:
Remember, however, that because template code executes before the page is served to the user, these techniques can only feed initial content to a page. To access Apps Script data from a page interactively, use the google.script.run API instead.
Because scriptlet code executes before the page is served, it can only run once per page; unlike client-side JavaScript or Apps Script functions that you call through google.script.run, scriptlets can't execute again after the page loads.^
scriptlets can call functions defined in other code files, reference global variables, or use any of the Apps Script APIs.
In your case, if you want to use scriptlets, you either have to call a function or make your variable dataglobal, e.g.:
//global variable
var data=myContent;
function doGet() {
var temp=HtmlService.createTemplateFromFile("index.html");
return temp.evaluate().setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
Also keep in mind:
Templates can be challenging to debug because the code you write is not executed directly; instead, the server transforms your template into code, then executes that resulting code.
In my website I have
<script src="js.php"></script>
Question is very simple but I have no idea of the answer:
Within js.php, how can I check if the file has been called though a script src="..."?
Purpose is to change the returned HTML code of js.php depending on how this php script file is called (direct access or script src="...").
The way to do it would be to assign a session variable to true right before you call the js.php file
session_start();
$_SESSION['src'] = true;
<script src="js.php"></script>
Then in the php file
session_start();
if(isset($_SESSION['src']) && $_SESSION['src'] == true) {
// file was called from a src
$_SESSION['src'] = false; // this is important so that it can't be called from direct access
}
Cool question. Let me help ya.
I'll provide here some not 100%-reliable methods, that will work in standard, non-user-malicious cases.
First
For this solution you will be required to download mimeparser from here. It's your choice what kind of mimeparser you want to use, I found this just ad-hoc for purpose of this answer.
Theory
In theory browser is sending headers, that your script during response should match for proper browser-side parsing. Especially I have here in mind HTTP_ACCEPT header.
Code example
Once you have downloaded mimeparser, lets start with creating file test.php:
<?php // test.php
//https://code.google.com/p/mimeparse/
include_once('mimeparse.php');
$mimeMatch = Mimeparse::best_match(array('text/javascript', 'text/css', 'text/html', 'application/xhtml+xml', 'application/xml', 'image/*'), $_SERVER['HTTP_ACCEPT']);
switch($mimeMatch) {
case 'text/javascript': // via <script src>
echo('alert("this is loaded as script");');
break;
case 'image/*': // via <image src>
header('Location: http://i.stack.imgur.com/sOq8x.jpg?s=128&g=1');
break;
case 'text/css': // via <link href>
echo('body::before{content: "this is written via CSS"}');
break;
default:
var_dump('detected standard file request by matching to ' . $mimeMatch);
// if __FILE__ is first on a list, its not included
if(__FILE__ !== array_shift(get_included_files())) {
var_dump('file was included or required');
} else {
var_dump('file runs on its own');
}
// additional detect for ajax request.
if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') {
var_dump('loaded via AJAX request');
} else {
var_dump('loaded via not-AJAX request');
}
break;
}
die();
You can visit it by now, to see that script detects, its loaded directly:
string 'detected standard file request by matching to text/html' (length=55)
string 'file runs on its own' (length=20)
string 'loaded via not-AJAX request' (length=27)
Inclusion - feature showdown
To see, whats happening with script in some special cases, you can create an example index.php:
<html>
<head>
<link rel="stylesheet" type="text/css" href="test.php"/>
</head>
<body>
<script src="test.php"></script>
<img src="test.php"></img>
<?php require('test.php'); ?>
Description
By parsing some standard-behavior headers sent from browser, we can predict loosely, what was context of page load. It's not 100% reliable and not a very good practice, but great for writing rootkits ;) anyway.
Hopefully rest is commented-out in PHP code.
Tested with Apache serving and Chrome reading.
Here are my code:
<script type="text/javascript">
function SaveToDisk(fileUrl, fileName) {
var hyperlink = document.createElement('a');
hyperlink.href = fileUrl;
hyperlink.target = '_blank';
hyperlink.download = fileName || fileUrl;
var mouseEvent = new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true
});
hyperlink.dispatchEvent(mouseEvent);
(window.URL || window.webkitURL).revokeObjectURL(hyperlink.href);
}
</script>
</head>
<body>
<?php
$newtarget = "0C004B290BF2D95F";
$filename = 'C:/Users/FOO/Downloads/'.$newtarget.'.txt';
if (file_exists($filename)) {
unlink($filename);
}
?>
<script type="text/javascript">
SaveToDisk('http://www.ticketmaster.com/json/resale?command=get_resale_listings&event_id=<?php print $newtarget; ?>','<?php print $newtarget; ?>.txt')
</script>
<?php
$newlink = file_get_contents('C:\\Users\\FOO\\Downloads\\'.$newtarget.'.txt');
When the file is deleted the file_get_contents php function runs before the SavetoDisk rewrite the file on disk.
"failed to open stream: No such file or directory".
When I don't delete the file, it works. I tried to insert sleep(10) right after the call of the javascript function but still got the error, inexplicably the file is wrote after the 10 seconds... any tips on this?
PHP is processed by your server whereas Javascript is processed by the user's browser, therefore regardless of how you order functions within the same .php doc, the Javascript will always run after the PHP is processed.
If you need to run PHP after your Javascript has been executed, look at jQuery's post function to call a PHP file from your Javascript. I'd strongly recommend you take a look at some online learning tools like codecademy to get a better grasp of PHP / JS.
You can't do that. PHP is executed on the server and JavaScript is executed on the client (web browser).
Right click on your web browser and select View Source to check the content. You will not see your PHP there.
When I'm using controller function with parameters the rendered view just seems to forget every included .js files.
public function view($id = null) {
if(!$id) {
throw new NotFoundException(__('Invalid post'));
}
$post = $this->Post->findById($id);
if(!$post) {
throw new NotFoundException(__('Invalid post'));
}
$this->set('post', $post);
}
If I take parameters away and put variable '$id = 1' on function the view with postID 1 renders okay in 'posts/view'.
I included javascript files to default.ctp in traditional way:
echo "script type='text/javascript' SRC='../js/jquery-1.9.1.min.js'></script>";);
(it includes '<' but this text editor won't me type it for safety reasons I guess)
I don't have knowledge about 'js helpers' of cakePHP. Can't I use javascript in traditional way?
Site renders okay in every other view (e.g. posts/add) and .js files are included in source code of 'posts/view/1'
The problem
You're using relative paths to the javascript;
<script src='../js/jquery-1.9.1.min.js'></script>
In this url, ../ means '1 directory up from the current location`, so when you're currently visiting this URL;
http://mysite.com/home/
Then your browser will correctly try to load the script from;
http://mysite.com/js/jquery-1.9.1.min.js
However, if you're visiting this url;
http://mysite.com/home/and/some/more/
Then the browser will look for the JavaScript here:
http://mysite.com/home/and/some/js/jquery-1.9.1.min.js
How to fix the problem
Use absolute paths for all 'assets' (CSS, JavaScript, Images);
src='/js/jquery-1.9.1.min.js'
Output the script-tags using CakePHP Helpers (after all, that's what they are meant for: to simplify your work :), e.g. echo $this->Html->script('jquery-1.9.1.min');