Is it possible to have many busyIndicators depending on context?
I tried with 4, but it doesn't work (only the last busyIndicator seems to be used, and can't be hidden):
Here's the code:
var myBusyIndicator1;
var myBusyIndicator2;
var myBusyIndicator3;
var myBusyIndicator4;
wlCommonInit(){
myBusyIndicator1 = new WL.BusyIndicator('content', {text : 'Loading data 1'});
myBusyIndicator2 = new WL.BusyIndicator('content', {text : 'Loading data 2'});
myBusyIndicator3 = new WL.BusyIndicator('content', {text : 'Loading data 3'});
myBusyIndicator4 = new WL.BusyIndicator('content', {text : 'Loading data 4'});
}
$('#myPage').on('showpage', function(e, ui){
myBusyIndicator1.show(); // 'Loading data 4' is displayed in modal window
//do some stuff
myBusyIndicator1.hide(); // modal window still, and app is not responsive anymore
});
"Busy indicator is a singleton. If you create several busy indicators, show them and then hide of them - all will be hidden." - Anton (source)
You could try to wrap it in your own "singleton", for example:
var Busy = (function () {
var busyObject;
var _show = function (message, options) {
//If you're using WL v6.0,
//see: https://stackoverflow.com/q/18501456/186909
WL.ClientMessages.loading = message;
//Others version of WL may not require
//the line above or the message parameter.
busyObject = new WL.BusyIndicator('content', options);
busyObject.show();
};
var _hide = function () {
if (busyObject !== null) {
busyObject.hide();
busyObject = null;
}
//else no busy indicator to hide
};
return {
show: _show,
hide: _hide
};
}());
//Usage:
Busy.show('message1', options1);
//Later...
Busy.hide();
//Later...
Busy.show('message2', options2);
//Later...
Busy.hide();
I did not test the code above, it's just meant to give the reader ideas, not to be copy/pasted into a project.
Related
When ever i try to save special character like ä,ö to my DojoGrid which loads and saves data via xe:restService the character get messedup,
When ever i end the grid directly it save ok, but when ever i work on it in the background and save it, it get messedup.below is the script on my button
var args = {
onComplete: function() {},
onError: function() { alert('Update error'); }
}
var grid = dijit.byId('#{id:grid}');
var selectedIDs =grid.selection.getSelected();
var store = dataGrid.store;
var Index = grid.selection.selectedIndex;
if(Index != null){
var curEntry = dataGrid.getItem(Index);
var nextEntry = dataGrid.getItem(Index-1);
currentViewIndex = store.getValue(curEntry,"ViewIndex");
nextViewIndex = store.getValue(nextEntry,"ViewIndex");
store.setValue(curEntry, 'ViewIndex',nextViewIndex);
store.setValue(nextEntry, 'ViewIndex',currentViewIndex);
grid.update();
restService1.save(args)
XSP.partialRefreshPost("#{id:gridDiv}",{});
}
Scenario: In our application a user can create a invoice by filling in certain fields on a Knockout view. This invoice can be previewed, via another Knockout page. I want to use the preview url within our PDF creator (EVOPdf), so we can provide the user with a PDF from this invoice.
To preview the invoice we load the data (on document ready) via an ajax-request:
var InvoiceView = function(){
function _start() {
$.get("invoice/GetInitialData", function (response) {
var viewModel = new ViewModel(response.Data);
ko.applyBindings(viewModel, $("#contentData").get(0));
});
};
return{
Start: _start
};
}();
My problem is within the data-binding when the PDF creator is requesting the url: the viewModel is empty. This makes sense because the GetInitialData action is not called when the PDF creator is doing the request. Calling this _start function from the preview page directly at the end of the page does not help either.
<script type="text/javascript">
$(document).ready(function() {
InvoiceView.Start();
});
</script>
Looking at the documentation of EvoPdf, JavaScript should be executed, as the JavaScriptEnabled is true by default: http://www.evopdf.com/api/index.aspx
How could I solve this, or what is the best approach to create an pdf from a knockout view?
Controller action code:
public FileResult PdfDownload(string url)
{
var pdfConverter = new PdfConverter();
// add the Forms Authentication cookie to request
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
pdfConverter.HttpRequestCookies.Add(
FormsAuthentication.FormsCookieName,
Request.Cookies[FormsAuthentication.FormsCookieName].Value);
}
var pdfBytes = pdfConverter.GetPdfBytesFromUrl(url);
return new FileContentResult(pdfBytes, "application/pdf");
}
Javascript:
var model = this;
model.invoiceToEdit = ko.observable(null);
model.downloadInvoice = function (invoice) {
model.invoiceToEdit(invoice);
var url = '/invoice/preview';
window.location.href = '/invoice/pdfDownload?url=' + url;
};
The comment of xdumaine prompted me to think into another direction, thank you for that!
It did take some time for the Ajax request to load, but I also discovered some JavaScript (e.g. knockout binding) errors along the way after I put a ConversionDelay on the pdf creator object
pdfConverter.ConversionDelay = 5; //time in seconds
So here is my solution for this moment, which works for me now:
To start the process a bound click event:
model.downloadInvoice = function (invoice) {
var url = '/invoice/preview/' + invoice.Id() + '?isDownload=true';
window.open('/invoice/pdfDownload?url=' + url);
};
which result in a GET resquest on the controller action
public FileResult PdfDownload(string url)
{
var pdfConverter = new PdfConverter { JavaScriptEnabled = true };
// add the Forms Authentication cookie to request
if (Request.Cookies[FormsAuthentication.FormsCookieName] != null)
{
pdfConverter.HttpRequestCookies.Add(
FormsAuthentication.FormsCookieName,
Request.Cookies[FormsAuthentication.FormsCookieName].Value);
}
pdfConverter.ConversionDelay = 5;
var absolutUrl = ToAbsulte(url);
var pdfBytes = pdfConverter.GetPdfBytesFromUrl(absolutUrl);
return new FileContentResult(pdfBytes, "application/pdf");
}
The Pdf creator is requesting this action on the controller, with isDownload = true (see bound click event):
public ActionResult Preview(string id, bool isDownload = false)
{
return PartialView("PdfInvoice", new InvoiceViewModel
{
IsDownload = isDownload,
InvoiceId = id
});
}
Which returns this partial view:
PartialView:
// the actual div with bindings etc.
#if (Model.IsDownload)
{
//Include your javascript and css here if needed
#Html.Hidden("invoiceId", Model.InvoiceId);
<script>
$(document).ready(function () {
var invoiceId = $("#invoiceId").val();
DownloadInvoiceView.Start(invoiceId);
});
</script>
}
JavaScript for getting the invoice and apply the knockout bindings:
DownloadInvoiceView = function() {
function _start(invoiceId) {
$.get("invoice/GetInvoice/" + invoiceId, function(response) {
var viewModel = new DownloadInvoiceView.ViewModel(response.Data);
ko.applyBindings(viewModel, $("#invoiceDiv").get(0));
});
};
return {
Start: _start
};
}();
DownloadInvoiceView.ViewModel = function (data) {
var model = this;
var invoice = new Invoice(data); //Invoice is a Knockout model
return model;
};
I am trying to use your api in a custom app with imported users.
Everything works fine (auth_token, login, call initiation) , but when the callee should get a response and add the remotestream nothing happens. no errors get shown in the console.
I would appreciate if someone takes a look at the code and tells me what i m missing.
I tried the vline demo at https://freeofcinema.vline.com and it worked with the same browsers and conditions between the two computers. In my app it is a http , but i tried it also with https, and the same problem came up. This is some simplified code i used to test the api.
var Streams = [];
var Vsession = null;
var Vline = (function(){
var Client;
var authToken;
var service_id = 'freeofcinema';
var profile = null;
var Person;
var Calls = [];
var onMessage = function(event){
//alert('message');
var msg = event.message, sender = msg.getSender();
console.log(sender.getDisplayName() +'sais: '+ msg.getBody());
console.log(event);
}
var onMediaSession = function(event){
console.log(event);
var mediaSession = event.target;
InitSession(mediaSession);
}
function Call(mediaSession) {
mediaSession.
on('change', alert_info);
}
function alert_info(b){
console.log(b);
}
function InitSession(mediaSession){
mediaSession.on('mediaSession:addRemoteStream', function(event) {
alert('addRemoteStream');
});
mediaSession.on('mediaSession:addLocalStream', function(event) {
alert('addLocalStream');
});
mediaSession.on('mediaSession:removeLocalStream mediaSession:removeRemoteStream', function(event) {
console.log('removedStream');
});
Calls.push(new Call(mediaSession));
}
return {
init : function(){
if(profile){
return;
}
profile = {
"displayName" : //some getusrname function...
};
$.post('vtoken.php',{//get auth token
id : Comm.Voip_user().id
},function(data){
authToken = data;
Client = vline.Client.create({
"serviceId": service_id,
"ui" : true
});
Client.on('recv:im', onMessage , this);
Client.on('add:mediaSession', onMediaSession, this);
Client.on('login', function(e) {
Vsession = e.target;
//alert('loged in');
});
Client.login(service_id, profile, authToken);
});
},
getPerson : function(id){//id of user to call
if(Vsession){
Vsession.getPerson(id).
done(function(person){
Person = person;
Vsession.startMedia(id);
});
}
}
}
}());
Thank you for your response.
I tried with one user from the app, and another from the https://freeofcinema.vline.com, and the same problem occured. Also the call (in pending state) gets terminated after a short while..
When passing ui:true when creating the client, you do not have to handle the media sessions yourself. Just comment the line Client.on('add:mediaSession', onMediaSession, this); and it should just work.
I am reading through titanium best practises and i was wondering why this doesnt appear to work can some one tell me whats changed with the api?
https://wiki.appcelerator.org/display/guides/Mobile+Best+Practices
ui/ToggleBox.js - A custom check box
function ToggleBox(onChange) {
this.view = Ti.UI.createView({backgroundColor:'red',height:50,width:50});
//private instance variable
var active = false;
//public instance functions to update internal state, execute events
this.setActive = function(_active) {
active = _active;
this.view.backgroundColor = (active) ? 'green' : 'red';
onChange.call(instance);
};
this.isActive = function() {
return active;
};
//set up behavior for component
this.view.addEventListener('click', function() {
this.setActive(!active);
});
}
exports.ToggleBox = ToggleBox;
Sample usage in app.js
var win = Ti.UI.createWindow({backgroundColor:'white'});
var ToggleBox = require('ui/ToggleBox').ToggleBox;
var tb = new ToggleBox(function() {
alert('The check box is currently: '+this.isActive());
});
tb.view.top = 50;
tb.view.left = 100;
win.add(tb.view);
it doesn't seem to want to return the setActive method when called from the add event listener?
The "this" in your click listener isn't what you're expecting it to be. (It's probably the view.) Because your function is already the ToggleBox context, the easiest solution is to just use a direct reference to setActive. "this." is only necessary for the API you're exposing for other code.
function ToggleBox(onChange) {
var view = this.view = Ti.UI.createView({backgroundColor:'red',height:50,width:50});
//private instance variable
var active = false;
//public instance functions to update internal state, execute events
var setActive = this.setActive = function(_active) {
active = _active;
view.backgroundColor = (active) ? 'green' : 'red';
onChange.call(instance);
};
var isActive = this.isActive = function() {
return active;
};
//set up behavior for component
view.addEventListener('click', function() {
setActive(!active);
});
}
exports.ToggleBox = ToggleBox;
I'm running a website, where I'd like to upload files with Drag 'n Drop, using the HTML5 File API and FileReader. I have successfully managed to create a new FileReader, but I don't know how to upload the file. My code (JavaScript) is the following:
holder = document.getElementById('uploader');
holder.ondragover = function () {
$("#uploader").addClass('dragover');
return false;
};
holder.ondragend = function () {
$("#uploader").removeClass('dragover');
return false;
};
holder.ondrop = function (e) {
$("#uploader").removeClass('dragover');
e.preventDefault();
var file = e.dataTransfer.files[0],
reader = new FileReader();
reader.onload = function (event) {
//I shoud upload the file now...
};
reader.readAsDataURL(file);
return false;
};
I also have a form (id : upload-form) and an input file field (id : upload-input).
Do you have any ideas?
P.S. I use jQuery, that's why there is $("#uploader") and others.
Rather than code this from scratch, why not use something like html5uploader, which works via drag n drop (uses FileReader etc.): http://code.google.com/p/html5uploader/
EDIT: apparently we respondents are supposed to tend to our answers forever more, for fear for down-votes. The Google Code link is now dead (four years later), so here's a jQuery plugin that is very similar: http://www.igloolab.com/jquery-html5-uploader/
You'll want to extract the base64 encoded file contents and ajax them over tot the server.
JavaScript
var extractBase64Data;
extractBase64Data = function(dataUrl) {
return dataUrl.substring(dataUrl.indexOf(',') + 1);
};
// Inside the ondrop event
Array.prototype.forEach.call(event.dataTransfer.files, function(file) {
var reader;
if (!file.type.match(options.matchType)) {
return;
}
reader = new FileReader();
reader.onload = function(event) {
var contentsBase64;
if (event.target.readyState === FileReader.DONE) {
contentsBase64 = extractBase64Data(event.target.result);
return $.post(someURL, {
contentsBase64: contentsBase64
});
}
};
reader.readAsDataURL(file);
});
CoffeeScript
extractBase64Data = (dataUrl) ->
dataUrl.substring(dataUrl.indexOf(',') + 1)
# Inside the ondrop event
Array::forEach.call event.dataTransfer.files, (file) ->
return unless file.type.match(options.matchType)
reader = new FileReader()
reader.onload = (event) ->
if event.target.readyState == FileReader.DONE
contentsBase64 = extractBase64Data(event.target.result)
$.post someURL,
contentsBase64: contentsBase64
reader.readAsDataURL(file)