I'm using this plugin grid system with drag and drop functionality:
https://github.com/McPants/jquery.shapeshift.
You can call the shapeshift function and pass it the parameters to enable and disable the drag and drop functionality.
$(".container").shapeshift({
enableDrag: true,
});
I want to be able to turn on and off this feature. I used this code:
var dragState = 0;
$(".switch").on("click", function() {
if(dragState == 0) {
options = {
enableDrag: true,
}
dragState = 1;
} else {
options = {
enableDrag: false,
}
dragState = 0;
}
$(".container").shapeshift(options);
});
When I run this code I can turn on drag and drop but not back off again.
Does anyone have any suggestions or experience with this plugin?
Use http://mcpants.github.io/jquery.shapeshift/ as a reference.
Basicaly all you need to do is:
$(function(){
var sso = {
minColumns: 3,
enableDrag: false
};
var ss = $(".container").shapeshift(sso);
$('button').click(function () {
sso.enableDrag = true;
ss.trigger('ss-destroy');
ss.shapeshift(sso);
});
});
I simplified the example to show what needs to be done in this fiddle:
http://jsfiddle.net/carisch19/hDm4e/2/
Added enable and disable buttons:
http://jsfiddle.net/carisch19/hDm4e/4/
Sorry for answering on such an old question but i was just going through shapeshift.js and understand that for disabling drag and drop we can destroy it but not in such a long way and there is no need to take it to variable.
Hope you will interested in this short way and update your codes.
Below is the code
$('div').trigger("ss-destroy");
Above code is sufficient for destroying and also a very clean and convenient way according to me.
Try once!
I am new to javascript, but I've been hired to give maintenance to an application which is developed in Sencha ExtJS 4. One of the modules I've been asked to modify, is of a component in which I show a tooltip whenever I hover over it. This component can be present in more than one view, it is something like "Customer Details" that is present in many screens of the application. If I hover over this data, I need to show a tooltip, this tooltip shows information retrieved by server (REST). I implemented some logic, but this logic involves the use of many listeners in each of the components that will show the information. For instance, I added a listener in all of the views that requires showing the tooltip:
this.listeners = {
boxready: {
fn: this.onAfterRender,
scope: this
}
And I had to implement this method for every view as well, which is a mess and, for sure, a very bad practice:
/**
* This method is executed after panels are rendered in order to set ToolTip listeners on
* users and workgroups.
*
* #param {Object} scope
*/
onAfterRender: function(scope) {
Ext.defer(function() {
var usElements = Ext.get(Ext.query('.usertooltip', scope.el.dom));
usElements.on({
click: function (e) {
var item = Ext.get(e.target);
if (Ext.isEmpty(item.dom.innerHTML.trim())) {
item.removeCls('usertooltip');
return;
}
if (item.hasCls('usertooltip-clicked')) {
return;
}
item.addCls('usertooltip-clicked');
var user = item.getAttribute('data-info');
UserInfo.getUserInfo(user, false);
if (UserInfo.errorResponse) {
UserInfo.getWGroupInfo(user);
}
UserInfo.displayToolTip(this);
}
});
var wgElements = Ext.get(Ext.query('.wgtooltip', scope.el.dom));
wgElements.on({
click : function (e) {
var item = Ext.get(e.target);
if (Ext.isEmpty(item.dom.innerHTML.trim())) {
item.removeCls('wgtooltip');
return;
}
if (item.hasCls('wgtooltip-clicked')) {
return;
}
item.addCls('wgtooltip-clicked');
var wgroup = item.getattribute('data-info');
WGroupInfo.getWGroupInfo(wgroup, false);
if (UserInfo.errorResponse) {
WGroupInfo.getUserInfo(wgroup);
}
WGroupInfo.displayToolTip(this);
}
});
}, 1000, this);
},
What I do is simply detect if the item is selected based a css class, if so, I handle the events and proceed with logic. But I've been doing some research and I think this can be achieved using a "delegator" but I am not sure how to implement this for my scenario.
What I've been thinking of, so far is to create a "js" class which have a method like an "observer" and whenever listen to someone asking for this tooltip functionality, delegate it to the executing object. But since I am new to javascript and this Sencha ExtJS, my tries have been frustrated. If someone can help me I would really appreciate it.
Thanks in advance.
Best regards.
The best way would be to declare a plugin:
Ext.define('TipPlugin', {
alias: 'plugin.tip',
init: function(c) {
c.on('boxready', this.onBoxReady, this);
},
onBoxReady: function(c) {
var els = this.el.select('.usertooltip');
// Do stuff!
}
});
var c = new Ext.Component({
plugins: ['tip']
});
I am wondering if there is a better way of doing this.
I have some HTML that needs some events attaching to it.
Question 1:
There is no data, models or collections behind it so I assume no need for a render method?
Question 2:
I am assuming it should be a view in backbone because it is a single piece of UI that needs code attaching to it?
Basically what I have is a panel with show and hide functionality, which shows some check boxes for saving settings. When the panel closes it will save the states of the check boxes.
Here is the HTML:
<div id="panel-holder">
<div id="settings">
<ul class="settingsChecks">
<li>
<label>Display Desktop Notification Popup </label>
<input type="checkbox" id="formDisplayPopup" checked="checked"/>
</li>
<li>
<label>Play Alert Sound </label>
<input type="checkbox" id="formPlaySounds" checked="checked"/>
</li>
</ul>
</div>
</div>
So the above code is attached to a view using #panel-holder.
Here is the Backbone code:
var SettingsView = Backbone.View.extend({
el: '#panel-holder',
events: {
'click #click': 'toggleContent'
},
initialize: function() {
this.toggleContent();
},
showmeState: true,
toggleContent: function(){
if (this.showmeState === false) {
this.openPanel();
} else {
this.closePanel();
}
},
closePanel: function() {
this.$el.find('#settings').slideUp('fast');//Close Panel
this.$el.find('#click').text("Open Settings");//Change Text
this.showmeState = false;
this.saveSettings();
},
openPanel: function() {
this.$el.find('#settings').slideDown('fast');//Open Panel
this.$el.find('#click').text("Close Settings");//Change Text
this.showmeState = true;
},
saveSettings: function() {
//when the panel closes get the states of the checkboxes and save them
}
});
Question 3:
Should I be using jQuery .find('') in the open and close panel areas? Is there a better way of attaching functionality to these elements.
Question 4:
Is this code and my understanding of Backbone Views ok? Am I way off course?
Answers
I would include a render method that returns itself so that you can append the view to the #panel-holder element
Yes, this is fine
Always use $.find("") when working within a view's elements. Just index the elements so you can access them as this.$settings, etc
No looks good generally
Code
Here is my recommended code in Coffeescript (sorry I'm lazy):
Also uses Handlebars library to compile templates
tmpl = ....all your html...
SettingsView = Backbone.View.extend
attributes:
id: 'settings'
template: Handlebars.compile tmpl
events:
'click #click': 'toggleContent'
initialize:
#toggleContent()
showMeState: true
toggleContent: ->
#showMeState is false then #openPanel()
else #closePanel()
closePanel:->
#$settings.slideUp('fast')
#$click.text('Open Settings')
#showMeState = false
#saveSettings()
openPanel: ->
#$settings.slideDown('fast')
#$click.text('Close Settings')
#showMeState = true
saveSettings: ->
render: ->
#$el.append #template
#Store settings and click
#$settings = #$el.find('#settings')
#$click = #$el.find('#click')
#
settings = new SettingsView
$('#panel-holder').append settings.render().el
Question 1: There is no data, models or collections behind it so I
assume no need for a render method?
For now it is not required. But if you want to add extra functionality or if the UI changes in any way later then you might be requiring one.
Question 2: I am assuming it should be a view in backbone because it
is a single piece of UI that needs code attaching to it?
Yes. it is a view.
Question 3: Should I be using jQuery .find('') in the open and close
panel areas? Is there a better way of attaching functionality to these
elements.
this.$el.find('#settings') is perfectly fine.
You can also use either $('#settings', this.$el) or this.$('#settings')
But remember that you are using ID selectors . And ID will be unique on the page. So you do not need to find it in the context of the view
$('#setting') should be good enough
Question 4: Is this code and my understanding of Backbone Views ok? Am
I way off course?
You are doing perfectly well. But the thing is in backbone you can get a task done in many ways which works. And you need to choose the best approach amongst them. You will get to know the more you work with it. So do not worry about it.
The same can be condensed into a single method that will take care of toggling
var SettingModel = Backbone.Model.extend({
defaults: {
showmeState : false
}
});
var settingModel = new SettingModel();
var SettingsView = Backbone.View.extend({
el: '#panel-holder',
events: {
'click #click': 'toggleState'
},
initialize: function () {
// Listen to the Model that triggers
this.listenTo(settingModel, 'change', this.toggleContent);
this.model.trigger('change');
},
toggleState: function() {
//When Clicked just negate the boolean so that it triggers the change event
this.model.set('showmeState', !this.model.get('showmeState'));
},
toggleContent: function() {
var check = !this.model.get('showmeState'),
txt = check === true ? "Close Settings" : "Open Settings";
$('#click').text(txt);
check === true ? $('#settings').slideUp('fast')
: $('#settings').slideDown('fast');
if(check)
saveSettings();
},
saveSettings: function () {
//when the panel closes get the states of the checkboxes and save them
}
});
If you think check for condition is an overkill, then a simple if should be sufficient.
In our application we use a general function to create jQuery dialogs which contain module-specific content. The custom dialog consists of 3 buttons (Cancel, Save, Apply). Apply does the same as Save but also closes the dialog.
Many modules are still using a custom post instead of an ajax-post. For this reason I'm looking to overwrite/redefine the buttons which are on a specific dialog.
So far I've got the buttons, but I'm unable to do something with them. Is it possible to get the buttons from a dialog (yes, I know) but apply a different function to them?
My code so far:
function OverrideDialogButtonCallbacks(sDialogInstance) {
oButtons = $( '#dialog' ).dialog( 'option', 'buttons' );
console.log(oButtons); // logs the buttons correctly
if(sDialogInstance == 'TestInstance') {
oButtons.Save = function() {
alert('A new callback has been assigned.');
// code for ajax-post will come here.
}
}
}
$('#dialog').dialog({
'buttons' : {
'Save' : {
id:"btn-save", // provide the id, if you want to apply a callback based on id selector
click: function() {
//
},
},
}
});
Did you try this? to override button's callback based on the need.
No need to re-assign at all. Try this.
function OverrideDialogButtonCallbacks(dialogSelector) {
var button = $(dialogSelector + " ~ .ui-dialog-buttonpane")
.find("button:contains('Save')");
button.unbind("click").on("click", function() {
alert("save overriden!");
});
}
Call it like OverrideDialogButtonCallbacks("#dialog");
Working fiddle: http://jsfiddle.net/codovations/yzfVT/
You can get the buttons using $(..).dialog('option', 'buttons'). This returns an array of objects that you can then rewire by searching through them and adjusting the click event:
// Rewire the callback for the first button
var buttons = $('#dialog').dialog('option', 'buttons');
buttons[0].click = function() { alert('Click rewired!'); };
See this fiddle for an example: http://jsfiddle.net/z4TTH/2/
If necessary, you can check the text of the button using button[i].text.
UPDATE:
The buttons option can be one of two forms, one is an array as described above, the other is an object where each property is the name of the button. To rewire the click event in this instance it's necessary to update the buttons option in the dialog:
// Rewire the callback for the OK button
var buttons = $('#dialog').dialog('option', 'buttons');
buttons.Ok = function() { alert('Click rewired!'); };
$('#dialog').dialog('option', 'buttons', buttons);
See this fiddle: http://jsfiddle.net/z4TTH/3/
Can you try binding your new function code with Click event of Save?
if(sDialogInstance == 'TestInstance') {
$('#'+savebtn_id).click(function() {
alert('A new callback has been assigned.');
// code for ajax-post will come here.
});
}
Looked around quite a bit, and can't seem to find a JQuery solution (maybe its just a limitation of JavaScript) for this:
<a href="somelink.php"
onclick="return confirm('Go to somelink.php?');">Click Here</a>
In the above example, when a user clicks on the link, it will only go to its href if the user clicks OK in the confirm box.
What I am trying to do is get a more modern look using a popup div. Perhaps something like this:
<a href="somelink.php"
onclick="return jq_confirm('Go to somelink.php?');">Click Here</a>
(Where jq_confirm is a custom JQuery confirm function that pops up a nice div with a YES/NO or OK/CANCEL button pair).
However, I cannot seem to find any such thing.
I have looked at some JQuery widget libraries etc which offer similar functionality, but none will wait for the response from the user (at least, not in the scenario described above), but instead they just proceed and take the user to the link (or run any JavaScript embedded in the href='' piece of the link). I suspect this is because while you can attach a callback function to many of these widgets to return a true/false value, the onclick event does not wait for a response (callbacks are asynchronous), thereby defeating the purpose of the confirm box.
What I need is the same kind of halt-all-javascript (modal) functionality that the default confirm() command provides. Is this possible in JQuery (or even in JavaScript)?
As I am not an expert in JavaScript nor in JQuery, I defer to you gurus out there. Any JQuery (or even pure JavaScript) solution is welcome (if possible).
Thanks -
I just had to solve the same problem. I wound up using the dialog widget from JQuery UI. I was able to implement this without using callbacks with the caveat that the dialog must be partially initialized in the click event handler for the link you want to use the confirmation functionality with (if you want to use this for more than one link). This is because the target URL for the link must be injected into the event handler for the confirmation button click.
Here's my solution, abstracted away to be suitable for an example. I use a CSS class to indicate which links should have the confirmation behavior.
<div id="dialog" title="Confirmation Required">
Are you sure about this?
</div>
<script type="text/javascript">
$(document).ready(function() {
$("#dialog").dialog({
autoOpen: false,
modal: true
});
$(".confirmLink").click(function(e) {
e.preventDefault();
var targetUrl = $(this).attr("href");
$("#dialog").dialog({
buttons : {
"Confirm" : function() {
window.location.href = targetUrl;
},
"Cancel" : function() {
$(this).dialog("close");
}
}
});
$("#dialog").dialog("open");
});
}); // end of $(document).ready
</script>
<a class="confirmLink" href="http://someLinkWhichRequiresConfirmation.com">Click here</a>
<a class="confirmLink" href="http://anotherSensitiveLink">Or, you could click here</a>
Check out http://www.84bytes.com/2008/06/02/jquery-modal-dialog-boxes/
They have a good variety of modal-boxes for JQuery.
I think you should see http://www.ericmmartin.com/simplemodal/
A modal dialog override of the JavaScript confirm function. Demonstrates the use of onShow as well as how to display a modal dialog confirmation instead of the default JavaScript confirm dialog.
Did you see the jQuery Modal Dialog on jQuery UI site?
Modal Confirmation Dialog demo
I blogged about the solution to this issue here: http://markmintoff.com/2011/03/asp-net-jquery-confirm-dialog/
Even though the article is geared towards ASP.Net it can be easily adapted to php. It relies on preventing the click with a return false and when the user clicks "OK" or "YES" or what-have-you; the link or button is simply clicked again.
var confirmed = false;
function confirmDialog(obj)
{
if(!confirmed)
{
$( "#dialog-confirm" ).dialog({
resizable: false,
height:140,
modal: true,
buttons: {
"Yes": function()
{
$( this ).dialog( "close" );
confirmed = true; obj.click();
},
"No": function()
{
$( this ).dialog( "close" );
}
}
});
}
return confirmed;
}
Give it a try and let me know what you think. I hope this solves your problem.
You should be able to override the standard window.confirm function be writing the following code.
window.confirm = modalConfirm
then you will need to make a function like this
function modalConfirm(message){
// put your code here and bind "return true/false" to the click event
// of the "Yes/No" buttons.
}
This should work, although I haven't tested it yet. I am going to do exactly this right now and will let you all know how it worked.
Edit:
I have tested my example above now and it was not possible, you will have to pass in a callback function to your overwritten confirm function like this:
function modalConfirm(message, callback){
...
$("button.yes").click(function(){
callback(result);
});
...
}
..making your call to the function look like this:
confirm("Are you sure?", function(result){
alert(result);
});
In other words, it is not possible to completely override the default window.confirm function without causing a nasty loop that causes the browser to hang. I think that you will have to modify your confirm calls like above.
Since this question seems to be missing the canonical answer: there is no way to programatically pause (and resume) javascript execution like alert or confirm do.
That being said, relying on this behaviour today is usually considered bad practice given the single threaded nature of javascript, and the reason why the aforementioned functions do pause execution is probably because they were designed when the web was still at a very early stage, and later left unchanged to ensure compatibility. Since the focus nowadays is in writing as much non-blocking js code as possible, it's unlikely the functionality to programmatically halt js will ever make it to any future specification of ECMAScript, so your best bet is to rework your site to make sure confirm and alert dialogs can co-exist with other javascript code running in the background.
My way around this problem was to add some arbitrary data to the object, and check for that data on click. If it existed, proceed with the function as normal, otherwise confirm with a yes/no (in my case using a jqtools overlay). If the user clicks yes - insert the data in the object, simulate another click and wipe the data. If they click no, just close the overlay.
Here is my example:
$('button').click(function(){
if ($(this).data('confirmed')) {
// Do stuff
} else {
confirm($(this));
}
});
And this is what I did to override the confirm function (using a jquery tools overlay):
window.confirm = function(obj){
$('#dialog').html('\
<div>\
<h2>Confirm</h2>\
<p>Are you sure?</p>\
<p>\
<button name="confirm" value="yes" class="facebox-btn close">Yes</button>\
<button name="confirm" value="no" class="facebox-btn close">No</button>\
</p>\
</div>').overlay().load();
$('button[name=confirm]').click(function(){
if ($(this).val() == 'yes') {
$('#dialog').overlay().close();
obj.data('confirmed', true).click().removeData('confirmed');
} else {
$('#dialog').overlay().close();
}
});
}
I have a solution that can be used to replace the default window.confirm function. It doesn't require you overriding window.confirm as that is not fully possible.
My solution allows you to have a general class like me, let's say 'confirm-action' that you place on any element that requires a confirmation before being processed. The script is very simple and utilizes jQuery, jQuery UI Dialog and no other plugins.
You can find the complete demo of the implementation on jsFiddle, http://jsfiddle.net/74NDD/39/.
Usage:
Add this javascript code in your html head or before any other click
binding you have in your javascript.
$("#dialog:ui-dialog").dialog("destroy");
$('.confirm-action').live('click', function(e) {
$self = $(this);
if (e && e.stopImmediatePropagation && $self.data('confirmed') !== true) {
e.stopImmediatePropagation();
$('#confirm-action-dialog').dialog({
height: 110,
modal: true,
resizable: false,
draggable: false,
buttons: {
'Yes': function() {
$(this).dialog('close');
$self.data('confirmed', true);
$self.click();
},
'No': function() {
$self.data('confirmed', false);
$(this).dialog('close');
}
}
});
} else if ($self.data('confirmed') === true) {
e = window.event;
e.cancelBubble = false;
$self.data('confirmed', false);
}
return false;
});
Place this html somewhere in the body (it is hidden by default).
<div style="display:none;" id="confirm-action-dialog" title="Confirm Action?">
<p>
<span class="ui-icon ui-icon-alert"></span>
Are you sure you want to continue?
</p>
</div>
Put the class 'confirm-action' on any element that requires confirmation.
confirm-action
This solution works perfect as it does not alter jQuery event bubbling, it merely pauses (stops) all other events until the user decides what they want to do.
I hope this is helpful for someone else as I was unable to find any other solution that doesn't require me installing another jQuery plugin or do some other hack.
Building on top of Banu's solution (thanks a ton!) to make it a one pop solution on top of each page. Paste this code inside:
$(document).ready
And add "confirmLinkFollow" class to all links you want confirmed:
$(".confirmLinkFollow").click(function(e) {
e.preventDefault();
var targetUrl = $(this).attr("href");
var $dialog_link_follow_confirm = $('<div></div>').
html("<p>Are you sure?</p>").
dialog({autoOpen: false,
title: 'Please Confirm',
buttons : {
"Confirm" : function() {
window.location.href = targetUrl;
},
"Cancel" : function() {
$(this).dialog("close");
}
},
modal: true,
minWidth: 250,
minHeight: 120
}
);
$dialog_link_follow_confirm.dialog("open");
});
Put the redirect inside the function like:
<script>
function confirmRedirect(url, desciption) {
if (confirmWindow(desciption)) {
window.location = url;
}
}
</script>
And call it like this:
Go!
Almost three years later, I am looking for something similar. Since I have not found an acceptable "quick" solution, I wrote something that comes very close to the criteria of the OP. I figure others may find it useful in the future.
JavaScript is event-driven and that means it does not support any sort of "wait" or "sleep" loop that we can use to pause a pure-javascript confirm function. The options involve burning processor cycles, using a browser plugin, or AJAX. In our increasingly mobile world, and with sometimes spotty internet connections, none of these are great solutions. This means that we have to return from our "confirm" function immediately.
However, since there is no "false" logic in the code snippet above (ie. nothing is done when the user clicks "Cancel"), we can trigger the "click" or "submit" event again when the user clicks "OK." Why not set a flag and react based on that flag within our "confirm" function?
For my solution, I opted to use FastConfirm rather than a "modal" dialog. You can easily modify the code to use anything you want but my example was designed to use this:
https://github.com/pjparra/Fast-Confirm
Due to the nature of what this does, I do not see a clean way to package it up. If you feel that this has too many rough edges, feel free to smooth them out or rewrite your code the way that everyone else has recommended:
/* This version of $.fn.hasEvent is slightly modified to provide support for
* the "onclick" or "onsubmit" tag attributes. I chose this because it was
* short, even if it is cryptic.
*
* Learn more about the code by Sven Eisenschmidt, which is licensed under
* the MIT and GPL at:
* http://github.com/fate/jquery-has-event
*/
(function($) {
$.fn.hasEvent = function(A, F, E) {
var L = 0;
var T = typeof A;
E = E ? E : this;
var V = (E.attr('on'+A) != undefined);
A = (T == 'string') ? $.trim(A) : A;
if (T == 'function')
F = A, A = null;
if (F == E)
delete(F);
var S = E.data('events');
for (e in S)
if (S.hasOwnProperty(e))
L++;
if (L < 1)
return V; // = false;
if (A && !F) {
return V = S.hasOwnProperty(A);
} else if(A && S.hasOwnProperty(A) && F) {
$.each(S[A], function(i, r) {
if(V == false && r.handler == F) V = true;
});
return V;
} else if(!A && F) {
$.each(S, function(i, s) {
if (V == false) {
$.each(s, function(k, r) {
if (V == false && r.handler == F)
V = true;
});
}
});
}
return V;
}
$.extend($, {hasEvent: $.fn.hasEvent});
}) (jQuery);
/* Nearly a drop-in replacement for JavaScript's confirm() dialog.
* Syntax:
* onclick="return jq_confirm(this, 'Are you sure that you want this?', 'right');"
*
* NOTE: Do not implement "false" logic when using this function. Find another way.
*/
var jq_confirm_bypass = false;
function jq_confirm(el, question, pos) {
var override = false;
var elem = $(el);
if ($.fn.fastConfirm == undefined) {
override = confirm(question);
} else if (!jq_confirm_bypass) {
if (pos == undefined) {
pos = 'right';
}
elem.fastConfirm({
position: pos,
questionText: question,
onProceed: function(trigger) {
var elem = $(trigger);
elem.fastConfirm('close');
if (elem.hasEvent('click')) {
jq_confirm_bypass = true;
elem.click();
jq_confirm_bypass = false;
}
if (elem.hasEvent('submit')) {
jq_confirm_bypass = true;
elem.submit();
jq_confirm_bypass = false;
}
// TODO: ???
},
onCancel: function(trigger) {
$(trigger).fastConfirm('close');
}
});
}
return override ? override : jq_confirm_bypass;
}
So... onclick="return confirm('Do you want to test this?');" would become onclick="return jq_confirm(this, 'Do you want to test this?');" The pos/"right" parameter is optional and is specifically for Fast-Confirm.
When you click, the jq_confirm() function will spawn the jQuery dialog and return "false." When the user clicks "OK" then jq_confirm() sets a flag, calls the original click (or submit) event, returns "true", then unsets the flag in case you want to remain on the same page.
The following link has a jQuery plugin for confirm boxes similar to constructing like confirm("something") in JavaScript
http://labs.abeautifulsite.net/archived/jquery-alerts/demo/