Vuejs same function on multiple divs need to run seperately - vue.js

Alright, I have these two divs with a mouseover and they have the same function. Now the problem is that if I mouse over one of them then BOTH shines. How to solve this? So shines one by one when I hover them.
DIVS:
<div class="latestItemBody" #mouseover="shineItemIcon"
#mouseout="shineOff" :style="{background: activeCardBg}">
<div class="latestItemBody" #mouseover="shineItemIcon"
#mouseout="shineOff" :style="{background: activeCardBg}">
Functions:
methods: {
shineItemIcon() {
this.activeCardBg = '#7a00ff';
this.bounce = 'animated bounceIn';
},
shineOff() {
this.activeCardBg = '';
this.bounce = '';
}

The reason why they both "shine" is because you have activeCardBg bound to both of them, which changes the background.
You could add the shine effect with pure CSS like this instead.
// CSS
.latestItemBody:hover {
background-color: #7a00ff
}
If you want to do this with JS, it could be done like this.
// Template
<div
class="latestItemBody"
#mouseover="shineItemIcon"
#mouseout="shineOff">
</div>
<div
class="latestItemBody"
#mouseover="shineItemIcon"
#mouseout="shineOff">
</div>
// Methods
shineItemIcon(e) {
e.target.style.backgroundColor = '#7a00ff';
this.bounce = 'animated bounceIn';
},
shineOff(e) {
e.target.style.backgroundColor = '';
this.bounce = '';
}

pass the div id as parameter to the shineitemicon and shineoff function. depending upon the condition set 'activeCardBg' value. give activecardBg1 to first div and activeCardBg2 to second div.

Related

Trouble to find element depending from other element in testcafe page object model

Having problems implementing the locator lookup method depending on its parent in POM
Example of DOM (roughly):
<div class="lessons">
<div [data-test="lesson"]>
<div class="lesson__info">
<div ...>
<h2 [data-test="lessonTitle"]>FirstLesson</h2>
<div class"lesson__data">
<div [data-test="lessonDataButton"]>
<div class"lesson__controls">
<div [data-test="lessonStartButton"]>
<div [data-test="lesson"]>
<div class="lesson__info">
<div ...>
<h2 [data-test="lessonTitle"]>SecondLesson</h2>
<div class"lesson__data">
<div [data-test="lessonDataButton"]>
<div class"lesson__controls">
<div [data-test="lessonStartButton"]>
Example of my POM:
import { Selector, t } from 'testcafe'
class Page {
constructor() {
this.lesson = Selector('[data-test="lesson"]')
this.lessonDataBtn = Selector('[data-test="lessonDataButton"]')
this.lessonStartBtn = Selector('[data-test="lessonStartButton"]')
this.lessonTitle = Selector('[data-test="lessonTitle"]')
}
async getLessonButton(title, lessonButton) {
const titleLocator = this.lessonTitle.withText(title);
const currentLesson = this.lesson.filter((node) => {
return node.contains(titleLocator())
}, { titleLocator });
const buttonSelector = currentLesson.find((node) => {
return node === lessonButton();
}, { lessonButton });
return buttonSelector;
}
In my test I'm trying to click "lessonDataButton" in specific lesson filtered by its "title":
await t.click(await schedule.getLessonButton(testData.lesson.data.title, page.lessonDataBtn))
It works correctly only for first occurrence of "lessonDataBtn" on page, but if I try to find the same button in second lesson - it will be an error:
The specified selector does not match any element in the DOM tree.
> | Selector('[data-test="lesson"]')
| .filter([function])
| .find([function])
I created an example using the code samples you provided and got a different error:
1. The specified selector does not match any element in the DOM tree.
| Selector('[data-test="lesson"]')
| .filter([function])
> | .find([function])
But I believe the case is the same: the lessonButton() call in the filter function of the find method of the currentLesson selector will always return the first node of the set. A straightforward solution is to search for the button directly with the css selector: const buttonSelector = currentLesson.find('[data-test="lessonDataButton"]');. You also can get rid of filter functions completely:
getLessonButton (title) {
return this.lessonTitle.withText(title)
.parent('[data-test="lesson"]')
.find('[data-test="lessonDataButton"]');
}

Vue: need to disable all inputs on page

I'm developing an app that has different license types, and according to the license we need to disable/enable inputs.
One way is to put a conditional :disabled for each input but that's a lot of work and error prone, since we might forget to put it on some inputs.
I thought of using a directive like v-disable-all that searches for all inputs under the container and adds disabled to them.
I was wandering if there is a better solution or if there is already a solution like this?
I ended up creating this directive:
import Vue from "vue";
Vue.directive("disable-all", {
// When all the children of the parent component have been updated
componentUpdated: function(el, binding) {
if (!binding.value) return;
const tags = ["input", "button", "textarea", "select"];
tags.forEach(tagName => {
const nodes = el.getElementsByTagName(tagName);
for (let i = 0; i < nodes.length; i++) {
nodes[i].disabled = true;
nodes[i].tabIndex = -1;
}
});
}
});
I'am coming a bit late, but there is an attribute on the HTML element called "disabled", which ... disable every input in the tree.
<fieldset :disabled="!canEdit">
...
</fieldset>
canEdit could be a computed property or anything you want.
You can do something like this:
let elems = document.getElementById('parentDiv').getElementsByTagName('input');
This will give you all the inputs inside a parent, then you can run a simple for loop to loop over them and set each one to disabled.
Something like this:
for(let i = 0; i < elems.length; i++) {
elems[i].disabled = true;
}
Hope this helps set you on the right path.
let elems = document.getElementById('someid').getElementsByTagName('input');
console.log(elems);
for(let i = 0; i < elems.length; i++) {
elems[i].disabled = true;
}
<html>
<body>
<div id="someid">
<input type="text">
<input type="text">
<input type="text">
<input type="text">
<input type="text">
</div>
</body>
</html>
Now you just need to wrap your fields inside <v-form :disabled="variable"></v-form>

Custom attribute not working on dynamic content

I'm using w2ui grid, and the template column generated like so:
{ field: 'TableCards', caption: 'Table cards', size: '10%', sortable: true ,
render:function(record, index, column_index) {
let html = '';
if (record.TableCards) {
record.TableCards.forEach(function(card) {
html += `<div class="card-holder" style="width: 12%; display: inline-block; padding: 0.5%;">
<div class="poker-card blah" poker-card data-value="${card.value}"
data-color="${card.color}"
data-suit="&${card.suit};"
style="width: 30px;height: 30px">
</div>
</div>`;
});
}
return html;
}
},
poker-card as u can see is a custom attribute. and it's not get rendered in the grid.
any other way?
You can use the TemplatingEngine.enhance() on your dynamic HTML.
See this article for a complete example: http://ilikekillnerds.com/2016/01/enhancing-at-will-using-aurelias-templating-engine-enhance-api/
Important note: based on how your custom attribute is implemented, you may need to call the View's lifecycle hooks such as .attached()
This happened to me, when using library aurelia-material, with their attribute mdl.
See this source where the MDLCustomAttribute is implemented, and now see the following snippet, which shows what I needed to do in order for the mdl attribute to work properly with dynamic HTML:
private _enhanceElements = (elems) => {
for (let elem of elems) {
let elemView = this._templEngine.enhance({ element: elem, bindingContext: this});
//we will now call the View's lifecycle hooks to ensure proper behaviors...
elemView.bind(this);
elemView.attached();
//if we wouldn't do this, for example MDL attribute wouldn't work, because it listens to .attached()
//see https://github.com/redpelicans/aurelia-material/blob/5d3129344e50c0fb6c71ea671973dcceea14c685/src/mdl.js#L107
}
}

getElementsByTagName of all siblings

UPDATE:
Let me rephrase.
I have multiple divs that all contain, among other things, an img element with the class="yes". But they're not all the same siblings.
Two examples:
<div id="div1" onclick="function(this)">
<img src="image1" />
<div>
<img src="image2" class="yes" />
</div>
</div>
<div id="div2" onclick="function(this)">
<img src="image3" class="yes" />
</div>
Now I'm trying to formulate one function for both divs that would change the source of the image with class yes.
getElementsByTagName doesn't seem to do the trick, nor does getElementsbyClassName.
Any thoughts? Thanks again!
getElementsByTagname is the wrong function.
There is no easy way to do what you're trying to do, unless you resort to third party libraries such as jQuery.
With jquery, you use this code:
$('img.yes').each(function() {
console.log(this);
});
Here is a working example of what you're trying to do: http://jsfiddle.net/ZYBp6/
You can use jQuery like this:
function some_function(x)
{
var arr = $("#" + x.id + " .yes"); // Gets all children of the class "yes"
}
Or if you only want to get img elements, you can do this instead:
function some_function(x)
{
var arr = $("#" + x.id + "img.yes");
}
In both of these examples, arr would contain DOM elements, and not the kind of "element" produced by jQuery normally.
This seems to work:
function function(x) {
$(x).find('.yes').attr('src','differentimage.png');
}

Can I bind data to data-win-options?

I use the control MicrosoftNSJS.Advertising.AdControl in the ItemTemplate of a ListView.
I would like to bind some datas to the following data-win-options properties : ApplicationId and AdUnitId
The source datas are correctly set and are visible in my item template, I can display them with an h2 + a classic data-win-bind on innerText property
Ads are displayed correctly if I put directly static IDs in html code but these IDs need to be loaded from a config file...
Is it possible ? Thanks
If it's not possible, can I modify directly the item template in the JS code before to be injected in the listview ?
Come to find out this is possible (I was trying to do something similar)
The syntax for the control properties must be prefixed with winControl.
Example (I'm setting the application id here but binding the html element's className and the ad control's adUnitId)
<div id="adItemTemplate" data-win-control="WinJS.Binding.Template">
<div data-win-bind="className:css; winControl.adUnitId: adUnitId"
data-win-control="MicrosoftNSJS.Advertising.AdControl"
data-win-options="{ applicationId: 'd25517cb-12d4-4699-8bdc-52040c712cab'}">
</div>
</div>
I finally found a way to perform this without real binding, by using the itemTemplateSelector function like this :
function itemTemplateSelector(itemPromise)
{
return itemPromise.then(function (item)
{
if (item.type == "ad")
{
var template = _$(".adTemplate").winControl.render(item, null);
// Access to the AdControl through the DOM
var adControl = template._value.childNodes[1].childNodes[1].winControl;
// Set options that are specified in the item
WinJS.UI.setOptions(adControl, { applicationId: item.AdAppId, adUnitId: item.AdUnitId });
return template;
}
else
{
return _$(".itemTemplate").winControl.render(item, null);
}
}
}
I had this problem in ratings:
<div data-win-control="WinJS.UI.Rating" data-win-options="{averageRating: 3.4, onchange: basics.changeRating}"></div>
I bind it via winControl:
<div data-win-control="WinJS.UI.Rating" data-win-bind="winControl.averageRating: myrating" data-win-options="{onchange: basics.changeRating}"></div>
It worked fine.
<div data-win-bind="this['data-list_item_index']:id WinJS.Binding.setAttribute" >