Okay.
routes.php:
Route::get('routine_details/{routine}','RoutineController@details'); // Getting the routine details on a separate view. {routine} is a placeholder for the number we're getting in view_routine.blade.php
Controller:
public function details ($routine) // Getting the routine id number from the view.$routine is a placeholder.
{
$user=Auth::user();
$exercises_routines=ExerciseRoutine::where('routine_id',$routine)->where('user_id',Auth::user()->id)->get();
// TO DO :
// if (count($exercises_routines == 0){echo "no exercises found"})
//SELECT * FROM exercises_routines WHERE routine_id= 30
$exercises_in_routine = array();
$count = 0;
foreach($exercises_routines as $single_routine)
{
//echo $single_routine->exercise_id; accessing the ExerciseRoutine , and get the exercise id's associated with the current routine.
$exercise_id = $single_routine->exercise_id; //So far we accessed the routine_id column. Now we're assigning all the exercises id's to the $single_routine.and now it has all its exercises.
$exercise =Exercise::find($exercise_id); // Accessing the Exercise Model, and looking for those exercises we're looking for, and making a match (for each loop - for one exercise only).
//Select * from exercises where id = 11
$exercises_in_routine[$count]['id'] = $exercise->id; // for each loop, we're getting the exercise id of that loop. We found the exercise through the Exercise model.
$exercises_in_routine[$count]['exercise_name'] = $exercise->name; //for each loop, we're getting the exercise name of that loop.
$exercises_in_routine[$count]['image_path'] = "images/".$exercise->image_path; //for each loop, we're getting the exercise image_path of that loop.
$exercises_in_routine[$count]['category'] = $exercise->category; //for each loop, we're getting the exercise category of that loop.
$count++; // Insert it all in the array ,as done above. and then iterate again, and add 1 to the count.
}
//Todo : Ask Karthik if there is a better way to bring details.
/*
echo "Print Exercises in routin";
echo "<pre>";
print_r($exercises_in_routine);
echo "<pre/>";
*/
// Arranging the array in form of categories:
$exercise_category = array(); //Stores the exercise category.
$list_of_exercises = array(); //Stores exercises but ordered by a category.
for($x=0; $x<count($exercises_in_routine); $x++)
{
$category = $exercises_in_routine[$x]['category']; // Get the current exercise category, from the foreach loop above (it's a value that we get there)
// We're accessing a property called 'category'.
if(!in_array($category, $exercise_category))
{
//If category is not inside the array - create a new key
$list_of_exercises[$category][0]['exercise_name'] = $exercises_in_routine[$x]['exercise_name']; // We're accessing again the array above and getting the exercise_name there, and assigning it to the new array name.
// We're using here an asssociative array, so we're assigning a value to the key 'exercise_name' in this array.
$list_of_exercises[$category][0]['image_path'] = $exercises_in_routine[$x]['image_path']; // Same thing goes here, like with exercise_name one line above.
$list_of_exercises[$category][0]['id'] = $exercises_in_routine[$x]['id']; // Same thing goes here, like with exercise_name 2 lines above.
array_push($exercise_category, $category); //Push the category to exercise category
}
else
{ // exercise_name and image_path and id are all used for the array.
$count = count($list_of_exercises[$category]); // Gives count of array elements in php. we're counting the exercises of the same category, so it could increase the index number by one each time.
$list_of_exercises[$category][$count]['exercise_name'] = $exercises_in_routine[$x]['exercise_name']; //If we already have the category name in the TRUE condition above, we're trying to get the rest of the exercises of the same group.
$list_of_exercises[$category][$count]['image_path'] = $exercises_in_routine[$x]['image_path']; // Trying to get the image_path of the image from the same category we're on now (stored in $category). Also getting the current count value.
$list_of_exercises[$category][$count]['id'] = $exercises_in_routine[$x]['id']; // Trying to get the id of the image from the same category we're on now (stored in $category). Also getting the current count value.
}
}
// dd($list_of_exercises);
return view('routine_details',compact('user','exercises_routines','routine','list_of_exercises','count'));
View:
@extends('layouts.master')
<meta name="_token" content="{!! csrf_token() !!}"/>
@section('scripts')
<script type="text/javascript">
/*
Live Binding(for future events): When the browser will detect a class called pickexercise, it'll trigger the function.
This won't work: ( the browser here expects to identify this class on document ready.)
$('.pickexercise').click(function (event)
{
console.log("hello");
});
*/
$(document).on('click','.pickexercise', function(event)
{
// Getting the neccesary parameters to update to another exercise.
var new_exercise = $(this).val(); // Getting the current value of the exercise being clicked (which is an id of the exercise).
var routine = $('.routine').html(); //getting the current routine id. Putting it with .html (since it's the content of the routine class)
//console.log(routine);
var old_exercise = $(this).attr('id');
//var token =$('.token').val();
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type: "POST",
url: "update_routine",
data: {
// getting the picked exercise, old exercise and routine id with the variables declared above.
//'_token':token,
'chosen_exercise': new_exercise,
'routine': routine,
'exercise_to_replace': old_exercise
},
success: function (data) {
console.log("updated");
//Comment out this line for debugging purposes.
window.location.reload();
},
error: function(data)
{ // This is error callback function.Can be written for testing purposes, to see if the ajax function's is being executed well.
alert("An error occured.");
}
});
});
</script>
<!-- CSRF Token. -->
<meta name="_token" content="{{csrf_token()}}">
<script type="text/javascript">
$(document).ready(function(){ // . is used for class identify. # is for id.
$('.replaceExercise').on('click', function(e){
$('.modal-body').html(''); // clear the modal-body each time we're opening the modal-body div.
var exercise_id = $(this).val(); // Getting the current value attribute of the replaceExercise button (replaceExercise is defined in line 22).
console.log("Exercise "+exercise_id);
$.ajax({
url: 'edit_routine',
type: "POST",
data: {'exercise_id':exercise_id}, // First parameter is a name given for the data. Second parameter (exercise_id) is the variable declared above (value).
success: function(data){
console.log(data);
var count;
// Accessing the data in this format: Access of index and then accesing its key (which could be (in this instace, take from exercises table: id, image_path etc).
for(count = 0; count < data.length; count++)
{
var name= data[count].name; // Accessing the data object,than accessing the current count of the iteration (first is 0). Then accessing the name property in the Exercise model. The name is accessed throught the data parameter.
var id= data[count].id;
var image_path= data[count].image_path;
//console.log(location.origin);
image_path = location.origin + '/images/' + image_path;
element = '<li>';
/*
if(count==0)
{
element+='<input type="hidden" class="token" id="token" value="{{ csrf_token() }}”>';
}
*/
element += '<img src='+image_path+'>';
element+= '<span>' + name + '</span>';
// check if the exercise id number is NOT equal to the current picked exercise_id, so we could show the pick exercise buttton to the different exercises and not the same one.
if(id != exercise_id){
// Getting the old exercise id, and in the value attribute we're getting the new id of the new exercise picked.
element+= '<button class="pickexercise" id='+exercise_id+' type="submit" value="'+id+'">Pick this exercise</button>';
}
// Catch the id of the exercises, when you click the button.
element+= '</li>';
//console.log(name); // showing the exercises name of the picked exercise mutual category.
//console.log(element);
$('.modal-body').append(element); // replace the entire modal-body div with the element contents we are passing.
}
}
});
});
});
</script>
<!-- Saving the replacement exercise to the server. -->
<script type="text/javascript">
// Should be triggered only once when clicking on "Replace this exercise".
</script>
<script type="text/javascript">
$.ajaxSetup({
headers: { 'X-CSRF-Token' : $('meta[name=_token]').attr('content') }
});
</script>
@stop
@section('content')
{!! csrf_field() !!}
@if (count($errors) > 0)
<div class="alert alert-danger">
<strong>Whoops!</strong> There were some problems with your input.<br><br>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<p>Hello, {{ $user->name }}.</p>
<!-- Key is: category_name and Value is $exercise array (using the foreach loop with associative array). -->
<div class="routine" style="visibility:hidden">{{ $routine }}</div>
<!--<script></script> !--><!-- $routine represents the current routine id taken from the details() function in the controller.
<!-- getting the current routine id from the details() function in the controller. -->
<div class="panel-group" id="accordion">
<?php $accordion_count = 0; ?> <!-- $accordion_count is used to iterate over accordion collapse divs (generated with a foreach (the divs)) -->
<!--
'abdomnials'
[0]=>exercise_name,
[1]=>exercise_name,
biceps
[0]
[1]
[2]
-->
@foreach($list_of_exercises as $category_name=>$exercise) {{--$exercise is getting values of the $list_of_exercises by their category name. $exercises is just a placeholder is this case. --}}
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a data-toggle="collapse" data-parent="#accordion" href="#collapse<?php echo $accordion_count; ?>"> <!-- Echoing the current $accordion_count value. -->
{{ $category_name }} </a>
</h4>
</div>
<div id="collapse<?php echo $accordion_count; ?>" class="panel-collapse collapse in"> <!-- attaching the current accordion_count value to the collapse name (collapse1,collapse2,etc...) -->
@for($x = 0; $x < count($exercise); $x++) <!-- we're iterating over exercises categories avobe. Now we're iterating over their individual exercises -->
<img src="{{ asset($exercise[$x]['image_path']) }}" />
<b>{{ $exercise[$x]['exercise_name'] }}</b>
<!-- Button trigger modal -->
<button type="button" id="replaceExercise" value="{{ $exercise[$x]['id'] }}" class="btn btn-primary btn-lg replaceExercise" data-toggle="modal" data-target="#myModal">
Replace this exercise
</button>
<!-- Iterating over the number of exercises the catergory (above) have, and going out once finised.Then increasing the number of $accordion_count.-->
<br/>
@endfor
</div>
</div>
<?php $accordion_count++; ?>
@endforeach
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
...
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
<div class="container">
Notice that in the ajax call I am writing window.location.reload(); to refresh the page after successfully replacing the image.
I have been told it's good for not overloading the server. Something like this. But I am sure you have better suggestion for this code? probably you would. @tykus_ikus