Arbitrary Timeline in Cesium? - maps

Cesium has a nice timeline at the bottom of the screen that changes the current astronomical phenomena and changes model positions and animation based on their model. What it doesn't have, and what I really need, is a way to plot events in arbitrary time. I'd like to start at time 00:00:00, and advance from there in real time, and rewind back to 00:00:00. At the moment, I don't care about astronomical activity, including solar and lunar activity. The API is set up to accept Julian Time, not set up for some arbitrary time. Is it possible to get an arbitrary timeline inserted in place of the normal timeline?

Give this a try. Internally it still uses JulianDates from some arbitrary date, but the user only ever sees the time, not the date.
var viewer = new Cesium.Viewer('cesiumContainer', {
navigationInstructionsInitiallyVisible: false,
skyBox: false
});
var clock = viewer.clock;
clock.clockRange = Cesium.ClockRange.LOOP_STOP;
clock.startTime = Cesium.JulianDate.fromIso8601('2016-01-01T00:00:00Z');
clock.stopTime = Cesium.JulianDate.fromIso8601('2016-01-01T23:59:59Z');
clock.currentTime = clock.startTime;
function twoDigits(num) {
return ((num < 10) ? ('0' + num.toString()) : num.toString());
}
var animationViewModel = viewer.animation.viewModel;
animationViewModel.dateFormatter = function() { return ''; };
animationViewModel.timeFormatter = function(date, viewModel) {
var gregorianDate = Cesium.JulianDate.toGregorianDate(date);
var millisecond = Math.round(gregorianDate.millisecond);
return Cesium.sprintf("%02d:%02d:%02d.%03d", gregorianDate.hour,
gregorianDate.minute, gregorianDate.second, millisecond);
};
viewer.timeline.makeLabel = function(time) {
var gregorian = Cesium.JulianDate.toGregorianDate(time);
var millisecond = gregorian.millisecond, millisecondString = '';
if ((millisecond > 0) && (this._timeBarSecondsSpan < 3600)) {
millisecondString = Math.floor(millisecond).toString();
while (millisecondString.length < 3) {
millisecondString = '0' + millisecondString;
}
millisecondString = '.' + millisecondString;
}
return twoDigits(gregorian.hour) + ':' + twoDigits(gregorian.minute) + ':' +
twoDigits(gregorian.second) + millisecondString;
};
viewer.timeline.updateFromClock();
viewer.timeline.zoomTo(clock.startTime, clock.stopTime);
html, body, #cesiumContainer {
width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
font-family: sans-serif;
}
<link href="http://cesiumjs.org/releases/1.18/Build/Cesium/Widgets/widgets.css"
rel="stylesheet"/>
<script src="http://cesiumjs.org/releases/1.18/Build/Cesium/Cesium.js">
</script>
<div id="cesiumContainer"></div>

Related

How to highlight cell in Anychart table when I click on that cell

