On 1/20/20, 9:27 AM, "Harbs" <[email protected]> wrote:
Yeah. I thought about subclassing HashChangeNotifierBead and the version
with Title, but almost all the code would have needed to be overridden (i.e.
I’m auto-stipping off the hash, etc.), so I decided to write it from scratch.
The bead was not intended to be a lightweight PAYG bead. If someone wants
very lightweight, they should use the Notifier beads. It’s meant to be as
drop-in as possible to make it easier on the developer.
IMO, in that case, it should go in Express not, Basic.
-Alex
> On Jan 20, 2020, at 6:41 PM, Alex Harui <[email protected]> wrote:
>
> Nit-picky comments:
>
> 1) there is already a bead that watches location.hash. It might be worth
using it to share code
> 2) forward/backward/go/title doesn't seem PAYG to me. I can imagine lots
of users won't need it, or might use it independently of routing (especially
Title).
>
> My 2 cents,
> -Alex
>
> On 1/20/20, 4:11 AM, "[email protected] <mailto:[email protected]>"
<[email protected] <mailto:[email protected]>> wrote:
>
> This is an automated email from the ASF dual-hosted git repository.
>
> harbs pushed a commit to branch develop
> in repository
https://nam04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitbox.apache.org%2Frepos%2Fasf%2Froyale-asjs.git&data=02%7C01%7Caharui%40adobe.com%7Cf932412ad0a24a40856a08d79dcdfa32%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C637151380297043799&sdata=UDJSMyIC%2FDXJZCm0M5xDb3GGNzXRyhMUe7bHu0anz%2Fc%3D&reserved=0
<https://nam04.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgitbox.apache.org%2Frepos%2Fasf%2Froyale-asjs.git&data=02%7C01%7Caharui%40adobe.com%7Cf932412ad0a24a40856a08d79dcdfa32%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C637151380297043799&sdata=UDJSMyIC%2FDXJZCm0M5xDb3GGNzXRyhMUe7bHu0anz%2Fc%3D&reserved=0>
>
>
> The following commit(s) were added to refs/heads/develop by this push:
> new 6cbc555 Added Router
> 6cbc555 is described below
>
> commit 6cbc5559bcc99bf2ceb3e033747ca3680b3b0d91
> Author: Harbs <[email protected] <mailto:[email protected]>>
> AuthorDate: Mon Jan 20 14:10:42 2020 +0200
>
> Added Router
> ---
> .../Basic/src/main/resources/basic-manifest.xml | 2 +
> .../royale/org/apache/royale/routing/RouteState.as | 34 +++
> .../royale/org/apache/royale/routing/Router.as | 274
+++++++++++++++++++++
> 3 files changed, 310 insertions(+)
>
> diff --git
a/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
b/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
> index 00e2325..3c30bed 100644
> --- a/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
> +++ b/frameworks/projects/Basic/src/main/resources/basic-manifest.xml
> @@ -273,4 +273,6 @@
> <component id="ModalDisplay"
class="org.apache.royale.html.beads.plugin.ModalDisplay"/>
> <component id="ModalOverlay"
class="org.apache.royale.html.beads.plugin.ModalOverlay"/>
>
> + <component id="Router" class="org.apache.royale.routing.Router"/>
> +
> </componentPackage>
> diff --git
a/frameworks/projects/Basic/src/main/royale/org/apache/royale/routing/RouteState.as
b/frameworks/projects/Basic/src/main/royale/org/apache/royale/routing/RouteState.as
> new file mode 100644
> index 0000000..84fcc4c
> --- /dev/null
> +++
b/frameworks/projects/Basic/src/main/royale/org/apache/royale/routing/RouteState.as
> @@ -0,0 +1,34 @@
>
+////////////////////////////////////////////////////////////////////////////////
> +//
> +// Licensed to the Apache Software Foundation (ASF) under one or more
> +// contributor license agreements. See the NOTICE file distributed
with
> +// this work for additional information regarding copyright
ownership.
> +// The ASF licenses this file to You under the Apache License,
Version 2.0
> +// (the "License"); you may not use this file except in compliance
with
> +// the License. You may obtain a copy of the License at
> +//
> +//
https://nam04.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.apache.org%2Flicenses%2FLICENSE-2.0&data=02%7C01%7Caharui%40adobe.com%7Cf932412ad0a24a40856a08d79dcdfa32%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C637151380297043799&sdata=dS98z1bAFk5RE0uJ6WmdDTvkuXIMbrQIfyfy9aGNBEk%3D&reserved=0
<https://nam04.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.apache.org%2Flicenses%2FLICENSE-2.0&data=02%7C01%7Caharui%40adobe.com%7Cf932412ad0a24a40856a08d79dcdfa32%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C637151380297043799&sdata=dS98z1bAFk5RE0uJ6WmdDTvkuXIMbrQIfyfy9aGNBEk%3D&reserved=0>
> +//
> +// Unless required by applicable law or agreed to in writing,
software
> +// distributed under the License is distributed on an "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
> +// See the License for the specific language governing permissions
and
> +// limitations under the License.
> +//
>
+////////////////////////////////////////////////////////////////////////////////
> +package org.apache.royale.routing
> +{
> + public class RouteState
> + {
> + public function RouteState(state:String="",title:String="")
> + {
> + this.state = state;
> + this.title = title;
> +
> + }
> + public var state:String;
> + public var title:String;
> + public var parameters:Object;
> + public var path:Array;
> + }
> +}
> \ No newline at end of file
> diff --git
a/frameworks/projects/Basic/src/main/royale/org/apache/royale/routing/Router.as
b/frameworks/projects/Basic/src/main/royale/org/apache/royale/routing/Router.as
> new file mode 100644
> index 0000000..98b9fc6
> --- /dev/null
> +++
b/frameworks/projects/Basic/src/main/royale/org/apache/royale/routing/Router.as
> @@ -0,0 +1,274 @@
>
+////////////////////////////////////////////////////////////////////////////////
> +//
> +// Licensed to the Apache Software Foundation (ASF) under one or more
> +// contributor license agreements. See the NOTICE file distributed
with
> +// this work for additional information regarding copyright
ownership.
> +// The ASF licenses this file to You under the Apache License,
Version 2.0
> +// (the "License"); you may not use this file except in compliance
with
> +// the License. You may obtain a copy of the License at
> +//
> +//
https://nam04.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.apache.org%2Flicenses%2FLICENSE-2.0&data=02%7C01%7Caharui%40adobe.com%7Cf932412ad0a24a40856a08d79dcdfa32%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C637151380297043799&sdata=dS98z1bAFk5RE0uJ6WmdDTvkuXIMbrQIfyfy9aGNBEk%3D&reserved=0
<https://nam04.safelinks.protection.outlook.com/?url=http%3A%2F%2Fwww.apache.org%2Flicenses%2FLICENSE-2.0&data=02%7C01%7Caharui%40adobe.com%7Cf932412ad0a24a40856a08d79dcdfa32%7Cfa7b1b5a7b34438794aed2c178decee1%7C0%7C0%7C637151380297053790&sdata=NY4972Z6X3a%2BHWhuAA9r2ViKiWpNJQIzaCcQlkH4TLI%3D&reserved=0>
> +//
> +// Unless required by applicable law or agreed to in writing,
software
> +// distributed under the License is distributed on an "AS IS" BASIS,
> +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied.
> +// See the License for the specific language governing permissions
and
> +// limitations under the License.
> +//
>
+////////////////////////////////////////////////////////////////////////////////
> +package org.apache.royale.routing
> +{
> + import org.apache.royale.core.DispatcherBead;
> + import org.apache.royale.core.IStrand;
> + import org.apache.royale.debugging.assert;
> + import org.apache.royale.core.IStatesObject;
> + import org.apache.royale.events.Event;
> + import org.apache.royale.core.IInitialViewApplication;
> + /**
> + * Dispatched when the state is changed.
> + *
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.7
> + */
> + [Event(name="stateChange", type="org.apache.royale.events.Event")]
> +
> + /**
> + * Router is a bead which automatically handles browsing history.
> + * It could be attached to any strand, but typically it would be
attached to Application or View
> + * Listen to stateChange events to handle changes to browsing
history and use setState and renderState for modifying the history.
> + * The state of the router can be modified before committing the
state changes.
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.7
> + */
> + public class Router extends DispatcherBead
> + {
> + public function Router()
> + {
> +
> + }
> + /**
> + * Use this to automatically sync the state of the strand.
> + * This only works for the state property of the RouterState.
> + * It also assumes that the strand is an IStatesObject.
> + * For this to work correctly, it's usually assumed that the bead
is attached to the application View
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.7
> + */
> + public var syncState:Boolean;
> + override public function set strand(value:IStrand):void
> + {
> + _strand = value;
> + COMPILE::JS
> + {
> + window.addEventListener("hashchange",
hashChangeHandler);
> + initialTitle = document.title;
> + }
> + // If it's an Application, listen to applicationComplete
> + if(_strand is IInitialViewApplication)
> + listenOnStrand("applicationComplete",onInit);
> + //Otherwise listen to initComplete
> + else
> + listenOnStrand("initComplete",onInit);
> + }
> + private function onInit(event:Event):void
> + {
> + COMPILE::JS
> + {
> + if(location.hash)
> + {
> + hashChangeHandler();
> + }
> + }
> + }
> + private var initialTitle:String;
> + private function hashChangeHandler():void
> + {
> + parseHash();
> + if(syncState)
> + {
> + assert(_strand is IStatesObject,"syncState can only be used
on IStatesObjects");
> + (_strand as IStatesObject).currentState = _routeState.state;
> + }
> + dispatchEvent(new Event("stateChange"));
> + }
> + private function parseHash():void
> + {
> + //TODO SWF implementation
> + COMPILE::JS
> + {
> + var hash:String = location.hash;
> + var index:int = 0;
> + if(hash.indexOf("!")==1){
> + index = 1;
> + }
> + hash = hash.slice(index+1);
> + var paths:Array = hash.split("/");
> + var statePart:String = paths.pop();
> + var splitParts:Array = statePart.split("?");
> + statePart = splitParts[0];
> + _routeState = new RouteState(statePart,document.title);
> + _routeState.path = paths;
> + _routeState.parameters = parseParameters(splitParts[1]);
> + }
> + }
> + private function parseParameters(query:String):Object
> + {
> + var urlVars:Object;
> + if(query){
> + var vars:Array = query.split("&");
> + if(vars.length){
> + urlVars = {};
> + }
> + for (var i:int=0;i<vars.length;i++) {
> + var pair:Array = vars[i].split("=");
> + urlVars[pair[0]] = pair[1] == undefined ? undefined :
decodeURIComponent(pair[1]);
> + }
> + }
> + return urlVars;
> + }
> +
> + private function buildHash():String
> + {
> + var hash:String = "#!";
> + if(_routeState.path && routeState.path.length){
> + hash += (_routeState.path.join("/") + "/");
> + }
> + if(_routeState.state){
> + hash += _routeState.state;
> + }
> + hash+= buildParameterString();
> + return hash;
> + }
> + private function buildParameterString():String{
> + var retVal:String = "";
> + if(_routeState.parameters){
> + retVal += "?";
> + for(var x:String in _routeState.parameters){
> + retVal += x;
> + if(_routeState.parameters[x] != undefined){
> + retVal += "=" +
encodeURIComponent(_routeState.parameters[x]);
> + retVal += "&";
> + }
> + }
> + //remove trailing &
> + retVal = retVal.slice(0, -1);
> + }
> +
> + return retVal;
> + }
> +
> + private var _routeState:RouteState;
> +
> + public function get routeState():RouteState
> + {
> + if(!_routeState){
> + _routeState = new RouteState();
> + }
> + return _routeState;
> + }
> +
> + public function set routeState(value:RouteState):void
> + {
> + _routeState = value;
> + }
> + /**
> + * Commits the current state to the browsing history
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.7
> + */
> + public function setState():void
> + {
> + COMPILE::JS
> + {
> +
window.history.pushState({"title":_routeState.title},_routeState.title,buildHash());
> + if(_routeState.title)
> + {
> + document.title = _routeState.title;
> + }
> + }
> + }
> + /**
> + * Same as setState, but also notifies of the state change
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.7
> + */
> + public function renderState():void
> + {
> + setState();
> + if(syncState)
> + {
> + assert(_strand is IStatesObject,"syncState can only be used
on IStatesObjects");
> + (_strand as IStatesObject).currentState = _routeState.state;
> + }
> + dispatchEvent(new Event("stateChange"));
> + }
> + private function setTitle():void
> + {
> + COMPILE::JS
> + {
> + if(window.history.state){
> + document.title = window.history.state["title"];
> + } else {
> + document.title = initialTitle;
> + }
> + }
> + }
> + /**
> + * Goes forward in the history
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.7
> + */
> + public function forward():void{
> + COMPILE::JS
> + {
> + window.history.forward();
> + setTitle();
> + parseHash();
> + }
> + }
> + /**
> + * Goes backwards in the history
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.7
> + */
> + public function back():void{
> + COMPILE::JS
> + {
> + window.history.back();
> + setTitle();
> + parseHash();
> + }
> + }
> +
> + /**
> + * Moved the specified number of steps (forward or backwards) in
the history
> + * calling it with 0 or no value will reload the page.
> + * @langversion 3.0
> + * @playerversion Flash 10.2
> + * @playerversion AIR 2.6
> + * @productversion Royale 0.9.7
> + */
> + public function go(steps:int=0):void{
> + COMPILE::JS
> + {
> + window.history.go(steps);
> + parseHash();
> + }
> + }
> +
> + }
> +}
> \ No newline at end of file