Button draggable and at the same time contenteditable - javascript

I have button that when clicked creates another button.
$('#button')
.click(function (eventClick, posX, posY) {
var htmlData = '<div id="btn' + $.count + '" class="draggable ui-widget-content ui-draggable" ' + 'data-page="' + $.page + '" ';
if (posX != null && posY != null) {
htmlData += 'style="left:' + Math.abs(posX - 439) + 'px; top:' + Math.abs(posY - 124) + 'px;""';
}
htmlData += '><button id="editable' + $.count + '" style="width:100%; height:100%">Button</button></div>';
$('.demo').append(htmlData);
$('.draggable').draggable({
containment: "#workspace",
scroll: false,
cancel: false,
})
.resizable({
containment: "#workspace"
})
.click(function () {
if ($(this).is('.ui-draggable-dragging')) {
return;
}
$(this).draggable("option", "disabled", true);
$(this).attr('contenteditable', 'true');
})
.blur(function () {
$(this).draggable('option', 'disabled', false);
$(this).attr('contenteditable', 'false');
});
$('a.delete').on('click', function (e) {
e.preventDefault();
btnID = $(this).closest('.draggable')[0].id;
//alert('Now deleting "'+objID+'"');
$('#' + btnID + '').remove();
});
$.count++;
});
This javascript fires when the create button is clicked, now this new button that is nested in a div has attributes draggable, resizable, deletable, and the content should supposedly be editable. Now my problem arise when I'm editing the text, the whole button tag is erased when I completely erase the content of it. I'm just left with I think a div tags. I can't seem to find what's the problem.

Looks to me like you are setting the contentEditable attribute on the div, because it has the 'draggable' class. This means everything inside the DIV is fair game to erase, including the button. If you want the text of the button to be editable, you should set the contentEditable attribute on the button instead.

Related

How do I capture the select event for a jquery ui autocomplete if it has images?

I have the this jsfiddle. I am trying to create an autocomplete with images and when the user selects an image then I want to capture that event but for some reason it doesn't work with images:
$("#input").autocomplete({
//source: tags,
source: images,
minLength: 1,
delay: 0,
open: function(){
$('.ui-menu .ui-menu-item a').css('word-wrap','break-word');
},
close: function () { $('.ui-autocomplete').show() },
focus: function(event, ui) {
return false;
},
select: function(event, ui){
alert("here there");
return false;
}
}).data("uiAutocomplete")._renderItem = function(ul, item){
//return $('<li style="margin-bottom:2px;"></li>').data("item.autocomplete", item).append('<a>hi there</a>').appendTo(ul);
return $('<li style="margin-bottom:2px;"></li>').data("item.autocomplete", item).append('<a><img src="' + item + '" style="width:115px;"/></a>').appendTo(ul);
};
If I instead return just plain text (just uncomment that part in the above code) I can capture the select event but it doesn't work with images? I have also set the z-index with no luck.
EDIT: I corrected the jsfiddle link
You need some text inside the list:
return $('<li style="margin-bottom:2px;">'+item.label+'</li>').data("item.autocomplete", item).append('<a><img src="' + item + '" style="width:115px;"/></a>').appendTo(ul);
Then, You can hide the text by setting:
li {
font-size: 0;
}
and adjust the .ui-state-active by setting:
a {
display: block;
}
I would advise the following:
.data("uiAutocomplete")._renderItem = function(ul, item) {
return $('<li style="margin-bottom:2px;"></li>').data("item.autocomplete", item).append('<div><img src="' + item.label + '" style="width:215px;"/></div>').appendTo(ul);
});
Since you're using <a>, it's click event is bubbling up first and this does not allow the click to target the <li> and thus not trigger select.
Example using DIV: https://jsfiddle.net/Twisty/napvj856/28/

Bug fix for a script that applies CSS to the title attribute