Is there any way to highlight a cell in an Anychart table when I click on the cell?
I tried the following code, but it doesn't work.
table.listen("click",function(e){e.cellBorder(" #ff0000")});
Unfortunately, the current version of AnyChart 8.2.1 tables does not support events. But you can implement this functionality with some extra code. For details, please, check the sample below.
anychart.onDocumentReady(function () {
// set stage
var stage = anychart.graphics.create("container");
// create table
var table = anychart.standalones.table();
// set table content
table.contents([
[
null,
"2003 Sales",
"2004 Sales"
],[
"January",
"$10000",
"$12000"
],[
"February",
"$12000",
"$15000"
],[
"March",
"$18000",
"$16000"
],[
"April",
"$11000",
"$15000"
],
[
"May",
"$9000",
"$14000"
]
]);
var contents = table.contents();
// Set rows height.
table.rowsHeight(70);
table.getRow(0).fontWeight(900);
table.getCol(0).width(70).fontWeight(900); // Set first column width 70 px and bold the text
table.getCol(1).width(300);
table.getCol(2).width(300);
table.cellFill("#E1E1E1"); // Set table background color
// adjust table border and position text in each cell into center
table.cellBorder("#B8B8B8").vAlign("middle").hAlign("center");
// set table container and initiate draw
table.container(stage).draw();
var colsCount = table.colsCount();
var widths = [];
for(var i = 0; i<colsCount;i++) {
var width = table.getCol(i).width();
widths.push(width);
}
var rowHeight = table.rowsHeight();
// buffer cell
var buffer = 0;
var cont = document.getElementById('container');
cont.addEventListener('click', function(e) {
var x = e.clientX;
var y = e.clientY;
var indX = null;
var indY = null;
if(x < widths[0]) {
indX = 0;
}
if(x> widths[0] && x<widths[0] + widths[1]) {
indX = 1;
}
if(x > widths[0] + widths[1]) {
indX = 2;
}
indY = Math.floor(y / rowHeight);
// color selected cell
if (contents[indY]) {
table.getCell(indY,indX).fill("#0000ff", 0.2);
}
// color back
if (buffer !=0) {
buffer.fill("#e1e1e1")
}
// save selected cell to buffer
if (contents[indY]) {
buffer = table.getCell(indY,indX);
}
});
});
html, body, #container {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
<link href="https://cdn.anychart.com/releases/8.2.1/css/anychart-ui.min.css" rel="stylesheet"/>
<script src="https://cdn.anychart.com/releases/8.2.1/js/anychart-base.min.js"></script>
<script src="https://cdn.anychart.com/releases/8.2.1/js/anychart-table.min.js"></script>
<script src="https://cdn.anychart.com/releases/8.2.1/js/anychart-exports.min.js"></script>
<script src="https://cdn.anychart.com/releases/8.2.1/js/anychart-ui.min.js"></script>
<div id="container"></div>

Passing through variable on ng-compile returns undefined

var suggestionElement = document.createElement('div');
vm.suggestActivate = function(keyCode) {
if(keyCode === 32) {
if(vm.summaryData) {
var words = vm.words;
var suggestions = "<div></div>";
var targetElement = event.srcElement;
var targetElementModel = targetElement.getAttribute("ng-model");
for(var i = 0; i < 5; i++) {
$log.debug(targetElementModel);
suggestions += '<div ng-click="vm.appendSuggestion(targetElementModel)" style="padding: 10px; border: 1px solid #B0B0B0;" onMouseOver="this.style.backgroundColor=\'#D8D8D8\'" onMouseLeave="this.style.backgroundColor=\'#F3F3F3\'">' + words[Math.floor(Math.random() * words.length)] + '</div>';
}
suggestionElement.innerHTML = suggestions;
suggestionElement.setAttribute('style', 'background: #F3F3F3; position: relative; top: -3.9em; width: 25%');
suggestionElement.style.display = 'block';
angular.element(targetElement.parentNode).append($compile(suggestionElement)($scope));
}
}
else {
suggestionElement.style.display = 'none';
}
};
vm.appendSuggestion = function(model) {
$log.debug(model);
}
In the above segment of code in the vm.appendSuggestion method, why is model returned as undefined? If I log it during the for loop, it returns a value? I want to return a value in the vm.appendSuggestion method as well. However, I noticed when it is hardcoded, it does not return as undefined.
When you click on the div element to which you have assigned the ngClick directive, Angular tries to find targetElementModel on the $scope and it does not exist there. You cannot pass a value to it like that.
A solution might be to expose a list of target elements to the view and do something like '<div ng-click="vm.appendSuggestion(' + targetElementIndex + ')" .... But this is just an example - you might find a more appropriate solution for your problem.

ExtJS4- Year and month date picker - disable all future dates

