How to Enable/Disable JEditable - javascript

SOLUTION
Thanks to Arman's P. proof of concept, finally got it to work with my site.
CODE
//Edit Note
$(function(){
function makeEditable() {
$(".edit").editable('ajax/save.php?editnotetext', {
type : 'mce',
submit : '<button class="save_button">Save</button>',
event: 'dblclick',
indicator : 'Saving...',
tooltip : 'Doubleclick to edit...',
onblur: 'ignore',
width : '700px',
height : '100px',
callback : function(value, settings){
console.log('unlocked');
$.post('ajax/save.php?unlocknotetext', {"id" : $(this).attr('id')});
$(this).effect("highlight", {}, 3000);
$(this).parents('.panel').effect("highlight", {}, 3000);
},
'onreset' : function(){
console.log('unlocked');
$.post('ajax/save.php?unlocknotetext', {"id" : $(this).attr('id')});
}
});
};
makeEditable();
$('.edit').live('click', function() {
console.log('locked');
$.post('ajax/save.php?locknotetext', {"id" : $(this).attr('id')});
});
$(".edit").click(function() {
$.post('ajax/save.php?checklock', {"id" : $(this).attr('id')},
function(data) {
// USE SAME OPTION IN BOTH PLACES
// IF YOU USE 1ST OPTION, YOU CAN TAKE JEDITABLE OUT OF makeEditable() and do everything without that function
if (data[0].is_locked == 1) {
// Option 1
//$(this).editable('disable');
//alert(data[0].username.toUpperCase() + " is editing this note!");
// Option 2
$(".edit").unbind('dblclick');
} else {
// Option 1
//$(this).editable('enable')
// Option 2
makeEditable();
}
},
"json"
);
});
});
UPDATE
So now, as per what I think Arman suggested, I made JEdtiable only work if a custom event is triggered. I'm trying to trigger the event only if I find no lock. But now JEditable doesn't get called. There's something wrong with how I'm trying ot trigger it. [Note that JEditable does get called if if I test it with a button like <button onclick="$('.edit').trigger('custom_event');">Click to Edit</button>]
CODE
So here's my new code
$(function(){
$(".edit").bind("dblclick",function() {
$.ajax({ // first check to see if locked
type: "POST",
url: "ajax/save.php?locknotetext",
data: {"id" : $(this).attr('id')},
dataType: "json",
success: function(data){
if (data[0].is_locked == 1){ // if locked then alert someone is editing ntoe
alert(data[0].username.toUpperCase() + " is editing this note!");
}
else{
$(this).trigger('custom_event');
$(this).unbind('custom_event.editable');
}
}
}); //close $.ajax(
});
});
Here's the JEditable pieces
$(function(){
$(".edit").editable('ajax/save.php?editnotetext', {
type : 'mce',
submit : '<button class="save_button">Save</button>',
event: 'custom_event',
indicator : 'Saving...',
tooltip : 'Doubleclick to edit...',
onblur: 'ignore',
width : '700px',
height : '100px',
callback : function(value, settings){
console.log(this, value, settings);
$(this).effect("highlight", {}, 3000);
$(this).parents('.panel').effect("highlight", {}, 3000);
$.ajax({
type: "POST",
url: "ajax/save.php?unlocknotetext",
data: {"id" : $(this).attr('id')}
}); //close $.ajax(
//$(this).addClass("edit");
}
// },
// function(value, settings) {
// $(this).unbind('settings.event');
});
});
BACKGROUND
I'm creating a website where people can share and edit notes. What I would like to do is if someone is editing a note, the note gets locked so that another user can't edit the note.
I'm using JEditable. Users can double click so edit a note.
If a user doubleclicks, I do an AJAX call to see if there's a lock in the note. If there isn't then I lock the note and the user can edit. If there is a lock, I alert the user the "userX is currently editing the note".
PROBLEM
My problem is that I only want to call JEditable when there is no lock. Otherwise, I just want to alert the user that someone else is editing it. The problem I'm getting with my code below is that JEditable is called no matter what. I've also tried using another class name for the editable and adding the class only when there is no lock in that callback of the first AJAX call, but that doesn't work either.
Any suggestions would be much appreciated!

