Add/Remove individual widgets from gridster - gridster

I'm trying to add and or remove a a widget based on a button click function. It works but once the function is called once it does something odd where the code is called on any mouse click instead of just the button click on the html page. So if I click the remove button on the html page it will remove that widget but then if I click any other widget (not on a button) it still removes that widget. I only want the function called on the html button click, not any mouse click. It's like the button is initializing something on the page to make any mouse click call the remove function. Can anyone explain why this is happening and how I can fix it? My code below:
function deleteWidget() {
var gridster = $('.gridster ul').gridster().data('gridster');
$(document).on( "click", ".gridster ul li", function() {
$(this).addClass("activ");
gridster.remove_widget($('.activ'));
});
}
function addWidget() {
var gridster = $(".gridster ul").gridster().data('gridster');
$(document).on("click", ".gridster ul li", function() {
gridster.add_widget('<li class="gs_w">The HTML of the widget...</li>', 2, 1);
});
}
<li data-row="1" data-col="4" data-sizex="1" data-sizey="1" class="gs_w"><button onclick="addWidget()" style="float: right;">+</button><h3>4</h3><span class="gs-resize-handle gs-resize-handle-both"></span></li>
<li data-row="1" data-col="6" data-sizex="1" data-sizey="1" class="gs_w"><button onclick="deleteWidget()"style="float: right;">-</button><h3>6</h3></li>
Thank you for any help!

When you click on your delete button, your code is creating a bind that makes any click on any widget, run the code to remove it.
$(document).on( "click", ".gridster ul li", function() {
$(this).addClass("activ");
gridster.remove_widget($('.activ'));
});
You can try change your html to:
<li data-row="1" data-col="4" data-sizex="1" data-sizey="1" class="gs_w"><button class="delete-button" style="float: right;">+</button><h3>4</h3><span class="gs-resize-handle gs-resize-handle-both"></span></li>
<li data-row="1" data-col="6" data-sizex="1" data-sizey="1" class="gs_w"><button class="add-button" style="float: right;">-</button><h3>6</h3></li>
and, in your javascript code, after initializing your gridster add:
$(document).on( "click", ".gridster .delete-button", function() {
var gridster = $(".gridster ul").gridster().data('gridster');
gridster.remove_widget($(this).parent());
});
$(document).on("click", ".gridster .add-button", function() {
var gridster = $(".gridster ul").gridster().data('gridster');
gridster.add_widget('<li class="gs_w">The HTML of the widget...</li>', 2, 1);
});
Hope it helps.

Below is the jQuery and HTML required for adding a widget to a gridster grid.
jQuery:
$(document).on( "click", "#addWidgetButton", function(e) {
e.preventDefault();
gridster.add_widget.apply(gridster, ['<li>new</li>', 1, 2]);
});
HTML:
<button id="addWidgetButton" style="float: right;">+</button>

Related

Modifying Bootstrap 3's Collapse Animation with Animate.css

I managed to override the default "collapse in" animation for Bootstrap 3's collapse plugin but unable override the toggle back animation.
Basically I want it to fade in (which is doing now) and fade out on close which at the moment its defaulting to the default BS animation for that event.
Example jsfiddle
<div class="collapse animated fadeIn" id="collapseExample">
<div class="well">
...
</div>
</div>
After taking a look at the Bootstrap 3 documentation for "collapse" and This other question, I took over the events and managed to get it working.
I removed all animate.css classes from element.
jQuery to override the show and hide events generated by BS.
Create a class that would delay the transition on "hide".
Result jsfiddle
JS
$(function() {
var animateIn = 'animated fadeIn';
var animateOut = 'animated fadeOut collapsing-delay';
$('#collapseExample').on('show.bs.collapse', function () {
// do something…
$(this).addClass(animateIn).on('shown.bs.collapse',
function() {
$(this).removeClass(animateIn);
});
})
$('#collapseExample').on('hide.bs.collapse', function () {
// do something…
$(this).addClass(animateOut).on('hidden.bs.collapse',
function() {
$(this).removeClass(animateOut);
});
})
})
CSS
.collapsing-delay {
/* delay BS transition for animated fadeOut to show */
-webkit-transition-delay: 2s !important;
transition-delay: 2s !important;
}