I am using a Ext.picker.Month.
Setting maxDate does not disable dates which are grater than the maxDate value, but causes a validation error when selecting one.
How can I disable all future dates?
See fiddle -
1. Set maxDate to new Date()
2. Use ExtJS 4.2
You are instantiating a MonthPicker, not a DatePicker, yet you are using dozens of config options that are only available for a DatePicker.
You can see here how to instantiate a MonthPicker. As you can see there and especially in the docs, MonthPicker does not provide a config option to disable anything. Also, if you check the DatePicker behaviour, you see that disabledDates option does not change anything in MonthPicker, only AFTER the month has been selected, all days in the DatePicker are disabled.
So you would be on your own in implementing disabledDates for the MonthPicker, which I would do by looking at the code from DatePicker and MonthPicker, and trying to transfer.
Try this one...working on ExtJS 6.0.0.
You need to override 'Ext.picker.Month'
find attached image
Accepted values -
new RegExp('(?:)'); disable all month/year
new RegExp('^((?!^Apr/2016$|^May/2016$|^Jun/2016$|^Jul/2016$).)*$') disable all values other than Apr/May/Jun/Jul 2016
CSS -
.x-monthpicker-disabled {
background-color: #eee !important;
cursor: default !important;
color: #bbb !important;
}
disabledCls: Ext.baseCSSPrefix + 'monthpicker-disabled',
disabledMonthYearsRE: null,
disabledMonthYearsText: 'Disabled',
updateBody: function () {
//default Extjs code
if (me.rendered) {
//default Extjs code
//remove disabled cls and tooltip
years.removeCls(disabledCls);
months.set({
'data-qtip': ''
});
years.set({
'data-qtip': ''
});
months.removeCls(disabledCls);
//default Extjs code
if (dmyMatch) {
if (month == null && year == null) {
months.set({
'data-qtip': dmyText
});
months.addCls(disabledCls);
}
yrInView = false;
for (y = 0; y < yLen; y++) {
yr = yearNumbers[y];
el = Ext.fly(yearItems[y]);
if (dmyMatch.toString().indexOf(yr) == -1) {
el.dom.setAttribute('data-qtip', dmyText);
el.addCls(disabledCls);
}
if (yr == year) {
yrInView = true;
}
}
if (year != null && yrInView) {
for (m = 0; m < mLen; m++) {
mNo = m;
if (mNo < monthOffset) {
mNo = mNo * 2;
} else {
mNo = (mNo - monthOffset) * 2 + 1;
}
mt = months.elements[mNo];
if (dmyMatch.test(mt.text + "/" + year)) {
mt.setAttribute('data-qtip', dmyText);
mt.className = disabledCls + ' ' + mt.className;
}
}
} else {
//Add tooltip 'disabled'
months.set({
'data-qtip': dmyText
});
months.addCls(disabledCls);
}
}
}
},
//Disable month and year click for disabled values
onMonthClick: function (target, isDouble) {
var me = this;
if (!me.disabled && !Ext.fly(target).hasCls(me.disabledCls)) {
//default Extjs code
}
},
onYearClick: function (target, isDouble) {
var me = this;
if (!me.disabled && !Ext.fly(target).hasCls(me.disabledCls)) {
//default Extjs code
}
}

create a decimal star rating for a comment in angularjs

Here is a code which present star rating code in angularjs. In some point I need to have a average of all the rating in whole the system so instead of rate:2 , i will have 2.4 . In such case i am interesting to present 2 star which are complete fill and one which has only half filled. How can I change my code in order to add this functionality?
Moreover, initially I would like to don't specify any star filled. That's also need a modification which I am not sure how should be done?
<div ng-app="app" ng-controller="RatingCtrl" class="container">
<h1>Angular Star Rating Directive</h1>
<div star-rating ng-model="rating1" max="10" on-rating-selected="rateFunction(rating)"></div>
<star-rating ng-model="rating2" readonly="isReadonly"></star-rating>
<label>
<input type="checkbox" ng-model="isReadonly" /> Is Readonly
</label>
<div><strong>Rating 1:</strong> {{rating1}}</div>
<div><strong>Rating 2:</strong> {{rating2}}</div>
</div>
In my directive
angular.module("app", [])
.controller("RatingCtrl", function($scope) {
$scope.rating1 = 1;
$scope.rating2 = 2;
$scope.isReadonly = true;
$scope.rateFunction = function(rating) {
console.log("Rating selected: " + rating);
};
})
.directive("starRating", function() {
return {
restrict : "EA",
template : "<ul class='rating' ng-class='{readonly: readonly}'>" +
" <li ng-repeat='star in stars' ng-class='star' ng-click='toggle($index)'>" +
" <i class='fa fa-star'></i>" + //&#9733
" </li>" +
"</ul>",
scope : {
ratingValue : "=ngModel",
max : "=?", //optional: default is 5
onRatingSelected : "&?",
readonly: "=?"
},
link : function(scope, elem, attrs) {
if (scope.max == undefined) { scope.max = 5; }
function updateStars() {
scope.stars = [];
for (var i = 0; i < scope.max; i++) {
scope.stars.push({
filled : i < scope.ratingValue
});
}
};
scope.toggle = function(index) {
if (scope.readonly == undefined || scope.readonly == false){
scope.ratingValue = index + 1;
scope.onRatingSelected({
rating: index + 1
});
}
};
scope.$watch("ratingValue", function(oldVal, newVal) {
if (newVal) { updateStars(); }
});
}
};
});
and css
.rating {
margin: 0;
padding: 0;
display: inline-block;
}
.rating li {
padding: 1px;
color: #ddd;
font-size: 20px;
text-shadow: .05em .05em #aaa;
list-style-type: none;
display: inline-block;
cursor: pointer;
}
.rating li.filled {
color: #fd0;
}
.rating.readonly li.filled {
color: #666;
}
http://codepen.io/anon/pen/RPLJYW
Thank you for any help.
You could use two identical set of stars to achieve this, position absolute one on top of the other. One fills your background star shapes (gray) and the one position at the top will represent your fill.
The top set of stars are all filled but its container's width can be adjusted to the proportion of stars representing your rate.
var score = 2.4;
var maxStars = 5;
var starContainerMaxWidth = 100; //pixls
var filledInStarsContainerWidth = score / maxStars * starsMaxWidth;
A CSS overflow hidden will hide the portion of stars that are not turned on, in effect allowing you to show 2.4 stars filled.
Update:
I have bashed a quick example http://codepen.io/anon/pen/NqazVa , will need some tidy up and reshuffling but the average rate is calculated and displayed correctly.
Check the AngularUI Bootstrap Rating component.
http://angular-ui.github.io/bootstrap/#/rating

