Jquery-ui sortable doesn't work on touch devices based on Android or IOS - iphone

Is there any fix to make Jquery-ui sortable work on touch devices based on Android or IOS?

I suggest jQuery UI Touch Punch. I've tested it on iOS 5 and Android 2.3 and it works great on both.

The other answer is great but unfortunately it will only work on iOS devices.
Also there was is a breakage caused by later versions of jquery.ui that meant that _touchEnd events were not correctly resetting an internal flag (mouseHandled) in mouse.ui and this was causing exceptions.
Both of these problems should now be fixed with this code.
/*
* Content-Type:text/javascript
*
* A bridge between iPad and iPhone touch events and jquery draggable,
* sortable etc. mouse interactions.
* #author Oleg Slobodskoi
*
* modified by John Hardy to use with any touch device
* fixed breakage caused by jquery.ui so that mouseHandled internal flag is reset
* before each touchStart event
*
*/
(function( $ ) {
$.support.touch = typeof Touch === 'object';
if (!$.support.touch) {
return;
}
var proto = $.ui.mouse.prototype,
_mouseInit = proto._mouseInit;
$.extend( proto, {
_mouseInit: function() {
this.element
.bind( "touchstart." + this.widgetName, $.proxy( this, "_touchStart" ) );
_mouseInit.apply( this, arguments );
},
_touchStart: function( event ) {
if ( event.originalEvent.targetTouches.length != 1 ) {
return false;
}
this.element
.bind( "touchmove." + this.widgetName, $.proxy( this, "_touchMove" ) )
.bind( "touchend." + this.widgetName, $.proxy( this, "_touchEnd" ) );
this._modifyEvent( event );
$( document ).trigger($.Event("mouseup")); //reset mouseHandled flag in ui.mouse
this._mouseDown( event );
return false;
},
_touchMove: function( event ) {
this._modifyEvent( event );
this._mouseMove( event );
},
_touchEnd: function( event ) {
this.element
.unbind( "touchmove." + this.widgetName )
.unbind( "touchend." + this.widgetName );
this._mouseUp( event );
},
_modifyEvent: function( event ) {
event.which = 1;
var target = event.originalEvent.targetTouches[0];
event.pageX = target.clientX;
event.pageY = target.clientY;
}
});
})( jQuery );

is this meant to replace the mouse.ui js code or to be called after that javascript is loaded? I am unable to get it to work for me on an Android tablet.
EDIT for anyone finding this in the future - got this to work for a Samsung Galaxy Android tablet with the following code:
/iPad|iPhone|Android/.test( navigator.userAgent ) && (function( $ ) {
var proto = $.ui.mouse.prototype,
_mouseInit = proto._mouseInit;
$.extend( proto, {
_mouseInit: function() {
this.element
.bind( "touchstart." + this.widgetName, $.proxy( this, "_touchStart" ) );
_mouseInit.apply( this, arguments );
},
_touchStart: function( event ) {
/* if ( event.originalEvent.targetTouches.length != 1 ) {
return false;
} */
this.element
.bind( "touchmove." + this.widgetName, $.proxy( this, "_touchMove" ) )
.bind( "touchend." + this.widgetName, $.proxy( this, "_touchEnd" ) );
this._modifyEvent( event );
$( document ).trigger($.Event("mouseup")); //reset mouseHandled flag in ui.mouse
this._mouseDown( event );
//return false;
},
_touchMove: function( event ) {
this._modifyEvent( event );
this._mouseMove( event );
},
_touchEnd: function( event ) {
this.element
.unbind( "touchmove." + this.widgetName )
.unbind( "touchend." + this.widgetName );
this._mouseUp( event );
},
_modifyEvent: function( event ) {
event.which = 1;
var target = event.originalEvent.targetTouches[0];
event.pageX = target.clientX;
event.pageY = target.clientY;
}
});
})( jQuery );

I finally found a solution that works with drag handles.
Go to this page.
In Downloads, grab the "altfix" version, which only applies touch handling to the elements you specify.
Add a script tag for the downloaded JS file.
Add touch handling for your drag handles in your document ready handler; e.g. $('.handle').addTouch()

