IntroJs hints
How can I skip or hide when a parent element is not visible? For some reason only inline seems to be working for my hints.I have the data-hints in spans on the HTML and I need to check if the nearest element is visible or parent/child element.
var hints = false;
var all = document.getElementsByTagName("*");
function introFunction() {
for (var i = 0, max = all.length; i < max; i++) {
if ((isHidden(all[i]) && hints));
document.getElementById("#helpFunc").html("Show Help");
introJs().hideHints();
} else {
document.getElementById("#helpFunc").html("Hide Help");
introJs().showHints();
}
hints = !hints;
function isHidden(el) {
var style = window.getComputedStyle(el);
return ((style.display === 'none') || (style.visibility === 'hidden'));
}
}
Instead of trying to get the computed style of the element, try checking the element bounding rectangles - if there aren't any, it means the element is not visible.
!!el.getClientRects().length; // false means el or its parent(s) is hidden
LE: that doesn't work for "visibility: hidden;" though. So maybe you can combine the above with what you already have.
Related
class CoinData {
var _controller = StreamController<Map<String,dynamic>>();
.....
Stream<Map<String,dynamic>> getAllCurrentRates() {
int numAssets = 0;
int counter = 0;
this.listAllAssets()
.then((list) {
if (list != null) {
numAssets = list.length;
List<Map<String, dynamic>>.from(list)
.where((map) => map["type_is_crypto"] == 1)
.take(3)
.map((e) => e["asset_id"].toString())
.forEach((bitCoin) {
this.getCurrentRate(bitCoin)
.then((rate) => _controller.sink.add(Map<String,dynamic>.from(rate)))
.whenComplete(() {
if (++counter >= numAssets) _controller.close();
});
});
}
});
return _controller.stream;
}
.....
}
The length of returned list is around 2500 and this value is assumed by numAssets, however as you see that list is modified later and therefore its length is less, then the evaluation (++counter >= numAssets) is incorrect. So, is it possible to fix that code maintaining its current structure?
.take(3) is temporal, it shall be removed later.
I'm trying to solve what seems like a fairly simple problem with a couchDb view, but I'm not even getting close to the target with my result set.
Rather than updating documents, I'm creating a new document every time as my versioning strategy, and tying those documents together with a versioning field called ver. The very first document in a version chain will see the ver field and the _id field having the same value. All subsequent documents in the chain will have the same ver field as previous docs in the chain, but will have a unique _id field. These documents also have a createdTime field which is my way of knowing which document is the latest.
Here's my documents:
{
"_id": "abcd-1234-efgh-9876",
"ver": "abcd-1234-efgh-9876",
"createdTime": "2020-01-12 01:15:00 PM -0600",
...
},
{
"_id": "uopa-3849-pmdi-1935",
"ver": "abcd-1234-efgh-9876",
"createdTime": "2020-02-16 02:39:00 PM -0600",
...
}
Here's my map function:
function (doc) {
emit(doc.ver, doc);
}
Here's my reduce function:
function(keys, values, rereduce) {
var latestVersions = {};
for (var i = 0; i < keys.length; i++) {
var found = latestVersions[keys[i][0]];
if (!found || found.createdTime < values[i].createdTime) {
latestVersions[keys[i][0]] = values[i];
}
}
return latestVersions;
}
And finally, here's my desired output from the view (just the doc that I want):
{
"_id": "uopa-3849-pmdi-1935",
"ver": "abcd-1234-efgh-9876",
"createdTime": "2020-02-16 02:39:00 PM -0600",
...
}
What am I missing here? The reduce function is returning both records, which is not what I want. Is what I'm trying to achieve possible or is there a better way to go about this?
Update
I was able to get this to work when a single key is used to access the view, which is one of my use cases.
function (keys, values, rereduce) {
var toReturn = values[0];
for (var i = 1; i < values.length; i++) {
if (values[i].createdTime > toReturn.createdTime) {
toReturn = values[i];
}
}
return toReturn;
}
I have another use case that will be returning all of the data in the view, however. The desired result there is the same as above, but the function I'm using for single keys will only ever return one result. How do I filter multiple values with a shared key such that 1 "shared" key:n values -> 1 key:1 value.
I was finally able to resolve this when I stumbled upon this couchbase article. It was much more articulate than some of the other dry computer-science documentation.
I still do not understand why certain items are grouped in a reduce method and other ones are not. For example, reduce was called 5 times for 6 items that shared an identical key; only one of the keys had actually grouped anything -- an array of two documents. It probably has something to do with those dry computer-science B-tree documents I glossed over.
Anyway, I was able to determine that all I needed to do was group the values by the ver field in both scenarios (the only difference being that rereduce had a 2 dimensional array). Here's what my reduce function ended up looking like:
function (keys, values, rereduce) {
var toValues = function(myMap) {
return Object.keys(myMap).map(function(key) {
return myMap[key];
});
}
if (rereduce) {
// values should look like [[{...}, {...}], [{...}]]
var outputMap = {};
for (var i = 0; i < values.length; i++) {
for (var j = 0; j < values[i].length; j++) {
var currentEl = values[i][j];
var found = outputMap[currentEl.ver];
if ((found && found.createdDate < currentEl.createdDate) || !found) {
outputMap[currentEl.ver] = currentEl;
}
}
}
return toValues(outputMap);
} else {
var outputMap = {};
for (var i = 0; i < values.length; i++) {
var found = outputMap[values[i].ver];
if ((found && found.createdDate < values[i].createdDate) || !found) {
outputMap[values[i].ver] = values[i];
}
}
return toValues(outputMap);
}
}
I have left/right arrows on a page and I want to pick the animation without having to define a relationship between all the routes. Is it possible to set it on the {{link-to}}? Right now it's pretty brittle.
I have been looking, and I don't think it's possible to know what link was clicked from the transition it caused. However, I can think of two different ways to tackle your use case.
Solution 1: metaprogramming
Make a list of your routes and generate transitions dynamically from it. Something like this:
// app/transitions.js
export default function() {
const orderedRoutes = [
'left-route',
'center-route',
'right-route',
];
// See https://github.com/coleww/each-cons
// where I pinched this from
function eachCons(a, n) {
var r = []
for (var i = 0; i < a.length - n + 1; i++) {
r.push(range(a, i, n))
}
return r
}
function range (a, i, n) {
var r = []
for (var j = 0; j < n; j++) {
r.push(a[i + j])
}
return r
}
eachCons(orderedRoutes, 2).forEach(pair => {
// `pair` will be each pair of consecutive routes
// on our `orderedRoutes` list
const left = pair[0];
const right = pair[1];
// For each pair, define a transition
this.transition(
this.fromRoute(left),
this.toRoute(right),
this.use('toLeft'),
this.reverse('toRight')
);
});
}
Note that I only define transitions for adjacent routes. If you want to define a transition between left-route and center-route, you'll need to alter the algorithm to define new combinations.
Solution 2: callback to fromRoute
The function fromRoute can not only take a string, but also a function. This function receives two parameters: the names of the initial and the final routes of a transition. In this function you can return true if the transition should apply, and false otherwise. See here:
http://ember-animation.github.io/liquid-fire/#/transition-map/route-constraints
You can use this function to decide whether you should be going left or right (as per your use case). See this:
// app/transitions.js
export default function() {
// Names of the routes in the left-right succession
const orderedRoutes = [
'left-route',
'center-route',
'right-route',
];
function isLeft(initial, destination) {
const i0 = orderedRoutes.indexOf(initial);
const i1 = orderedRoutes.indexOf(destination);
if (i0 === -1 || i1 === -1) {
// This is not one of the transitions
// in the left-right succession
return false;
}
if (i0 === i1) {
// They are the same route
return false;
}
// This will be `true` if the initial route
// is "to the left" of the destination route
return i0 < i1;
}
this.transition(
this.fromRoute(isLeft),
this.use('toLeft')
this.reverse('toRight')
);
}
In this example, for each transition we check the initial and the destination route. We see if they belong to the left-right succession, and whether the transition corresponds to a "left" or a "right". If it's a "left" we return true in the "toLeft" case. If it's a "right", we return true in the "toRight" case.
I want to create a dropdown menu With English or German as the options in Javascript / jQuery that checks that:
check if on a domain - say happy.com/pizza
if german is selected on dropdown
redirect user to
happy.de/pizza
and I could have a list
if happy.com/pizza got to happy.de/pizza
happy.com/coke got to happy.de/coke
happy.com/juice got to happy.de/juice
etc etc.
I have written the code yet but how would one go about this?
Thanks!
I have written some code but I just need a little help please:
In this scenario I am on the www.something.com/beer page and want it to go to the German Beer Page!
<select>
<option value="1">English</option>
<option value="2">German</option>
</select>
if(value == 2) && is current domain www.something.com/beer{
window.top.location.href = 'www.something.de/beer';
}else if(value == 2) && is current domain www.something.com/cheese{
window.top.location.href = 'www.something.de/cheese';
}else{
do nothing
}
How do I get this to check the value of the dropdown and the domain is currently on?
Here is my Jsfiddle
http://jsfiddle.net/msasz2an/
Thanks again!
function current(arr) {
// discuss at: http://phpjs.org/functions/current/
// original by: Brett Zamir (http://brett-zamir.me)
// note: Uses global: php_js to store the array pointer
// example 1: transport = ['foot', 'bike', 'car', 'plane'];
// example 1: current(transport);
// returns 1: 'foot'
this.php_js = this.php_js || {};
this.php_js.pointers = this.php_js.pointers || [];
var indexOf = function (value) {
for (var i = 0, length = this.length; i < length; i++) {
if (this[i] === value) {
return i;
}
}
return -1;
};
// END REDUNDANT
var pointers = this.php_js.pointers;
if (!pointers.indexOf) {
pointers.indexOf = indexOf;
}
if (pointers.indexOf(arr) === -1) {
pointers.push(arr, 0);
}
var arrpos = pointers.indexOf(arr);
var cursor = pointers[arrpos + 1];
if (Object.prototype.toString.call(arr) === '[object Array]') {
return arr[cursor] || false;
}
var ct = 0;
for (var k in arr) {
if (ct === cursor) {
return arr[k];
}
ct++;
}
// Empty
return false;
}
I would really appreciate some help with this problem. It may be easy to solve but I just can't figure out how to go about coding it. I have a map based on this Geocodezip Example Categories which displays markers and has a sidebar next to it. The markers belong to one of three categories and based on whether the checkboxes are checked, the markers will appear on the map.
function show(category) {
for (var i=0; i<gmarkers.length; i++) {
if (gmarkers[i].mycategory == category) {
gmarkers[i].setVisible(true);
}
}
document.getElementById(category+"box").checked = true;
}
function hide(category) {
for (var i=0; i<gmarkers.length; i++) {
if (gmarkers[i].mycategory == category) {
gmarkers[i].setVisible(false);
}
}
document.getElementById(category+"box").checked = false;
infowindow.close();
}
At the same time, I am trying to display the markers' info in the sidebar but under two conditions:
the marker category must be checked &
the marker must be contained in the map viewport/bounds
I then added one code for the sidebar that only displays the markers for checked categories and one where the info is shown in the sidebar when the markers are in the viewport. However, I can only do these separately (for to completely different codes) and cannot get both conditions to work together. These are the two examples that I am trying to merge:
Include in sidebar if box is checked
function makeSidebar() {
var side_bar_html = "";
for (var i=0; i<gmarkers.length; i++) {
if (gmarkers[i].getVisible()) {
side_bar_html += '<a href="javascript:myclick(' + i + ')">' + gmarkers[i].myname + '<\/a><br>';
}
}
document.getElementById("side_bar").innerHTML = side_bar_html;
}
(when bounds change) Include in sidebar if marker is contained within bounds
function makeSidebar() {
google.maps.event.addListener(map, 'bounds_changed', function() {
var side_bar_html = "";
var bounds = map.getBounds();
for (var i=0; i<gmarkers.length; i++) {
if (bounds.contains(gmarkers[i].position)) {
side_bar_html += '<a href="javascript:myclick(' + i + ')">' + gmarkers[i].myname + '<\/a><br>';
}
}
document.getElementById("side_bar").innerHTML = side_bar_html;
});
}
I tried putting the two together in a combined if statement (&&) within the if bounds.contains statement but the sidebar won't change if a box is checked/unchecked.
Add the check to makeSidebar only when the map bounds is available:
// == rebuilds the sidebar to match the markers currently displayed ==
function makeSidebar() {
var html = "";
for (var i=0; i<gmarkers.length; i++) {
if (gmarkers[i].getVisible() &&
map.getBounds &&
map.getBounds() &&
map.getBounds().contains(gmarkers[i].getPosition())) {
html += '<a href="javascript:myclick(' + i + ')">' + gmarkers[i].myname + '<\/a><br>';
}
}
document.getElementById("side_bar").innerHTML = html;
}
execute makeSidebar when the bounds_changed event fires:
google.maps.event.addListener(map, 'bounds_changed', makeSidebar);
working fiddle