Codeigniter manipulate DOM from view? - php

In order to best organize JavaScript AJAX handlers in a web app, I'm taking the approach of using an AJAX controller to process the AJAX requests. Simple enough.
The second half of this decision is the result of the AJAX request, and specifically how, where, and if the JSON/data returned is added to DOM elements. Is it a good (or at least non-foolish idea) to put the JavaScript DOM manipulation logic within the view?

I normally handle AJAX and all JavaScript execution within a static .js file. This way, I can handle a request whether it's ajax or not, and I can keep my logic in one place. So, I might have the following setup:
// application/controllers/Mycontroller.php
class Mycontroller extends CI_Controller {
function index()
{
$content['text'] = "Lorem ipsum dolor sit amet...";
$data['content'] = $this->load->view('embeds/home_page', $content, TRUE);
$this->load->view('public_template', $data);
}
}
// embeds/home_page.php
<div id="container">
<h1>Home Page</h1>
<p><?php echo $text; ?></p>
Change Content
</div>
// public_template.php
<html>
<head>
<title>Home Page</title>
<script src="/jquery.js"></script>
<script src="/myscript.js"></script>
</head>
<body>
<?php echo $content; ?>
</body>
</html>
// myscript.js
$(function(){
$("#container a").live("click", function(e){
e.preventDefault();
$.ajax({
url: $(this).attr("href"),
success: function(data) {
$("#container p").html(data);
}
});
});
});
// my_other_controller.php
class My_other_controller extends CI_Controller {
function method(){
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']=="XMLHttpRequest") {
// is an ajax request
echo "This is new content for the page.";
} else {
// is not an ajax request, render whole page
$content['text'] = "This is new content for the page.";
$data['content'] = $this->load->view('embeds/home_page', $content, TRUE);
$this->load->view('public_template', $data);
}
}
}

Related

updating div without page refresh