say I have many divs and each div trigger an event when clicked

Dojo 1.7
say I have many divs and each div trigger an event when clicked. So when I cilck a div, dojo adds a class, say "clicked" to the div. But how can I set it so when I click another div, it removes the previous div class "clicked" and gives it to the div that I just clicked?
This is because if I clicked on one div it supposed to change its background and remove the background from the previously clicked div
Thanks!!!
You can put all these div in one container, for example
<div class='RadioDivContainer'>
<div> </div>
....
<div> </div>
<div>
Then do this in onclick event handler of divs:
dojo.query(".RadioDivContainer .clicked").forEach(function(node){
dojo.removeClass(node, "clicked");
});
dojo.addClass(evt.target, "clicked");
This is just show the idea how to implement it. You can change it to suit your case.
You can remove the clicked class from all the elements in the group before applying the clicked class to the newly-clicked element.
Using Dojo 1.7:
require([
'dojo/query',
'dojo/dom-class',
'dojo/on',
'dojo/dom',
'dojo/domReady!'
], function(query, dom_class, on, dom) {
var boxes = query('.box', dom.byId('#container')); // get elements inside #container
boxes.forEach(function(box) {
on(box, 'click', function() {
boxes.forEach(function(b) {
dom_class.remove(b, 'clicked');
});
dom_class.add(box, 'clicked');
});
});
});
Here's a fiddle.
You could also keep track of the last clicked element and remove the clicked class from that. You can see both examples in the fiddle.
You should enable hooks to your desired DOM elements with dojo.query, handle click events using dojo.on and assign/unassign classes with dojo/dom-class. Give the div elements a shared class to denote that they are part of this clickable unit, then listen for click events on all of them and assign classes as necessary. See this JSfiddle, using Dojo 1.7.4:
HTML
<div class="mutable"></div>
<div class="mutable"></div>
<div class="mutable"></div>
Javascript/Dojo
require(["dojo/query", "dojo/dom-class", "dojo/on", "dojo/domReady!"], function(query, domClass, on) {
on(query(".mutable"), "click", function(e) {
query(".mutable").forEach(function(node) {
domClass.remove(node, "clicked");
});
domClass.add(this, "clicked")
});
});
CSS
.mutable {
background-color:red;
}
.clicked {
background-color:green;
}
div {
border:2px solid black;
margin:5px;
}
This will also work with Dojo 1.8.x and 1.9.x.

jsplumb state machine on multiple tabs

