Using BEM in LESS like SASS using parents - less

I am trying to refrence the base class to change a sub class based on a BEM modifier.
This works well in SASS, but I'm working with LESS now.
Heres the SASS refrence...
https://css-tricks.com/the-sass-ampersand/
And heres the code that dosn't work...
.s-body {
#self: &;
...
&__door {
...
&--state-past {
#{#self}__image {
...
}
}
}
&__image {
...
}
}

It isn't possible in LESS to assign the current class to a variable using an ampersand (&). But you can set the class name as a variable like this:
.s-body {
#self: .s-body;
}
After that, you can use the variable as a selector like this: #{self}. For further explanation, check the LESS documentation: http://lesscss.org/features/#variables-feature-variable-interpolation
In your example, this will result in the following code:
.s-body {
#self: .s-body;
&__door {
&--state-past {
#{self}__image {
}
}
}
&__image {
}
}

Related

listop operator causing infinite recursion, any way to fix?

I'm looking to possibly help update the File::HomeDir module which was never finished. While inspecting it, I noticed that stubbed out methods were causing infinite loops:
In the File::HomeDir role:
unit class File::HomeDir;
use File::HomeDir::Win32;
use File::HomeDir::MacOSX;
use File::HomeDir::Unix;
my File::HomeDir $singleton;
method new
{
return $singleton if $singleton.defined;
if $*DISTRO.is-win {
$singleton = self.bless does File::HomeDir::Win32;
} elsif $*DISTRO.name.starts-with('macos') {
$singleton = self.bless does File::HomeDir::MacOSX;
} else {
$singleton = self.bless does File::HomeDir::Unix;
}
return $singleton;
}
method my-home {
return File::HomeDir.new.my-home;
}
method my-desktop {
return File::HomeDir.new.my-desktop;
}
<snip>
In the File::HomeDir::MacOSX module:
use v6;
unit role File::HomeDir::MacOSX;
method my-home {
# Try HOME on every platform first, because even on Windows, some
# unix-style utilities rely on the ability to overload HOME.
return %*ENV<HOME> if %*ENV<HOME>.defined;
return;
}
method my-desktop {
!!!
}
<snip>
With this code, calling say File::HomeDir.my-desktop; results in an infinite loop.
This module was first written about 5 1/2 years ago. I'm assuming it worked at the time. But it appears now that if a role method has a listop operator, it causes the parent's class to be called which then called the role method which then calls the parent class, etc.
I'd do it like this, staying close to the original design:
role File::HomeDir::Win32 {
method my-home() { dd }
method my-desktop() { dd }
}
role File::HomeDir::MacOSX {
method my-home() { dd }
method my-desktop() { dd }
}
role File::HomeDir::Unix {
method my-home() { dd }
method my-desktop() { dd }
}
class File::HomeDir {
my $singleton;
# Return singleton, make one if there isn't one already
sub singleton() {
without $singleton {
$_ = File::HomeDir but $*DISTRO.is-win
?? File::HomeDir::Win32
!! $*DISTRO.name.starts-with('macos')
?? File::HomeDir::MacOSX
!! File::HomeDir::Unix;
}
$singleton
}
method my-home() { singleton.my-home }
method my-desktop() { singleton.my-desktop }
}
File::HomeDir.my-home;
File::HomeDir.my-desktop;

WebdriverIO function reusability pattern

