How to implement jQuery mobile swipe/shake in place of mouse swiping? - android

I have managed to build a simple jQuery flash card game following an online tutorial, resulting in this code:
var eng2fr = {
from: null,
to: null,
suggester: {
i: 0,
words: [
[ "beer", "binouze" ],
[ "another beer", "une autre bière" ],
[ "crazy", "fou" ],
[ "What the heck?!", "c'est quoi ce délire" ],
[ "whatever", "n'importe quoi"]
],
next: function(){
return this.words[ ( this.i++ ) % this.words.length ];
}
},
init: function(el) {
this.bindSwipe( $( "#display" ) );
this.from = $( "#from" );
this.to = $( "#to" );
Events.listen( "card_next", $.proxy( this.next, this ) );
Events.listen( "card_flip", $.proxy( this.flip, this ) );
// Begin!
this.next();
},
next: function() {
var to = this.to,
from = this.from,
next = this.suggester.next(),
_this = this;
to.text( next[ 0 ] );
to.addClass( "push in current" );
from.addClass( "push out" ).one( "webkitAnimationEnd", function() {
from.text( next[ 1 ] );
from.removeClass( "current push out" );
to.removeClass( "push in" );
_this.from = to;
_this.to = from;
});
},
flip: function() {
var to = this.to,
from = this.from,
_this = this;
to.addClass( "flip in current" );
from.addClass( "flip out" ).one( "webkitAnimationEnd", function() {
from.removeClass( "current flip out" );
to.removeClass( "flip in" );
_this.from = to;
_this.to = from;
});
},
bindSwipe: function( el ) {
this.xStart = null;
this.downEvent = 'ontouchstart' in document.documentElement && navigator.appVersion.indexOf( 'iPhone OS ' ) > -1 ? 'touchstart' : 'mousedown';
this.upEvent = 'ontouchend' in document.documentElement && navigator.appVersion.indexOf( 'iPhone OS ' ) > -1 ? 'touchend' : 'mouseup';
var _this = this;
el.bind({
"touchstart mousedown": function( e ) {
if( e.type !== _this.downEvent ) return;
e.preventDefault();
_this.xStart = e.pageX && e.pageX > 0 ? e.pageX : e.originalEvent.changedTouches[ 0 ].pageX;
},
"touchend mouseup": function( e ) {
if( e.type !== _this.upEvent ) return;
var newX = e.pageX && e.pageX > 0 ? e.pageX : e.originalEvent.changedTouches[ 0 ].pageX;
var diff = newX - _this.xStart;
if( Math.abs( diff ) > 20) {
if( diff > 0 ){
Events.trigger( "card_previous", {} );
} else {
Events.trigger( "card_next", {} );
}
} else {
Events.trigger( "card_flip", {} );
}
},
"touchmove": function( e ) {
e.preventDefault();
}
});
}
};
As you can probably see, this code relies on mouse events for flipping and browsing through cards. I'm looking to implement jQuery mobile swipe/tap functions in place of these and I was wondering if someone could help me with that or at least point me in the right direction.
Also, I'm wondering if there is a simple way to detect a shake event and use this to select a random "card" / word pair?

Related

How can a regular React application save video to Android Galery?

I figured out it is not possible to share video content onto Instagram directly on Android in behalf of the user. This was my original intention.
Seems I can not use navigator.share call which works on iOS but not on Android, or only for text and url, but not for video / mp4.
I would not use MediaStore and similar React Nativ solutions as my app is a regular React.
What elso approach do you know?
I have now this:
const showShareDialog = async () => {
try {
log(
{
text: 'setIsDownloadFileInProgress(true) ' + getTempUserShortId(),
},
env
)
setIsDownloadFileInProgress(true)
const res = await axios.get(
`https://t44-post-cover.s3.eu-central-1.amazonaws.com/${imgId}.mp4`,
{ withCredentials: false, responseType: 'blob' }
)
setIsDownloadFileInProgress(false)
const shareData = {
files: [
new File([res.data], `${imgId}.mp4`, {
type: 'video/mp4',
}),
],
title: 'Megosztom',
text: 'Mentsd le a képekbe, és oszd meg storyban.',
}
//showShareDialog(shareData, 0)
if (navigator.share && !isDesktop) {
log(
{
text:
`navigator.share && !isDesktop shareData.files[0].size: ${shareData.files[0].size} ` +
getTempUserShortId(),
},
env
)
if (isAndroid()) {
const { status } = await MediaLibrary.requestPermissionsAsync()
if (status === 'granted') {
const asset = await MediaLibrary.createAssetAsync(res.data)
await MediaLibrary.createAlbumAsync(`${imgId}.mp4`, asset, false)
}
} else {
navigator
.share(shareData)
.then(() => {
log(
{
text: `'The share was successful 1 ` + getTempUserShortId(),
},
env
)
})
.catch((error) => {
log(
{
text:
`There was an error sharing 1 ${error} ` +
getTempUserShortId(),
},
env
)
})
}
} else {
log(
{
text: 'else ' + getTempUserShortId(),
},
env
)
setIsDesktopDownloadDialogVisible(true)
}
} catch (error) {
console.error(error)
log(
{
text: `a onclick error 2: ${error} ` + getTempUserShortId(),
},
env
)
}
}

