'jQuery UI Portlet Save State on Database
We can drag and drop elements using jQuery UI sortable - Portlets. I want to save the state into the MySQL database. Any way (Perhaps AJAX) to do so?
My HTML:
<div class="column" id = "column-1">
First Category
<div class="portlet">
<div class="portlet-header">Feeds</div>
<div class="portlet-content">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</div>
</div>
<div class="portlet">
<div class="portlet-header">News</div>
<div class="portlet-content">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</div>
</div>
</div>
<div class="column" id = "column-2">
Second Category
<div class="portlet">
<div class="portlet-header">Shopping</div>
<div class="portlet-content">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</div>
</div>
</div>
<div class="column" id = "column-3">
Third Category
<div class="portlet">
<div class="portlet-header">Shopping</div>
<div class="portlet-content">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</div>
</div>
<div class="portlet">
<div class="portlet-header">Shopping</div>
<div class="portlet-content">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</div>
</div>
</div>
<div class="column" id = "column-4">
Fourth Category
<div class="portlet">
<div class="portlet-header">Links</div>
<div class="portlet-content">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</div>
</div>
<div class="portlet">
<div class="portlet-header">Images</div>
<div class="portlet-content">Lorem ipsum dolor sit amet, consectetuer adipiscing elit</div>
</div>
</div>
My JavaScript:
<script>
$( function() {
$( ".column" ).sortable({
connectWith: ".column",
handle: ".portlet-header",
cancel: ".portlet-toggle",
placeholder: "portlet-placeholder ui-corner-all"
});
$( ".portlet" )
.addClass( "ui-widget ui-widget-content ui-helper-clearfix ui-corner-all" )
.find( ".portlet-header" )
.addClass( "ui-widget-header ui-corner-all" )
.prepend( "<span class='ui-icon ui-icon-minusthick portlet-toggle'></span>");
$( ".portlet-toggle" ).on( "click", function() {
var icon = $( this );
icon.toggleClass( "ui-icon-minusthick ui-icon-plusthick" );
icon.closest( ".portlet" ).find( ".portlet-content" ).toggle();
});
} );
</script>
Styling:
<style>
body {
min-width: 520px;
}
.column {
width: 170px;
float: left;
padding-bottom: 100px;
}
.portlet {
margin: 0 1em 1em 0;
padding: 0.3em;
}
.portlet-header {
padding: 0.2em 0.3em;
margin-bottom: 0.5em;
position: relative;
}
.portlet-toggle {
position: absolute;
top: 50%;
right: 0;
margin-top: -8px;
}
.portlet-content {
padding: 0.4em;
}
.portlet-placeholder {
border: 1px dotted black;
margin: 0 1em 1em 0;
height: 50px;
}
</style>
Scripts and Stylesheets:
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
Any help would be appreciated for PHP. Below is the screenshot of current state:
Whenever the user drags and drops element from First Category to Second Category, it should be updated on the database.
Solution 1:[1]
I don't really really understand your question, or even what you mean by states, but I'll take a shot in the dark and assume you mean that you want to save the position of each box relative to the columns.
I would set it up so that each column has a name/number, and each box has a rank.
So each box when either initialized or changed would have a rank (0 to infiniti), and it's parent, the column, would have a name
Say you move the News box from the first category to the second category under the shopping box.
When you first look at it, News would be designated as ['First', 1]. After the switch it would be ['Second', 1].
Solution 2:[2]
I found a way to save states of a portlet (expanded, collapsed and position) https://github.com/coyote333666/pjp
for example, if showOrHide = {"portlet-content-01":0,"portlet-content-02":0,"portlet-content-03":1,"portlet-content-04":0}
to save expanded and collapsed states:
$( ".portlet" )
.addClass( "ui-widget ui-widget-content ui-helper-clearfix ui-corner-all" )
.find( ".portlet-header" )
.addClass( "ui-widget-header ui-corner-all" )
.prepend( "<span id='s1' class='ui-icon ui-icon-minusthick portlet-toggle'></span>");
$( ".portlet-toggle" ).on( "click", function() {
var icon = $( this );
icon.toggleClass( "ui-icon-minusthick ui-icon-plusthick" );
icon.closest( ".portlet" ).find( ".portlet-content" ).toggle();
var x = icon.closest( ".portlet" ).find( ".portlet-content" ).attr("id");
if ( showOrHide[x] == 1 )
{
showOrHide[x] = 0;
}
else if ( showOrHide[x] == 0 )
{
showOrHide[x] = 1;
}
var data = {
'state' : JSON.stringify(showOrHide)
}
$.ajax({
data: data,
type: 'POST',
url: '<?php echo("?" . S_PARAMETER_REDIRECTOR .S_FILE_PORTLET_UPDATE); ?>'
});
});
to restore expanded and collapsed states:
$(window).ready(function()
{
for (var k in showOrHide)
{
var last2 = k.slice(-2);
if (showOrHide.hasOwnProperty(k))
{
if (showOrHide[k] == 1 )
{
$('#' + k).show();
}
else if (showOrHide[k] == 0 )
{
$('#' + k).hide();
$('#portlet-header-' + last2 + ' #s1.ui-icon-minusthick').removeClass('ui-icon-minusthick').addClass('ui-icon-plusthick');
}
}
}
});
to save position state:
var showOrHide = <?php
$sQuery =
"
SELECT portlets_state,portlets_left,portlets_right
FROM portlet_user
WHERE user_id = " . fncSetInt($_SESSION["user_id"]) . ";
";
$oRecordset = fncQueryPg($sQuery);
if(!empty($oRecordset[0]["portlets_state"]["VALUE"]))
{
echo($oRecordset[0]["portlets_state"]["VALUE"]);
}
else
{
if(!empty($oRecordset[0]["portlets_left"]["VALUE"]))
{
$portlet = explode(",", $oRecordset[0]["portlets_left"]["VALUE"]);
}
if(!empty($oRecordset[0]["portlets_right"]["VALUE"]))
{
$section_2 = explode(",", $oRecordset[0]["portlets_right"]["VALUE"]);
for($z=0; $z<sizeof($section_2); $z++)
{
array_push($portlet,$section_2[$z]);
}
}
for($z=0; $z<sizeof($portlet); $z++)
{
$key = str_replace('portlet_','portlet-content-',$portlet[$z]);
$aPortlet[$key] = 1;
}
echo(json_encode($aPortlet));
} ?>;
$( ".column" ).sortable({
connectWith: ".column",
handle: ".portlet-header",
cancel: ".portlet-toggle",
placeholder: "portlet-placeholder ui-corner-all",
update: function (event, ui) {
var list = $(this).sortable("toArray").join(",");
var data = {
'section': this.id,
'components': list
}
$.ajax({
data: data,
type: 'POST',
url: '<?php echo("?" . S_PARAMETER_REDIRECTOR .S_FILE_PORTLET_UPDATE); ?>'
});
}
});
to restore position state :
<div class="column" id="section-1">
<?php
$sQuery =
"
SELECT portlets_left,portlets_right
FROM portlet_user
WHERE user_id = " . fncSetInt($_SESSION["user_id"]) . ";
";
$oRecordset = fncQueryPg($sQuery);
$section_1 = $oRecordset[0]["portlets_left"]["VALUE"];
$section_2 = $oRecordset[0]["portlets_right"]["VALUE"];
if(!empty($section_1))
{
$portlet = explode(",", $section_1);
for($z=0; $z<sizeof($portlet); $z++)
{
require_once($portlet[$z] . ".php");
}
}
?>
</div>
<div class="column" id="section-2">
<?php
if(!empty($section_2))
{
$portlet = explode(",", $section_2);
for($z=0; $z<sizeof($portlet); $z++)
{
require_once($portlet[$z] . ".php");
}
}
?>
</div>
and portlet update :
if(isset($_POST["components"]) && isset($_POST["section"]))
{
$sListePortlet = preg_replace('/\,+/', ',', trim($_POST["components"],','));
if($_POST["section"] == 'section-1')
{
$sQuery =
"
UPDATE portlet_user
SET portlets_left = " . fncSetString($sListePortlet) . "
WHERE user_id = " . fncSetInt($_SESSION["user_id"]) . ";
";
fncQueryPg($sQuery);
}
if($_POST["section"] == 'section-2')
{
$sQuery =
"
UPDATE portlet_user
SET portlets_right = " . fncSetString($sListePortlet) . "
WHERE user_id = " . fncSetInt($_SESSION["user_id"]) . "
";
fncQueryPg($sQuery);
}
}
if(isset($_POST["state"]))
{
$sQuery =
"
UPDATE portlet_user
SET portlets_state = " . fncSetString($_POST["state"]) . "
WHERE user_id = " . fncSetInt($_SESSION["user_id"]) . ";
";
fncQueryPg($sQuery);
}
Note that you place eache portlet in a separate file : portlet_99.php where 99 = 01,02,...
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | hamza765 |
| Solution 2 |

