Giter VIP home page Giter VIP logo

alkali's People

Contributors

ahamid avatar bruno-gouveia avatar dependabot[bot] avatar foundling avatar gitter-badger avatar jlmakes avatar kriszyp avatar sergiocrisostomo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

alkali's Issues

Element: classes manipulated with renderer in `created` get overwritten

class Foo extends Div('.foo') {
  // @param { Variable.<Boolean>} active
  created({active}) {
    new ElementRenderer({
      element: this,
      variable: active,
      renderUpdate: (isActive) => {
        this.classList.toggle('active', isActive)
        this.classList.toggle('inactive', !isActive)
        this.classList.toggle('hidden', !isActive)
      }
    })
  }
}
new Foo({ active: new Variable(false) })

Results in

<div class="foo"></div>

Expected

<div class="foo hidden inactive"></div>

Setting a property on a Map variable triggers update on parent, but not of property

let selection = new Variable(new Map())

selection.subscribe((event) => {
  console.log('Selection changed:', event.value())
})

selection.set('foo', true)

selection.property('foo').subscribe((event) => {
  console.log('Foo changed:', event.value())
})

selection.set('foo', false)
selection.set('foo', 'foo')
selection.property('foo').put(true)

// Logs the following

// Selection changed: Map {}
// Selection changed: Map {"foo" => true}
// Foo changed: true
// Selection changed: Map {"foo" => false}
// Selection changed: Map {"foo" => 'foo'}
// Selection changed: Map {"foo" => true}

selection.property('foo').updated()
// Selection changed: Map {"foo" => true}
// Foo changed: true

Unreachable code after return statement

Line 108 here outputs a warning:

Unreachable code after return statement

alkali/Renderer.js

Lines 105 to 110 in 1c29e5e

specify: function(Variable) {
return this.contextualized = Context.prototype.specify.call(this, Variable)
// a new context to get this
this.contextualized = this.newContext(null, true).specify(Variable)
},

Using `.property` on maps defined by keyBy should return original variable instance

Is it possible/desirable for maps generated by keyBy to return original variable instances?

class Foo extends Variable<{ Name: string, Id: number }> {}
const Collection = VArray.of(Foo)

const collection = new Collection([{
  Name: 'Kerry',
  Id: 123
}])

const index = collection.keyBy(model => model.get('Id'))

// fails
assert.strictEqual(index.property(123), collection.property(0))

// fails
assert(index.property(123) instanceof Foo)

let newProps = {
  Name: 'Jerry',
  Id: 123,
} 

index.set(123, newProps)

// fails
assert.strictEqual(collection.get(0), newProps)

Updating property with key of empty string fails to trigger updates

let foo = new Variable({'': 'foo'})

foo.get('')
// -> 'foo'

foo.property('').subscribe((event) => {
  console.log(event.value())
})

foo.set('', 'wat')
foo.property('').put('does it blend?')
// nothing happens, the subscribed event handler never fires.

This issue came up when using variables to represent selection state hashes, and some (selectable) values come up as empty string.

This works but it also triggers updaters for the entire object, rather than just that 1 property:

foo.set('', 'wat') && foo.property('').updated()

Request: CommonJS module support

At times I'd like to be able to quickly set up a sandbox for toying around with variables. Being able to import as a Node CommonJS module would be helpful.

Getting the number of listeners to a Variable

Hello, first thank you for all your work on this, hopping this isn't a dumb question.

I'd like to know if a variable has any listeners, or dependent variable using its value, but can't find anything about it or in the variable object. Is there any relatively fast way to do this ?

Feature request: disregard/coalesce Promise values

The fact that promise values are implicitly resolved in transforms largely solves the issue of dealing with them, however there still arises from time to time the case of some downstream consumer eagerly, non-reactively, forcing the resolution of a variable chain, and assuming the value it receives is not a wrapping promise. When the value is not a promise, this works fine and is unremarkable, but if a Promise sneaks into the chain at any point, it can become very difficult to track down and currently requires breaking/bridging the reactivity.

This can be done explicitly with a simple utility, like:

export default (variableYieldingPromise, initialValue) => {
  const outputVar = new Variable(initialValue)
  variableYieldingPromise.subscribe((e) => {
    Promise.resolve(e.value()).then((value) => outputVar.put(value))
  })
  return outputVar
}

However this is pretty clunky, and non-idiomatic. It would be preferable if there were some idiomatic way to "consume"/coalesce Promises such that we have a guarantee to never see them (at least, never see an initial level of Promises - Promises are self-composable, so I would not expect to see a Promise yielding underlying value that is itself a Promise).

e.g.:

var s = new Variable('z')
var v = s.as(VPromised)
assert.equal(v.valueOf(), 'z')
s.put(new Promise(function (r) {
    setTimeout(function() { r('a') }, 100)
}))
assert.equal(v.valueOf(), 'z')
return new Promise(setTimeout).then(function () {
    // still initial value
    assert.equal(v.valueOf(), 'z')
    return new Promise(function (r) { setTimeout(r, 110) }).then(function() {
        // should contain resolved value now
	assert.equal(v.valueOf(), 'a')
    })
})

