I am brand new to Jquery and have run into something that if answered will help greatly in the future. I have 2 very simple questions
I am using codeigniter, HTML5 and all php pages as well.
I have a menu 'aside' with 4-5 sections that I want to be able to close to save space. So I am using 2 simple slideToggle scripts.
$("a").click(function () {
$('#cat').slideToggle('slow', function() {
})
});
and
$("button").click(function () {
$('#dog').slideToggle('slow', function() {
})
});
The problem is, if I use button on both, both scripts operate even though I am requesting the script to run on 2 different ID's ( I know the dog and cat thing is silly, I just threw them in to see if a fake id would work and it did)
The question is, how can I use button OR a href on both scripts to preserve my styling?
My second question is can you put multiple scripts on a .js file for inclusion and how would you do it? Does each get script tags or some other kind of separator?
Thanks for helping, these are my first two scripts. At least they work :)
<div class="menu">
<h2>News Links</h2>
Display
<!--
if I use "button" here, both scripts run on tandem
-->
<script>
$("a").click(function () {
$('#cat').slideToggle('slow', function() {
})
});
benchmark->mark('links_start');
$this->db->order_by('id', 'DESC');
$this->db->limit('10');
$query = $this->db->get('links');
foreach ($query->result() as $row)
{
echo "link \" title=\"$row->title\" target=\"_blank\">$row->name ";
}
$this->benchmark->mark('links_end');
?>
</ul>
</div>
</div>
<div class="menu">
<h2>Archives</h2>
<button>Display</button> <!--if I use "a" here, both scripts run on tandem
-->
<script>
$("button").click(function () {
$('#dog').slideToggle('slow', function() {
})
});
</script>
<div id="dog">
<?php
$this->db->order_by('id', 'DESC');
$where = "publish";
$this->db->where('status', $where);
$this->db->select('id, title', FALSE);
$this->db->select('DATE_FORMAT(date, "%b %D %Y")AS date');
$this->db->from('posts');
$query = $this->db->get();
foreach ($query->result() as $row)
I think what you want is something like this:
<button id="news_display">Display News</button>
<button id="archive_display">Display Archive</button>
$("#news_display").click(function () {
$('#news').slideToggle('slow');
});
$("#archive_display").click(function () {
$('#archive').slideToggle('slow');
});
This uses jQuery id selectors for the click events, as you already did in the anonymous functions. That way, they're specific and independent.
You can used combined selectors:
$("a, button").click(function () {
$('#cat').slideToggle('slow');
});
That will allow you to run the same function when either an a or a button is clicked.
My second question is can you put multiple scripts on a .js file for inclusion and how would you do it? Does each get script tags or some other kind of separator?
A javascript 'script' generally refers to a file included by the script tag, although that usage is ambiguous.
What you've got in your post is a javascript statement, probably inside a script tag on your page:
<script type="text/javascript">
function helloWorld() {
alert('Hello world');
}
</script>
You can do this (inline to the page), or move the contained code out to a .js file and reference it:
<script type="text/javascript" src="myjavascript.js"></script>
Your myjavascript.js file would look like this:
function helloWorld() {
alert('Hello world');
}
myjavascript.js can contain as much javascript as you'd like. Common approaches are to put grouped functionality into a single javascript file, and include it in the page. This makes it easy to re-use the javascript you've written across multiple pages by including it with the script tag on each page that makes use of it (I assume you've done this with the jquery javascript library already).
You can do the exact same thing that jquery has done, and dump all your javascript into a .js file and use script to load it into your page.
In re: your 2nd question: The code you posted
$("a").click(function () {
$('#cat').slideToggle('slow', function() {
})
});
… is one statement. You can write as many statements as you'd like into a single javascript file or <script> tag. If you have multiple JavaScript files, you can concatenate them into one file and reference that file from a script tag.
Related
I am trying to test the jQuery GET method, but what I am getting as result is completely insane. All I am trying to do is call a function from my controller with jQuery and then display the echoed value in a div within my view. Below is my code and finally a breakdown of the problem I am encountering.
Controller
public function generate_suggestions2() {
echo "James";
}
View views\suggestions_v.php
<body>
//This DIV is used a button to call the jQuery function
<div id="next_btn">
<p>Click here to display a name</p>
</div>
//In this div the value retrieved by the jQuery should be displayed
<div id="listB"></div>
//This is the function that calls the function within my controller
<script type="text/javascript">
$( "#next_btn" ).click(function() {
$.get("core/generate_suggestions2/",
function(data) {
$( "#listB" ).html(data);
});
});
</script> //For some reason I need to put the script at the end of the body. When it's in the head nothing happens when I click the button. Also something I do not understand.
</body>
Now the problem is that when I click the DIV next_btn it does NOT display the James in the DIV listB.
Instead it populates the DIV listB with my source code from my main view views\core_v.php
I have no idea how this is even remotely possible, so please if you have a clue or even better you know what I am doing wrong please tell me. I am trying to get this to work for the past three days without any success or progress :(
Try using this code in your view
<script type="text/javascript">
"$( "#next_btn" ).click(function() {
$.get("<?php echo site_url().'/core/generate_suggestions2';?>",
function(data) {
$( "#listB" ).html(data);
});
});"
</script>
Also delete the </script> tag just right before this block comment.
Regarding this comment you have:
//For some reason I need to put the script at the end of the body. When it's in the head nothing happens when I click the button. Also something I do not understand.
It is because the DOM is not yet fully loaded and Javascript executes its code when the browser has finished loading the DOM you are referring to. So you either have to put it after the DOM element you want to edit, like you do now or you could use $(document).ready(function(){
}
); .
Read more about it here
This line is pretty strange:
</script><script type="text/javascript">
Try to delete first closing tag 'script' on it.
I have a form inside a DIV (normally the div is hidden using "display:none;")
The user open the DIV with: onclick='$("#Details").show("slow");
Fills out the form and save the data.
I don't want the entire page to be reloaded, and I need only this DIV to be reloaded
I tried:
function(data) {
$('#Detalils').load(location.href + ' #Detalils');
});
and:
$("#Detalils").load(location.href + " #Detalils, script");
and:
$('#Detalils').load(location.href + ' #Detalils', function() {
$('#script').hide();
})
where in #script I put my script
In this div I have some script, and because of the jQuery on load script execution, the script is not executed.
I cannot put the script in an external file, it must be in the page body.
Is there a way to execute the script a well?
Thanks
Your actual Javascript code should not be within the div, that is the issue. If you wish to reload the form for the user to enter new data, then use ID's on the elements within your forms and write your JQuery code outside of it or in an external file, here is a simple example :
Instead of something like :
<form>
<input type="button" onclick="alert('hello');"> Click me ! </input>
</form>
Do something like :
<form>
<input id="myButton" type="button"> Click me ! </input>
</form>
<script type="text/javascript">
$("#myButton").click(function()
{
alert('hello');
});
</script>
You will have to adapt your code to this, of course, but you don't have another choice. HTML code can be removed and added at will, but Javascript code must not be treated the same way. There are many reasons for this, but one reason is that the browser will only load the Javascript functions once, for obvious optimization reasons.
The works within my local environment. Give it a shot in yours.
The HTML:
<div id="wrapper">
Remove
Reload
<div id="Details">my details box</div>
</div>
The jQuery:
<script type="text/javascript">
function mload() {
/*LOAD IN MY EXTERNAL STUFF*/
mtarget = $('#Details'); //the element on your page, that houses your external content
mscript = 'external.js'; //the js script required for your plugin to work
mtarget.load("external.html", function(){
$.getScript(mscript, function() {
//run the plug-in options code for your external script here
});
});
//*/
}
function madjustments() {
/*ADJUST THE LOADING PROCESS*/
//remove the load request on click from your remove button
$('#mremovebtn').on("click",function(e) {
e.preventDefault();
$('#Details').children().remove();
});
//reload the request on click from your reload button
$('#mreloadbtn').on("click", function(e) {
e.preventDefault();
mload();
});
//*/
}
(function($){
mload();
madjustments();
})(jQuery);
</script>
You will obviously need 2 additional files. One called external.html and another called external.js, for my demo code to work. But you can change the naming process to whatever works for you.
Extra:
Set a class in your external html file (on the parent element), for example #external. And by default, set the CSS to display:none in the style sheet. Then when the page loads in, simply show() it in the jQuery code.
Following the example here Very Simple jQuery and PHP Ajax Request – Ready to use code
I've been successful in creating a drop down list that passes the value to an external PHP script and returns the HTML output back to a "div" on the same page and it works great.
What I want to do now is post values when I click on link instead of building a drop down list. So ...if I created this link:
Route Number 2
I want "2" passed to that external PHP script and the content changed on the " div " as it currently works with the dropdown. I don't know how to change the javascript to handle this or what "foo.php" really needs to be.
Here's the current javascript from that example:
<script type="text/javascript">
$(document).ready(function() {
$('#route_number').click(function() {
routenumber = $('#route_number').val();
$.post('api.php', { route_number : routenumber }, function(res) {
$("#mainlayer").html(res);
});
});
});
</script>
And here's what the dropdown portion of the HTML looks like:
<select name="route_number" id="route_number">
<option value="notchosen">Please Choose A Route</option>
<option value="2">Riverfront</option>
<option value="11">Magazine</option>
<option value="16">Claiborne</option>
</select>
<div id="mainlayer">
</div>
So, to be clear, instead of a dropdown that passes values, I want to create links that accomplish the same result.
Thanks in advance,
dan -
Create a class, capture its (meaning whatever link you clicked on) value, then post.
<a class="RouteNumber" href="foo.php?route_number=2">Route Number 2</a>
$(function(){
$('a.RouteNumber').on('click',function(event){
// prevent the browser's default action for clicking on a link
event.preventDefault();
// break href attribute into array, then parse desired value as int
var routenumber = $(this).attr('href').split('='),
rtnum = parseInt(routenumber[1]);
$.post('api.php',{route_number:rtnum},function(res){
$("#mainlayer").html(res);
});
});
});
If you don't need to parse the integer out of it (if a string is good enough), you don't need that second variable. You can just use routenumber[1] in the post data.
Just a heads up, I modified the jQuery to use the .on() syntax. .click() is shorthand for it, but I like using .on() just because it allows for less potential codewriting if you want to do more (like mouseenter/mouseleave, for example) because you can combine them into a single codeset.
I had hoped simply fixing #LifeInTheGrey's example would've sufficed, but there are some things I would've done differently that probably need some explaining.
Your HTML could look something like this:
<a class="route" href="foo.php?route_number=2" data-route="2">Route Number 2</a>
The JavaScript would look something like this:
$(function() {
var fill_div_with_response = function(res) {
$("#mainlayer").html(res);
};
var handle_error = function(res) {
alert('something went wrong!');
};
$(document.body).on('click', '.route', function(event) {
// prevent the browser's default action for clicking on a link
event.preventDefault();
// grab route number from data attribute
var route = $(this).data('route');
// make that post request
$.post('api.php', {route_number: route})
// handle the response
.done(fill_div_with_response)
// handle errors
.fail(handle_error);
});
});
The example uses delegated events. They're cheap to initialize and consume the least amount of memory.
The example handles errors. Most answers to questions like these neglect that. errors happen. Always. Make people aware of that. Surely throwing an alert() is not the thing you want to be doing, but it's still better than simply ignoring errors completely.
The example uses Deferreds (Promises) rather than callbacks, as this usually makes code much cleaner.
We're defining the callbacks fill_div_with_response() and handle_error() at the root closure to prevent redefining them on the next click. There's no need to feed the garbage collector.
The data attribute poses the optimal alternative to <option value="123"> in the way that it prevents you from having to parse the href attribute to extract that number from a string.
since you want to make a menu, I would modify your markup
<ul name="route_number" id="route_number">
<li value="2">Riverfront</li>
<li value="11">Magazine</li>
<li value="16">Claiborne</li>
</ul>
then simply process that list:
$('#route_number').find('li').click(function () {
var routenumber = $(this).attr('value');
$.post('api.php', {
route_number: routenumber
}, function (res) {
$("#mainlayer").html(res);
});
});
EDIT1: As an improvement (as you seem to be pretty new to this stuff) you could use the data with altered markup as such:
<ul name="route_number" id="route_number">
<li data-routenumber="2">Riverfront</li>
<li data-routenumber="11">Magazine</li>
<li data-routenumber="16">Claiborne</li>
</ul>
Then the code would be:
$('#route_number').find('li').click(function () {// add click event manager to each li
var routenumber = $(this).data('routenumber');// get routenumber of clicked
$.post('api.php', {
route_number: routenumber
}, function (res) {
$("#mainlayer").html(res);
});
});
Alternate code using .on() form
$('#route_number').on('click, 'li', function () {//click event manager for ul/li
var routenumber = $(this).data('routenumber');// get routenumber of clicked
$.post('api.php', {
route_number: routenumber
}, function (res) {
$("#mainlayer").html(res);
});
});
Note that this last form binds to the #route_number element so you could add more menu options during processing and they would still work. This is also better than attachment to the document as it is a more focused approach to the event attachment.
My understanding of your question is that the functionality you have is fine, and you just need to change the look to a piece of text from a dropdown. If so, good news! You can keep (almost) the same JavaScript.
Right now, your JavaScript is getting the value of your select box, sending it via AJAX, and using the returned value. The only change you need is to get the 'value' of the text clicked.
You don't want to use a link, since that's designed to take the user someplace. Instead you can use a span and format it to look like a link, or even a button if you want that kind of look.
You will also need to change $('#route_number').val();, probably to something passed by the click event. For example:
<span id="route1" class="routeSpan" onclick="sendVal(1)">Route 1 Name</span>
<span id="route2" class="routeSpan" onclick="sendVal(2)">Route 2 Name</span>
And your JavaScript:
function sendVal(routeVal) {
$.post('api.php',{route_number:routeVal},function(res){
$("#mainlayer").html(res);
});
}
I have a main (index) page which loads pages dynamically and places them inside it's div but the Javascript within those pages doesn't execute. Specifically this part
<script type="text/javascript">
$(document).ready(function(){
$('#regForm').submit(function(e) {
register();
e.preventDefault();
});
});
</script>
You will have to use getScript like this:
$('#foo').load('bar.html', function(){
$.getScript("js/fileName.js");
// call a function from fileName.js
});
You will have to put your JS code in that file and call that via getScript and then you can call functions from it as shown above.
Write your javascript in the index.php or write at the bottom of loaded page without document.ready
This is in reality a cross-browser issue: When <div>s are dynamically filled with HTML containing <script> tags, these scripts may or may not run - and this behaviour is different not only between browsers, but also between browser versions.
The only workaround I know of is to extract your JS, send it seperately and execute it after the <div> content has been set.
I could be mistaken here but I thought that inline html can call an external javascript file's function with onmouseover.
For example:
<a href="#" onmouseover="updateParentImage('<?php echo $this->getGalleryUrl($_image) ?>');">
And my EXTERNAL jquery/javascript file function looks like:
function updateParentImage ($image_url)
{
alert($image_url);
$('.product-img-box .product-image img').attr('src', $image_url);
}
The function never runs. Am I completely missing something? Shouldn't that tag call the appropriate file even thought the javascript is external?
Note: If I include the javascript inline, the alert box shows but the image that I am trying to change in the document does not change, even though I"m using the same referencing as another place in the code where it successfully updates the image.
Any help would be appreciated. Thanks!
How about something like this...
<a href="#" class="imageChanger" data-imagesrc="<?php echo $this->getGalleryUrl($_image) ?>">
Then use jquery to add a mouseenter event
$(document).ready(function(){
$('.imageChanger').mouseenter(function(){
alert($image_url);
$('.product-img-box .product-image img').attr('src', $(this).data('imagesrc'));
});
});
Based on your comment, I've come to this solution that might help you:
This is one of many links
Then you can have this in your script:
(function($) {
$(document).ready(function() {
$('a').hover(function() {
// this happens onmouseenter
var imageUrl = $(this).data('imageurl');
updateParentImage(imageUrl);
}, function() {
//this happens onmouseleave
});
});
function updateParentImage(image_url) {
alert(image_url);
$('.product-img-box .product-image img').attr('src', $image_url);
}
})(jQuery);
That small piece of code binds to all 'a' elements, which might not exactly be right in your case, but it's just there as an example. Then I've wrapped all the code in a closure/immediately invoked function expression (IIFE), to make sure we don't pollute the global namespace too much. It also makes sure that $ stays jQuery inside that closure.
One more thing to be noted is that I've used the data attribute on the links to store the image URL for that link. Clean and easy :)
If you have any question, shout out!
(See comments above for context for response)
You should never have to duplicate event binding, and doing inline, obtrusive JavaScript in never an answer.
Bind once and set your URL to a property that you can grab. Further, I write the following under the assumption that you don't want to touch your external JS function:
<div id="linkContainer">
Something
</div>
JavaScript (can be placed in your page's HTML in script tags if you must):
$('#linkContainer a').bind('mouseover', function() {
updateParentImage($(this).data('imgsrc'));
return false;
});