I am designing a web page for state machine and I am using jsplumb state machine. I want to draw this state machine on multiple tabs. Tabs are created dynamically using 'New' button
<div id="tabs">
<ul>
<li>
Untitled-1
<span class="ui-icon ui-icon-close"></span>
</li>
</ul>
<div id="Untitled-1" class="content">
<div id="Untitled-1-content" class="fsm">
</div>
</div>
</div>
In the div area of class 'fsm', state machine is drawn dynamically by dragging state machine(SM) blocks and dropping it in 'fsm' div. If there are multiple tabs, after dropping SM block in fsm div, it is draggable in fsm div only on 1st tab and not in another tabs. For example, if there are 2 tabs, I can re-position SM blocks only in 1st tab, on 2nd tab when I start dragging SM block, it disappears from fsm div and its left-top coordinates become negative.
This is the code for fsm div -
$("div.fsm").droppable({
accept: ".cTemp, .rTemp",
hoverClass: "ui-state-hover",
drop: function (event, ui) {
var draggable = $(ui.draggable[0]);
if (draggable.attr("class").indexOf("rTemp") > -1) {
$("<div class='rBase' id='rect" + rectI + "'></div>").text("rect" + rectI).appendTo(this);
$("#rect" + rectI).append("<div class='ep'></div>").appendTo(this);
$("#rect" + rectI).addClass("draggable");
jsPlumb.draggable($(".rBase"),{containment: ".fsm", zIndex: 30});
} else if (draggable.attr("class").indexOf("cTemp") > -1) {
$("<div class='cBase' id='circle" + circleI + "'></div>").text("circle" + circleI).appendTo(this);
$("#circle" + circleI).append("<div class='ep'></div>").appendTo(this);
$("#circle" + circleI).addClass("draggable");
jsPlumb.draggable($(".cBase"),{containment: ".fsm", zIndex: 30});
}
jsPlumbDemo.init();
}
});
This might be because fsm div is created dynamically or there are more than 1 fsm divs. What would be the best option to handle this multitab situation ?
I tried to remove fsm div from all tabs except the active tab then it works. I can drag SM blocks from tab content even if there are more than 1 tabs since there is only 1 fsm div. But then I have to add fsm div back again to the tab when I switch to that tab.
Then which is the best way to save the tab's content before switching to any other tab and load it back when that tab is opened ?
To give my background, this is my first time to work on jquery/jsplumb so detailed explanation is very much appreciated.
Here is a couple of comments
You can use the Jquery command hasClass() instead of attr("class")indexOf
To handle tabs I guess you are using the Jquery command tabs() ? in that case you don't need to save anything.
As far as your dropping issue is concerned you should use the appendTo: property in the draggable() parameters specifying which div they are supposed to be dropped to. You can change the target tab by reacting to the jquery tab select event this way
$("#tabs").tabs({
select: function(event, ui) {
// Your code
}
});
You can play with this fiddle I made for you
http://jsfiddle.net/webaba/sy9PJ/
$(document).ready(function () {
// Calls custom select tab function, scroll down for implementation
selectTab(1);
// Block models are made draggable
function selectTab(tabIndex) {
var tabName = '#tab'+tabIndex;
$(".model").draggable({
appendTo: tabName,
helper: 'clone'
});
}
// Tabs div is formatted as tabs by jquery
$("#tabs").tabs({
select: function (event, ui) {
selectTab(ui.index + 1);
}
});
//Sets canvas as droppable
$(".tab").droppable({
accept: ".model",
drop: function (event, ui) {
var newBlock = ui.helper.clone();
$(newBlock).removeClass("model").addClass("block");
$(this).append($(newBlock));
$(newBlock).draggable({containment:$(this)});
return true;
}
});
});
and the html
<body>
<div id="container">
<div id="library">
<div class="model type1" type="1">Block1</div>
<div class="model type2" type="2">Block2</div>
</div>
<div id="tabs">
<ul>
<li>Tab1
</li>
<li>Tab2
</li>
<li>Tab3
</li>
</ul>
<div id="tab1" class="tab">Tab1</div>
<div id="tab2" class="tab">Tab2</div>
<div id="tab3" class="tab">Tab3</div>
</div>
</div>
</body>
and the CSS
#container {
width:100%;
height:300px;
}
#tabs {
height:300px;
width:70%;
float:right;
border:1px solid black;
}
.tab{
height:100%;
border:1px dotted blue;
}
#library {
border:1px solid black;
width:20%;
height:300px;
float:left;
}
.type1 {
width:50px;
height:50px;
border:1px solid green;
}
.type2 {
width:50px;
height:20px;
border:1px solid red;
}

How to make a dojo dijit tab blink or flash when an event occurs and it is not the active tab?

