in ic3Report.html file, is it possible to get the user name in the callback function ?
var options = {
root: "ic3-report/app/",
rootLocal: "ic3-report/app-local/",
rootVersion: "_IC3_ROOT_VERSION_",
callback: function () {
$('#intro').remove();
window.ic3application = ic3.startReport(
{
<!-- ic3-start-report-options (DO NOT REMOVE - USED TO GENERATE FILES) -->
});
// get user name here !
}
};
in order to gather current user information you should setup GVI configuration. It could be done with appropriate method:
var options = {
root: "ic3-report/app/",
rootLocal: "ic3-report/app-local/",
rootVersion: "_IC3_ROOT_VERSION_",
callback: function () {
$('#intro').remove();
var ic3reporting = new ic3.Reporting(
{
noticesLevel: ic3.NoticeLevel.INFO,
dsSettings: {
url: GVI_URL
}
});
ic3reporting.setupGVIConfiguration(function () {
var userName = ic3reporting.userName();
})
}
};
After that user information will be available inside context. See code above for details.
Update
A more robust solution is adding the code to the local files that are not overwritten with a new version of the reporting. You can use ic3bootstrapLocal function in Admin > Common JS configuration.
function ic3bootstrapLocal(options) {
var ic3reporting = new ic3.Reporting({
noticesLevel: ic3.NoticeLevel.INFO,
});
ic3reporting.setupGVIConfiguration(function(){
ic3reporting.userName()
options.callback && options.callback();
});
}
Related
My question is somewhat similar to followin unanswered question. (Not sure though)
Sitecore 8 SPEAK: Getting an Error When calling a Method in JS File
I am using Sitecore8
On my page there is a button and on its click event I want to call add() of custom datasource component.
Layout:
JS Code for the Page:
define(["sitecore"], function (Sitecore) {
var JsonListPage = Sitecore.Definitions.App.extend({
initialized: function () {
alert('Inside Json PageList Init');
},
loadData: function () {
alert('Button clicked');
app.add();
}
});
return JsonListPage;
});
JS Code for the custom datasource component:
define(["sitecore"], function (Sitecore) {
var model = Sitecore.Definitions.Models.ControlModel.extend({
initialize: function (options) {
this._super();
this.set("json", null);
alert('Inside Jsondatasource Init');
},
add: function (data) {
var json = this.get("json");
if (json === null)
json = new Array();
// this is done because array.push changes the array to an object which then do no work on the SPEAK listcontrol.
var newArray = new Array(json.length + 1);
for (var i = json.length - 1; i >= 0; i--)
newArray[i + 1] = json[i];
newArray[0] = data;
this.set("json", newArray);
}
});
var view = Sitecore.Definitions.Views.ControlView.extend({
initialize: function (options) {
this._super();
this.model.set("json", null);
}
});
Sitecore.Factories.createComponent("JsonDatasource", model, view, ".x-sitecore-jsondatasource");
});
.cshtml for Custom component:
#using Sitecore.Mvc
#using Sitecore.Mvc.Presentation
#using Sitecore.Web.UI.Controls.Common.UserControls
#model RenderingModel
#{
var userControl = Html.Sitecore().Controls().GetUserControl(Model.Rendering);
userControl.Requires.Script("client", "JsonDatasource.js");
userControl.Class = "x-sitecore-jsondatasource";
userControl.Attributes["type"] = "text/x-sitecore-jsondatasource";
userControl.DataBind = "Json: json";
var htmlAttributes = userControl.HtmlAttributes;
}
<div #htmlAttributes>
am here again
</div>
When the page loads:
It shows alert from Custom components Init
Then shows alert from host page's Init
On button click it shows the alert and after that gives error on "app".
There is some bit which I am missing.. any help would be appreciated.. Please let me know if you need anymore inputs.
Thanks in advance!
app is only available in debug mode so id avoid using that, use "this" instead.
From your code example it appears that you are calling app.Add(), There is no Add function on your pageCode, this is what your code is doing. Instead you need to access your components's Add Method.
Instead to access events within your component you want to call the function like this:
this.ComponentID.Add();
I have an example of a custom SPEAK component here you can refer to for how to create the component. https://github.com/sobek1985/MikeRobbinsSPEAKRichTextEditor
From the code is seems your creating a JSON datasource, there is an example by Anders here http://laubplusco.net/creating-simple-sitecore-speak-json-datasource/
I'm developing a Sails.js application and I want to extend all views with custom data and functions.
What would be the best course of action to do so?
I've tried to create a policy to do so, but policies are only applied to routes with controllers.
Custom data
You can use a custom hook in order to achieve that.
Create a file at the specified path: api/hooks/viewsGlobals/index.js with the following content:
module.exports = function viewsGlobals (sails) {
return {
routes: {
before: {
// This middleware will be executed for every request.
'*': function (req, res, next) {
// Using condition to filter out static file requests.
if (req.accepted.some(function (type) {
return type.value === 'text/html';
})) {
res.locals.someData = {
// Place your custom data here.
};
}
return next();
}
}
}
}
};
Custom filters
Create a file at the following path: config/view-filters/toUpper.js and the following content:
// Replace this with templating engine that you use.
var swig = require('swig');
// Use the API of your templating engine to add custom filter.
swig.setFilter('toUpper', function (value) {
return value.toUpperCase();
});
I am talking about loopback push component. I am trying to intercept the "create" method of "Installation" model. My code looks like this -
server/boot/installationex.js
module.exports = function (app) {
var Installation = app.models.Installation;
var create = Installation.create;
Installation.create = function (data, cb) {
//reinitializing old implementation
this.create = create;
console.log("Received data: "+JSON.stringify(data));
if (!data || !data.imei) {
console.log("No data or imei was provided, creating new");
this.create(data, cb);
return;
}
//saving 'this' reference
var that = this;
//search by imei filter
var filter = {where: {imei: data.imei}};
this.findOne(filter, function (err, result) {
if (err) {
console.log("Error occurred while looking for installation by IMEI");
cb(err);
return;
}
if (!result) {
console.log("No installation found by IMEI, will create a new installation");
that.create(data, cb);
return;
}
console.log("Found existing installation with id: " + JSON.stringify(result));
result.deviceToken = result.gpsLocation = result.osVersion = result.vendor = result.phoneNumbers = null;
if (data.deviceToken) {
result.deviceToken = data.deviceToken;
}
if (data.gpsLocation) {
result.gpsLocation = data.gpsLocation;
}
if (data.osVersion) {
result.osVersion = data.osVersion;
}
if (data.vendor) {
//result.vendor=data.vendor;
result.vendor = 'jahid';
}
if (data.phoneNumbers) {
result.phoneNumbers = data.phoneNumbers;
}
that.upsert(result, cb);
});
}
}
Unfortunately this code is invoked only once, I mean the first time. After that this code is never invoked. I became sure by looking at the log. It only prints the log first time. After that it does not print any log.
Any idea why this glue code is only invoked once? My intention is to intercept all create method invocation for Installation model. And check if there is already an entry for supplied "IMEI", if so then reuse that. Otherwise create new.
Thanks in advance.
Best regards,
Jahid
What I would start here with is:
instead of implementing your own intercepting mechanism use Model Hooks
check out findOrCreate() method
boot scripts are only run once during application startup. if you want a function that triggers every time a function is called, use a remote hook or model hook. probably something along the lines of:
...
Installation.beforeRemote('create', ...
...
see http://docs.strongloop.com/display/LB/Adding+logic+to+models for more info
I'm having a difficult time returning data from a module using RequireJS and Knockout to populate my markup for my single page app. Knockout can't seem to find my data binding observables.
I'm trying to keep each view in a separate js file, but I'm failing to identify where I've gone wrong. Here's what I have so far:
/app/app.js
define(function(require) {
require('simrou');
var $ = require('jQuery'),
ko = require('knockout'),
videoView = require('videoView');
var init = function() {
var viewModel = function() {
var self = this;
self.currentPage = ko.observable();
self.videoView = new videoView();
}
var view = new viewModel();
ko.applyBindings( view );
_router = new Simrou({
'/video/:id': [ view.videoView.getVideo ]
});
_router.start();
};
return {
init: init
};
});
/app/videoView.js
define(function(require) {
"use strict";
var $ = require('jQuery'),
ko = require('knockout');
return function() {
var self = this;
self.currentPage = ko.observable( 'showVideo' );
self.currentVideo = ko.observable();
self.videoData = ko.observableArray([]);
self.videoList = ko.observableArray([]);
var getVideo = function( event, params ) {
// ajax pseudo code
$.ajax({});
self.videoData( dataFromAjaxCall );
}
return {
getVideo: getVideo
};
};
});
index.html
When I browse to /#/video/14 I receive the following error:
Uncaught ReferenceError: Unable to parse bindings.
Bindings value: attr: { 'data-video-id': videoData().id }
Message: videoData is not defined
Here's the markup:
<section id="showVideo" data-bind="fadeVisible: currentPage()=='showVideo', with: $root">
<div class="video" data-bind="attr: { 'data-video-id': videoData().id }></div>
</section>
Like I said, I'm trying to keep each view separated, but I would love some enlightenment on what I'm doing wrong, or if this is even possible? Is there a better more efficient way?
videoData is a property of $root.videoView, not of the root model (the one you passed to applyBindings). It's also an observableArray, so videoData() is just a plain array and even if you get the context right, you won't be able to access its id property, since, being an array, it doesn't have.named properties.
The problem
I am trying to test some directives (code for both below). One of them is an "email" (called "epost" in the code(norwegian)) directive. The solution to this should work for all of them, so I am keeping it to this one for now.
Technologies: Angularjs, Jasmine, Requirejs, (grunt & karma running in Chrome)
The directive validates email addresses in two ways; on upshift and on blur. I can test the upshift without problems as you can see in the test below, but I can't figure out how to simulate a blur so the bind('blur') in the directive runs.
What I have done
I have tried to catch the compiled element like this:
elem = angular.element(html);
element = $compile(elem)($scope);
And then in the test i tried several permutations to trigger the blur with a console log just inside the bind function in the directive. None of the below works. It does not trigger.
elem.trigger('blur');
element.trigger('blur');
elem.triggerHandler('blur');
element.triggerHandler('blur');
element.blur();
elem.blur();
I based the injection and setup on this: To test a custom validation angularjs directive
The email directive in angularjs wrapped in requirejs
define(function() {
var Directive = function() {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ctrl) {
var pattern = /^[A-Za-z0-9._%+-]+#[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/;
elem.bind('blur', function() {
scope.$apply(function () {
if (!elem.val() || pattern.test(elem.val())) {
ctrl.$setValidity('epost', true);
} else {
ctrl.$setValidity('epost', false);
}
});
});
ctrl.$parsers.unshift(function(viewValue) {
if (pattern.test(viewValue)) {
ctrl.$setValidity('epost', true);
return viewValue;
} else {
return undefined;
}
});
}
};
};
return Directive;
});
The test (using jasmine and requirejs)
define([
'Angular',
'AngularMocks',
], function () {
describe('Directives', function () {
var $scope;
var form;
beforeEach(module('common'));
beforeEach(function () {
var html = '<form name="form">';
html += '<input type="text" id="epost" name="epost" epost="" ng-model="model.epost"/>';
html += '</form>';
inject(function ($compile, $rootScope) {
$scope = $rootScope.$new();
$scope.model = {
epost: null
};
// Compile the element, run digest cycle
var elem = angular.element(html);
$compile(elem)($scope);
$scope.$digest();
form = $scope.form;
});
});
describe('(epost) Given an input field hooked up with the email directive', function () {
var validEmail = 'a#b.no';
var invalidEmail = 'asdf#asdf';
it('should bind data to model and be valid when email is valid on upshift', function () {
form.epost.$setViewValue(validEmail);
expect($scope.model.epost).toBe(validEmail);
expect(form.epost.$valid).toBe(true);
});
});
});
});
I have been able to figure out where I went wrong after some breakpoint debugging.
The "element" item I get out using the approach described in the top of the question is not actually the directive it self. It's an object which wraps the form and the directive.
Like this
{ 0: // The form
{ 0: // The directive (input element)
{
}
}
}
To actually simulate a blur on the directive it self, I did something like this
var directiveElement = $(element[0][0]);
directiveElement.blur();
After getting the element I wanted, and wrapping it in a jQuery object (may be optional), it worked like a charm. I then used the approach like in the test in the question with $setViewValue and checked the model value like this.
form.epost.$setViewValue('a#b.no');
directiveElement.blur();
expect($scope.model.epost).toBe('a#b.no');
expect($scope.form.epost.$valid).toBeTruthy();
Hope this could be of help to others trying to figure the directive testing out.
I too ran into a similar problem and it mystified me. My solution was to use JQuery to get the input and then use angular.element(input).triggerHandler('blur') to make it work. This is odd to me because I do not have to do this with the click event.
spyOn(controller, 'setRevenueIsInvalid');
var sugarRow = $(element).find('tr#ve_id_5')[0];
var amount = $(sugarRow).find('input.amount')[0];
angular.element(amount).triggerHandler('blur');
expect(controller.setRevenueIsInvalid).toHaveBeenCalled();