Giter Club home page Giter Club logo

bacon.jquery's Introduction

Note: This repository is not maintained anymore. You can still use it of course, or just use Bacon.js core which adds the asEventStream method to jQuery objects, for accessing events as EventStream objects.

bacon.jquery

A JQuery data binding library for Bacon.js.

Adds stuff to Bacon.$. Is also called BJQ.

Includes

  • Binding the state of HTML input elements to Bacon.Model objects that extend the Bacon.js Property API by providing a bidirectional binding
  • AJAX helpers. Wrap a JQuery AJAX call into an EventStream using Bacon.$.ajax("/get/stuff"). Convert an EventStream of requests into an EventStream of responses like requests.ajax().
  • FRP extensions to JQuery. Wrap JQuery events easily into an EventStream, as in $("body").clickE()

This library is intended as a replacement for Bacon.UI. It provides the same functionality, with the addition of two-way bound Models, model composition and lenses.

Example Applications

There are example applications in the examples directory, each with a README.md describing how they are started.

Each application does essentially the same thing and the code in the example applications is essentially just this:

  // binding for "left" text field
  left = bjq.textFieldValue($("#left"))
  // binding for "right" text field
  right = bjq.textFieldValue($("#right"))
  // make a two-way binding between these two
  // values in the two fields will now stay in sync
  right.bind(left)
  // Make a one-way side effect: update label text on changes, uppercase
  right.map(".toUpperCase").changes().assign($("#output"), "text")
  // Add an input stream for resetting the value
  left.addSource($("#reset").asEventStream("click").map(""))

API

The bacon.jquery API consists of methods for creating a Model representing the state of a DOM element or a group of DOM elements. This API is published as Bacon.$, and the same object is returned when using AMD or CommonJS.

Bacon.$.textFieldValue(field [, initValue])

Creates a Model for an <input type="text"> element, given as a JQuery object. You can optionally supply an initial value.

Bacon.$.checkBoxValue(field [, initValue])

Creates a Model for a <input type="checkbox"> element, given as a JQuery object. The value is true if the checkbox is checked and false otherwise.

Bacon.$.selectValue(field [,initValue])

Creates a Model for a <select> element, given as a JQuery object. The value of the model corresponds to the value attribute of the selected <option> element.

Bacon.$.radioGroupValue(fields, [,initValue])

Creates a Model for a group of <input type="radio"> elements, given as a JQuery object or an Array of jQuery objects. The value of the model corresponds to the value attribute of the selected radio input element. Note that value is a string.

Bacon.$.intRadioGroupValue(fields [, initValue])

Like Bacon.$.radioGroupValue, but for integer values.

Bacon.$.checkBoxGroupValue(fields, [,initValue])

Creates a Model for a group of <input type="checkbox"> elements, given as a JQuery object or an Array of jQuery objects. The value of the model is an array of the value attributes of the checked checkbox input elements. For instance, if you have checkboxes and 2 of these are checked, having values a and b, the value of the Model is ["a", "b"].

TODO: add HTML/JS examples

FRP extensions to JQuery Events

BJQ adds methods to JQuery, for wrapping events into an EventStream.

For example, to wrap click events on <body> into an EventStream, you can

var clicks = $("body").clickE()

Supported methods include the following:

  • keydownE
  • keyupE
  • keypressE
  • clickE
  • dblclickE
  • mousedownE
  • mouseupE
  • mouseenterE
  • mouseleaveE
  • mousemoveE
  • mouseoutE
  • mouseoverE
  • dragstart
  • drag
  • dragenter
  • dragleave
  • dragover
  • drop
  • dragend
  • resizeE
  • scrollE
  • selectE
  • changeE
  • submitE
  • blurE
  • focusE
  • focusinE
  • focusoutE
  • loadE
  • unloadE

FRP extensions to JQuery Effects

BJQ adds methods to JQuery, for performing animations and wrapping the result Promise into an EventStream. For example

var fadeOut = $("#thing").fadeOutE("fast")

Supported methods include the following:

  • animateE
  • showE
  • hideE
  • toggleE
  • fadeInE
  • fadeOutE
  • fadeToE
  • fadeToggleE
  • slideDownE
  • slideUpE
  • slideToggleE

AJAX

BJQ provides helpers for JQuery AJAX. All the methods return an EventStream of AJAX results. AJAX errors are mapped into Error events in the stream.

Aborted requests are not sent into the error stream. If you want to have a stream that observes whether an AJAX request is running, use Bacon.awaiting. For example:

var searchParams = Bacon.once({ url: '/search', data: { query: 'apple' } })
var ajaxRequest = searchParams.ajax()
var requestRunning = searchParams.awaiting(ajaxRequest)
requestRunning.assign($('#ajaxSpinner'), 'toggle')

stream.ajax(fn)

