I'm using Kendo UI Mobile via Icenium Extension for Visual Studio. I'm very new at this, but I'm stumbling along. I've written a method (called popDataSource) in a view that gets some data (reads the names of files in a folder) and returns those file names. The method works perfectly if I wire it up to a button click event, but what I really want is for the method to be called when the page first loads. I've tried setting data-show=popDataSource and even data-after-show=popDataSource, but when I do that I get the error Object [object Object] has no method 'set' when I try to return the data. I'm also not that well versed in javascript, which I'm sure isn't helping me any.
Here's my code:
Snippet from index.html:
<div id="tabstrip-listSonicImages" data-role="view" data-title="Sonic Images List" data-model="app.listSonicImagesService.viewModel"
data-after-show="app.listSonicImagesService.viewModel.popDataSource">
<div data-role="content" class="view-content">
<div data-role="scroller">
<div class="buttonArea">
<a id="btnShowList" data-role="button" data-bind="click: popDataSource"
class="login-button">Display List</a>
</div>
<ul class="forecast-list" data-role="listview" data-bind="source: sonicImagesDataSource" data-template="sonic-image-list-template">
</ul>
</div>
</div>
</div>
<script type="text/x-kendo-tmpl" id="sonic-image-list-template">
<a data-role="listview-link" href="\#tabstrip-playSonicImage?fileName=${fileName}">${fileName}</a>
</script>
listiconimages.js
(function(global) {
var SonicImageListViewModel,
app = global.app = global.app || {};
SonicImageListViewModel = kendo.data.ObservableObject.extend({
popDataSource: function () {
var that = this;
var listSI = new Array();
try{
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0,
function (fileSys) {
fileSys.root.getDirectory("SIData", { create: true, exclusive: false},
function (dataDirEntry) {
var directoryReader = dataDirEntry.createReader ();
directoryReader.readEntries(
function (entries) {
var rows = entries.length;
for (i = 0; i < rows; i++) {
var fName = entries[i].name;
listSI[i] = { "fileName": fName, "image": "xxx" };
}
},
function (error) {
alert("error: " + error.code);
}
);
},
null);
},
null
);
var dataSource = new kendo.data.DataSource(
{
data: listSI,
filter: { field: "fileName", operator: "endswith", value: ".simg" }
}
);
that.set("sonicImagesDataSource", dataSource);
} catch (ex) {
alert(ex.message);
}
}
});
app.listSonicImagesService = {
viewModel: new SonicImageListViewModel()
};
}
)(window);
app.js
(function (global) {
var mobileSkin = "",
app = global.app = global.app || {};
document.addEventListener("deviceready", function () {
app.application = new kendo.mobile.Application(document.body, { layout: "tabstrip-layout" });
}, false);
app.changeSkin = function (e) {
if (e.sender.element.text() === "Flat") {
e.sender.element.text("Native");
mobileSkin = "flat";
}
else {
e.sender.element.text("Flat");
mobileSkin = "";
}
app.application.skin(mobileSkin);
};
})(window)
As I said, I'm new to Icenium and Kendo, and my javascript knowledge is limited, so I'm not quite sure where the answer lies. Any help would be greatly appreciated.
Thanks
Related
Good morning. I am new to the coding world, so my skills growing daily. I am trying to activate a SharePoint 2013 list workflow by using a button and Javascript. I know there are plenty of examples available, and to be honest, I'm a bit embarrassed about not being able to figure this out myself. All the codes that I have seen to date however have initiation variables in them, but my workflow doesn't. I'm at a loss for how to alter the examples to exclude having initiation variables. Please help. Example code I have looked at:
http://ranaictiu-technicalblog.blogspot.com/2013/06/sharepoint-2013-start-workflow-with.html
https://www.codeproject.com/Articles/607127/Using-SharePoint-2013-Workflow-Services-JS-API#example5
https://sharepoint.stackexchange.com/questions/236329/start-sharepoint-designer-workflow-2013-using-javascript
I used the following code from first link:
//dialog element to show during processing
var dlg = null;
//Subscription id - Workflow subscription id
//list item id for which to start workflow. If site workflow, then send null for itemId
function StartWorkflow(subscriptionId, itemId) {
showInProgressDialog();
var ctx = SP.ClientContext.get_current();
var wfManager = SP.WorkflowServices.WorkflowServicesManager.newObject(ctx, ctx.get_web());
var subscription = wfManager.getWorkflowSubscriptionService().getSubscription(subscriptionId);
ctx.load(subscription, 'PropertyDefinitions');
ctx.executeQueryAsync(
function (sender, args) {
var params= new Object();
//Find initiation data to be passed to workflow.
var formData = subscription.get_propertyDefinitions()["FormData"];
if (formData != null && formData != 'undefined' && formData != "") {
var assocParams = formData.split(";#");
for (var i = 0; i < assocParams.length; i++) {
params[assocParams[i]] = subscription.get_propertyDefinitions()[assocParams[i]];
}
}
if (itemId) {
wfManager.getWorkflowInstanceService().startWorkflowOnListItem(subscription, itemId, params);
}
else {
wfManager.getWorkflowInstanceService().startWorkflow(subscription, params);
}
ctx.executeQueryAsync(
function (sender, args) {
closeInProgressDialog();
},
function (sender, args) {
closeInProgressDialog();
alert('Failed to run workflow');
}
);
},
function (sender, args) {
closeInProgressDialog();
alert('Failed to run workflow');
}
);
}
function closeInProgressDialog() {
if (dlg != null) {
dlg.close();
}
}
function showInProgressDialog() {
if (dlg == null) {
dlg = SP.UI.ModalDialog.showWaitScreenWithNoClose("Please wait...", "Waiting for workflow...", null, null);
}
}
And inserted the following HTML to create the button.
<button onclick="function StartWorkflow('8E645164-959C-4358-B22C-47FDA93F7906',5)">Click Me</button>
I am 100% confident that my subscriptionId and my itemId are correct.
Please help.
Thank you.
My test code for your reference,it's just slightly different from your code:
<input type="button" id="test" value="Click Me" />
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script src="/_layouts/15/sp.workflowservices.js"></script>
<script>
$("#test").click(function(){
console.log(1)
SP.SOD.executeFunc('sp.js', 'SP.ClientContext', init);
function init() {
$.getScript(SP.Utilities.Utility.getLayoutsPageUrl('sp.js'), function () {
$.getScript(SP.Utilities.Utility.getLayoutsPageUrl('sp.workflowservices.js'), function () {
StartWorkflow("SubscriptionId","itemid","siteurl");
});
});
}
//dialog element to show during processing
var dlg = null;
//Subscription id – Workflow subscription id
//list item id for which to start workflow. If site workflow, then send null for itemId
//SiteURL – site collection where the workflow exists
function StartWorkflow(subscriptionId, itemId, SiteURL) {
showInProgressDialog();
var ctx = new SP.ClientContext(SiteURL);
var wfManager = SP.WorkflowServices.WorkflowServicesManager.newObject(ctx, ctx.get_web());
var subscription = wfManager.getWorkflowSubscriptionService().getSubscription(subscriptionId);
ctx.load(subscription, 'PropertyDefinitions');
ctx.executeQueryAsync(
function (sender, args) {
var params = new Object();
//Find initiation data to be passed to workflow.
var formData = subscription.get_propertyDefinitions()["FormData"];
if (formData != null && formData != 'undefined' && formData != "") {
var assocParams = formData.split(";#");
for (var i = 0; i < assocParams.length; i++) {
params[assocParams[i]] = subscription.get_propertyDefinitions()[assocParams[i]];
}
}
if (itemId) {
wfManager.getWorkflowInstanceService().startWorkflowOnListItem(subscription, itemId, params);
}
else {
wfManager.getWorkflowInstanceService().startWorkflow(subscription, params);
}
ctx.executeQueryAsync(
function (sender, args) {
closeInProgressDialog(SiteURL);
},
function (sender, args) {
closeInProgressDialog(SiteURL);
$('#msg')[0].innerHTML = "Woops – something went wrong, the document may have already been reviewed";
}
);
},
function (sender, args) {
closeInProgressDialog(SiteURL);
$('#msg')[0].innerHTML = "Woops – something went wrong, the document may have already been reviewed";
}
);
}
function closeInProgressDialog(SiteURL) {
if (dlg != null) {
dlg.close();
$('#msg')[0].innerHTML = "Thank you – you can now close the page";
}
}
function showInProgressDialog() {
if (dlg == null) {
dlg = SP.UI.ModalDialog.showWaitScreenWithNoClose("Please wait…", "Waiting for workflow…", null, null);
}
}
})
</script>
.controller('paymentsController', function ($scope, $localStorage, $log, $state, $window, $ionicModal, Payment, ItemList, SweetAlert) {
$scope.scanCard = function(){
var cardIOResponseFields = [
"card_type",
"redacted_card_number",
"card_number",
"expiry_month",
"expiry_year",
"cvv",
"zip"
];
var onCardIOComplete = function(response) {
for (var i = 0, len = cardIOResponseFields.length; i < len; i++) {
var field = cardIOResponseFields[i];
console.log(field + ": " + response[field]);
}
};
var onCardIOCancel = function() {
console.log("card.io scan cancelled");
};
var onCardIOCheck = function (canScan) {
console.log("card.io canScan? " + canScan);
var scanBtn = angular.element($("#scanBtn")).scope();
//var scanBtn = document.getElementById("scanBtn");
if (!canScan) {
scanBtn.innerHTML = "Manual entry";
}
};
CardIO.scan({
"collect_expiry": true,
"collect_cvv": false,
"collect_zip": false,
"shows_first_use_alert": true,
"disable_manual_entry_buttons": false
},
onCardIOComplete,
onCardIOCancel
);
CardIO.canScan(onCardIOCheck);
};
}
I installed a card reader plugin in my phonegap(i'm using ionic as a framework) the problem I'm having is that the plugin doesn't work. this is the plugin I'm using https://github.com/card-io/card.io-iOS-SDK-PhoneGap.
this is my view.
<button id="scanBtn" ng-click="scanCard()" class="button button-large button-block button-light">Scan Card</button>
when the user click on the #scanBtn it loads this script.
var cardIOResponseFields = [
"card_type",
"redacted_card_number",
"card_number",
"expiry_month",
"expiry_year",
"cvv",
"zip"
];
var onCardIOComplete = function(response) {
for (var i = 0, len = cardIOResponseFields.length; i < len; i++) {
var field = cardIOResponseFields[i];
console.log(field + ": " + response[field]);
}
};
var onCardIOCancel = function() {
console.log("card.io scan cancelled");
};
var onCardIOCheck = function (canScan) {
console.log("card.io canScan? " + canScan);
var scanBtn = angular.element($("#scanBtn")).scope();
//var scanBtn = document.getElementById("scanBtn");
if (!canScan) {
scanBtn.innerHTML = "Manual entry";
}
};
CardIO.scan({
"collect_expiry": true,
"collect_cvv": false,
"collect_zip": false,
"shows_first_use_alert": true,
"disable_manual_entry_buttons": false
},
onCardIOComplete,
onCardIOCancel
);
CardIO.canScan(onCardIOCheck);
};
my app doesn't work in my browser or using the phonegap app, but when i launch the ionic emulator only the entry to input the card form shows up and no camera loads to scan the card, which led me to believe the camera execution is failing.
When load the cardio on my browser i get the following console error:
ReferenceError: CardIO is not defined.
Try the same on device.
I got the same error on browser and it works well on the device. You could think of this as the camera / or contacts picker plugin - which will work only on device - and not on sim or browser.
All cordova plugins will throw an error when running on browsers or emulators. Always use them on devices and inside
$ionicPlatform.ready(function() { ... });
I have been working on an arcgis project for the last two weeks and I have ran into an issue with my upload shapefile function in my code. I keep getting an dom is undefined error and I don't know what to do.
Here is the code:
<div class="modal fade" id="UpdateShapefileForm" tabindex="-1" role="dialog" aria- labelledby="Set View" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<form enctype="multipart/form-data" method="post" id="uploadForm">
<div class="field">
<label class="file-upload">
<span><strong>Add File</strong></span>
<input type="file" name="file" id="inFile"/>
</label>
</div>
</form>
</div>
</div>
</div>
</div>
<script src="http://js.arcgis.com/3.9/"></script>
<script src="/static/js/mapping/mapobject.js" type="text/javascript"></script>
<script src="/static/js/mapping/mapmanager.js" type="text/javascript"></script>
<script type="text/javascript">
var map, toolbar;
var PROJECT_OUTLINE, PROJECT_FILL, PARCEL_OUTLINE, PARCEL_FILL, PLOT_OUTLINE, PLOT_FILL;
var toolbarEvent;
var mapManager = new MapManager();
var markerPictures = {
'project': '/static/assets/grnball.png',
'parcel': '/static/assets/bluball.png',
'plot': '/static/assets/redball.png'
}
require([
"esri/config",
"esri/InfoTemplate",
"esri/map",
"esri/request",
"esri/geometry/scaleUtils",
"esri/layers/FeatureLayer",
"esri/renderers/SimpleRenderer",
"esri/symbols/PictureMarkerSymbol",
"esri/symbols/SimpleFillSymbol",
"esri/symbols/SimpleLineSymbol",
"esri/symbols/SimpleMarkerSymbol",
"dojo/dom",
"dojo/json",
"dojo/on",
"dojo/parser",
"dojo/sniff",
"dojo/_base/array",
"esri/Color",
"dojo/_base/lang",
"dijit/layout/BorderContainer",
"dijit/layout/ContentPane",
"dojo/domReady!"
], function(
esriConfig, InfoTemplate, Map, request, scaleUtils, FeatureLayer,
SimpleRenderer, PictureMarkerSymbol, SimpleFillSymbol, SimpleLineSymbol, SimpleMarkerSymbol,
dom, JSON, on, parser, sniff, arrayUtils, Color, lang
) {
map = new Map("mapcanvas", {
center: [-56.049, 38.485],
zoom: 3,
basemap: "hybrid"
});
map.on("load", function() {
$("#waiting_img").hide();
createToolbar();
setConstants();
parser.parse();
var portalUrl = "http://www.arcgis.com";
esriConfig.defaults.io.proxyUrl = "/proxy";
on(dom.byId("uploadForm"), "change", function (event) {
var fileName = event.target.value.toLowerCase();
if (sniff("ie")) { //filename is full path in IE so extract the file name
var arr = fileName.split("\\");
fileName = arr[arr.length - 1];
}
if (fileName.indexOf(".zip") !== -1) {//is file a zip - if not notify user
generateFeatureCollection(fileName);
}
else {
dom.byId('upload-status').innerHTML = '<p style="color:red">Add shapefile as .zip file</p>';
}
map.graphics.on("click", function(evt) {
console.log("geometry type: " + evt.graphic.geometry.type);
if(evt.graphic.geometry.type == "polygon")
{
selectPolygon();
}
else if(evt.graphic.geometry.type == "multipoint" || evt.graphic.geometry.type == "point")
{
selectMarker();
}
});
});
});
});
function generateFeatureCollection (fileName) {
var name = fileName.split(".");
//Chrome and IE add c:\fakepath to the value - we need to remove it
//See this link for more info: http://davidwalsh.name/fakepath
name = name[0].replace("c:\\fakepath\\", "");
dom.byId('upload-status').innerHTML = '<b>Loading </b>' + name;
//Define the input params for generate see the rest doc for details
//http://www.arcgis.com/apidocs/rest/index.html?generate.html
var params = {
'name': name,
'targetSR': map.spatialReference,
'maxRecordCount': 1000,
'enforceInputFileSizeLimit': true,
'enforceOutputJsonSizeLimit': true
};
//generalize features for display Here we generalize at 1:40,000 which is approx 10 meters
//This should work well when using web mercator.
var extent = scaleUtils.getExtentForScale(map, 40000);
var resolution = extent.getWidth() / map.width;
params.generalize = true;
params.maxAllowableOffset = resolution;
params.reducePrecision = true;
params.numberOfDigitsAfterDecimal = 0;
var myContent = {
'filetype': 'shapefile',
'publishParameters': JSON.stringify(params),
'f': 'json',
'callback.html': 'textarea'
};
//use the rest generate operation to generate a feature collection from the zipped shapefile
request({
url: portalUrl + '/sharing/rest/content/features/generate',
content: myContent,
form: dom.byId('uploadForm'),
handleAs: 'json',
load: lang.hitch(this, function (response) {
if (response.error) {
errorHandler(response.error);
return;
}
var layerName = response.featureCollection.layers[0].layerDefinition.name;
dom.byId('upload-status').innerHTML = '<b>Loaded: </b>' + layerName;
addShapefileToMap(response.featureCollection);
}),
error: lang.hitch(this, errorHandler)
});
}
function errorHandler (error) {
dom.byId('upload-status').innerHTML =
"<p style='color:red'>" + error.message + "</p>";
}
function addShapefileToMap (featureCollection) {
//add the shapefile to the map and zoom to the feature collection extent
//If you want to persist the feature collection when you reload browser you could store the collection in
//local storage by serializing the layer using featureLayer.toJson() see the 'Feature Collection in Local Storage' sample
//for an example of how to work with local storage.
var fullExtent;
var layers = [];
arrayUtils.forEach(featureCollection.layers, function (layer) {
var infoTemplate = new InfoTemplate("Details", "${*}");
var featureLayer = new FeatureLayer(layer, {
infoTemplate: infoTemplate
});
//associate the feature with the popup on click to enable highlight and zoom to
featureLayer.on('click', function (event) {
map.infoWindow.setFeatures([event.graphic]);
});
//change default symbol if desired. Comment this out and the layer will draw with the default symbology
fullExtent = fullExtent ?
fullExtent.union(featureLayer.fullExtent) : featureLayer.fullExtent;
layers.push(featureLayer);
});
map.addLayers(layers);
map.setExtent(fullExtent.expand(1.25), true);
dom.byId('upload-status').innerHTML = "";
}
function setConstants() {
PROJECT_OUTLINE = new esri.Color(([0,255,0]));
PROJECT_FILL = new esri.Color([0,255,0,0.5]);
PARCEL_OUTLINE = new esri.Color(([0,0,255]));
PARCEL_FILL = new esri.Color([0,0,255,0.5]);
PLOT_OUTLINE = new esri.Color(([255,0,0]));
PLOT_FILL = new esri.Color([255,0,0,0.5]);
}
function createToolbar() {
toolbar = new esri.toolbars.Draw(map);
}
function drawEnd(geometry, pType, outline, fill) {
toolbar.deactivate();
map.showZoomSlider();
console.log("geometry: " + geometry.type);
var text_symbol = null;
switch (geometry.type) {
case "point":
case "multipoint":
symbol = new esri.symbol.PictureMarkerSymbol(markerPictures[pType], 13, 13);
break;
default:
symbol = new esri.symbol.SimpleFillSymbol();
symbol.setColor(fill);
symbol.setOutline(new esri.symbol.SimpleLineSymbol(esri.symbol.SimpleLineSymbol.STYLE_SOLID, outline, 2));
break;
}
var graphic = new esri.Graphic(geometry, symbol);
map.graphics.add(graphic);
var map_obj = new MapObject(pType, pType, graphic, geometry.type);
mapManager.Add(map_obj);
if(toolbarEvent != null)
{
toolbarEvent.remove();
toolbarEvent = null;
}
}
error happens specifically on this line:
dom.byId('upload-status').innerHTML = '<b>Loading </b>' + name;
You've got a simple scoping error - the variable dom is declared as an argument to this function:
require([...,"dojo/dom",...], function(...,dom,...) {...});
Your next function declaration is this:
function generateFeatureCollection (fileName) {
...
dom.byId(...);
...
}
but the variable dom is not defined in this function, so you can't use it here. You need to either pass it to the function:
function generateFeatureCollection (fileName, dom) {...}
which gets very clumsy if you're going to pass it around to every function, assign the dom variable in your require function to a global variable, or redeclare it where you need it. From the docs:
require(["dojo/dom"], function(dom){
// fetch a node by id="someNode"
var node = dom.byId("someNode");
});
I have a URL route that has a parameter whose value is not known ahead of time when the page is loaded. For example:
/read/book/page/:page
But when the user is selection screen they get to type in which page number they want to start on then click submit. Is it possible to catch this form submission and place it in the URL? Normally there is a question mark (?) right because its a GET request. But Backbone how can backbone catch that?
Demo:
http://jsfiddle.net/vpetrychuk/PT2tU/
JS:
var Model = Backbone.Model.extend({
url : function () {
return 'http://fiddle.jshell.net/echo/json?page=' + this.get('page');
},
// remove it
parse : function (response) {
response || (response = {});
response.justToTriggerChangeEvent = Math.random();
return response;
},
getPageContent : function () {
return 'Here should be page a content for page #' + this.get('page');
}
});
var View = Backbone.View.extend({
el : '[data-page]',
events : {
'submit' : 'submit'
},
initialize : function () {
this.listenTo(this.model, 'change', this.showPage);
},
showPage : function () {
this.$('[data-page-content]').html(this.model.getPageContent());
},
submit : function (e) {
e.preventDefault();
var page = this.$('[data-page-num]').val();
if (page) {
app.navigate('read/book/page/' + page, true);
}
}
});
var Router = Backbone.Router.extend({
routes : {
'read/book/page/:page' : 'page'
},
initialize : function (options) {
this.bookModel = options.bookModel;
},
page : function (page) {
this.bookModel.set('page', page);
this.bookModel.fetch();
}
});
var model = new Model();
var view = new View({model:model});
var app = new Router({bookModel:model});
Backbone.history.start();
HTML:
<div data-page>
<form>
<label><input type="text" data-page-num /></label>
<button type="submit">Submit</button>
</form>
<div data-page-content></div>
</div>
I'm using the following code to get google contacts name and phone number. Authorization page itself is not coming properly it shows error as "The page you requested is invalid". :( pls help me to solve this...
`
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript">
google.load("gdata", "1.x");
var contactsService;
function setupContactsService()
{
contactsService = new google.gdata.contacts.ContactsService('exampleCo-exampleApp-1.0');
}
function logMeIn() {
var scope = 'https://www.google.com/m8/feeds';
var token = google.accounts.user.login(scope);
}
function initFunc() {
setupContactsService();
logMeIn();
getMyContacts();
}
function checkLoggedIn(){
scope = "https://www.google.com/m8/feeds";
var token = google.accounts.user.checkLogin(scope);
if(token != "")
return true;
else
return false;
}
function getMyContacts() {
var contactsFeedUri = 'https://www.google.com/m8/feeds/contacts/default/full';
var query = new google.gdata.contacts.ContactQuery(contactsFeedUri);
//We load all results by default//
query.setMaxResults(10);
contactsService.getContactFeed(query, handleContactsFeed, ContactsServiceInitError);
}
//Gets the contacts feed passed as parameter//
var handleContactsFeed = function(result) {
//All contact entries//
entries = result.feed.entry;
for (var i = 0; i < entries.length; i++) {
var contactEntry = entries[i];
var telNumbers = contactEntry.getPhoneNumbers();
var title = contactEntry.getTitle().getText();
}
}
</script>
<body>
<input type="submit" value="Login to Google" id="glogin" onclick="initFunc();">
</body>`
Thanks
It looks like you are trying to use the Google Contacts 1.X API. That's been deprecated. Look at the JavaScript examples for the Google 3.X API and see if that helps.
You can try this example
var config = {
'client_id': 'Client ID',
'scope': 'https://www.google.com/m8/feeds'
};
inviteContacts = function() {
gapi.auth.authorize($scope.config, function() {
fetch(gapi.auth.getToken());
});
}
function fetch(token) {
$.get("https://www.google.com/m8/feeds/contacts/default/full?access_token=" + token.access_token + "&alt=json", function(response) {
console.log(response);
//console.log(response.data.feed.entry);
});
}
Don't forget to add <script src="https://apis.google.com/js/client.js"></script> into your html file. Good Luck!