I use Ionic Framework.
Camera works perfectly in Ionic View. But it doesn't work after compilitaion on iOS.
Please, help to find out what is the problem.
Camera code in services.js:
app.factory('FileService', function() {
var images;
var IMAGE_STORAGE_KEY = 'dav-images';
function getImages() {
var img = window.localStorage.getItem(IMAGE_STORAGE_KEY);
if (img) {
images = JSON.parse(img);
} else {
images = [];
}
return images;
};
function addImage(img) {
images.push(img);
window.localStorage.setItem(IMAGE_STORAGE_KEY, JSON.stringify(images));
};
return {
storeImage: addImage,
images: getImages
}
});
app.factory('ImageService', function($cordovaCamera, FileService, $q, $cordovaFile) {
function optionsForType(type) {
var source;
switch (type) {
case 0:
source = Camera.PictureSourceType.CAMERA;
break;
case 1:
source = Camera.PictureSourceType.PHOTOLIBRARY;
break;
}
return {
quality: 90,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: source,
allowEdit: false,
encodingType: Camera.EncodingType.JPEG,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false,
correctOrientation:true
};
}
function saveMedia(type) {
return $q(function(resolve, reject) {
var options = optionsForType(type);
$cordovaCamera.getPicture(options).then(function(imageBase64) {
FileService.storeImage(imageBase64);
});
})
}
return {
handleMediaDialog: saveMedia
}
});
Camera code in controllers.js:
app.controller('CameraController', function($scope, $cordovaDevice, $cordovaFile, $ionicPlatform, $cordovaEmailComposer, $ionicActionSheet, ImageService, FileService) {
$ionicPlatform.ready(function() {
$scope.images = FileService.images();
$scope.$apply();
});
$scope.addMedia = function() {
$scope.hideSheet = $ionicActionSheet.show({
buttons: [
{ text: 'Take photo' },
{ text: 'Photo from library' }
],
titleText: 'Add images',
cancelText: 'Cancel',
buttonClicked: function(index) {
$scope.addImage(index);
}
});
}
$scope.addImage = function(type) {
$scope.hideSheet();
ImageService.handleMediaDialog(type).then(function() {
$scope.$apply();
});
}
$scope.sendEmail = function() {
if ($scope.images != null && $scope.images.length > 0) {
var mailImages = [];
var savedImages = $scope.images;
for (var i = 0; i < savedImages.length; i++) {
mailImages.push('base64:attachment'+i+'.jpg//' + savedImages[i]);
}
$scope.openMailComposer(mailImages);
}
}
$scope.openMailComposer = function(attachments) {
var bodyText = '<html><h2>My Images</h2></html>';
var email = {
to: '',
attachments: attachments,
subject: 'Devdactic Images',
body: bodyText,
isHtml: true
};
$cordovaEmailComposer.open(email, function(){
console.log('email view dismissed');
}, this);
}
});
To resolve this problem you need to compile an app with XCode.
After XCode compilation camera works correctly.
Probably, the problem with camera was caused by Ionic compilation.
Related
I want to implement image uploading. It works for web (Chrome/Safari), but not for mobile ios (built with Capacitor). It shows image selection, but when I select it nothing happens.
Here is my input:
<q-file
v-model="avatarFile"
accept=".jpg, .png"
#input="uploadImage"
/>
async uploadImage() {
if (this.avatarFile) {
let extension = "jpg";
if (this.avatarFile.type === "image/png") {
extension = "png";
}
try {
this.loading = 1;
const {
data: {
uploadUrl: { uploadUrl },
},
} = await this.$apollo.query({
query: GET_UPLOAD_URL,
variables: {
extension,
},
});
await axios.put(uploadUrl, this.avatarFile);
await setTimeout(() => {
this.$emit("on-image-upload");
this.loading = 0;
}, 3000);
} catch (e) {
this.alertError(e);
this.loading = 0;
}
}
}
What am I doing wrong? Thanx in advance!
Found the solution. My accept rule had the wrong format. This works:
accept="image/*"
I'm using the gem ratyrate, and locally it works fine, but in production it generates a 404 error of the images.
Some solutions I found were these, but they do not work
/initializer/raty_helper.rb
https://github.com/wazery/ratyrate/blob/master/lib/ratyrate/helpers.rb
raty.js.rb
$.fn.raty.defaults.half = false;
$.fn.raty.defaults.halfShow = true;
$.fn.raty.defaults.path = '<%= asset_path('images') %>';
$.fn.raty.defaults.cancel = false;
$(function(){
$(".star").each(function() {
var $readonly = ($(this).attr('data-readonly') == 'true');
var $half = ($(this).attr('data-enable-half') == 'true');
var $halfShow = ($(this).attr('data-half-show') == 'true');
var $single = ($(this).attr('data-single') == 'true');
$(this).raty({
score: function() {
return $(this).attr('data-rating')
},
number: function() {
return $(this).attr('data-star-count')
},
half: $half,
halfShow: $halfShow,
single: $single,
path: $(this).attr('data-star-path'),
starOn: '/star-on.png',
starOff: '/star-off.png',
starHalf: '/star-half.png',
cancel: $(this).attr('data-cancel'),
cancelPlace: $(this).attr('data-cancel-place'),
cancelHint: $(this).attr('data-cancel-hint'),
cancelOn: '/cancel-on.png',
cancelOff: '/cancel-off',
noRatedMsg: $(this).attr('data-no-rated-message'),
round: $(this).attr('data-round'),
space: $(this).attr('data-space'),
target: $(this).attr('data-target'),
targetText: $(this).attr('data-target-text'),
targetType: $(this).attr('data-target-type'),
targetFormat: $(this).attr('data-target-format'),
targetScoret: $(this).attr('data-target-score'),
readOnly: $readonly,
click: function(score, evt) {
var _this = this;
if (score == null) { score = 0; }
$.post('<%= Rails.application.class.routes.url_helpers.rate_path %>',
{
score: score,
dimension: $(this).attr('data-dimension'),
id: $(this).attr('data-id'),
klass: $(this).attr('data-classname')
},
function(data) {
if(data) {
// success code goes here ...
if ($(_this).attr('data-disable-after-rate') == 'true') {
$(_this).raty('set', { readOnly: true, score: score });
}
}
});
}
});
});
});
Add to your your config/environments/production.rb:
config.serve_static_assets = true
The solution is to execute this command:
rails assets:precompile
I use Kendo UI in ASP .NET MVC app. I have Kendo Treelist. Sometimes, after editing a row, all rows disappear, and I see only root element without child rows. Is it Kendo bug?Or I can prevent it? And when rows have disappeared, I refresh page, do the same changes and save treelist - the treelist works correctly.
var parsedXmlDataInJson = #Html.Raw(#ViewBag.XmlData); //jsonarray data
$( document ).ready(function() {
});
function ShowMessage(message,timeout) //пока сообщению пользователю в левом верхнем углу
{
var divMessage = $('#toggler');
if(divMessage.css('display') != 'none')
{
divMessage.clearQueue();
divMessage.stop();
divMessage.css('display','none');
}
if (timeout == 0)
divMessage.text(message).toggle('slow');
else
divMessage.text(message).toggle('slow').delay(timeout).toggle('slow');
}
var treelistds = new kendo.data.TreeListDataSource({ //CRUD for dataSource
transport: {
read: function(e) {
e.success(parsedXmlDataInJson);
},
update: function(e) {
var updatedItem = e.data;
$.each(parsedXmlDataInJson, function(indx, value) {
if (value.id == updatedItem.Id) {
value = updatedItem;
return false;
}
});
e.success();
},
create: function(e) {//Works for root element when editing only once - it's broke my treelist.
e.data.Id = GetId();
parsedXmlDataInJson.push(e.data);
e.success(e.data);
},
destroy: function(e) {
var updatedItem = e.data;
$.each(parsedXmlDataInJson, function(indx, value) {
if (value.id == updatedItem.Id) {
parsedXmlDataInJson.splice(indx, 1);
}
});
e.success();
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {
models: kendo.stringify(options.models)
};
}
}
},
batch: false,
schema: {
model: {
id: "Id",
parentId: "parentId",
fields: {
Id: {
type: "number",
editable: true,
nullable: false
},
parentId: {
field: "parentId",
nullable: true
}
}
}
}
});
$("#treeList").kendoTreeList({
resizable: true,
dataSource: treelistds,
toolbar: ["create"],
columns: [{
field: "typeAndAttributes",
width:400
}, {
field: "text",
title: "Текст",
}, {
field: "cData",
title: "CDATA",
}, { //my custom command
command: ["edit", "destroy", "createchild", {
name: "commentOut",
text: "commentOut",
click: function(e) {
var dataItem = this.dataItem($(e.target).closest("tr")); ///my custom command
dataItem.commentedOut = !dataItem.commentedOut;
var isCommentedOut = dataItem.commentedOut;
var childNotes = this.dataSource.childNodes(dataItem);
childNotes.forEach(function(childModel, i) //
{
childModel.commentedOut = isCommentedOut;
SetChildrenIsCommentedOut(childModel, isCommentedOut);
})
//обновляем цвет и текст кнопок у всех элементов вызывая dataBound
$("#treeList").data("kendoTreeList").refresh();
},
}, ]
}],
messages: {
commands: {
edit: "Изменить",
destroy: "Удалить",
createchild: "Добавить"
}
},
dataBound: function(e) {
this.autoFitColumn(3);
Databound(e.sender, e.sender.table.find("tr"));
},
editable: true,
editable: {
mode: "popup",
template: kendo.template($("#popup-editor").html()),
window: {
width:800
}
},
edit: function(e) { //invokes when popup open
$("#date").kendoDateTimePicker({
});
$("#cDataEditor").kendoEditor({
tools: [
"formatting", "bold", "italic", "underline", "insertUnorderedList",
"insertOrderedList", "indent", "outdent", "createLink", "unlink"
],
resizable: {
content: true,
toolbar: true,
max:350
}
});
//my custom logic. Popup contains many fileds splitted from one model field
if (!e.model.isNew()) { //split typeAndAttrubites to popup's fileds
var fileds = e.model.typeAndAttributes.split(';').
filter(function(v) {
return v !== ''
});
e.container.find("#type").val(fileds[0]);
var length = fileds.length;
for (i = 1; i < length; i++) {
var keyAndValue = fileds[i].split('=');
if (keyAndValue[0] != "id")
e.container.find("#" + keyAndValue[0].trim()).val(keyAndValue[1].trim());
else
e.container.find("#xmlId").val(keyAndValue[1].trim());
}
}
},
save: function(e) { //invokes when saving
var splitter = "; ";
var inputValue = $("input[id='type']").val().trim();
if (e.model.type !== undefined) {
e.model.typeAndAttributes = e.model.type;
} else {
e.model.typeAndAttributes = inputValue;
}
var allInputs = $(":input[data-appointment=attributes]");
allInputs.each(function(index, input) { //collect inputs in one filed
var attrName;
var attrValue;
if (input.id != "id") {
attrName = input.id;
e.model[attrName];
} else {
attrName = "id";
attrValue = e.model["xmlId"];
}
//значение изменили и оно не пустое
if (attrValue !== undefined && attrValue !== "") {
if (attrValue == false)
return true;
e.model.typeAndAttributes += splitter + attrName + "=" + attrValue;
}
//my custom logic
else if (input.value.trim() && input.value != "on") {
e.model.typeAndAttributes += splitter + attrName + "=" + input.value.trim();
}
})
}
});
//рекурсивно помечаем ряды как закомментированные или нет
function SetChildrenIsCommentedOut(dataItem, isCommentedOut) {
var childNotes = $("#treeList").data("kendoTreeList").dataSource.childNodes(dataItem);
childNotes.forEach(function(childModel, i) {
childModel.commentedOut = isCommentedOut;
SetChildrenIsCommentedOut(childModel, isCommentedOut);
})
}
//Раскрашивает строки соответственно значению закомментировано или нет
function Databound(sender, rows) {
rows.each(function(idx, row) {
var dataItem = sender.dataItem(row);
if (dataItem.commentedOut) {
//обозначаем ряд как закомментированный
$(row).css("background", "#DCFFE0");
$(row).find("[data-command='commentout']").html("Раскомментировать");
} else {
//обозначаем ряд как незакомментированный
$(row).css("background", "");
$(row).find("[data-command='commentout']").html("Закомментировать");
}
})
}
});
var currentId = 0;
function GetId() { //генерирование Id для новых записей
var dataSource = $("#treeList").data("kendoTreeList").dataSource;
do {
currentId++;
var dataItem = dataSource.get(currentId);
} while (dataItem !== undefined)
return currentId;
}
In my import photos script, I try to update a progressbar (Jquery UI) following a while loop with Ajax requests.
The JQueryUI progressbar, which is supposed to be displayed before the launch of ajax requests do it after. So I have the user feedback at the end of the execution of my while loop ... (The console shows me that these applications are running well, in the right order)
I thought about using live () or bind (), but I do not know how to test it ...
Here is my jquery code:
$(function() {
var percent_progressbar=0;
$('#myform').submit(function() {
$('#myform').hide();
$("#text_result").html("Import in progress : <span class='progression'>0/0</span>").show(10, function() {
$("#myprogressbar").progressbar({value:percent_progressbar});
$("#myprogressbar").show(10, function() {
if (jQuery.trim($("#id_src").val()).length!=0) {
// Total number of photos to import
$.ajax({
type : 'POST',
async : false,
url : '/nbphotos.php',
data : 'chem=mydir',
success : function(nbphotos){
if (nbphotos>0){
$(".progression").html("0"+" / "+nbphotos);
var finish=false;
var nb_photos_imported=0;
var ajax_done = false;
var resultat_ajax="";
// Variables envoyées en Ajax
var datas = desvariables;
while (nb_photos_imported < nbphotos) {
ajax_done = false;
$.ajax({
type : 'GET',
async : false,
url : '/traitement.php',
data : datas,
success : function(resultat){
resultat_ajax=resultat;
ajax_done=true;
nb_photos_imported++;
}
});
if (ajax_done==true){
if (resultat_ajax=="ok") {
percent_progressbar = Math.floor(nb_photos_imported*100/nbphotos);
$("#myprogressbar").progressbar("option", "value", percent_progressbar);
console.info("Succès ajax (resultat : OK) : "+percent_progressbar);
$(".progression").html(nb_photos_imported+" / "+nbphotos);
} else {
finish=true;
$("#text_result").html(ajax_done);
return false;
}
} else {
// ajax error => exit the while
console.info("Ajax execution error "+nb_photos_imported);
return false;
}
} // While
if (finish==true) {
$("#myprogressbar").hide('slow');
$('#text_result').html("Import of "+nb_photos_imported+" photos done.");
}
} else{
$("#text_result").html("No photo to import.");
$("#myprogressbar").hide(10);
$('#myform').show("slow");
}
}
});
}
});
}); // callback #text_result.show()
return false;
});
});
Here is my new code. The console log show the progression of the percentage, the photos are imported, but I still have the display at the end. If I put a breakpoint with me debugging tool somewhere in the loop, the display is refreshing and everything is OK...
$(function () {
$("#myprogressbar").show();
var RetourNbPhotos = "";
var RetourImported = "";
var fini = false;
var percent_progressbar = 0;
var nb_photos_imported = 0;
var datas = desvariables; // datas sent with ajax
// Number of photos to import
function NbPhotoAjax() {
return $.ajax({
type: 'POST',
async: false,
url: '/boutique/modules/importimageswithiptc/ajax-nbphotos.php',
data: 'chem=$cheminimport',
success: function (nbphotos) {
RetourNbPhotos = nbphotos;
}
});
}
// Photo Ajax Import
function ImportPhotoAjax() {
$("#text_result").html("Import in progress : <span class='progression'>0/0</span>").show();
// RetourImported = "";
return $.ajax({
type: 'GET',
async: false,
url: '/boutique/modules/importimageswithiptc/ajax-traitement.php',
data: datas,
success: function (resultat) {
RetourImported = resultat;
}
});
}
$("#myprogressbar").progressbar({
value: percent_progressbar
});
$('#generator').submit(function () {
$('#generator').hide();
if (jQuery.trim($("#id_product_src").val()).length != 0) {
$.when(NbPhotoAjax()).then(function () {
if (RetourNbPhotos > 0) {
while (nb_photos_imported < RetourNbPhotos) {
$.when(ImportPhotoAjax()).then(function () {
nb_photos_imported++;
if (RetourImported == "ok") {
percent_progressbar = Math.floor(nb_photos_imported * 100 / RetourNbPhotos);
$("#myprogressbar").progressbar("option", "value", percent_progressbar);
console.info("Success : " + percent_progressbar + "%");
$(".progression").html(nb_photos_imported + " / " + RetourNbPhotos);
} else {
fini = true;
$("#text_result").html("ajax_reussi");
return false;
}
}).fail(function () {
// ajax error => exit the while
console.info("Ajax execution error " + nb_photos_imported);
return false;
});
} // While
if (fini == true) {
$("#myprogressbar").hide('slow');
$('#text_result').html("Import of " + nb_photos_imported + " photos done.");
}
} else {
$("#text_result").html("No photo to import.");
$("#myprogressbar").hide(10);
$('#generator').show("slow");
}
});
}
return false;
});
});
Is there a way to keep the impromptu dialog box displayed during a post?
Here's the javascript code
$('#linkPostTest').click(function() {
openprompt();
});
function openprompt() {
var temp = {
state0: {
html: 'Are you sure you want to post?<br />',
buttons: { Yes: true, No: false },
focus: 1,
submit: function(v, m, f) {
if (v) {
var form = $('frmPostTest');
$.ajax(
{
type: 'POST',
url: '/Path/TestPost',
data: form.serialize(),
success: function(data) {
// I realize I could check "data"
// for true...just have not
// implemented that yet....
$.prompt.goToState('state1');
//$.prompt('Test was successful!');
},
error: function() {
$.prompt.goToState('state2');
//$.prompt('Test was not successful.');
}
}
);
return true;
}
else {
//$.prompt.goToState('state1'); //go forward
return false;
}
}
},
state1: {
html: 'Test was successful!',
buttons: { Close: 0 },
focus: 0,
submit: function(v, m, f) {
if (v === 0) {
$.prompt.close();
}
}
},
state2: {
html: 'Test was not successful.<br />',
buttons: { Close: 0 },
submit: function(v, m, f) {
if (v === 0) {
$.prompt.close();
}
}
}
};
$.prompt(temp);
}
The controller does this
[AcceptVerbs(HttpVerbs.Post)]
public bool TestPost()
{
// runs some code that saves some data...
// this works fine
bool updated = functionThatSavesCode();
return updated;
}
After I click Yes when the 'Are you sure you want to post?' impromptu dialog is displayed... it disappears...How can I make it stay displayed?
OK got it to work...I'm really impressed with the impromptu plug-in and jQuery!
Two of the things I did differently to get this to work was to add the two
return false;
statements under the state0 block and...
to set the the ajax call to
async: false,
Here's the new javascript:
$('#linkTestPost').click(function() {
TestPost();
});
function TestPost() {
var temp = {
state0: {
html: 'Are you sure you want to post?<br />',
buttons: { Yes: true, No: false },
focus: 1,
submit: function(v, m, f) {
if (v) {
if (PostView() === true) {
$.prompt.goToState('state1');
// the line below was missing from my original attempt
return false;
}
else {
$.prompt.goToState('state2');
// the line below was missing from my original attempt
return false;
}
}
else {
return false;
}
}
},
state1: {
html: 'Test Post was successful!',
buttons: { Close: 0 },
focus: 0,
submit: function(v, m, f) {
if (v === 0) {
$.prompt.close();
}
}
},
state2: {
html: 'Test Post was not successful',
buttons: { Close: 0 },
submit: function(v, m, f) {
if (v === 0) {
$.prompt.close();
}
}
}
};
$.prompt(temp);
}
function PostView() {
var form = $('frmTestPost');
var postSuccess = new Boolean();
$.ajax(
{
type: 'POST',
url: '/Path/TestPost',
data: form.serialize(),
// the line below was missing from my original attempt
async: false,
success: function(data) {
postSuccess = true;
},
error: function() {
postSuccess = false;
}
});
return postSuccess;
}