I'm using this snippet below in conjunction with jquery-sortable which does allow the drag sort to happen on my iPhone. I am having a problem after I finish the first sort however as any scrolling on the list at all is detected as a drag.
EDIT - see here as well http://bugs.jqueryui.com/ticket/4143
EDIT 2 - I was able to get this working if I use the entire row as the handle. It also fixed a problem I was having where the offset was incorrect after scrolling.
/*
* A bridge between iPad and iPhone touch events and jquery draggable, sortable etc. mouse interactions.
* #author Oleg Slobodskoi
*/
/iPad|iPhone/.test( navigator.userAgent ) && (function( $ ) {
var proto = $.ui.mouse.prototype,
_mouseInit = proto._mouseInit;
$.extend( proto, {
_mouseInit: function() {
this.element
.bind( "touchstart." + this.widgetName, $.proxy( this, "_touchStart" ) );
_mouseInit.apply( this, arguments );
},
_touchStart: function( event ) {
if ( event.originalEvent.targetTouches.length != 1 ) {
return false;
}
this.element
.bind( "touchmove." + this.widgetName, $.proxy( this, "_touchMove" ) )
.bind( "touchend." + this.widgetName, $.proxy( this, "_touchEnd" ) );
this._modifyEvent( event );
this._mouseDown( event );
return false;
},
_touchMove: function( event ) {
this._modifyEvent( event );
this._mouseMove( event );
},
_touchEnd: function( event ) {
this.element
.unbind( "touchmove." + this.widgetName )
.unbind( "touchend." + this.widgetName );
this._mouseUp( event );
},
_modifyEvent: function( event ) {
event.which = 1;
var target = event.originalEvent.targetTouches[0];
event.pageX = target.clientX;
event.pageY = target.clientY;
}
});
})( jQuery );

This worked a lot better for me than the selected answer, so I hope this helps other people:
http://code.google.com/p/rsslounge/source/browse/trunk/public/javascript/addtouch.js?r=115.
The other code behaves weird, when you drag an element the potential dropping position is very far from were it should be.

Using Touch Punch is as easy as 1, 2…
Just follow these simple steps to enable touch events in your jQuery UI app:
Include jQuery and jQuery UI on your page.
Include Touch Punch after jQuery UI and before its first use.
Please note that if you are using jQuery UI's components, Touch Punch must be included after jquery.ui.mouse.js, as Touch Punch modifies its behavior.
There is no 3. Just use jQuery UI as expected and watch it work at the touch of a finger.
$('#widget').draggable();
Tested on iPad, iPhone, Android and other touch-enabled mobile devices.

Related

Plugin with multiple commands in ckeditor

I want to know how to create a ckeditor(v4.x) plugin with two or more commands inside it.
I'm able to create and execute a ckeditor with one command, as the code can be saw below:
CKEDITOR.plugins.add ('family',
{
init: function (editor)
{
editor.setKeystroke (CKEDITOR.CTRL + 65, 'parent'); // CTRL+A
editor.addCommand ('parent',
{
exec : function(editor)
{
var selection = editor.getSelection ().getSelectedText ();
editor.insertHtml ('<span data-role="parent">' + selection + '</span>' );
}
});
}
} );
What I want to achieve:
CKEDITOR.plugins.add ('family',
{
init: function (editor)
{
editor.setKeystroke (CKEDITOR.CTRL + 65, 'parent'); // CTRL+A
editor.addCommand ('parent',
{
exec : function(editor)
{
var selection = editor.getSelection ().getSelectedText ();
editor.insertHtml ('<span data-role="parent">' + selection + '</span>' );
}
});
editor.setKeystroke (CKEDITOR.CTRL + 69, 'child'); // CTRL+E
editor.addCommand ('child',
{
exec : function (editor)
{
var selection = editor.getSelection ().getSelectedText ();
editor.insertHtml ('<span data-role="child">' + selection + '</span>' );
}
});
}
} );
Suggestions?
I made a mistake in my tests to verify if the plugin was or not working. The mistake made it looks like it wasn't when it was.
This way of inserting two commands to one plugin does really work.

jQuery UI Autocomplete category is selecting only results in all categories