How can I load youtube videos with angularjs?

I am trying to delay loading of youtube videos via javascript code as explained here.
and here is the code for that:
function optimizeYouTubeEmbeds() {
// Get all iframes
var frames = document.getElementsByTagName('iframe');
// Loop through each iframe in the page.
for (var i = 0; i < frames.length; i++) {
// Find out youtube embed iframes.
if (frames[i].src && frames[i].src.length > 0 && frames[i].src.match(/http(s)?:\/\/www\.youtube\.com/)) {
// For Youtube iframe, extract src and id.
var src = frames[i].src;
var p = /^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/;
var id = (src.match(p) ? RegExp.$1 : false);
if (id == false) { continue; }
// Get width and height.
var w = frames[i].width;
var h = frames[i].height;
if (src == '' || w == '' || h == '') { continue; }
// Thease are to position the play button centrally.
var pw = Math.ceil(w / 2 - 38.5);
var ph = Math.ceil(h / 2 + 38.5);
// The image+button overlay code.
var code = '<img src="http://i.ytimg.com/vi/' + id + '/hqdefault.jpg" style="" />';
// Replace the iframe with a the image+button code.
var div = document.createElement('div');
div.innerHTML = code;
div = div.firstChild;
frames[i].parentNode.replaceChild(div, frames[i]);
i--;
}
}
}
// Replace preview image of a video with it's iframe.
function LoadYoutubeVidOnPreviewClick(id, w, h) {
var code = '<iframe src="https://www.youtube.com/embed/' + id + '/? autoplay=1&autohide=1&border=0&wmode=opaque&enablejsapi=1" width="' + w + '" height="' + h + '" frameborder=0 allowfullscreen style="border:1px solid #ccc;" ></iframe>';
var iframe = document.createElement('div');
iframe.innerHTML = code;
iframe = iframe.firstChild;
var div = document.getElementById("skipser-youtubevid-" + id);
div.parentNode.replaceChild(iframe, div);
}
This code worked before switching my project to the angular way of doing things.
I initially thought I could just wrap that code in a $scope and call it, but that did not work. Here is my code that retrieves the videos:
$scope.renderHtml = function (html) {
return $sce.trustAsHtml(html);
};
$scope.Videos = [];
$scope.getVideos = function() {
// api call
$http.get('/api/Videos/AllVideos')
.success(function(data) {
$scope.Videos = data;
});
};
$scope.getVideos();
and here is the html tag where it is rendered:
<div ng-repeat="vid in Videos">
<div ng-bind-html="renderHtml(vid.url)"></div>
</div>
The vid.url includes all the iframe tag information etc. What do I need to do to make this work?

Resources