Performs an AJAX request on each event of your stream, collating results in the result stream.

The source stream is expected to provide the parameters for the AJAX call.

var usernameRequest = username.map(function(un) { return { type: "get", url: "/usernameavailable/" + un } })
var usernameAvailable = usernameRequest.changes().ajax()

Bacon.$.ajax(params)

Performs an AJAX request and returns the results in an EventStream.

var results = Bacon.$.ajax("/get/results")

or

var results = Bacon.$.ajax({ url: "/get/results"})

Bacon.$.lazyAjax(params)

Like above, but performs the AJAX call lazily, i.e. not before it has a subscriber.

Bacon.$.ajaxGet(url, data, dataType)

Bacon.$.ajaxGetJSON(url, data)

Bacon.$.ajaxPost(url, data, dataType)

Bacon.$.ajaxGetScripts(url)

stream.toDeferred()

Turns your Bacon Ajax stream back to $.Deferred. It's useful if you need to provide a solution for users who are not familiar with Bacon.

Model API

All the BJQ methods, such as textFieldValue return a Model object, which is a Bacon.js Property, but extends that API by the following methods.

Model API reference migrated to bacon.model

TODO: more

Use with AMD / RequireJS

The requirejs example-app uses RequireJS, like this:

require.config({
  paths: {
    "bacon.jquery": "../dist/bacon.jquery",
    "bacon": "components/bacon/dist/Bacon",
    "jquery": "components/jquery/jquery"
  }})
require(["bacon.jquery", "jquery"], function(bjq, $) {
  left = bjq.textFieldValue($("#left"))
  right = bjq.textFieldValue($("#right"))
  right.bind(left)
  right.assign($("#output"), "text")
})

The prebuilt javascript file can be found in the dist directory, or here.

The API can be accessed using Bacon.$ or like in the above example.

Use without AMD

The plain example-app uses RequireJS, like this:

So feel free to use plain old <script> tags to include Bacon, JQuery and BJQ.

The BJQ methods are exposed through Bacon.$, so you can call them as in Bacon.$.textFieldValue(..).

The prebuilt javascript file can be found in the dist directory, or here.

There's a plain example-app that uses script tags only.

Use with Node / Browserify

BJQ is registered in the NPM repository as bacon.jquery and works fine with node-browserify.

See the browserify example-app for an example.

Use with Bower

Registered to the Bower registry as bacon.jquery. See the Example Applications, for instance requirejs example-app.

Building

The bacon.jquery module is built using NPM and Grunt.

To build, use npm install.

Built javascript files are under the dist directory.

Automatic tests

Use the npm test to run all tests.

Tests include mocha tests under the test directory, and mocha browser tests under the browsertest directory. The test script uses mocha-phantomjs to run the browser tests headless.

The browser tests can also be run by opening the browsertest/runner.html in the browser.

The tests are also run automatically on Travis CI. See build status below.

Build Status

What next?

See Issues.

If this seems like a good idea, please tell me so! If you'd like to contribute, please do! Pull Requests, Issues etc appreciated. Star this project to let me know that you care.

bacon.jquery's People

Contributors

bryant1410 avatar dremora avatar fujimotos avatar jliuhtonen avatar juhamikkola avatar kare avatar matchdav avatar raimohanska avatar tco avatar tkareine avatar wolfflow 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

Watchers

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

bacon.jquery's Issues

Using other types than strings as bacon.jquery model values

Bacon.jquery does not currently support using other types than strings with the models it creates. Trying to set model value to integer for example does not reflect to the UI, which is understandable as the values are strings in the DOM after all.

Anyway, it would be nice to use e.g. numbers with your Bacon.$.radioButtonGroup and hide the conversions from application logic. For example:

var initialId = 23256;
var radioElems = $("#myForm").find("input:radio")
var radioGroupWithIdValues = Bacon.$.radioGroupValue(radioElems, initialId)
...
radioGroupWithIdValues.set(54347)

One can work around this by making a bidirectional conversion between types with Bacon.Model's Bacon.Binding, like in this fiddle: http://jsfiddle.net/jliuhtonen/EfmLU/

Or perhaps make some changes to bacon.jquery directly...

Do you think that it would be useful to have something like this in Bacon.Jquery or Bacon.Model?

checkBoxValue

Thank you for an excellent set of libraries.

I tried using checkBoxValue on checkbox like this:

<input type="checkbox" value="foo" />

I then sampled changes to the property with a button click and found that I always received the same value (false if the checkbox defaulted to unchecked, true otherwise).

I managed to get things working by re-implementing checkBoxValue using jQuery's :checked pseudo-attribute as follows:

  Bacon.$.checkBoxValue = (element, initValue) ->
    Bacon.Binding {
      initValue,
      get: -> element.is(":checked"),
      events: element.asEventStream("change"),
      set: (value) -> element.attr "checked", value
    }

