You find much infos to trailing commas here:
Are trailing commas in arrays and objects part of the spec?
It's about the comma at "right there".
[
{ title: "..", display: function() { return ".."; } },
{ title: "..", display: function() { return ".."; } },
{ title: "..", display: function() { return ".."; } }, // <--right there
]
My problem is now, that a 3rd party tool generates this list with a trailing comma and I am not able to access the sourcecode of this tool. I
<body>
my stuff
<!-- the folloging div with the javascript comes from the 3rd party -->
<div class="item"><script type="text/javascript">
$(document).ready(function() {
$.supersized({
// Functionality
slide_interval : 8000, // Length between transitions
transition : 1, // 0-None, 1-Fade, 2-Slide Top, 3-Slide Right, 4-Slide Bottom, 5-Slide Left, 6-Carousel Right, 7-Carousel Left
transition_speed : 400, // Speed of transition
fit_always : 0, //Prevents the image from being cropped by locking it at 100% width.
min_width : 600, //min-width of images
random : 0, //random img
vertical_center : 1, //vertical alignment
// Components
slide_links : 'false', // Individual links for each slide (Options: false, 'number', 'name', 'blank')
slides : [ // Slideshow Images
{image : 'image1.jpg', otherstuff: 'blah', moreotherstuff: 'lorem'},
{image : 'image2.jpg', otherstuff: 'blub', moreotherstuff: 'ipsum'},
]
});
});
</script></div>
And now I am asking me is there any way to get this working in IE7/IE8.
The only way I see right now (as i can't edit the 3rd party and can't access it on the server) is:
- give a special output without that div
- request the normal side via ajax
- parse everything, get this div, delete last comma and execute the javascript
that's realy not the way I want do it. Is there another way I could solve this?
IE7/IE8 will report 1 element bigger array length, unless you trim those arrays.
If you know all JS methods which accepts data from 3rd party you can write wrapper for them. For example:
var removeEmpty = function(array){
var i, result = [];
for (i = 0; i < array.length; ++i){
if ( typeof array[i] != 'undefined' ){
result.push(array[i]);
}
}
return result;
};
$.supersized = (function() {
var origMethod = $.supersized;
return function(config) {
config.slides = removeEmpty(config.slides); // get rid of undefined data in array
return origMethod.call(this, config); // call original method
};
}());
No, there is no way to get those trailing commas working in IE. It simply can't be done; it's a fundamental part of the browser's javascript parser.
This is an extremely well-known issue, which means that your third party tool is very obviously faulty and clearly hasn't been tested properly. I don't know where you got it from, but if you paid for it, I'd be complaining loudly if I were you.
If you really can't deal with the problem at source, then your only option remaining is to fix the generated code before it gets into IE. That much is easier said than done. Depending on the complexity of the generated code, you might be able to write a regex for it if it's simple and predictable, but if the code it generates is complex or of varying complexity, I suspect you may be in trouble with that idea.
Related
I'm using ChartJS (v 2.9.4) and I want the hover interaction / tooltip system (they work the same way from what I can tell) to select the point nearest (relative to the x axis) to the mouse pointer on all datasets.
Now, if the x-axis of the chart is operating in the default category mode (i.e.: data points with the same index in the dataset have the same position on the x-axis) this is easily achieved with this configuration:
options: {
hover: {
mode: 'index',
intersect: false
}
//other options...
}
However, if the x-axis is of type linear (i.e.: each data point in each dataset has a specific x-value) this doesn't work properly, since the decision on which point to select is based on its index in the dataset, rather than its x-axis value.
I've created an example here:
https://jsfiddle.net/parhwv73/5/
as you can see by hovering the mouse around, you can easily find yourself in situations like this, where the points selected in the two datasets are very far apart:
while what I would like is this:
in other words: I would like to select the point in each dataset nearest to the mouse pointer (relative to the x-axis).
I've tried playing around with the mode and intersect options, but I found no combination that works, mainly because most other modes only select a point in one single dataset, rather than all of them, index mode is the closest one to being correct, but not quite as I've explained.
Is there a way to achieve this natively?
Or if there isn't, can anyone give some pointers on how to implement a plugin of some sort that can achieve this?
If someone has the same problem in a more recent version (like 3.7.0), you can just modify the interaction mode: instead of 'index', use this:
options: {
interaction: {
intersect: false,
mode: 'nearest',
axis: 'x'
},
}
found on the docs
Well, in the end I had to modify the ChartJS source code to achieve this. Fortunately, it wasn't too hard. All I had to do was add this function to the core.interaction.js file:
function xPositionMode(chart, e, options) {
var position = getRelativePosition(e, chart);
// Default axis for index mode is 'x' to match old behaviour
options.axis = options.axis || 'x';
var distanceMetric = getDistanceMetricForAxis(options.axis);
var items = options.intersect ? getIntersectItems(chart, position) : getNearestItems(chart, position, false, distanceMetric);
var elements = [];
if (!items.length) {
return [];
}
const findClosestByX = function(array, element) {
let minDiff = -1;
let ans;
for (let i = 0; i < array.length; i++) {
var m = Math.abs(element._view.x - array[i]._view.x);
if (minDiff === -1 || m < minDiff) {
minDiff = m;
ans = array[i];
}
}
return ans;
}
chart._getSortedVisibleDatasetMetas().forEach(function(meta) {
var element = findClosestByX(meta.data, items[0]);
// don't count items that are skipped (null data)
if (element && !element._view.skip) {
elements.push(element);
}
});
return elements;
}
This is basically a modified version of the indexMode function present in the same file, but instead of searching items by their index in the dataset it searches the closest items by their horizontal position on the canvas (see the findClosestByX inner function for the search algorithm)
To make this usable, you also have to add the new mode in the list of exports (in the same file):
module.exports = {
// Helper function for different modes
modes: {
xPosition: xPositionMode,
//Rest of the original code...
}
}
Once this is done, recompile the ChartJS library and use it instead of the original one. Now you can use the new mode like this:
options: {
hover: {
mode: 'xPosition',
intersect: false
}
//other options...
}
Note: all code in this answer refers to the 2.9.4 version of the ChartJS library, it might not work the same for 3.x versions.
I started this project just for fun (inspired by the Conway's Game of Life). In my project, I have a file for the cell (defined as an object) and other for the game (universe) where the rules are set so the cell can play. The cell object is defined like this:
const cell = {
x_birth: 0,
y_birth: 0,
alive: false,
live: function() {
fill(100);
square((WIDTH/F)*x, (HIGH/F)*y, (WIDTH/F), (HIGH/F));
},
die: function() {
fill(255);
square((WIDTH/F)*x, (HIGH/F)*y, (WIDTH/F), (HIGH/F));
},
move: function(x_var, y_var) {
if (this.alive == false){
x = this.x_birth;
y = this.y_birth;
this.alive = true; // Bug?
this.live();
} else { //... }}}
WIDTH, HIGH and F are global constants from the other main file.
The problem I have is that when I create two objects with 'Object.create(cell)' in the main file, just one of the cells moves. It appears that when one of the cells executes its function 'move()', it does it correctly, setting it's property 'alive' to 'true' when the other cell (object) doesn't. I though that this may be the problem, but then I searched and I didn't find why this should be the issue.
If you want, you can download the files from my repo: https://github.com/Atotem/Game.git . There you will understand what i mean. I'm open to all suggestions.
PD: I'm using p5.js libraries.
I want my raycaster to look for intersections only when the trigger of my vive controller is pressed.
I thought to initialize the raycaster with a fake class in objects, change it to the real one .prop and gather the intersectedEls
let rightHand = document.getElementById('rightController');
rightHand.setAttribute('line', 'color: purple; opacity: 1;');
rightHand.setAttribute('raycaster', { showLine: true, objects: '.none' });
rightHand.setAttribute('cursor', { downEvents: ['triggerdown'], upEvents: ['triggerup'], rayOrigin: 'entity', fuse: false });
let scene = document.getElementById('scene');
scene.addEventListener('triggerdown', this.myTriggerDown);
scene.addEventListener('triggerup', this.myTriggerUp);
myTriggerDown() {
let rightHand = document.getElementById('rightController');
rightHand.setAttribute('raycaster', { showLine: true, objects: '.prop' });
rightHand.components['raycaster'].refreshObjects();
let raycaster = rightHand.components['raycaster'];
let intersectedEls = raycaster.intersectedEls;
if (typeof intersectedEls !== 'undefined' && intersectedEls.length > 0) {
scene.components['resize'].enableResize(intersectedEls[0]);
} else {
console.log('1234 no intersections')
}
}
myTriggerUp() {
let rightHand = document.getElementById('rightController');
rightHand.setAttribute('raycaster', { showLine: true, objects: '.none' });
}
Unfortunately I keep getting the console.log('1234 no intersections') message.
I tried adding the refreshObjects() line with no effects.
I tried toggling the enabled property instead of changing the objects, but had still the same result.
Any help would be appreciated. Thanks
edit:
if I look for intersections in the triggerup part it works. but this is a workaround which also deprives me of using the intersected element and doing things while keeping the trigger pressed . I'd still like to know why it does not work to enable the ray/change target objects and immediately look for intersections.
I recommend using the raycaster.enabled property versus swapping to a dummy class.
The raycaster checks for intersections once per frame (or whatever the raycaster.interval is). On trigger down, you enable the raycaster, but you have to wait until the next frame for it to pick up intersections.
You can manually invoke intersection check via raycaster.checkIntersections() or run a setTimeout before checking.
I believe I have a problem that may be fairly easily addressed via something that I am missing, but I can't seem to see what the actual issue is. I have an application that returns 5000 points (5 array elements of 1000 x,y points) every second that I want to update on the client side using NVD3. This is an AngularJS application, so I am using krispos angular-nvd3 directive. However, it is bogging the whole application down, and it appears that, according to the timeline captured by Chrome's developer tools, the application seems to be waiting on d3_timer_step to return for 5-6 seconds.
I thought this problem was due to how we were updating the data, but the whole issue seems to be with the actual d3 portion. The code on the client side is
<nvd3 options="optionsRingdown" data="ringdownAvg" config="{refreshDataOnly:true}"></nvd3>
and in the controller the options are defined as follows
$scope.options = {
chart: {
type: 'lineChart',
height: 300,
margin: {
top: 20,
right: 40,
bottom: 60,
left: 75
},
x: function(d) {
return d.x;
},
y: function(d) {
return d.y;
},
useInteractiveGuideline: false,
yAxis: {
tickFormat: function(d) {
return d3.format('0.01f')(d);
},
axisLabel: 'Testing'
},
xAxis: {
tickFormat: function(d) {
return d3.time.format('%X')(new Date(d));
},
rotateLabels: -45
},
transitionDuration: 0,
showXAxis: true,
showYAxis: true
}
};
and the data is defined in the following template
var ringdownT = [{
values: [],
key: 'Cell 0'
}, {
values: [],
key: 'Cell 1'
}, {
values: [],
key: 'Cell 2'
}, {
values: [],
key: 'Cell 3'
}, {
values: [],
key: 'Cell 4'
}];
The data is updated via a function call on broadcast from a service using the following
function updateCRD(d){
var dataOut = {
"tauData": [],
"rdFit": ringdownT,
"rdAvg":ringdownT
}
for (k = 0; k < d.cell.length; k++) {
dataOut.rdAvg[k].values = d.cell[k].avg_rd;
dataOut.rdFit[k].values = d.cell[k].fit_rd;
}
return dataOut;
}
The function is called in a broadcast using the following (which is broadcast at 1 second intervals)
$scope.$on('dataAvailable', function() {
$scope.data = Data.crd;
var data = updateCRD(Data.crd);
$scope.tauData = data.tauData;
$scope.ringdownAvg = data.rdAvg;
$scope.ringdownFit = data.rdFit;
});
Does anyone see something that looks obviously wrong here or that I should be doing differently? Is there an option that I am missing? Any help would be great.
Cheers, Matt
Try to add deepWatchData: false flag to config (it means that directive won't watch the data for updates) and update chart via api:
<nvd3 options="optionsRingdown" data="ringdownAvg" api="apiRingdown" config="{refreshDataOnly:true, deepWatchData: false}"></nvd3>
The directive watches options and complex data objects for any updates using $watch(watchExpression, listener, [objectEquality]) method. In our case deepWatchData is the objectEquality flag, while watching chart data for updates.
According to the angular docs, inequality of the watchExpression is determined according to the angular.equals function. And to save the value of the object for later comparison, the angular.copy function is used. This therefore means that watching complex objects will have adverse memory and performance implications.
In versions (1.0.2, 1.0.3) only, this flag is false by default.
Then, to update chart, we can use apiRingdown.update method in your controller:
$scope.$on('dataAvailable', function() {
$scope.data = Data.crd;
var data = updateCRD(Data.crd);
$scope.tauData = data.tauData;
$scope.ringdownAvg = data.rdAvg;
$scope.ringdownFit = data.rdFit;
//this line updates the chart
$scope.apiRingdown.update();
});
UPDATED
Some updates are added in the latest versions [1.0.4+]. Now flag deepWatchData means to use or not to use data watching at all (it's not objectEquality as before). And deepWatchData is true by default. But now we can manage the $watch depth with a new flag deepWatchDataDepth: 2, and thereby regulate performance. With this flag we can specify a change detection strategy (scope $watch depth) for data:
0 - By Reference (the least powerful, but the most efficient)
1 - By Collection Items
2 - By Value (the most powerful, but also the most expensive; default value)
Also, flag refreshDataOnly is true by default.
So, the updated tag element may look like:
<nvd3 options="optionsRingdown" data="ringdownAvg" api="apiRingdown" config="{deepWatchDataDepth: 0}"></nvd3>
demo
Are you using SVG? nvd3.lineChart is SVG so yeah, probably. If so, #mbostock has the answer for you: http://bl.ocks.org/mbostock/1276463. Use a canvas instead of SVG for lots more speed.
Most of the suggestions on https://www.safaribooksonline.com/blog/2014/02/20/speeding-d3-js-checklist/ are pretty solid.
Are you redrawing all 5000 points each second? If so, this is a job for webGL imo, not nvd3. canvas might be fast enough to do this, if canvas isn't fast enough then I'll stick to former answer.
What % of the time is it spending in d3_timer_step? It doesn't make sense that that function would be slow, it may just be called a great many times. Actually, d3_timer_frame is called by d3_timer_step, which could be the actual render code and would definitely take all your time. Try to do the canvas.
possible nvd3 performance improvements:
Definitely disable useInteractiveGuideline if you haven't already.
So I have spritesheet i have almost looked everywhere nor i can find good tutorial neither i can get this thing to work .Can some one point it out for me that what's wrong here.?Coz none error is generated nor is anythign getting showed on the canvas .
var result = queue.getResult("avatar1");
var data=
{
images: [ result],
// The 5th value is the image index per the list defined in "images" (defaults to 0).
frames: [
// x, y, width, height, imageIndex, regX, regY
//head_south":{"x":120,"h":20,"y":138,"w":15}
[120,138,15,20],
[64,0,15,20,2],
],
animations: {
show: { frames: [0,1], next: true, frequency: 1 }
}
};
var sp = new createjs.SpriteSheet(data);
createjs.Ticker.setFPS(60);
var sprite_anim = new createjs.BitmapAnimation(sp,"show");
sprite_anim.x=100;
sprite_anim.y=100;
stage.addChild(this.sprite_anim);
sprite_anim.play("show");
sprite_anim.gotoAndPlay('show');
Do you update the stage with the ticker ? :
createjs.Ticker.addEventListener("tick", function(event) {
stage.update(event);
});
4 arguments [120,138,15,20], 5 arguments [64,0,15,20,2]
Arguments that are allowed are either 4 or 7.So changed back to 4.That was why it was generating error of" createjs type error '.
Thank everyone for your conern .Closing this question.