The script below applies a CSS class to the html title attribute. The original page in which the script appears is here: How to change the style of Title attribute inside the anchor tag?
Works great, but has a minor bug. If the title attribute is empty (<input type="text" title="">), it still shows an empty popup box on screen.
Can anyone please help with fixing this? Something like "if title attribute has no value, do not apply css, do not show popup box. Thank you!
Script below:
// Use a closure to keep vars out of global scope
(function () {
var ID = "tooltip", CLS_ON = "tooltip_ON", FOLLOW = true,
DATA = "_tooltip", OFFSET_X = 20, OFFSET_Y = 10,
showAt = function (e) {
var ntop = e.pageY + OFFSET_Y, nleft = e.pageX + OFFSET_X;
$("#" + ID).html($(e.target).data(DATA)).css({
position: "absolute", top: ntop, left: nleft
}).show();
};
$(document).on("mouseenter", "*[title]", function (e) {
$(this).data(DATA, $(this).attr("title"));
$(this).removeAttr("title").addClass(CLS_ON);
$("<div id='" + ID + "' />").appendTo("body");
showAt(e);
});
$(document).on("mouseleave", "." + CLS_ON, function (e) {
$(this).attr("title", $(this).data(DATA)).removeClass(CLS_ON);
$("#" + ID).remove();
});
if (FOLLOW) { $(document).on("mousemove", "." + CLS_ON, showAt); }
}());
This way:
$(document).on("mouseenter", "*[title]:not([title=''])" ...
One way is to return immediately if there is no title:
$(document).on("mouseenter", "*[title]", function (e) {
if (!$(this).attr('title')) return;
// rest of code
});
#c-smile's answer is cleaner though.

Jquery mobile swipe

I have tabs within a dynamic page. The tabs works great when pressed but I would like to add a swipe function to it so that users can also swipe to next tab.
Here is my attempt of trying to make the swipe function work
function goToMatchDetailPage(matchHome, matchAway){
first_part_id = matchHome.substring(0,2);
sec_part_id = matchAway.substring(0,2);
var id = first_part_id.concat(sec_part_id);
//create the html template
var matchPage = $("<div data-role='page' data-url=dummyUrl><div data-role='header'><h1>"
+ matchHome + "</h1></div><div data-role='content'><div data-role='tabs'>"
+ "<div data-role='navbar'>"
+ "<ul>"
+ "<li><a href='#fragment-1'>" + matchHome + "</a></li>"
+ "<li><a href='#fragment-2'>" + matchAway + "</a></li>"
+ "</ul>"
+ "</div>"
+ "<div id='fragment-1'>"
+ "<p>This is the content of the tab 'One', with the id fragment-1.</p>"
+ "</div>"
+ "<div id='fragment-2'>"
+ "<p>This is the content of the tab 'Two', with the id fragment-2.</p>"
+ "</div></div></div>");
//append the new page to the page contanier
matchPage.appendTo($.mobile.pageContainer);
//go to the newly created page
$.mobile.changePage(matchPage);
Here is the ppart that doesn't work
$(function(){
// Bind the swipeleftHandler callback function to the swipe event on div.box
$( "div" ).on( "swipeleft", swipeleftHandler );
// Callback function references the event target and adds the 'swipeleft' class to it
function swipeleftHandler( event ){
//go to the newly created page
$.mobile.changePage('#fragment-2');
}
});
}
!
Try using event delegation:
Because fragment-1 does not exist at the time you are creating the handler, you assign the handler to the document and delegate it to any child elements called fragment-1 that exist now or will exist in the future.
To make it more generic, you can assign classes to the div and delegate to the class instead of an id...
UPDATE
You can't use changepage to go between tabs, instead use the tabs widget active property(http://api.jqueryui.com/tabs/#option-active):
$(document).on("pagecreate", "#page1", function () {
$("#btngo").on("click", function(){
goToMatchDetailPage('Liverpool', 'Southhampton');
});
$(document).on("swipeleft", "#fragment-1", function(){
$(this).parents("div [data-role=tabs]").tabs( "option", "active", 1 );
} );
$(document).on("swiperight", "#fragment-2", function(){
$(this).parents("div [data-role=tabs]").tabs( "option", "active", 0 );
} );
});
Here is a DEMO
The swipe code is assigned to the document and then delegated to the dynamic div. When you swipe on a tab div, we find its parent that is the tab widget container and then set its active tab option to change tabs.
try this simple code
$(document).on("swipeleft", '#'+event.target.id, function () {
var nextpage = $(this).next('div[data-role="page"]');
if (nextpage.length > 0) {
alert(nextpage.attr('id'));
$.mobile.changePage(nextpage, "slide", false, true);
}
});
$(document).on("swiperight", '#'+event.target.id, function () {
var prevpage = $(this).prev('div[data-role="page"]');
if (prevpage.length > 0) {
$.mobile.changePage(prevpage, { transition: "slide", reverse: true }, true, true);
}
});
I'm easier than the others.. It's not the whole solution, but you can get my point.
Option 1
$(document).on("swipeleft", '#page1', function () {
$('#fragment-2').trigger('click');
});
Option 2
$(document).on("swipeleft", '#page1', function () {
$(this).find("div [data-role=tabs]").tabs( "option", "active", 1 );
});
Not sure about which one is better thought :)

Jquery events for closing and opening select drop down , and not on change