I have used the jQuery UI Autocomplete demo source code for the Categories example (http://jqueryui.com/autocomplete/#categories) and have it working (querying a database which returns a JSON array).
I'm building a search function for an art gallery and my categories are Artists and Exhibitions. I want to show results from one or both categories. My problem is that results are only showing when the search term covers a result in both categories.
My suggestions script uses the search term to query two different database tables. I format and append the results into a single JSON array with rows for ["id"], ["value"], ["label"] and ["category"].
So for the search term CORN, the results that come back might be:
{ label: "Christopher Corner", category: "Artists" },
{ label: "New Pictures From Cornwall", category: "Exhibitions" },
{ label: "Cornie Collins", category: "Artists" },
At the moment when I type a search term, the possible results are only shown as long as a result is possible in ALL my categories, rather than what I want, which is one or more. So when I type CORN, I can see an Artist named Corner, and an Exhibition about Cornwall, but the minute I type the E of CORNE, all the options disappear, including the Artist whose name is Corner (which I would expect to remain).
I'm new to jQuery and jQuery UI and struggling to understand where the logic would be to select a list item from any category rather than all of them.
I have edited to add my code. This is the backend suggestions file - search_suggestions.php:
<?php
# if the 'term' variable is not sent with the request, exit
if (!isset($_REQUEST['term'])) {
exit;
}
# retrieve the search term that autocomplete sends
$term = trim(strip_tags($_GET['term']));
$a_json = array();
$a_json_row = array();
# connect to database, send relevant query and retrieve recordset
include 'includes/db_access.php';
$compoundFind = $fm->newCompoundFindCommand('web_Artists');
$request1 = $fm->newFindRequest('web_Artists');
$request2 = $fm->newFindRequest('web_Artists');
$request1->addFindCriterion('Last name', '*'.$term.'*');
$request2->addFindCriterion('First name', '*'.$term.'*');
$compoundFind->add(1, $request1);
$compoundFind->add(2, $request2);
$compoundFind->addSortRule('Last name', 1, FILEMAKER_SORT_ASCEND);
$result = $compoundFind->execute();
if (FileMaker::isError($result)) {
die();
}
$records = $result->getRecords();
# loop through records compiling JSON array
foreach ($records as $record) {
$artistID = htmlentities(stripslashes($record->getRecordID())) ;
$artistName = htmlentities(stripslashes($record->getField('Full name'))) ;
$a_json_row["id"] = $artistID;
$a_json_row["value"] = $artistName;
$a_json_row["label"] = $artistName;
$a_json_row["category"] = "Artists";
array_push($a_json, $a_json_row);
}
$findCommand = $fm->newFindCommand('web_Exhibitions');
$findCommand->addFindCriterion('Title', '*'.$term.'*');
$result = $findCommand->execute();
if (FileMaker::isError($result)) {
die();
}
$records = $result->getRecords();
foreach ($records as $record) {
$exhibitionID = htmlentities(stripslashes($record->getField('Exhibition ID'))) ;
$exhibitionTitle = htmlentities(stripslashes($record->getField('Title'))) ;
$a_json_row["id"] = $exhibitionID;
$a_json_row["value"] = $exhibitionTitle;
$a_json_row["label"] = $exhibitionTitle;
$a_json_row["category"] = "Exhibitions";
array_push($a_json, $a_json_row);
}
echo json_encode($a_json);
flush();
?>
And here is the JS in my section which sets things up:
<style>
.ui-autocomplete-category {
font-weight: bold;
padding: .2em .4em;
margin: .8em 0 .2em;
line-height: 1.5;
}
</style>
<script>
$.widget( "custom.catcomplete", $.ui.autocomplete, {
_create: function() {
this._super();
this.widget().menu( "option", "items", "> :not(.ui-autocomplete-category)" );
},
_renderMenu: function( ul, items ) {
var that = this,
currentCategory = "";
$.each( items, function( index, item) {
var li;
if ( item.category != currentCategory ) {
ul.append( "<li class='ui-autocomplete-category'>" + item.category + "</li>" );
currentCategory = item.category;
}
li = that._renderItemData( ul, item );
if ( item.category ) {
li.attr( "aria-label", item.category + " : " + item.label );
}
});
}
});
</script>
<script>
$(function() {
$( "#searchInput" ).catcomplete({
minLength: 2,
source:'search_suggestions.php'
});
});
</script>
Finally this is the actual input field on the page:
<input class="u-full-width" placeholder="Search" id="searchInput" />
Sorry if this is too much code!

Destroying and Re-initializing Turn.js

I have a web page where I'm using turn.js and wish to destroy and re-initialize the plug-in if a user resizes the page to below a certain threshold. I'm testing this as follows:
$(window).resize(function() {
if (Modernizr.mq('(min-width: 764px)')) {
$("#flipbook").turn("destroy");
}
});
However I'm not sure how to re-initialize turn.js subsequently?
You are close: Just one more thing needed was to add $( window ).unbind( 'keydown' ); and then re-initialize by adding .turn() again;
$( '#book' ).turn( 'addpage', element, pageNo ); is the proper way of doing it but I don't want to return just a block of HTML. I prefer reloading the entire div. So what worked for me was:
// data is html ajax response
// destroy any previous bindings'
if ( $( '#book' ).turn( 'is' ) ) {
$( '#book' ).turn( 'destroy' );
$( window ).unbind( 'keydown' );
}
$( '#book' ).html( data );
// load the book
$( '#book' ).turn({
display: 'double'
, acceleration: true
, gradients: !$.isTouch
, elevation:50
});

wp_is_post_autosave is not working

I want to auto publish all articles of my WP blog on Facebook without using any plugin.
I wrote some working code to do that and it's OK... but I also need to invoke this code only when I publish a new article (not for revisions or autosave).
That's the part of my function.php file that you need to see:
add_action( 'save_post', 'koolmind_facebook_post_article',3 );
function koolmind_facebook_post_article( $post_id ) {
/* configuration of facebook params */
....
....
/* end config */
if ( !wp_is_post_revision( $post_id ) && !wp_is_post_autosave( $post_id ) ) {
/* retrieve some data to publish */
/* invoke my code to publish on facebook */
}
}
My code is invoked as soon as I click on "add new article", and an empty draft is sent to my Facebook page.
In add, as soon as I insert a single char on my article body, autosave is triggered and a new post (almost empty) is sent again to facebook.
I just want to block this automatic publishing and send my data to facebook only when I press the PUBLISH button.
Is that possible?
UPDATE
Finally I've found the problem. There was an error inside my fb code.
Problem now is avoiding multiple pubblication when updating my post.
Here's the code now:
add_action('pending_to_publish', 'koolmind_facebook_post_article');
add_action('draft_to_publish', 'koolmind_facebook_post_article');
add_action('new_to_publish', 'koolmind_facebook_post_article');
function koolmind_facebook_post_article( $post_id ) {
require_once 'facebook/facebook.php';
/* some code here */
//verify post is not a revision
if ( !wp_is_post_revision( $post_id ) ) {
$post_title = get_the_title( $post_id );
$post_url = get_permalink( $post_id );
$post_excerpt = get_the_excerpt();
$post_image = 'http://.../default.jpg'; //default image
if( $thumb_id = get_post_thumbnail_id( $post_id ) ){
$image_attributes = wp_get_attachment_image_src( $thumb_id );
$post_image = $image_attributes[0];
}
/* some code here */
}
}
Let me explain the issue:
If I use these 3 hooks I have no problem, but the code is executed before my featured image is stored into the database, so $post_image is always equals to the default image.
If I use publish_post hook instead, featured image is set properly (maybe because this hook is called after all data have been saved), but I cannot avoid data sending to Facebook if I update my post (wp_is_post_revision seems not to be fired).
Hope you have a good idea... now the code is almost OK! :)
The 'save_post' hook 'Runs after the data is saved to the database'. This means you can do this validation:
//WP hook
//the last parameter 2 means you pass 2 variables to the callback:
//the ID and the post WP object
add_action( 'save_post', 'koolmind_facebook_post_article',3,2 );
//Callback
function koolmind_facebook_post_article( $post_id, $post ) {
// Validation:
//If current WP user has no permissions to edit posts: exit function
if( !current_user_can('edit_post', $post_id) ) return;
//If is doing auto-save: exit function
if( defined('DOING_AUTOSAVE') AND DOING_AUTOSAVE ) return;
//If is doing auto-save via AJAX: exit function
if( defined( 'DOING_AJAX' ) && DOING_AJAX ) return;
//If is a revision or an autosave version or anything else: exit function
if( $post->post_status != 'publish') return;
/* configuration of facebook params */
/* invoke my code to publish on facebook */
}
It worked for me.
Try using:
add_action('publish_post', 'koolmind_facebook_post_article');