JEditable supports this natively at this point:
$.fn.editable = function(target, options) {
if ('disable' == target) {
$(this).data('disabled.editable', true);
return;
}
if ('enable' == target) {
$(this).data('disabled.editable', false);
return;
}
This seems to work:
$(...).editable("disable")
$(...).editable("enable")

Try to unbind previous event (probably dblclick) that jeditable added to the element, add your own with alert and then when the element is unlocked call jeditable again.
Another solution would be to add transparent div or something with absolute positioning on your elements when they're locked and bind dblclik event with your own message to that transpatrent elements. .remove() them when your original elements've been unlocked.
The problem I see in your code is: when first user dblclicks element you apply jeditable and lock it and when second user dbclicks it you want to alert, but the problem is that jeditable has already applied dblclick event to element. Instead of this change your check for lock to mouseenter event and if your condition for lock succeeds unbind dblclick event (see unbind), if nobody is editing simply apply jeditable, the function body of editText(). There is no need to have seperate function for it. And why are using .live(). Do you have dinamically added elements?
You can find also some answers to your question here JQuery JEditable - How to Disable on click editing
The solution I came up for you looks like this.
HTML file:
<html>
<head>
<title>Lock wirh jEditable</title>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript" src="http://www.appelsiini.net/download/jquery.jeditable.mini.js"></script>
<script type="text/javascript">
$(function() {
function makeEditable() {
$('#editable').editable("save.php", {
tooltip : 'Doubleclick to edit...',
event : 'dblclick',
onblur : 'ignore',
callback : function(value, settings) {
console.log('unlocked');
},
'onreset' : function() {
console.log('unlocked');
$.post('unlock.php');
}
});
};
makeEditable();
$('#editable input').live('focus', function() {
console.log('locked');
$.post('lock.php');
});
$('#editable').hover(function() {
$.post('checklock.php', function(response) {
// USE SAME OPTION IN BOTH PLACES
// IF YOU USE 1ST OPTION, YOU CAN TAKE JEDITABLE OUT OF makeEditable() and do everything without that function
if (response) {
// Option 1
$('#editable').editable('disable');
// Option 2
//$('#editable').unbind('dblclick');
} else {
// Option 1
$('#editable').editable('enable')
// Option 2
//makeEditable();
}
});
});
});
</script>
</head>
<body>
<div id="editable">Here is the text that can be edited.</div>
</body>
</html>
LOCK.PHP
<?php
$fileName = 'lock.txt';
file_put_contents($fileName, '1');
?>
UNLOCK.PHP
<?php
$fileName = 'lock.txt';
file_put_contents($fileName, '0');
?>
CHECKLOCK.PHP
<?php
$fileName = 'lock.txt';
$locked = file_get_contents($fileName);
if ($locked == '0') {
echo false;
} else {
echo true;
}
?>
SAVE.PHP
<?php
$fileName = 'lock.txt';
file_put_contents($fileName, '0');
echo $_POST['value'];
?>
LOCK.TXT (Initial)
0
You can grab the idea from the example. Of course you can do it more elegantly. This is rough example. You can try on your own simply by creating those files in same directory on your web server and copy-pasting contents. Sorry for not putting demo online, jsFiddle doesn't support ajax with change state (at least I think so). If you need any further assistance, let me know. Good Luck.

This does require a bit of messing with classes, and placement, but it works well.
Here is the jquery UI based code to create a button that controls its own state and the state of the editable text
function makeEditable(params){ //params excluded for now
$("div#body").append("<button id='editTable'>Edit Table</button>"); //inserts a button into a div
$("div#body button#editTable").button({icons: {primary:'ui-icon-pencil'}}); //creates button
$("div#body button#editTable").unbind(); //removes all listeners
$("div#body button#editTable").hover( //sets hover behaviour
function(event){ //over
$(this).addClass("ui-state-hover");
},
function(event){ //over
$(this).removeClass("ui-state-hover");
}
);
//uses a class called editText which is assigned to the td elements of the blocks you want to make editable
$("div#body table .editText").editable("http://www.blah.com/Controller/CEditTable.php", {
indicator : 'Saving...',
tooltip : 'Click to edit...'
}); //basic editable initialization
$("div#body table .editText").editable("disable"); //disables by default
//adds a toggle to the button which enables/disables the editable functionality
$("div#body button#editTable").toggle(
function(event){
$("button#editTable").removeClass("ui-state-default");
$("button#editTable").addClass("ui-state-active");
$("div#body table .editText").editable("enable");
},
function(event){
$("button#editTable").removeClass("ui-state-active");
$("button#editTable").addClass("ui-state-default");
$("div#body table .editText").editable("disable");
}
);
$("div#body button#editTable").appendTo("div#body div#tableControls"); //move button to wherever to want it.
}

Related

JSTree Select Open Node

I have a problem with the JSTree.
I'm filling the selected item with data from DB.
But I want the item I selected to open automatically after it is filled. I could not do the automatic opening part.
I added one button to the page (btn_test).
I wrote the following in the click event of this button.
$("#TreeElement").jstree("toggle_node","#34B526D0-1E2C-4170-829E-1995782DB831");
When I click on the btn_test button, the node whose ID is written opens and closes. But I could not set this to open automatically when selecting and filling the corresponding node.
$("#btn_test").click(function () {
$("#TreeElement").jstree("toggle_node","#34B526D0-1E2C-4170-829E-1995782DB831");
});
JS side is as follows;
var TreeElement = $("#TreeElement");
TreeElement.jstree({
"core" : {
"check_callback" : true
},
state : { "opened" : true }
});
TreeElement.bind("select_node.jstree", function (e, data) {
GetSelectedElementChildrenNodes(data.node.id);
});
function GetSelectedElementChildrenNodes(SelectedNodeId) {
$.getJSON('http://serveripadress/api/browser.php?getchildren='+SelectedNodeId,function (data) {
$.each(data,function (index,element) {
TreeElement.jstree().create_node(SelectedNodeId
, { "id" : element.nodeid, "text" : element.nodename}, "last");
TreeElement.jstree(true).set_icon(element.nodeid,element.icon);
});
});
}
I get a different result when I change the code as follows.
I click on Node1, it is filled with relevant data, but it does not open, then I click on Node2, but node1 is opening :)
TreeElement.bind("select_node.jstree", function (e, data) {
GetSelectedElementChildrenNodes(data.node.id);
$("#"+data.node.id).jstree("open_all");
});
I've been changing the code for a while, but I just couldn't get it to work. If someone can help me with this, I really thank him.
Thank you so much!
Problem solved.
In the function where I pulled the data with Json, I added the following code to the end of getJson.
TreeElement.jstree("toggle_node",NodeId);
The new state of the function is as follows;
function GetSelectedElementChildrenNodes(SelectedNodeId) {
$.getJSON('http://serveripadress/api/browser.php?getchildren='+SelectedNodeId,function (data) {
$.each(data,function (index,element) {
TreeElement.jstree().create_node(SelectedNodeId
, { "id" : element.nodeid, "text" : element.nodename}, "last");
TreeElement.jstree(true).set_icon(element.nodeid,element.icon);
});
TreeElement.jstree("toggle_node",NodeId);
});
}