Not sure if I'm overlooking something obvious or if this is a bug. Thanks in advance for any feedback.

Doesn't work with simultaneous events

Failing case:

    a = Bacon.Model()
    f = a.lens("first").log("first")
    l = a.lens("last").log("last")
    stuff = Bacon.Model.combine({f, l}).log("stuff")
    values = collect(stuff)
    a.set({first:"f", last:"l"})
    expect(values).to.deep.equal([{}, {first: "f", last: "l"}])

I stumbled upon this when testing Bacon.js 0.7.0 in a project.

Rename?

The name bacon-jquery-bindings is not funky. I'm already calling it BJQ for brevity. Maybe BBQ or Barbeque instead?

Current value not passed when modifying a lens

When modifying a lens the value passed to the modification function seems to always be undefined. The modification can be successfully made to the original model.

var model = Bacon.$.Model({
  left: "left"        
});

var l = model.lens("left");
l.bind(Bacon.$.textFieldValue($("#left")));

// Doesn't work
l.modify(function(current){
  return current + "-asdas";
});

// Works
model.modify(function(current){
  return {left: current.left + "-asdas"};
});

Tests for the stuff shipped from Bacon.UI

There's a bunch of stuff (AJAX, JQuery DOM Events, JQuery animations) that was just copy-pasted from Bacon.UI without any testing. Some tests should be added.

AJAX can be tested using Mockjax.

Event helpers can be tested using JQuery.trigger.

Animations can be tested using JQuery. It might be enough to test, for instance, that fadeOutE works in the sense that it hides the element and produces an event through the stream.

Empty install via bower on gentoo

On Gentoo Linux on server (via ssh) I ran $ bower install for project (all info in bower.json is correct and the same works on Mac).

Then, I see that bower got bacon.jquery, but grunt fails to compile the project and says that file bower_components/bacon.jquery/dist/bacon.jquery.min.js doesn't exist.

I made $ ls -la bower_components/bacon.jquery/dist/ and it shows me an empty folder. But this works pretty on Mac and on Windows.

Please help. Something went wrong.

UPD: tried to install this explicitly via $ bower install bacon.jquery and the same happened.

Model.addSource doesn't use initial Property's value

To reproduce, use the following code:

model = bjq.Model()
property = Bacon.constant(3)
property.log()
model.addSource(property)

Here I'm expecting the new value of the model to be shown in the console output, but nothing happens. I'm not sure if this is by design, but I don't see any reason to skip the initial value.

Perform multiple simultaneous ajax calls and zip the results is not working

I'm trying to perform multiple simultaneous ajax request to a REST api and get a stream that emits a value with a data structure containing the data retrieved by all the responses altogether. For this I'm using zip but I'm getting the following exception from Bacon.js:
Uncaught Error: At least one EventStream required

As an example, below there is a simplified version of my code:

let profileStreams = [];
let profiles = {
  someURL: {
    href: 'www.google.com'
  },
  someOtherURL: {
    href: 'github.com'
  },
  yetAnotherURL: {
    href: 'twitter.com'
  }
};

for (let index in profiles) {
  profileStreams.push(
    b$.ajax({
      url: profiles[index].href
    }).map((profileObject) => {
      return {
        owner: index,
        profile: profileObject
      };
    })
  );
}

let allUrlsRetrievedAsArray = Bacon.zipAsArray(profileStreams);

Model, Binding and Lens โ€” should they be constructors?

In JavaScript, TitleCasedNames usually indicate a constructor โ€” a function which should be called with a prefix new. Capital letter in the beginning also implies that the object can be extended (for instance, using class D extends C syntax in CoffeeScript). Violating this rule might cause confusion and prevent objects from being easily extendable. Bacon is following this convention, while Bacon.jQuery is not.

Extract bacon-model

The non-jquery specific parts could be extracted, including Model, Binding, Lens.

Rename `Binding`?

What should we call the "two-way-property" that the Binding class represents?

Event helper methods are defunct

The simplification in #28 suffer from "access to modified closure" and simply do not work.

I've already committed a fix to master in 7967538.

I'm currently unable to release because of problems with NPM. Will release 0.4.4 ASAP.

I'm wondering how this crap passed tests :(

And very sorry for bad quality.

Split code into multiple modules

Currently the entire plugin is in one large file, but it would be easier to maintain and for potential contributors to wrap their heads around if it was split into many small modules. I'm currently thinking something like:

bacon.jquery.coffee Re-export public API on `Bacon.$` namespace & monkey-patches Bacon.Observable with ajax
elements/* One module for each element that has a value function (eg. check-box.js exports checkBoxValue)
ajax.coffee Exports ajax functions
events.coffee Exports jQuery event wrappers

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.