i have a php script that counts button clicks to a txt file. this is working just fine.
On my html page i am displaying the clicks as such :
<?php
include ('counter.php');
?>
<div class="count_right" id="one"></div>
<div class="count_left" id="two"></div>
<form action="" method="post" id="form" >
<button class="vote_right" name="clicks1" ></button>
</form>
<form action="" method="post" id="form2" >
<button class="vote_left" name="clicks2"></button>
</form>
the php
<?php
if( isset($_POST['clicks1']) ) {
incrementClickCount1();
}
function getClickCount1()
{
return (int)file_get_contents("count_files/clickcount1.txt");
}
function incrementClickCount1()
{
$count = getClickCount1() + 1;
file_put_contents("count_files/clickcount1.txt", $count);
}
if( isset($_POST['clicks2']) ) {
incrementClickCount2();
}
function getClickCount2()
{
return (int)file_get_contents("count_files/clickcount2.txt");
}
function incrementClickCount2()
{
$count2 = getClickCount2() + 1;
file_put_contents("count_files/clickcount2.txt", $count2);
}
?>
and the js (EDITED)
<script type="text/javascript">
var valueOne = "<?php echo getClickCount1(); ?>";
var valueTwo = "<?php echo getClickCount2(); ?>";
$('#one').html(valueOne);
$('#two').html(valueTwo);
$('.vote_right').click(function(){
$.ajax({
type: "POST",
url: "counter.php",
data: valueOne,
cache: false,
success: function(data)
{
$("#one").html(data);
} });
</script>
tried also adding
e.preventDefault();
but then the button wont work.
My problam is that i dont want the page to refresh when the button is clicked. insted i would like the div to refresh with the new data.
I have tried usin ajax but with no success. its either the page refreshes or the data wont update.
Any suggestions?
Use type=button to not submit the form when clicking buttons (and thus prevent page reloading).
<button type="button" class="vote_right" name="clicks1" ></button>
The below shows how to write two of the 4 api calls you need to add to your website.
Main Page:
<?php
include ('counter.php');
?>
<div class="count_right" id="one"></div>
<div class="count_left" id="two"></div>
<button class="vote_right" name="clicks1" onclick="addCount1()"></button>
<button class="vote_left" name="clicks2" onclick="addCount2()"></button>
JS:
<script type="text/javascript">
var valueOne = //use ajax (GET) to call the page for count1;
var valueTwo = //use ajax (GET) to call the page for count2;
$(document).ready(function(){
$('#one').html(valueOne);
$('#two').html(valueTwo);
});
function addCount1(){
//use ajax (POST/PUT) to call a page that adds 1 to your text file thing for count1
}
function addCount2(){
//use ajax (POST/PUT) to call a page that adds 1 to your text file thing for count2
}
</script>
New API Page (for count1):
<?php
class IntegerValue implements JsonSerializable {
public function __construct($number) {
$this->number = (integer) $number;
}
public function jsonSerialize() {
return $this->number;
}
}
echo json_encode(new IntegerValue(getClickCount1()), JSON_PRETTY_PRINT);
?>
New API page (for count2):
<?php
class IntegerValue implements JsonSerializable {
public function __construct($number) {
$this->number = (integer) $number;
}
public function jsonSerialize() {
return $this->number;
}
}
echo json_encode(new IntegerValue(getClickCount2()), JSON_PRETTY_PRINT);
?>
How PHP and JavaScript work
On initial page load:
The process flow looks like this:
Server Side code (php) -> sends data to client -> browser begins rendering and executing JS
On form Submit:
Client Executes code (javascript) -> Sends data to server -> Server gets data and processes (PHP)
Because of this if you don't want the page to "refresh" you'd have to use JavaScript and the best way of handling this is AJAX if you use a form you are going to get a refresh also known as a POST-BACK. Otherwise with AJAX you can easily just send a POST or a GET and it won't refresh.
No need to put with in form tag for ajax async request.
Use only
<?php
include ('counter.php');
?>
<div class="count_right" id="one"></div>
<div class="count_left" id="two"></div>
<button class="vote_right" name="clicks1" ></button>
<button class="vote_left" name="clicks2"></button>

How to load a script in a template footer - CodeIgniter

I'm trying out a more maintainable way to structure my code as learnt by some tutorials at nettuts+.
I've succeeded in making my header and footer files separate from the main content of each page so that they are loaded along with each different page, thus making it easier to manage changes to these two files.
I currently want to add some jQuery code to my footer, for only one page. This is where I've hit a wall in thinking. How can I allow this jQuery code to be present in my footer for only one page, and not all pages? Could someone please explain?
I was thinking of doing something like:
<?php if($title = "The jQuery Page"){?>
<script>
jquery code here....
</script>
<?php } ?>
But I think that is considered messy, as you are using one language to set off another.
Edit: Here's the requested code:
In my Controller I call the views:
$data['title'] = "The jQuery Page";
$this->load->view('header', $data);
$this->load->view('cool_page');
$this->load->view('footer');
Then in my footer I want to load a specific script in only this one pages footer:
<script src="<?php echo base_url();?>js/jquery-1.10.2.min.js"></script>
<script>
$(document).ready(function() {
/*cool jquery stuff*/
});
</script>
Try to load a view into the main view
/application/controllers/test.php
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Test extends CI_Controller {
public function index() {
$data = array(
'title' => "The jQuery Page",
'script' => TRUE // if you omit or comment this variable the 'views/script.php' is not loaded
);
$this->load->view('test', $data);
}
}
/application/views/test.php
<html>
<head>
<title><?php echo $title;?></title>
</head>
<body>
<?php if (isset($script)) { $this->load->view('script'); } ?>
</body>
</html>
/application/views/script.php
<script>
jquery code here....
</script>
You could specify JS to include as part of the data passed to the view:
CONTROLLER1
$this->data['js'][] = 'alert(\'Hi\');';
$this->data['js'][] = 'alert(\'Hey\');';
$this->load->view('footer', $this->data);
CONTROLLER2
$this->data['js'][] = 'alert(\'Yo\');';
$this->data['js'][] = 'alert(\'Sup\');';
$this->load->view('footer', $this->data);
Footer VIEW
if(isset($js) && is_array($js) && count($js) > 0){
echo '<script>';
foreach($js as $key=>$value){
$value;
}
echo '</script>';
}
I don't think there is a way around making a conditional 'if' statement around the script, so I used the suggested solution in my question.
Check the title to see if it is the desired page:
<?php if($title = "Photo Albums - Hands of Humanity"):?>
Then add the script to the DOM if it is so:
<script>
$(document).ready(function() {
//jquery stuff
});
</script>
<?php endif;?>
If there are other ways which are better for maintainability, I would be happy to hear them

Load page while PHP is executing

What Im trying to do: Display a loading gif or text... at the very least show a black screen before and during the time the php is being executed.
What I have tried.
I have tested using flush () and I get nothing until the entire php process is finished. I dont particularly like this concept either but I'll take anything.
I am considering using two pages to accomplish this though the current project is nearly complete and would take some time to consolidate the scattered html/php code.
Currently I'm doing 3-simpleXML_load_file(), 1-include(), 1-file_get_contents()
I have javascript function plotting data from one of the simpleXML_Load_file()...
Im up for moving parts of the code to a different file but it's a big task. So id like some advise or suggestions on how to proceed.
If I need to elaborate more just ask!
Thanks,
JT
<html>
<head>
<?php
$lat = $_POST['Lat'];
$long = $_POST['Lon'];
$weather_hourly = simplexml_load_file('http:....lat='.$lat.'&lon='.$long.'');
?>
<script type="text/javascript">
<!--Plot function-->
$(function()
{
var d =
[
<?php
//Pulling in hourly data to plot temp vs time
$i=0;
$array=array();
while ($i<=100)
{
echo '['. (strtotime($weather_hourly->data->{'time-layout'}->{'start-valid-time'}[$i])*1000) .','.$weather_hourly->data->parameters->temperature->value[$i] .'],';
$value = $weather_hourly->data->parameters->temperature->value[$i];
array_push($array,$value);
$i++;
}
foreach ($array as $key => $value)
{
$value = (string) $value;
$min_sec_array[] = $value;
}
?>
</script>
</head>
<body>
<div id=graph>
</div>
</body
The main way you can accomplish this is by using AJAX and multiple pages. To accomplish this, the first page should not do any of the processing, just put the loading image here. Next, make an AJAX request, and once the request is finished, you can show the results on the page or redirect to a different page.
Example:
File 1 (jQuery must be included also), put this in the body along with the loader animation:
<script language="javascript" type="text/javascript">
$(function(){
var mydata = {};
$.post('/myajaxfile.php', mydata, function(resp){
// process response here or redirect page
}, 'json');
});
</script>
Update: Here is a more complete example based on your code. This has not been tested and needs to have the jQuery library included, but this should give you a good idea:
File 1: file1.html
</head>
<body>
<?php
$lat = $_POST['Lat'];
$long = $_POST['Lon'];
?>
<!-- Include jQuery here! Also have the loading animation here. -->
<script type="text/javascript">
$(function(){
$.get('/file2.php?Lat=<?php echo $lat; ?>&Lon=<?php echo $long; ?>', null, function(resp){
// resp will have the data from file2.php
console.log(resp);
console.log(resp['min_sec_array']);
console.log(resp['main']);
// here is where you will setup the graph
// with the data loaded
<!--Plot function-->
}, 'json');
});
</script>
<div id=graph>
</div>
</body
</html>
File 2: file2.php
I'm not sure if you needed the $min_sec_array, but I had this example return that as well as the main data you were using before.
$lat = $_POST['Lat'];
$long = $_POST['Lon'];
$weather_hourly = simplexml_load_file('http:....lat='.$lat.'&lon='.$long.'');
//Pulling in hourly data to plot temp vs time
$i=0;
$main = array();
$array=array();
while ($i<=100)
{
$main[] = array((strtotime($weather_hourly->data->{'time-layout'}->{'start-valid-time'}[$i])*1000), $weather_hourly->data->parameters->temperature->value[$i]);
$value = $weather_hourly->data->parameters->temperature->value[$i];
array_push($array,$value);
$i++;
}
foreach ($array as $key => $value)
{
$min_sec_array[] = (string) $value;
}
echo json_encode(array(
'min_sec_array' =>$min_sec_array,
'main' => $main
));
exit();
?>
I would recommend not to do this with plain html and php if u expect it modify the page after it is loaded. Because php is server side processing, so it is executed before the page is send to the user. U need Javascript. Using Javascript will enable u to dynamically add or remove html elements to or from the DOM tree after the page was send to the user. It is executed by the users browser.
For easier start I would recommend jQuery, because there are lots of tutorials on such topics.
JQuery
JQuery learning center
A small example:
HTML
<head>
<meta charset="utf-8" />
<title> </title>
<script type="text/javascript" src="js/lib/jquery-1.9.1.js"></script>
</head>
<body>
<h1>Addition</h1>
<div id="error_msg"> </div>
<div id="content">
<!-- show loading image when opening the page -->
<img src="images/loading.gif"/>
</div>
<script type="text/javascript">
// your script to load content from php goes here
</script>
</body>
this will be nothing more then the following until now:
adding the following php file
<?php
$num1 = $_GET['num1'];
$num2 = $_GET['num2'];
$result = $num1 + $num2;
echo '<p>Calculating '.$num1.' + '.$num2.' took a lot of time, but finally we were able to evaluate it to '.$result.'.</p>'
.'<p> '.$num1.' + '.$num2.' = '.$result.'</p>';
?>
wont change anything of the html, but adding javascript/ Jquery inside the HTML will be kind of connection between static html and server side php.
$(document).ready(function(){
$.ajax({ // call php script
url: 'php/script.php?num1=258&num2=121',
type:'GET',
timeout: 500,
contentType: 'html'
}).success(function(data){
// remove loading image and add content received from php
$('div#content').html(data);
}).error(function(jqXHR, textStatus, errorThrown){
// in case something went wrong, show error
$('div#error_msg').append('Sorry, something went wrong: ' + textStatus + ' (' + errorThrown + ')');
});
});
This will change your page to show the loading animation until the php script returns its data, like:
So you can setup the whole page in plain html, add some loading gifs, call several php scripts and change the content without reloading the page itself.
It is kind of nasty solution to your problem...
But this can work:
You work with those -
ob_start();
//printing done here...
ob_end_flush();
at the beginning you will create your rotating ajax gif...
Then you do all the processing and calculating you want...
At the end of the processing, just echo a small script that does a hide to your gif...
Depends on the exact need, maybe ajax can be more elegant solution.
In response to your conversation with David Constantine below, did you try using ob_flush()?
ob_start();
echo '<img src="pics/loading.gif">';
ob_flush();
// Do your processing here
ob_end_flush();
I think you don't have a problem with flushing your PHP output to the browser, but more likely with getting the browser to start rendering the partial html output. Unfortunately, browser behavior on partial html is browser-specific, so if you want something to work the same in any browser, the AJAX solution suggested in other answers is the better way to go.
But if you don't like that added complexity of a full AJAX solution, you can try to make your html output "nice" in the sense of providing some body output that can be formatted without needing the rest of the html output. This is were your sample code fails: It spends most of its time outputting data into a script tag inside the html header. The browser never even sees the start of the body until your PHP code has practically finished executing. If you first write your complete body, then add the script tag for the data there, you give the browser something to at least try to render whilst waiting for the final script to be completed.
I've found the same issue (albeit not in PHP) discussed here: Stack Overflow question "When do browsers start to render partially transmitted HTML?" In particular, the accepted answer there provides a fairly minimal non-AJAX example to display and hide a placeholder whilst the html file hasn't completely loaded yet.
I know this is an old question, but the answer provided in this page by rpnew is extremely clear and easy to adjust to your project's requirements.
It is a combination of AJAX and PHP.
The HTML page PHPAjax.html which calls the PHP script:
<html>
<head>
<script type="text/javascript">
document.write('<div id="loading">Loading...</div>');
//Ajax Function
function getHTTPObject()
{
var xmlhttp;
if (window.ActiveXObject)
{
try
{
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try
{
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (E)
{
xmlhttp = false;
}
}
}
else
{
xmlhttp = false;
}
if (window.XMLHttpRequest)
{
try
{
xmlhttp = new XMLHttpRequest();
}
catch (e)
{
xmlhttp = false;
}
}
return xmlhttp;
}
//HTTP Objects..
var http = getHTTPObject();
//Function which we are calling...
function AjaxFunction()
{
url='PHPScript.php';
http.open("GET",url, true);
http.onreadystatechange = function()
{
if (http.readyState == 4)
{
//Change the text when result comes.....
document.getElementById("content").innerHTML="http. responseText";
}
}
http.send(null);
}
</script>
</head>
<body onload="AjaxFunction()">
</body>
</html>
The Background PHP Script PHPScript.php:
<?php
sleep(10);
echo "I'm from PHP Script";
?>
Save both files in the same directory. From your browser open the HTML file. It will show 'Loading...' for 10 seconds and then you will see the message changing to "I'm from PHP Script".

Call function in a seperate div tagad from href link

I have two files: index.php and cart.php
In cart.php I have few three functions - products_all(), products_shirts(), products_hoodies(). Those functions get info from my database and outputs it if called.
I want each of those functions to be called by clicking on hyperlinks and then to be outputed in a div tag, so that only the div tag is being refreshed not the whole site.
I read about jQuery/AJAX function load, but I can't get it to work.
If you don't want the whole page to be refreshed, there is no way around using ajax.
But it's not that hard. When using a library like jQuery, you can do it in a few lines.
Your HTNL + javscript code:
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
function callFunction(yourfunction)
{
$.post('cart.php', { "function": yourfunction }, function(data) {
alert(data);
});
}
$(document).ready(function()
{
$("#functionOne").on("click", function()
{
callFunction(1)
});
$("#functionTwo").on("click", function()
{
callFunction(2)
});
});
</script>
</head>
<body>
<a id="functionOne">function one</a>
<a id="functionTwo">function two</a>
</body>
</html>
And on the server side (cart.php) something like this:
<?php
if (isset($_POST['function']))
{
switch ($_POST['function'])
{
case 1:
functionOne();
break;
case 2:
functionTwo();
break;
}
}
function functionOne()
{
echo "hi, i am func1";
}
function functionTwo()
{
echo "hi, i am func2";
}
This should get you started!

Zend MVC - design - onClick, load new view ? A view inside a view?

I have a page and, that page will fade out to display a new content (from another view).
In general terms, what should we have into consideration here?
Where should I dig in to make this possible?
Should I call a view inside another view, by using some sort of ajax?
class EquipasController extends OccControllerAction{
public function init(){
if ($this->getRequest()->isXMLHttpRequest()) {
$this->_helper->layout()->setLayout('blank');
//$this->_helper->layout()->disableLayout();
$logger = $this->getInvokeArg('bootstrap')->getResource('Log');
$logger->debug('AJAX Call');
}
}
public function listaAction()
{
echo ("I'm HERE??");
$dados = array('dados1', 'dados2', 'dados3');
}
}
<h1>Tests...</h1>
Mostra Lista Sff
<div id="testresults">
<h1>Esta é uma coisa que aparece sempre.</h1>
</div>
<script type="text/javascript">
$(function() {
$('.ajaxloader').click(function(event) {
var target = $(this).attr('href');
window.location.hash = target;
$.ajax({
url: target,
success: function(data) {
$('#testresults').html(data);
}
});
return false;
});
});
</script>
When I first load the page, all ok.
When I click the link, I actually get an ajax call (because I notice no refresh).
When it displays it displays the all page again.
It doesn't display the echo that i've put on listaAction ! :-(
UPDATE:
When I see my link URL on the browser I see:
http://mypage.org/equipas/registo#/equipas/lista
By on the anchor I have:
http://mypage.org/equipas/lista
Could the issue be here?
I've done this exact thing before. Here's a stripped down version of what I do.
Have a 'blank' layout. This excludes any global header/content/css.
Have a 'smart' controller init() or plugin that will toggle between your default and blank layout if the request is ajax. Here's my (stripped) controller code:
class TestController extends Zend_Controller_Action
{
public function init()
{
/* Initialize action controller here */
if ($this->getRequest()->isXMLHttpRequest()) {
$this->_helper->layout()->setLayout('blank');
$logger = $this->getInvokeArg('bootstrap')->getResource('Log');
$logger->debug('AJAX Call');
}
}
public function indexAction()
{
// render the default page
}
public function speedAction()
{
// Do stuff render something
}
public function somethingelseAction()
{
// do something else render something.
}
}
Have your initial view render with a target div, as well as some links that you want to go into that target. Here's my index.phtml:
<h1>Tests...</h1>
<a class="ajaxloader"
href="<?php echo $this->url(array('controller'=> 'test', 'action' => 'speed'), null, true);?>">Speed</a>
<a class="ajaxloader"
href="<?php echo $this->url(array('controller'=> 'test', 'action' => 'somethingelse'), null, true);?>">Something Else</a>
<div id="testresults">
<h1>Default stuff to show.</h1>
</div>
Setup some jQuery code (however you like) to attach to these 'ajaxloader' links and target your results to the 'testresults' div. Here's some basic JS:
$(function() {
$('.ajaxloader').click(function(event) {
var target = $(this).attr('href');
window.location.hash = target;
$('#testresults').fadeOut('slow', function() {
// complete fadeout, load new content while it's hiding!
$.ajax( {
url : target,
success : function(data) {
$('#testresults').html(data);
$('#testresults').fadeIn();
}
});
});
return false;
})
});
All links clicked on that have the class 'ajaxloader' will be loaded via ajax and put into the 'testresults' div.
If your page causes a portion to fade out then you must use JavaScript (or CSS animation or IE's old, awful propriety, meta tags).
I would use JavaScript to fetch a view via AJAX, and load it into an element on your page.

Categories