javascript/jquery doesn't work in ajax

I have php page "Home.php", that present user posts(using ajax).
This is how I get the posts:
<script type="text/javascript">
function loadmore()
{
var val = document.getElementById("result_no").value;
var userval = document.getElementById("user_id").value;
$.ajax({
type: 'post',
url: 'fetch.php',
data: {
getresult:val,
getuserid:userval
},
success: function (response) {
var content = document.getElementById("result_para");
content.innerHTML = content.innerHTML+response;
// We increase the value by 2 because we limit the results by 2
document.getElementById("result_no").value = Number(val)+10;
}
});
}
</script>
<div id="content">
<div id="result_para">
</div>
</div>
In every post, there is a like button(which also uses ajax). This is how I save the likes:
<script type="text/javascript">
function likethis(likepostid)
{
$.ajax({
type: 'post',
url: 'fetchlikes.php',
data: {
getpostid:likepostid
},
success: function (response) {
}
});
}
</script>
Before I used ajax to present posts, all worked well. But now when I press the like button, it DOES save the like, BUT the javascript/jquery doesn't work. I tried to make alert when I pressed the LIKE button, but it didn't work.
This is the index.js code(the javascript). It add +1 likes, when the user press the button:
$('.btn-counter_likecount').on('click', function(event, count) {
event.preventDefault();
//alert("hello");
var $this = $(this),
count = $this.attr('data-count'),
active = $this.hasClass('active'),
multiple = $this.hasClass('multiple-count_likecount');
$.fn.noop = $.noop;
$this.attr('data-count', ! active || multiple ? ++count : --count )[multiple ? 'noop' : 'toggleClass']('active');
});
EDIT fetchlikes.php:
<?php
mysql_connect('localhost','root','');
mysql_select_db('blabla');
$postid=$_POST['getpostid'];
mysql_query("UPDATE user_post SET likes_count=likes_count+1 WHERE post_id='$postid'");
?>
Because your posts are being loaded dynamically, the javascript where you bind the event is running before the posts are actually loaded, thus the buttons don't exist when you try to bind the event. You can use delegated events in jQuery to handle this.
Your previous code
$('.btn-counter_likecount').on('click', function(event, count) {
....
});
New Code
$('#result-para').on('click','.btn-counter_likecount',function(event, count) {
....
}
This way the event will actually be bound to a parent element that already exists when jQuery's ready() function runs. This way, the event handler checks for matching elements when the event is fired rather than when the event is bound.
For further reading, look into jQuery's delegated events

Limit ajaxStart function to only 1 of 2 ajax functions

I have a loading.gif that launches each time the user makes an AJAX powered search. However, I've got some search fields that automatically show suggestions while the user types, also powered by AJAX.
Now my loading.gif appears on the user search as well as the search suggestions while typing. How do I limit my function that shows the loading.gif to only show when it's a user AJAX search and not a search-suggestion-while-typing AJAX search?
This is my function:
$(document).ajaxStart(function () {
$(".se-pre-con").fadeIn("fast");
}).ajaxStop(function () {
$(".se-pre-con").fadeOut("fast");
});
how about bind it with condition like if user is still on the search input then dont show the loading.gif else if the user is out of the search input or first contact on the search input then show the loading.gif (refer below)
first the global variable
var input_focus = false;
and then when the specified input is on focus
$("#specified_input").focus(function(){
//set the variable named 'input_focus' to true to reject the showing of the loader (loading.gif) or hide it.
input_focus = true;
}).blur(function(){
//when the specified input lose it focus then set the variable 'input_focus' to false so that the loader (loading.gif) is allowed to show
input_focus = false;
});
$.ajax({
url : 'my-url',
type : 'post',
data : {},
beforeSend : function(){
//check if input is on focus
if(input_focus !== true){
//show the loading.gif, assume that #loader
$("#loader").show();
}else{
//hide the loading.gif, assume that #loader
$("#loader").hide();
}
},
complete : function(){
//when the ajax request is complete
},
success : function(response){
//the response function
}
});
I'd tackle it by either of the following:
1) Add a global variable such as showLoadingAnimation and set it to true or false depending on the need. Within your ajaxStart and ajaxStop do the following:
$(document).ajaxStart(function () {
if (showLoadingAnimation) $(".se-pre-con").fadeIn("fast");
}).ajaxStop(function () {
if (showLoadingAnimation) $(".se-pre-con").fadeOut("fast");
});
2) Instead of changing the jQuery global settings, Wrap the jQuery method with your own method:
//only listen to ajaxStop event so that we can hide the animation
$(document).ajaxStop(function () {
$(".se-pre-con").fadeOut("fast");
});
function myAjax(params, showAnimation) {
if (showAnimation) $(".se-pre-con").fadeIn("fast");
$.ajax(params);
}
//in your code you instead of calling $.ajax({...}) simply use `myAjax({...})`
Hope this helps.

