Dojo Tooltip Attach to Multiple Nodes: Element Selector Works, but not Class Selector - css-selectors

I'm trying to use dojo Tooltips on a series of SVG elements that are tool buttons in my header. I'm using the method in the docs of attaching tooltips to multiple nodes like this:
new Tooltip({
connectId: query('.header'),
selector: 'svg',
position: ['below'],
getContent: function (e) {
return e.getAttribute('data-tooltiptext');
}
});
And that works, but if I use a selector of '.tool' (every SVG has a class of tool on it) my getContent function never gets called. 'svg.tool' doesn't work as a selector either. The docs an several examples around the net claim class selectors will work, but I've only been able to get element selectors to work.
I'm requiring 'dojo/query' and I've tried using 'dojo/query!css3' but that doesn't seem to make a difference. I don't know if it makes a difference, but I'm using dojo included with ESRI's ArcGIS JS API library, which reports a dojo version of 1.14.2.

I've experienced the same issue when using the selector attribute while creating a Menu. Within an SVG element, element selectors (even comma-concatenated ones) work, but class selectors do not. Outside of the SVG element, they worked just fine. You can play around with this by using dojo.query in your browser's console to see which elements get selected.
I was able to solve the issue by changing the selectorEngine in my dojo config. Using any of css3, css2.1, and css2 worked, so I think the issue may be in the acme engine. If you don't already have a dojo config, you can add it via a script tag:
<script>
var dojoConfig = {
selectorEngine: 'css3',
};
</script>

Related

Cypress: access custom defined css property

I am building an APP using React + chakra-ui and I am in the process of adding Cypress tests to it, but I am facing a blocker and I was wondering if anyone had faced a similar problem and that could help!
Problem:
The test I am trying to pass is to verify that my element contains a CSS property, however, the CSS was generated by Charkaui with their unique syntax (e.g --chakra-scale-x)
My test case is as follow
cy.get('MY_ELEMENT')
.should('be.visible')
.should('have.css', '--chakra-scale-y', 1);
This test gave me the error
expected '<div.css-o64oke>' to have CSS property '--chakra-scale-x'
even though I can see from inspect element that it does have the following property.
Does anyone know a solution or a workaround for this? Thanks in advance!
Edit:
--chakra-scale-y is a css variable, which will be applied (probably as a transform) by the browser css engine.
Take a look in the devtools Computed tab (unselect Show all to see just those applied). If a transform shows up, this is what you need to test for.
In the test use getComputedStyle to check the value identified above.
cy.get('MY_ELEMENT')
.then($el => {
const win = cy.state('window')
const styles = win.getComputedStyle($el[0])
const transform = styles.getPropertyValue('transform')
console.log(transform)
expect(transform).to.eq(...)
})
It looks like you need to check scaleY, this is from the chakra library
const transformTemplate = [
"rotate(var(--chakra-rotate, 0))",
"scaleX(var(--chakra-scale-x, 1))",
"scaleY(var(--chakra-scale-y, 1))",
"skewX(var(--chakra-skew-x, 0))",
"skewY(var(--chakra-skew-y, 0))",
]

ChartistJS : Converting jQuery solution to AngularJS

I am using Chartist JS for my charts in my Angular JS app. The issue is I am seeing this here. There is a JS bin that highlights the issue. The author gives a solution for it. The solution is doing DOM manipulations in Jquery which is easy to do. However with AngularJS the way you manipulate the DOM is via Directives. I have created a plunker here which highlights the same issue in Angular JS but I am confused as to how to put the solution provided by author into my Angular code.
Here is the solution
$('[data-tab]').on('toggled', function (event, tab) {
tab.find('.ct-chart').each(function(i, e) {
e.__chartist__.update();
});
});
Edit: As requested the JSFiddle is updated, so what I am trying to do is. I have three different tabs and three different graphs, whenever I click on them I should see the respective graph. To make the tab behavior possible I have written a basic code using scope and model. which facilitates the changing of tabs. The issue is that the chart is getting created for first or default tab but not for the second and third tab. There is a solution given by the author but I don't know how to implement that in AngualrJS
the jQuery solution that you post is basically finding all the chart references and then doing DOM manipulation and call the update() function.
The key is how to find the chart to update in Angular.
In this case, you can assign a variable when you create a chart. For example:
var chart4 = new Chartist.Bar('#chart4', data1);
var chart5 = new Chartist.Bar('#chart5', data2);
Now you have the reference of the chart. All you have to do is to call update() function to render the chart again.
if (value === "allDrivers") {
$scope.tab = "All";
chart4.update();
}
Here is the working plunker
One thing I like to point out is: right now you need to double click the tab in order to see the chart is being rendered or you resize the browser window. I am still trying to find a way to fix this. But at least this approach gives you an idea how to convert the jQuery solution to Angular solution.
I was able to solve this using angular.element() method. So if you wish you use jquery in your angular code. You have to do this via angular.element method. But make sure to include jquery before angular in your index.html
If jQuery is available, angular.element is an alias for the jQuery
function. If jQuery is not available, angular.element delegates to
Angular's built-in subset of jQuery, called "jQuery lite" or jqLite.
I did not know this. From here it was learning for me. Following advice of #pieterjandesmedt from this post. I was able to do this. For other people who want to learn how this works. I have created a GitHub repo which gives a solution to this issue. The link for problem is given in the question. Hope that helps

Material Design Lite rendering problems with Angular JS

