From b899a0eb8c798cb70be6f63ecf3d04c1d7e8d897 Mon Sep 17 00:00:00 2001 From: Ilya Fadeev Date: Mon, 13 Apr 2015 16:49:59 -0400 Subject: [PATCH 1/3] can-href: initial structure with tests --- view/href/href.js | 48 +++++++++++++++++++++++++++++++ view/href/href_test.js | 42 +++++++++++++++++++++++++++ view/href/test.html | 3 ++ view/href/tests/steal-basics.html | 25 ++++++++++++++++ view/href/tests/steal-basics.js | 16 +++++++++++ 5 files changed, 134 insertions(+) create mode 100644 view/href/href.js create mode 100644 view/href/href_test.js create mode 100644 view/href/test.html create mode 100644 view/href/tests/steal-basics.html create mode 100644 view/href/tests/steal-basics.js diff --git a/view/href/href.js b/view/href/href.js new file mode 100644 index 00000000000..1c037cc9d79 --- /dev/null +++ b/view/href/href.js @@ -0,0 +1,48 @@ +steal("can/util", + "can/view/stache/mustache_core.js", + "can/view/callbacks", + "can/view/scope", function (can, mustacheCore) { + + + var removeCurly = function(value){ + if(value[0] === "{" && value[value.length-1] === "}") { + return value.substr(1, value.length - 2); + } + return value; + }; + + // registers a callback can-href + can.view.attr("can-href", function(el, attrData){ + + // foo='bar' zed=5 abc=myValue + var attrInfo = mustacheCore.expressionData(removeCurly(el.getAttribute("can-href"))); + // -> {hash: {foo: 'bar', zed: 5, abc: {get: 'myValue'}}} + + var routeHref = can.compute(function(){ + var hash = {}; + can.each(attrInfo.hash, function(val, key) { + if (val && val.hasOwnProperty("get")) { + hash[key] = attrData.scope.read(val.get, {}).value; + } else { + hash[key] = val; + } + }); + return can.route.url(hash); + }); + + + el.setAttribute("href", routeHref()); + + var handler = function(ev, newVal){ + el.setAttribute("href", newVal); + }; + + routeHref.bind("change", handler ); + + can.bind.call(el,"removed", function(){ + routeHref.unbind("change", handler ); + }); + }); + + +}); \ No newline at end of file diff --git a/view/href/href_test.js b/view/href/href_test.js new file mode 100644 index 00000000000..e83fa078526 --- /dev/null +++ b/view/href/href_test.js @@ -0,0 +1,42 @@ +steal("can/test", "steal-qunit", function () { + + var makeIframe = function(src){ + var iframe = document.createElement('iframe'); + window.removeMyself = function(){ + delete window.removeMyself; + delete window.isReady; + delete window.hasError; + document.body.removeChild(iframe); + start(); + }; + window.hasError = function(error) { + ok(false, error.message); + window.removeMyself(); + }; + window.isReady = function(el, scope) { + + equal(el.find('a').attr('href'), "#!page=recipe&id=5", "should set href attribute"); + + window.removeMyself(); + }; + document.body.appendChild(iframe); + iframe.src = src; + }; + + QUnit.module("can/view/href"); + if(window.steal) { + asyncTest("the basics are able to work for steal", function(){ + makeIframe( can.test.path("view/href/tests/steal-basics.html?"+Math.random()) ); + }); + } + //else if(window.requirejs) { + // asyncTest("the basics are able to work for requirejs", function(){ + // makeIframe(can.test.path("../../view/href/tests/requirejs-basics.html?"+Math.random())); + // }); + //} else { + // asyncTest("the basics are able to work standalone", function(){ + // makeIframe(can.test.path("view/href/tests/standalone-basics.html?"+Math.random())); + // }); + //} + +}); diff --git a/view/href/test.html b/view/href/test.html new file mode 100644 index 00000000000..012024c906a --- /dev/null +++ b/view/href/test.html @@ -0,0 +1,3 @@ +can/view/href + +
diff --git a/view/href/tests/steal-basics.html b/view/href/tests/steal-basics.html new file mode 100644 index 00000000000..5d4d311a550 --- /dev/null +++ b/view/href/tests/steal-basics.html @@ -0,0 +1,25 @@ + + + + + + + + diff --git a/view/href/tests/steal-basics.js b/view/href/tests/steal-basics.js new file mode 100644 index 00000000000..12618aec56f --- /dev/null +++ b/view/href/tests/steal-basics.js @@ -0,0 +1,16 @@ +steal("can/component", "can/util",function(Component, can){ + return Component.extend({ + tag: "href-component", + template: $('#basics').html(), + viewModel: { + recipe: { + name: 'Cool recipe' + } + }, + events: { + "inserted": function(){ + console.log('href-component INSERTED'); + } + } + }); +}); From 6c5b9b0dbdf5344f38665cdc3cd7a519f527f3f2 Mon Sep 17 00:00:00 2001 From: Ilya Fadeev Date: Tue, 14 Apr 2015 00:27:13 -0400 Subject: [PATCH 2/3] can-href: added tests, fixed attrInfo parsing --- view/href/href.js | 3 +- view/href/href.md | 55 +++++++++++++++++++++++++++++++ view/href/href_test.js | 16 +++++++-- view/href/tests/steal-basics.html | 6 ++-- view/href/tests/steal-basics.js | 1 + 5 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 view/href/href.md diff --git a/view/href/href.js b/view/href/href.js index 1c037cc9d79..8fc255186b5 100644 --- a/view/href/href.js +++ b/view/href/href.js @@ -15,7 +15,8 @@ steal("can/util", can.view.attr("can-href", function(el, attrData){ // foo='bar' zed=5 abc=myValue - var attrInfo = mustacheCore.expressionData(removeCurly(el.getAttribute("can-href"))); + // Note: 'tmp ' is added because expressionData "Breaks up the name and arguments of a mustache expression.", but we don't use name: + var attrInfo = mustacheCore.expressionData('tmp ' + removeCurly(el.getAttribute("can-href"))); // -> {hash: {foo: 'bar', zed: 5, abc: {get: 'myValue'}}} var routeHref = can.compute(function(){ diff --git a/view/href/href.md b/view/href/href.md new file mode 100644 index 00000000000..c42d0d54b84 --- /dev/null +++ b/view/href/href.md @@ -0,0 +1,55 @@ +# can-href + +Sets an element's href attribute so that it's url will set the specified attribute values on [can.route]. + +@siganture `can-href='{[attrName=attrValue...]}'` + +@param {String} attrName +@param {can.stache.key} attrValue + +## Use + + +With no pretty routing rules, the following: + +``` +
  • {{recipe.name}}
  • +``` + +produces: + +``` +
  • {{recipe.name}}
  • +``` + +If pretty route is defined like: + +``` +can.route(":page/:id") +``` + +The previous use of `can-href` will instead produce: + +``` +
  • {{recipe.name}}
  • +``` + +You can use values from stache's scope like: + +``` +
  • {{recipe.name}}
  • +``` + +If `recipeId` was 6: + +``` +
  • {{recipe.name}}
  • +``` + +If `recipeId` is observable and changes to 7: + +``` +
  • {{recipe.name}}
  • +``` + + diff --git a/view/href/href_test.js b/view/href/href_test.js index e83fa078526..dc152a078fe 100644 --- a/view/href/href_test.js +++ b/view/href/href_test.js @@ -1,4 +1,4 @@ -steal("can/test", "steal-qunit", function () { +steal("can/test", "steal-qunit", "can/route", function () { var makeIframe = function(src){ var iframe = document.createElement('iframe'); @@ -13,9 +13,19 @@ steal("can/test", "steal-qunit", function () { ok(false, error.message); window.removeMyself(); }; - window.isReady = function(el, scope) { + window.isReady = function(el, viewModel, setPrettyUrl) { - equal(el.find('a').attr('href'), "#!page=recipe&id=5", "should set href attribute"); + equal(el.find('a').attr('href'), "#!&page=recipe&id=5", "should set unpretty href attribute"); + + viewModel.recipe.attr('id', 7); + equal(el.find('a').attr('href'), "#!&page=recipe&id=7", "should update href"); + + setPrettyUrl(); + viewModel.recipe.attr('id', 8); + equal(el.find('a').attr('href'), "#!recipe/8", "should set pretty href"); + + viewModel.recipe.attr('id', 9); + equal(el.find('a').attr('href'), "#!recipe/9", "should update pretty href"); window.removeMyself(); }; diff --git a/view/href/tests/steal-basics.html b/view/href/tests/steal-basics.html index 5d4d311a550..cc2dea8c27a 100644 --- a/view/href/tests/steal-basics.html +++ b/view/href/tests/steal-basics.html @@ -9,7 +9,7 @@ window.removeMyself = window.parent.removeMyself; @@ -18,7 +18,9 @@ steal('can', 'can/view/href', 'can/view/href/tests/steal-basics.js', function(can){ console.log(); $("body").html(can.view.mustache('Test component')); - isReady($("body href-component"), can.viewModel('href-component')); + isReady($("body href-component"), can.viewModel('href-component'), function(){ + can.route(":page/:id"); + }); }); diff --git a/view/href/tests/steal-basics.js b/view/href/tests/steal-basics.js index 12618aec56f..9bb48aab7bb 100644 --- a/view/href/tests/steal-basics.js +++ b/view/href/tests/steal-basics.js @@ -4,6 +4,7 @@ steal("can/component", "can/util",function(Component, can){ template: $('#basics').html(), viewModel: { recipe: { + id: 5, name: 'Cool recipe' } }, From bbb21d36543d48ab8379bc9f2a3a07b27410c148 Mon Sep 17 00:00:00 2001 From: David Luecke Date: Thu, 23 Apr 2015 16:08:39 -0600 Subject: [PATCH 3/3] Some documentation updates for can-href. --- view/doc/elements_and_attributes.md | 2 ++ view/href/href.md | 8 ++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/view/doc/elements_and_attributes.md b/view/doc/elements_and_attributes.md index 124a61c2fdf..3fbb4d9d62e 100644 --- a/view/doc/elements_and_attributes.md +++ b/view/doc/elements_and_attributes.md @@ -24,6 +24,8 @@ The following is supported by CanJS's [can.mustache] and [can.stache] templates ``` + - [can.view.href] - Sets an element's href attribute so that it's url will set the specified attribute values on [can.route]. + ## Plugins The following functionality is available within plugins: diff --git a/view/href/href.md b/view/href/href.md index c42d0d54b84..7d316da87b8 100644 --- a/view/href/href.md +++ b/view/href/href.md @@ -1,4 +1,5 @@ -# can-href +@page can.view.href +@parent can.view.bindings Sets an element's href attribute so that it's url will set the specified attribute values on [can.route]. @@ -7,8 +8,9 @@ Sets an element's href attribute so that it's url will set the specified attribu @param {String} attrName @param {can.stache.key} attrValue -## Use +@body +## Use With no pretty routing rules, the following: @@ -51,5 +53,3 @@ If `recipeId` is observable and changes to 7: ```
  • {{recipe.name}}
  • ``` - -