Intense Debate uses the following javascript code to display a comments number on my blog, which I have included in a handy little php function. By passing this php function the ID of a blog post, it creates a link to the comments section of that specific post.
function show_comments_number($id) {
$url="index.php?p=post&id=$id";
?>
<script>
var idcomments_acct = 'xxx';
var idcomments_post_id = '<? echo $id;?>';
var idcomments_post_url = '<? echo $url;?>';
</script>
<script type="text/javascript" src="http://www.intensedebate.com/js/genericLinkWrapperV2.js"></script>
<?}
The problem is that Intense Debate parses the URL I'm trying to pass it, leaving off the & and everything after it. So the link Intense Debate produces is just "index.php?p=post" -- obviously this is a problem.
Any ideas as to why it's chopping the URL in this way?
Or follow the W3C's advice and change & to a ; (make sure to modify your argument_separator.input and argument_separator.output accordingly).
Chances are, the &id in your URL is being interpreted as an invalid HTML entity. Wrapping your <script> tag in a comment (<!--<script></script>//-->) should help with that.
Change the &id to &id, and you should solve it.
Related
Since I know many consider the use of PHP code inside Javascript code bad practice, I wonder how to execute a javascript function provided that a certain PHP variable has a certain value.
This is the way I currently write the code:
<script type="text/javascript">
function execute_this() {
some code;
}
<?php
if(!empty($_SESSION['authorized'])) :
?>
execute_this();
<?php
endif;
?>
</script>
Any ideas how to avoid using PHP inside Javascript in this particular example?
If you don't want to include any PHP code inside the javascript code but want to know the value of a php variable, you have to integrate a communication between the server side (PHP) and the client (JS)
For example you could use a ajax request to call a small php snippet that provides the value in its reply. With that value you can go on in you java script code.
In my opinion you should decide if its worth the effort.
Edit:
In regard to the edited question: If it is important that the JS function is never ever called if the PHP session value isn't present I would stay with the PHP code but would do it that way:
<?php
if(!empty($_SESSION['authorized'])) :
?>
<script type="text/javascript">
function execute_this() {
some code;
}
execute_this();
</script>
<?php
endif;
?>
If you evaluate the value of the session variable in javascript, you have to make sure that nothing bad happens to your code if the provided value was manipulated.
It's a matter of code style. The time your project grows, you will find it increasingly difficult to maintain it or to extend its functionality. A better solution would be to initialize all needed variables in the beginning of the file and to externalize the main JavaScript functionality.
Example PHP:
<script type="text/javascript">
MYCONFIG = {
authorized: '<?php echo $_SESSION['authorized']; ?>',
foo: 'something else'
}
$(document).trigger('init'); // fire init event, you can call it as you like
</script>
Example JS with jQuery (note that i use the custom trigger 'init', you can call it however you like):
$(document).on('init', function() {
function execute_this() {
document.write(MYCONFIG.foo);
}
if(MYCONFIG.authorized) {
execute_this();
}
})
This should be in an external JS file and does not need any PHP tags.
You have to store the php variables somewhere in the html code and then access it.
For example:
<input type="hidden" id="hidval" value=<?php echo $_SESSION['authorized'] ?>/>
then in your js:
var somevar=document.getElementById(hidval).value;
if(somevar==what you want){
execute_this();
}
I think you have some basic design issues, and we are only seeing the tip of the iceberg and can't fully help you.
There is nothing inherently wrong with calling a php function this way, but you have several issues:
1) you cannot separate your js file & allow for caching or cdn
2) while MVC is certainly not "mandatory", it is definitely a good idea to try to separate this type of logic from your "view" - your rendered output
3) I suspect elsewhere you have a massive security hole - if you are setting certain parameters based on whether or not they are "authorized" in their session, this means you are most likely sending back info on which to base a permissions decision in your php code somewhere. Never do that from the page - all data should be "neutral" on the page itself, because you have no control over it.
Give this a read if you are not clear why I say that: http://www.codebyjeff.com/blog/2012/12/web-form-security-avoiding-common-mistakes
There are three possible ways to do it.
Use hidden field and add necessary variable value inside each fields and get those using jQuery.
User jQuery Session plugin and access php session variable.
make a ajax call to php and get response in json format and access response.
Like this:
<script>
setSomeStuffUp();
<?php if ($otherStuffNeedsToBeDone === true) { ?>
doSomeOtherStuff();
<?php } ?>
breakSomeStuffDown();
</script>
Came across something like this at work- done with templating (Smarty), so it looks a bit cleaner- but not by much! Also echoes some template variables used for things such as jQuery selectors, and other little unpleasant-looking bits.
What's the proper way to do this? Load the data that needs to be used for logic in the JS as JSON via AJAX? HTML data attributes?
Something about it just smells bad, bad, bad.
Thanks everyone.
It is bad practice to use language X to generate code in language Y.
Try "decoupling" the two languages, for example, like this:
<script type="text/javascript">
var data = {
id: "<?php echo $id ?>",
...
};
$(document).ready(function(){
$("#" + data.id).on("click", function(){
/*do something*/
});
});
</script>
This way, PHP only cares about populating the data structure and JavaScript only cares about consuming the data structure.
Echoing configuration variables and some javascript initialization code from server doesn't sound too bad in general, but if such js-injection-from-server pieces are all over the place then you're right, it's ugly, at least because such code is difficult to manage.
Just try to centralize any kinds of initialization and do the rest in statically-defined client-side JavaScript logic.
UPD. #Oscar Jara is talking about the same thing and provided a good illustration. But often even such cases can be avoided if server-side logic provides data for JavaScript processing via HTML (after all, that's what HTML is for).
Here's a trivial example that you can often encounter. Say you want to output a gallery that will be enhanced into a carousel via JavaScript.
Server generated HTML:
<ul id="myGallery">
<li><img src="img1.jpg /></li>
<li><img src="img2.jpg /></li>
<li><img src="img3.jpg /></li>
...
</ul>
And then you have your static JavaScript code initialize the carousel when DOM is ready:
// when DOM ready...
AwesomeCarousel.init($('#myGallery'));
Here the data prepared by the server is this piece of HTML with a list of images, no need to generate JavaScript explicitly loading every image. You can pass arbitrary data via the data-* attributes.
Personally, I use PHP in JS in many instances. Sometimes it is to populate a variable with JSON data, a page id, or something of that nature. As far as I am concerned, PHP is designed to write the code that appears on the page, and JS is designed to interact with the user once the content is there.
I do get what you are saying, in that there are probably cleaner ways of doing this. You mentioned AJAX, which would probably be cleaner and would definitely help the flow of the document being output. The only issue is that you have to make a second request to the server for some very simple and meanial variable. A few milliseconds isn't huge, but in the a production website, you probably don't want to be making that additional request and bogging down server resources.
In response to what the cleanest way to do it would be, if it was that big of a deal... I would create a separate JS file with that code and then use the server to include that individual file if needed. Again, I don't do this, but I think it would look the cleanest in the template.
If you want to get really out-there, you can have the HTML page request a .js file, coupled with their session-id or some other indicator of who they are, operate the .js call as a PHP call, dynamically build the JS based on what their session requires and then output it back to the browser as a .js filetype.
But that's a lot of work.
If you'd like something that smells less, have PHP dump either a JSON-string at the end of your file:
var cfg_string = "{\"username\":\"Norguard\", \"new_messages\":[......]}"; // client
$cfg_obj = array(); // whole lot o'PHP
$json_encoded_cfg = json_encode($cfg_obj);
echo "var cfg_string = {$json_encoded_cfg};" //server-side
And then parse it, in the client for added safety...
...or just outright create a map in the template:
$cfg_string = "var dataMap = {";
foreach ($cfg_obj as $key => $val) {
// print key:val all pretty-like,
// handle commas (ie: no trailing comma at the end), indent with tabs or spaces
// if you want, count the number of items so that the object closes ({})
// without any newline operator, if there are no config settings
}
echo $cfg_string;
Both of these are clean and unobtrusive and keep everything separate.
The config data/text can go right above whatever your init/loading code is going to be, and be passed in as a parameter to that init-logic.
If all you're doing is passing data from the server-side language to the JavaScript code, then that's fine. Plenty of CMS packages out there do it.
I don't really see the need to conditionally generate JavaScript code on the server side. Maybe there's a use case for it but JavaScript is a language itself, so why not just put the logic in the JavaScript code?
I've built an online community in Drupal with a homepage that is kind of like the Facebook wall. You see the 25 most recent posts, with the two most recent comments below those posts. There is also a textarea right below those comments so that you can quickly post a new comment on a particular post.
These Facebook-style posts have a lot of functionality built into them via JavaScript. Clicking a "view all comments" link directly below a post makes an AJAX call that grabs all the comments for that post and displays them right below it. You can also mark posts as helpful, as the solution to your question, edit comments inline, etc. All of these actions require AJAX requests, which means that the JavaScript making the request needs to know essential information such as the Node ID (the unique identifier of the post), the comment ID (unique identifier of the comment), etc.
My initial implementation had these pieces of essential data sprinkled all over the posts, making it more complicated to write the JS that needed to find it. So my second implementation simply output all this data into a JSON-compatible string in the main wrapping element of each post. While this made it much easier for the JS to find the data it needed, writing JSON as a string is a pain (escaping quotes, no line breaks).
So now I have a third idea, and I'm looking for feedback on it prior to implementation. The idea is to create a single global JS Array for all these posts that contains within it objects that hold the data for each post. Each element in that array would hold the necessary data needed for the AJAX calls. So it would look something like this:
Facebook-style post template
<div class="post" data-postindex="<?php echo $post->index; ?>">
<!-- lots of other HTML for the post -->
</div>
<script type="text/javascript">
globalPostArray.push({
nid: <?php echo $post->nid; ?>,
authorID: <?php $post->authorID; ?>,
//etc. etc. etc.
});
</script>
The result of the above code is that when a link gets clicked that requires an AJAX request, the JS would simply traverse the DOM upwards from that link until it finds the main .post element. It would then grab the value of data-postindex in order to know which element in globalPostArray holds the data it needs.
Thoughts? I feel like there must be some standard, accepted way of accomplishing something like this.
I've never heard of a standard way to "pass" information between PHP and Javascript, as they are a server-side and client-side language, respectively. I would personally use a hybrid of your second and third solutions.
Store the post id in a data-postindex attribute (data attributes are newish, and the "right" way to store small amounts of data). But I would still just use a JSON array for the rest, as storing lots of data in data-attributes (and escaping them!) is potentially problematic. PHP has a json_encode function that takes care of all the escaping and such for you - just build a PHP array (say, $postdata) like you normally would, and then throw this in your post template:
<script type="text/javascript">
globalPostArray.push(<?php echo json_encode($postdata) ?>);
</script>
Where $postdata is something like the following:
$postdata = array(
'nid' => 5,
'authorId' => 45
...etc...
);
It should be easy enough to generate such an array from your existing code.
I wrote a blog post a while back about my implementation of this kind of thing, but it sounds like all you need is a pointer at json_encode.
The most reliable way to pass any PHP variable to JavaScript is json_encode.
<script type="text/javascript">
var something = <?php echo json_encode($var); ?>;
</script>
You can't pass closures and resources, but otherwise anything's game for being passed.
I would store the data inside the element:
<div class="post" data-postindex="<?php echo $post->index; ?>"
data-nid="<?php echo $post->nid; ?>"
data-authorID="<?php echo $post->authorID; ?>">
...or storing a complete JSON-string in 1 data-attribute:
<div data-data="<?php echo htmlentities(json_encode($somedata));?>">
My answer is about the same as the other guys but more detailed. I usually do it like this and i think is the best approach: (of course you can grab the data using ajax, but depends on the context)
somefile.html
<html>
<head>..</head>
<body>
html code
<script>
window.my_data = <?php echo json_encode($my_php_var); ?>
</script>
</body>
</html>
somefile.js
$(function() {
window.myitem = new myClass(window.my_data);
});
var MyClass = function(init_data) {...}
EDIT:
OK, I believe I've found a way around the issue using the info posted by #ManseUK along with #Johan's comment. As a n00b I can't answer my own question but I've added an explanation below the question in case it helps anyone else out.
I am re-writing part of an e-commerce solution which was written by
another development team some years ago. In the new version, we are
experimenting with shortening the user journey using Ajax but doing so
gives JavaScript errors and causes some functions to fail. Dev URL is
here:
http://cognition.thelightbulb.co.uk/type-18/general-purpose-lamps-and-bulbs/craftlight-daylight
The errors appear once the dropdowns have been selected and the
product displays.
The errors are displaying most notably in IE7:
Error: 'frm.qty' is null or not an object
Error: 'qty.value' is null or not an object
I believe this is where the problem is coming from:
var frm = document.frmOrder;
var qty = frm.qty;
In the lines above, frmOrder is the name of the form and qty is
the name of the input for product quantity.
Compare that to http://cognition.thelightbulb.co.uk/product-54 where
the product loads without the Ajax selection process and you'll see
that the functions work correctly.
I suspect that the problem is to do with the fact that var frm =
document.frmOrder; is not working due to the way it relates to the
DOM when loaded with Ajax.
I am using innerHTML=xmlhttp.responseText as the Ajax method. Is
there an alternative way to define var frm so that it will function
properly when loaded with Ajax?
EDIT:
Using the info posted by #ManseUK along with #Johan's comment, I added another argument to CheckMinQty(minorder) so that it now looks like this...
function CheckMinQty(minorder,qty)
...where qty is passed to the function on an onclick event as document.forms['frmOrder'].qty.value
I then moved the whole function out into a separate .js file. It's maybe not the best approach but it still feels tidier for the Ajax call to just return workable HTML which CheckMinQty can use rather than bringing in a whole load of <script> and then trying to run it.
Thanks for all the suggestions and I'd welcome any comments about the approach/solution outlined above.
Change this
var frm = document.frmOrder;
to this
var frm = document.forms['frmOrder'];
That will give you a handle to the form
document.frmOrder refers to the element with id frmOrder on the page, which happens to be the form on this page. Just try to get the correct form-element as the variable there.
Though the Manse's solution might work, use a more sensible way and assign an id to the form and since you're using jQuery anyway, retrieve the form with var frm = $(#formid); Not only is it easier to write, it's much more easier to read by you and everybody else.
When loading script via AJAX, you don't have DOMReady event anymore. In other words, when you want to execute your script on AJAX load, you should use self-invoked functions.
Wrap your ajax-loaded script inside a function like this:
(function(){
// Do what you want to do here.
})();
See if that solves the problem?
I have the following code:
<?php
if ($x == 1){
?>
<b>Some html...</b>
<?php
}
else if ($x==2){ ?>
<b> Other html...</b>
<?php
}
?>
Now I would like to have two links below (a href) and somehow pass the variable $x (so Link1 passes x=1 and Link2 passes x=2) in order to load the relevant bit of code from if statement. I know I can pass $x using the form and then test its value and load required a bit of code, but I would like to do it smoothly, without reloading the page. I think that jQuery could help it, but I have no idea how to do it. Any ideas greatly appreciated.
Forgetting about PHP for the moment, you're looking for jQuery's .load():
<div id="container"></div>
Load 1
Load 2
<script type="text/javascript">
loadContent = function(content){
$('#container').load(content + '.html');
}
</script>
The above code (not tested, but it's at least close) will insert the contents of 1.html, or 2.html (on the server) into the div with id="container".
There are plenty of tutorials, like the one linked in pygorex1' answer, that cover various ways of doing this.
What you're looking for is AJAX - the ability to load server content using background HTTP requests in Javascript. Here's a tutorial I've found useful for implementing AJAX using JQuery:
http://articles.sitepoint.com/article/ajax-jquery