See #41 for tests illustrating usage, and several unsuccessful stabs at an implementation

0 is ignored when used for content

This will correctly render as "0" in the element:

  Span({ textContent: 0 })

These will create an empty element:

  Span({ content: 0 })
  Span(0)
  Span('.some-class', 0)

Variable assignment proxying upstream by default

In the process of trying to exploit the behavior of "non-proxying" variable assignment for derived/dynamic defaults, as documented here, I noticed that this may not be working.

let sourceVariable = new Variable({foo: 1})
let containingVariable = new Variable(sourceVariable)
sourceVariable.set('foo', 2) // this will propagate down to containingVariable
containingVariable.set('foo', 3) // this will not affect the sourceVariable
containingVariable.get('foo') -> 3
sourceVariable.get('foo') -> 2

Test cases at PR #39

Native ES6 Module Support

Hey Kris, are you open to a PR augmenting the way alkali is packaged to include native ES6 module support?

Return VBoolean from `equal`

import { equal } from 'alkali'

let foo = new Variable('foo')

// Fails
let isFoo: VBoolean = equal(foo, 'foo')

Suggestion: support multiple configured elements in Updaters

To simplify code like...

el1 = createThing1()
new PropertyUpdater({variable: variable, element: el1...
el2 = createThing2()
new PropertyUpdater({variable: variable, element: el2...
elN = createThingN()
new PropertyUpdater({variable: variable, element: elN...

It might be nice to support multiple (statically) configured elements in Updaters. There is somewhat related support for specifying a selector, but not an explicit list of elements.

E.g.

new PropertyUpdater({
  name: 'disabled',
  elements: [e1, e2, e3],
  variable: disabledVar
})

I started on a tentative patch, which was mostly a straightforward conversion from operating on this.element to iterating on this.elements, but ran into this line that I'm not sure what to do with:

if (!context || context == this.element || context.contains(this.element)) {

I think in this case the intent is to determine whether the passed context "matches" the element configuration of the updater; i'm not sure if that makes sense in the case of multiple elements, or perhaps warrants a more sophisticated check for array inclusion.

ListUpdater would get a bit more complicated since it has state, I suspect that would only require keeping a map of builtList on element.

Not a high priority, I just wanted to see if it was something that could be done simply and fit with the intent of Updaters (maybe there is a better way to aggregate similar Updaters).

Generating dynamic class name

Hello, I'm creating a MyButton class as:

class MyButton extends Div('.my-morphing-button', {
    caption: Variable,
    close_caption: Variable,
    body: Variable,
    modal_num: Variable,
}){
    created(properties)....

And I want to use modal_num for child Div's class name like:

MyButton.children = [
    Div('.morph-button-modal-`${MorphButton.modal_num}`', [ /*doesn't work for class name*/
        MorphButton.modal_num  /*but works for content*/
    ])
]

But I can't set desired number to the class name. How to fix it?.. (Is it possible?)
Thanks in advance

Feature request: support for Map

Can the property, get, and set methods for object variables be extended to work for Map data structures?

let selection = new Variable(new Map())

// User selects the `false` value
selection.set(false, true)

selection.get(false)
// -> true

Suggestion: expose configurable change binding

Text inputs are notoriously finicky for detecting changes reliably. I had to supplement the default bindChanges functionality, as below, to respond to changes without waiting for a blur to occur:

const ADDTL_TEXT_INPUT_CHANGE_EVENTS = [ 'propertychange', 'click', 'keyup', 'input', 'paste']
const textInput = new Variable()
const textInputCtrl = TextInput('.form-control', {
  type: 'text',
  name: 'name',
  created: function() {
    // try harder to detect changes eagerly
    const updateVar = () => { this.content.put(this['typedValue' in this ? 'typedValue' : 'value'], this) }
    for (const type of ADDTL_TEXT_INPUT_CHANGE_EVENTS) {
      this.addEventListener(type, updateVar)
    }
  }
}, this.textInput)

I'm wondering if this could be made configurable, or bindChanges added to the element prototype?

Cannot add image

This not work for me, cannot set src to image.

import {Div, Span, Image, Variable} from 'alkali';

let PromoComp = new Div('.outer', [
	Image({src: '/img/wikipedia/wP.png'})
]);

Also, to the document appends <image></image>, but must <img />
Alkali version - 0.11.7

Support for whole-object `classes` transform

To support fewer transforms/renderers when mutating multiple classes:

let selected = new Variable({
  '1': true
})

function buildButton(id) {
  Button({
    classes: selected.to((selected) => ({
      active: !!selected[id],
      inactive: !selected[id],
  }))
}

TypeError: Cannot read property 'length' of undefined

this not works:

import { Div, Span } from 'alkali';
// define
class MyComponent extends Div {
}
MyComponent.children = [
    Span(MyComponent.property('title')),
];

// init
var el = new MyComponent({
    title: 'text for the span',
    link: 'a link for a[href]'
});

// console.log(el)
document.body.appendChild( el )

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.