I am using PptxGenJS.js in my project which consists of graphs across various dashboards(pages/views),
I have a specific requirement where once the user adds a graph(SVG image) as a slide to the PptxGenJS object it should be maintained throughout the application till the user clicks on export ppt.
Please go through the below explanation for better understanding.
I initialise the PptxGenJS object in the layout.cshtml which is common for all the views.
var thispptx = new PptxGenJS();
And now in each view, there are multiple graphs, When the user clicks on Add To PPT button as shown below,
The slide gets added to the PPT
The SVG file gets added to the previously created PptxGenJS object.
i.e.
$('#Chart1PPTId').click(function ()
{
var pptslide1 = CreateSlide("#barChartz1", "bar",thispptx,CustomlabeltextForPPT);
});
function CreateSlide(divId, ChartType,pptx,SearchCriteria) {
var slide = pptx.addNewSlide()
var svg;
if (ChartType != "guage") {
svg = EntryPoint.getChartsvg(divId);
}
else {
svg = EntryPoint.getGuageChartsvg(divId);
}
var DOMURL = window.URL || window.webkitURL || window;
var svgBlob = new Blob([svg], { type: 'image/svg+xml;charset=utf-8' });
var url = DOMURL.createObjectURL(svgBlob);
slide.addImage({ path: url, x: 0.5, y: 0.5, w: 9.0, h: 4.5});
slide.addText('Search Criteria : ' + SearchCriteria, { x: 0.1, y: 5.2, font_size: 12, color: '363636' });
return slide
}
Now after adding several slides to the PptxGenJS object the user will click on Export to PPT button which will export it as a PowerPoint Presentation.
So my problem is that all of this works fine within the current page/view.
But my requirement is to maintain the same PptxGenJS object across all the views, which is not currently possible as I have initialised the PptxGenJS object in the layout which loads for every page/view (so a new PptxGenJS object is created for every view/page)
Is there a better way to handle this situation of mine?
Related
I've loaded some JSon data outlining each country on a globe as a GeoJSonDataSource into my Cesium project. Each country is also copied as a separate entry into an array. In order to highlight a country, I use
viewer.entities.add(countryArray[countryID]);
which places a colored polygon over the selected country when the user clicks on it. However, when I click on the Camera icon in the info box that Cesium provides by default, nothing happens. In the console, the error message reads:
TypeError: t is undefined
and points to Cesium.js. If I don't add anything to the viewer.entities array, this error doesn't appear.
There may be a better way to highlight the selected country. Try capturing the selected entity, and change the material properties on the existing polygon, rather than creating a new one.
For example, give this a try: Load up the Cesium Sandcastle and paste in the following code into the code editor, then hit F8:
var viewer = new Cesium.Viewer('cesiumContainer', {
navigationHelpButton: false, animation: false, timeline: false,
selectionIndicator: false
});
var deselectColor = Cesium.Color.BLUE.withAlpha(0.3);
var selectedColor = Cesium.Color.LIME.withAlpha(0.5);
var deselectMaterial = new Cesium.ColorMaterialProperty(
new Cesium.ConstantProperty(deselectColor));
var selectedMaterial = new Cesium.ColorMaterialProperty(
new Cesium.ConstantProperty(selectedColor));
viewer.dataSources.add(Cesium.GeoJsonDataSource.load(
'../../SampleData/ne_10m_us_states.topojson', {
stroke: Cesium.Color.WHITE,
fill: deselectColor,
strokeWidth: 2
}));
//Set the camera to a US centered tilted view.
viewer.camera.lookAt(Cesium.Cartesian3.fromDegrees(-98.0, 40.0),
new Cesium.Cartesian3(0.0, -4790000.0, 3930000.0));
viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);
var previousEntity;
Cesium.knockout.getObservable(viewer, '_selectedEntity').subscribe(function(newEntity) {
if (Cesium.defined(previousEntity) && Cesium.defined(previousEntity.polygon)) {
previousEntity.polygon.material = deselectMaterial;
}
if (Cesium.defined(newEntity) && Cesium.defined(newEntity.polygon)) {
newEntity.polygon.material = selectedMaterial;
}
previousEntity = newEntity;
});
I am creating a famo.us app in which header footer and content area is there. In content area different views are rendering using RenderController on action of each other and in each view different sub views are there. Events are communicating through java script using document.dispatchEvent() and addEventLiserner() method instead of famo.us events. I just want to ask that whether it is worth using this listener functions.
As I have tried through famous events like setInputHandler, setOnputHandler, emit , addListener, pipe given in famo.us documentation, But I cannot able to communicate using this.
The main question is the static app created by me is taking huge time when loaded from server and animations are running very slowly. Is there any solution for this.
Actually code is too long dummy example is below. I am creating an application having header footer and content view. In Content view I am rendering different views using renderController.
Content View
define(function(require, exports, module) {
var View = require('famous/core/View');
var Surface = require('famous/core/Surface');
var LoginView = require('views/login/LoginView');
var AccountsView = require('views/login/AccountsView'); //need to call on login
function ContentView() {
View.apply(this, arguments);
var renderController = new RenderController({
inTransition: {curve: Easing.easeOut, duration: 1000},
outTransition: {curve: Easing.easeIn, duration: 1000},
overlap: true,
});
var loginview = new LoginView();
renderController.show(loginview); //rendered initially
this.add(renderController);
document.addEventListener("showAccountsView",function(){
var accoutsView = new AccountsView()
renderController.show(accoutsView);
}.bind(this));
}
});
Login View
define(function(require, exports, module) {
var View = require('famous/core/View');
var Surface = require('famous/core/Surface');
var InputSurface = require("famous/surfaces/InputSurface");
function LoginView() {
View.apply(this, arguments);
var loginBoxContainer = new ContainerSurface({
classes:["backfaceVisibility"],
size:[undefined,295],
properties: {
overflow: 'hidden',
padding:'0 10px'
}
});
this.add(loginBoxContainer);
var userInput = new InputSurface({
size: [undefined, 45],
});
var userInputModifier = new StateModifier({
transform: Transform.translate(0,53,1)
});
var pwdInput = new InputSurface({
classes:["pwdInput"],
size: [undefined, 45],
});
var pwdInputModifier = new StateModifier({
transform: Transform.translate(0,100,1)
});
loginBoxContainer.add(userInputModifier).add(userInput);
loginBoxContainer.add(pwdInputModifier).add(pwdInput);
var submit = new Surface({
content:["Submit"],
size:[100,30],
});
submit.on("click",function(){
document.dispatchEvent(new Event("showAccountsView"));
});
loginBoxContainer.add(submit);
}
});
I have to render different view on clicking ligin submit button. I have used dispatchEvent and addEventListener of Javascript to make communication between two files. I want to use famous events. I have tried various ways using setInputHandler, setOnputHandler, emit , addListener, pipebut could not able to do that as data and listener functions cannot calling. Please explain..
Inside LoginView, replace this code:
submit.on("click",function(){
document.dispatchEvent(new Event("showAccountsView"));
});
with:
submit.on("click",function(){
this._eventOutput.emit('showAccountsView', { data: someValue });
});
In ContentView, replace:
document.addEventListener("showAccountsView",function(){
var accoutsView = new AccountsView()
renderController.show(accoutsView);
}.bind(this));
with:
loginView.on('showAccountsView', function(data){
var accoutsView = new AccountsView()
renderController.show(accoutsView);
}.bind(this));
I am making an application in which user can drag & drop multiple objects from a toolbar onto a canvas.After dragging and dropping that particular object onto the canvas the user can move that object around in the canvas.Double Clicking on that object will make it disappear.I have been able to implement this for one object in the toolbar as shown in the link below..
http://jsfiddle.net/gkefk/26/
To drag & drop multiple objects from the toolbar I made the following additions in the function DragDrop()
var image2 = new Kinetic.Image({
name: data,
id: "image"+(imageCount++),
x: x,
y: y,
image2: theImage2,
draggable: true
});
image2.on('dblclick', function() {
image2.remove();
layer.draw();
});
layer.add(image2);
layer.draw();
var image3 = new Kinetic.Image({
name: data,
id: "image"+(imageCount++),
x: x,
y: y,
image3: theImage3,
draggable: true
});
image3.on('dblclick', function() {
image3.remove();
layer.draw();
});
layer.add(image3);
layer.draw();
The Fiddle containing the above code is http://jsfiddle.net/gkefk/29/
Even though I've made the necessary additions in the DragDrop() function, the two new objects are visible in the toolbar but i'm not being able to drag,drop,move around and delete them like the first object.Please Help...
I made it work with some major changes:
The image sources are provided in a dynamic array - so you can extend this at one single place in your code:
var imageSrc = [
"http://t2.gstatic.com/images?q=tbn:ANd9GcQ5fOr5ro_dK6D9UmSsVn0Z9m1QQMqRwr0z1tP_BzEGr7GuTrgeZQ",
"http://sandbox.kendsnyder.com/IM/square-stripped.png",
"http://t3.gstatic.com/images?q=tbn:ANd9GcRBYkAv40Eeaxlze2dqhayvKUeoUH6l_jYNLlsfjzJu0Uy9ucjcNA"
];
(of course you also have to update your HTML with the toolbar accordingly)
The list of images gets processed in a loop and for each element a new draggable object is created in connection with the corresponding <img id = "..." />:
//loop through imageSrc list
for (var i = 0; i < imageSrc.length; i++) {
//use a closure to keep references clean
(function() {
var $house, image;
var $house = $("#house"+i);
$house.hide();
image = new Image();
image.onload = function () {
$house.show();
}
image.src = imageSrc[i];
// start loading the image used in the draggable toolbar element
// this image will be used in a new Kinetic.Image
// make the toolbar image draggable
$house.draggable({helper: 'clone'});
$house.data("url", "house.png"); // key-value pair
$house.data("width", "32"); // key-value pair
$house.data("height", "33"); // key-value pair
$house.data("image", image); // key-value pair
})();
}
The counter for IDs is only relevant to the new element that is created on drop. As you only drop one image at the same time you also have to create a single new Image() only, instead of trying to create three of them.
Your working example can be found here and is extensible: http://jsfiddle.net/gkefk/32/
Creating a new object on mouseclick as a way for users to create reference points (which I call 'crumbs') when reading large web documents. I've got this working with a new Image() function, however, that won't let me assign a tabindex to each new image created by mouseclick (posX, posY). 'crumbtoggle' simply acknowledges that the crumb dropping tool has been selected.
working new Image() function:
function draw_crumb()
{
var b_canvas = document.getElementById("b");
var b_context = b_canvas.getContext("2d");
var crumb = new Image();
crumb.src = "crumb.gif";
if(crumbtoggle.className == "on")
{
b_context.drawImage(crumb, posX-20, posY-20, 50, 75);
}
}
non-working new Object () function:
function draw_crumb()
{
var b_canvas = document.getElementById("b");
var b_context = b_canvas.getContext("2d");
var crumb = new Object();
crumb.type = "button";
crumb.src = "crumb.gif";
crumb.tabindex = 1;
if(crumbtoggle.className == "on")
{
b_context.drawObject(crumb, posX-20, posY-20, 50, 75);
}
}
I've looked in to applying focus to the new Image objects, but that doesn't seem to be a good alternative to tabindex attributes. Any ideas would be greatly appreciated.
An HTML5 Canvas is like a real-world canvas with instantly-drying paint. When you paint a rectangle or line or image on the canvas, it becomes part of the canvas. You cannot later re-order the items, or move them relative to each other. It is not a separate entity that can get focus.
Any sort of focus management integrated with the browser's handling of focus will have to be done through form inputs or anchors recognized by the browser.
It's not clear to me why you need a canvas, or if you need one at all.
What I'm trying to do sounds pretty simple, but I can't do it.
I am building a game using Phaser, and on the top bar of my game want to print the picture of the player inside a circle. But I can't find a way to do this.
I find how to do a circle :
this.mask = this.game.add.graphics(0,0);
this.mask.drawCircle(50,50,50);
But I can't find a way to fill it with a picture, without the picture overflowing the circle.
Phaser has support for using an image to mask another.
See the official Alpha Mask example for an example with two images. Using an image for the mask might be the recommended method.
I've also created a JSFiddle that shows how to use a created circle:
// Create our 'main' state that will contain the game
var mainState = {
preload: function() {
// This function will be executed at the beginning
// That's where we load the images and sounds
this.load.crossOrigin = 'anonymous';
this.load.image('baseImage', 'https://placeholder.baker.com/200');
},
create: function() {
this.baseImage = this.game.add.sprite(this.world.centerX, this.world.centerY * .5, 'baseImage');
this.baseImage.anchor.setTo(0.5);
this.mask = game.add.bitmapData(this.baseImage.width, this.baseImage.height);
this.mask.circle(this.world.centerX, this.world.centerY * .5, 100, 'rgb(0,200,0)');
this.bmd = this.game.make.bitmapData(200, 200);
this.bmd.alphaMask('baseImage', this.mask);
this.game.add.image(this.game.world.centerX, this.world.centerY * 1.5, this.bmd).anchor.set(0.5);
},
};
// Initialize Phaser, and create a game
var game = new Phaser.Game(200, 400);
// Add the 'mainState' and call it 'main'
game.state.add('main', mainState);
// Start the state to actually start the game
game.state.start('main');