I am transitioning from Selenium to WebdriverIO and I'm running into some difficulty regarding function reusability. Let me demonstrate with an example:
<nav>
<div><a>Clients</a></div>
<div><a>Accounts</a></div>
<div><a>Packages</a></div>
</nav>
lets say I have a navigation bar with 3 links above. When I land on this page, I want to check if each link exists. My function may look something like this:
class LoginPage extends Page {
get clientsLink() { return $('//a[contains(., "Clients")]'); }
isTabDisplayed() {
if (this.clientsLink.isDisplayed()) {
return true;
} else {
false
}
}
}
this is fine except I would have to write 2 more getters for Accounts and Packages and so my class would look like this:
class LoginPage extends Page {
get clientsLink() { return $('//a[contains(., "Clients")]'); }
get accountsLink() { return $('//a[contains(., "Accounts")]'); }
get packagesLink() { return $('//a[contains(., "Packages")]'); }
isClientTabDisplayed(tab) {
if (this.clientsLink.isDisplayed()) {
return true;
} else {
false
}
}
isAccountsTabDisplayed(tab) {
if (this.accountsLink.isDisplayed()) {
return true;
} else {
false
}
}
isPackagesTabDisplayed(tab) {
if (this.packagesLink.isDisplayed()) {
return true;
} else {
false
}
}
}
at this point, my anxiety kicks in and I start to think of ways I can reuse the isTabDisplayed function where I can pass a string to the getter with my tab name, or something along the lines of that.
Unfortunately, getters do not accept parameters and so far I have not found any resources on google that can help me to solve this issue (most common being Page Object Model which doesn't seem to address this problem)
Is my thought process out of line that I am striving for reusable code in UI testing or am I not googling for correct patterns?
Page Objects in WebdriverIO are just plain ES6 classes. Have a look through the documentation on ES6 classes to understand how you can create functions that you can pass arguments in to.
Now, that being said, what you're doing here isn't necessary. Instead of creating a function which references a getter, why not just reference that getter directly in your test?
const login = new LoginPage();
const isAccountsTabDisplayed = login.accountsLink.isDisplayed();
There's really no reason to create a wrapper function around this.

How to check if no condition was met?

<Check Object "If there is not an object at (x,y)">
{
<Create Instance "create instance of object at (x,y)">
}
...
Using Game Maker events, I created a repeated process like the one above, checking one space and then the other, and filling all the empty ones. The code works fine, but I want to add a message at the end ONLY IF NONE OF THE SPACES ARE EMPTY. I tried using an ELSE at the end, but that only uses the very last if.
Sorry for bad wording, I can elaborate if needed.
What you want is an if-else if-else structure. You can do this by nesting conditions:
if () {
...
} else {
if(...) {
...
} else {
if(...) {
...
} else {
...
}
}
}
Though your code would be easier to read were it to use GML, rather than the visual language, as in GML you can do this:
if () {
...
} else if(...) {
...
} else if(...) {
...
} else {
...
}

Properties in a module

Is there a way to define a property in a TypeScript module?
None of these compile:
module My {
// doesnt work
get Value(): number { return 42; }
// doesn't work either
get function Value(): number { return 42; }
// nope
function get Value(): number { return 42; }
}
Right now I'm forced to use this:
module My {
declare var Value: number;
Object.defineProperty(My, "Value", {
get: () => 42
});
}
The second form seems messy to me and the code hinting doesn't really treat it as a read-only property but as a plain variable.
Is there any standard way of defining properties directly inside modules?
No, there's not a way to declare a property on a module in TypeScript using any documented language features.
You can do it in several slightly round-about techniques.
A module can extend an existing class or function. So, I've created a class with a static property, and then later created a module that uses the same name as the class.
class My
{
static get Value():Number {
return 42;
}
}
module My {
var works: boolean = true;
}
alert(My.Value);
It does generate one oddity in the JavaScript generated code that you wouldn't do manually (and should be removed by most optimizers anyway) ... it will redeclare the variable My when the module is created. This does not cause a run-time issue as the variable was already lifted in JavaScript and will not conflict with the first usage.
Here's another option:
module Global {
class Inner {
get Value():Number {
return 42;
}
}
export var My;
My = new Inner();
}
var My = Global.My;
alert(My.Value);
While it presents an extra namespace, you can manipulate it however you'd like and use the inner class or change it as needed. This way, the My variable is global, just like it would be as a module.
Instead of using the module keyword, consider instead using export, which will allow you to do what you want to do, treating the file itself as a module (which is how CommonJS and AMD both work).
// in My.ts
var My = {
get value() {
return 42;
}
};
export = My;
// in foo.ts
import My = require('My');
console.log(My.value);
I describe this in greater detail in a blog post, The Definitive Guide to TypeScript.
I tried the singleton
let My = {
get value() {
return 42;
}
}
export My
but ran into an issue where the emitted JS still said get value() and didn't work on older versions of Node. I tried Object.defineProperty but then lost TypeScript compatibility. Here's my bridge that fixes both cases:
interface My {
value: number
}
// type assertion fixes TypeScript usage
let my = <My>{}
// defineProperty fixes JS usage
Object.defineProperty(my, 'value', {
get: () => 42
});
export = my;
It's used like a module in typescript
import * as my from './my'
my.property // returns 42
// my.property = doesn't work
I know it's a "little" late for this but using typescript 4.8 you can do this:
export module MyModule {
export var myVariable: string = "test";
}
then use it like:
MyModule.myVariable = "something else";

setAttribute() function in YII is not working

I am using PHP Yii Framework with MongoDB(yiimongodbsuite). I have created a Model which extends from EMongoDocument.
<?php
class MyModel extends EMongoDocument
{
public $attr1;
public $attr2;
// rules, custom validations and other functions....
public function setAttributes($values, $safeOnly=true)
{
if(!is_array($values))
return;
if($this->hasEmbeddedDocuments())
{
$attributes=array_flip($safeOnly ? $this->getSafeAttributeNames() : $this->attributeNames());
foreach($this->embeddedDocuments() as $fieldName => $className)
if(isset($values[$fieldName]) && isset($attributes[$fieldName]))
{
$this->$fieldName->setAttributes($values[$fieldName], $safeOnly);
unset($values[$fieldName]);
}
}
parent::setAttributes($values, $safeOnly);
}
}
In Controller,
$dataModel = new MyModel();
$dataModel->setAttributes($_POST['MyModel']);
if($dataModel->validate()){
$dataModel->save();
}
the above code is not setting the attribute value.
Please let me know if there is any mistake.
You need to make sure that the 'safe' validation rules is used on each level.
To understand more read this http://www.yiiframework.com/wiki/161/understanding-safe-validation-rules/
Try to determine which valdation errors you have:
if(!$model->validate()) {
die( print_r($model->getErrors()) );
}