How to export sio2 file on iPhone?

When i export sio2 file of 3d game on simulator it is loading but then black screen appears.
Even i getting "current frame does not matches this frame" this error.
Can anybody help me out with his problem.
To be more technical while getting material objects its happening so
You have to write the code in templateRender as follows
void templateRender( void )
{
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT );
SIO2camera *_SIO2camera = ( SIO2camera * )sio2ResourceGet(
sio2->_SIO2resource, SIO2_CAMERA, "camera/Camera" );
if( _SIO2camera )
{
// Adjust the perspective, please take not
// that this operation should only be done
// once everytime you are switching cameras.
sio2Perspective( _SIO2camera->fov,
sio2->_SIO2window->scl->x / sio2->_SIO2window->scl->y,
_SIO2camera->cstart,
_SIO2camera->cend );
// Enter the 3D landscape mode
sio2WindowEnterLandscape3D();
{
sio2CameraRender( _SIO2camera );
sio2ResourceRender( sio2->_SIO2resource,
sio2->_SIO2window,
_SIO2camera,
SIO2_RENDER_SOLID_OBJECT );
}
sio2WindowLeaveLandscape3D();
}
}
Then in templateLoading:
void templateLoading( void )
{
unsigned int i = 0;
sio2ResourceCreateDictionary( sio2->_SIO2resource );
sio2ResourceOpen( sio2->_SIO2resource,
"Tutorial1.sio2", 1 );
while( i != sio2->_SIO2resource->gi.number_entry )
{
sio2ResourceExtract( sio2->_SIO2resource, NULL );
++i;
}
sio2ResourceClose( sio2->_SIO2resource );
sio2ResourceBindAllMatrix( sio2->_SIO2resource );
sio2ResourceGenId( sio2->_SIO2resource );
sio2ResetState();
sio2->_SIO2window->_SIO2windowrender = templateRender;
}