Pass Id to a Onclick Function JQGrid

I have a JQGrid.I need to take some Id to the OnClick function.In my scenario i wanted to get BasicId to the OnClick function.
MyCode
function grid() {
//JqGrid
$('#griddata').html('<table class="table" id="jqgrid"></table>')
$('#jqgrid').jqGrid({
url: '/Admin/GetBasicData/',
datatype: 'json',
mtype: 'GET',
//columns names
colNames: ['BasicId','Images'],
//columns model
colModel: [
{ name: 'BasicId', index: 'BasicId', resizable: false },
{
name: 'Images',
width: 120,
formatter: function () {
return "<button class='btn btn-warning btn-xs' onclick='OpenDialog()' style='margin-left:30%'>View</button>";
}
},
//Some Code here
Open Dialog Function
function OpenDialog(BasicId)
{
//Some code here
}
You can use onclick='OpenDialog.call(this, event)' instead of onclick='OpenDialog()'. You will have this inside of OpenDialog initialized to the clicked <button> and the event.target. Thus your code could be like the following
function OpenDialog (e) {
var rowid = $(this).closest("tr.jqgrow").attr("id"),
$grid = $(this).closest(".ui-jqgrid-btable"),
basicId = $grid.jqGrid("getCell", rowid, "BasicId");
// ...
e.stopPropagation();
}
One more option is even better: you don't need to specify any onclick. Instead of that you can use beforeSelectRow callback of jqGrid:
beforeSelectRow (rowid, e) {
var $td = $(e.target).closest("td"),
iCol = $.jgrid.getCellIndex($td[0]),
colModel = $(this).jqGrid("getGridParam", "colModel"),
basicId = $(this).jqGrid("getCell", rowid, "BasicId");
if (colModel[iCol].name === "Images") { // click in the column "Images"
// one can make additional test for
// if (e.target.nodeName.toUpperCase() === "button")
// to be sure that it was click to the button
// and not the click on another part of the column
OpenDialog(rowid);
return false; // don't select the row - optional
}
}
The main advantages of the last approach: one don't need to make any additional binding (every binding get memory resources and it take time). There are already exist on click handler in the grid and one can use it. It's enough to have one click handler because of event bubbling. The e.target provide us still full information about the clicked element.
Writing js event in your buttons html is not a good idea, its against 'un-obtrusive javasript' principle. You can instead add a click event on the entire grid in the render function and in the callback, filter out based on whether the button was clicked.
//not sure of the syntax of jqgrid, but roughly:
render: function(){
$('#jqgrid').unbind('click').on('click', function(){
if($(e.target).hasClass('btn-warning')){
var tr = $(e.target).parent('tr');
//retrieve the basicId from 'tr'
OpenDialog(/*pass the basicId*/)
}
})
}

optimizing colorbox and adding extra jquery

I have two problems
I am trying to open a jQuery colorbox and it is very slow. The reason is I am trying to get html content from a different page (I cannot use iframe because I just need a part of this page). The following code works but it takes time after the button is clicked:
$(document).ready(function() {
$(".cart-link a").click(function(event) {
$(this).colorbox.close();
});
$(".rest-menuitem a").click(function(event) {
event.preventDefault();
var result = null;
var sURL = $(this).attr("href");
$.colorbox({
html: function() {
$.ajax({
url: sURL,
type: 'get',
dataType: 'html',
async: false,
success: function(data) {
result = data;
}
});
return $(result).find('.product');
},
width: '650px',
height: '10px',
onComplete: function() {
$(this).colorbox.resize();
}
});
});
});
I want to know if there is a alternative way to do it. I dont mind if the colorbox popup and then takes time to load the content. The above version can be fount at this url (http://delivery3.water-7.com/index.php/restaurants/manufacturers/3/Barcelona-Restaurant-&-Winebar/products).
I am also trying to close the colorbox when a user clicks on add to cart. But some reason it is not triggered. $(".cart-link a").click is not triggered when I click on add to cart. Is there a special way to add jquery to colorbox content?
Try this instead:
$(".rest-menuitem a").colorbox({
href: function(){
return $(this).attr('href') + ' .products';
},
width: '650px',
height: '10px',
onComplete: function() {
$(this).colorbox.resize();
}
});
ColorBox uses jQuery's load() method for it's ajax handling, so you just need to add the desired selector to the link's href.
For your question 2 can you try this ?
$(document).ready(function() {
$(".cart-link a").live('click',function(event) {
$(this).colorbox.close();
});
});
For your question 1..it will be slow since you are fetching it from different page.Use a different logic for that
For your question no 1
$('selector').colorbox({onLoad: function() { /*Intially load a empty color box with only <div id="contenttoload"></div> (No other html content */
$.ajax({
url :'Your url',
data : {}, //data to send if any
type : "POST" //or get
success:function(data){ /*data means the stuff you want to show in color box which you must return from the other page*/
$('#contenttoload').html(data); //data should be well formatted i mean add your css,classes etc from the server itself */
}
});
}});

Categories

Resources