issue facing in recording video and uploading to server in android titanium

I am using Android device for upload video on the server using titanium platform. I am facing following issue when retrieving data.
No Activity found to handle Intent { act=android.media.action.VIDEO_CAPTURE dat=content://com.example.videoupload.tifileprovider/filesystem/storage/emulated/0/Android/data/com.example.videoupload/cache/_tmp/tia7257530851591479880.mp4 typ=video/* flg=0x3 }
Following is the code which I am using:-
Titanium.Media.showCamera( {
success: function( event ) {
// called when media returned from the camera
if( ( event.mediaType === Ti.Media.MEDIA_TYPE_VIDEO ) && ( event.media !== null ) ) {
// AndroidSelectedImage(event.media.imageAsThumbnail(300));
var image = event.media;
var intent = Ti.Android.createIntent( {
action: "android.media.action.VIDEO_CAPTURE",
//action : Ti.Android.ACTION_PICK,
//flags : Titanium.Android.FLAG_GRANT_READ_URI_PERMISSION | Titanium.Android.FLAG_GRANT_WRITE_URI_PERMISSION,
//data : event.media.getFile().nativePath,
type: 'video/*',
} );
var activity = require( 'main' ).activity;
//winCertificate.getActivity()
activity.startActivityForResult( intent, function( param ) {
Ti.API.info( 'intent :- ' + JSON.stringify( intent ) );
Ti.API.info( 'intent 1:- ' + JSON.stringify( param ) );
} );
} );
} );
Help me in this situation. Thanks in advance
Send you video directly to the server using HttpClient
success: function( event ) {
if( ( event.mediaType === Ti.Media.MEDIA_TYPE_VIDEO ) && ( event.media !== null ) ) {
var client = Ti.Network.createHTTPClient( {
onload: function( e ) {
alert( 'success' );
},
onerror: function( e ) {
alert( 'error' );
},
timeout: 0
} );
client.open( "GET", URL );
client.send( {
video: media.video
} );
}
}
With titanium activity start like this
Ti.Android.currentActivity.startActivity(intent);

Expected HTTP 101 response but was '403 Forbidden' in Android WebSocket - React Native

I Making a chess app with react native, i sending & receiving my request with websocket,
when i run my app in ios every thing is ok,but when i run my app in android the web socket not open and return " Expected HTTP 101 response but was '403 Forbidden' ".
my create game code :
createGame() {
const { playConfig } = this.props;
fetch('https://en.lichess.org/setup/ai', {
method: 'POST',
headers: {
Accept: 'application/vnd.lichess.v2+json',
'Content-Type': 'application/json',
},
body: playConfig,
})
.then(res => res.json())
.then(this.onGameCreated);
}
onGameCreated = res => {
const { game } = this.state;
const socketUrl = res.url.socket;
const clientId = Math.random().toString(36).substring(2);
clearInterval(this.interval);
this.wsReady = false;
let url = `wss://socket.lichess.org${socketUrl}?sri=${clientId}&mobile=1`;
this.ws = new WebSocket(
url,
);
this.ws.onmessage = e => {
// a message was received
console.log(`received: ${e.data}`);
const data = JSON.parse(e.data);
let moveData;
let victor;
if (data.t === 'move' && data.v > game.history().length) {
moveData = data.d;
} else if (data.t === 'end') {
victor = data.d;
} else if (data.t === 'b') {
// b for batch
const first = data.d[0];
if (first) {
if (first.d.status && first.d.status.name === 'mate') {
moveData = first.d;
}
if (first.t === 'end') {
victor = first.d;
}
if (first.d.winner) {
victor = first.d.winner;
}
}
}
if (victor) {
dongSound.play();
this.setState({
victor,
});
this.ws = null;
} else if (moveData) {
const { uci, clock } = moveData;
const castle = moveData.castle;
let from = uci.substring(0, 2);
let to = uci.substring(2, 4);
if (castle && castle.king) {
from = castle.king[0];
to = castle.king[1];
}
this.board.movePiece(to, from);
if (clock) {
this.latestClock = clock;
}
}
};
this.ws.onerror = e => {
// an error occurred
console.log(e.message);
};
this.ws.onopen = () => {
this.wsReady = true;
dongSound.play();
this.setState({
initialized: true,
userColor: res.player.color === 'white' ? 'w' : 'b',
});
console.log('ws open');
// ping every second
this.interval = setInterval(
() => {
this.sendMessage({
t: 'p',
v: game.history().length,
});
},
1000,
);
};
};
any one has idea?
thank you in advance
Looks like you don't have permission to open a socket on this webserver.
I don't think the problem is in your Java code but the webserver configuration.

React native listview does not show all the rows

I have a questionnaire application which works fine on Android. However on iOS, the ListView never shows all the questions. Of the 11 questions in the questionnaire. only about 2 or 2.5 of them are rendered. A small amount of scrolling does seem to happen based on the size off the emulator window. I have tried all the suggestion posted including:
- setting the height of the ListView item using Dimensions
- setting flex:1 up the container hierarchy.
But nothing seems to work.
I am posting a much abridged and modified version of the code that uses NativeBase's RadionButton. My original code uses my own home-brewed radio buttons, but all of them have the same problem. I would appreciate any help I can get on this problem. Thanks in advance.
Here is my code:
import React, { Component } from 'react';
import {
Alert,
StyleSheet,
// Text,
TextInput,
View,
ListView,
TouchableHighlight,
Dimensions,
} from 'react-native';
import Svg,{
Rect,
} from 'react-native-svg';
import { Actions } from 'react-native-router-flux';
import realm from './realm';
import Utils from './Utils';
import moment from 'moment';
import { Container, Content, InputGroup, Input,
List, ListItem, Text, Radio } from 'native-base';
require('Dimensions');
const windowDims = Dimensions.get('window');
///////////////////////////////////////////////////////////////////////////////
const WhenSymptom = 0;
const FrequencySymptom = 1;
const FeelingSymptom = 2;
const YesNoSymptom = 3;
const ValueSymptom = 4;
global.junk = "hello";
var SymptomValues = new Array
(
// WhenSymptom
[ "none", "only after inactivity", "mostly AM", "AM and PM", "all the time" ],
// FrequencySymptom
[ "None", "Less than usual", "Usual", "More than usual", "Very bothersome" ],
// FeelingSymptom
[ "Great", "Fair", "So-so", "Poor", "Terrible" ],
// YesNoSymptom
[ "No", "", "", "", "Yes" ],
// ValueSymptom
[]
);
// var questions = new Array
global.questions = new Array
(
{ rowIndex: 0,
chartTitle: "Tremors",
answer: 0},
{ rowIndex: 1,
chartTitle: "Speech-slurring",
answer: 1},
{ rowIndex: 2,
chartTitle: "Feeling-stuck",
answer: 2},
{ rowIndex: 3,
chartTitle: "Instability",
answer: 3},
{ rowIndex: 4,
chartTitle: "Anxiety",
answer: 4},
{ rowIndex: 5,
chartTitle: "# of steps",
answer: 1},
{ rowIndex: 6,
chartTitle: "Pain or aches",
answer: 3},
{ rowIndex: 7,
chartTitle: "Day drowsiness",
answer: 2},
{ rowIndex: 8,
chartTitle: "Urinary urgency",
answer: 1},
{ rowIndex: 9,
chartTitle: "Constipation",
answer: 0},
{ rowIndex: 10,
chartTitle: "Overall feeling",
answer: 2}
);
var colors = new Array( "green", "#dbdb70", "yellow", "orange", "red" );
var styles = StyleSheet.create({
list: {
flexDirection: 'column',
flex:1,
//height: windowDims.height-30,
marginTop: 52,
},
questionText: {
flex:1,
fontSize: 14,
// color: 'white',
color: 'black',
alignSelf: 'flex-start'
},
});
var junk = 0;
// const mySaveAction = () => console.log('Back From the Questions page ');
///////////////////////////////////////////////////////////////////////////////
export default class QuestionsPage extends Component {
constructor(props){
super(props);
console.log("numToPop: " + this.props.numToPop);
var ds = new ListView.DataSource({
rowHasChanged: (r1, r2) => r1 != r2
//rowHasChanged: (r1, r2) => true
});
// if it is a new panel, set all the answers to -1
let answersIn = new Array(questions.length);
if (this.props.panel == null) {
for (let i in questions) {
answersIn[i] = -1;
questions[i].answer = -1;
}
}
else {
answersIn = this.props.panel.symptoms.split(",");
for (let i in questions) {
questions[i].answer = answersIn[i];
}
}
this.state = {
ds: questions,
dataSource:ds,
editAllowed: 0,
initialAnswers: answersIn,
behavior: 'position'
// there is three ways to adjust (position , height , padding )
}
}
///////////////////////////////////////////////////////////////////////////////
componentDidMount(){
this.setState({
dataSource:this.state.dataSource.cloneWithRows(this.state.ds),
});
// When we come in here with newPanel == 1, the route was
// MenuPage => QuestionsPage; so cancel should just be
// Actions.pop(). If newPanel == 0, , the route was
// MenuPage => Calendar => QuestionsPage; so cancel should call Actions.pop(2)
Actions.refresh({ onRight: () => { this._saveButtonPressed(); },
onBack: () => { this._cancelButtonPressed(); },
title: (this.props.panel == null ?
"New panel" :
(" Panel of " +
Utils.readableDate(this.props.panel.panelDate)))
});
}
///////////////////////////////////////////////////////////////////////////////
_saveButtonPressed() {
var finalAnswers = new Array(questions.length);
var panelChanged = 0;
var dateString;
for (let i=0; i<finalAnswers.length; i++) {
finalAnswers[i] = questions[i].answer;
if (finalAnswers[i] != this.state.initialAnswers[i])
panelChanged = 1;
}
var symptoms = "" + finalAnswers[0];
for (let i=1; i<finalAnswers.length; i++) {
symptoms = (symptoms + "," + finalAnswers[i]);
}
console.log("_saveButtonPressed panelChanged: " + panelChanged);
if (this.props.panel == null) {
if (panelChanged) {
let myPanelKey = Utils.newPanelKey();
this._updateDB(myPanelKey, symptoms);
}
Actions.pop();
}
else {
if (panelChanged) {
this._updateDB(this.props.panel.panelDate, symptoms);
}
// Kluge:
this._returnFromScreen();
}
}
///////////////////////////////////////////////////////////////////////////////
_updateDB(myPanelDate, symptoms) {
console.log("_updateDB dt: " + moment(myPanelDate).toString() +
" symptoms: " + symptoms);
// var dateString = Utils._myISOString(myPanelDate);
realm.write(() => {
realm.create('Symptoms', {panelDate: myPanelDate, symptoms: symptoms}, true);
});
console.log("Trace");
let after = realm.objects('Symptoms');
for (let i=0; i<after.length; i++) {
console.log("panelDate: " + moment(after[i].panelDate).toString() +
" (" + after[i].panelDate + " )" +
"; symptoms: " + after[i].symptoms);
}
}
///////////////////////////////////////////////////////////////////////////////
_returnFromScreen() {
if (this.props.numToPop == 1)
Actions.pop();
else
Actions.pop({popNum: 2});
}
///////////////////////////////////////////////////////////////////////////////
_cancelButtonPressed() {
console.log("_cancelButtonPressed in QuestionsPage numToPop: " +
this.props.numToPop);
this._returnFromScreen();
}
///////////////////////////////////////////////////////////////////////////////
_rowPressed(rowData){
console.log("In _rowPressed");
}
///////////////////////////////////////////////////////////////////////////////
_buttonPressed(rowIndex, value, forceEdit = 0){
// console.log("In _buttonPressed " + rowIndex + " " + value);
let newDs = this.state.ds.slice();
newDs[rowIndex] = {
...this.state.ds[rowIndex],
answer: value,
};
// This is absolutely essential to do!!!!!
questions[rowIndex].answer = value;
this.setState({
dataSource:this.state.dataSource.cloneWithRows(newDs),
})
// this.forceUpdate();
// console.log("answers: " + this.state.answers);
}
///////////////////////////////////////////////////////////////////////////////
_renderButton(rowIndex, column){
return (
<ListItem>
<Radio selected={this.state.ds[rowIndex].answer == column ? true : false} />
<Text>{SymptomValues[0][column]}</Text>
</ListItem>
);
}
///////////////////////////////////////////////////////////////////////////////
_renderRow(rowData){
// console.log("renderRow " + this.state.ds[rowData.rowIndex].answer);
return (
<View style={styles.list}>
<Text style={styles.questionText}>Question {rowData.rowIndex+1}.</Text>
<Container>
<Content>
<List>
{ this._renderButton(rowData.rowIndex, 0) }
{ this._renderButton(rowData.rowIndex, 1) }
{ this._renderButton(rowData.rowIndex, 2) }
{ this._renderButton(rowData.rowIndex, 3) }
{ this._renderButton(rowData.rowIndex, 4) }
</List>
</Content>
</Container>
</View>
);
}
///////////////////////////////////////////////////////////////////////////////
render(){
// console.log("render");
return (
<ListView style={styles.list}
dataSource = {this.state.dataSource}
renderRow = {this._renderRow.bind(this)}>
</ListView>
);
}
}
module.exports = QuestionsPage;
// Util.js
import moment from 'moment';
let Utils = {
// toISOString returns (YYYY-MM-DDTHH:mm:ss.sssZ
newPanelKey: function() {
let myPanelDate = moment();
myPanelDate.milliseconds(0);
myPanelDate.seconds(0);
myPanelDate.minutes(0);
return myPanelDate.valueOf();
},
readableDate: function(utc) {
return moment(utc).format("MMM D, YYYY#ha");
},
readableDateNoTime: function(utc) {
return moment(utc).format("MMM D, YYYY");
},
shortDate: function(utc) {
let mom = moment(utc);
let date = mom.format("DDMMM:hha");
return date.substring(0,date.length-1);
}
}
module.exports = Utils;

Android 4.3 doesn't show bxslider's content properly

I've been stuck for 2 days and I can't find a solution.
My development enviroment:
Cordova 3.4.0-0.1.0,jQuery v1.10.2, BxSlider v4.1.1 and Android
When I select a category I make an ajax call and load my bxslider from the server
My code: front
$('.background_folder').on("change", function(){
var folder = $(this).val();
if(folder != '' && folder != undefined){
var jqxhr = $.ajax({
url:'http://myserver/get_backgrounds.php?folder='+folder
})
.done(function( html ) {
$('.background_sample').html(html);
if ($(window).width() <= 320 || $(window).height() <= 480) {
var s1 = $('.slider1').bxSlider({
slideWidth: 230,
minSlides: 1,
maxSlides: 1,
slideMargin: 10,
pager: false
});
}else{
var s2 = $('.slider1').bxSlider({
slideWidth: 265,
minSlides: 2,
maxSlides: 3,
slideMargin: 10,
pager: false
});
}
})
.always(function() {
alert( "complete" );
$('.convert').on("click", function(){
$('.convert').css({border: '2px solid transparent'}).animate({
opacity: 0.5
}, 500 );
$(this).css({border: '2px solid #f37736'}).animate({
opacity: 1
}, 500 );
});
});
}
});
My code: back
function get_backgrounds($folder){
//image backgrounds
$backgrounds = array();
if ($handle = opendir("../backgrounds/".$folder)) {
//$backgrounds = array();
while (false !== ($entry = readdir($handle))) {
$backgrounds[] = $entry;
}
foreach ($backgrounds as $key => $value) {
if($value == '.' || $value == '..'){
unset($backgrounds[$key]);
}
}
}
$i = 0;
echo '<div class="slider1">';
foreach ($backgrounds as $key => $value) {
if($i == 0){
$selected = 'checked="checked"';
}else{
$selected = '';
}
$idvalue = 'data'.$key;
echo '<div class="slide">';
echo '<div class="background_thumb">';
echo '<label class="fb" for="'.$idvalue.'">';
echo '<input '.$selected.' type="radio" name="background" id="'.$idvalue.'" value="'.$value.'">';
echo '<img class="convert" src="backgrounds/'.$folder.'/'.$value.'">';
echo '</label>';
echo '</div>';
echo '</div>';
$i++;
}
echo '</div>';
}
For any reason in Android 4.4.2 is fine but in Android 4.3 and lower versions the content is there but I can't see it.
Any idea what is happening ???
Certainly it was a CSS issue, for some reason I was losing the height, so my solution:
$('.slider1').bxSlider({
slideWidth: 265,
minSlides: 2,
maxSlides: 3,
slideMargin: 10,
pager: false,
onSliderLoad: function(){
$('.bx-viewport').css({"height":"80px !important"});
$('.convert').css({"height":"80px !important"});
}
});

Categories

Resources