i want a neat solution to handle event for a drop down menu , so that when user opens the select menu , it alerts opened , and when he closes it , it alerts closed , neglecting wheather the selected value is changed or not.
<select id="dummy">
<option>dummy1</option>
<option>dummy2</option>
<option>dummy3</option>
</select>
what i want is something like
$("#dummy").on('open',function(){//do something})
$("#dummy").on('close',function(){//do something})
something like heapbox
http://www.bartos.me/heapbox/
and this solution is not acceptable : Run change event for select even when same option is reselected
the typical approach to extending the native functionality of a select box is to replace it with styleable markup and then tie the values of the new markup back into the origninal (now hidden) select element. (NOTE: I've not included any styles. This is a bare-bones example of using a select replacement).
var SelectBox = {
init: function () {
if ($('select').length > 0) {
this.generateStyledSelectbox('custom-select');
};
},
generateStyledSelectbox: function (cssClass) {
// Contained within .each to isolate all instances of <select>
$('select').each(function(index) {
var $source = $(this),
selected = $source.find("option[selected]"),
options = $source.find('option'),
selindex = index;
// Append styleable pseudo-select element to doc
$source.after('<div id="result-' + index + '" class="' + cssClass + '"></div>');
// Construct select list in pseudo select element
$('#result-' + index).append('<dl id="activeValue-' + index + '" class="dropdown"></dl>');
$('#activeValue-' + index).append('<dt>' + selected.text() + '<span class="value">' + selected.val() + '</span></dt>');
$('#activeValue-' + index).append('<dd><ul></ul></dd>');
// Assign select values to pseudo-select lis items
options.each(function () {
$('#activeValue-'+ index + ' dd ul').append('<li class="select-menu-item">' + $(this).text() + '<span class="value">' + $(this).val() + '</span></li>');
});
$('.dropdown').each(function(index) {
$(this).find('dd ul li a').on('click', function(event) {
event.preventDefault();
var text = $(this).not('.value').html(),
$base = $('.custom-selectbox').eq(index);
$('.dropdown').eq(index).find('dt a').html(text);
$('.dropdown').eq(index).find('dd ul').hide();
$base.val($(this).find('span.value').html());
});
});
// prevent link actions in dropdown
$('.dropdown dt a').on('click', function (event) {
event.preventDefault();
});
// open/close
$(".dropdown").eq(index).find('dt a').on('click', function () {
$(".dropdown").eq(index).find('dd ul').toggle();
});
$(".dropdown").eq(index).find('dd ul li a').on('click', function () {
var text = $(this).html(),
newval = $(this).find('.value').html();
$(".dropdown").eq(index).find('dt a span').html(text);
$('select').eq(index).val(newval);
$(".dropdown").eq(index).find('dd ul').hide();
});
// Hide dropdown on outside click
$(document).on('click', function (e) {
var $clicked = $(e.target);
if (!$clicked.parents().hasClass("dropdown")) {
$(".dropdown").eq(index).find('dd ul').hide();
}
// remove dropdown-open targetable class
if (!$clicked.parents().hasClass("dropdown-open")) {
$clicked.parents().removeClass('dropdown-open');
}
});
// Hide native select
$source.css('display', 'none');
// assign initial (default) value
var initialval = $source.find('option').eq(0).html();
$('#activeValue-'+index+' dt a').html(initialval);
}); // END .each
}
};
SelectBox.init();
Here's a fiddle http://jsfiddle.net/P6ZCn/ (again, without styles)

Hiding and showing an element via visibility:hidden/visible

I got 2 div-boxes which should show/hide when clicking other 2 div-boxes. And I want the div's keep their space so it wouldn't ruin the DOM, so I guess .toggle() is out of question.
I tried this with no luck:
$('#red, #pink').click(function() {
// Based on the id property of the clicked element
// this selects #reddef or #pinkdef element
if($('#' + this.id + 'def').is(":visible")) {
$('#' + this.id + 'def').css('visibility','hidden');}
else if($('#' + this.id + 'def').is(":hidden")) {
$('#' + this.id + 'def').css('visibility','visible')}
});
So if I click #red then #reddef disappears while keeping the space. But when I click again nothing happens. I guess there's just a little thing I'm misssing atm, but can't figure out what.
According to the docs for the :hidden selector:
Elements with visibility: hidden or opacity: 0 are considered to be visible, since they still consume space in the layout.
I would recommend instead to add/remove a class as this is easier to test like so:
if($('#' + this.id + 'def').hasClass('visHidden')) {
$('#' + this.id + 'def').removeClass('visHidden')
}
else {
$('#' + this.id + 'def').addClass('visHidden');
}
Where your CSS would be:
.visHidden {
visibility:hidden;
}
Working fiddle: http://jsfiddle.net/rYYPb/
$('#red, #pink').on('click', function() {
var $def = $('#' + this.id + 'def');
if ($def.css('visibility') === 'hidden') {
$def.css('visibility', 'visible')
}
else {
$def.css('visibility', 'hidden');
}
});
Like winterblood said, visibility: hidden is still "visible" by jQuery's standards. So instead you can check whether it actually has the hidden style.

Categories

Resources