├── .gitignore
├── Gruntfile.js
├── LICENSE
├── README.md
├── angular_bind_polymer.js
├── bower.json
├── index.html
├── karma.conf.js
├── package.json
└── test
├── BindingSpec.js
├── PolymerSetup.js
└── x-double.html
/.gitignore:
--------------------------------------------------------------------------------
1 | bower_components
2 | node_modules
3 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 | grunt.initConfig({
3 | pkg: grunt.file.readJSON('package.json'),
4 | watch: {
5 | code: {
6 | files: ['index.html', 'angular_bind_polymer.js', 'bower_components/**'],
7 | options: {
8 | livereload: true
9 | }
10 | }
11 | }
12 | });
13 |
14 | grunt.loadNpmTasks('grunt-contrib-watch');
15 | };
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Chris Strom
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | angular-bind-polymer
2 | ====================
3 |
4 | Angular directive for *double* variable binding of Polymer attributes.
5 |
6 | N.B. This will not work with raw paper/core elements because they do not publish their attributes. See note below on Polymer Usage for details.
7 |
8 | Installation
9 | ------------
10 |
11 | Use bower to install:
12 |
13 | ```
14 | $ bower install angular-bind-polymer
15 | ```
16 |
17 | Usage
18 | -----
19 |
20 | Script order is important. The web components platform (polyfills) need to be loaded first, followed by the Angular library and then this library (angular-bind-polymer):
21 |
22 | ```html
23 |
24 |
25 |
26 | ```
27 |
28 | The Angular module needs to be inititialized before the Polymer elements are imported otherwise Polymer will overwrite the attributes before angular-bind-polymer has a chance to process them.
29 |
30 | Add `eee-c.angularBindPolymer` as dependency for your Angular application:
31 |
32 | ```javascript
33 | var PizzaStoreApp = angular.module('pizzaStoreApp', [
34 | 'eee-c.angularBindPolymer'
35 | ]);
36 | ```
37 |
38 | The final piece of setup is to import the Polymer elements:
39 |
40 | ```html
41 |
42 | ```
43 |
44 | To bind values from Polymer elements, apply the `bind-polymer` directive:
45 |
46 | ```html
47 |
35 | in:
36 |
37 |
40 | out: 41 |
42 | 43 |tag) 28 | ngElement = container1.children[0]; 29 | polymerElement = container1.children[1]; 30 | 31 | polymerElement.setAttribute('in', '2'); 32 | 33 | // Must wait one event loop for ??? to do its thing 34 | setTimeout(done, 0); // One event loop for Polymer to process 35 | }); 36 | 37 | it('sees polymer update properly', function(){ 38 | expect(polymerElement.getAttribute('out')).toEqual('4'); 39 | }); 40 | 41 | // The actual test 42 | it('sees values from polymer', function(){ 43 | expect(ngElement.innerHTML).toEqual('4'); 44 | }); 45 | }); 46 | 47 | describe('Custom Elements with dash attributes', function(){ 48 | // Build in setup, check expectations in tests 49 | var ngElement, polymerElement; 50 | 51 | beforeEach(function(done){ 52 | // The angular element is the first child (thetag) 53 | ngElement = container2.children[0]; 54 | polymerElement = container2.children[1]; 55 | 56 | polymerElement.setAttribute('in', '2'); 57 | 58 | // Must wait one event loop for ??? to do its thing 59 | setTimeout(done, 0); // One event loop for Polymer to process 60 | }); 61 | 62 | it('sees polymer update properly', function(){ 63 | expect(polymerElement.getAttribute('out-value')).toEqual('4'); 64 | }); 65 | 66 | // The actual test 67 | it('sees values from polymer', function(){ 68 | expect(ngElement.innerHTML).toEqual('4'); 69 | }); 70 | }); 71 | 72 | describe('Double binding multiple polymer instances', function(done){ 73 | // Build in setup, check expectations in tests 74 | var ngElementA, polymerElementA; 75 | var ngElementB, polymerElementB; 76 | 77 | beforeEach(function(done){ 78 | // The angular element is the first child (thetag) 79 | ngElementA = container3.children[0]; 80 | polymerElementA = container3.children[1]; 81 | ngElementB = container3.children[2]; 82 | polymerElementB = container3.children[3]; 83 | 84 | polymerElementA.setAttribute('in', '2'); 85 | polymerElementB.setAttribute('in', '4'); 86 | 87 | // Must wait one event loop for ??? to do its thing 88 | setTimeout(done, 0); // One event loop for Polymer to process 89 | }); 90 | 91 | it('sees first polymer update properly', function(){ 92 | expect(polymerElementA.getAttribute('out')).toEqual('4'); 93 | }); 94 | 95 | // The actual test 96 | it('sees values from first polymer', function(){ 97 | expect(ngElementA.innerHTML).toEqual('4'); 98 | }); 99 | 100 | it('sees second polymer update properly', function(){ 101 | expect(polymerElementB.getAttribute('out')).toEqual('8'); 102 | }); 103 | 104 | // The actual test 105 | it('sees values from second polymer', function(){ 106 | expect(ngElementB.innerHTML).toEqual('8'); 107 | }); 108 | }); 109 | 110 | describe('binding objects', function(){ 111 | // Build in setup, check expectations in tests 112 | var ngElement, polymerElement; 113 | 114 | beforeEach(function(done){ 115 | // The angular element is the first child (thetag) 116 | ngElement = object_container.children[0]; 117 | polymerElement = object_container.children[1]; 118 | 119 | polymerElement.setAttribute('in', '2'); 120 | 121 | // Must wait one event loop for ??? to do its thing 122 | setTimeout(done, 0); // One event loop for Polymer to process 123 | }); 124 | 125 | it('sees polymer update properly', function(){ 126 | expect(polymerElement.getAttribute('out')).toEqual('4'); 127 | }); 128 | 129 | // The actual test 130 | it('sees values from polymer', function(){ 131 | expect(ngElement.innerHTML).toEqual('4'); 132 | }); 133 | }); 134 | -------------------------------------------------------------------------------- /test/PolymerSetup.js: -------------------------------------------------------------------------------- 1 | // 1. Load Polymer before any code that touches the DOM. 2 | // *** This is done in karma.conf to avoid script loading race *** 3 | // *** conditions. It is OK to do it here once the Spec files are *** 4 | // *** of non-trivial size. *** 5 | // var script = document.createElement("script"); 6 | // script.src = "/base/bower_components/platform/platform.js"; 7 | // document.getElementsByTagName("head")[0].appendChild(script); 8 | 9 | // Container to hold angular and polymer elements 10 | var container = document.createElement('div'); 11 | container.setAttribute('ng-app', 'acceptanceTest'); 12 | document.body.appendChild(container); 13 | 14 | var container1 = document.createElement('div'); 15 | container1.innerHTML = 16 | '' + 17 | ''; 18 | container.appendChild(container1); 19 | 20 | var container2 = document.createElement('div'); 21 | container2.innerHTML = 22 | '' + 23 | ' '; 24 | container.appendChild(container2); 25 | 26 | var container3 = document.createElement('div'); 27 | container3.innerHTML = 28 | '' + 29 | ' ' + 30 | '' + 31 | ' '; 32 | container.appendChild(container3); 33 | 34 | var object_container = document.createElement('div'); 35 | object_container.innerHTML = 36 | '' + 37 | ' '; 38 | container.appendChild(object_container); 39 | 40 | 41 | // Load the angular-bind-polymer directive 42 | angular.module('acceptanceTest', [ 43 | 'eee-c.angularBindPolymer' 44 | ]); 45 | 46 | // Settimeout to give angular a chance to process the directive. Don't 47 | // care about mulitple link tags — it'll just get loaded once. 48 | beforeEach(function(done){ 49 | setTimeout(function(){ 50 | var link = document.createElement("link"); 51 | link.rel = "import"; 52 | link.href = "/base/test/x-double.html"; 53 | document.getElementsByTagName("head")[0].appendChild(link); 54 | done(); 55 | }, 56 | 0 57 | ); 58 | }); 59 | 60 | // Delay Jasmine specs until Polymer is ready 61 | var POLYMER_READY = false; 62 | beforeEach(function(done) { 63 | function waitForPolymer() { 64 | if (Polymer && Polymer.whenReady) { 65 | Polymer.whenReady(done); 66 | return; 67 | } 68 | if (Polymer && Polymer.whenPolymerReady) { 69 | Polymer.whenPolymerReady(done); 70 | return; 71 | } 72 | if (HTMLImports && HTMLImports.whenReady) { 73 | HTMLImports.whenReady(done); 74 | return; 75 | } 76 | setTimeout(waitForPolymer, 200); 77 | } 78 | waitForPolymer(); 79 | 80 | if (POLYMER_READY) done(); 81 | }); 82 | -------------------------------------------------------------------------------- /test/x-double.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 31 | 32 | --------------------------------------------------------------------------------