I have some problems using Material Design Lite (getmdl.io). I followed the steps showed in the getmdl.io web in order to install it (actually I use bower), but I always have the same problem, when I change the ng-route in my web, some resources don't render properly, I need to reload the page to get it properly rendered, for example.
First I have this:
then when I reload, I get what I want:
What I cant understand is why other resources like google icons or buttons work correctly but the menu button on the nav bar and other resources like this one need to reaload the page in order to render properly.
I try to include the library using the hosted method and bower method.
Any idea what is going on?
i past in my code this function
angular.module('app', ['ngRoute']).
run(function($rootScope, xxxx, xxx){
$rootScope.$on('$viewContentLoaded', function(event, next) {
componentHandler.upgradeAllRegistered();
});
});
It worked perfect! Good luck..
Libraries like MDL work by waiting for the page to load using the DOMContentLoaded event, scanning the page for things like input elements and manipulating them with JavaScript so that they can inject the bits and pieces needed to work with their components. This works fine on static websites, but the DOMContentLoaded event only fires once, so when Angular performs a page transition, the DOM changes without MDL knowing about it.
Material Design Lite has a section in its FAQ about using MDL on dynamic websites:
Material Design Lite will automatically register and render all elements marked with MDL classes upon page load. However in the case where you are creating DOM elements dynamically you need to register new elements using the upgradeElement function. Here is how you can dynamically create the same raised button with ripples shown in the section above:
<div id="container"/>
<script>
var button = document.createElement('button');
var textNode = document.createTextNode('Click Me!');
button.appendChild(textNode);
button.className = 'mdl-button mdl-js-button mdl-js-ripple-effect';
componentHandler.upgradeElement(button);
document.getElementById('container').appendChild(button);
</script>
Of course, this probably isn't terribly easy to do in your case, since you'd have to manually find each new element and call upgradeElement on it.
Usually, instead of doing this sort of event-based DOM manipulation, Angular uses directives to initiate DOM changes. Consider using a library built to interoperate with Angular, instead, such as Angular Material.

Polymer-Angular two-way data binding for framework components (core-elements/paper-elements)

I am trying to blend Polymer web components in my Angular application, but I am not being able to get the two-way data binding between these frameworks working. I've already watched this video and already tried the solution provided in this question but it still doesn't work for me. These were my attempts:
Object attribute value
<game-card game="{{game}}" bind-polymer></game-card> - based on post-card.html on the Polymer tutorial. game is an object with id, title, etc.
I created the gameChanged function on the web component and added a new property in the game variable, something like this.game.foo = 'bar';, but if I do
<pre><code>{{game | json}}</code></pre>
right after the component, there's no "foo": "bar" in the stringified object. Even with
publish: {
game: {reflect: true}
},
it doesn't work.
Framework components
<core-input value="{{cool}}" bind-polymer></core-input>
<paper-input value="{{cool}}" bind-polymer></paper-input>
It only works if I edit the element's source code to reflect the value attribute (on core-input.html, as paper-input extends it). I think it isn't a good way of solving this issue.
Am I missing something? Is there a good resource I can look for this Angular-Polymer integration? Searching on Google brings more results about the material than about the library itself and, when found, most of them are "Polymer for Dart" resources.
Try with the NG Polymer Elements lib it solves the 2 way data binding of angular and polymer (core and paper elements) and some other stuff that breaks with angular/polymer, it also has the documentation to addyour own custom polymer elements to the angular binding support
NG Polymer Elements

ng-repeat moves dom elements around, which breaks a ckeditor because it doesn't support having it's dom elements moved

I'm trying have an ng-repeat which contains divs that include a CKEDITOR instance. The list is sortable by a few different properties. However, when the list is resorted, the CKEDITORs break because they don't support being moved around in the DOM. The only solution I can think of is to destroy the CKEDITOR instance before sort, and recreate them after. Is there any events on ng-repeat that can accomplish this?
plunkr here: http://plnkr.co/edit/tGnTdzvRl7xhEX7zYq4c?p=preview
Was able to get this fixed eventually. Pretty easy now that I think about, but took me 3 days to realize it. Instead of trying to listen for events on ng-repeat, catch the event that is causing the data to be modified. For me, it was jquery UI sortable (angular directive.) In the controller add $scope.$broadcast('unbind-ckeditor') before the change, and then $scope.$broadcast('rebind-ckeditor') after it. In your angularjs directive for ckeditor, call scope.$on('unbind-ckeditor', function() {instance.destroy /* instance is your ckeditor instance*/}); and then reload it in the rebind. Hope this helps someone.
Edit:
Make sure the $on('unbind-ckeditor'... is only added to the scope once, or multiple sorts will throw exceptions.
The solution for me:
use divArea and not iframe, this will work with ng-repeat when the list changed.
using other textarea (hidden) and monitoring it as the ng-sortable+ckeditor broke the order of CKEditors.
in ng-sortable (who make the change in the list) I was added this code:
$rootScope.$broadcast('rebind-ckeditor'); console.log("rebind")
and in CKEDITOR directive:
scope.$on('rebind-ckeditor', function () {
if (jQuery(element).data("loaded")) {
console.log("rebind");
CKEDITOR.instances[element[0].id].destroy();
jQuery(element).data("loaded", null);
element[0].value = $("textarea", element.parent())[1].value; // update manualy from the hidden textarea
onLoad(); //recreate CKE after textarea changed.
}
})

Resources