I have a dojo dijit tab container and I want the tabs to flash a few times when an event occurs and it is not the selected tab. For example, when I receive a chat message I want the "Chat tab" to flash a few times as a visual notification that a chat has been received. I'm having a hard time finding the right control (the tab) to modify. Here is the code:
The HTML:
<div data-dojo-type="dijit.layout.TabContainer" data-dojo-props="region:'center',splitter: true">
<div id="tabChat" title="Chat" data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="iconClass:'i-chat', design: 'sidebar'">
<div id="pnlChatLog" style="background-color:#FFF; padding:0px;" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'center', splitter:true">
<div id="divChatLog" style="width:100%; height:100%; overflow-y:scroll; overflow-x:hidden;">
</div>
</div>
<div id="pnlChatMessage" style="background-color:#FFF; padding:0px; overflow:hidden;" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'bottom', splitter:false">
<input id="txtChatMessage" style="width:100%; margin:0px; border:0px;" data-dojo-type="dijit.form.ValidationTextBox" data-dojo-props="intermediateChanges:false,placeholder:'Enter Message'" />
</div>
</div>
<div id="tabQuestions" title="Questions" data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="iconClass:'i-help', design: 'sidebar'">
<div data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="region:'center', splitter:false, gutters:false">
<div style="background-color:#FFF; padding:0px; border-top:0px;" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'center', splitter:true">
<div id="gridQuestions"></div>
</div>
</div>
</div>
The javaScript:
//Chat message Event
chat.on("message", function(e) {
//Message code is here...
//TODO: Make the tab flash if it is not the current tab
});
Note: The messaging code (not shown here) works. I just need to know what javaScript will replace the TODO section so the tab blinks/flashes for a few seconds at this point.
To get to the tab button you have to use the tab element's "controlButton" then modify the domNode. Here is an example:
//A method for the blinking using setInterval. The top line shows
//how to get the actual tab that you want to modify. Then add and remove the
//Hover classes for a nice flashing/blinking effect.
function blinkTab(tabId, count, interval) {
var tabbutton = dijit.byId(tabId).controlButton.domNode;
var interval = setInterval(function(){
if(count % 2 == 0) {
tabbutton .className += " dijitTabHover";
tabbutton .className += " dijitHover";
}
else {
//Not sure this is the best way to remove a class but I couldn't find
//a "clean" way to do it with dojo.
tabbutton .className = tabbutton .className.replace( /(?:^|\s)dijitTabHover(?!\S)/ , '');
tabbutton .className = tabbutton .className.replace( /(?:^|\s)dijitHover(?!\S)/ , '');
}
if(count == 0) {
tabbutton .className = tabbutton .className.replace( /(?:^|\s)dijitTabHover(?!\S)/ , '');
tabbutton .className = tabbutton .className.replace( /(?:^|\s)dijitHover(?!\S)/ , '');
clearInterval(interval);
}
count--;
}, interval);
}
//Now make the calls where desired
//Chat message Event
chat.on("message", function(e) {
//Message code is here...
blinkTab("tabChat", 10, 500);
});
//Question Event
questions.on("message", function(e) {
//Question code is here...
blinkTab("tabQuestions", 10, 500);
});
You might just want to change the "class" of the tab title span (or is it a div? don't remember). The easy way is to use firebug, check the element used for the tab title, identify it in the node hierarchy, then put an id on your tab like tabMsg or something, then you justy ned to dijit.byId to get the right tab, and then go to the title node and addClass/removeClass every seconds or 0.5s to make it "blink".
You might want to add a "blinking" property to your tab, so that while this is true you switch classes, and when you click on the tab you set it to false and disable the blinking.

Data binding does not work after simple modal popup

Please consider the following code (also in this fiddle):
var viewModel = {
count:ko.observable(0),
add:function (){
this.count(this.count()+1);
},
popup:function (){
$.modal($("#divPopup"));
}
}
ko.applyBindings(viewModel);
And this corresponding View:
<button id="btnAdd" data-bind="click:add">Add</button>
<button id="btnPopup" data-bind="click:popup">Popup</button>
<div id="divPopup">
<span data-bind="text:count"></span>
</div>
Now:
click Add button
click Popup button
click top right corner of modal window (sorry I can't have "x" image)
Add button don't work
I can't use:
$.modal($("#divPopup").html());
Because in my app html does not render when $.modal().
Or to put it as another question: how I can know when html render was completed when my viewModel changed?
Try passing persist: true in for the options to modal() like:
$("#divPopup").modal({ persist: true });
http://jsfiddle.net/rniemeyer/BxVF9/