You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@flex.apache.org by ah...@apache.org on 2014/10/31 23:08:48 UTC
[13/14] FlexJSStore works well enough to try to make it work on JS.
Drag/Drop, ToolTips, States with Transitions are functional
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/f2a370c6/examples/FlexJSStore/src/data/catalog.xml
----------------------------------------------------------------------
diff --git a/examples/FlexJSStore/src/data/catalog.xml b/examples/FlexJSStore/src/data/catalog.xml
new file mode 100755
index 0000000..423e177
--- /dev/null
+++ b/examples/FlexJSStore/src/data/catalog.xml
@@ -0,0 +1,256 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+ 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
+
+ http://www.apache.org/licenses/LICENSE-2.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.
+
+ -->
+<catalog>
+
+ <product productId="1">
+ <name>Andrew Brilliam</name>
+ <description>15 years experience. 8 years with Flex. Specializing in Text Layout Framework</description>
+ <price>60.00</price>
+ <image>assets/pic/abrilliam.jpg</image>
+ <experience>15</experience>
+ <blazeds>false</blazeds>
+ <mobile>false</mobile>
+ <video>false</video>
+ <highlight1>Text Layout Framework</highlight1>
+ <highlight2>Parsley</highlight2>
+ </product>
+
+ <product productId="2">
+ <name>Annette Kotter</name>
+ <description>Specializing in custom components. PHP servers.</description>
+ <price>55</price>
+ <image>assets/pic/akotter.jpg</image>
+ <experience>3</experience>
+ <blazeds>true</blazeds>
+ <mobile>false</mobile>
+ <video>false</video>
+ <highlight1>Custom Components</highlight1>
+ <highlight2>PHP</highlight2>
+ </product>
+
+ <product productId="3">
+ <name>Ben Crater</name>
+ <description>Specializing in BlazeDS backends.</description>
+ <price>55</price>
+ <image>assets/pic/bcrater.jpg</image>
+ <experience>4</experience>
+ <blazeds>true</blazeds>
+ <mobile>false</mobile>
+ <video>false</video>
+ <highlight1>BlazeDS</highlight1>
+ <highlight2>Remote Object</highlight2>
+ </product>
+
+ <product productId="4">
+ <name>Beth Leporte</name>
+ <description>BlazeDS or PHP servers. Multimedia messagin.</description>
+ <price>70.00</price>
+ <image>assets/pic/bleporte.jpg</image>
+ <experience>6</experience>
+ <blazeds>true</blazeds>
+ <mobile>false</mobile>
+ <video>false</video>
+ <highlight1>Multimedia messaging</highlight1>
+ <highlight2>BlazeDS</highlight2>
+ </product>
+
+ <product productId="5">
+ <name>Brad Van Brocklin</name>
+ <description>Emphasis on mobile application development</description>
+ <price>80</price>
+ <image>assets/pic/bvanbrocklin.jpg</image>
+ <experience>6</experience>
+ <blazeds>false</blazeds>
+ <mobile>true</mobile>
+ <video>false</video>
+ <highlight1>Mobile</highlight1>
+ <highlight2>Android</highlight2>
+ </product>
+
+ <product productId="6">
+ <name>Carlos Carpenter</name>
+ <description>Built many mobile apps and video apps.</description>
+ <price>80</price>
+ <image>assets/pic/ccarpenter.jpg</image>
+ <experience>4</experience>
+ <blazeds>false</blazeds>
+ <mobile>true</mobile>
+ <video>true</video>
+ <highlight1>Mobile</highlight1>
+ <highlight2>Video</highlight2>
+ </product>
+
+ <product productId="7">
+ <name>Christine Lampberto</name>
+ <description>7 years experience building mobile applications.</description>
+ <price>90</price>
+ <image>assets/pic/clampberto.jpg</image>
+ <experience>7</experience>
+ <blazeds>true</blazeds>
+ <mobile>true</mobile>
+ <video>false</video>
+ <highlight1>BlazeDS</highlight1>
+ <highlight2>Mobile</highlight2>
+ </product>
+
+ <product productId="8">
+ <name>Dee Dee Avenon</name>
+ <description>I've been making video apps for over 5 years and mobile apps for about 3 years.</description>
+ <price>100</price>
+ <image>assets/pic/davenon.jpg</image>
+ <experience>10</experience>
+ <blazeds>false</blazeds>
+ <mobile>true</mobile>
+ <video>true</video>
+ <highlight1>Video Applications</highlight1>
+ <highlight2>Mobile Applications</highlight2>
+ </product>
+
+ <product productId="9">
+ <name>Denise McGoyal</name>
+ <description>Specializing in video sharing applicaions. MObile apps too.</description>
+ <price>100</price>
+ <image>assets/pic/dmcgoyal.jpg</image>
+ <experience>5</experience>
+ <blazeds>false</blazeds>
+ <mobile>true</mobile>
+ <video>true</video>
+ <highlight1>Video Applications</highlight1>
+ <highlight2>Mobile Applications</highlight2>
+ </product>
+
+ <product productId="10">
+ <name>Daniel Willhelm</name>
+ <description>I'm into mobile apps, video apps and social apps.</description>
+ <price>70</price>
+ <image>assets/pic/dwillhelm.jpg</image>
+ <experience>90</experience>
+ <blazeds>false</blazeds>
+ <mobile>true</mobile>
+ <video>true</video>
+ <highlight1>Video Applications</highlight1>
+ <highlight2>Mobile Applications</highlight2>
+ </product>
+
+ <product productId="11">
+ <name>Eunice Sunderland</name>
+ <description>My recent focus is on mobile apps, but I have considerable experience in video apps as well.</description>
+ <price>150</price>
+ <image>assets/pic/esunderland.jpg</image>
+ <experience>30</experience>
+ <blazeds>false</blazeds>
+ <mobile>true</mobile>
+ <video>true</video>
+ <highlight1>Video Applications</highlight1>
+ <highlight2>Mobile Applications</highlight2>
+ </product>
+
+ <product productId="12">
+ <name>Jane Proctor</name>
+ <description>I've been developing mobile companion apps for the past 3 years.</description>
+ <price>75</price>
+ <image>assets/pic/jproctor.jpg</image>
+ <experience>6</experience>
+ <blazeds>false</blazeds>
+ <mobile>true</mobile>
+ <video>true</video>
+ <highlight1>Video Applications</highlight1>
+ <highlight2>Mobile Applications</highlight2>
+ </product>
+
+ <product productId="13">
+ <name>Mark Fields</name>
+ <description>Video is my favorite thing. Mobile is also a favorite.</description>
+ <price>60</price>
+ <image>assets/pic/mfields.jpg</image>
+ <experience>70</experience>
+ <blazeds>false</blazeds>
+ <mobile>true</mobile>
+ <video>true</video>
+ <highlight1>Video Applications</highlight1>
+ <highlight2>Mobile Applications</highlight2>
+ </product>
+
+ <product productId="14">
+ <name>Patricia Dempsey</name>
+ <description>I've been cranking out mobile apps for the past 6 years. A few have involved video as well.</description>
+ <price>120</price>
+ <image>assets/pic/pdempsey.jpg</image>
+ <experience>7</experience>
+ <blazeds>false</blazeds>
+ <mobile>true</mobile>
+ <video>true</video>
+ <highlight1>Video Applications</highlight1>
+ <highlight2>Mobile Applications</highlight2>
+ </product>
+
+ <product productId="15">
+ <name>Paul Trandep</name>
+ <description>I've been working on a mobile app that incorporates music. It just shipped so now I'm looking for the next fun thing to work on.'</description>
+ <price>50</price>
+ <image>assets/pic/ptranep.jpg</image>
+ <experience>6</experience>
+ <blazeds>false</blazeds>
+ <mobile>true</mobile>
+ <video>true</video>
+ <highlight1>Video Applications</highlight1>
+ <highlight2>Mobile Applications</highlight2>
+ </product>
+
+ <product productId="16">
+ <name>Roscoe Crawley</name>
+ <description>My main specialty is in BlazeDS connected to Flex.</description>
+ <price>59</price>
+ <image>assets/pic/rcrawley.jpg</image>
+ <experience>9</experience>
+ <blazeds>true</blazeds>
+ <mobile>false</mobile>
+ <video>false</video>
+ <highlight1>BlazeDS</highlight1>
+ <highlight2>Remote Object</highlight2>
+ </product>
+
+ <product productId="17">
+ <name>Renee Dreifus</name>
+ <description>I can do it all: BlazeDS, Mobile, Video.</description>
+ <price>79</price>
+ <image>assets/pic/rdreifus.jpg</image>
+ <experience>90</experience>
+ <blazeds>true</blazeds>
+ <mobile>true</mobile>
+ <video>true</video>
+ <highlight1>Video Applications</highlight1>
+ <highlight2>Mobile Applications</highlight2>
+ </product>
+
+ <product productId="18">
+ <name>Tina Wong</name>
+ <description>I've been developing Flex apps since 1.5. Most of my recent work has been on mobile apps.</description>
+ <price>109</price>
+ <image>assets/pic/twong.jpg</image>
+ <experience>9</experience>
+ <blazeds>false</blazeds>
+ <mobile>true</mobile>
+ <video>true</video>
+ <highlight1>Video Applications</highlight1>
+ <highlight2>Mobile Applications</highlight2>
+ </product>
+
+</catalog>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/f2a370c6/examples/FlexJSStore/src/main.css
----------------------------------------------------------------------
diff --git a/examples/FlexJSStore/src/main.css b/examples/FlexJSStore/src/main.css
new file mode 100755
index 0000000..e092b58
--- /dev/null
+++ b/examples/FlexJSStore/src/main.css
@@ -0,0 +1,95 @@
+/*
+////////////////////////////////////////////////////////////////////////////////
+//
+// 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
+//
+// http://www.apache.org/licenses/LICENSE-2.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.
+//
+////////////////////////////////////////////////////////////////////////////////
+*/
+
+@namespace basic "library://ns.apache.org/flexjs/basic";
+
+/*
+//----------------------------
+// Global styles
+//----------------------------
+*/
+.global {
+ IStatesImpl: ClassReference("org.apache.flex.core.StatesWithTransitionsImpl");
+ color: #170505;
+ fillAlphas: 1.00, 1.00; /* last pair are for OVER state */
+ fillColors: #FFFFFF, #DDDDDD, #FFFFFF, #EEEEEE;
+}
+
+global {
+ IStatesImpl: ClassReference("org.apache.flex.core.StatesWithTransitionsImpl");
+}
+
+/*
+//----------------------------
+// Type selectors
+//----------------------------
+
+HRule
+{
+ color: #666666;
+}
+*/
+
+/*
+//----------------------------
+// Named styles
+//----------------------------
+*/
+.glass {
+ borderColor: #767473;
+ fillAlphas: .60, .60, .60, .60;
+ fillColors: #888888, #F3F3F3, #9E9E9E, #FCFCFC;
+ highlightAlphas: .07, .45;
+}
+
+.glassSlider
+{
+ fillAlphas: .80, .80, .80, .80;
+ fillColors: #F3F3F3, #BBBBBB, #FCFCFC, #CCCCCC;
+}
+
+.listItem
+{
+ paddingLeft: 4;
+ paddingRight: 4;
+ horizontalGap: 5;
+ verticalAlign: "middle";
+ backgroundColor: #FFFFFF;
+ backgroundAlpha: .5;
+ borderStyle: "outset";
+}
+
+basic|Container
+{
+ IBeadLayout: ClassReference("org.apache.flex.html.beads.layouts.NonVirtualBasicLayout");
+}
+
+.sectionHeader
+{
+ fontWeight: "bold";
+ fontSize: 11;
+}
+
+.homeSection
+{
+ cornerRadius: 4;
+ borderStyle: "solid";
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/f2a370c6/examples/FlexJSStore/src/productsView/CatalogTitleButtons.mxml
----------------------------------------------------------------------
diff --git a/examples/FlexJSStore/src/productsView/CatalogTitleButtons.mxml b/examples/FlexJSStore/src/productsView/CatalogTitleButtons.mxml
new file mode 100755
index 0000000..d2cca30
--- /dev/null
+++ b/examples/FlexJSStore/src/productsView/CatalogTitleButtons.mxml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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
+
+http://www.apache.org/licenses/LICENSE-2.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.
+
+-->
+<basic:HContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:basic="library://ns.apache.org/flexjs/basic"
+ xmlns:mx="library://ns.adobe.com/flex/mx"
+ currentState="showFilter">
+ <basic:style>
+ <basic:SimpleCSSStyles verticalAlign="middle"
+ paddingTop="0"
+ paddingBottom="0" />
+ </basic:style>
+ <basic:beads>
+ <basic:ParentDocumentBead id="pdb" />
+ <basic:ContainerDataBinding />
+ </basic:beads>
+ <fx:Script>
+ <![CDATA[
+ [Bindable]
+ public var cartCount:int;
+
+ private function rollOverLabel(event:Event):void
+ {
+ Label(event.target).className = "catalogTitleButtonHighlighted";
+ }
+
+ private function rollOutLabel(event:Event):void
+ {
+ Label(event.target).className = "catalogTitleButtonDeselected";
+ }
+ ]]>
+ </fx:Script>
+ <fx:Binding source="ProductCatalogPanel(pdb.parentDocument).cartCount" destination="cartCount" />
+ <!-- two-way binding between the states of panel title buttons and the product view state -->
+ <fx:Binding source="ProductsView(ProductCatalogPanel(pdb.parentDocument).pdb.parentDocument).currentState" destination="currentState" />
+ <fx:Binding destination="ProductsView(ProductCatalogPanel(pdb.parentDocument).pdb.parentDocument).currentState" source="currentState" />
+
+ <basic:Label id="findPhones" text="Find Developers" click="currentState = 'showFilter'"
+ className.showFilter="catalogTitleButtonSelected"
+ className.showCart="catalogTitleButtonDeselected"
+ rollOver.showCart="rollOverLabel(event)"
+ rollOut.showCart="rollOutLabel(event)"/>
+ <basic:HRule height="{findPhones.height * .75}" alpha=".75" style="color:#333333" />
+ <basic:Label id="viewCart" text="View Cart ({cartCount} items)" click="currentState = 'showCart'"
+ className.showFilter="catalogTitleButtonDeselected"
+ className.showCart="catalogTitleButtonSelected"
+ rollOver.showFilter="rollOverLabel(event)"
+ rollOut.showFilter="rollOutLabel(event)"/>
+
+ <basic:states>
+ <mx:State name="showFilter" />
+ <mx:State name="showCart" />
+ </basic:states>
+</basic:HContainer>
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/f2a370c6/examples/FlexJSStore/src/productsView/Grip.mxml
----------------------------------------------------------------------
diff --git a/examples/FlexJSStore/src/productsView/Grip.mxml b/examples/FlexJSStore/src/productsView/Grip.mxml
new file mode 100755
index 0000000..127c764
--- /dev/null
+++ b/examples/FlexJSStore/src/productsView/Grip.mxml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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
+
+http://www.apache.org/licenses/LICENSE-2.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.
+
+-->
+<basic:VContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:basic="library://ns.apache.org/flexjs/basic"
+ xmlns:mx="library://ns.adobe.com/flex/mx" width="17" height="100%" >
+ <basic:style>
+ <basic:SimpleCSSStyles paddingTop="10" horizontalAlign="center" />
+ </basic:style>
+
+ <fx:Script>
+ <![CDATA[
+ [Bindable]
+ public var gripTip:String;
+
+ [Bindable]
+ public var gripIcon:String;
+ ]]>
+ </fx:Script>
+ <basic:beads>
+ <basic:ContainerDataBinding />
+ <basic:LayoutChangeNotifier watchedProperty="{icon.height}" initialValue="0" />
+ <basic:LayoutChangeNotifier watchedProperty="{grip.height}" initialValue="0" />
+ </basic:beads>
+
+ <basic:Image id="icon" source="{gripIcon}" />
+ <basic:Image id="grip" source="assets/grip.png" >
+ <basic:beads>
+ <basic:ToolTipBead toolTip="{gripTip}" />
+ </basic:beads>
+ </basic:Image>
+
+</basic:VContainer>
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/f2a370c6/examples/FlexJSStore/src/productsView/ProductCart.mxml
----------------------------------------------------------------------
diff --git a/examples/FlexJSStore/src/productsView/ProductCart.mxml b/examples/FlexJSStore/src/productsView/ProductCart.mxml
new file mode 100755
index 0000000..00459f3
--- /dev/null
+++ b/examples/FlexJSStore/src/productsView/ProductCart.mxml
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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
+
+http://www.apache.org/licenses/LICENSE-2.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.
+
+-->
+<basic:Container xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:basic="library://ns.apache.org/flexjs/basic"
+ xmlns:mx="library://ns.adobe.com/flex/mx"
+ xmlns:productsView="productsView.*"
+ >
+ <basic:style>
+ <basic:SimpleCSSStyles horizontalAlign="right"
+ paddingTop="8"
+ paddingBottom="8"
+ paddingRight="4"
+ paddingLeft="4" />
+ </basic:style>
+ <basic:beads>
+ <basic:ContainerDataBinding />
+ <basic:OneFlexibleChildVerticalLayout />
+ </basic:beads>
+ <fx:Script>
+ <![CDATA[
+
+ import org.apache.flex.html.SimpleAlert;
+
+ import samples.flexstore.Product;
+ import samples.flexstore.ProductListEvent;
+
+ [Bindable]
+ public var numProducts:int=0;
+
+ [Bindable]
+ private var total:Number = 0;
+
+ private const SHIPPING:Number = 1.99;
+
+ private function productListEventHandler(event:ProductListEvent):void
+ {
+ switch (event.type)
+ {
+ case ProductListEvent.ADD_PRODUCT:
+ event.product.qty = 0;
+ //fall through into the same logic as dup
+ case ProductListEvent.DUPLICATE_PRODUCT:
+ event.product.qty++;
+ total += event.product.price;
+ numProducts++;
+ break;
+ case ProductListEvent.PRODUCT_QTY_CHANGE:
+ case ProductListEvent.REMOVE_PRODUCT:
+ var items:Array = productList.items;
+ total = 0;
+ numProducts = 0;
+ for (var i:int=0; i < items.length; i++)
+ {
+ var product:Product = items[i].product;
+ total += product.qty * product.price;
+ numProducts += product.qty;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ ]]>
+ </fx:Script>
+ <fx:Declarations>
+ <basic:CurrencyFormatter currencySymbol="$" id="cf" fractionalDigits="2"/>
+ </fx:Declarations>
+
+ <basic:Label width="100%" text="Your Shopping Cart" className="sectionHeader"/>
+
+ <productsView:ProductList id="productList" height="100%" width="100%"
+ newItemStartX="-100" newItemStartY="-100"
+ addProduct="productListEventHandler(event)"
+ duplicateProduct="productListEventHandler(event)"
+ productQtyChange="productListEventHandler(event)"
+ removeProduct="productListEventHandler(event)"
+ showQuantity="true" />
+
+ <basic:Container style="paddingRight:0">
+ <basic:beads>
+ <basic:VerticalColumnLayout numColumns="2" />
+ </basic:beads>
+ <basic:Label text="Total:" width="100%" />
+ <basic:Label width="70" text="{cf.format(total)}" style="textAlign:'right'"/>
+
+ <basic:Label text="Service Fee:" width="100%" />
+ <basic:Label width="70" text="{cf.format(numProducts * SHIPPING)}" style="textAlign:'right'"/>
+
+ <basic:Label text="Grand Total:" style="fontWeight:'bold'" width="100%" />
+ <basic:Label width="70" text="{cf.format(total + (numProducts * SHIPPING))}" style="textAlign:'right'"/>
+
+ </basic:Container>
+
+ <basic:TextButton text="Submit Order" click="SimpleAlert.show('This feature is not implemented in this sample', 'Submit Order')"/>
+
+</basic:Container>
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/f2a370c6/examples/FlexJSStore/src/productsView/ProductCatalogPanel.mxml
----------------------------------------------------------------------
diff --git a/examples/FlexJSStore/src/productsView/ProductCatalogPanel.mxml b/examples/FlexJSStore/src/productsView/ProductCatalogPanel.mxml
new file mode 100755
index 0000000..80ffadf
--- /dev/null
+++ b/examples/FlexJSStore/src/productsView/ProductCatalogPanel.mxml
@@ -0,0 +1,545 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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
+
+http://www.apache.org/licenses/LICENSE-2.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.
+
+-->
+<basic:Panel xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:basic="library://ns.apache.org/flexjs/basic"
+ xmlns:mx="library://ns.adobe.com/flex/mx"
+ implements="org.apache.flex.core.IDragInitiator"
+ xmlns:productsView="productsView.*"
+ currentState="browse"
+ title.browse="Browse"
+ title.compare="Product Comparison"
+ title.details="Product Details"
+ className="catalogPanel"
+ >
+
+ <fx:Metadata>
+ [Event(name="purchase", type="samples.flexstore.ProductThumbEvent")]
+ [Event(name="compare", type="samples.flexstore.ProductThumbEvent")]
+ [Event(name="details", type="samples.flexstore.ProductThumbEvent")]
+ </fx:Metadata>
+
+ <fx:Script>
+ <![CDATA[
+ import org.apache.flex.core.IUIBase;
+ import org.apache.flex.effects.Effect;
+ import org.apache.flex.effects.Fade;
+ import org.apache.flex.effects.Move;
+ import org.apache.flex.effects.Parallel;
+ import org.apache.flex.effects.Tween;
+ import org.apache.flex.events.DragEvent;
+ import org.apache.flex.events.Event;
+ import org.apache.flex.net.dataConverters.LazyCollection;
+
+ import samples.flexstore.Product;
+ import samples.flexstore.ProductFilter;
+ import samples.flexstore.ProductFilterEvent;
+ import samples.flexstore.ProductThumbEvent;
+
+
+ private var accepted:Object = new Object();
+ private var thumbnails:Array;
+ private var filterCount:int;
+ private var thumbnailState:String = 'browse'; //either 'browse' or 'compare'
+
+ [Bindable]
+ public var cartCount:int;
+
+ //-----------------------------
+ // catalog
+ //-----------------------------
+
+ private var _catalog:LazyCollection;
+
+ [Bindable]
+ public function set catalog(c:LazyCollection):void
+ {
+ _catalog = c;
+ createThumbnails();
+ }
+
+ public function get catalog():LazyCollection
+ {
+ return _catalog;
+ }
+
+ //----------------------------------------------------------------------
+ // methods
+ //----------------------------------------------------------------------
+
+ private function createThumbnails():void
+ {
+ var i:int; //variables are hoisted up in scope so declare here to avoid warning
+ if (thumbnails != null)
+ {
+ for (i=0; i < thumbnails.length; i++)
+ {
+ thumbContent.removeElement(thumbnails[i]);
+ }
+ }
+
+ var row:int = 0;
+ var col:int = -1;
+ var n:int = catalog.length;
+ thumbnails = new Array(n);
+ filterCount = n;
+
+ for (i=0; i < n; i++)
+ {
+ var thumb:ProductCatalogThumbnail = new ProductCatalogThumbnail();
+ thumbnails[i] = thumb;
+ // thumbnails[i].showInAutomationHierarchy = true;
+ thumb.product = catalog.getItemAt(i) as Product;
+ accepted[thumb.product.productId.toString()] = true;
+ thumbContent.addElement(thumb);
+ thumb.addEventListener(ProductThumbEvent.PURCHASE, productThumbEventHandler);
+ thumb.addEventListener(ProductThumbEvent.COMPARE, productThumbEventHandler);
+ thumb.addEventListener(ProductThumbEvent.DETAILS, productThumbEventHandler);
+ thumb.addEventListener(DragEvent.DRAG_START,thumbDragStartHandler);
+ }
+
+ var lastMove:Effect = layoutCatalog();
+ if (lastMove)
+ {
+ lastMove.addEventListener(Tween.TWEEN_UPDATE, updateLayout);
+ }
+ }
+
+ private function updateLayout(event:org.apache.flex.events.Event):void
+ {
+ thumbContent.dispatchEvent(new org.apache.flex.events.Event("layoutNeeded"));
+ }
+
+ private function thumbDragStartHandler(event:MouseEvent):void
+ {
+ if (DragMouseController.dragging == false)
+ {
+ var thumb:ProductCatalogThumbnail = event.target as ProductCatalogThumbnail;
+ DragMouseController.dragSource = thumb.product;
+
+ var di:ProductCatalogThumbnail = new ProductCatalogThumbnail();
+ di.product = thumb.product;
+ di.currentState = thumb.currentState;
+ DragMouseController.dragImage = di;
+
+ DragMouseController.dragInitiator = this;
+ }
+ }
+
+ public function filter(productFilter:ProductFilter, live:Boolean):void
+ {
+ currentState = "browse";
+ thumbnailState = "browse";
+ var count:int=0;
+ var n:int = thumbnails.length;
+ var targets:Array = [];
+ for (var i:int = 0; i < n; i++)
+ {
+ var thumb:ProductCatalogThumbnail = thumbnails[i];
+ var product:Product = thumb.product;
+ if (productFilter.accept(product))
+ {
+ accepted[product.productId.toString()] = true;
+ thumb.alpha = 1;
+ count++;
+ }
+ else
+ {
+ accepted[product.productId.toString()] = false;
+ if (live)
+ {
+ thumb.alpha = .1;
+ }
+ else if (thumb.alpha == 1) //only fade if we hadn't started
+ {
+ targets.push(thumb);
+ }
+ }
+ }
+ productFilter.count = count;
+ filterCount = count;
+
+ if (targets.length > 0)
+ {
+ var p:Parallel = new Parallel();
+ n = targets.length;
+ for (i = 0; i < n; i++)
+ {
+ var fadeOut:Fade = new Fade(targets[i] as IUIBase);
+ fadeOut.alphaFrom = 1;
+ fadeOut.alphaTo = .1;
+ p.addChild(fadeOut);
+ }
+ p.play();
+ p.addEventListener(Effect.EFFECT_END,
+ function(event:org.apache.flex.events.Event):void
+ {
+ layoutCatalog();
+ });
+ }
+ else if (!live)
+ {
+ layoutCatalog();
+ }
+ }
+
+ private function layoutCatalog():Effect
+ {
+ var tileWidth:Number;
+ var tileHeight:Number;
+ var numCols:int;
+
+ if (filterCount > 9 || currentState == "compare")
+ {
+ numCols = 4;
+ tileWidth = ProductCatalogThumbnail.COL_WIDTH_4;
+ tileWidth = currentState == "compare"
+ ? ProductCatalogThumbnail.COMPARE_WIDTH
+ : ProductCatalogThumbnail.COL_WIDTH_4
+ tileHeight = currentState == "compare"
+ ? height - 4
+ : ProductCatalogThumbnail.COL_HEIGHT_4;
+ }
+ else if (filterCount > 4)
+ {
+ numCols = 3;
+ tileWidth = ProductCatalogThumbnail.COL_WIDTH_3;
+ tileHeight = ProductCatalogThumbnail.COL_HEIGHT_3;
+ }
+ else if (filterCount <= 9)
+ {
+ numCols = 2;
+ tileWidth = ProductCatalogThumbnail.COL_WIDTH_2;
+ tileHeight = ProductCatalogThumbnail.COL_HEIGHT_2;
+ }
+ else
+ {
+ }
+
+ var row:int = 0;
+ var col:int = -1;
+
+ var move:Move = null;
+
+ var n:int = catalog.length;
+ for (var i:int = 0 ; i < n ; i++)
+ {
+ var product:Product = catalog.getItemAt(i) as Product;
+ var thumb:ProductCatalogThumbnail = thumbnails[i];
+ if (accepted[product.productId.toString()])
+ {
+ thumb.currentState = "x" + numCols + "cols";
+ col++;
+ if (col > numCols - 1)
+ {
+ row++;
+ col = 0;
+ }
+
+ var xTo:Number = col * (tileWidth + ProductCatalogThumbnail.HORIZONTAL_GAP);
+ var yTo:Number = row * (tileHeight + ProductCatalogThumbnail.VERTICAL_GAP);
+
+ // If the thumbnail is already visible
+ // animate it to its new position.
+ if (thumb.visible)
+ {
+ // Animate only if the position is different
+ // from its current position.
+ if (thumb.x != xTo || thumb.y != yTo)
+ {
+ move = new Move(thumb);
+ move.xTo = xTo;
+ move.yTo = yTo;
+ move.play();
+ }
+ }
+
+ // If the thumbnail was not previously visible, sets its
+ // x and y coordinates. We'll make it reappear after all
+ // the visible thumbnails have reached their new position.
+ else
+ {
+ thumb.x = xTo;
+ thumb.y = yTo;
+// thumb.includeInLayout = true;
+ }
+ }
+ else
+ {
+ thumb.visible = false;
+// thumb.includeInLayout = false;
+ }
+ }
+
+ if (!move)
+ {
+ // No visible thumbnails were animated to a new position;
+ // fade in newly selected thumbnails right away.
+ fadeInThumbnails();
+ }
+ else
+ {
+ //since movement is happening get the scrollbar back to the top
+ scv.verticalScrollPosition = 0;
+ // Fade in newly selected thumbnails after the last
+ // visible thumbnail has moved to its new position.
+ move.addEventListener(Effect.EFFECT_END,
+ function(event:org.apache.flex.events.Event):void
+ {
+ fadeInThumbnails();
+ });
+ }
+ thumbContent.dispatchEvent(new org.apache.flex.events.Event("layoutNeeded"));
+ //return the last move to watch
+ return move;
+ }
+
+ //return the last effect so we could add effectEnd handler if desired
+ private function fadeInThumbnails():void
+ {
+ var n:int = thumbnails.length;
+ var targets:Array = [];
+ for (var i:int = 0; i < n ; i++)
+ {
+ var thumb:ProductCatalogThumbnail = thumbnails[i];
+ if (accepted[thumb.product.productId.toString()] && !thumb.visible)
+ {
+ thumb.alpha = 0;
+ thumb.visible = true;
+ targets.push(thumb);
+ }
+ }
+ if (targets.length > 0)
+ {
+ n = targets.length;
+ for (i = 0; i < n; i++)
+ {
+ var effect:Fade = new Fade(targets[i] as IUIBase);
+ effect.alphaTo = 1;
+ effect.play();
+ }
+ }
+ }
+
+ private function showDetails(product:Product):void
+ {
+ if (currentState == "details")
+ {
+ details.product = product;
+ return;
+ }
+
+ var row:int = -1;
+
+ //should be computed using border metrics instead of hard-coding the 20, but...
+ var xTo:Number = thumbContent.width - ProductCatalogThumbnail.COL_WIDTH_4 - 20;
+ var yTo:Number;
+
+ var move:Move;
+ var first:Boolean = true;
+ var selectedThumb:ProductCatalogThumbnail;
+
+ var n:int = thumbnails.length;
+ for (var i:int = 0; i < n; i++)
+ {
+ var thumb:ProductCatalogThumbnail = thumbnails[i];
+ if (thumb.visible)
+ {
+ row++;
+ yTo = row * (ProductCatalogThumbnail.COL_HEIGHT_4 + ProductCatalogThumbnail.VERTICAL_GAP);
+
+ thumb.currentState = "x4cols";
+
+ if (thumb.x != xTo || thumb.y != yTo)
+ {
+ move = new Move(thumb);
+ if (first)
+ {
+ move.addEventListener(Effect.EFFECT_END,
+ function(event:org.apache.flex.events.Event):void
+ {
+ details.product = product;
+ currentState = "details";
+ });
+
+ first = false;
+ }
+ move.xTo = xTo;
+ move.yTo = yTo;
+ move.play();
+ }
+
+ if (thumb.product == product)
+ {
+ selectedThumb = thumb;
+ }
+ }
+ }
+ if (selectedThumb != null)
+ {
+ //make sure that the selected thumb is visible in the list on the right
+ move.addEventListener(Effect.EFFECT_END,
+ function(e:org.apache.flex.events.Event):void
+ {
+ var curpos:int = scv.verticalScrollPosition;
+ if (selectedThumb.y < curpos)
+ {
+ scv.verticalScrollPosition = y;
+ }
+ else if (selectedThumb.y + ProductCatalogThumbnail.COL_HEIGHT_4 > curpos + thumbContent.height)
+ {
+ //this logic doesn't seem to be perfect but it will do
+ var diff:int = selectedThumb.y - (curpos + thumbContent.height)
+ scv.verticalScrollPosition += diff + ProductCatalogThumbnail.COL_HEIGHT_4 + ProductCatalogThumbnail.VERTICAL_GAP;
+ }
+ });
+ }
+
+ }
+
+ private function productThumbEventHandler(event:ProductThumbEvent):void
+ {
+ if (event.type == ProductThumbEvent.DETAILS)
+ {
+ showDetails(event.product);
+ }
+ else if (event.type == ProductThumbEvent.BROWSE)
+ {
+ if (thumbnailState == "browse")
+ {
+ currentState = "browse";
+ layoutCatalog();
+ }
+ else
+ {
+ compare();
+ }
+ }
+ else
+ {
+ dispatchEvent(event);
+ }
+ }
+
+ public function compare(toCompare:Array=null):void
+ {
+ currentState = "compare";
+ thumbnailState = "compare";
+ if (toCompare != null)
+ {
+ var n:int = thumbnails.length;
+ for (var i:int = 0; i < n; i++)
+ {
+ accepted[thumbnails[i].product.productId.toString()] = false;
+ }
+ for (i=0; i < toCompare.length; i++)
+ {
+ accepted[toCompare[i].productId.toString()] = true;
+ }
+ }
+ var lastEffect:Effect = layoutCatalog();
+ if (lastEffect != null)
+ {
+ lastEffect.addEventListener(Effect.EFFECT_END,
+ function (event:org.apache.flex.events.Event):void
+ {
+ setCompareState();
+ });
+ }
+ else
+ {
+ setCompareState();
+ }
+ }
+
+ private function setCompareState():void
+ {
+ //avoid an issue if the user clicks quickly where we move into
+ //compare state even though we're no longer in compare
+ if (currentState == "compare")
+ {
+ var n:int = thumbnails.length;
+ for (var i:int = 0; i < n; i++)
+ {
+ var thumb:ProductCatalogThumbnail = thumbnails[i];
+ if (accepted[thumb.product.productId.toString()])
+ {
+ thumb.currentState = "compare";
+ }
+ }
+
+ }
+ }
+
+ public function acceptingDrop(dropTarget:Object, type:String):void
+ {
+
+ }
+
+ public function acceptedDrop(dropTarget:Object, type:String):void
+ {
+
+ }
+
+ ]]>
+ </fx:Script>
+
+ <basic:beads>
+ <basic:ContainerDataBinding />
+ <basic:NonVirtualVerticalLayout />
+ <basic:DragMouseController id="dragger" />
+ <basic:ParentDocumentBead id="pdb" />
+ <basic:PanelView>
+ <basic:titleBar>
+ <basic:TitleBar>
+ <basic:style>
+ <basic:SimpleCSSStyles backgroundColor="0xA65904" />
+ </basic:style>
+ <basic:beads>
+ <productsView:ProductCatalogPanelTitleBarView />
+ </basic:beads>
+ </basic:TitleBar>
+ </basic:titleBar>
+ </basic:PanelView>
+ </basic:beads>
+ <basic:Container width="100%" height="100%">
+ <basic:Container id="thumbContentGroup" width="100%" height="100%">
+ <basic:beads>
+ <basic:ScrollingContainerView id="scv" />
+ <basic:NonVirtualBasicScrollingLayout />
+ </basic:beads>
+ <basic:Container id="thumbContent" width="100%" height="100%" />
+ </basic:Container>
+ <productsView:ProductDetails id="details"
+ width="{ProductCatalogThumbnail.COL_WIDTH_4 * 3}"
+ height="100%"
+ visible="false"
+ visible.details="true"
+ compare="productThumbEventHandler(event)"
+ purchase="productThumbEventHandler(event)"
+ browse="productThumbEventHandler(event)" />
+ </basic:Container>
+
+ <basic:states>
+ <mx:State name="browse" />
+ <mx:State name="compare" />
+ <mx:State name="details" />
+ </basic:states>
+
+</basic:Panel>
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/f2a370c6/examples/FlexJSStore/src/productsView/ProductCatalogPanelTitleBarView.mxml
----------------------------------------------------------------------
diff --git a/examples/FlexJSStore/src/productsView/ProductCatalogPanelTitleBarView.mxml b/examples/FlexJSStore/src/productsView/ProductCatalogPanelTitleBarView.mxml
new file mode 100755
index 0000000..6c6de2b
--- /dev/null
+++ b/examples/FlexJSStore/src/productsView/ProductCatalogPanelTitleBarView.mxml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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
+
+http://www.apache.org/licenses/LICENSE-2.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.
+
+-->
+<basic:MXMLBeadViewBase xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:basic="library://ns.apache.org/flexjs/basic"
+ xmlns:mx="library://ns.adobe.com/flex/mx"
+ xmlns:productsView="productsView.*"
+ >
+ <fx:Script>
+ <![CDATA[
+ import org.apache.flex.html.TitleBar;
+ import org.apache.flex.core.ITitleBarModel;
+ import org.apache.flex.core.UIBase;
+ import org.apache.flex.events.Event;
+
+ private function clickHandler():void
+ {
+ var newEvent:org.apache.flex.events.Event = new org.apache.flex.events.Event('close',true);
+ UIBase(_strand).dispatchEvent(newEvent)
+ }
+ ]]>
+ </fx:Script>
+ <basic:beads>
+ <basic:MXMLBeadViewBaseDataBinding />
+ <basic:LayoutChangeNotifier watchedProperty="{titleLabel.height}" />
+ </basic:beads>
+ <basic:Label id="titleLabel" text="{ITitleBarModel(model).title}"
+ />
+ <basic:CloseButton id="closeButton" click="clickHandler()"
+ visible="{ITitleBarModel(model).showCloseButton}";
+ />
+ <productsView:CatalogTitleButtons />
+</basic:MXMLBeadViewBase>
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/f2a370c6/examples/FlexJSStore/src/productsView/ProductCatalogThumbnail.mxml
----------------------------------------------------------------------
diff --git a/examples/FlexJSStore/src/productsView/ProductCatalogThumbnail.mxml b/examples/FlexJSStore/src/productsView/ProductCatalogThumbnail.mxml
new file mode 100755
index 0000000..6b6d7a6
--- /dev/null
+++ b/examples/FlexJSStore/src/productsView/ProductCatalogThumbnail.mxml
@@ -0,0 +1,232 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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
+
+http://www.apache.org/licenses/LICENSE-2.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.
+
+-->
+<basic:Container xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:basic="library://ns.apache.org/flexjs/basic"
+ xmlns:mx="library://ns.adobe.com/flex/mx"
+ width="{COL_WIDTH_4}" height="{COL_HEIGHT_4}" height.compare="502"
+ width.x4cols="{COL_WIDTH_4}" height.x4cols="{COL_HEIGHT_4}"
+ width.x3cols="{COL_WIDTH_3}" height.x3cols="{COL_HEIGHT_3}"
+ width.x2cols="{COL_WIDTH_2}" height.x2cols="{COL_HEIGHT_2}"
+ rollOver="rollOverHandler(event)"
+ rollOut="rollOutHandler(event)"
+ mouseDown="mouseDownHandler(event)"
+ mouseMove="mouseMoveHandler(event)"
+ mouseUp="mouseUpHandler(event)"
+ click="clickHandler(event)"
+ currentState="x4cols"
+ >
+ <!-- automationName="{product.name}" -->
+ <basic:beads>
+ <basic:ContainerDataBinding />
+ <basic:LayoutChangeNotifier watchedProperty="{details.height}" />
+ </basic:beads>
+ <basic:style>
+ <basic:SimpleCSSStyles borderStyle="solid"
+ borderColor="#FFFFFF" />
+ </basic:style>
+ <fx:Metadata>
+ [Event(name="purchase", type="samples.flexstore.ProductThumbEvent")]
+ [Event(name="compare", type="samples.flexstore.ProductThumbEvent")]
+ [Event(name="details", type="samples.flexstore.ProductThumbEvent")]
+ </fx:Metadata>
+
+ <fx:Script>
+ <![CDATA[
+
+ import org.apache.flex.events.*;
+ import org.apache.flex.utils.PointUtils;
+
+ import samples.flexstore.Product;
+ import samples.flexstore.ProductThumbEvent;
+
+ public static const COL_WIDTH_4:int = 162;
+ public static const COL_HEIGHT_4:int = 122;
+ public static const COL_WIDTH_3:int = 217;
+ public static const COL_HEIGHT_3:int = 165;
+ public static const COL_WIDTH_2:int = 327;
+ public static const COL_HEIGHT_2:int = 250;
+ public static const COMPARE_WIDTH:int = 162;
+ public static const HORIZONTAL_GAP:int = 2;
+ public static const VERTICAL_GAP:int = 3;
+
+ [Bindable]
+ public var product:Product;
+
+ private function rollOverHandler(event:MouseEvent):void
+ {
+ style["borderColor"] = "#CCCCCC";
+ //style["dropShadowEnabled"] = true;
+ buttons.visible = true;
+ }
+
+ private function rollOutHandler(event:MouseEvent):void
+ {
+ style["borderColor"] = "#FFFFFF";
+ //style["dropShadowEnabled"] = false;
+ buttons.visible = false;
+ }
+
+ private var dragStartPoint:Point;
+
+ public function mouseDownHandler(event:MouseEvent):void
+ {
+ if (event.target != purchase &&
+ event.target != compare &&
+ event.target != details)
+ {
+ dragStartPoint = new Point(event.stageX, event.stageY);
+ dragStartPoint = PointUtils.globalToLocal(dragStartPoint, this);
+
+ }
+ }
+
+ public function mouseMoveHandler(event:MouseEvent):void
+ {
+ if (dragStartPoint != null)
+ {
+ var dragEvent:DragEvent = new DragEvent(DragEvent.DRAG_START, true);
+ dragEvent.localX = dragStartPoint.x;
+ dragEvent.localY = dragStartPoint.y;
+ dragEvent.buttonDown = true;
+ dispatchEvent(dragEvent);
+
+ rollOutHandler(event);
+
+ dragStartPoint = null;
+ }
+ }
+
+ public function mouseUpHandler(event:MouseEvent):void
+ {
+ if (dragStartPoint != null)
+ {
+ dragStartPoint = null;
+ }
+ }
+
+ public function clickHandler(event:org.apache.flex.events.Event):void
+ {
+ if (event.target != purchase &&
+ event.target != compare &&
+ event.target != details)
+ {
+ dispatchEvent(new ProductThumbEvent(ProductThumbEvent.DETAILS, product));
+ }
+ }
+
+ ]]>
+ </fx:Script>
+ <fx:Declarations>
+ <basic:CurrencyFormatter currencySymbol="$" id="cf" fractionalDigits="2"/>
+ </fx:Declarations>
+
+ <basic:VContainer id="vb" width="100%" height="100%">
+ <basic:style>
+ <basic:SimpleCSSStyles paddingLeft="6" paddingTop="4" paddingRight="8" paddingBottom="4" />
+ <!-- gap="0"> -->
+ </basic:style>
+
+
+ <basic:Label text="{product.name}" style="fontWeight:bold"/>
+
+ <basic:HContainer width="100%" >
+ <basic:style>
+ <basic:SimpleCSSStyles paddingTop="0" /> <!-- gap="4 -->"
+ </basic:style>
+
+ <basic:Image id="img" height="45" width="45"
+ width.x3cols="60" height.x3cols="60"
+ width.x2cols="60" height.x2cols="60"
+ source="{product.image}" />
+
+ <basic:VContainer id="descr" width="100%" height="100%" >
+ <basic:style>
+ <basic:SimpleCSSStyles paddingTop="0" /> <!-- gap="0" -->
+ </basic:style>
+ <basic:Label text="{product.featureString}" width="80" height="48" />
+ <basic:Label text="{cf.format(product.price)}" style="fontWeight:bold"/>
+ <basic:Spacer height="4"/>
+ <basic:Label text="{product.highlight1}" style="color:#EE8D0C" includeIn="x3cols, x2cols"/>
+ <basic:Label text="{product.highlight2}" style="color:#EE8D0C" includeIn="x3cols, x2cols"/>
+ </basic:VContainer>
+
+ </basic:HContainer>
+
+ <basic:Spacer height="8"/>
+
+ <basic:Label id="compYears" text="Years: {product.experience}" includeIn="compare"/>
+ <basic:Label id="compBlaze" text="BlazeDS: {product.blazeds}" includeIn="compare"/>
+ <basic:Label id="compMobile" text="Mobile: {product.mobile}" includeIn="compare"/>
+ <basic:Label id="compVideo" text="Video: {product.video}" includeIn="compare"/>
+ <basic:Label id="compHigh1" text="Highlight: {product.highlight1}" includeIn="compare"/>
+ <basic:Label id="compHigh2" text="Highlight: {product.highlight2}" includeIn="compare"/>
+ <basic:Label text="Description:" includeIn="compare"/>
+ <basic:Label id="compDesc" text="{product.description}" width="100%" includeIn="compare">
+ <basic:beads>
+ <basic:MultilineTextFieldView />
+ </basic:beads>
+ </basic:Label>
+ </basic:VContainer>
+
+
+ <basic:VContainer id="buttons" visible="false">
+ <basic:style>
+ <basic:SimpleCSSStyles paddingRight="8" right="8" top="12" /> <!-- gap="4" -->
+ </basic:style>
+ <basic:beads>
+ <basic:LayoutChangeNotifier watchedProperty="{purchase.height}" initialValue="0" />
+ <basic:LayoutChangeNotifier watchedProperty="{compare.height}" initialValue="0" />
+ <basic:LayoutChangeNotifier watchedProperty="{details.height}" initialValue="0" />
+ </basic:beads>
+ <basic:ImageButton id="purchase" backgroundImage="assets/button_cart_empty.png"
+ click="dispatchEvent(new ProductThumbEvent(ProductThumbEvent.PURCHASE, product))"
+ width="30">
+ <basic:beads>
+ <basic:ToolTipBead toolTip="Add to cart"/>
+ </basic:beads>
+ </basic:ImageButton>
+ <basic:ImageButton id="compare" backgroundImage="assets/button_compare.png"
+ click="dispatchEvent(new ProductThumbEvent(ProductThumbEvent.COMPARE, product))"
+ width="30">
+ <basic:beads>
+ <basic:ToolTipBead toolTip="Add to compare list"/>
+ </basic:beads>
+ </basic:ImageButton>
+ <basic:ImageButton id="details" backgroundImage="assets/button_details.png"
+ click="dispatchEvent(new ProductThumbEvent(ProductThumbEvent.DETAILS, product))"
+ width="30">
+ <basic:beads>
+ <basic:ToolTipBead toolTip="Show details"/>
+ </basic:beads>
+ </basic:ImageButton>
+ </basic:VContainer>
+
+ <basic:states>
+
+ <mx:State name="compare" />
+
+ <mx:State name="x4cols" />
+
+ <mx:State name="x3cols" />
+
+ <mx:State name="x2cols"/>
+ </basic:states>
+
+</basic:Container>
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/f2a370c6/examples/FlexJSStore/src/productsView/ProductDetails.mxml
----------------------------------------------------------------------
diff --git a/examples/FlexJSStore/src/productsView/ProductDetails.mxml b/examples/FlexJSStore/src/productsView/ProductDetails.mxml
new file mode 100755
index 0000000..ae128b7
--- /dev/null
+++ b/examples/FlexJSStore/src/productsView/ProductDetails.mxml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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
+
+http://www.apache.org/licenses/LICENSE-2.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.
+
+-->
+<basic:Container xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:basic="library://ns.apache.org/flexjs/basic"
+ xmlns:mx="library://ns.adobe.com/flex/mx"
+ xmlns:productsView="productsView.*"
+ >
+ <basic:beads>
+ <basic:ContainerDataBinding />
+ </basic:beads>
+
+ <fx:Metadata>
+ [Event(name="purchase", type="samples.flexstore.ProductThumbEvent")]
+ [Event(name="compare", type="samples.flexstore.ProductThumbEvent")]
+ [Event(name="browse", type="samples.flexstore.ProductThumbEvent")]
+ </fx:Metadata>
+
+ <fx:Script>
+ <![CDATA[
+
+ import mx.events.*;
+
+ import samples.flexstore.Product;
+ import samples.flexstore.ProductThumbEvent;
+
+ private var _product:Product;
+
+ [Bindable]
+ public function get product():Product
+ {
+ return _product;
+ }
+
+ public function set product(p:Product):void
+ {
+ _product = p;
+ tn.selectedIndex = 0;
+ }
+
+ ]]>
+ </fx:Script>
+
+ <fx:Declarations>
+ <basic:CurrencyFormatter currencySymbol="$" id="cf" fractionalDigits="2"/>
+ </fx:Declarations>
+
+ <basic:states>
+ <mx:State name="Features" />
+ <mx:State name="Support" />
+ </basic:states>
+
+ <basic:transitions>
+ <basic:Transition>
+ <basic:Fade />
+ </basic:Transition>
+ </basic:transitions>
+
+ <basic:ButtonBar id="tn" width="100%" change="currentState = tn.selectedItem as String">
+ <basic:dataProvider>
+ <fx:Array>
+ <fx:String>Features</fx:String>
+ <fx:String>Support</fx:String>
+ </fx:Array>
+ </basic:dataProvider>
+ </basic:ButtonBar>
+ <basic:Container width="100%" height="100%" >
+ <basic:style>
+ <basic:SimpleCSSStyles left="4" right="8" top="34" bottom="4" />
+ </basic:style>
+
+
+ <basic:VContainer width="100%" height="100%" includeIn="Features" >
+ <basic:style>
+ <!--<basic:SimpleCSSStyles gap="8"-->
+ <basic:SimpleCSSStyles
+ paddingLeft="8" paddingTop="8" paddingRight="8" paddingBottom="8"/>
+ </basic:style>
+ <basic:HContainer width="100%" style="gap:12">
+
+ <basic:Image id="img" width="101" height="101" source="{product.image}"/>
+
+ <basic:VContainer id="descr" width="100%" height="100%">
+ <basic:style>
+ <basic:SimpleCSSStyles paddingTop="0" />
+ <!--<basic:SimpleCSSStyles paddingTop="0" gap="4" />-->
+ </basic:style>
+
+ <basic:Label text="{product.name}" style="fontSize:11;fontWeight:'bold'"/>
+
+ <basic:Label text="{product.featureString}" width="80" height="48" />
+
+ <basic:Label text="{product.highlight1}" style="color:#EE8D0C"/>
+
+ <basic:Label text="{product.highlight2}" style="color:#EE8D0C"/>
+
+ <basic:Label text="{cf.format(product.price)}" style="fontWeight:'bold'"/>
+
+ </basic:VContainer>
+ </basic:HContainer>
+
+ <basic:Label id="descriptionText" width="100%" height="100%" text="{product.description}"/>
+
+ </basic:VContainer>
+
+ <productsView:ProductSupport width="100%" height="100%" includeIn="Support" />
+
+ </basic:Container>
+
+ <basic:VContainer>
+ <basic:beads>
+ <basic:LayoutChangeNotifier watchedProperty="{purchase.height}" initialValue="0" />
+ <basic:LayoutChangeNotifier watchedProperty="{compare.height}" initialValue="0" />
+ <basic:LayoutChangeNotifier watchedProperty="{tiles.height}" initialValue="0" />
+ </basic:beads>
+ <basic:style>
+ <basic:SimpleCSSStyles marginTop="4" right="16" top="36" />
+ </basic:style>
+ <basic:Spacer width="100%"/>
+ <basic:ImageButton id="purchase" backgroundImage="assets/button_cart_empty.png" click="dispatchEvent(new ProductThumbEvent(ProductThumbEvent.PURCHASE, product))" width="30">
+ <basic:beads>
+ <basic:ToolTipBead toolTip="Add to cart"/>
+ </basic:beads>
+ </basic:ImageButton>
+ <basic:ImageButton id="compare" backgroundImage="assets/button_compare.png" click="dispatchEvent(new ProductThumbEvent(ProductThumbEvent.COMPARE, product))" width="30">
+ <basic:beads>
+ <basic:ToolTipBead toolTip="Add to compare list"/>
+ </basic:beads>
+ </basic:ImageButton>
+ <basic:ImageButton id="tiles" backgroundImage="assets/button_tiles.png" click="dispatchEvent(new ProductThumbEvent(ProductThumbEvent.BROWSE, product));" width="30">
+ <basic:beads>
+ <basic:ToolTipBead toolTip="Back to thumbnail view"/>
+ </basic:beads>
+ </basic:ImageButton>
+ </basic:VContainer>
+
+</basic:Container>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/f2a370c6/examples/FlexJSStore/src/productsView/ProductFilterPanel.mxml
----------------------------------------------------------------------
diff --git a/examples/FlexJSStore/src/productsView/ProductFilterPanel.mxml b/examples/FlexJSStore/src/productsView/ProductFilterPanel.mxml
new file mode 100755
index 0000000..c32ba78
--- /dev/null
+++ b/examples/FlexJSStore/src/productsView/ProductFilterPanel.mxml
@@ -0,0 +1,221 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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
+
+http://www.apache.org/licenses/LICENSE-2.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.
+
+-->
+<basic:VContainer xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:basic="library://ns.apache.org/flexjs/basic"
+ xmlns:mx="library://ns.adobe.com/flex/mx"
+ xmlns:productsView="productsView.*"
+ xmlns:flexstore="samples.flexstore.*"
+ height="100%"
+ currentState="showingThumbnails"
+ initComplete="series.selectedIndex = 0">
+ <basic:style>
+ <basic:SimpleCSSStyles paddingLeft="4"
+ paddingRight="12"
+ paddingTop="12"
+ paddingBottom="8"
+ />
+
+ </basic:style>
+
+ <fx:Metadata>
+ [Event(name="filter", type="samples.flexstore.ProductFilterEvent")]
+ [Event("compare")]
+ </fx:Metadata>
+
+ <fx:Script>
+ <![CDATA[
+ import org.apache.flex.html.Slider;
+ import org.apache.flex.html.SimpleAlert;
+ import samples.flexstore.ProductFilterEvent;
+
+ private var thumbBeingPressed:Boolean;
+
+ private function dispatchFilter():void
+ {
+ var event:ProductFilterEvent =
+ new ProductFilterEvent(filter, thumbBeingPressed);
+ dispatchEvent(event);
+ currentState = "showingThumbnails";
+ }
+
+ private function sliderValue(values:Array, index:int):Number
+ {
+ return values[index];
+ }
+
+ private function productRemoved():void
+ {
+ if (currentState == "showingComparison")
+ {
+ if (productList.items.length == 0)
+ {
+ dispatchFilter();
+ }
+ else
+ {
+ attemptCompare();
+ }
+ }
+ }
+
+ private function attemptCompare():void
+ {
+ if (productList.items.length > 0)
+ {
+ dispatchEvent(new Event("compare"));
+ currentState = "showingComparison";
+ }
+ else
+ {
+ SimpleAlert.show("There are no items to compare.", "Compare");
+ }
+ }
+
+ ]]>
+ </fx:Script>
+ <fx:Declarations>
+ <flexstore:ProductFilter id="filter">
+ <flexstore:experience>{series.selectedItem}</flexstore:experience>
+ <flexstore:minPrice>{loPrice.value}</flexstore:minPrice>
+ <flexstore:maxPrice>{hiPrice.value}</flexstore:maxPrice>
+ <flexstore:blazeds>{cbBlazeDS.selected}</flexstore:blazeds>
+ <flexstore:mobile>{cbMobile.selected}</flexstore:mobile>
+ <flexstore:video>{cbVideo.selected}</flexstore:video>
+ </flexstore:ProductFilter>
+
+ <basic:CurrencyFormatter currencySymbol="$" id="cf"/>
+
+ </fx:Declarations>
+ <basic:beads>
+ <basic:ContainerDataBinding />
+ </basic:beads>
+
+ <basic:Label text="Find" className="sectionHeader"/>
+
+ <basic:Container width="100%">
+ <basic:beads>
+ <basic:FlexibleFirstChildHorizontalLayout />
+ </basic:beads>
+ <basic:TextInput className="glass" width="100%"/>
+ <basic:TextButton className="glass" text="Go" click="SimpleAlert.show('This feature is not implemented in this sample', 'Find')"/>
+ </basic:Container>
+
+ <basic:Spacer height="18"/>
+
+ <basic:HRule width="100%"/>
+
+ <basic:Spacer height="8"/>
+
+ <basic:HContainer>
+ <basic:style>
+ <basic:SimpleCSSStyles paddingTop="0" paddingLeft="0" verticalAlign="bottom" />
+ </basic:style>
+ <basic:Label text="Filter" className="sectionHeader"/>
+ <basic:Label text="({filter.count} items selected)" >
+ <basic:style>
+ <basic:SimpleCSSStyles fontWeight="bold" />
+ <!--<basic:SimpleCSSStyles color="{getStyle('themeColor')}" fontWeight="bold" />-->
+ </basic:style>
+ </basic:Label>
+ </basic:HContainer>
+
+ <basic:Spacer height="8"/>
+
+ <basic:Label text="Years of Experience"/>
+
+ <basic:DropDownList id="series" className="glass" width="140" change="dispatchFilter();">
+ <basic:dataProvider>
+ <fx:Array>
+ <fx:String>All</fx:String>
+ <fx:String>3</fx:String>
+ <fx:String>5</fx:String>
+ <fx:String>7</fx:String>
+ <fx:String>9</fx:String>
+ </fx:Array>
+ </basic:dataProvider>
+ </basic:DropDownList>
+
+ <basic:Spacer height="18"/>
+
+ <basic:Label text="Price"/>
+
+ <!--<s:HSlider id="priceSlider" className="glassSlider" minimum="0" maximum="200" tickInterval="10" snapInterval="10"
+ width="100%" thumbCount="2" values="[0,200]" labels="[$0,$200]" liveDragging="true" dataTipFormatFunction="{cf.format}"
+ change="dispatchFilter()"
+ thumbPress="thumbBeingPressed=true"
+ thumbRelease="thumbBeingPressed=false;dispatchFilter()"
+ />-->
+ <basic:HContainer>
+ <basic:NumericStepper width="48%" id="loPrice" minimum="0" maximum="{hiPrice.value}" value="0" valueChange="dispatchFilter()" />
+ <basic:NumericStepper width="48%" id="hiPrice" minimum="{loPrice.value}" maximum="200" value="200" valueChange="dispatchFilter()" />
+ </basic:HContainer>
+
+ <basic:Spacer height="18"/>
+
+ <basic:Label text="Required Features"/>
+
+ <basic:Spacer height="4"/>
+
+ <basic:CheckBox id="cbBlazeDS" className="glass" text="BlazeDS" click="dispatchFilter();"/>
+ <basic:Spacer height="4"/>
+ <basic:CheckBox id="cbMobile" className="glass" text="Mobile" click="dispatchFilter()"/>
+ <basic:Spacer height="4"/>
+ <basic:CheckBox id="cbVideo" className="glass" text="Video" click="dispatchFilter();"/>
+
+ <basic:Spacer height="18"/>
+
+ <basic:HRule width="100%"/>
+
+ <basic:Spacer height="8"/>
+
+ <basic:HContainer>
+ <basic:Label text="Compare" className="sectionHeader"/>
+ <basic:Label text="(Drag items here to compare)" className="instructions"/>
+ </basic:HContainer>
+
+
+ <basic:Spacer height="4"/>
+
+ <!-- height is maxItems * ProductListItem.HEIGHT + 2px border -->
+ <productsView:ProductList id="productList" height="{productList.maxItems * ProductListItem.HEIGHT + 2}" width="100%"
+ newItemStartX="300" newItemStartY="-100" maxItems="4"
+ removeProduct="productRemoved()"/>
+
+ <basic:Spacer height="8"/>
+
+ <basic:TextButton id="compareButton" className="glass"
+ click.showingThumbnails="attemptCompare()"
+ click.showingComparison="dispatchFilter()"
+ text.showingComparison="Back to thumbnail view"
+ text.showingThumbnails="Compare Items"
+ >
+ <basic:beads>
+ <basic:ImageAndTextButtonView
+ image.showingThumbnails="assets/icon_compare.png"
+ image.showingComparison="assets/icon_tiles.png" />
+ </basic:beads>
+ </basic:TextButton>
+
+ <basic:states>
+ <mx:State name="showingThumbnails" />
+ <mx:State name="showingComparison" />
+ </basic:states>
+
+</basic:VContainer>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/f2a370c6/examples/FlexJSStore/src/productsView/ProductList.mxml
----------------------------------------------------------------------
diff --git a/examples/FlexJSStore/src/productsView/ProductList.mxml b/examples/FlexJSStore/src/productsView/ProductList.mxml
new file mode 100755
index 0000000..2d54ed7
--- /dev/null
+++ b/examples/FlexJSStore/src/productsView/ProductList.mxml
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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
+
+http://www.apache.org/licenses/LICENSE-2.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.
+
+-->
+<basic:Container xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:basic="library://ns.apache.org/flexjs/basic"
+ xmlns:mx="library://ns.adobe.com/flex/mx"
+ >
+ <basic:style>
+ <basic:SimpleCSSStyles borderStyle="solid" backgroundColor="#BCB29F" />
+ </basic:style>
+ <!-- need a background color for drag and drop but can set alpha to 0 -->
+
+ <fx:Metadata>
+ [Event(name="addProduct", type="samples.flexstore.ProductListEvent")]
+ [Event(name="duplicateProduct", type="samples.flexstore.ProductListEvent")]
+ [Event(name="productQtyChange", type="samples.flexstore.ProductListEvent")]
+ [Event(name="removeProduct", type="samples.flexstore.ProductListEvent")]
+ </fx:Metadata>
+
+ <fx:Script>
+ <![CDATA[
+ import org.apache.flex.effects.Effect;
+ import org.apache.flex.effects.Move;
+ import org.apache.flex.effects.Sequence;
+ import org.apache.flex.core.DropType;
+ import org.apache.flex.core.IUIBase;
+ import org.apache.flex.events.DragEvent;
+
+ import samples.flexstore.Product;
+ import samples.flexstore.ProductListEvent;
+
+ public var items:Array = [];
+
+ public var newItemStartX:int;
+ public var newItemStartY:int;
+ [Bindable]
+ public var maxItems:int;
+ public var showQuantity:Boolean;
+
+ private var playingEffects:Object = new Object();
+
+ public function addProduct(product:Product):void
+ {
+ var index:int = indexOf(product.productId);
+ var event:ProductListEvent;
+ var item:ProductListItem;
+
+ if (index != -1)
+ {
+ item = items[index] as ProductListItem;
+ //if we don't keep track of what's playing a double-click can
+ //cause the list item to keep rising
+ if (playingEffects[item.uid] == null)
+ {
+ var jump:Sequence = new Sequence();
+ var m1:Move = new Move(item)
+ m1.yBy = -5;
+ var m2:Move = new Move(item)
+ m2.yBy = 5;
+ jump.addChild(m1);
+ jump.addChild(m2);
+ jump.duration = 150;
+ playingEffects[item.uid] = jump;
+ jump.addEventListener(Effect.EFFECT_END, function(event:Event):void
+ {
+ delete playingEffects[item.uid];
+ });
+ jump.play();
+ }
+ event = new ProductListEvent(ProductListEvent.DUPLICATE_PRODUCT);
+ event.product = item.product;
+ dispatchEvent(event);
+ }
+ else
+ {
+ index = items.length;
+ if (maxItems <= 0 || index < maxItems)
+ {
+ item = new ProductListItem();
+ if (showQuantity)
+ {
+ item.currentState = 'showQuantity';
+ }
+ item.product = product;
+ item.percentWidth = 100;
+ item.addEventListener(ProductListEvent.REMOVE_PRODUCT, removeItemHandler);
+ items[index] = item;
+ viewport.addElement(item);
+ layoutItems(index, true);
+ event = new ProductListEvent(ProductListEvent.ADD_PRODUCT);
+ event.product = product;
+ dispatchEvent(event);
+ }
+ }
+ }
+
+ public function getProducts():Array
+ {
+ var ret:Array = [];
+ for (var i:int = 0; i < items.length; i++)
+ {
+ ret[i] = items[i].product;
+ }
+ return ret;
+ }
+
+ private function removeItemHandler(event:Event):void
+ {
+ var item:ProductListItem = event.target as ProductListItem;
+ var index:int = indexOf(item.product.productId);
+ items.splice(index, 1);
+ viewport.removeElement(item);
+ layoutItems(index);
+ }
+
+ private function layoutItems(startIndex:int, scrollToBottom:Boolean=false):void
+ {
+ var n:int = items.length;
+ var e:Move;
+ for (var i:int = startIndex; i < n ; i++)
+ {
+ var item:ProductListItem = items[i];
+ var yTo:Number = i * (item.height);
+ //still need to prevent items that are already in motion from getting
+ //jumpy
+ if (playingEffects[item.uid] == null)
+ {
+ e = new Move(item);
+ if (item.x == 0 && item.y == 0)
+ {
+ e.xFrom = newItemStartX;
+ e.yFrom = newItemStartY;
+ }
+
+ e.xTo = 0;
+ e.yTo = yTo;
+ playingEffects[item.uid] = e;
+ e.addEventListener(Effect.EFFECT_END, function(event:Event):void
+ {
+ delete playingEffects[item.uid];
+ });
+ e.play();
+ }
+ else
+ {
+ playingEffects[item.uid].pause();
+ playingEffects[item.uid].yTo = yTo;
+ playingEffects[item.uid].play();
+ }
+ }
+ //get the last event and if we should scroll make sure we can validate
+ //and scroll to maxVPosition
+ if (scrollToBottom)
+ {
+ e.addEventListener(Effect.EFFECT_END, function(event:Event):void
+ {
+ scrollingView.verticalScrollPosition = scrollingView.maxVerticalScrollPosition;
+ });
+ }
+ }
+
+ private function indexOf(productId:int):int
+ {
+ var index:int = -1;
+
+ var n:int = items.length;
+ for (var i:int = 0; i < items.length; i++)
+ {
+ if (items[i].product.productId == productId)
+ {
+ index = i;
+ break;
+ }
+ }
+
+ return index;
+ }
+
+ private function doDragEnter(event:DragEvent):void
+ {
+ trace("doDragEnter");
+ dmc.acceptDragDrop(event.target as IUIBase, DropType.COPY);
+ }
+
+ private function doDragDrop(event:DragEvent):void
+ {
+ trace("doDragDrop");
+ var product:Product = event.dragSource as Product;
+ addProduct(product);
+ }
+
+ ]]>
+ </fx:Script>
+ <basic:beads>
+ <basic:DropMouseController id="dmc" dragEnter="doDragEnter(event)" dragDrop="doDragDrop(event)" />
+ <basic:ScrollingContainerView id="scrollingView" />
+ <basic:NonVirtualVerticalScrollingLayout />
+ </basic:beads>
+ <basic:Container id="viewport" width="100%" height="100%" >
+ </basic:Container>
+</basic:Container>
http://git-wip-us.apache.org/repos/asf/flex-asjs/blob/f2a370c6/examples/FlexJSStore/src/productsView/ProductListItem.mxml
----------------------------------------------------------------------
diff --git a/examples/FlexJSStore/src/productsView/ProductListItem.mxml b/examples/FlexJSStore/src/productsView/ProductListItem.mxml
new file mode 100755
index 0000000..b4fe57d
--- /dev/null
+++ b/examples/FlexJSStore/src/productsView/ProductListItem.mxml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+
+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
+
+http://www.apache.org/licenses/LICENSE-2.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.
+
+-->
+<basic:Container xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:basic="library://ns.apache.org/flexjs/basic"
+ xmlns:mx="library://ns.adobe.com/flex/mx"
+ className="listItem"
+ height="{ProductListItem.HEIGHT}" implements="org.apache.flex.core.IItemRenderer">
+ <!--automationName="{product.name}">-->
+
+ <fx:Metadata>
+ [Event(name="productQtyChange", type="samples.flexstore.ProductListEvent")]
+ [Event(name="removeProduct", type="samples.flexstore.ProductListEvent")]
+ </fx:Metadata>
+
+ <fx:Script>
+ <![CDATA[
+
+ import samples.flexstore.Product;
+ import samples.flexstore.ProductListEvent;
+
+ private static var idCounter:int = 0;
+ public var uid:String = (idCounter++).toString();
+
+ public static const HEIGHT:int = 30;
+
+ [Bindable("__NoChangeEvent__")]
+ public function get product():Product
+ {
+ return _data as Product;
+ }
+ public function set product(value:Product):void
+ {
+ _data = value;
+ }
+
+ private var _data:Object;
+
+ public function get data():Object
+ {
+ return _data;
+ }
+
+ public function set data(value:Object):void
+ {
+ _data = value;
+ }
+
+ private var _itemRendererParent:Object;
+
+ public function get itemRendererParent():Object
+ {
+ return _itemRendererParent;
+ }
+
+ public function set itemRendererParent(value:Object):void
+ {
+ _itemRendererParent = value;
+ }
+
+ private function qtyChange():void
+ {
+ product.qty = int(qty.text);
+ var event:ProductListEvent = new ProductListEvent(ProductListEvent.PRODUCT_QTY_CHANGE);
+ event.product = product;
+ dispatchEvent(event);
+ }
+
+ private function removeItem():void
+ {
+ var event:ProductListEvent = new ProductListEvent(ProductListEvent.REMOVE_PRODUCT);
+ event.product = product;
+ dispatchEvent(event);
+ }
+
+ ]]>
+ </fx:Script>
+
+ <fx:Declarations>
+ <basic:CurrencyFormatter currencySymbol="$" id="cf" fractionalDigits="2"/>
+ </fx:Declarations>
+
+ <basic:beads>
+ <basic:ContainerDataBinding />
+ </basic:beads>
+
+ <basic:ImageButton id="removeButton" backgroundImage="assets/trashcan.png"
+ width="14" height="14"
+ click="removeItem()">
+ <basic:beads>
+ <basic:ToolTipBead toolTip="Remove from cart" />
+ </basic:beads>
+ </basic:ImageButton>
+
+ <basic:Image id="productImage" x="14" width="12" height="12" source="{product.image}"/>
+
+ <basic:Label id="productName" x="26" width="100" text="{product.name}"/>
+
+ <basic:Label id="productPrice" width="60"
+ text="{cf.format(product.price)}" style="textAlign:right;right:0"
+ style.showQuantity="textAlign:right;right:25"/>
+
+ <basic:TextInput id="qty" width="25" text="{product.qty}" includeIn="showQuantity"
+ style="textAlign:right;right:0" change="qtyChange()" >
+ <basic:beads>
+ <basic:NumericOnlyTextInputBead maxChars="3" />
+ </basic:beads>
+ </basic:TextInput>
+
+ <basic:states>
+ <mx:State name="compare" />
+ <mx:State name="showQuantity" />
+ </basic:states>
+
+</basic:Container>