Version Notes
Custom Product Design Tools, No Support Provided
Download this release
Release Info
Developer | blg4mail.com |
Extension | Blog4mails |
Version | 1.0.0 |
Comparing to | |
See all releases |
Version 1.0.0
- app/code/community/Blog4mail/Customproduct/Block/Customproduct.php +17 -0
- app/code/community/Blog4mail/Customproduct/Helper/Data.php +6 -0
- app/code/community/Blog4mail/Customproduct/Model/Customproduct.php +10 -0
- app/code/community/Blog4mail/Customproduct/Model/Mysql4/Customproduct.php +10 -0
- app/code/community/Blog4mail/Customproduct/Model/Mysql4/Customproduct/Collection.php +10 -0
- app/code/community/Blog4mail/Customproduct/Model/Status.php +15 -0
- app/code/community/Blog4mail/Customproduct/controllers/IndexController.php +617 -0
- app/code/community/Blog4mail/Customproduct/controllers/IndexController.php~ +617 -0
- app/code/community/Blog4mail/Customproduct/etc/config.xml +72 -0
- app/code/community/Blog4mail/Customproduct/etc/config.xml~ +72 -0
- app/code/community/Blog4mail/Customproduct/sql/customproduct_setup/mysql4-install-1.0.0.php +52 -0
- app/code/community/Blog4mail/Customproduct/sql/customproduct_setup/mysql4-install-1.0.0.php~ +52 -0
- app/code/community/Blog4mail/Customproduct/sql/customproduct_setup/mysql4-install-1.0.php~ +52 -0
- app/code/community/Blog4mail/Customproduct/sql/customproduct_setup/mysql4-upgrade-1.0-1.1.php~ +27 -0
- app/code/community/Blog4mail/Customproduct/sql/customproduct_setup/mysql4-upgrade-1.3.4-1.4.php~ +34 -0
- app/code/community/Blog4mail/Customproductadmin/Block/Customproduct.php +12 -0
- app/code/community/Blog4mail/Customproductadmin/Block/Customproduct/Edit.php +45 -0
- app/code/community/Blog4mail/Customproductadmin/Block/Customproduct/Edit/Form.php +19 -0
- app/code/community/Blog4mail/Customproductadmin/Block/Customproduct/Edit/Tab/Form.php +58 -0
- app/code/community/Blog4mail/Customproductadmin/Block/Customproduct/Edit/Tabs.php +24 -0
- app/code/community/Blog4mail/Customproductadmin/Block/Customproduct/Grid.php +116 -0
- app/code/community/Blog4mail/Customproductadmin/Helper/Data.php +6 -0
- app/code/community/Blog4mail/Customproductadmin/controllers/CustomproductController.php +214 -0
- app/code/community/Blog4mail/Customproductadmin/etc/config.xml +68 -0
- app/code/community/Blog4mail/customproduct_catalog.xml~ +93 -0
- app/design/frontend/base/default/layout/customproduct_catalog.xml +252 -0
- app/design/frontend/base/default/template/catalog/product/view/media_custom.phtml +115 -0
- app/design/frontend/base/default/template/catalog/product/view_custom.phtml +635 -0
- app/etc/modules/Blog4mail_Customproduct.xml +9 -0
- media/finalimages/2b0e7ecb7dffaca13b2be8c6f4e5f89e.jpg +0 -0
- media/finalimages/46c4f93a056c2e11c45c301a0dda1da4.jpg +0 -0
- media/finalimages/8605d98db258cb59cd4a0bc5e1374104.jpg +0 -0
- media/finalimages/upload/50ef9eafe2774image1.jpeg +0 -0
- media/finalimages/upload/50ef9ef6b49aeimage1.jpeg +0 -0
- media/finalimages/upload/50ef9fa951afcimage1.jpeg +0 -0
- media/finalimages/upload/50efa5be9c0a0image1.jpeg +0 -0
- media/finalimages/upload/50f4f56c28bfdimage1.jpeg +0 -0
- media/finalimages/upload/50f4f56caf383image1.jpeg +0 -0
- media/finalimages/upload/50f4f5e7aa803image1.jpeg +0 -0
- media/finalimages/upload/50f4f71c53eecimage1.jpeg +0 -0
- package.xml +25 -0
- skin/frontend/default/customproduct/css/oauth-simple.css +239 -0
- skin/frontend/default/customproduct/css/print.css +40 -0
- skin/frontend/default/customproduct/css/styles-ie.css +149 -0
- skin/frontend/default/customproduct/css/styles.css +1788 -0
- skin/frontend/default/customproduct/favicon.ico +0 -0
- skin/frontend/default/customproduct/images/addtext.png +0 -0
- skin/frontend/default/customproduct/images/best_selling_tr_even_bg.gif +0 -0
- skin/frontend/default/customproduct/images/best_selling_tr_odd_bg.gif +0 -0
- skin/frontend/default/customproduct/images/bgimage.png +0 -0
- skin/frontend/default/customproduct/images/bgimage7.png +0 -0
- skin/frontend/default/customproduct/images/bkg_account_box.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_block-actions.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_block-currency.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_block-layered-dd.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_block-layered-dt.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_block-layered-label.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_block-layered-li.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_block-layered-title.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_block-layered1.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_block-title-account.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_block-title.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_body.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_buttons-set1.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_checkout.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_collapse-gm.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_collapse.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_divider1.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_form-search.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_grand-total.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_grid.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_header.jpg +0 -0
- skin/frontend/default/customproduct/images/bkg_login-box.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_main1.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_main2.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_nav0.jpg +0 -0
- skin/frontend/default/customproduct/images/bkg_nav1.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_nav2.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_opc-title-off.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_pipe1.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_pipe2.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_pipe3.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_product-view.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_product_collateral.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_rating.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_sp-methods.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_tfoot.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_th-v.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_th.gif +0 -0
- skin/frontend/default/customproduct/images/bkg_toolbar.gif +0 -0
- skin/frontend/default/customproduct/images/btn_checkout.gif +0 -0
- skin/frontend/default/customproduct/images/btn_edit.gif +0 -0
- skin/frontend/default/customproduct/images/btn_gm-close.gif +0 -0
- skin/frontend/default/customproduct/images/btn_google_checkout.gif +0 -0
- skin/frontend/default/customproduct/images/btn_paypal_checkout.gif +0 -0
- skin/frontend/default/customproduct/images/btn_place_order.gif +0 -0
- skin/frontend/default/customproduct/images/btn_previous.gif +0 -0
- skin/frontend/default/customproduct/images/btn_proceed_to_checkout.gif +0 -0
- skin/frontend/default/customproduct/images/btn_proceed_to_checkout_dis.gif +0 -0
- skin/frontend/default/customproduct/images/btn_remove.gif +0 -0
- skin/frontend/default/customproduct/images/btn_remove2.gif +0 -0
- skin/frontend/default/customproduct/images/btn_search.gif +0 -0
- skin/frontend/default/customproduct/images/btn_trash.gif +0 -0
- skin/frontend/default/customproduct/images/btn_window_close.gif +0 -0
- skin/frontend/default/customproduct/images/button1.png +0 -0
- skin/frontend/default/customproduct/images/button2.png +0 -0
- skin/frontend/default/customproduct/images/button3.png +0 -0
- skin/frontend/default/customproduct/images/calendar.gif +0 -0
- skin/frontend/default/customproduct/images/catalog/product/placeholder/image.jpg +0 -0
- skin/frontend/default/customproduct/images/catalog/product/placeholder/small_image.jpg +0 -0
- skin/frontend/default/customproduct/images/catalog/product/placeholder/thumbnail.jpg +0 -0
- skin/frontend/default/customproduct/images/cvv.gif +0 -0
- skin/frontend/default/customproduct/images/cvv.jpg +0 -0
- skin/frontend/default/customproduct/images/fam_book_open.png +0 -0
- skin/frontend/default/customproduct/images/free_shipping_callout.jpg +0 -0
- skin/frontend/default/customproduct/images/grid-cal.gif +0 -0
- skin/frontend/default/customproduct/images/home_left_callout.jpg +0 -0
- skin/frontend/default/customproduct/images/home_main_callout.jpg +0 -0
- skin/frontend/default/customproduct/images/i_arrow-top.gif +0 -0
- skin/frontend/default/customproduct/images/i_asc_arrow.gif +0 -0
- skin/frontend/default/customproduct/images/i_availability_only.gif +0 -0
- skin/frontend/default/customproduct/images/i_availability_only_arrow.gif +0 -0
- skin/frontend/default/customproduct/images/i_block-cart.gif +0 -0
- skin/frontend/default/customproduct/images/i_block-currency.gif +0 -0
- skin/frontend/default/customproduct/images/i_block-list.gif +0 -0
- skin/frontend/default/customproduct/images/i_block-poll.gif +0 -0
- skin/frontend/default/customproduct/images/i_block-related.gif +0 -0
- skin/frontend/default/customproduct/images/i_block-subscribe.gif +0 -0
- skin/frontend/default/customproduct/images/i_block-tags.gif +0 -0
- skin/frontend/default/customproduct/images/i_block-viewed.gif +0 -0
- skin/frontend/default/customproduct/images/i_block-wishlist.gif +0 -0
- skin/frontend/default/customproduct/images/i_desc_arrow.gif +0 -0
- skin/frontend/default/customproduct/images/i_discount.gif +0 -0
- skin/frontend/default/customproduct/images/i_folder-table.gif +0 -0
- skin/frontend/default/customproduct/images/i_ma-info.gif +0 -0
- skin/frontend/default/customproduct/images/i_ma-reviews.gif +0 -0
- skin/frontend/default/customproduct/images/i_ma-tags.gif +0 -0
- skin/frontend/default/customproduct/images/i_msg-error.gif +0 -0
- skin/frontend/default/customproduct/images/i_msg-note.gif +0 -0
- skin/frontend/default/customproduct/images/i_msg-success.gif +0 -0
- skin/frontend/default/customproduct/images/i_notice.gif +0 -0
- skin/frontend/default/customproduct/images/i_page1.gif +0 -0
- skin/frontend/default/customproduct/images/i_page2.gif +0 -0
- skin/frontend/default/customproduct/images/i_pager-next.gif +0 -0
- skin/frontend/default/customproduct/images/i_pager-prev.gif +0 -0
- skin/frontend/default/customproduct/images/i_print.gif +0 -0
- skin/frontend/default/customproduct/images/i_rss-big.png +0 -0
- skin/frontend/default/customproduct/images/i_rss.gif +0 -0
- skin/frontend/default/customproduct/images/i_search_criteria.gif +0 -0
- skin/frontend/default/customproduct/images/i_shipping.gif +0 -0
- skin/frontend/default/customproduct/images/i_tag_add.gif +0 -0
- skin/frontend/default/customproduct/images/i_tier.gif +0 -0
- skin/frontend/default/customproduct/images/i_type_grid.gif +0 -0
- skin/frontend/default/customproduct/images/i_type_list.gif +0 -0
- skin/frontend/default/customproduct/images/logo.gif +0 -0
- skin/frontend/default/customproduct/images/logo_email.gif +0 -0
- skin/frontend/default/customproduct/images/logo_print.gif +0 -0
- skin/frontend/default/customproduct/images/magnifier_handle.gif +0 -0
- skin/frontend/default/customproduct/images/map_popup_arrow.gif +0 -0
- skin/frontend/default/customproduct/images/media/404_callout1.jpg +0 -0
- skin/frontend/default/customproduct/images/media/404_callout2.jpg +0 -0
- skin/frontend/default/customproduct/images/media/about_us_img.jpg +0 -0
- skin/frontend/default/customproduct/images/media/best_selling_img01.jpg +0 -0
- skin/frontend/default/customproduct/images/media/best_selling_img02.jpg +0 -0
- skin/frontend/default/customproduct/images/media/best_selling_img03.jpg +0 -0
- skin/frontend/default/customproduct/images/media/best_selling_img04.jpg +0 -0
- skin/frontend/default/customproduct/images/media/best_selling_img05.jpg +0 -0
- skin/frontend/default/customproduct/images/media/best_selling_img06.jpg +0 -0
- skin/frontend/default/customproduct/images/media/cell_phone_landing_banner1.jpg +0 -0
- skin/frontend/default/customproduct/images/media/col_left_callout.jpg +0 -0
- skin/frontend/default/customproduct/images/media/col_right_callout.jpg +0 -0
- skin/frontend/default/customproduct/images/media/electronics_cellphones.jpg +0 -0
- skin/frontend/default/customproduct/images/media/electronics_digitalcameras.jpg +0 -0
- skin/frontend/default/customproduct/images/media/electronics_laptops.jpg +0 -0
- skin/frontend/default/customproduct/images/media/furniture_callout_spot.jpg +0 -0
- skin/frontend/default/customproduct/images/media/furnitures_bed_room.jpg +0 -0
- skin/frontend/default/customproduct/images/media/furnitures_living_room.jpg +0 -0
- skin/frontend/default/customproduct/images/media/head_electronics_cellphones.gif +0 -0
- skin/frontend/default/customproduct/images/media/head_electronics_digicamera.gif +0 -0
- skin/frontend/default/customproduct/images/media/head_electronics_laptops.gif +0 -0
- skin/frontend/default/customproduct/images/media/laptop_callout_mid1.jpg +0 -0
- skin/frontend/default/customproduct/images/media/laptop_callout_mid2.jpg +0 -0
- skin/frontend/default/customproduct/images/media/laptop_callout_mid3.jpg +0 -0
- skin/frontend/default/customproduct/images/media/laptop_callout_spot.jpg +0 -0
- skin/frontend/default/customproduct/images/media/shirts_landing_banner1.jpg +0 -0
- skin/frontend/default/customproduct/images/np_cart_thumb.gif +0 -0
- skin/frontend/default/customproduct/images/np_more_img.gif +0 -0
- skin/frontend/default/customproduct/images/np_product_main.gif +0 -0
- skin/frontend/default/customproduct/images/np_thumb.gif +0 -0
- skin/frontend/default/customproduct/images/np_thumb2.gif +0 -0
- skin/frontend/default/customproduct/images/opc-ajax-loader.gif +0 -0
- skin/frontend/default/customproduct/images/pager_arrow_left.gif +0 -0
- skin/frontend/default/customproduct/images/pager_arrow_right.gif +0 -0
- skin/frontend/default/customproduct/images/ph_callout_left_rebel.jpg +0 -0
- skin/frontend/default/customproduct/images/ph_callout_left_top.gif +0 -0
- skin/frontend/default/customproduct/images/product_zoom_overlay_magnif.gif +0 -0
- skin/frontend/default/customproduct/images/slider_bg.gif +0 -0
- skin/frontend/default/customproduct/images/slider_btn_zoom_in.gif +0 -0
- skin/frontend/default/customproduct/images/slider_btn_zoom_out.gif +0 -0
- skin/frontend/default/customproduct/images/spacer.gif +0 -0
- skin/frontend/default/customproduct/images/textimage.png +0 -0
- skin/frontend/default/customproduct/images/validation_advice_bg.gif +0 -0
- skin/frontend/default/customproduct/images/xmlconnect/catalog/category/placeholder/image.jpg +0 -0
- skin/frontend/default/customproduct/images/xmlconnect/catalog/category/placeholder/small_image.jpg +0 -0
- skin/frontend/default/customproduct/images/xmlconnect/catalog/category/placeholder/thumbnail.jpg +0 -0
- skin/frontend/default/customproduct/images/xmlconnect/tab_account.png +0 -0
- skin/frontend/default/customproduct/images/xmlconnect/tab_cart.png +0 -0
- skin/frontend/default/customproduct/images/xmlconnect/tab_home.png +0 -0
- skin/frontend/default/customproduct/images/xmlconnect/tab_more.png +0 -0
- skin/frontend/default/customproduct/images/xmlconnect/tab_page.png +0 -0
- skin/frontend/default/customproduct/images/xmlconnect/tab_search.png +0 -0
- skin/frontend/default/customproduct/images/xmlconnect/tab_shop.png +0 -0
- skin/frontend/default/customproduct/js/Uize.Array.Dupes.js +188 -0
- skin/frontend/default/customproduct/js/Uize.Array.Order.js +338 -0
- skin/frontend/default/customproduct/js/Uize.Array.Sort.js +510 -0
- skin/frontend/default/customproduct/js/Uize.Array.Util.js +206 -0
- skin/frontend/default/customproduct/js/Uize.Array.js +28 -0
- skin/frontend/default/customproduct/js/Uize.Build.All.js +68 -0
- skin/frontend/default/customproduct/js/Uize.Build.AuditStrings.js +215 -0
- skin/frontend/default/customproduct/js/Uize.Build.AutoScruncher.js +217 -0
- skin/frontend/default/customproduct/js/Uize.Build.ModuleInfo.js +104 -0
- skin/frontend/default/customproduct/js/Uize.Build.NeatenJsFiles.js +74 -0
- skin/frontend/default/customproduct/js/Uize.Build.RunUnitTest.js +41 -0
- skin/frontend/default/customproduct/js/Uize.Build.RunUnitTests.js +89 -0
- skin/frontend/default/customproduct/js/Uize.Build.Scruncher.js +515 -0
- skin/frontend/default/customproduct/js/Uize.Build.ServicesSetup.js +51 -0
- skin/frontend/default/customproduct/js/Uize.Build.UpdateCopyrightNotices.js +94 -0
- skin/frontend/default/customproduct/js/Uize.Build.Util.js +359 -0
- skin/frontend/default/customproduct/js/Uize.Build.js +28 -0
- skin/frontend/default/customproduct/js/Uize.Class.Value.js +44 -0
- skin/frontend/default/customproduct/js/Uize.Class.js +2288 -0
- skin/frontend/default/customproduct/js/Uize.Color.js +1515 -0
- skin/frontend/default/customproduct/js/Uize.Color.xCmyk.js +237 -0
- skin/frontend/default/customproduct/js/Uize.Color.xHsv.js +223 -0
- skin/frontend/default/customproduct/js/Uize.Color.xSvgColors.js +324 -0
- skin/frontend/default/customproduct/js/Uize.Color.xUtil.js +720 -0
- skin/frontend/default/customproduct/js/Uize.Comm.Ajax.js +108 -0
- skin/frontend/default/customproduct/js/Uize.Comm.Iframe.Upload.js +77 -0
- skin/frontend/default/customproduct/js/Uize.Comm.Iframe.js +106 -0
- skin/frontend/default/customproduct/js/Uize.Comm.Script.js +115 -0
- skin/frontend/default/customproduct/js/Uize.Comm.js +518 -0
- skin/frontend/default/customproduct/js/Uize.Cookie.js +115 -0
- skin/frontend/default/customproduct/js/Uize.Curve.Mod.js +522 -0
- skin/frontend/default/customproduct/js/Uize.Curve.Rubber.js +538 -0
- skin/frontend/default/customproduct/js/Uize.Curve.js +854 -0
- skin/frontend/default/customproduct/js/Uize.Data.Combinations.js +725 -0
- skin/frontend/default/customproduct/js/Uize.Data.Csv.js +1190 -0
- skin/frontend/default/customproduct/js/Uize.Data.Matches.js +369 -0
app/code/community/Blog4mail/Customproduct/Block/Customproduct.php
ADDED
@@ -0,0 +1,17 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
class Blog4mail_Customproduct_Block_Customproduct extends Mage_Core_Block_Template
|
3 |
+
{
|
4 |
+
public function _prepareLayout()
|
5 |
+
{
|
6 |
+
return parent::_prepareLayout();
|
7 |
+
}
|
8 |
+
|
9 |
+
public function getCustomproduct()
|
10 |
+
{
|
11 |
+
if (!$this->hasData('customproduct')) {
|
12 |
+
$this->setData('customproduct', Mage::registry('customproduct'));
|
13 |
+
}
|
14 |
+
return $this->getData('customproduct');
|
15 |
+
|
16 |
+
}
|
17 |
+
}
|
app/code/community/Blog4mail/Customproduct/Helper/Data.php
ADDED
@@ -0,0 +1,6 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Blog4mail_Customproduct_Helper_Data extends Mage_Core_Helper_Abstract
|
4 |
+
{
|
5 |
+
|
6 |
+
}
|
app/code/community/Blog4mail/Customproduct/Model/Customproduct.php
ADDED
@@ -0,0 +1,10 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Blog4mail_Customproduct_Model_Customproduct extends Mage_Core_Model_Abstract
|
4 |
+
{
|
5 |
+
public function _construct()
|
6 |
+
{
|
7 |
+
parent::_construct();
|
8 |
+
$this->_init('customproduct/customproduct');
|
9 |
+
}
|
10 |
+
}
|
app/code/community/Blog4mail/Customproduct/Model/Mysql4/Customproduct.php
ADDED
@@ -0,0 +1,10 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Blog4mail_Customproduct_Model_Mysql4_Customproduct extends Mage_Core_Model_Mysql4_Abstract
|
4 |
+
{
|
5 |
+
public function _construct()
|
6 |
+
{
|
7 |
+
// Note that the customproduct_id refers to the key field in your database table.
|
8 |
+
$this->_init('customproduct/customproduct', 'customproduct_id');
|
9 |
+
}
|
10 |
+
}
|
app/code/community/Blog4mail/Customproduct/Model/Mysql4/Customproduct/Collection.php
ADDED
@@ -0,0 +1,10 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Blog4mail_Customproduct_Model_Mysql4_Customproduct_Collection extends Mage_Core_Model_Mysql4_Collection_Abstract
|
4 |
+
{
|
5 |
+
public function _construct()
|
6 |
+
{
|
7 |
+
parent::_construct();
|
8 |
+
$this->_init('customproduct/customproduct');
|
9 |
+
}
|
10 |
+
}
|
app/code/community/Blog4mail/Customproduct/Model/Status.php
ADDED
@@ -0,0 +1,15 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Blog4mail_Customproduct_Model_Status extends Varien_Object
|
4 |
+
{
|
5 |
+
const STATUS_ENABLED = 1;
|
6 |
+
const STATUS_DISABLED = 2;
|
7 |
+
|
8 |
+
static public function getOptionArray()
|
9 |
+
{
|
10 |
+
return array(
|
11 |
+
self::STATUS_ENABLED => Mage::helper('customproduct')->__('Enabled'),
|
12 |
+
self::STATUS_DISABLED => Mage::helper('customproduct')->__('Disabled')
|
13 |
+
);
|
14 |
+
}
|
15 |
+
}
|
app/code/community/Blog4mail/Customproduct/controllers/IndexController.php
ADDED
@@ -0,0 +1,617 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
class Blog4mail_Customproduct_IndexController extends Mage_Core_Controller_Front_Action
|
3 |
+
{
|
4 |
+
public function indexAction()
|
5 |
+
{
|
6 |
+
$this->loadLayout();
|
7 |
+
$this->renderLayout();
|
8 |
+
}
|
9 |
+
|
10 |
+
protected function set_file_name($new_name = '') { // this 'conversion' is used for unique/new filenames
|
11 |
+
if ($this->rename_file) {
|
12 |
+
if ($this->the_file == '') return;
|
13 |
+
$name = ($new_name == '') ? uniqid() : $new_name;
|
14 |
+
sleep(3);
|
15 |
+
$name = $name.$this->get_extension($this->the_file);
|
16 |
+
} else {
|
17 |
+
$name = str_replace(' ', '_', $this->the_file); // space will result in problems on linux systems
|
18 |
+
}
|
19 |
+
return $name;
|
20 |
+
}
|
21 |
+
|
22 |
+
public function uploadAction(){
|
23 |
+
|
24 |
+
|
25 |
+
$bsdir = Mage::getBaseDir('base');
|
26 |
+
|
27 |
+
|
28 |
+
$dest_dir = $bsdir.'/media/finalimages/upload/';
|
29 |
+
$source = $_FILES['userfile']['tmp_name'];
|
30 |
+
$filename = $_FILES['userfile']['name'];
|
31 |
+
$newfile = uniqid().$filename;
|
32 |
+
move_uploaded_file($source,$dest_dir.$newfile);
|
33 |
+
print $newfile;
|
34 |
+
|
35 |
+
}
|
36 |
+
|
37 |
+
public function ajaxoptionsAction()
|
38 |
+
{
|
39 |
+
$pid=$_REQUEST['product_id'];
|
40 |
+
$product = Mage::getModel('catalog/product')->load($pid);
|
41 |
+
$html=$this->getProductOptionsHtml($product);
|
42 |
+
print $html;
|
43 |
+
}
|
44 |
+
|
45 |
+
public function getProductOptionsHtml(Mage_Catalog_Model_Product $product)
|
46 |
+
{
|
47 |
+
|
48 |
+
$x = Mage::app()->getLayout()->createBlock("Mage_Core_Block_Template");
|
49 |
+
|
50 |
+
$x->setTemplate("catalog/product/view/options/js.phtml");
|
51 |
+
$a=$x->toHtml();
|
52 |
+
|
53 |
+
$y = Mage::app()->getLayout()->createBlock("Mage_Catalog_Block_Product_View_Options");
|
54 |
+
$y->setProduct($product);
|
55 |
+
$y->setTemplate("catalog/product/view/options.phtml");
|
56 |
+
$b=$y->toHtml();
|
57 |
+
|
58 |
+
$z = Mage::app()->getLayout()->createBlock("Mage_Core_Block_Html_Calendar");
|
59 |
+
$z->setProduct($product);
|
60 |
+
$z->setTemplate("page/js/calendar.phtml");
|
61 |
+
$c = $z->toHtml();
|
62 |
+
|
63 |
+
|
64 |
+
$blockOption = Mage::app()->getLayout()->createBlock("Mage_Catalog_Block_Product_View_Options");
|
65 |
+
$blockOption->addOptionRenderer("default","catalog/product_view_options_type_default","catalog/product/view/options/type/default.phtml");
|
66 |
+
$blockOption->addOptionRenderer("text","catalog/product_view_options_type_text","catalog/product/view/options/type/text.phtml");
|
67 |
+
$blockOption->addOptionRenderer("file","catalog/product_view_options_type_file","catalog/product/view/options/type/file.phtml");
|
68 |
+
$blockOption->addOptionRenderer("select","catalog/product_view_options_type_select","catalog/product/view/options/type/select.phtml");
|
69 |
+
$blockOption->addOptionRenderer("date","catalog/product_view_options_type_date","catalog/product/view/options/type/date.phtml") ;
|
70 |
+
$blockOptionsHtml = null;
|
71 |
+
|
72 |
+
|
73 |
+
|
74 |
+
if($product->getTypeId()=="simple"||$product->getTypeId()=="virtual"||$product->getTypeId()=="configurable")
|
75 |
+
{
|
76 |
+
|
77 |
+
|
78 |
+
|
79 |
+
$blockOption->setProduct($product);
|
80 |
+
if($product->getOptions())
|
81 |
+
{
|
82 |
+
foreach ($product->getOptions() as $o)
|
83 |
+
{
|
84 |
+
$h=$blockOption->getOptionHtml($o);
|
85 |
+
|
86 |
+
$blockOptionsHtml .= $blockOption->getOptionHtml($o);
|
87 |
+
};
|
88 |
+
}
|
89 |
+
}
|
90 |
+
|
91 |
+
|
92 |
+
|
93 |
+
if($product->getTypeId()=="configurable")
|
94 |
+
{
|
95 |
+
$blockViewType = Mage::app()->getLayout()->createBlock("Mage_Catalog_Block_Product_View_Type_Configurable");
|
96 |
+
$blockViewType->setProduct($product);
|
97 |
+
//$blockViewType->setTemplate("inchoo_catalog/product/view/type/options/configurable.phtml");
|
98 |
+
$blockViewType->setTemplate("mage_catalog/product/view/type/options/configurable.phtml");
|
99 |
+
$blockOptionsHtml .= $blockViewType->toHtml();
|
100 |
+
}
|
101 |
+
return $a.$b.$blockOptionsHtml.$c;
|
102 |
+
}
|
103 |
+
|
104 |
+
public function setMyCustomOption($productId, $title, array $optionData, array $values = array())
|
105 |
+
{
|
106 |
+
$product = Mage::getModel('catalog/product')->load($productId);
|
107 |
+
|
108 |
+
$data = array_merge( $optionData, array(
|
109 |
+
'product_id' => (int)$productId,
|
110 |
+
'title' => $title,
|
111 |
+
'values' => $values,
|
112 |
+
));
|
113 |
+
|
114 |
+
|
115 |
+
//$data=$optionData;
|
116 |
+
|
117 |
+
$product->setHasOptions(1)->save();
|
118 |
+
$option = Mage::getModel('catalog/product_option')->setData($data)->setProduct($product)->save();
|
119 |
+
|
120 |
+
return $option;
|
121 |
+
}
|
122 |
+
|
123 |
+
|
124 |
+
public function textAction(){
|
125 |
+
$spath1 = $_SERVER['DOCUMENT_ROOT'];
|
126 |
+
|
127 |
+
$spath = $_SERVER['SCRIPT_FILENAME'];
|
128 |
+
|
129 |
+
|
130 |
+
$spath = substr($spath,0,-9);
|
131 |
+
$ex=explode($spath1,$spath);
|
132 |
+
|
133 |
+
$host=$_SERVER['HTTP_HOST'];
|
134 |
+
|
135 |
+
$webpath = "http://".$host.$ex[1].'media/';
|
136 |
+
//print $webpath;
|
137 |
+
//return;
|
138 |
+
|
139 |
+
$mytext = $_REQUEST['mytext'];
|
140 |
+
|
141 |
+
|
142 |
+
/* Create some objects */
|
143 |
+
$image = new Imagick();
|
144 |
+
$draw = new ImagickDraw();
|
145 |
+
|
146 |
+
$pixel = new ImagickPixel('white');
|
147 |
+
|
148 |
+
$transparent = new ImagickPixel('white');
|
149 |
+
|
150 |
+
|
151 |
+
$w=strlen($mytext)*10;
|
152 |
+
|
153 |
+
/* New image */
|
154 |
+
$image->newImage($w,15,$pixel);
|
155 |
+
$image->paintTransparentImage($transparent, 0, 10);
|
156 |
+
|
157 |
+
/* Black text */
|
158 |
+
$draw->setFillColor('blue');
|
159 |
+
|
160 |
+
/* Font properties */
|
161 |
+
$draw->setFont('Bookman-DemiItalic');
|
162 |
+
$draw->setFontSize(11);
|
163 |
+
|
164 |
+
/* Create text */
|
165 |
+
|
166 |
+
$image->annotateImage($draw,15,10,0,$mytext);
|
167 |
+
|
168 |
+
/* Give image a format */
|
169 |
+
|
170 |
+
$x = md5($mytext.time()).'.png';
|
171 |
+
$filename = $spath.'media/'.$x;
|
172 |
+
|
173 |
+
|
174 |
+
$image->setImageFormat('png');
|
175 |
+
$image->writeImages($filename,true);
|
176 |
+
|
177 |
+
echo $webpath.$x;
|
178 |
+
|
179 |
+
//echo $filename;
|
180 |
+
/* Output the image with headers */
|
181 |
+
//header('Content-type: image/png');
|
182 |
+
//echo $image;
|
183 |
+
}
|
184 |
+
|
185 |
+
public function imageAction(){
|
186 |
+
|
187 |
+
|
188 |
+
|
189 |
+
$baseurl1 = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
|
190 |
+
|
191 |
+
$bsdir = Mage::getBaseDir('base');
|
192 |
+
$product_id = $_REQUEST['product'];
|
193 |
+
$filename = $bsdir.'/media/finalimages/'.md5(time().$product).'.jpg';
|
194 |
+
|
195 |
+
$filename1=$baseurl1.'media/finalimages/'.md5(time().$product).'.jpg';
|
196 |
+
|
197 |
+
$mainimage = $_REQUEST['mainimage'];
|
198 |
+
|
199 |
+
$image = $_REQUEST['image'];
|
200 |
+
|
201 |
+
$oldprice = trim(str_replace('$',' ',$_REQUEST['oldprice']));
|
202 |
+
|
203 |
+
$w = $_REQUEST['width'];
|
204 |
+
$h = $_REQUEST['height'];
|
205 |
+
|
206 |
+
|
207 |
+
/*$pos_left = $_REQUEST['left']=150;
|
208 |
+
$pos_top = $_REQUEST['top']=150;
|
209 |
+
*/
|
210 |
+
|
211 |
+
$pos_left = $_REQUEST['left'];
|
212 |
+
$pos_top = $_REQUEST['top'];
|
213 |
+
|
214 |
+
$pos_left_text=$_REQUEST['left_text'];
|
215 |
+
$pos_top_text=$_REQUEST['top_text'];
|
216 |
+
|
217 |
+
$w_text=$_REQUEST['w_text'];
|
218 |
+
$h_text=$_REQUEST['h_text'];
|
219 |
+
|
220 |
+
$textimage=$_REQUEST['textimage'];
|
221 |
+
|
222 |
+
//center
|
223 |
+
//system("/var/www/cylinderize -m vertical -r 73 -l 120 -w 90 -p 5 -n 94 -e 2 -s 200 -a 100 -v background -b none -f none -o -15-15 /var/www/yellowpage/image1.jpeg /var/www/yellowpage/mug1.jpeg /var/www/yellowpage/im4.jpeg");
|
224 |
+
|
225 |
+
//Right
|
226 |
+
//system("/var/www/cylinderize -m vertical -r 73 -l 100 -w 100 -p 5 -n 94 -e 2 -s 200 -a -100 -v background -b none -f none -o +24+10 /var/www/yellowpage/image1.jpeg /var/www/yellowpage/mug1.jpeg /var/www/yellowpage/im4.jpeg");
|
227 |
+
|
228 |
+
//Left
|
229 |
+
//system("/var/www/cylinderize -m vertical -r 73 -l 100 -w 100 -p 5 -n 94 -e 2 -s 200 -a 100 -v background -b none -f none -o -24+10 /var/www/yellowpage/image1.jpeg /var/www/yellowpage/mug1.jpeg /var/www/yellowpage/im4.jpeg");
|
230 |
+
|
231 |
+
//system("/var/www/cylinderize -m vertical -r 73 -l 150 -w 150 -p 5 -n 94 -e 2 -s 200 -a -100 -v background -b none -f none -o -15+15 /var/www/yellowpage/image1.jpeg /var/www/yellowpage/mug1.jpeg /var/www/yellowpage/im4.jpeg");
|
232 |
+
|
233 |
+
$foundimage = strpos($mainimage,'bgimage.png');
|
234 |
+
$foundtextimage = strpos($textimage,'textimage.png');
|
235 |
+
|
236 |
+
if ($foundimage !== false && $foundtextimage !== false) {
|
237 |
+
$ar=array();
|
238 |
+
$ar['filename']=0;
|
239 |
+
$ar['opthtml']=0;
|
240 |
+
print json_encode($ar);
|
241 |
+
return;
|
242 |
+
}
|
243 |
+
|
244 |
+
$mug = new Imagick($image);
|
245 |
+
|
246 |
+
if ($foundimage === false) {
|
247 |
+
$im = new Imagick($mainimage);
|
248 |
+
$im->scaleImage($w,$h);
|
249 |
+
$im->setImageFormat('jpeg');
|
250 |
+
$im->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_TRANSPARENT);
|
251 |
+
$im->setImageMatte(true);
|
252 |
+
|
253 |
+
//$im->setImageBackgroundColor('red');
|
254 |
+
|
255 |
+
$height = $im->getImageHeight();
|
256 |
+
|
257 |
+
$mug->compositeImage($im, $im->getImageCompose(),$pos_left, $pos_top);
|
258 |
+
}
|
259 |
+
//$im = new Imagick($bsdir.'/media/image1.jpeg');
|
260 |
+
//$mug = new Imagick($bsdir.'/media/mug1.jpeg');
|
261 |
+
|
262 |
+
|
263 |
+
|
264 |
+
|
265 |
+
if($foundtextimage === false) {
|
266 |
+
$im1 = new Imagick($textimage);
|
267 |
+
$mug->compositeImage($im1, $im1->getImageCompose(),$pos_left_text,$pos_top_text);
|
268 |
+
}
|
269 |
+
|
270 |
+
$persp="$mainimage,$w,$h,$pos_left,$pos_top|$textimage,$w_text,$h_text,$pos_left_text,$pos_top_text";
|
271 |
+
|
272 |
+
|
273 |
+
$mug->writeImages($filename,true);
|
274 |
+
|
275 |
+
$product = Mage::getModel('catalog/product')->load($product_id);
|
276 |
+
$magentoid = $product->getId();
|
277 |
+
|
278 |
+
|
279 |
+
$ctype=$product->getcustomproducttype();
|
280 |
+
|
281 |
+
$sku=$product->getSku();
|
282 |
+
$sku = $sku.'custom'.time();
|
283 |
+
|
284 |
+
|
285 |
+
|
286 |
+
if($magentoid && $ctype == 'designed'){
|
287 |
+
// UPDATE RECORDS
|
288 |
+
$data['id']=$product->getId();
|
289 |
+
$data['name']=$product->getName();
|
290 |
+
$data['desc']=$product->getDescription();
|
291 |
+
$data['shortdesc']=$product->getShortDescription();
|
292 |
+
$data['sku']=$sku;
|
293 |
+
$data['weight']=$product->getWeight();
|
294 |
+
$data['status']=$product->getStatus();
|
295 |
+
|
296 |
+
//$price = $product->getPrice();
|
297 |
+
//$data['price'] = $price;
|
298 |
+
$data['price'] = round($oldprice+($oldprice*5/100),2);
|
299 |
+
$data['designed']=$product->getcustomproducttype();
|
300 |
+
$data['image']=$filename;
|
301 |
+
$data['persp']=$persp;
|
302 |
+
|
303 |
+
$id=$this->_updateShopsProduct($data,$designedProduct='true',$magentoid);
|
304 |
+
$opthtml=$this->getProductOptionsHtml($product);
|
305 |
+
} else {
|
306 |
+
//print 'create';
|
307 |
+
//return;
|
308 |
+
// INSERT RECORDS
|
309 |
+
$data['id']=$product->getId();
|
310 |
+
$data['name']=$product->getName();
|
311 |
+
$data['desc']=$product->getDescription();
|
312 |
+
$data['shortdesc']=$product->getShortDescription();
|
313 |
+
$data['sku'] = $sku;
|
314 |
+
$data['weight']=$product->getWeight();
|
315 |
+
$data['status']=$product->getStatus();
|
316 |
+
//$price = $product->getPrice() + ($product->getPrice()*10/100);
|
317 |
+
//$data['price'] = $price;
|
318 |
+
$data['price'] = round($oldprice + ($oldprice*5/100),2);
|
319 |
+
$data['designed']='designed';
|
320 |
+
$data['image']=$filename;
|
321 |
+
$data['persp']=$persp;
|
322 |
+
$id = $this->createShopsProduct($data,$designedProduct='true');
|
323 |
+
$opthtml=$this->getProductOptionsHtml($product);
|
324 |
+
}
|
325 |
+
|
326 |
+
|
327 |
+
|
328 |
+
$ar=array();
|
329 |
+
$ar['filename']=$filename1;
|
330 |
+
$ar['opthtml']=$opthtml;
|
331 |
+
$ar['product_id']=$id;
|
332 |
+
$ar['price']=$data['price'];
|
333 |
+
print json_encode($ar);
|
334 |
+
}
|
335 |
+
|
336 |
+
|
337 |
+
|
338 |
+
protected function _updateShopsProduct($data,$designedProduct,$magentoid){
|
339 |
+
$serverurl = $data['image'];
|
340 |
+
try{
|
341 |
+
$_product = Mage::getModel('catalog/product');
|
342 |
+
$product = $_product->load($magentoid);
|
343 |
+
|
344 |
+
//
|
345 |
+
// foreach ($product->getOptions() as $opt)
|
346 |
+
// {
|
347 |
+
// $opt->delete();
|
348 |
+
// }
|
349 |
+
// $product->save();
|
350 |
+
|
351 |
+
$store = Mage::app()->getStore(Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID);
|
352 |
+
$product->setStoreId($store->getId());
|
353 |
+
|
354 |
+
/*
|
355 |
+
$websiteIds = array();
|
356 |
+
|
357 |
+
|
358 |
+
if (Mage::app()->isSingleStoreMode()) {
|
359 |
+
$websites = Mage::app()->getWebsites();
|
360 |
+
foreach($websites as $curWebsite){
|
361 |
+
$websiteIds[] = $curWebsite->getId();
|
362 |
+
}
|
363 |
+
|
364 |
+
}
|
365 |
+
else {
|
366 |
+
|
367 |
+
|
368 |
+
$website = Mage::app()->getWebsite();
|
369 |
+
$websiteIds[] = $website->getId();
|
370 |
+
}
|
371 |
+
|
372 |
+
$product->setWebsiteIds($websiteIds);
|
373 |
+
*/
|
374 |
+
|
375 |
+
$product->setName($data['name']);
|
376 |
+
$product->setDescription($data['desc']);
|
377 |
+
$product->setShortDescription($data['shortdesc']);
|
378 |
+
$product->setPrice($data['price']);
|
379 |
+
$product->setWeight($data['weight']);
|
380 |
+
$product->setSku($data['sku']);
|
381 |
+
$product->setcustomproducttype($designedProduct);
|
382 |
+
$product->setcustomperspective($data['persp']);
|
383 |
+
|
384 |
+
$mediaApi = Mage::getModel("catalog/product_attribute_media_api");
|
385 |
+
$items = $mediaApi->items($product->getId());
|
386 |
+
|
387 |
+
foreach($items as $item){
|
388 |
+
$mediaApi->remove($product->getId(), $item['file']);
|
389 |
+
}
|
390 |
+
|
391 |
+
$product->addImageToMediaGallery($serverurl,array('thumbnail','small_image','image'),false,false);
|
392 |
+
|
393 |
+
Mage::dispatchEvent('catalog_product_prepare_save',array('product' => $product, 'request' => null));
|
394 |
+
$product->save();
|
395 |
+
return $magentoid;
|
396 |
+
}
|
397 |
+
catch (Exception $e) {
|
398 |
+
Mage::logException($e);
|
399 |
+
return null;
|
400 |
+
}
|
401 |
+
}
|
402 |
+
|
403 |
+
|
404 |
+
|
405 |
+
|
406 |
+
public function customdesignAction(){
|
407 |
+
|
408 |
+
$ar['alias'] = 'Mugs - Good';
|
409 |
+
$ar['description']='Mugs - Good';
|
410 |
+
$ar['shortDescription']='Mugs - Good';
|
411 |
+
$ar['MSRP']='10.50';
|
412 |
+
$ar['weight']=1;
|
413 |
+
$ar['_id']=2;
|
414 |
+
$ar['clientSku']='A1';
|
415 |
+
|
416 |
+
|
417 |
+
|
418 |
+
$en=json_encode($ar);
|
419 |
+
|
420 |
+
|
421 |
+
$data = json_decode($en);
|
422 |
+
|
423 |
+
|
424 |
+
$this->createShopsProduct($data, $designedProduct='true');
|
425 |
+
|
426 |
+
|
427 |
+
print 'Helo';
|
428 |
+
}
|
429 |
+
|
430 |
+
|
431 |
+
|
432 |
+
|
433 |
+
|
434 |
+
|
435 |
+
|
436 |
+
public function createShopsProduct($data, $designedProduct='true'){
|
437 |
+
|
438 |
+
|
439 |
+
// Add or create new product magento through code with custom options, image and manage stock
|
440 |
+
// mmoves image and assigns to all three types image, small_image and thumbnail_image
|
441 |
+
//require_once 'app/Mage.php';
|
442 |
+
//umask(0);
|
443 |
+
|
444 |
+
//$app = Mage::app();
|
445 |
+
//$session = Mage::getSingleton('customer/session', array('name'=>'frontend'));
|
446 |
+
|
447 |
+
|
448 |
+
|
449 |
+
//create a new product
|
450 |
+
|
451 |
+
try {
|
452 |
+
|
453 |
+
//$serverurl = $_SERVER['DOCUMENT_ROOT'].'/yellowpage/image6.jpeg';
|
454 |
+
$serverurl=$data['image'];
|
455 |
+
$product = Mage::getModel('catalog/product');
|
456 |
+
|
457 |
+
$stockData = $product->getStockData();
|
458 |
+
|
459 |
+
$stockData['qty'] = 1;
|
460 |
+
$stockData['is_in_stock'] = 1;
|
461 |
+
$stockData['manage_stock'] = 1;
|
462 |
+
$stockData['use_config_manage_stock'] = 0;
|
463 |
+
|
464 |
+
$stockData['inventory_use_config_min_sale_qty'] = 1;
|
465 |
+
$stockData['inventory_use_config_max_sale_qty'] = 1;
|
466 |
+
|
467 |
+
$options = array();
|
468 |
+
|
469 |
+
|
470 |
+
$options['Colors']['opt']['type']='radio';
|
471 |
+
$options['Colors']['opt']['is_require']=0;
|
472 |
+
$options['Colors']['opt']['price']=0;
|
473 |
+
$options['Colors']['opt']['price_type']='fixed';
|
474 |
+
|
475 |
+
|
476 |
+
$options['Colors']['values'][0]['title']='Red';
|
477 |
+
$options['Colors']['values'][0]['price']=10.00;
|
478 |
+
$options['Colors']['values'][0]['price_type']='fixed';
|
479 |
+
|
480 |
+
$options['Colors']['values'][1]['title']='Green';
|
481 |
+
$options['Colors']['values'][1]['price']=11.00;
|
482 |
+
$options['Colors']['values'][1]['price_type']='fixed';
|
483 |
+
|
484 |
+
$options['Colors']['values'][2]['title']='Blue';
|
485 |
+
$options['Colors']['values'][2]['price']=12.00;
|
486 |
+
$options['Colors']['values'][2]['price_type']='fixed';
|
487 |
+
|
488 |
+
|
489 |
+
$options['Sizes']['opt']['type']='radio';
|
490 |
+
$options['Sizes']['opt']['is_require']=0;
|
491 |
+
$options['Sizes']['opt']['price']=0;
|
492 |
+
$options['Sizes']['opt']['price_type']='fixed';
|
493 |
+
|
494 |
+
$options['Sizes']['values'][0]['title']='L';
|
495 |
+
$options['Sizes']['values'][0]['price']=9.00;
|
496 |
+
$options['Sizes']['values'][0]['price_type']='fixed';
|
497 |
+
|
498 |
+
$options['Sizes']['values'][1]['title']='XL';
|
499 |
+
$options['Sizes']['values'][1]['price']=15.00;
|
500 |
+
$options['Sizes']['values'][1]['price_type']='fixed';
|
501 |
+
|
502 |
+
|
503 |
+
|
504 |
+
/*$options['title'] = array(
|
505 |
+
'title' => 'Colors',
|
506 |
+
'type' => 'radio',
|
507 |
+
'is_require' => 1,
|
508 |
+
'sort_order' => 0,
|
509 |
+
'values' => array()
|
510 |
+
);
|
511 |
+
|
512 |
+
$options['values'][] = array(
|
513 |
+
'title' => 'Red',
|
514 |
+
'price' => 10.00,
|
515 |
+
'price_type' => 'fixed',
|
516 |
+
'sku' => '',
|
517 |
+
'sort_order' => '1'
|
518 |
+
);
|
519 |
+
|
520 |
+
$options['values'][] = array(
|
521 |
+
'title' => 'Green',
|
522 |
+
'price' => 89.00,
|
523 |
+
'price_type' => 'fixed',
|
524 |
+
'sku' => '',
|
525 |
+
'sort_order' => '1'
|
526 |
+
);
|
527 |
+
|
528 |
+
$options['values'][] = array(
|
529 |
+
'title' => 'Blue',
|
530 |
+
'price' => 89.00,
|
531 |
+
'price_type' => 'fixed',
|
532 |
+
'sku' => '',
|
533 |
+
'sort_order' => '1'
|
534 |
+
);
|
535 |
+
*/
|
536 |
+
|
537 |
+
|
538 |
+
|
539 |
+
|
540 |
+
$store = Mage::app()->getStore(Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID);
|
541 |
+
// Save all product attributes under "default" store, no matter whether system is in single or multi-store mode
|
542 |
+
$product->setStoreId($store->getId());
|
543 |
+
// Build array of website ids
|
544 |
+
$websiteIds = array();
|
545 |
+
|
546 |
+
if (Mage::app()->isSingleStoreMode()) {
|
547 |
+
$websites = Mage::app()->getWebsites();
|
548 |
+
foreach($websites as $curWebsite){
|
549 |
+
$websiteIds[] = $curWebsite->getId();
|
550 |
+
}
|
551 |
+
}
|
552 |
+
else {
|
553 |
+
//set to specific website/store
|
554 |
+
$website = Mage::app()->getWebsite();
|
555 |
+
$websiteIds[] = $website->getId();
|
556 |
+
}
|
557 |
+
|
558 |
+
$product->setWebsiteIds($websiteIds);
|
559 |
+
|
560 |
+
$product->setAttributeSetId(Mage::getModel('catalog/product')->getResource()->getEntityType()->getDefaultAttributeSetId());
|
561 |
+
|
562 |
+
//->setAttributeSetId(4)
|
563 |
+
//$product->setStoreId('default')
|
564 |
+
|
565 |
+
$product->setTypeId('simple')
|
566 |
+
->setName($data['name'])
|
567 |
+
->setDescription($data['desc'])
|
568 |
+
->setShortDescription($data['shortdesc'])
|
569 |
+
->setSku($data['sku'])
|
570 |
+
->setWeight($data['weight'])
|
571 |
+
->setStatus($data['status'])
|
572 |
+
//->setVisibility(4)
|
573 |
+
->setPrice($data['price'])
|
574 |
+
->addImageToMediaGallery($serverurl,array('thumbnail','small_image','image'),false,false)
|
575 |
+
->setTaxClassId(0)
|
576 |
+
->setStockData($stockData)
|
577 |
+
->setCategoryIds('3')
|
578 |
+
//->setHasOptions(1)
|
579 |
+
//->setProductOptions(array($opt))
|
580 |
+
//->setCanSaveCustomOptions(true)
|
581 |
+
//->setPageLayout('one_column')
|
582 |
+
->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH)
|
583 |
+
->setCreatedAt(strtotime('now'))
|
584 |
+
->setcustomproducttype($data['designed'])
|
585 |
+
->setcustomperspective($data['persp']);
|
586 |
+
|
587 |
+
Mage::dispatchEvent('catalog_product_prepare_save',array('product' => $product, 'request' => null));
|
588 |
+
Mage::log("setup product");
|
589 |
+
|
590 |
+
$product->save();
|
591 |
+
$product_id = $product->getId();
|
592 |
+
|
593 |
+
//echo 'OK Product ID: '.$product->getId();
|
594 |
+
|
595 |
+
foreach($options as $title=>$v){
|
596 |
+
$this->setMyCustomOption($product_id,$title,$optionData=$v['opt'],$values = $v['values']);
|
597 |
+
}
|
598 |
+
|
599 |
+
$cache = Mage::getSingleton('core/cache');
|
600 |
+
$cache->flush();
|
601 |
+
|
602 |
+
return $product->getId();
|
603 |
+
}
|
604 |
+
catch (Mage_Core_Exception $e) {
|
605 |
+
echo $e->getMessage();
|
606 |
+
}
|
607 |
+
catch (Exception $e) {
|
608 |
+
echo $e;
|
609 |
+
}
|
610 |
+
|
611 |
+
|
612 |
+
|
613 |
+
}
|
614 |
+
|
615 |
+
|
616 |
+
}
|
617 |
+
?>
|
app/code/community/Blog4mail/Customproduct/controllers/IndexController.php~
ADDED
@@ -0,0 +1,617 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
class Blog4mail_Customproduct_IndexController extends Mage_Core_Controller_Front_Action
|
3 |
+
{
|
4 |
+
public function indexAction()
|
5 |
+
{
|
6 |
+
$this->loadLayout();
|
7 |
+
$this->renderLayout();
|
8 |
+
}
|
9 |
+
|
10 |
+
protected function set_file_name($new_name = '') { // this 'conversion' is used for unique/new filenames
|
11 |
+
if ($this->rename_file) {
|
12 |
+
if ($this->the_file == '') return;
|
13 |
+
$name = ($new_name == '') ? uniqid() : $new_name;
|
14 |
+
sleep(3);
|
15 |
+
$name = $name.$this->get_extension($this->the_file);
|
16 |
+
} else {
|
17 |
+
$name = str_replace(' ', '_', $this->the_file); // space will result in problems on linux systems
|
18 |
+
}
|
19 |
+
return $name;
|
20 |
+
}
|
21 |
+
|
22 |
+
public function uploadAction(){
|
23 |
+
|
24 |
+
|
25 |
+
$bsdir = Mage::getBaseDir('base');
|
26 |
+
|
27 |
+
|
28 |
+
$dest_dir = $bsdir.'/media/finalimages/upload/';
|
29 |
+
$source = $_FILES['userfile']['tmp_name'];
|
30 |
+
$filename = $_FILES['userfile']['name'];
|
31 |
+
$newfile = uniqid().$filename;
|
32 |
+
move_uploaded_file($source,$dest_dir.$newfile);
|
33 |
+
print $newfile;
|
34 |
+
|
35 |
+
}
|
36 |
+
|
37 |
+
public function ajaxoptionsAction()
|
38 |
+
{
|
39 |
+
$pid=$_REQUEST['product_id'];
|
40 |
+
$product = Mage::getModel('catalog/product')->load($pid);
|
41 |
+
$html=$this->getProductOptionsHtml($product);
|
42 |
+
print $html;
|
43 |
+
}
|
44 |
+
|
45 |
+
public function getProductOptionsHtml(Mage_Catalog_Model_Product $product)
|
46 |
+
{
|
47 |
+
|
48 |
+
$x = Mage::app()->getLayout()->createBlock("Mage_Core_Block_Template");
|
49 |
+
|
50 |
+
$x->setTemplate("catalog/product/view/options/js.phtml");
|
51 |
+
$a=$x->toHtml();
|
52 |
+
|
53 |
+
$y = Mage::app()->getLayout()->createBlock("Mage_Catalog_Block_Product_View_Options");
|
54 |
+
$y->setProduct($product);
|
55 |
+
$y->setTemplate("catalog/product/view/options.phtml");
|
56 |
+
$b=$y->toHtml();
|
57 |
+
|
58 |
+
$z = Mage::app()->getLayout()->createBlock("Mage_Core_Block_Html_Calendar");
|
59 |
+
$z->setProduct($product);
|
60 |
+
$z->setTemplate("page/js/calendar.phtml");
|
61 |
+
$c = $z->toHtml();
|
62 |
+
|
63 |
+
|
64 |
+
$blockOption = Mage::app()->getLayout()->createBlock("Mage_Catalog_Block_Product_View_Options");
|
65 |
+
$blockOption->addOptionRenderer("default","catalog/product_view_options_type_default","catalog/product/view/options/type/default.phtml");
|
66 |
+
$blockOption->addOptionRenderer("text","catalog/product_view_options_type_text","catalog/product/view/options/type/text.phtml");
|
67 |
+
$blockOption->addOptionRenderer("file","catalog/product_view_options_type_file","catalog/product/view/options/type/file.phtml");
|
68 |
+
$blockOption->addOptionRenderer("select","catalog/product_view_options_type_select","catalog/product/view/options/type/select.phtml");
|
69 |
+
$blockOption->addOptionRenderer("date","catalog/product_view_options_type_date","catalog/product/view/options/type/date.phtml") ;
|
70 |
+
$blockOptionsHtml = null;
|
71 |
+
|
72 |
+
|
73 |
+
|
74 |
+
if($product->getTypeId()=="simple"||$product->getTypeId()=="virtual"||$product->getTypeId()=="configurable")
|
75 |
+
{
|
76 |
+
|
77 |
+
|
78 |
+
|
79 |
+
$blockOption->setProduct($product);
|
80 |
+
if($product->getOptions())
|
81 |
+
{
|
82 |
+
foreach ($product->getOptions() as $o)
|
83 |
+
{
|
84 |
+
$h=$blockOption->getOptionHtml($o);
|
85 |
+
|
86 |
+
$blockOptionsHtml .= $blockOption->getOptionHtml($o);
|
87 |
+
};
|
88 |
+
}
|
89 |
+
}
|
90 |
+
|
91 |
+
|
92 |
+
|
93 |
+
if($product->getTypeId()=="configurable")
|
94 |
+
{
|
95 |
+
$blockViewType = Mage::app()->getLayout()->createBlock("Mage_Catalog_Block_Product_View_Type_Configurable");
|
96 |
+
$blockViewType->setProduct($product);
|
97 |
+
//$blockViewType->setTemplate("inchoo_catalog/product/view/type/options/configurable.phtml");
|
98 |
+
$blockViewType->setTemplate("mage_catalog/product/view/type/options/configurable.phtml");
|
99 |
+
$blockOptionsHtml .= $blockViewType->toHtml();
|
100 |
+
}
|
101 |
+
return $a.$b.$blockOptionsHtml.$c;
|
102 |
+
}
|
103 |
+
|
104 |
+
public function setMyCustomOption($productId, $title, array $optionData, array $values = array())
|
105 |
+
{
|
106 |
+
$product = Mage::getModel('catalog/product')->load($productId);
|
107 |
+
|
108 |
+
$data = array_merge( $optionData, array(
|
109 |
+
'product_id' => (int)$productId,
|
110 |
+
'title' => $title,
|
111 |
+
'values' => $values,
|
112 |
+
));
|
113 |
+
|
114 |
+
|
115 |
+
//$data=$optionData;
|
116 |
+
|
117 |
+
$product->setHasOptions(1)->save();
|
118 |
+
$option = Mage::getModel('catalog/product_option')->setData($data)->setProduct($product)->save();
|
119 |
+
|
120 |
+
return $option;
|
121 |
+
}
|
122 |
+
|
123 |
+
|
124 |
+
public function textAction(){
|
125 |
+
$spath1 = $_SERVER['DOCUMENT_ROOT'];
|
126 |
+
|
127 |
+
$spath = $_SERVER['SCRIPT_FILENAME'];
|
128 |
+
|
129 |
+
|
130 |
+
$spath = substr($spath,0,-9);
|
131 |
+
$ex=explode($spath1,$spath);
|
132 |
+
|
133 |
+
$host=$_SERVER['HTTP_HOST'];
|
134 |
+
|
135 |
+
$webpath = "http://".$host.$ex[1].'media/';
|
136 |
+
//print $webpath;
|
137 |
+
//return;
|
138 |
+
|
139 |
+
$mytext = $_REQUEST['mytext'];
|
140 |
+
|
141 |
+
|
142 |
+
/* Create some objects */
|
143 |
+
$image = new Imagick();
|
144 |
+
$draw = new ImagickDraw();
|
145 |
+
|
146 |
+
$pixel = new ImagickPixel('white');
|
147 |
+
|
148 |
+
$transparent = new ImagickPixel('white');
|
149 |
+
|
150 |
+
|
151 |
+
$w=strlen($mytext)*10;
|
152 |
+
|
153 |
+
/* New image */
|
154 |
+
$image->newImage($w,15,$pixel);
|
155 |
+
$image->paintTransparentImage($transparent, 0, 10);
|
156 |
+
|
157 |
+
/* Black text */
|
158 |
+
$draw->setFillColor('blue');
|
159 |
+
|
160 |
+
/* Font properties */
|
161 |
+
$draw->setFont('Bookman-DemiItalic');
|
162 |
+
$draw->setFontSize(11);
|
163 |
+
|
164 |
+
/* Create text */
|
165 |
+
|
166 |
+
$image->annotateImage($draw,15,10,0,$mytext);
|
167 |
+
|
168 |
+
/* Give image a format */
|
169 |
+
|
170 |
+
$x = md5($mytext.time()).'.png';
|
171 |
+
$filename = $spath.'media/'.$x;
|
172 |
+
|
173 |
+
|
174 |
+
$image->setImageFormat('png');
|
175 |
+
$image->writeImages($filename,true);
|
176 |
+
|
177 |
+
echo $webpath.$x;
|
178 |
+
|
179 |
+
//echo $filename;
|
180 |
+
/* Output the image with headers */
|
181 |
+
//header('Content-type: image/png');
|
182 |
+
//echo $image;
|
183 |
+
}
|
184 |
+
|
185 |
+
public function imageAction(){
|
186 |
+
|
187 |
+
|
188 |
+
|
189 |
+
$baseurl1 = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
|
190 |
+
|
191 |
+
$bsdir = Mage::getBaseDir('base');
|
192 |
+
$product_id = $_REQUEST['product'];
|
193 |
+
$filename = $bsdir.'/media/finalimages/'.md5(time().$product).'.jpg';
|
194 |
+
|
195 |
+
$filename1=$baseurl1.'media/finalimages/'.md5(time().$product).'.jpg';
|
196 |
+
|
197 |
+
$mainimage = $_REQUEST['mainimage'];
|
198 |
+
|
199 |
+
$image = $_REQUEST['image'];
|
200 |
+
|
201 |
+
$oldprice = trim(str_replace('$',' ',$_REQUEST['oldprice']));
|
202 |
+
|
203 |
+
$w = $_REQUEST['width'];
|
204 |
+
$h = $_REQUEST['height'];
|
205 |
+
|
206 |
+
|
207 |
+
/*$pos_left = $_REQUEST['left']=150;
|
208 |
+
$pos_top = $_REQUEST['top']=150;
|
209 |
+
*/
|
210 |
+
|
211 |
+
$pos_left = $_REQUEST['left'];
|
212 |
+
$pos_top = $_REQUEST['top'];
|
213 |
+
|
214 |
+
$pos_left_text=$_REQUEST['left_text'];
|
215 |
+
$pos_top_text=$_REQUEST['top_text'];
|
216 |
+
|
217 |
+
$w_text=$_REQUEST['w_text'];
|
218 |
+
$h_text=$_REQUEST['h_text'];
|
219 |
+
|
220 |
+
$textimage=$_REQUEST['textimage'];
|
221 |
+
|
222 |
+
//center
|
223 |
+
//system("/var/www/cylinderize -m vertical -r 73 -l 120 -w 90 -p 5 -n 94 -e 2 -s 200 -a 100 -v background -b none -f none -o -15-15 /var/www/yellowpage/image1.jpeg /var/www/yellowpage/mug1.jpeg /var/www/yellowpage/im4.jpeg");
|
224 |
+
|
225 |
+
//Right
|
226 |
+
//system("/var/www/cylinderize -m vertical -r 73 -l 100 -w 100 -p 5 -n 94 -e 2 -s 200 -a -100 -v background -b none -f none -o +24+10 /var/www/yellowpage/image1.jpeg /var/www/yellowpage/mug1.jpeg /var/www/yellowpage/im4.jpeg");
|
227 |
+
|
228 |
+
//Left
|
229 |
+
//system("/var/www/cylinderize -m vertical -r 73 -l 100 -w 100 -p 5 -n 94 -e 2 -s 200 -a 100 -v background -b none -f none -o -24+10 /var/www/yellowpage/image1.jpeg /var/www/yellowpage/mug1.jpeg /var/www/yellowpage/im4.jpeg");
|
230 |
+
|
231 |
+
//system("/var/www/cylinderize -m vertical -r 73 -l 150 -w 150 -p 5 -n 94 -e 2 -s 200 -a -100 -v background -b none -f none -o -15+15 /var/www/yellowpage/image1.jpeg /var/www/yellowpage/mug1.jpeg /var/www/yellowpage/im4.jpeg");
|
232 |
+
|
233 |
+
$foundimage = strpos($mainimage,'bgimage.png');
|
234 |
+
$foundtextimage = strpos($textimage,'textimage.png');
|
235 |
+
|
236 |
+
if ($foundimage !== false && $foundtextimage !== false) {
|
237 |
+
$ar=array();
|
238 |
+
$ar['filename']=0;
|
239 |
+
$ar['opthtml']=0;
|
240 |
+
print json_encode($ar);
|
241 |
+
return;
|
242 |
+
}
|
243 |
+
|
244 |
+
$mug = new Imagick($image);
|
245 |
+
|
246 |
+
if ($foundimage === false) {
|
247 |
+
$im = new Imagick($mainimage);
|
248 |
+
$im->scaleImage($w,$h);
|
249 |
+
$im->setImageFormat('jpeg');
|
250 |
+
$im->setImageVirtualPixelMethod(Imagick::VIRTUALPIXELMETHOD_TRANSPARENT);
|
251 |
+
$im->setImageMatte(true);
|
252 |
+
|
253 |
+
//$im->setImageBackgroundColor('red');
|
254 |
+
|
255 |
+
$height = $im->getImageHeight();
|
256 |
+
|
257 |
+
$mug->compositeImage($im, $im->getImageCompose(),$pos_left, $pos_top);
|
258 |
+
}
|
259 |
+
//$im = new Imagick($bsdir.'/media/image1.jpeg');
|
260 |
+
//$mug = new Imagick($bsdir.'/media/mug1.jpeg');
|
261 |
+
|
262 |
+
|
263 |
+
|
264 |
+
|
265 |
+
if($foundtextimage === false) {
|
266 |
+
$im1 = new Imagick($textimage);
|
267 |
+
$mug->compositeImage($im1, $im1->getImageCompose(),$pos_left_text,$pos_top_text);
|
268 |
+
}
|
269 |
+
|
270 |
+
$persp="$mainimage,$w,$h,$pos_left,$pos_top|$textimage,$w_text,$h_text,$pos_left_text,$pos_top_text";
|
271 |
+
|
272 |
+
|
273 |
+
$mug->writeImages($filename,true);
|
274 |
+
|
275 |
+
$product = Mage::getModel('catalog/product')->load($product_id);
|
276 |
+
$magentoid = $product->getId();
|
277 |
+
|
278 |
+
|
279 |
+
$ctype=$product->getcustomproducttype();
|
280 |
+
|
281 |
+
$sku=$product->getSku();
|
282 |
+
$sku = $sku.'custom'.time();
|
283 |
+
|
284 |
+
|
285 |
+
|
286 |
+
if($magentoid && $ctype == 'designed'){
|
287 |
+
// UPDATE RECORDS
|
288 |
+
$data['id']=$product->getId();
|
289 |
+
$data['name']=$product->getName();
|
290 |
+
$data['desc']=$product->getDescription();
|
291 |
+
$data['shortdesc']=$product->getShortDescription();
|
292 |
+
$data['sku']=$sku;
|
293 |
+
$data['weight']=$product->getWeight();
|
294 |
+
$data['status']=$product->getStatus();
|
295 |
+
|
296 |
+
//$price = $product->getPrice();
|
297 |
+
//$data['price'] = $price;
|
298 |
+
$data['price'] = round($oldprice+($oldprice*5/100),2);
|
299 |
+
$data['designed']=$product->getcustomproducttype();
|
300 |
+
$data['image']=$filename;
|
301 |
+
$data['persp']=$persp;
|
302 |
+
|
303 |
+
$id=$this->_updateShopsProduct($data,$designedProduct='true',$magentoid);
|
304 |
+
$opthtml=$this->getProductOptionsHtml($product);
|
305 |
+
} else {
|
306 |
+
//print 'create';
|
307 |
+
//return;
|
308 |
+
// INSERT RECORDS
|
309 |
+
$data['id']=$product->getId();
|
310 |
+
$data['name']=$product->getName();
|
311 |
+
$data['desc']=$product->getDescription();
|
312 |
+
$data['shortdesc']=$product->getShortDescription();
|
313 |
+
$data['sku'] = $sku;
|
314 |
+
$data['weight']=$product->getWeight();
|
315 |
+
$data['status']=$product->getStatus();
|
316 |
+
//$price = $product->getPrice() + ($product->getPrice()*10/100);
|
317 |
+
//$data['price'] = $price;
|
318 |
+
$data['price'] = round($oldprice + ($oldprice*5/100),2);
|
319 |
+
$data['designed']='designed';
|
320 |
+
$data['image']=$filename;
|
321 |
+
$data['persp']=$persp;
|
322 |
+
$id = $this->createShopsProduct($data,$designedProduct='true');
|
323 |
+
$opthtml=$this->getProductOptionsHtml($product);
|
324 |
+
}
|
325 |
+
|
326 |
+
|
327 |
+
|
328 |
+
$ar=array();
|
329 |
+
$ar['filename']=$filename1;
|
330 |
+
$ar['opthtml']=$opthtml;
|
331 |
+
$ar['product_id']=$id;
|
332 |
+
$ar['price']=$data['price'];
|
333 |
+
print json_encode($ar);
|
334 |
+
}
|
335 |
+
|
336 |
+
|
337 |
+
|
338 |
+
protected function _updateShopsProduct($data,$designedProduct,$magentoid){
|
339 |
+
$serverurl = $data['image'];
|
340 |
+
try{
|
341 |
+
$_product = Mage::getModel('catalog/product');
|
342 |
+
$product = $_product->load($magentoid);
|
343 |
+
|
344 |
+
//
|
345 |
+
// foreach ($product->getOptions() as $opt)
|
346 |
+
// {
|
347 |
+
// $opt->delete();
|
348 |
+
// }
|
349 |
+
// $product->save();
|
350 |
+
|
351 |
+
$store = Mage::app()->getStore(Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID);
|
352 |
+
$product->setStoreId($store->getId());
|
353 |
+
|
354 |
+
/*
|
355 |
+
$websiteIds = array();
|
356 |
+
|
357 |
+
|
358 |
+
if (Mage::app()->isSingleStoreMode()) {
|
359 |
+
$websites = Mage::app()->getWebsites();
|
360 |
+
foreach($websites as $curWebsite){
|
361 |
+
$websiteIds[] = $curWebsite->getId();
|
362 |
+
}
|
363 |
+
|
364 |
+
}
|
365 |
+
else {
|
366 |
+
|
367 |
+
|
368 |
+
$website = Mage::app()->getWebsite();
|
369 |
+
$websiteIds[] = $website->getId();
|
370 |
+
}
|
371 |
+
|
372 |
+
$product->setWebsiteIds($websiteIds);
|
373 |
+
*/
|
374 |
+
|
375 |
+
$product->setName($data['name']);
|
376 |
+
$product->setDescription($data['desc']);
|
377 |
+
$product->setShortDescription($data['shortdesc']);
|
378 |
+
$product->setPrice($data['price']);
|
379 |
+
$product->setWeight($data['weight']);
|
380 |
+
$product->setSku($data['sku']);
|
381 |
+
$product->setcustomproducttype($designedProduct);
|
382 |
+
$product->setcustomperspective($data['persp']);
|
383 |
+
|
384 |
+
$mediaApi = Mage::getModel("catalog/product_attribute_media_api");
|
385 |
+
$items = $mediaApi->items($product->getId());
|
386 |
+
|
387 |
+
foreach($items as $item){
|
388 |
+
$mediaApi->remove($product->getId(), $item['file']);
|
389 |
+
}
|
390 |
+
|
391 |
+
$product->addImageToMediaGallery($serverurl,array('thumbnail','small_image','image'),false,false);
|
392 |
+
|
393 |
+
Mage::dispatchEvent('catalog_product_prepare_save',array('product' => $product, 'request' => null));
|
394 |
+
$product->save();
|
395 |
+
return $magentoid;
|
396 |
+
}
|
397 |
+
catch (Exception $e) {
|
398 |
+
Mage::logException($e);
|
399 |
+
return null;
|
400 |
+
}
|
401 |
+
}
|
402 |
+
|
403 |
+
|
404 |
+
|
405 |
+
|
406 |
+
public function customdesignAction(){
|
407 |
+
|
408 |
+
$ar['alias'] = 'Mugs - Good';
|
409 |
+
$ar['description']='Mugs - Good';
|
410 |
+
$ar['shortDescription']='Mugs - Good';
|
411 |
+
$ar['MSRP']='10.50';
|
412 |
+
$ar['weight']=1;
|
413 |
+
$ar['_id']=2;
|
414 |
+
$ar['clientSku']='A1';
|
415 |
+
|
416 |
+
|
417 |
+
|
418 |
+
$en=json_encode($ar);
|
419 |
+
|
420 |
+
|
421 |
+
$data = json_decode($en);
|
422 |
+
|
423 |
+
|
424 |
+
$this->createShopsProduct($data, $designedProduct='true');
|
425 |
+
|
426 |
+
|
427 |
+
print 'Helo';
|
428 |
+
}
|
429 |
+
|
430 |
+
|
431 |
+
|
432 |
+
|
433 |
+
|
434 |
+
|
435 |
+
|
436 |
+
public function createShopsProduct($data, $designedProduct='true'){
|
437 |
+
|
438 |
+
|
439 |
+
// Add or create new product magento through code with custom options, image and manage stock
|
440 |
+
// mmoves image and assigns to all three types image, small_image and thumbnail_image
|
441 |
+
//require_once 'app/Mage.php';
|
442 |
+
//umask(0);
|
443 |
+
|
444 |
+
//$app = Mage::app();
|
445 |
+
//$session = Mage::getSingleton('customer/session', array('name'=>'frontend'));
|
446 |
+
|
447 |
+
|
448 |
+
|
449 |
+
//create a new product
|
450 |
+
|
451 |
+
try {
|
452 |
+
|
453 |
+
//$serverurl = $_SERVER['DOCUMENT_ROOT'].'/yellowpage/image6.jpeg';
|
454 |
+
$serverurl=$data['image'];
|
455 |
+
$product = Mage::getModel('catalog/product');
|
456 |
+
|
457 |
+
$stockData = $product->getStockData();
|
458 |
+
|
459 |
+
$stockData['qty'] = 1;
|
460 |
+
$stockData['is_in_stock'] = 1;
|
461 |
+
$stockData['manage_stock'] = 1;
|
462 |
+
$stockData['use_config_manage_stock'] = 0;
|
463 |
+
|
464 |
+
$stockData['inventory_use_config_min_sale_qty'] = 1;
|
465 |
+
$stockData['inventory_use_config_max_sale_qty'] = 1;
|
466 |
+
|
467 |
+
$options = array();
|
468 |
+
|
469 |
+
|
470 |
+
$options['Colors']['opt']['type']='radio';
|
471 |
+
$options['Colors']['opt']['is_require']=0;
|
472 |
+
$options['Colors']['opt']['price']=0;
|
473 |
+
$options['Colors']['opt']['price_type']='fixed';
|
474 |
+
|
475 |
+
|
476 |
+
$options['Colors']['values'][0]['title']='Red';
|
477 |
+
$options['Colors']['values'][0]['price']=10.00;
|
478 |
+
$options['Colors']['values'][0]['price_type']='fixed';
|
479 |
+
|
480 |
+
$options['Colors']['values'][1]['title']='Green';
|
481 |
+
$options['Colors']['values'][1]['price']=11.00;
|
482 |
+
$options['Colors']['values'][1]['price_type']='fixed';
|
483 |
+
|
484 |
+
$options['Colors']['values'][2]['title']='Blue';
|
485 |
+
$options['Colors']['values'][2]['price']=12.00;
|
486 |
+
$options['Colors']['values'][2]['price_type']='fixed';
|
487 |
+
|
488 |
+
|
489 |
+
$options['Sizes']['opt']['type']='radio';
|
490 |
+
$options['Sizes']['opt']['is_require']=0;
|
491 |
+
$options['Sizes']['opt']['price']=0;
|
492 |
+
$options['Sizes']['opt']['price_type']='fixed';
|
493 |
+
|
494 |
+
$options['Sizes']['values'][0]['title']='L';
|
495 |
+
$options['Sizes']['values'][0]['price']=9.00;
|
496 |
+
$options['Sizes']['values'][0]['price_type']='fixed';
|
497 |
+
|
498 |
+
$options['Sizes']['values'][1]['title']='XL';
|
499 |
+
$options['Sizes']['values'][1]['price']=15.00;
|
500 |
+
$options['Sizes']['values'][1]['price_type']='fixed';
|
501 |
+
|
502 |
+
|
503 |
+
|
504 |
+
/*$options['title'] = array(
|
505 |
+
'title' => 'Colors',
|
506 |
+
'type' => 'radio',
|
507 |
+
'is_require' => 1,
|
508 |
+
'sort_order' => 0,
|
509 |
+
'values' => array()
|
510 |
+
);
|
511 |
+
|
512 |
+
$options['values'][] = array(
|
513 |
+
'title' => 'Red',
|
514 |
+
'price' => 10.00,
|
515 |
+
'price_type' => 'fixed',
|
516 |
+
'sku' => '',
|
517 |
+
'sort_order' => '1'
|
518 |
+
);
|
519 |
+
|
520 |
+
$options['values'][] = array(
|
521 |
+
'title' => 'Green',
|
522 |
+
'price' => 89.00,
|
523 |
+
'price_type' => 'fixed',
|
524 |
+
'sku' => '',
|
525 |
+
'sort_order' => '1'
|
526 |
+
);
|
527 |
+
|
528 |
+
$options['values'][] = array(
|
529 |
+
'title' => 'Blue',
|
530 |
+
'price' => 89.00,
|
531 |
+
'price_type' => 'fixed',
|
532 |
+
'sku' => '',
|
533 |
+
'sort_order' => '1'
|
534 |
+
);
|
535 |
+
*/
|
536 |
+
|
537 |
+
|
538 |
+
|
539 |
+
|
540 |
+
$store = Mage::app()->getStore(Mage_Catalog_Model_Abstract::DEFAULT_STORE_ID);
|
541 |
+
// Save all product attributes under "default" store, no matter whether system is in single or multi-store mode
|
542 |
+
$product->setStoreId($store->getId());
|
543 |
+
// Build array of website ids
|
544 |
+
$websiteIds = array();
|
545 |
+
|
546 |
+
if (Mage::app()->isSingleStoreMode()) {
|
547 |
+
$websites = Mage::app()->getWebsites();
|
548 |
+
foreach($websites as $curWebsite){
|
549 |
+
$websiteIds[] = $curWebsite->getId();
|
550 |
+
}
|
551 |
+
}
|
552 |
+
else {
|
553 |
+
//set to specific website/store
|
554 |
+
$website = Mage::app()->getWebsite();
|
555 |
+
$websiteIds[] = $website->getId();
|
556 |
+
}
|
557 |
+
|
558 |
+
$product->setWebsiteIds($websiteIds);
|
559 |
+
|
560 |
+
$product->setAttributeSetId(Mage::getModel('catalog/product')->getResource()->getEntityType()->getDefaultAttributeSetId());
|
561 |
+
|
562 |
+
//->setAttributeSetId(4)
|
563 |
+
//$product->setStoreId('default')
|
564 |
+
|
565 |
+
$product->setTypeId('simple')
|
566 |
+
->setName($data['name'])
|
567 |
+
->setDescription($data['desc'])
|
568 |
+
->setShortDescription($data['shortdesc'])
|
569 |
+
->setSku($data['sku'])
|
570 |
+
->setWeight($data['weight'])
|
571 |
+
->setStatus($data['status'])
|
572 |
+
//->setVisibility(4)
|
573 |
+
->setPrice($data['price'])
|
574 |
+
->addImageToMediaGallery($serverurl,array('thumbnail','small_image','image'),false,false)
|
575 |
+
->setTaxClassId(0)
|
576 |
+
->setStockData($stockData)
|
577 |
+
->setCategoryIds('3')
|
578 |
+
//->setHasOptions(1)
|
579 |
+
//->setProductOptions(array($opt))
|
580 |
+
//->setCanSaveCustomOptions(true)
|
581 |
+
//->setPageLayout('one_column')
|
582 |
+
->setVisibility(Mage_Catalog_Model_Product_Visibility::VISIBILITY_BOTH)
|
583 |
+
->setCreatedAt(strtotime('now'))
|
584 |
+
->setcustomproducttype($data['designed'])
|
585 |
+
->setcustomperspective($data['persp']);
|
586 |
+
|
587 |
+
Mage::dispatchEvent('catalog_product_prepare_save',array('product' => $product, 'request' => null));
|
588 |
+
Mage::log("setup product");
|
589 |
+
|
590 |
+
$product->save();
|
591 |
+
$product_id = $product->getId();
|
592 |
+
|
593 |
+
//echo 'OK Product ID: '.$product->getId();
|
594 |
+
|
595 |
+
foreach($options as $title=>$v){
|
596 |
+
$this->setMyCustomOption($product_id,$title,$optionData=$v['opt'],$values = $v['values']);
|
597 |
+
}
|
598 |
+
|
599 |
+
$cache = Mage::getSingleton('core/cache');
|
600 |
+
$cache->flush();
|
601 |
+
|
602 |
+
return $product->getId();
|
603 |
+
}
|
604 |
+
catch (Mage_Core_Exception $e) {
|
605 |
+
echo $e->getMessage();
|
606 |
+
}
|
607 |
+
catch (Exception $e) {
|
608 |
+
echo $e;
|
609 |
+
}
|
610 |
+
|
611 |
+
|
612 |
+
|
613 |
+
}
|
614 |
+
|
615 |
+
|
616 |
+
}
|
617 |
+
?>
|
app/code/community/Blog4mail/Customproduct/etc/config.xml
ADDED
@@ -0,0 +1,72 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Blog4mail_Customproduct>
|
5 |
+
<version>1.0.0</version>
|
6 |
+
</Blog4mail_Customproduct>
|
7 |
+
</modules>
|
8 |
+
<frontend>
|
9 |
+
<routers>
|
10 |
+
<customproduct>
|
11 |
+
<use>standard</use>
|
12 |
+
<args>
|
13 |
+
<module>Blog4mail_Customproduct</module>
|
14 |
+
<frontName>customproduct</frontName>
|
15 |
+
</args>
|
16 |
+
</customproduct>
|
17 |
+
</routers>
|
18 |
+
<layout>
|
19 |
+
<updates>
|
20 |
+
<catalog>
|
21 |
+
<file>customproduct_catalog.xml</file>
|
22 |
+
</catalog>
|
23 |
+
</updates>
|
24 |
+
</layout>
|
25 |
+
</frontend>
|
26 |
+
<global>
|
27 |
+
<models>
|
28 |
+
<customproduct>
|
29 |
+
<class>Blog4mail_Customproduct_Model</class>
|
30 |
+
<resourceModel>customproduct_mysql4</resourceModel>
|
31 |
+
</customproduct>
|
32 |
+
<customproduct_mysql4>
|
33 |
+
<class>Blog4mail_Customproduct_Model_Mysql4</class>
|
34 |
+
<entities>
|
35 |
+
<customproduct>
|
36 |
+
<table>customproduct</table>
|
37 |
+
</customproduct>
|
38 |
+
</entities>
|
39 |
+
</customproduct_mysql4>
|
40 |
+
</models>
|
41 |
+
<resources>
|
42 |
+
<customproduct_setup>
|
43 |
+
<setup>
|
44 |
+
<module>Blog4mail_Customproduct</module>
|
45 |
+
</setup>
|
46 |
+
<connection>
|
47 |
+
<use>core_setup</use>
|
48 |
+
</connection>
|
49 |
+
</customproduct_setup>
|
50 |
+
<customproduct_write>
|
51 |
+
<connection>
|
52 |
+
<use>core_write</use>
|
53 |
+
</connection>
|
54 |
+
</customproduct_write>
|
55 |
+
<customproduct_read>
|
56 |
+
<connection>
|
57 |
+
<use>core_read</use>
|
58 |
+
</connection>
|
59 |
+
</customproduct_read>
|
60 |
+
</resources>
|
61 |
+
<blocks>
|
62 |
+
<customproduct>
|
63 |
+
<class>Blog4mail_Customproduct_Block</class>
|
64 |
+
</customproduct>
|
65 |
+
</blocks>
|
66 |
+
<helpers>
|
67 |
+
<customproduct>
|
68 |
+
<class>Blog4mail_Customproduct_Helper</class>
|
69 |
+
</customproduct>
|
70 |
+
</helpers>
|
71 |
+
</global>
|
72 |
+
</config>
|
app/code/community/Blog4mail/Customproduct/etc/config.xml~
ADDED
@@ -0,0 +1,72 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Blog4mail_Customproduct>
|
5 |
+
<version>1.0.0</version>
|
6 |
+
</Blog4mail_Customproduct>
|
7 |
+
</modules>
|
8 |
+
<frontend>
|
9 |
+
<routers>
|
10 |
+
<customproduct>
|
11 |
+
<use>standard</use>
|
12 |
+
<args>
|
13 |
+
<module>Blog4mail_Customproduct</module>
|
14 |
+
<frontName>customproduct</frontName>
|
15 |
+
</args>
|
16 |
+
</customproduct>
|
17 |
+
</routers>
|
18 |
+
<layout>
|
19 |
+
<updates>
|
20 |
+
<catalog>
|
21 |
+
<file>customproduct_catalog.xml</file>
|
22 |
+
</catalog>
|
23 |
+
</updates>
|
24 |
+
</layout>
|
25 |
+
</frontend>
|
26 |
+
<global>
|
27 |
+
<models>
|
28 |
+
<customproduct>
|
29 |
+
<class>Blog4mail_Customproduct_Model</class>
|
30 |
+
<resourceModel>customproduct_mysql4</resourceModel>
|
31 |
+
</customproduct>
|
32 |
+
<customproduct_mysql4>
|
33 |
+
<class>Blog4mail_Customproduct_Model_Mysql4</class>
|
34 |
+
<entities>
|
35 |
+
<customproduct>
|
36 |
+
<table>customproduct</table>
|
37 |
+
</customproduct>
|
38 |
+
</entities>
|
39 |
+
</customproduct_mysql4>
|
40 |
+
</models>
|
41 |
+
<resources>
|
42 |
+
<customproduct_setup>
|
43 |
+
<setup>
|
44 |
+
<module>Blog4mail_Customproduct</module>
|
45 |
+
</setup>
|
46 |
+
<connection>
|
47 |
+
<use>core_setup</use>
|
48 |
+
</connection>
|
49 |
+
</customproduct_setup>
|
50 |
+
<customproduct_write>
|
51 |
+
<connection>
|
52 |
+
<use>core_write</use>
|
53 |
+
</connection>
|
54 |
+
</customproduct_write>
|
55 |
+
<customproduct_read>
|
56 |
+
<connection>
|
57 |
+
<use>core_read</use>
|
58 |
+
</connection>
|
59 |
+
</customproduct_read>
|
60 |
+
</resources>
|
61 |
+
<blocks>
|
62 |
+
<customproduct>
|
63 |
+
<class>Blog4mail_Customproduct_Block</class>
|
64 |
+
</customproduct>
|
65 |
+
</blocks>
|
66 |
+
<helpers>
|
67 |
+
<customproduct>
|
68 |
+
<class>Blog4mail_Customproduct_Helper</class>
|
69 |
+
</customproduct>
|
70 |
+
</helpers>
|
71 |
+
</global>
|
72 |
+
</config>
|
app/code/community/Blog4mail/Customproduct/sql/customproduct_setup/mysql4-install-1.0.0.php
ADDED
@@ -0,0 +1,52 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Mashon Sync Update for Dabble Attributes
|
4 |
+
*
|
5 |
+
* @category Mashon
|
6 |
+
* @package Mashon_Sync
|
7 |
+
* @copyright Mashon
|
8 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
9 |
+
*/
|
10 |
+
$installer = $this;
|
11 |
+
$installer->startSetup();
|
12 |
+
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Create the editable attribute in the General Attribute Group
|
16 |
+
* This determines which Pre-designed products (Magento attribute productType = designed) can be loaded and further edited in Dabble
|
17 |
+
*/
|
18 |
+
$code = 'customperspective';
|
19 |
+
|
20 |
+
$attr = array(
|
21 |
+
'entity_type_id' => 'catalog_product',
|
22 |
+
'backend_type' => 'varchar',
|
23 |
+
'is_user_defined' => 1,
|
24 |
+
'frontend_input' => 'text',
|
25 |
+
'is_visible' => 0,
|
26 |
+
'label' => 'Custom Perspective',
|
27 |
+
'required' => 0,
|
28 |
+
'user_defined' => 1,
|
29 |
+
'group' => 'General',
|
30 |
+
);
|
31 |
+
|
32 |
+
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
|
33 |
+
$setup->addAttribute('catalog_product', $code, $attr);
|
34 |
+
|
35 |
+
$code1 = 'customproducttype';
|
36 |
+
|
37 |
+
$attr1 = array(
|
38 |
+
'entity_type_id' => 'catalog_product',
|
39 |
+
'backend_type' => 'varchar',
|
40 |
+
'is_user_defined' => 1,
|
41 |
+
'frontend_input' => 'text',
|
42 |
+
'is_visible' => 0,
|
43 |
+
'label' => 'Custom Product Type',
|
44 |
+
'required' => 0,
|
45 |
+
'user_defined' => 1,
|
46 |
+
'group' => 'General',
|
47 |
+
);
|
48 |
+
|
49 |
+
$setup1 = new Mage_Eav_Model_Entity_Setup('core_setup');
|
50 |
+
$setup1->addAttribute('catalog_product', $code1, $attr1);
|
51 |
+
|
52 |
+
$installer->endSetup();
|
app/code/community/Blog4mail/Customproduct/sql/customproduct_setup/mysql4-install-1.0.0.php~
ADDED
@@ -0,0 +1,52 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Mashon Sync Update for Dabble Attributes
|
4 |
+
*
|
5 |
+
* @category Mashon
|
6 |
+
* @package Mashon_Sync
|
7 |
+
* @copyright Mashon
|
8 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
9 |
+
*/
|
10 |
+
$installer = $this;
|
11 |
+
$installer->startSetup();
|
12 |
+
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Create the editable attribute in the General Attribute Group
|
16 |
+
* This determines which Pre-designed products (Magento attribute productType = designed) can be loaded and further edited in Dabble
|
17 |
+
*/
|
18 |
+
$code = 'customperspective';
|
19 |
+
|
20 |
+
$attr = array(
|
21 |
+
'entity_type_id' => 'catalog_product',
|
22 |
+
'backend_type' => 'varchar',
|
23 |
+
'is_user_defined' => 1,
|
24 |
+
'frontend_input' => 'text',
|
25 |
+
'is_visible' => 0,
|
26 |
+
'label' => 'Custom Perspective',
|
27 |
+
'required' => 0,
|
28 |
+
'user_defined' => 1,
|
29 |
+
'group' => 'General',
|
30 |
+
);
|
31 |
+
|
32 |
+
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
|
33 |
+
$setup->addAttribute('catalog_product', $code, $attr);
|
34 |
+
|
35 |
+
$code1 = 'customproducttype';
|
36 |
+
|
37 |
+
$attr1 = array(
|
38 |
+
'entity_type_id' => 'catalog_product',
|
39 |
+
'backend_type' => 'varchar',
|
40 |
+
'is_user_defined' => 1,
|
41 |
+
'frontend_input' => 'text',
|
42 |
+
'is_visible' => 0,
|
43 |
+
'label' => 'Custom Product Type',
|
44 |
+
'required' => 0,
|
45 |
+
'user_defined' => 1,
|
46 |
+
'group' => 'General',
|
47 |
+
);
|
48 |
+
|
49 |
+
$setup1 = new Mage_Eav_Model_Entity_Setup('core_setup');
|
50 |
+
$setup1->addAttribute('catalog_product', $code1, $attr1);
|
51 |
+
|
52 |
+
$installer->endSetup();
|
app/code/community/Blog4mail/Customproduct/sql/customproduct_setup/mysql4-install-1.0.php~
ADDED
@@ -0,0 +1,52 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Mashon Sync Update for Dabble Attributes
|
4 |
+
*
|
5 |
+
* @category Mashon
|
6 |
+
* @package Mashon_Sync
|
7 |
+
* @copyright Mashon
|
8 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
9 |
+
*/
|
10 |
+
$installer = $this;
|
11 |
+
$installer->startSetup();
|
12 |
+
|
13 |
+
|
14 |
+
/**
|
15 |
+
* Create the editable attribute in the General Attribute Group
|
16 |
+
* This determines which Pre-designed products (Magento attribute productType = designed) can be loaded and further edited in Dabble
|
17 |
+
*/
|
18 |
+
$code = 'customperspective';
|
19 |
+
|
20 |
+
$attr = array(
|
21 |
+
'entity_type_id' => 'catalog_product',
|
22 |
+
'backend_type' => 'varchar',
|
23 |
+
'is_user_defined' => 1,
|
24 |
+
'frontend_input' => 'text',
|
25 |
+
'is_visible' => 0,
|
26 |
+
'label' => 'Custom Perspective',
|
27 |
+
'required' => 0,
|
28 |
+
'user_defined' => 1,
|
29 |
+
'group' => 'General',
|
30 |
+
);
|
31 |
+
|
32 |
+
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
|
33 |
+
$installer->addAttribute('catalog_product', $code, $attr);
|
34 |
+
|
35 |
+
$code1 = 'customproducttype';
|
36 |
+
|
37 |
+
$attr1 = array(
|
38 |
+
'entity_type_id' => 'catalog_product',
|
39 |
+
'backend_type' => 'varchar',
|
40 |
+
'is_user_defined' => 1,
|
41 |
+
'frontend_input' => 'text',
|
42 |
+
'is_visible' => 0,
|
43 |
+
'label' => 'Custom Product Type',
|
44 |
+
'required' => 0,
|
45 |
+
'user_defined' => 1,
|
46 |
+
'group' => 'General',
|
47 |
+
);
|
48 |
+
|
49 |
+
$setup1 = new Mage_Eav_Model_Entity_Setup('core_setup');
|
50 |
+
$installer->addAttribute('catalog_product', $code, $attr);
|
51 |
+
|
52 |
+
$installer->endSetup();
|
app/code/community/Blog4mail/Customproduct/sql/customproduct_setup/mysql4-upgrade-1.0-1.1.php~
ADDED
@@ -0,0 +1,27 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
$this->startSetup();
|
3 |
+
|
4 |
+
|
5 |
+
/**
|
6 |
+
* Create The productType attribute in the General Attribute Group
|
7 |
+
* This determines what to display on the Product View.phtml and is also needed for Dabble Order Processor
|
8 |
+
*/
|
9 |
+
$code = 'customproducttype';
|
10 |
+
|
11 |
+
$attr = array(
|
12 |
+
'entity_type_id' => 'catalog_product',
|
13 |
+
'backend_type' => 'varchar',
|
14 |
+
'is_user_defined' => 1,
|
15 |
+
'frontend_input' => 'text',
|
16 |
+
'is_visible' => 0,
|
17 |
+
'label' => 'Custom Product Type',
|
18 |
+
'required' => 0,
|
19 |
+
'user_defined' => 1,
|
20 |
+
'group' => 'General',
|
21 |
+
);
|
22 |
+
|
23 |
+
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
|
24 |
+
$setup->addAttribute('catalog_product', $code, $attr);
|
25 |
+
|
26 |
+
|
27 |
+
$this->endSetup();
|
app/code/community/Blog4mail/Customproduct/sql/customproduct_setup/mysql4-upgrade-1.3.4-1.4.php~
ADDED
@@ -0,0 +1,34 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
/**
|
3 |
+
* Mashon Sync Update for Dabble Attributes
|
4 |
+
*
|
5 |
+
* @category Mashon
|
6 |
+
* @package Mashon_Sync
|
7 |
+
* @copyright Mashon
|
8 |
+
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
|
9 |
+
*/
|
10 |
+
$this->startSetup();
|
11 |
+
|
12 |
+
|
13 |
+
/**
|
14 |
+
* Create the editable attribute in the General Attribute Group
|
15 |
+
* This determines which Pre-designed products (Magento attribute productType = designed) can be loaded and further edited in Dabble
|
16 |
+
*/
|
17 |
+
$code = 'customperspective';
|
18 |
+
|
19 |
+
$attr = array(
|
20 |
+
'entity_type_id' => 'catalog_product',
|
21 |
+
'backend_type' => 'varchar',
|
22 |
+
'is_user_defined' => 1,
|
23 |
+
'frontend_input' => 'text',
|
24 |
+
'is_visible' => 0,
|
25 |
+
'label' => 'Custom Perspective',
|
26 |
+
'required' => 0,
|
27 |
+
'user_defined' => 1,
|
28 |
+
'group' => 'General',
|
29 |
+
);
|
30 |
+
|
31 |
+
$setup = new Mage_Eav_Model_Entity_Setup('core_setup');
|
32 |
+
$setup->addAttribute('catalog_product', $code, $attr);
|
33 |
+
|
34 |
+
$this->endSetup();
|
app/code/community/Blog4mail/Customproductadmin/Block/Customproduct.php
ADDED
@@ -0,0 +1,12 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
class Blog4mail_Customproductadmin_Block_Adminhtml_Customproduct extends Mage_Adminhtml_Block_Widget_Grid_Container
|
3 |
+
{
|
4 |
+
public function __construct()
|
5 |
+
{
|
6 |
+
$this->_controller = 'customproductadmin';
|
7 |
+
$this->_blockGroup = 'customproductadmin';
|
8 |
+
$this->_headerText = Mage::helper('customproductadmin')->__('Item Manager');
|
9 |
+
$this->_addButtonLabel = Mage::helper('customproductadmin')->__('Add Item');
|
10 |
+
parent::__construct();
|
11 |
+
}
|
12 |
+
}
|
app/code/community/Blog4mail/Customproductadmin/Block/Customproduct/Edit.php
ADDED
@@ -0,0 +1,45 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Blog4mail_Customproductadmin_Block_Customproduct_Edit extends Mage_Adminhtml_Block_Widget_Form_Container
|
4 |
+
{
|
5 |
+
public function __construct()
|
6 |
+
{
|
7 |
+
parent::__construct();
|
8 |
+
|
9 |
+
$this->_objectId = 'id';
|
10 |
+
$this->_blockGroup = 'customproductadmin';
|
11 |
+
$this->_controller = 'customproductadmin';
|
12 |
+
|
13 |
+
$this->_updateButton('save', 'label', Mage::helper('customproduct')->__('Save Item'));
|
14 |
+
$this->_updateButton('delete', 'label', Mage::helper('customproduct')->__('Delete Item'));
|
15 |
+
|
16 |
+
$this->_addButton('saveandcontinue', array(
|
17 |
+
'label' => Mage::helper('adminhtml')->__('Save And Continue Edit'),
|
18 |
+
'onclick' => 'saveAndContinueEdit()',
|
19 |
+
'class' => 'save',
|
20 |
+
), -100);
|
21 |
+
|
22 |
+
$this->_formScripts[] = "
|
23 |
+
function toggleEditor() {
|
24 |
+
if (tinyMCE.getInstanceById('customproduct_content') == null) {
|
25 |
+
tinyMCE.execCommand('mceAddControl', false, 'customproduct_content');
|
26 |
+
} else {
|
27 |
+
tinyMCE.execCommand('mceRemoveControl', false, 'customproduct_content');
|
28 |
+
}
|
29 |
+
}
|
30 |
+
|
31 |
+
function saveAndContinueEdit(){
|
32 |
+
editForm.submit($('edit_form').action+'back/edit/');
|
33 |
+
}
|
34 |
+
";
|
35 |
+
}
|
36 |
+
|
37 |
+
public function getHeaderText()
|
38 |
+
{
|
39 |
+
if( Mage::registry('customproduct_data') && Mage::registry('customproduct_data')->getId() ) {
|
40 |
+
return Mage::helper('customproduct')->__("Edit Item '%s'", $this->htmlEscape(Mage::registry('customproduct_data')->getTitle()));
|
41 |
+
} else {
|
42 |
+
return Mage::helper('customproduct')->__('Add Item');
|
43 |
+
}
|
44 |
+
}
|
45 |
+
}
|
app/code/community/Blog4mail/Customproductadmin/Block/Customproduct/Edit/Form.php
ADDED
@@ -0,0 +1,19 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Blog4mail_Customproductadmin_Block_Customproduct_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
|
4 |
+
{
|
5 |
+
protected function _prepareForm()
|
6 |
+
{
|
7 |
+
$form = new Varien_Data_Form(array(
|
8 |
+
'id' => 'edit_form',
|
9 |
+
'action' => $this->getUrl('*/*/save', array('id' => $this->getRequest()->getParam('id'))),
|
10 |
+
'method' => 'post',
|
11 |
+
'enctype' => 'multipart/form-data'
|
12 |
+
)
|
13 |
+
);
|
14 |
+
|
15 |
+
$form->setUseContainer(true);
|
16 |
+
$this->setForm($form);
|
17 |
+
return parent::_prepareForm();
|
18 |
+
}
|
19 |
+
}
|
app/code/community/Blog4mail/Customproductadmin/Block/Customproduct/Edit/Tab/Form.php
ADDED
@@ -0,0 +1,58 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Blog4mail_Customproductadmin_Block_Customproduct_Edit_Tab_Form extends Mage_Adminhtml_Block_Widget_Form
|
4 |
+
{
|
5 |
+
protected function _prepareForm()
|
6 |
+
{
|
7 |
+
$form = new Varien_Data_Form();
|
8 |
+
$this->setForm($form);
|
9 |
+
$fieldset = $form->addFieldset('customproduct_form', array('legend'=>Mage::helper('customproduct')->__('Item information')));
|
10 |
+
|
11 |
+
$fieldset->addField('title', 'text', array(
|
12 |
+
'label' => Mage::helper('customproduct')->__('Title'),
|
13 |
+
'class' => 'required-entry',
|
14 |
+
'required' => true,
|
15 |
+
'name' => 'title',
|
16 |
+
));
|
17 |
+
|
18 |
+
$fieldset->addField('filename', 'file', array(
|
19 |
+
'label' => Mage::helper('customproduct')->__('File'),
|
20 |
+
'required' => false,
|
21 |
+
'name' => 'filename',
|
22 |
+
));
|
23 |
+
|
24 |
+
$fieldset->addField('status', 'select', array(
|
25 |
+
'label' => Mage::helper('customproduct')->__('Status'),
|
26 |
+
'name' => 'status',
|
27 |
+
'values' => array(
|
28 |
+
array(
|
29 |
+
'value' => 1,
|
30 |
+
'label' => Mage::helper('customproduct')->__('Enabled'),
|
31 |
+
),
|
32 |
+
|
33 |
+
array(
|
34 |
+
'value' => 2,
|
35 |
+
'label' => Mage::helper('customproduct')->__('Disabled'),
|
36 |
+
),
|
37 |
+
),
|
38 |
+
));
|
39 |
+
|
40 |
+
$fieldset->addField('content', 'editor', array(
|
41 |
+
'name' => 'content',
|
42 |
+
'label' => Mage::helper('customproduct')->__('Content'),
|
43 |
+
'title' => Mage::helper('customproduct')->__('Content'),
|
44 |
+
'style' => 'width:700px; height:500px;',
|
45 |
+
'wysiwyg' => false,
|
46 |
+
'required' => true,
|
47 |
+
));
|
48 |
+
|
49 |
+
if ( Mage::getSingleton('adminhtml/session')->getCustomproductData() )
|
50 |
+
{
|
51 |
+
$form->setValues(Mage::getSingleton('adminhtml/session')->getCustomproductData());
|
52 |
+
Mage::getSingleton('adminhtml/session')->setCustomproductData(null);
|
53 |
+
} elseif ( Mage::registry('customproduct_data') ) {
|
54 |
+
$form->setValues(Mage::registry('customproduct_data')->getData());
|
55 |
+
}
|
56 |
+
return parent::_prepareForm();
|
57 |
+
}
|
58 |
+
}
|
app/code/community/Blog4mail/Customproductadmin/Block/Customproduct/Edit/Tabs.php
ADDED
@@ -0,0 +1,24 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Blog4mail_Customproductadmin_Block_Customproduct_Edit_Tabs extends Mage_Adminhtml_Block_Widget_Tabs
|
4 |
+
{
|
5 |
+
|
6 |
+
public function __construct()
|
7 |
+
{
|
8 |
+
parent::__construct();
|
9 |
+
$this->setId('customproductadmin_tabs');
|
10 |
+
$this->setDestElementId('edit_form');
|
11 |
+
$this->setTitle(Mage::helper('customproduct')->__('Item Information'));
|
12 |
+
}
|
13 |
+
|
14 |
+
protected function _beforeToHtml()
|
15 |
+
{
|
16 |
+
$this->addTab('form_section', array(
|
17 |
+
'label' => Mage::helper('customproduct')->__('Item Information'),
|
18 |
+
'title' => Mage::helper('customproduct')->__('Item Information'),
|
19 |
+
'content' => $this->getLayout()->createBlock('customproduct/adminhtml_customproduct_edit_tab_form')->toHtml(),
|
20 |
+
));
|
21 |
+
|
22 |
+
return parent::_beforeToHtml();
|
23 |
+
}
|
24 |
+
}
|
app/code/community/Blog4mail/Customproductadmin/Block/Customproduct/Grid.php
ADDED
@@ -0,0 +1,116 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Blog4mail_Customproductadmin_Block_Customproduct_Grid extends Mage_Adminhtml_Block_Widget_Grid
|
4 |
+
{
|
5 |
+
public function __construct()
|
6 |
+
{
|
7 |
+
parent::__construct();
|
8 |
+
$this->setId('customproductadminGrid');
|
9 |
+
$this->setDefaultSort('customproduct_id');
|
10 |
+
$this->setDefaultDir('ASC');
|
11 |
+
$this->setSaveParametersInSession(true);
|
12 |
+
}
|
13 |
+
|
14 |
+
protected function _prepareCollection()
|
15 |
+
{
|
16 |
+
$collection = Mage::getModel('customproduct/customproduct')->getCollection();
|
17 |
+
$this->setCollection($collection);
|
18 |
+
return parent::_prepareCollection();
|
19 |
+
}
|
20 |
+
|
21 |
+
protected function _prepareColumns()
|
22 |
+
{
|
23 |
+
$this->addColumn('customproduct_id', array(
|
24 |
+
'header' => Mage::helper('customproduct')->__('ID'),
|
25 |
+
'align' =>'right',
|
26 |
+
'width' => '50px',
|
27 |
+
'index' => 'customproduct_id',
|
28 |
+
));
|
29 |
+
|
30 |
+
$this->addColumn('title', array(
|
31 |
+
'header' => Mage::helper('customproduct')->__('Title'),
|
32 |
+
'align' =>'left',
|
33 |
+
'index' => 'title',
|
34 |
+
));
|
35 |
+
|
36 |
+
/*
|
37 |
+
$this->addColumn('content', array(
|
38 |
+
'header' => Mage::helper('customproduct')->__('Item Content'),
|
39 |
+
'width' => '150px',
|
40 |
+
'index' => 'content',
|
41 |
+
));
|
42 |
+
*/
|
43 |
+
|
44 |
+
$this->addColumn('status', array(
|
45 |
+
'header' => Mage::helper('customproduct')->__('Status'),
|
46 |
+
'align' => 'left',
|
47 |
+
'width' => '80px',
|
48 |
+
'index' => 'status',
|
49 |
+
'type' => 'options',
|
50 |
+
'options' => array(
|
51 |
+
1 => 'Enabled',
|
52 |
+
2 => 'Disabled',
|
53 |
+
),
|
54 |
+
));
|
55 |
+
|
56 |
+
$this->addColumn('action',
|
57 |
+
array(
|
58 |
+
'header' => Mage::helper('customproduct')->__('Action'),
|
59 |
+
'width' => '100',
|
60 |
+
'type' => 'action',
|
61 |
+
'getter' => 'getId',
|
62 |
+
'actions' => array(
|
63 |
+
array(
|
64 |
+
'caption' => Mage::helper('customproduct')->__('Edit'),
|
65 |
+
'url' => array('base'=> '*/*/edit'),
|
66 |
+
'field' => 'id'
|
67 |
+
)
|
68 |
+
),
|
69 |
+
'filter' => false,
|
70 |
+
'sortable' => false,
|
71 |
+
'index' => 'stores',
|
72 |
+
'is_system' => true,
|
73 |
+
));
|
74 |
+
|
75 |
+
$this->addExportType('*/*/exportCsv', Mage::helper('customproduct')->__('CSV'));
|
76 |
+
$this->addExportType('*/*/exportXml', Mage::helper('customproduct')->__('XML'));
|
77 |
+
|
78 |
+
return parent::_prepareColumns();
|
79 |
+
}
|
80 |
+
|
81 |
+
protected function _prepareMassaction()
|
82 |
+
{
|
83 |
+
$this->setMassactionIdField('customproduct_id');
|
84 |
+
$this->getMassactionBlock()->setFormFieldName('customproduct');
|
85 |
+
|
86 |
+
$this->getMassactionBlock()->addItem('delete', array(
|
87 |
+
'label' => Mage::helper('customproduct')->__('Delete'),
|
88 |
+
'url' => $this->getUrl('*/*/massDelete'),
|
89 |
+
'confirm' => Mage::helper('customproduct')->__('Are you sure?')
|
90 |
+
));
|
91 |
+
|
92 |
+
$statuses = Mage::getSingleton('customproduct/status')->getOptionArray();
|
93 |
+
|
94 |
+
array_unshift($statuses, array('label'=>'', 'value'=>''));
|
95 |
+
$this->getMassactionBlock()->addItem('status', array(
|
96 |
+
'label'=> Mage::helper('customproduct')->__('Change status'),
|
97 |
+
'url' => $this->getUrl('*/*/massStatus', array('_current'=>true)),
|
98 |
+
'additional' => array(
|
99 |
+
'visibility' => array(
|
100 |
+
'name' => 'status',
|
101 |
+
'type' => 'select',
|
102 |
+
'class' => 'required-entry',
|
103 |
+
'label' => Mage::helper('customproduct')->__('Status'),
|
104 |
+
'values' => $statuses
|
105 |
+
)
|
106 |
+
)
|
107 |
+
));
|
108 |
+
return $this;
|
109 |
+
}
|
110 |
+
|
111 |
+
public function getRowUrl($row)
|
112 |
+
{
|
113 |
+
return $this->getUrl('*/*/edit', array('id' => $row->getId()));
|
114 |
+
}
|
115 |
+
|
116 |
+
}
|
app/code/community/Blog4mail/Customproductadmin/Helper/Data.php
ADDED
@@ -0,0 +1,6 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Blog4mail_Customproductadmin_Helper_Data extends Mage_Core_Helper_Abstract
|
4 |
+
{
|
5 |
+
|
6 |
+
}
|
app/code/community/Blog4mail/Customproductadmin/controllers/CustomproductController.php
ADDED
@@ -0,0 +1,214 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
|
3 |
+
class Blog4mail_Customproductadmin_CustomproductController extends Mage_Adminhtml_Controller_action
|
4 |
+
{
|
5 |
+
|
6 |
+
protected function _initAction() {
|
7 |
+
$this->loadLayout()
|
8 |
+
->_setActiveMenu('customproductadmin/items')
|
9 |
+
->_addBreadcrumb(Mage::helper('adminhtml')->__('Items Manager'), Mage::helper('adminhtml')->__('Item Manager'));
|
10 |
+
|
11 |
+
return $this;
|
12 |
+
}
|
13 |
+
|
14 |
+
public function indexAction() {
|
15 |
+
$this->_initAction()
|
16 |
+
->renderLayout();
|
17 |
+
}
|
18 |
+
|
19 |
+
public function editAction() {
|
20 |
+
$id = $this->getRequest()->getParam('id');
|
21 |
+
$model = Mage::getModel('customproduct/customproduct')->load($id);
|
22 |
+
|
23 |
+
if ($model->getId() || $id == 0) {
|
24 |
+
$data = Mage::getSingleton('adminhtml/session')->getFormData(true);
|
25 |
+
if (!empty($data)) {
|
26 |
+
$model->setData($data);
|
27 |
+
}
|
28 |
+
|
29 |
+
Mage::register('customproduct_data', $model);
|
30 |
+
|
31 |
+
$this->loadLayout();
|
32 |
+
$this->_setActiveMenu('customproduct/items');
|
33 |
+
|
34 |
+
$this->_addBreadcrumb(Mage::helper('adminhtml')->__('Item Manager'), Mage::helper('adminhtml')->__('Item Manager'));
|
35 |
+
$this->_addBreadcrumb(Mage::helper('adminhtml')->__('Item News'), Mage::helper('adminhtml')->__('Item News'));
|
36 |
+
|
37 |
+
$this->getLayout()->getBlock('head')->setCanLoadExtJs(true);
|
38 |
+
|
39 |
+
$this->_addContent($this->getLayout()->createBlock('customproduct/adminhtml_customproduct_edit'))
|
40 |
+
->_addLeft($this->getLayout()->createBlock('customproduct/adminhtml_customproduct_edit_tabs'));
|
41 |
+
|
42 |
+
$this->renderLayout();
|
43 |
+
} else {
|
44 |
+
Mage::getSingleton('adminhtml/session')->addError(Mage::helper('customproduct')->__('Item does not exist'));
|
45 |
+
$this->_redirect('*/*/');
|
46 |
+
}
|
47 |
+
}
|
48 |
+
|
49 |
+
public function newAction() {
|
50 |
+
$this->_forward('edit');
|
51 |
+
}
|
52 |
+
|
53 |
+
public function saveAction() {
|
54 |
+
if ($data = $this->getRequest()->getPost()) {
|
55 |
+
|
56 |
+
if(isset($_FILES['filename']['name']) && $_FILES['filename']['name'] != '') {
|
57 |
+
try {
|
58 |
+
/* Starting upload */
|
59 |
+
$uploader = new Varien_File_Uploader('filename');
|
60 |
+
|
61 |
+
// Any extention would work
|
62 |
+
$uploader->setAllowedExtensions(array('jpg','jpeg','gif','png'));
|
63 |
+
$uploader->setAllowRenameFiles(false);
|
64 |
+
|
65 |
+
// Set the file upload mode
|
66 |
+
// false -> get the file directly in the specified folder
|
67 |
+
// true -> get the file in the product like folders
|
68 |
+
// (file.jpg will go in something like /media/f/i/file.jpg)
|
69 |
+
$uploader->setFilesDispersion(false);
|
70 |
+
|
71 |
+
// We set media as the upload dir
|
72 |
+
$path = Mage::getBaseDir('media') . DS ;
|
73 |
+
$uploader->save($path, $_FILES['filename']['name'] );
|
74 |
+
|
75 |
+
} catch (Exception $e) {
|
76 |
+
|
77 |
+
}
|
78 |
+
|
79 |
+
//this way the name is saved in DB
|
80 |
+
$data['filename'] = $_FILES['filename']['name'];
|
81 |
+
}
|
82 |
+
|
83 |
+
|
84 |
+
$model = Mage::getModel('customproduct/customproduct');
|
85 |
+
$model->setData($data)
|
86 |
+
->setId($this->getRequest()->getParam('id'));
|
87 |
+
|
88 |
+
try {
|
89 |
+
if ($model->getCreatedTime == NULL || $model->getUpdateTime() == NULL) {
|
90 |
+
$model->setCreatedTime(now())
|
91 |
+
->setUpdateTime(now());
|
92 |
+
} else {
|
93 |
+
$model->setUpdateTime(now());
|
94 |
+
}
|
95 |
+
|
96 |
+
$model->save();
|
97 |
+
Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('customproduct')->__('Item was successfully saved'));
|
98 |
+
Mage::getSingleton('adminhtml/session')->setFormData(false);
|
99 |
+
|
100 |
+
if ($this->getRequest()->getParam('back')) {
|
101 |
+
$this->_redirect('*/*/edit', array('id' => $model->getId()));
|
102 |
+
return;
|
103 |
+
}
|
104 |
+
$this->_redirect('*/*/');
|
105 |
+
return;
|
106 |
+
} catch (Exception $e) {
|
107 |
+
Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
|
108 |
+
Mage::getSingleton('adminhtml/session')->setFormData($data);
|
109 |
+
$this->_redirect('*/*/edit', array('id' => $this->getRequest()->getParam('id')));
|
110 |
+
return;
|
111 |
+
}
|
112 |
+
}
|
113 |
+
Mage::getSingleton('adminhtml/session')->addError(Mage::helper('customproduct')->__('Unable to find item to save'));
|
114 |
+
$this->_redirect('*/*/');
|
115 |
+
}
|
116 |
+
|
117 |
+
public function deleteAction() {
|
118 |
+
if( $this->getRequest()->getParam('id') > 0 ) {
|
119 |
+
try {
|
120 |
+
$model = Mage::getModel('customproduct/customproduct');
|
121 |
+
|
122 |
+
$model->setId($this->getRequest()->getParam('id'))
|
123 |
+
->delete();
|
124 |
+
|
125 |
+
Mage::getSingleton('adminhtml/session')->addSuccess(Mage::helper('adminhtml')->__('Item was successfully deleted'));
|
126 |
+
$this->_redirect('*/*/');
|
127 |
+
} catch (Exception $e) {
|
128 |
+
Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
|
129 |
+
$this->_redirect('*/*/edit', array('id' => $this->getRequest()->getParam('id')));
|
130 |
+
}
|
131 |
+
}
|
132 |
+
$this->_redirect('*/*/');
|
133 |
+
}
|
134 |
+
|
135 |
+
public function massDeleteAction() {
|
136 |
+
$customproductIds = $this->getRequest()->getParam('customproduct');
|
137 |
+
if(!is_array($customproductIds)) {
|
138 |
+
Mage::getSingleton('adminhtml/session')->addError(Mage::helper('adminhtml')->__('Please select item(s)'));
|
139 |
+
} else {
|
140 |
+
try {
|
141 |
+
foreach ($customproductIds as $customproductId) {
|
142 |
+
$customproduct = Mage::getModel('customproduct/customproduct')->load($customproductId);
|
143 |
+
$customproduct->delete();
|
144 |
+
}
|
145 |
+
Mage::getSingleton('adminhtml/session')->addSuccess(
|
146 |
+
Mage::helper('adminhtml')->__(
|
147 |
+
'Total of %d record(s) were successfully deleted', count($customproductIds)
|
148 |
+
)
|
149 |
+
);
|
150 |
+
} catch (Exception $e) {
|
151 |
+
Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
|
152 |
+
}
|
153 |
+
}
|
154 |
+
$this->_redirect('*/*/index');
|
155 |
+
}
|
156 |
+
|
157 |
+
public function massStatusAction()
|
158 |
+
{
|
159 |
+
$customproductIds = $this->getRequest()->getParam('customproduct');
|
160 |
+
if(!is_array($customproductIds)) {
|
161 |
+
Mage::getSingleton('adminhtml/session')->addError($this->__('Please select item(s)'));
|
162 |
+
} else {
|
163 |
+
try {
|
164 |
+
foreach ($customproductIds as $customproductId) {
|
165 |
+
$customproduct = Mage::getSingleton('customproduct/customproduct')
|
166 |
+
->load($customproductId)
|
167 |
+
->setStatus($this->getRequest()->getParam('status'))
|
168 |
+
->setIsMassupdate(true)
|
169 |
+
->save();
|
170 |
+
}
|
171 |
+
$this->_getSession()->addSuccess(
|
172 |
+
$this->__('Total of %d record(s) were successfully updated', count($customproductIds))
|
173 |
+
);
|
174 |
+
} catch (Exception $e) {
|
175 |
+
$this->_getSession()->addError($e->getMessage());
|
176 |
+
}
|
177 |
+
}
|
178 |
+
$this->_redirect('*/*/index');
|
179 |
+
}
|
180 |
+
|
181 |
+
public function exportCsvAction()
|
182 |
+
{
|
183 |
+
$fileName = 'customproduct.csv';
|
184 |
+
$content = $this->getLayout()->createBlock('customproduct/adminhtml_customproduct_grid')
|
185 |
+
->getCsv();
|
186 |
+
|
187 |
+
$this->_sendUploadResponse($fileName, $content);
|
188 |
+
}
|
189 |
+
|
190 |
+
public function exportXmlAction()
|
191 |
+
{
|
192 |
+
$fileName = 'customproduct.xml';
|
193 |
+
$content = $this->getLayout()->createBlock('customproduct/adminhtml_customproduct_grid')
|
194 |
+
->getXml();
|
195 |
+
|
196 |
+
$this->_sendUploadResponse($fileName, $content);
|
197 |
+
}
|
198 |
+
|
199 |
+
protected function _sendUploadResponse($fileName, $content, $contentType='application/octet-stream')
|
200 |
+
{
|
201 |
+
$response = $this->getResponse();
|
202 |
+
$response->setHeader('HTTP/1.1 200 OK','');
|
203 |
+
$response->setHeader('Pragma', 'public', true);
|
204 |
+
$response->setHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0', true);
|
205 |
+
$response->setHeader('Content-Disposition', 'attachment; filename='.$fileName);
|
206 |
+
$response->setHeader('Last-Modified', date('r'));
|
207 |
+
$response->setHeader('Accept-Ranges', 'bytes');
|
208 |
+
$response->setHeader('Content-Length', strlen($content));
|
209 |
+
$response->setHeader('Content-type', $contentType);
|
210 |
+
$response->setBody($content);
|
211 |
+
$response->sendResponse();
|
212 |
+
die;
|
213 |
+
}
|
214 |
+
}
|
app/code/community/Blog4mail/Customproductadmin/etc/config.xml
ADDED
@@ -0,0 +1,68 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Blog4mail_Customproductadmin>
|
5 |
+
<version>0.1.0</version>
|
6 |
+
</Blog4mail_Customproductadmin>
|
7 |
+
</modules>
|
8 |
+
<admin>
|
9 |
+
<routers>
|
10 |
+
<customproductadmin>
|
11 |
+
<use>admin</use>
|
12 |
+
<args>
|
13 |
+
<module>Blog4mail_Customproductadmin</module>
|
14 |
+
<frontName>customproductadmin</frontName>
|
15 |
+
</args>
|
16 |
+
</customproductadmin>
|
17 |
+
</routers>
|
18 |
+
</admin>
|
19 |
+
<adminhtml>
|
20 |
+
<menu>
|
21 |
+
<customproductadmin module="customproductadmin">
|
22 |
+
<title>Customproduct</title>
|
23 |
+
<sort_order>71</sort_order>
|
24 |
+
<children>
|
25 |
+
<items module="customproductadmin">
|
26 |
+
<title>Manage Items</title>
|
27 |
+
<sort_order>0</sort_order>
|
28 |
+
<action>customproductadmin/customproduct</action>
|
29 |
+
</items>
|
30 |
+
</children>
|
31 |
+
</customproductadmin>
|
32 |
+
</menu>
|
33 |
+
<acl>
|
34 |
+
<resources>
|
35 |
+
<all>
|
36 |
+
<title>Allow Everything</title>
|
37 |
+
</all>
|
38 |
+
<admin>
|
39 |
+
<children>
|
40 |
+
<Blog4mail_Customproductadmin>
|
41 |
+
<title>Customproduct Module</title>
|
42 |
+
<sort_order>10</sort_order>
|
43 |
+
</Blog4mail_Customproductadmin>
|
44 |
+
</children>
|
45 |
+
</admin>
|
46 |
+
</resources>
|
47 |
+
</acl>
|
48 |
+
<layout>
|
49 |
+
<updates>
|
50 |
+
<customproductadmin>
|
51 |
+
<file>customproductadmin.xml</file>
|
52 |
+
</customproductadmin>
|
53 |
+
</updates>
|
54 |
+
</layout>
|
55 |
+
</adminhtml>
|
56 |
+
<global>
|
57 |
+
<blocks>
|
58 |
+
<customproductadmin>
|
59 |
+
<class>Blog4mail_Customproductadmin_Block</class>
|
60 |
+
</customproductadmin>
|
61 |
+
</blocks>
|
62 |
+
<helpers>
|
63 |
+
<customproductadmin>
|
64 |
+
<class>Blog4mail_Customproductadmin_Helper</class>
|
65 |
+
</customproductadmin>
|
66 |
+
</helpers>
|
67 |
+
</global>
|
68 |
+
</config>
|
app/code/community/Blog4mail/customproduct_catalog.xml~
ADDED
@@ -0,0 +1,93 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<layout version="0.1.0">
|
3 |
+
<catalog_product_view translate="label">
|
4 |
+
<label>Catalog Product View (Any)</label>
|
5 |
+
<!-- Mage_Catalog -->
|
6 |
+
<reference name="root">
|
7 |
+
<action method="setTemplate"><template>page/2columns-right.phtml</template></action>
|
8 |
+
</reference>
|
9 |
+
<reference name="head">
|
10 |
+
<action method="addJs"><script>varien/product.js</script></action>
|
11 |
+
<action method="addJs"><script>varien/configurable.js</script></action>
|
12 |
+
|
13 |
+
<action method="addItem"><type>js_css</type><name>calendar/calendar-win2k-1.css</name><params/><!--<if/><condition>can_load_calendar_js</condition>--></action>
|
14 |
+
<action method="addItem"><type>js</type><name>calendar/calendar.js</name><!--<params/><if/><condition>can_load_calendar_js</condition>--></action>
|
15 |
+
<action method="addItem"><type>js</type><name>calendar/calendar-setup.js</name><!--<params/><if/><condition>can_load_calendar_js</condition>--></action>
|
16 |
+
</reference>
|
17 |
+
<reference name="content">
|
18 |
+
<block type="catalog/product_view" name="product.info" template="catalog/product/view_custom.phtml">
|
19 |
+
<!--
|
20 |
+
<action method="addReviewSummaryTemplate"><type>default</type><template>review/helper/summary.phtml</template></action>
|
21 |
+
<action method="addReviewSummaryTemplate"><type>short</type><template>review/helper/summary_short.phtml</template></action>
|
22 |
+
<action method="addReviewSummaryTemplate"><type>...</type><template>...</template></action>
|
23 |
+
-->
|
24 |
+
<block type="catalog/product_view_media" name="product.info.media" as="media" template="catalog/product/view/media_custom.phtml"/>
|
25 |
+
<block type="core/text_list" name="alert.urls" as="alert_urls" translate="label">
|
26 |
+
<label>Alert Urls</label>
|
27 |
+
</block>
|
28 |
+
|
29 |
+
<action method="setTierPriceTemplate"><template>catalog/product/view/tierprices.phtml</template></action>
|
30 |
+
|
31 |
+
<block type="catalog/product_list_upsell" name="product.info.upsell" as="upsell_products" template="catalog/product/list/upsell.phtml">
|
32 |
+
<action method="setColumnCount"><columns>4</columns></action>
|
33 |
+
<action method="setItemLimit"><type>upsell</type><limit>4</limit></action>
|
34 |
+
</block>
|
35 |
+
|
36 |
+
<block type="catalog/product_view_additional" name="product.info.additional" as="product_additional_data" />
|
37 |
+
<block type="catalog/product_view_description" name="product.description" as="description" template="catalog/product/view/description.phtml">
|
38 |
+
<action method="addToParentGroup"><group>detailed_info</group></action>
|
39 |
+
</block>
|
40 |
+
<block type="catalog/product_view_attributes" name="product.attributes" as="additional" template="catalog/product/view/attributes.phtml">
|
41 |
+
<action method="addToParentGroup"><group>detailed_info</group></action>
|
42 |
+
</block>
|
43 |
+
<block type="catalog/product_view" name="product.info.addto" as="addto" template="catalog/product/view/addto.phtml"/>
|
44 |
+
<block type="catalog/product_view" name="product.info.addtocart" as="addtocart" template="catalog/product/view/addtocart.phtml"/>
|
45 |
+
|
46 |
+
<block type="core/text_list" name="product.info.extrahint" as="extrahint" translate="label">
|
47 |
+
<label>Product View Extra Hint</label>
|
48 |
+
</block>
|
49 |
+
|
50 |
+
<block type="catalog/product_view" name="product.info.options.wrapper" as="product_options_wrapper" template="catalog/product/view/options/wrapper.phtml" translate="label">
|
51 |
+
<label>Info Column Options Wrapper</label>
|
52 |
+
<block type="core/template" name="options_js" template="catalog/product/view/options/js.phtml"/>
|
53 |
+
<block type="catalog/product_view_options" name="product.info.options" as="product_options" template="catalog/product/view/options.phtml">
|
54 |
+
<action method="addOptionRenderer"><type>text</type><block>catalog/product_view_options_type_text</block><template>catalog/product/view/options/type/text.phtml</template></action>
|
55 |
+
<action method="addOptionRenderer"><type>file</type><block>catalog/product_view_options_type_file</block><template>catalog/product/view/options/type/file.phtml</template></action>
|
56 |
+
<action method="addOptionRenderer"><type>select</type><block>catalog/product_view_options_type_select</block><template>catalog/product/view/options/type/select.phtml</template></action>
|
57 |
+
<action method="addOptionRenderer"><type>date</type><block>catalog/product_view_options_type_date</block><template>catalog/product/view/options/type/date.phtml</template></action>
|
58 |
+
</block>
|
59 |
+
<block type="core/html_calendar" name="html_calendar" as="html_calendar" template="page/js/calendar.phtml"/>
|
60 |
+
</block>
|
61 |
+
<block type="catalog/product_view" name="product.info.options.wrapper.bottom" as="product_options_wrapper_bottom" template="catalog/product/view/options/wrapper/bottom.phtml" translate="label">
|
62 |
+
<label>Bottom Block Options Wrapper</label>
|
63 |
+
<action method="insert"><block>product.tierprices</block></action>
|
64 |
+
<block type="catalog/product_view" name="product.clone_prices" as="prices" template="catalog/product/view/price_clone.phtml"/>
|
65 |
+
<action method="append"><block>product.info.addtocart</block></action>
|
66 |
+
<action method="append"><block>product.info.addto</block></action>
|
67 |
+
</block>
|
68 |
+
|
69 |
+
<block type="core/template_facade" name="product.info.container1" as="container1">
|
70 |
+
<action method="setDataByKey"><key>alias_in_layout</key><value>container1</value></action>
|
71 |
+
<action method="setDataByKeyFromRegistry"><key>options_container</key><key_in_registry>product</key_in_registry></action>
|
72 |
+
<action method="append"><block>product.info.options.wrapper</block></action>
|
73 |
+
<action method="append"><block>product.info.options.wrapper.bottom</block></action>
|
74 |
+
</block>
|
75 |
+
<block type="core/template_facade" name="product.info.container2" as="container2">
|
76 |
+
<action method="setDataByKey"><key>alias_in_layout</key><value>container2</value></action>
|
77 |
+
<action method="setDataByKeyFromRegistry"><key>options_container</key><key_in_registry>product</key_in_registry></action>
|
78 |
+
<action method="append"><block>product.info.options.wrapper</block></action>
|
79 |
+
<action method="append"><block>product.info.options.wrapper.bottom</block></action>
|
80 |
+
</block>
|
81 |
+
<action method="unsetCallChild"><child>container1</child><call>ifEquals</call><if>0</if><key>alias_in_layout</key><key>options_container</key></action>
|
82 |
+
<action method="unsetCallChild"><child>container2</child><call>ifEquals</call><if>0</if><key>alias_in_layout</key><key>options_container</key></action>
|
83 |
+
</block>
|
84 |
+
</reference>
|
85 |
+
<reference name="right">
|
86 |
+
<block type="catalog/product_list_related" name="catalog.product.related" before="-" template="catalog/product/list/related.phtml"/>
|
87 |
+
</reference>
|
88 |
+
</catalog_product_view>
|
89 |
+
|
90 |
+
</layout>
|
91 |
+
|
92 |
+
|
93 |
+
|
app/design/frontend/base/default/layout/customproduct_catalog.xml
ADDED
@@ -0,0 +1,252 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
|
3 |
+
<layout version="0.1.0">
|
4 |
+
<!--
|
5 |
+
Product view
|
6 |
+
-->
|
7 |
+
|
8 |
+
<catalog_product_view translate="label">
|
9 |
+
<label>Catalog Product View (Any)</label>
|
10 |
+
<!-- Mage_Catalog -->
|
11 |
+
<reference name="root">
|
12 |
+
<action method="setTemplate"><template>page/2columns-right.phtml</template></action>
|
13 |
+
</reference>
|
14 |
+
<reference name="head">
|
15 |
+
<action method="addJs"><script>varien/product.js</script></action>
|
16 |
+
<action method="addJs"><script>varien/configurable.js</script></action>
|
17 |
+
|
18 |
+
<action method="addItem"><type>js_css</type><name>calendar/calendar-win2k-1.css</name><params/><!--<if/><condition>can_load_calendar_js</condition>--></action>
|
19 |
+
<action method="addItem"><type>js</type><name>calendar/calendar.js</name><!--<params/><if/><condition>can_load_calendar_js</condition>--></action>
|
20 |
+
<action method="addItem"><type>js</type><name>calendar/calendar-setup.js</name><!--<params/><if/><condition>can_load_calendar_js</condition>--></action>
|
21 |
+
</reference>
|
22 |
+
<reference name="content">
|
23 |
+
<block type="catalog/product_view" name="product.info" template="catalog/product/view_custom.phtml">
|
24 |
+
|
25 |
+
<!--
|
26 |
+
<action method="addReviewSummaryTemplate"><type>default</type><template>review/helper/summary.phtml</template></action>
|
27 |
+
<action method="addReviewSummaryTemplate"><type>short</type><template>review/helper/summary_short.phtml</template></action>
|
28 |
+
<action method="addReviewSummaryTemplate"><type>...</type><template>...</template></action>
|
29 |
+
-->
|
30 |
+
<block type="catalog/product_view_media" name="product.info.media" as="media" template="catalog/product/view/media_custom.phtml"/>
|
31 |
+
<block type="core/text_list" name="alert.urls" as="alert_urls" translate="label">
|
32 |
+
<label>Alert Urls</label>
|
33 |
+
</block>
|
34 |
+
|
35 |
+
<action method="setTierPriceTemplate"><template>catalog/product/view/tierprices.phtml</template></action>
|
36 |
+
|
37 |
+
<block type="catalog/product_list_upsell" name="product.info.upsell" as="upsell_products" template="catalog/product/list/upsell.phtml">
|
38 |
+
<action method="setColumnCount"><columns>4</columns></action>
|
39 |
+
<action method="setItemLimit"><type>upsell</type><limit>4</limit></action>
|
40 |
+
</block>
|
41 |
+
|
42 |
+
<block type="catalog/product_view_additional" name="product.info.additional" as="product_additional_data" />
|
43 |
+
<block type="catalog/product_view_description" name="product.description" as="description" template="catalog/product/view/description.phtml">
|
44 |
+
<action method="addToParentGroup"><group>detailed_info</group></action>
|
45 |
+
</block>
|
46 |
+
<block type="catalog/product_view_attributes" name="product.attributes" as="additional" template="catalog/product/view/attributes.phtml">
|
47 |
+
<action method="addToParentGroup"><group>detailed_info</group></action>
|
48 |
+
</block>
|
49 |
+
<block type="catalog/product_view" name="product.info.addto" as="addto" template="catalog/product/view/addto.phtml"/>
|
50 |
+
<block type="catalog/product_view" name="product.info.addtocart" as="addtocart" template="catalog/product/view/addtocart.phtml"/>
|
51 |
+
|
52 |
+
<block type="core/text_list" name="product.info.extrahint" as="extrahint" translate="label">
|
53 |
+
<label>Product View Extra Hint</label>
|
54 |
+
</block>
|
55 |
+
|
56 |
+
<block type="catalog/product_view" name="product.info.options.wrapper" as="product_options_wrapper" template="catalog/product/view/options/wrapper.phtml" translate="label">
|
57 |
+
<label>Info Column Options Wrapper</label>
|
58 |
+
<block type="core/template" name="options_js" template="catalog/product/view/options/js.phtml"/>
|
59 |
+
<block type="catalog/product_view_options" name="product.info.options" as="product_options" template="catalog/product/view/options.phtml">
|
60 |
+
<action method="addOptionRenderer"><type>text</type><block>catalog/product_view_options_type_text</block><template>catalog/product/view/options/type/text.phtml</template></action>
|
61 |
+
<action method="addOptionRenderer"><type>file</type><block>catalog/product_view_options_type_file</block><template>catalog/product/view/options/type/file.phtml</template></action>
|
62 |
+
<action method="addOptionRenderer"><type>select</type><block>catalog/product_view_options_type_select</block><template>catalog/product/view/options/type/select.phtml</template></action>
|
63 |
+
<action method="addOptionRenderer"><type>date</type><block>catalog/product_view_options_type_date</block><template>catalog/product/view/options/type/date.phtml</template></action>
|
64 |
+
</block>
|
65 |
+
<block type="core/html_calendar" name="html_calendar" as="html_calendar" template="page/js/calendar.phtml"/>
|
66 |
+
</block>
|
67 |
+
<block type="catalog/product_view" name="product.info.options.wrapper.bottom" as="product_options_wrapper_bottom" template="catalog/product/view/options/wrapper/bottom.phtml" translate="label">
|
68 |
+
<label>Bottom Block Options Wrapper</label>
|
69 |
+
<action method="insert"><block>product.tierprices</block></action>
|
70 |
+
<block type="catalog/product_view" name="product.clone_prices" as="prices" template="catalog/product/view/price_clone.phtml"/>
|
71 |
+
<action method="append"><block>product.info.addtocart</block></action>
|
72 |
+
<action method="append"><block>product.info.addto</block></action>
|
73 |
+
</block>
|
74 |
+
|
75 |
+
<block type="core/template_facade" name="product.info.container1" as="container1">
|
76 |
+
<action method="setDataByKey"><key>alias_in_layout</key><value>container1</value></action>
|
77 |
+
<action method="setDataByKeyFromRegistry"><key>options_container</key><key_in_registry>product</key_in_registry></action>
|
78 |
+
<action method="append"><block>product.info.options.wrapper</block></action>
|
79 |
+
<action method="append"><block>product.info.options.wrapper.bottom</block></action>
|
80 |
+
</block>
|
81 |
+
<block type="core/template_facade" name="product.info.container2" as="container2">
|
82 |
+
<action method="setDataByKey"><key>alias_in_layout</key><value>container2</value></action>
|
83 |
+
<action method="setDataByKeyFromRegistry"><key>options_container</key><key_in_registry>product</key_in_registry></action>
|
84 |
+
<action method="append"><block>product.info.options.wrapper</block></action>
|
85 |
+
<action method="append"><block>product.info.options.wrapper.bottom</block></action>
|
86 |
+
</block>
|
87 |
+
<action method="unsetCallChild"><child>container1</child><call>ifEquals</call><if>0</if><key>alias_in_layout</key><key>options_container</key></action>
|
88 |
+
<action method="unsetCallChild"><child>container2</child><call>ifEquals</call><if>0</if><key>alias_in_layout</key><key>options_container</key></action>
|
89 |
+
</block>
|
90 |
+
</reference>
|
91 |
+
<reference name="right">
|
92 |
+
<block type="catalog/product_list_related" name="catalog.product.related" before="-" template="catalog/product/list/related.phtml"/>
|
93 |
+
</reference>
|
94 |
+
</catalog_product_view>
|
95 |
+
|
96 |
+
<!--
|
97 |
+
Additional block dependant on product type
|
98 |
+
-->
|
99 |
+
<PRODUCT_TYPE_simple translate="label" module="catalog">
|
100 |
+
<label>Catalog Product View (Simple)</label>
|
101 |
+
<reference name="product.info">
|
102 |
+
<block type="catalog/product_view_type_simple" name="product.info.simple" as="product_type_data" template="catalog/product/view/type/default.phtml">
|
103 |
+
<block type="core/text_list" name="product.info.simple.extra" as="product_type_data_extra" translate="label">
|
104 |
+
<label>Product Extra Info</label>
|
105 |
+
</block>
|
106 |
+
</block>
|
107 |
+
</reference>
|
108 |
+
</PRODUCT_TYPE_simple>
|
109 |
+
<PRODUCT_TYPE_configurable translate="label" module="catalog">
|
110 |
+
<label>Catalog Product View (Configurable)</label>
|
111 |
+
<reference name="product.info">
|
112 |
+
<block type="catalog/product_view_type_configurable" name="product.info.configurable" as="product_type_data" template="catalog/product/view/type/default.phtml">
|
113 |
+
<block type="core/text_list" name="product.info.configurable.extra" as="product_type_data_extra" translate="label">
|
114 |
+
<label>Product Extra Info</label>
|
115 |
+
</block>
|
116 |
+
</block>
|
117 |
+
</reference>
|
118 |
+
<reference name="product.info.options.wrapper">
|
119 |
+
<block type="catalog/product_view_type_configurable" name="product.info.options.configurable" as="options_configurable" before="-" template="catalog/product/view/type/options/configurable.phtml"/>
|
120 |
+
</reference>
|
121 |
+
</PRODUCT_TYPE_configurable>
|
122 |
+
<PRODUCT_TYPE_grouped translate="label" module="catalog">
|
123 |
+
<label>Catalog Product View (Grouped)</label>
|
124 |
+
<reference name="product.info">
|
125 |
+
<block type="catalog/product_view_type_grouped" name="product.info.grouped" as="product_type_data" template="catalog/product/view/type/grouped.phtml">
|
126 |
+
<block type="core/text_list" name="product.info.grouped.extra" as="product_type_data_extra" translate="label">
|
127 |
+
<label>Product Extra Info</label>
|
128 |
+
</block>
|
129 |
+
</block>
|
130 |
+
</reference>
|
131 |
+
</PRODUCT_TYPE_grouped>
|
132 |
+
<PRODUCT_TYPE_virtual translate="label" module="catalog">
|
133 |
+
<label>Catalog Product View (Virtual)</label>
|
134 |
+
<reference name="product.info">
|
135 |
+
<block type="catalog/product_view_type_virtual" name="product.info.virtual" as="product_type_data" template="catalog/product/view/type/default.phtml">
|
136 |
+
<block type="core/text_list" name="product.info.virtual.extra" as="product_type_data_extra" translate="label">
|
137 |
+
<label>Product Extra Info</label>
|
138 |
+
</block>
|
139 |
+
</block>
|
140 |
+
</reference>
|
141 |
+
</PRODUCT_TYPE_virtual>
|
142 |
+
|
143 |
+
|
144 |
+
|
145 |
+
<!--
|
146 |
+
Product send to friend
|
147 |
+
-->
|
148 |
+
|
149 |
+
<catalog_product_send translate="label">
|
150 |
+
<label>Catalog Product Email to a Friend</label>
|
151 |
+
<!-- Mage_Catalog -->
|
152 |
+
<reference name="root">
|
153 |
+
<action method="setTemplate"><template>page/2columns-right.phtml</template></action>
|
154 |
+
</reference>
|
155 |
+
<reference name="head">
|
156 |
+
<action method="addJs"><script>varien/product.js</script></action>
|
157 |
+
</reference>
|
158 |
+
<reference name="content">
|
159 |
+
<block type="catalog/product_send" name="product.send" template="catalog/product/send.phtml">
|
160 |
+
</block>
|
161 |
+
</reference>
|
162 |
+
</catalog_product_send>
|
163 |
+
|
164 |
+
<!--
|
165 |
+
Product additional images gallery popup
|
166 |
+
-->
|
167 |
+
|
168 |
+
<catalog_product_gallery translate="label">
|
169 |
+
<label>Catalog Product Image Gallery Popup</label>
|
170 |
+
<!-- Mage_Catalog -->
|
171 |
+
<reference name="root">
|
172 |
+
<action method="setTemplate"><template>page/popup.phtml</template></action>
|
173 |
+
</reference>
|
174 |
+
<reference name="content">
|
175 |
+
<block type="catalog/product_gallery" name="catalog_product_gallery" template="catalog/product/gallery.phtml"/>
|
176 |
+
</reference>
|
177 |
+
</catalog_product_gallery>
|
178 |
+
|
179 |
+
<!--
|
180 |
+
SEO Site Map
|
181 |
+
-->
|
182 |
+
|
183 |
+
<catalog_seo_sitemap translate="label">
|
184 |
+
<label>Catalog Seo Sitemap (Common)</label>
|
185 |
+
<remove name="right"/>
|
186 |
+
<remove name="left"/>
|
187 |
+
|
188 |
+
<reference name="root">
|
189 |
+
<action method="setTemplate"><template>page/1column.phtml</template></action>
|
190 |
+
</reference>
|
191 |
+
<reference name="content">
|
192 |
+
<block type="page/template_container" name="seo.sitemap.container" template="catalog/seo/sitemap/container.phtml">
|
193 |
+
<block type="page/template_links" name="seo.sitemap.links" as="links" template="page/template/links.phtml"/>
|
194 |
+
<block type="page/html_pager" name="seo.sitemap.pager.top" as="pager_top" template="page/html/pager.phtml"/>
|
195 |
+
<block type="page/html_pager" name="seo.sitemap.pager.bottom" as="pager_bottom" template="page/html/pager.phtml"/>
|
196 |
+
</block>
|
197 |
+
</reference>
|
198 |
+
</catalog_seo_sitemap>
|
199 |
+
|
200 |
+
<catalog_seo_sitemap_category translate="label">
|
201 |
+
<label>Catalog Seo Sitemap (Category List)</label>
|
202 |
+
<reference name="head">
|
203 |
+
<action method="setTitle" translate="title" module="catalog"><title>Site Map</title></action>
|
204 |
+
</reference>
|
205 |
+
<update handle="catalog_seo_sitemap" />
|
206 |
+
<reference name="seo.sitemap.container">
|
207 |
+
<action method="setTitle" translate="title" module="catalog"><title>Categories</title></action>
|
208 |
+
<block type="catalog/seo_sitemap_category" name="seo.sitemap.sitemap" as="sitemap" after="pager_top" template="catalog/seo/sitemap.phtml">
|
209 |
+
<action method="bindPager"><pager>seo.sitemap.pager.top</pager></action>
|
210 |
+
<action method="bindPager"><pager>seo.sitemap.pager.bottom</pager></action>
|
211 |
+
<action method="setItemsTitle" translate="title" module="catalog"><title>categories</title></action>
|
212 |
+
</block>
|
213 |
+
</reference>
|
214 |
+
<reference name="seo.sitemap.links">
|
215 |
+
<action method="addLink" translate="label title" module="catalog"><label>Products Sitemap</label><url helper="catalog/map/getProductUrl"/><title>Products Sitemap</title></action>
|
216 |
+
</reference>
|
217 |
+
</catalog_seo_sitemap_category>
|
218 |
+
|
219 |
+
<catalog_seo_sitemap_category_tree translate="label">
|
220 |
+
<label>Catalog Seo Sitemap (Category Tree)</label>
|
221 |
+
<reference name="seo.sitemap.container">
|
222 |
+
<remove name="seo.sitemap.pager.top" />
|
223 |
+
<remove name="seo.sitemap.pager.bottom" />
|
224 |
+
<block type="catalog/seo_sitemap_tree_pager" name="seo.sitemap.tree.pager.top" as="pager_top" template="page/html/pager.phtml"/>
|
225 |
+
<block type="catalog/seo_sitemap_tree_pager" name="seo.sitemap.tree.pager.bottom" as="pager_bottom" template="page/html/pager.phtml"/>
|
226 |
+
<remove name="seo.sitemap.sitemap" />
|
227 |
+
<block type="catalog/seo_sitemap_tree_category" name="seo.sitemap.sitemap_tree" as="sitemap" after="pager_top" template="catalog/seo/tree.phtml">
|
228 |
+
<action method="bindPager"><pager>seo.sitemap.tree.pager.top</pager></action>
|
229 |
+
<action method="bindPager"><pager>seo.sitemap.tree.pager.bottom</pager></action>
|
230 |
+
</block>
|
231 |
+
</reference>
|
232 |
+
</catalog_seo_sitemap_category_tree>
|
233 |
+
|
234 |
+
<catalog_seo_sitemap_product translate="label">
|
235 |
+
<label>Catalog Seo Sitemap (Product List)</label>
|
236 |
+
<reference name="head">
|
237 |
+
<action method="setTitle" translate="title" module="catalog"><title>Site Map</title></action>
|
238 |
+
</reference>
|
239 |
+
<update handle="catalog_seo_sitemap" />
|
240 |
+
<reference name="seo.sitemap.container">
|
241 |
+
<action method="setTitle" translate="title" module="catalog"><title>Products</title></action>
|
242 |
+
<block type="catalog/seo_sitemap_product" name="seo.sitemap.sitemap" as="sitemap" after="pager_top" template="catalog/seo/sitemap.phtml">
|
243 |
+
<action method="bindPager"><pager>seo.sitemap.pager.top</pager></action>
|
244 |
+
<action method="bindPager"><pager>seo.sitemap.pager.bottom</pager></action>
|
245 |
+
<action method="setItemsTitle" translate="title" module="catalog"><title>products</title></action>
|
246 |
+
</block>
|
247 |
+
</reference>
|
248 |
+
<reference name="seo.sitemap.links">
|
249 |
+
<action method="addLink" translate="label title" module="catalog"><label>Categories Sitemap</label><url helper="catalog/map/getCategoryUrl"/><title>Categories Sitemap</title></action>
|
250 |
+
</reference>
|
251 |
+
</catalog_seo_sitemap_product>
|
252 |
+
</layout>
|
app/design/frontend/base/default/template/catalog/product/view/media_custom.phtml
ADDED
@@ -0,0 +1,115 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?php
|
2 |
+
$baseurl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
|
3 |
+
$skinurl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_SKIN);
|
4 |
+
/**
|
5 |
+
* Magento
|
6 |
+
*
|
7 |
+
* NOTICE OF LICENSE
|
8 |
+
*
|
9 |
+
* This source file is subject to the Academic Free License (AFL 3.0)
|
10 |
+
* that is bundled with this package in the file LICENSE_AFL.txt.
|
11 |
+
* It is also available through the world-wide-web at this URL:
|
12 |
+
* http://opensource.org/licenses/afl-3.0.php
|
13 |
+
* If you did not receive a copy of the license and are unable to
|
14 |
+
* obtain it through the world-wide-web, please send an email
|
15 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
16 |
+
*
|
17 |
+
* DISCLAIMER
|
18 |
+
*
|
19 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
20 |
+
* versions in the future. If you wish to customize Magento for your
|
21 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
22 |
+
*
|
23 |
+
* @category design
|
24 |
+
* @package base_default
|
25 |
+
* @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
|
26 |
+
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
27 |
+
*/
|
28 |
+
|
29 |
+
/**
|
30 |
+
* Product media data template
|
31 |
+
*
|
32 |
+
* @see Mage_Catalog_Block_Product_View_Media
|
33 |
+
*/
|
34 |
+
?>
|
35 |
+
<style>
|
36 |
+
#designs{
|
37 |
+
background:url('<?php print $skinurl?>frontend/default/customproduct/images/bgimage7.png');
|
38 |
+
}
|
39 |
+
</style>
|
40 |
+
|
41 |
+
<?php
|
42 |
+
$_product = $this->getProduct();
|
43 |
+
$_helper = $this->helper('catalog/output');
|
44 |
+
print '<input type="button" value="Product" id="idproduct"><input type="button" value="Design" id="iddesign">';
|
45 |
+
?>
|
46 |
+
<?php if ($_product->getImage() != 'no_selection' && $_product->getImage()): ?>
|
47 |
+
<p id="products" class="product-image product-image-zoom">
|
48 |
+
<?php
|
49 |
+
$_img = '<img style="width:265px" id="image" src="'.$this->helper('catalog/image')->init($_product, 'image').'" alt="'.$this->htmlEscape($this->getImageLabel()).'" title="'.$this->htmlEscape($this->getImageLabel()).'" />';
|
50 |
+
echo $_helper->productAttribute($_product, $_img, 'image');
|
51 |
+
?>
|
52 |
+
<input type="hidden" name="oldimage" value="<?php print $this->helper('catalog/image')->init($_product,'image'); ?>" id="oldimage"/>
|
53 |
+
<input type="hidden" name="oldprice" value="" id="oldprice"/>
|
54 |
+
<input type="hidden" name="oldproduct" value="" id="oldproduct"/>
|
55 |
+
</p>
|
56 |
+
|
57 |
+
<div id="designs" class="product-image product-image-zoom" style="display:none;position:relative; width:265px; height:400px;" class="darkInsetBackgroundColor">
|
58 |
+
<div id="page_imagePort" style="position:absolute; left:0px; top:0px; width:265px; height:400px; overflow:hidden;">
|
59 |
+
<img id="page_imagePort-image" src="<?php print $skinurl.'frontend/default/customproduct/images/'.'bgimage.png'; ?>" style="position:absolute; width:265px; height:200px;" alt=""/>
|
60 |
+
</div>
|
61 |
+
<div id="page_marquee" style="position:absolute; left:0px; top:0px; width:265px; height:400px;"></div>
|
62 |
+
|
63 |
+
<div id="page_imagePort1" style="position:absolute; left:0px; top:0px; width:265px; height:400px; overflow:hidden;">
|
64 |
+
<img id="page_imagePort1-image" src="<?php print $skinurl.'frontend/default/customproduct/images/'.'textimage.png'; ?>" style="position:absolute; width:265px; height:200px;" alt=""/>
|
65 |
+
</div>
|
66 |
+
<div id="page_marquee1" style="position:absolute; left:0px; top:0px; width:265px; height:400px;"></div>
|
67 |
+
|
68 |
+
</div>
|
69 |
+
|
70 |
+
<input id="page-marqueePositionLeft" type="hidden"/>
|
71 |
+
<input id="page-marqueePositionTop" type="hidden"/>
|
72 |
+
<input id="page-marqueePositionWidth" type="hidden"/>
|
73 |
+
<input id="page-marqueePositionHeight" type="hidden"/>
|
74 |
+
|
75 |
+
<input id="page-marqueePositionLeftT" type="hidden"/>
|
76 |
+
<input id="page-marqueePositionTopT" type="hidden"/>
|
77 |
+
<input id="page-marqueePositionWidthT" type="hidden"/>
|
78 |
+
<input id="page-marqueePositionHeightT" type="hidden"/>
|
79 |
+
|
80 |
+
|
81 |
+
<p class="zoom-notice" id="track_hint"><?php echo $this->__('Double click on above image to view full picture') ?></p>
|
82 |
+
<div class="zoom">
|
83 |
+
<img id="zoom_out" src="<?php echo $this->getSkinUrl('images/slider_btn_zoom_out.gif') ?>" alt="<?php echo $this->__('Zoom Out') ?>" title="<?php echo $this->__('Zoom Out') ?>" class="btn-zoom-out" />
|
84 |
+
<div id="track">
|
85 |
+
<div id="handle"></div>
|
86 |
+
</div>
|
87 |
+
<img id="zoom_in" src="<?php echo $this->getSkinUrl('images/slider_btn_zoom_in.gif') ?>" alt="<?php echo $this->__('Zoom In') ?>" title="<?php echo $this->__('Zoom In') ?>" class="btn-zoom-in" />
|
88 |
+
</div>
|
89 |
+
<script type="text/javascript">
|
90 |
+
//<![CDATA[
|
91 |
+
Event.observe(window, 'load', function() {
|
92 |
+
product_zoom = new Product.Zoom('image', 'track', 'handle', 'zoom_in', 'zoom_out', 'track_hint');
|
93 |
+
});
|
94 |
+
//]]>
|
95 |
+
</script>
|
96 |
+
<?php else: ?>
|
97 |
+
<p class="product-image">
|
98 |
+
<?php
|
99 |
+
$_img = '<img src="'.$this->helper('catalog/image')->init($_product, 'image')->resize(265).'" alt="'.$this->htmlEscape($this->getImageLabel()).'" title="'.$this->htmlEscape($this->getImageLabel()).'" />';
|
100 |
+
echo $_helper->productAttribute($_product, $_img, 'image');
|
101 |
+
?>
|
102 |
+
</p>
|
103 |
+
<?php endif; ?>
|
104 |
+
<?php if (count($this->getGalleryImages()) > 0): ?>
|
105 |
+
<div class="more-views">
|
106 |
+
<h2><?php echo $this->__('More Views') ?></h2>
|
107 |
+
<ul>
|
108 |
+
<?php foreach ($this->getGalleryImages() as $_image): ?>
|
109 |
+
<li>
|
110 |
+
<a href="#" onclick="popWin('<?php echo $this->getGalleryUrl($_image) ?>', 'gallery', 'width=300,height=300,left=0,top=0,location=no,status=yes,scrollbars=yes,resizable=yes'); return false;" title="<?php echo $this->htmlEscape($_image->getLabel()) ?>"><img src="<?php echo $this->helper('catalog/image')->init($this->getProduct(), 'thumbnail', $_image->getFile())->resize(56); ?>" width="56" height="56" alt="<?php echo $this->htmlEscape($_image->getLabel()) ?>" /></a>
|
111 |
+
</li>
|
112 |
+
<?php endforeach; ?>
|
113 |
+
</ul>
|
114 |
+
</div>
|
115 |
+
<?php endif; ?>
|
app/design/frontend/base/default/template/catalog/product/view_custom.phtml
ADDED
@@ -0,0 +1,635 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
|
2 |
+
|
3 |
+
<?php $skin_url = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_SKIN); ?>
|
4 |
+
<?php $skin_url_uize = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_SKIN).'frontend/default/customproduct/js/Uize.js'; ?>
|
5 |
+
|
6 |
+
<script src="<?php print $skin_url_uize;?>"></script>
|
7 |
+
<script>jQuery.noConflict();</script>
|
8 |
+
|
9 |
+
<?php
|
10 |
+
$baseurl = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_WEB);
|
11 |
+
//$skin_url = Mage::getBaseUrl(Mage_Core_Model_Store::URL_TYPE_SKIN);
|
12 |
+
?>
|
13 |
+
<style>
|
14 |
+
#main_container{
|
15 |
+
//margin-left:300px;
|
16 |
+
//margin-top:200px;
|
17 |
+
position:relative;
|
18 |
+
}
|
19 |
+
|
20 |
+
#toaddtext{
|
21 |
+
padding:2px;
|
22 |
+
}
|
23 |
+
|
24 |
+
.mytext{
|
25 |
+
height:30px;
|
26 |
+
}
|
27 |
+
|
28 |
+
.addtxt {
|
29 |
+
background:url('<?php echo $skin_url?>frontend/default/customproduct/images/button1.png') no-repeat;
|
30 |
+
width:113px;
|
31 |
+
height:30px;
|
32 |
+
}
|
33 |
+
|
34 |
+
.uploads{
|
35 |
+
height: 30px;
|
36 |
+
margin-left: 100px;
|
37 |
+
width: 113px;
|
38 |
+
background:url('<?php echo $skin_url?>frontend/default/customproduct/images/button3.png') no-repeat;
|
39 |
+
}
|
40 |
+
|
41 |
+
.fileUpload{
|
42 |
+
height: 30px;
|
43 |
+
}
|
44 |
+
|
45 |
+
</style>
|
46 |
+
<script type="text/javascript">
|
47 |
+
|
48 |
+
jQuery(document).ready(function(){
|
49 |
+
|
50 |
+
var p = jQuery('.price').html();
|
51 |
+
jQuery('#oldprice').val(p);
|
52 |
+
|
53 |
+
jQuery('#oldproduct').val(jQuery("input[name=product]").val());
|
54 |
+
|
55 |
+
jQuery('#product-essential').append('<div id="product-options-wrapper" class="product-options"></div>');
|
56 |
+
|
57 |
+
document.getElementById('userfiles').addEventListener('change', function(e) {
|
58 |
+
var url='<?print $baseurl; ?>customproduct/index/upload';
|
59 |
+
var file = this.files[0];
|
60 |
+
var xhr = new XMLHttpRequest();
|
61 |
+
xhr.file = file; // not necessary if you create scopes like this
|
62 |
+
xhr.addEventListener('progress', function(e) {
|
63 |
+
var done = e.position || e.loaded, total = e.totalSize || e.total;
|
64 |
+
console.log('xhr progress: ' + (Math.floor(done/total*1000)/10) + '%');
|
65 |
+
}, false);
|
66 |
+
if ( xhr.upload ) {
|
67 |
+
xhr.upload.onprogress = function(e) {
|
68 |
+
var done = e.position || e.loaded, total = e.totalSize || e.total;
|
69 |
+
console.log('xhr.upload progress: ' + done + ' / ' + total + ' = ' + (Math.floor(done/total*1000)/10) + '%');
|
70 |
+
};
|
71 |
+
}
|
72 |
+
xhr.onreadystatechange = function(e) {
|
73 |
+
if ( 4 == this.readyState ) {
|
74 |
+
this.response = this.response || this.responseText;
|
75 |
+
jQuery('#page_imagePort-image').attr('src','media/finalimages/upload/'+ this.response);
|
76 |
+
|
77 |
+
console.log(['xhr upload complete', e]);
|
78 |
+
}
|
79 |
+
};
|
80 |
+
xhr.open('post', url, true);
|
81 |
+
var formData = new FormData();
|
82 |
+
formData.append("userfile",file);
|
83 |
+
xhr.send(formData);
|
84 |
+
//xhr.send(file);
|
85 |
+
}, false);
|
86 |
+
|
87 |
+
//});
|
88 |
+
|
89 |
+
/*jQuery("input[type=file]").filestyle({
|
90 |
+
image: "http://localhost/magento/skin/frontend/base/default/toajax/images/button2.png",
|
91 |
+
imageheight : 30,
|
92 |
+
imagewidth : 113,
|
93 |
+
width : 200
|
94 |
+
});
|
95 |
+
*/
|
96 |
+
|
97 |
+
|
98 |
+
var prod_id = jQuery("input[name=product]").val();
|
99 |
+
jQuery.post('<?print $baseurl; ?>customproduct/index/ajaxoptions',{'product_id':prod_id},function(data){
|
100 |
+
jQuery('#product-options-wrapper').html(data);
|
101 |
+
});
|
102 |
+
|
103 |
+
jQuery('#idproduct').click(function(){
|
104 |
+
jQuery('#designs').hide();
|
105 |
+
jQuery('#products').show();
|
106 |
+
});
|
107 |
+
|
108 |
+
|
109 |
+
jQuery('#iddesign').click(function(){
|
110 |
+
|
111 |
+
jQuery('#page_imagePort-image').attr('src','<?php echo $skin_url?>frontend/default/customproduct/images/bgimage.png');
|
112 |
+
jQuery('#page_imagePort1-image').attr('src','<?php echo $skin_url?>frontend/default/customproduct/images/textimage.png');
|
113 |
+
|
114 |
+
jQuery('#designs').show();
|
115 |
+
jQuery('#products').hide();
|
116 |
+
|
117 |
+
|
118 |
+
Uize.module ({
|
119 |
+
required:[
|
120 |
+
'Uize.Widget.Page',
|
121 |
+
'Uize.Node',
|
122 |
+
'Uize.Widget.ImagePort',
|
123 |
+
'Uize.Widget.Bar.Slider.xSkin',
|
124 |
+
'Uize.Widget.Resizer.Marquee'
|
125 |
+
],
|
126 |
+
builder:function () {
|
127 |
+
/*** create the example page widget ***/
|
128 |
+
|
129 |
+
var page = window.page = Uize.Widget.Page ();
|
130 |
+
|
131 |
+
/*** add the image port child widget ***/
|
132 |
+
var imagePort = page.addChild (
|
133 |
+
'imagePort',
|
134 |
+
Uize.Widget.ImagePort,
|
135 |
+
{
|
136 |
+
sizingLowerBound:'0',
|
137 |
+
sizingUpperBound:'fill',
|
138 |
+
sizingValue:.5,
|
139 |
+
alignX:.5,
|
140 |
+
alignY:.5
|
141 |
+
}
|
142 |
+
);
|
143 |
+
|
144 |
+
|
145 |
+
var imagePort1 = page.addChild (
|
146 |
+
'imagePort1',
|
147 |
+
Uize.Widget.ImagePort,
|
148 |
+
{
|
149 |
+
sizingLowerBound:'0',
|
150 |
+
sizingUpperBound:'fill',
|
151 |
+
sizingValue:.5,
|
152 |
+
alignX:.5,
|
153 |
+
alignY:.5
|
154 |
+
}
|
155 |
+
);
|
156 |
+
|
157 |
+
/*** code to update the image port instance based on user input values ***/
|
158 |
+
function updateImagePortSettings () {
|
159 |
+
imagePort.set ({
|
160 |
+
alignX:0.5,
|
161 |
+
alignY:0.5,
|
162 |
+
sizingUpperBound:'fill',
|
163 |
+
sizingLowerBound:'0',
|
164 |
+
sizingValue:'1'
|
165 |
+
});
|
166 |
+
}
|
167 |
+
|
168 |
+
function updateImagePortSettings1 () {
|
169 |
+
imagePort1.set ({
|
170 |
+
alignX:0.5,
|
171 |
+
alignY:0.5,
|
172 |
+
sizingUpperBound:'fill',
|
173 |
+
sizingLowerBound:'0',
|
174 |
+
sizingValue:'1'
|
175 |
+
});
|
176 |
+
}
|
177 |
+
|
178 |
+
/*** common values shared by alignX, alignY, and sizingValue sliders ***/
|
179 |
+
/*Uize.Widget.Bar.Slider.set ({
|
180 |
+
value:.5,
|
181 |
+
fullTintColor:'#9aa',
|
182 |
+
fullTintLevel:50,
|
183 |
+
emptyTintColor:'#9aa',
|
184 |
+
emptyTintLevel:50,
|
185 |
+
borderThickness:3,
|
186 |
+
borderTintColor:'#455',
|
187 |
+
borderTintLevel:50,
|
188 |
+
increments:0,
|
189 |
+
knobSize:28,
|
190 |
+
built:false
|
191 |
+
});*/
|
192 |
+
|
193 |
+
/*** add the alignX slider child widget ***/
|
194 |
+
/*var alignXSlider = page.addChild (
|
195 |
+
'alignXSlider',
|
196 |
+
Uize.Widget.Bar.Slider,
|
197 |
+
{
|
198 |
+
minValue:0,
|
199 |
+
maxValue:1,
|
200 |
+
orientation:'horizontal'
|
201 |
+
}
|
202 |
+
);*/
|
203 |
+
/*alignXSlider.wire ('Changed.value',updateImagePortSettings);*/
|
204 |
+
|
205 |
+
/*** add the alignY slider child widget ***/
|
206 |
+
/*var alignYSlider = page.addChild (
|
207 |
+
'alignYSlider',
|
208 |
+
Uize.Widget.Bar.Slider,
|
209 |
+
{
|
210 |
+
minValue:1,
|
211 |
+
maxValue:0,
|
212 |
+
orientation:'vertical'
|
213 |
+
}
|
214 |
+
);
|
215 |
+
alignYSlider.wire ('Changed.value',updateImagePortSettings);*/
|
216 |
+
|
217 |
+
/*** add the sizingValue slider child widget ***/
|
218 |
+
/*var sizingValueSlider = page.addChild (
|
219 |
+
'sizingValueSlider',
|
220 |
+
Uize.Widget.Bar.Slider,
|
221 |
+
{
|
222 |
+
fullTintColor:'#fff',
|
223 |
+
fullTintLevel:70,
|
224 |
+
minValue:0,
|
225 |
+
maxValue:3,
|
226 |
+
value:1,
|
227 |
+
orientation:'vertical'
|
228 |
+
}
|
229 |
+
);
|
230 |
+
sizingValueSlider.wire ('Changed.value',updateImagePortSettings);*/
|
231 |
+
|
232 |
+
/*** add the marquee child widget ***/
|
233 |
+
function updateImagePortPos () {
|
234 |
+
imagePort.setNodeStyle ('',marquee.getCoords());
|
235 |
+
imagePort.updateUi ();
|
236 |
+
}
|
237 |
+
|
238 |
+
function updateImagePortPos1 () {
|
239 |
+
imagePort1.setNodeStyle ('',marquee1.getCoords());
|
240 |
+
imagePort1.updateUi ();
|
241 |
+
}
|
242 |
+
|
243 |
+
|
244 |
+
|
245 |
+
var marquee = page.addChild (
|
246 |
+
'marquee',
|
247 |
+
Uize.Widget.Resizer.Marquee,
|
248 |
+
{
|
249 |
+
constrain:true,
|
250 |
+
minWidth:20,
|
251 |
+
minHeight:20,
|
252 |
+
built:false
|
253 |
+
}
|
254 |
+
);
|
255 |
+
marquee.wire ('Position Changed',updateImagePortPos);
|
256 |
+
|
257 |
+
var marquee1 = page.addChild (
|
258 |
+
'marquee1',
|
259 |
+
Uize.Widget.Resizer.Marquee,
|
260 |
+
{
|
261 |
+
constrain:true,
|
262 |
+
minWidth:20,
|
263 |
+
minHeight:20,
|
264 |
+
built:false
|
265 |
+
}
|
266 |
+
);
|
267 |
+
marquee1.wire ('Position Changed',updateImagePortPos1);
|
268 |
+
|
269 |
+
|
270 |
+
/*** initialize the ImagePort instance ***/
|
271 |
+
updateImagePortSettings ();
|
272 |
+
updateImagePortSettings1 ();
|
273 |
+
updateImagePortPos ();
|
274 |
+
updateImagePortPos1 ();
|
275 |
+
|
276 |
+
/*** wire up the page widget ***/
|
277 |
+
page.wireUi ();
|
278 |
+
|
279 |
+
/*** watch for changes in sizing bound values ***/
|
280 |
+
page.wireNode ('sizingUpperBound','change',updateImagePortSettings);
|
281 |
+
page.wireNode ('sizingLowerBound','change',updateImagePortSettings1);
|
282 |
+
|
283 |
+
|
284 |
+
function displayMarqueePosition () {
|
285 |
+
page.setNodeValue ('marqueePositionLeft',marquee.get ('left'));
|
286 |
+
page.setNodeValue ('marqueePositionTop',marquee.get ('top'));
|
287 |
+
page.setNodeValue ('marqueePositionWidth',marquee.get ('width'));
|
288 |
+
page.setNodeValue ('marqueePositionHeight',marquee.get ('height'));
|
289 |
+
}
|
290 |
+
|
291 |
+
function displayMarqueePosition1 () {
|
292 |
+
page.setNodeValue ('marqueePositionLeftT',marquee1.get ('left'));
|
293 |
+
page.setNodeValue ('marqueePositionTopT',marquee1.get ('top'));
|
294 |
+
page.setNodeValue ('marqueePositionWidthT',marquee1.get ('width'));
|
295 |
+
page.setNodeValue ('marqueePositionHeightT',marquee1.get ('height'));
|
296 |
+
}
|
297 |
+
|
298 |
+
marquee.wire('Position Changed',displayMarqueePosition);
|
299 |
+
marquee1.wire('Position Changed',displayMarqueePosition1);
|
300 |
+
|
301 |
+
/*** display marquee's initial position ***/
|
302 |
+
displayMarqueePosition();
|
303 |
+
|
304 |
+
displayMarqueePosition1();
|
305 |
+
|
306 |
+
}
|
307 |
+
});
|
308 |
+
|
309 |
+
|
310 |
+
|
311 |
+
|
312 |
+
});
|
313 |
+
|
314 |
+
|
315 |
+
jQuery(".addtxt").click(function(){
|
316 |
+
|
317 |
+
var l_text = jQuery('#page-marqueePositionLeftT').val();
|
318 |
+
var t_text = jQuery('#page-marqueePositionTopT').val();
|
319 |
+
var w_text = jQuery('#page-marqueePositionWidthT').val();
|
320 |
+
var h_text = jQuery('#page-marqueePositionHeightT').val();
|
321 |
+
|
322 |
+
var mytext=jQuery('.mytext').val();
|
323 |
+
|
324 |
+
jQuery.post('<?print $baseurl; ?>customproduct/index/text',{'mytext':mytext,'width':w_text,'height':h_text,'left':l_text,'top':t_text},function(data){
|
325 |
+
jQuery('#page_imagePort1-image').attr('src',data);
|
326 |
+
});
|
327 |
+
|
328 |
+
});
|
329 |
+
|
330 |
+
jQuery('#idproduct').click(function(){
|
331 |
+
|
332 |
+
var left =jQuery('#page-marqueePositionLeft').val();
|
333 |
+
var top = jQuery('#page-marqueePositionTop').val();
|
334 |
+
var width = jQuery('#page-marqueePositionWidth').val();
|
335 |
+
var height =jQuery('#page-marqueePositionHeight').val();
|
336 |
+
|
337 |
+
var left_text =jQuery('#page-marqueePositionLeftT').val();
|
338 |
+
var top_text = jQuery('#page-marqueePositionTopT').val();
|
339 |
+
var w_text = jQuery('#page-marqueePositionWidthT').val();
|
340 |
+
var h_text =jQuery('#page-marqueePositionHeightT').val();
|
341 |
+
|
342 |
+
var product =jQuery("input[name=product]").val();
|
343 |
+
|
344 |
+
var textimage =jQuery('#page_imagePort1-image').attr('src');
|
345 |
+
var mainimage =jQuery('#page_imagePort-image').attr('src');
|
346 |
+
|
347 |
+
jQuery('#image').attr('src',jQuery('#oldimage').val());
|
348 |
+
|
349 |
+
var image = jQuery('#image').attr('src');
|
350 |
+
|
351 |
+
//var product =jQuery("input[name=product]").val();
|
352 |
+
|
353 |
+
var oldprice = jQuery('#oldprice').val();
|
354 |
+
|
355 |
+
jQuery.post('<?print $baseurl; ?>customproduct/index/image',{'oldprice':oldprice,'image':image,'mainimage':mainimage,'product':product,'textimage':textimage,'left':left,'top':top,'width':width,'height':height,'left_text':left_text,'top_text':top_text,'w_text':w_text,'h_text':h_text},function(data){
|
356 |
+
|
357 |
+
var data = JSON.parse(data);
|
358 |
+
|
359 |
+
|
360 |
+
if(data['filename']!=0){
|
361 |
+
jQuery('#image').attr('src',data['filename']);
|
362 |
+
var pid = data['product_id'];
|
363 |
+
jQuery(".price").html('$'+data['price']);
|
364 |
+
} else {
|
365 |
+
jQuery('#image').attr('src',jQuery('#oldimage').val());
|
366 |
+
var pid = jQuery('#oldproduct').val();
|
367 |
+
jQuery(".price").html(jQuery('#oldprice').val());
|
368 |
+
}
|
369 |
+
|
370 |
+
if(data['opthtml']!=0){
|
371 |
+
jQuery('#product-options-wrapper').html(data['opthtml']);
|
372 |
+
}
|
373 |
+
|
374 |
+
|
375 |
+
|
376 |
+
|
377 |
+
|
378 |
+
|
379 |
+
jQuery("input[name=product]").val(pid);
|
380 |
+
|
381 |
+
|
382 |
+
var addcart = jQuery("#product_addtocart_form").attr('action');
|
383 |
+
var addcart = addcart.split('product/');
|
384 |
+
var addcart_url = addcart[0]+'product/'+pid+'/'
|
385 |
+
|
386 |
+
|
387 |
+
var wish = jQuery(".link-wishlist").attr('href');
|
388 |
+
var wish = wish.split('product/');
|
389 |
+
|
390 |
+
|
391 |
+
var wish_url = wish[0]+'product/'+pid+'/'
|
392 |
+
|
393 |
+
|
394 |
+
var comp = jQuery(".link-compare").attr('href');
|
395 |
+
var comp = comp.split('uenc/');
|
396 |
+
var comp1 = comp[0].split('product/');
|
397 |
+
|
398 |
+
var comp_url = comp1[0]+'product/id/'+pid+'/uenc/'+comp[1];
|
399 |
+
|
400 |
+
/*var rv=jQuery(".no-rating a").attr('href');
|
401 |
+
var rv = rv.trim();
|
402 |
+
rv.split('/review');
|
403 |
+
var rev_url = rv[0]+'list/id/'+pid+'#review-form';*/
|
404 |
+
|
405 |
+
jQuery("#product_addtocart_form").attr('action',addcart_url);
|
406 |
+
|
407 |
+
jQuery(".link-wishlist").attr('href',wish_url);
|
408 |
+
|
409 |
+
jQuery(".link-compare").attr('href',comp_url);
|
410 |
+
|
411 |
+
|
412 |
+
|
413 |
+
var prod_id = jQuery("input[name=product]").val();
|
414 |
+
jQuery.post('<?print $baseurl; ?>customproduct/index/ajaxoptions',{'product_id':prod_id},function(data){
|
415 |
+
jQuery('#product-options-wrapper').html(data);
|
416 |
+
});
|
417 |
+
|
418 |
+
|
419 |
+
});
|
420 |
+
|
421 |
+
|
422 |
+
|
423 |
+
|
424 |
+
|
425 |
+
|
426 |
+
|
427 |
+
});
|
428 |
+
|
429 |
+
|
430 |
+
});
|
431 |
+
|
432 |
+
|
433 |
+
|
434 |
+
|
435 |
+
</script>
|
436 |
+
|
437 |
+
<?php
|
438 |
+
/**
|
439 |
+
* Magento
|
440 |
+
*
|
441 |
+
* NOTICE OF LICENSE
|
442 |
+
*
|
443 |
+
* This source file is subject to the Academic Free License (AFL 3.0)
|
444 |
+
* that is bundled with this package in the file LICENSE_AFL.txt.
|
445 |
+
* It is also available through the world-wide-web at this URL:
|
446 |
+
* http://opensource.org/licenses/afl-3.0.php
|
447 |
+
* If you did not receive a copy of the license and are unable to
|
448 |
+
* obtain it through the world-wide-web, please send an email
|
449 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
450 |
+
*
|
451 |
+
* DISCLAIMER
|
452 |
+
*
|
453 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
454 |
+
* versions in the future. If you wish to customize Magento for your
|
455 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
456 |
+
*
|
457 |
+
* @category design
|
458 |
+
* @package base_default
|
459 |
+
* @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
|
460 |
+
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
461 |
+
*/
|
462 |
+
|
463 |
+
/**
|
464 |
+
* Product view template
|
465 |
+
*
|
466 |
+
* @see Mage_Catalog_Block_Product_View
|
467 |
+
* @see Mage_Review_Block_Product_View
|
468 |
+
*/
|
469 |
+
?>
|
470 |
+
<?php $_helper = $this->helper('catalog/output'); ?>
|
471 |
+
<?php $_product = $this->getProduct(); ?>
|
472 |
+
<script type="text/javascript">
|
473 |
+
var optionsPrice = new Product.OptionsPrice(<?php echo $this->getJsonConfig() ?>);
|
474 |
+
</script>
|
475 |
+
<div id="messages_product_view"><?php echo $this->getMessagesBlock()->getGroupedHtml() ?></div>
|
476 |
+
<div class="product-view">
|
477 |
+
<div class="product-essential">
|
478 |
+
|
479 |
+
|
480 |
+
|
481 |
+
|
482 |
+
|
483 |
+
<form action="<?php echo $this->getSubmitUrl($_product) ?>" method="post" id="product_addtocart_form"<?php if($_product->getOptions()): ?> enctype="multipart/form-data"<?php endif; ?>>
|
484 |
+
<div class="no-display">
|
485 |
+
<input type="hidden" name="product" value="<?php echo $_product->getId() ?>" />
|
486 |
+
<input type="hidden" name="related_product" id="related-products-field" value="" />
|
487 |
+
</div>
|
488 |
+
|
489 |
+
<div class="product-shop">
|
490 |
+
<div class="product-name">
|
491 |
+
<h1><?php echo $_helper->productAttribute($_product, $_product->getName(), 'name') ?></h1>
|
492 |
+
</div>
|
493 |
+
|
494 |
+
<?php if ($this->canEmailToFriend()): ?>
|
495 |
+
<p class="email-friend"><a href="<?php echo $this->helper('catalog/product')->getEmailToFriendUrl($_product) ?>"><?php echo $this->__('Email to a Friend') ?></a></p>
|
496 |
+
<?php endif; ?>
|
497 |
+
|
498 |
+
|
499 |
+
|
500 |
+
|
501 |
+
|
502 |
+
<?php echo $this->getReviewsSummaryHtml($_product, false, true)?>
|
503 |
+
<?php echo $this->getChildHtml('alert_urls') ?>
|
504 |
+
<?php echo $this->getChildHtml('product_type_data') ?>
|
505 |
+
<?php echo $this->getTierPriceHtml() ?>
|
506 |
+
<?php echo $this->getChildHtml('extrahint') ?>
|
507 |
+
|
508 |
+
<?php if (!$this->hasOptions()):?>
|
509 |
+
<div class="add-to-box">
|
510 |
+
<?php if($_product->isSaleable()): ?>
|
511 |
+
<?php echo $this->getChildHtml('addtocart') ?>
|
512 |
+
<?php if( $this->helper('wishlist')->isAllow() || $_compareUrl=$this->helper('catalog/product_compare')->getAddUrl($_product)): ?>
|
513 |
+
<span class="or"><?php echo $this->__('OR') ?></span>
|
514 |
+
<?php endif; ?>
|
515 |
+
<?php endif; ?>
|
516 |
+
<?php echo $this->getChildHtml('addto') ?>
|
517 |
+
</div>
|
518 |
+
<?php echo $this->getChildHtml('extra_buttons') ?>
|
519 |
+
<?php elseif (!$_product->isSaleable()): ?>
|
520 |
+
<div class="add-to-box">
|
521 |
+
<?php echo $this->getChildHtml('addto') ?>
|
522 |
+
</div>
|
523 |
+
<?php endif; ?>
|
524 |
+
|
525 |
+
<?php if ($_product->getShortDescription()):?>
|
526 |
+
<div class="short-description">
|
527 |
+
<h2><?php echo $this->__('Quick Overview') ?></h2>
|
528 |
+
<div class="std"><?php echo $_helper->productAttribute($_product, nl2br($_product->getShortDescription()), 'short_description') ?></div>
|
529 |
+
</div>
|
530 |
+
<?php endif;?>
|
531 |
+
|
532 |
+
|
533 |
+
<div id="main_container">
|
534 |
+
<h2>Upload Image Files</h2>
|
535 |
+
<form id="uploadfile" action="<?print $baseurl; ?>customproduct/index/upload" enctype="multipart/form-data">
|
536 |
+
<input type="file" name="userfiles" id="userfiles" class="fileUpload" multiple>
|
537 |
+
<!--<input class="uploads" type="button" name="upload" id="upload">-->
|
538 |
+
</form>
|
539 |
+
<div id="mlist">
|
540 |
+
</div>
|
541 |
+
|
542 |
+
|
543 |
+
<div id="toaddtext">
|
544 |
+
<span><input type="button" name="addtxt" class="addtxt" value="Add text"></span><span><input type="text" name="mytext" id="mytext" class="mytext"/></span>
|
545 |
+
</div>
|
546 |
+
</div>
|
547 |
+
|
548 |
+
|
549 |
+
|
550 |
+
<?php echo $this->getChildHtml('other');?>
|
551 |
+
|
552 |
+
<?php if ($_product->isSaleable() && $this->hasOptions()):?>
|
553 |
+
<?php echo $this->getChildChildHtml('container1', '', true, true) ?>
|
554 |
+
<?php endif;?>
|
555 |
+
|
556 |
+
</div>
|
557 |
+
|
558 |
+
<div class="product-img-box">
|
559 |
+
<?php echo $this->getChildHtml('media') ?>
|
560 |
+
</div>
|
561 |
+
|
562 |
+
<div class="clearer"></div>
|
563 |
+
<?php if ($_product->isSaleable() && $this->hasOptions()):?>
|
564 |
+
<?php echo $this->getChildChildHtml('container2', '', true, true) ?>
|
565 |
+
<?php endif;?>
|
566 |
+
</form>
|
567 |
+
|
568 |
+
|
569 |
+
|
570 |
+
<script type="text/javascript">
|
571 |
+
//<![CDATA[
|
572 |
+
var productAddToCartForm = new VarienForm('product_addtocart_form');
|
573 |
+
productAddToCartForm.submit = function(button, url) {
|
574 |
+
if (this.validator.validate()) {
|
575 |
+
var form = this.form;
|
576 |
+
var oldUrl = form.action;
|
577 |
+
|
578 |
+
if (url) {
|
579 |
+
form.action = url;
|
580 |
+
}
|
581 |
+
var e = null;
|
582 |
+
try {
|
583 |
+
this.form.submit();
|
584 |
+
} catch (e) {
|
585 |
+
}
|
586 |
+
this.form.action = oldUrl;
|
587 |
+
if (e) {
|
588 |
+
throw e;
|
589 |
+
}
|
590 |
+
|
591 |
+
if (button && button != 'undefined') {
|
592 |
+
button.disabled = true;
|
593 |
+
}
|
594 |
+
}
|
595 |
+
}.bind(productAddToCartForm);
|
596 |
+
|
597 |
+
productAddToCartForm.submitLight = function(button, url){
|
598 |
+
if(this.validator) {
|
599 |
+
var nv = Validation.methods;
|
600 |
+
delete Validation.methods['required-entry'];
|
601 |
+
delete Validation.methods['validate-one-required'];
|
602 |
+
delete Validation.methods['validate-one-required-by-name'];
|
603 |
+
// Remove custom datetime validators
|
604 |
+
for (var methodName in Validation.methods) {
|
605 |
+
if (methodName.match(/^validate-datetime-.*/i)) {
|
606 |
+
delete Validation.methods[methodName];
|
607 |
+
}
|
608 |
+
}
|
609 |
+
|
610 |
+
if (this.validator.validate()) {
|
611 |
+
if (url) {
|
612 |
+
this.form.action = url;
|
613 |
+
}
|
614 |
+
this.form.submit();
|
615 |
+
}
|
616 |
+
Object.extend(Validation.methods, nv);
|
617 |
+
}
|
618 |
+
}.bind(productAddToCartForm);
|
619 |
+
//]]>
|
620 |
+
</script>
|
621 |
+
</div>
|
622 |
+
|
623 |
+
<div class="product-collateral">
|
624 |
+
<?php foreach ($this->getChildGroup('detailed_info', 'getChildHtml') as $alias => $html):?>
|
625 |
+
<div class="box-collateral <?php echo "box-{$alias}"?>">
|
626 |
+
<?php if ($title = $this->getChildData($alias, 'title')):?>
|
627 |
+
<h2><?php echo $this->escapeHtml($title); ?></h2>
|
628 |
+
<?php endif;?>
|
629 |
+
<?php echo $html; ?>
|
630 |
+
</div>
|
631 |
+
<?php endforeach;?>
|
632 |
+
<?php echo $this->getChildHtml('upsell_products') ?>
|
633 |
+
<?php echo $this->getChildHtml('product_additional_data') ?>
|
634 |
+
</div>
|
635 |
+
</div>
|
app/etc/modules/Blog4mail_Customproduct.xml
ADDED
@@ -0,0 +1,9 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<config>
|
3 |
+
<modules>
|
4 |
+
<Blog4mail_Customproduct>
|
5 |
+
<active>true</active>
|
6 |
+
<codePool>community</codePool>
|
7 |
+
</Blog4mail_Customproduct>
|
8 |
+
</modules>
|
9 |
+
</config>
|
media/finalimages/2b0e7ecb7dffaca13b2be8c6f4e5f89e.jpg
ADDED
Binary file
|
media/finalimages/46c4f93a056c2e11c45c301a0dda1da4.jpg
ADDED
Binary file
|
media/finalimages/8605d98db258cb59cd4a0bc5e1374104.jpg
ADDED
Binary file
|
media/finalimages/upload/50ef9eafe2774image1.jpeg
ADDED
Binary file
|
media/finalimages/upload/50ef9ef6b49aeimage1.jpeg
ADDED
Binary file
|
media/finalimages/upload/50ef9fa951afcimage1.jpeg
ADDED
Binary file
|
media/finalimages/upload/50efa5be9c0a0image1.jpeg
ADDED
Binary file
|
media/finalimages/upload/50f4f56c28bfdimage1.jpeg
ADDED
Binary file
|
media/finalimages/upload/50f4f56caf383image1.jpeg
ADDED
Binary file
|
media/finalimages/upload/50f4f5e7aa803image1.jpeg
ADDED
Binary file
|
media/finalimages/upload/50f4f71c53eecimage1.jpeg
ADDED
Binary file
|
package.xml
ADDED
@@ -0,0 +1,25 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
<?xml version="1.0"?>
|
2 |
+
<package>
|
3 |
+
<name>Blog4mails</name>
|
4 |
+
<version>1.0.0</version>
|
5 |
+
<stability>stable</stability>
|
6 |
+
<license uri="http://opensource.org/licenses/osl-3.0.php">Open Source</license>
|
7 |
+
<channel>community</channel>
|
8 |
+
<extends/>
|
9 |
+
<summary>Product design tools for online custom product development</summary>
|
10 |
+
<description>This custom product development tool helps in
|
11 |
+

|
12 |
+
1. Design the product image
|
13 |
+
2. Put some text on the image
|
14 |
+
3. It saves the perspective info of the product
|
15 |
+
4. Custom products created along with the custom options.
|
16 |
+

|
17 |
+
No support will be provided.</description>
|
18 |
+
<notes>Custom Product Design Tools, No Support Provided</notes>
|
19 |
+
<authors><author><name>blg4mail.com</name><user>oklovein</user><email>lovein.sales@gmail.com</email></author></authors>
|
20 |
+
<date>2013-01-14</date>
|
21 |
+
<time>00:52:13</time>
|
22 |
+
<contents><target name="magecommunity"><dir name="Blog4mail"><dir name="Customproduct"><dir name="Block"><file name="Customproduct.php" hash="a4899e23da7d9dae771c83a24c52a88e"/></dir><dir name="Helper"><file name="Data.php" hash="08503e586d976bebfa5cd1514e75252a"/></dir><dir name="Model"><file name="Customproduct.php" hash="318f77d3897c7414d3dca31e6e85d40c"/><dir name="Mysql4"><dir name="Customproduct"><file name="Collection.php" hash="3cd16a4a839db77e030e460a99d262a1"/></dir><file name="Customproduct.php" hash="1c65e603f80c74332fbf5f8be0cb92b2"/></dir><file name="Status.php" hash="00c86b88578549ac14b07c38464bc712"/></dir><dir name="controllers"><file name="IndexController.php" hash="f96519394f5b20b83409f2ecddc133eb"/><file name="IndexController.php~" hash="f96519394f5b20b83409f2ecddc133eb"/></dir><dir name="etc"><file name="config.xml" hash="6e6e8474d3d9ef34df839a98dc99b78f"/><file name="config.xml~" hash="6e6e8474d3d9ef34df839a98dc99b78f"/></dir><dir name="sql"><dir name="customproduct_setup"><file name="mysql4-install-1.0.0.php" hash="0dc4a56f5e1df4d08114ef15aab664aa"/><file name="mysql4-install-1.0.0.php~" hash="0dc4a56f5e1df4d08114ef15aab664aa"/><file name="mysql4-install-1.0.php~" hash="9fde8f4568409cbbf213710d9d4e53a1"/><file name="mysql4-upgrade-1.0-1.1.php~" hash="5506677e7dc6193d133a3001efad33c0"/><file name="mysql4-upgrade-1.3.4-1.4.php~" hash="5e7ac5dcfafbe474a9abced425c4e392"/></dir></dir></dir><dir name="Customproductadmin"><dir name="Block"><dir name="Customproduct"><dir name="Edit"><file name="Form.php" hash="0a1e5440f3bf0ea5d2f9daab579f5cee"/><dir name="Tab"><file name="Form.php" hash="8424855b71f54d8cbb03f8e3a0f6fa8d"/></dir><file name="Tabs.php" hash="1c91af75536c3e0a96b192049df86c4f"/></dir><file name="Edit.php" hash="dcf43fa99a11aab5f27f5a252aca785a"/><file name="Grid.php" hash="aa2fa7575446737c60f59549bdae2631"/></dir><file name="Customproduct.php" hash="3df8149185c3d4a568db8ee0b438cdd7"/></dir><dir name="Helper"><file name="Data.php" hash="65e1bdc90e4c6c85145e6316f20fec16"/></dir><dir name="controllers"><file name="CustomproductController.php" hash="9ca7d9d04e17d49b6ad12cd4322ceb07"/></dir><dir name="etc"><file name="config.xml" hash="68304389a8476c574263f0f37b73c9a4"/></dir></dir><file name="customproduct_catalog.xml~" hash="e57cdd5f8b92ba63a29aac9518d8654e"/></dir></target><target name="magedesign"><dir name="frontend"><dir name="base"><dir name="default"><dir name="template"><dir name="catalog"><dir name="product"><file name="view_custom.phtml" hash="30fbe9a8b0c60f2d2dede2f7d7a84723"/><dir name="view"><file name="media_custom.phtml" hash="8e38f9fd6ab720ca0ad5ed12b7695d10"/></dir></dir></dir></dir><dir name="layout"><file name="customproduct_catalog.xml" hash="b45f0d4d29a0e01a32d5f9c7c260f2f7"/></dir></dir></dir></dir></target><target name="magemedia"><dir name="finalimages"><file name="2b0e7ecb7dffaca13b2be8c6f4e5f89e.jpg" hash="8a8f8dd682b3db6790368d5c030c4bbd"/><file name="46c4f93a056c2e11c45c301a0dda1da4.jpg" hash="0db5fea3c4efaca76f0040f915cb7fa1"/><file name="8605d98db258cb59cd4a0bc5e1374104.jpg" hash="e4f30c8ecdb88a7bab105179f610811b"/><dir name="upload"><file name="50ef9eafe2774image1.jpeg" hash="3f4cbd39c8b42c17b71cf980707e1768"/><file name="50ef9ef6b49aeimage1.jpeg" hash="3f4cbd39c8b42c17b71cf980707e1768"/><file name="50ef9fa951afcimage1.jpeg" hash="3f4cbd39c8b42c17b71cf980707e1768"/><file name="50efa5be9c0a0image1.jpeg" hash="3f4cbd39c8b42c17b71cf980707e1768"/><file name="50f4f56c28bfdimage1.jpeg" hash="3f4cbd39c8b42c17b71cf980707e1768"/><file name="50f4f56caf383image1.jpeg" hash="3f4cbd39c8b42c17b71cf980707e1768"/><file name="50f4f5e7aa803image1.jpeg" hash="3f4cbd39c8b42c17b71cf980707e1768"/><file name="50f4f71c53eecimage1.jpeg" hash="3f4cbd39c8b42c17b71cf980707e1768"/></dir></dir></target><target name="mageskin"><dir name="frontend"><dir name="default"><dir name="customproduct"><dir><dir name="css"><file name="oauth-simple.css" hash="bf193322afc4112a25ae99d1137053e1"/><file name="print.css" hash="aafa75a7a320ecf563e63b9098beba05"/><file name="styles-ie.css" hash="ffe623005339241d8748054baad4e831"/><file name="styles.css" hash="6b0b4807578427ef9404540d6386fe25"/></dir><dir name="images"><file name="addtext.png" hash="91a5ff8c60c0d0b41ff5e8ca17409180"/><file name="best_selling_tr_even_bg.gif" hash="5022d648379090e306f00cd64738b146"/><file name="best_selling_tr_odd_bg.gif" hash="926622704f53796801bb5d097e116c8e"/><file name="bgimage.png" hash="50ad0d6300ff1c745db2e4f4ad8274cc"/><file name="bgimage7.png" hash="4e26bd58bcda18cb45cd2920d1447008"/><file name="bkg_account_box.gif" hash="dd98174b6e3e5605a3f9551a59c66841"/><file name="bkg_block-actions.gif" hash="da2970eac0a22c850b19ee3680475d51"/><file name="bkg_block-currency.gif" hash="bfaad1b64557c05ad6f4b124ad3d3532"/><file name="bkg_block-layered-dd.gif" hash="6ae6f8184e87de496fb74eeec65737c9"/><file name="bkg_block-layered-dt.gif" hash="ba8229068657b80f2c42111c5a1a307e"/><file name="bkg_block-layered-label.gif" hash="14687dfa3921cfd12d2149c1497d9765"/><file name="bkg_block-layered-li.gif" hash="753ebb76a4fc2b5b6915c536fcf4d487"/><file name="bkg_block-layered-title.gif" hash="c92e29b30af7abf4e0bc3f714a246f55"/><file name="bkg_block-layered1.gif" hash="607167f198572e83a0e728b6b9383a70"/><file name="bkg_block-title-account.gif" hash="a64f1df5a7e3d0f6a58b017f74311cb1"/><file name="bkg_block-title.gif" hash="f8c1f130ad69464fe7aff2f589b2ec75"/><file name="bkg_body.gif" hash="82bfc5bfe346c8e974cd33b1314b0acf"/><file name="bkg_buttons-set1.gif" hash="2c641e927bc83156b7004ea37920513c"/><file name="bkg_checkout.gif" hash="11258fe49feff5513c9608f2ea486776"/><file name="bkg_collapse-gm.gif" hash="37418f23e65006dcfde07ce9b249e057"/><file name="bkg_collapse.gif" hash="2333c68e38163ed4656da82b9bcf362b"/><file name="bkg_divider1.gif" hash="260ebae91ffb1b7c663906b29a069925"/><file name="bkg_form-search.gif" hash="2ca36eb80ea705e063409153f3821f78"/><file name="bkg_grand-total.gif" hash="10f1c3d82d78170706fa3e9c4baa7e04"/><file name="bkg_grid.gif" hash="a6f64fedbac51fb1b86184cd488cc4e6"/><file name="bkg_header.jpg" hash="0211c47be1493bd0ec72949c47932b81"/><file name="bkg_login-box.gif" hash="5538675d7f1c35d96a2b8013948f42a6"/><file name="bkg_main1.gif" hash="a8f5717873dc6cf8f6bd22924b5838fe"/><file name="bkg_main2.gif" hash="cf18ba9f7c7e6b058b439cde1a897e9c"/><file name="bkg_nav0.jpg" hash="f9ac3f31e293cf075471d2d3fe07353a"/><file name="bkg_nav1.gif" hash="f4e26840c8cca0e74aba5b810341c5c0"/><file name="bkg_nav2.gif" hash="a64c8f5165b239e432d26a62ae5f79b6"/><file name="bkg_opc-title-off.gif" hash="f69b40b5331ab3760f54d038daf287eb"/><file name="bkg_pipe1.gif" hash="7852290f6a443000ead96b8cec5cd7c7"/><file name="bkg_pipe2.gif" hash="7da64eefaf4da3855ab6ee76dbced0c2"/><file name="bkg_pipe3.gif" hash="11bfac1e590f0c77fb12f37d7f05cd3c"/><file name="bkg_product-view.gif" hash="7078a7f2827156d5ae0a1cb59da3c418"/><file name="bkg_product_collateral.gif" hash="1d4d6b22e5108aefae52709d3934f397"/><file name="bkg_rating.gif" hash="0a8777c815350ddf1e316a537ad0c335"/><file name="bkg_sp-methods.gif" hash="17d68b5449adaa87dafc62ae0afa1b9a"/><file name="bkg_tfoot.gif" hash="da2970eac0a22c850b19ee3680475d51"/><file name="bkg_th-v.gif" hash="b0d17555dfc6060941e0c067718189df"/><file name="bkg_th.gif" hash="f249911b08f2822fc0b561b7f98575d2"/><file name="bkg_toolbar.gif" hash="fb7ed019476eaa1643af922b59ede4fb"/><file name="btn_checkout.gif" hash="d2060501e14e86c29e28137130e5726e"/><file name="btn_edit.gif" hash="df3565eb4e4d0dc578201df60de54b47"/><file name="btn_gm-close.gif" hash="346e26eece27449a2f224aef76ae372e"/><file name="btn_google_checkout.gif" hash="843d75249ce05b5d87ca5419f37b1c3b"/><file name="btn_paypal_checkout.gif" hash="6edd61270b7b5632eafad10557129114"/><file name="btn_place_order.gif" hash="d35219f86ae2c983ee1a31557e37b612"/><file name="btn_previous.gif" hash="63473a1520a73bb0c9b47b685d17cd21"/><file name="btn_proceed_to_checkout.gif" hash="4daac687b514fecfd1068539500ac3d7"/><file name="btn_proceed_to_checkout_dis.gif" hash="9e152c01d5d88f690dc52cb62428f3b6"/><file name="btn_remove.gif" hash="6182e723aa2a253dc6cf334a3dfaaa84"/><file name="btn_remove2.gif" hash="234bddc4c5878c5ef16407a944824236"/><file name="btn_search.gif" hash="2d93b43c0a1c1182358677661e26a978"/><file name="btn_trash.gif" hash="bcb22f558a0eb32243a2a36645189e9f"/><file name="btn_window_close.gif" hash="c83f3cbbb2aedfc580dff78d5cfb63ed"/><file name="button1.png" hash="64be81dcc268ed39513ebdf31c463fb3"/><file name="button2.png" hash="2eaa97c0181145ebcba44b7045314546"/><file name="button3.png" hash="de022547c9533a127256b41f972cd64f"/><file name="calendar.gif" hash="b1468e5239504974c689eea5d93f86d4"/><dir name="catalog"><dir name="product"><dir name="placeholder"><file name="image.jpg" hash="097ab8a3051bc037ea3de0e17f440540"/><file name="small_image.jpg" hash="f825d16f97a640453553c79c48ebaa73"/><file name="thumbnail.jpg" hash="b2b682d28a08a748a73d2cda70ab5a57"/></dir></dir></dir><file name="cvv.gif" hash="83cdd38bf110b0f9c52fe84b56f45298"/><file name="cvv.jpg" hash="e27210d810bbab732935d9410936ef87"/><file name="fam_book_open.png" hash="0ba89b9fbe7e88d4c6896ed0a1f495aa"/><file name="free_shipping_callout.jpg" hash="cbf2e494ef7ca50acf8826321d739559"/><file name="grid-cal.gif" hash="b1468e5239504974c689eea5d93f86d4"/><file name="home_left_callout.jpg" hash="ee99a5586cf52e85c986d1275958a7da"/><file name="home_main_callout.jpg" hash="e6d1c119d5b24a5916fe394cb4b5cdc3"/><file name="i_arrow-top.gif" hash="3dbb0584e8eb1d96cc3d3c40c17d7aaf"/><file name="i_asc_arrow.gif" hash="40aa554212d6a1f60593c27d78d85fa3"/><file name="i_availability_only.gif" hash="bca1f00a50864171ad98317b778e869c"/><file name="i_availability_only_arrow.gif" hash="0cf32b72fefc94b89b74e4f3f02c2e93"/><file name="i_block-cart.gif" hash="cc19e21f9c89b70cc10354ff588ca8ab"/><file name="i_block-currency.gif" hash="643024bcae5ece554fdbbc041aeb297c"/><file name="i_block-list.gif" hash="fe8424127ecbe4b0d893bcf6f253dc1a"/><file name="i_block-poll.gif" hash="52d778dddbf48b8d04226bee9370a7ef"/><file name="i_block-related.gif" hash="4e277173b6372b1a90b0f19e0388ad54"/><file name="i_block-subscribe.gif" hash="9e5fee06a543742045118a95f2debcb8"/><file name="i_block-tags.gif" hash="67d1255c2c3e9ed1a5c845f8d4e4a3ba"/><file name="i_block-viewed.gif" hash="67d1255c2c3e9ed1a5c845f8d4e4a3ba"/><file name="i_block-wishlist.gif" hash="8f8cda89ca20ba4a9b2f8c91f73fdff9"/><file name="i_desc_arrow.gif" hash="92fd194bfae4ce5ae3354e1e47d7ac7d"/><file name="i_discount.gif" hash="908d44da90de5e54185764d093bbdb77"/><file name="i_folder-table.gif" hash="bf006ddb591d8ac95d2e895bf2fdbc8d"/><file name="i_ma-info.gif" hash="91259557447ee80eb1110fe0c85cb3b5"/><file name="i_ma-reviews.gif" hash="859c97695ec396c0b284a0c3c7c416ad"/><file name="i_ma-tags.gif" hash="1e83e3b0b677c92b3aa8a252268f7b86"/><file name="i_msg-error.gif" hash="e4f28607f075a105e53fa3113d84bd26"/><file name="i_msg-note.gif" hash="e774ee481a2820789c1a77112377c4e0"/><file name="i_msg-success.gif" hash="834dfafd5f8b44c4b24a4c00add56fcf"/><file name="i_notice.gif" hash="ebd56dc80b8346e10e93628bc0e6c372"/><file name="i_page1.gif" hash="704f7d4eccbdf9cabbad7770f18856ff"/><file name="i_page2.gif" hash="57a04ca584e05e28dc94c7e68f0af62e"/><file name="i_pager-next.gif" hash="ed4d6640624c2b6edeab4c212314bd6d"/><file name="i_pager-prev.gif" hash="75973b020105dccbaf34e49d7852552d"/><file name="i_print.gif" hash="0aed138181495642e9ab29e55d194d40"/><file name="i_rss-big.png" hash="6cf70e7c52a3f3d7b833ccadb041a555"/><file name="i_rss.gif" hash="e5bbc388d818c142868b4a1df0b48793"/><file name="i_search_criteria.gif" hash="cf67b9cc5c311ae3f99e68cd29ae17be"/><file name="i_shipping.gif" hash="91a0d2cc2eb2391f90ec8a75c04b3183"/><file name="i_tag_add.gif" hash="a736baa992aa55b6fb71e8742a04dc82"/><file name="i_tier.gif" hash="c5189e25afeb7c1a8c4902a42832593e"/><file name="i_type_grid.gif" hash="a1e5d8ac36fb2891ea16e729b95c552c"/><file name="i_type_list.gif" hash="61333d383ec142b8d270abe77324aa5d"/><file name="logo.gif" hash="48b7eb03807fdf80bdfb19b872cf84b8"/><file name="logo_email.gif" hash="8de347192e0524cff7a69e4020182dbd"/><file name="logo_print.gif" hash="8de347192e0524cff7a69e4020182dbd"/><file name="magnifier_handle.gif" hash="238fbdd7959f517db11c6f57ee4daaf4"/><file name="map_popup_arrow.gif" hash="6383b40a9e7bd3c95260bef4fbb1b163"/><dir name="media"><file name="404_callout1.jpg" hash="834e53a03e2921a2fd3c135c0c7189df"/><file name="404_callout2.jpg" hash="016984b4a1579df34147f9407098db73"/><file name="about_us_img.jpg" hash="726f36dd75b5a709a1a14acab1660188"/><file name="best_selling_img01.jpg" hash="5e7337a4061a636df8ee4bf979a092ac"/><file name="best_selling_img02.jpg" hash="b9a49c0964938ec72fb834cb166b9352"/><file name="best_selling_img03.jpg" hash="e3581487fb4589baecc553f2ce8d5247"/><file name="best_selling_img04.jpg" hash="7e59bf99f5f813e327595c52d3320174"/><file name="best_selling_img05.jpg" hash="e396892daec7ffcf7244082b3e596911"/><file name="best_selling_img06.jpg" hash="2702839637efbe0fd0a4bad41cd6a551"/><file name="cell_phone_landing_banner1.jpg" hash="b25562360fc470f1091ca7ea014a3290"/><file name="col_left_callout.jpg" hash="5f762006021e046f9bd536f37ea7c463"/><file name="col_right_callout.jpg" hash="dae22f37a542da272a35195ec286ec25"/><file name="electronics_cellphones.jpg" hash="8f6badbc32ce806c6109c788df6ef5e9"/><file name="electronics_digitalcameras.jpg" hash="953b8d7db6f0bdcd53b1d6b1386962b9"/><file name="electronics_laptops.jpg" hash="e050e92d72000e6bdc763a7b5888ec8a"/><file name="furniture_callout_spot.jpg" hash="28edc7d72486ab2362324995550d87af"/><file name="furnitures_bed_room.jpg" hash="b8616c5bffc23a92d2a1c97dae57b262"/><file name="furnitures_living_room.jpg" hash="2663737f3997cb1a49ce24d07dc8aefb"/><file name="head_electronics_cellphones.gif" hash="a69425966444ea597fb7c629114d5165"/><file name="head_electronics_digicamera.gif" hash="bde3cec3fc16b2d0ae57e7783eb00652"/><file name="head_electronics_laptops.gif" hash="b2c55387ffa92277315bdedeb4cb9b8f"/><file name="laptop_callout_mid1.jpg" hash="4ffb50bd3b7b32a78fd059b1571c202e"/><file name="laptop_callout_mid2.jpg" hash="662cf3881b06b090e9500496b19b03e4"/><file name="laptop_callout_mid3.jpg" hash="22aa71ecfe0aa9b6936a1eddb62d889e"/><file name="laptop_callout_spot.jpg" hash="2e469d1bd871355eaef6076487a973db"/><file name="shirts_landing_banner1.jpg" hash="4acc8620b009d835e5c25587671ea25d"/></dir><file name="np_cart_thumb.gif" hash="e9fdd943e0947e15f0638506f477e358"/><file name="np_more_img.gif" hash="ace357bfe3e81ffb62137cd5b25ae5e1"/><file name="np_product_main.gif" hash="d0cccda76de50efa025215ce85dacb1c"/><file name="np_thumb.gif" hash="e46270c89358ecc8341d1565c14644b8"/><file name="np_thumb2.gif" hash="8502866cdabc5c74aca7d7bd32a06a03"/><file name="opc-ajax-loader.gif" hash="e805ea7eca1f34c75ba0f93780d32d38"/><file name="pager_arrow_left.gif" hash="75973b020105dccbaf34e49d7852552d"/><file name="pager_arrow_right.gif" hash="ed4d6640624c2b6edeab4c212314bd6d"/><file name="ph_callout_left_rebel.jpg" hash="0ce8ad0026d8b8a83ed7acdf6209129b"/><file name="ph_callout_left_top.gif" hash="f17a036d75e5065eb76bafbb2c8ad7ff"/><file name="product_zoom_overlay_magnif.gif" hash="83834893e162221d6d9257fe67847370"/><file name="slider_bg.gif" hash="87bc1b46d87de4f6252c7216216627c3"/><file name="slider_btn_zoom_in.gif" hash="ef0fc67f77f30827ee67f4e744b60781"/><file name="slider_btn_zoom_out.gif" hash="68b3d1c28dc5aec4f6b64d70a6996b6f"/><file name="spacer.gif" hash="df3e567d6f16d040326c7a0ea29a4f41"/><file name="textimage.png" hash="99cee6b4075cdc3f659cc170fc4cc6fb"/><file name="validation_advice_bg.gif" hash="b85432906de8985a8b14eeb2dc652d3c"/><dir name="xmlconnect"><dir name="catalog"><dir name="category"><dir name="placeholder"><file name="image.jpg" hash="097ab8a3051bc037ea3de0e17f440540"/><file name="small_image.jpg" hash="f825d16f97a640453553c79c48ebaa73"/><file name="thumbnail.jpg" hash="b2b682d28a08a748a73d2cda70ab5a57"/></dir></dir></dir><file name="tab_account.png" hash="0498d73e47ed47179e5546dc15c17dc7"/><file name="tab_cart.png" hash="9055ba76e256a51d3fee53a8c41d5226"/><file name="tab_home.png" hash="07d0af93e167b9366d3d4fb3d6cdb31c"/><file name="tab_more.png" hash="b9fc21feb8d7655bc9c2985c37b0de2f"/><file name="tab_page.png" hash="ca05dbc42f944b8d4255f6675f6dd93a"/><file name="tab_search.png" hash="25e880eb2a4d06828e2e1c3f32d22400"/><file name="tab_shop.png" hash="fe602fc2e7093efef5ecc0b027a32d91"/></dir></dir><dir name="js"><dir name="Uize"><file name="blank.gif" hash="c5091c08fa2020c5eb3bf99e5271ef15"/><file name="blank.html" hash="abdc3d57a6ec1616e365fb7689984706"/></dir><file name="Uize.Array.Dupes.js" hash="2605a034d727a868da9cc3fe33016e2f"/><file name="Uize.Array.Order.js" hash="f5b2346f5036f79fdaba676ddb7712d2"/><file name="Uize.Array.Sort.js" hash="786de5604d9b61931c50d23e3c60f5b7"/><file name="Uize.Array.Util.js" hash="ebee5eb7a7336df125c5bdbfcdb2acb2"/><file name="Uize.Array.js" hash="08c89711d5644c5aeffc606def98f415"/><file name="Uize.Build.All.js" hash="dbf1223c34786c2d3a5748957f929839"/><file name="Uize.Build.AuditStrings.js" hash="6c82e075540a43c151e63caf35e3fe40"/><file name="Uize.Build.AutoScruncher.js" hash="20eaddfa858c867b930f76964450b603"/><file name="Uize.Build.ModuleInfo.js" hash="e882b4c00743ef8064b7351149fa47e5"/><file name="Uize.Build.NeatenJsFiles.js" hash="54daf16efe901b16af839f7a9481712a"/><file name="Uize.Build.RunUnitTest.js" hash="7c0e59adfa5bdf7d2586cb62e5d01f84"/><file name="Uize.Build.RunUnitTests.js" hash="cc9b837278611120574b6ca77e0b0559"/><file name="Uize.Build.Scruncher.js" hash="8adb053e62f0aa16be1ec4158b49bd1c"/><file name="Uize.Build.ServicesSetup.js" hash="ad38e34dd57bc26f8da7f2e0a1de28e4"/><file name="Uize.Build.UpdateCopyrightNotices.js" hash="4ec086a4a3e16b68401469565fdd4d42"/><file name="Uize.Build.Util.js" hash="d4d3a91bc1fb777b5003d0a6c04a9586"/><file name="Uize.Build.js" hash="7042720907c23e8091e8fd8186a2f436"/><file name="Uize.Class.Value.js" hash="02801703e3053612b9a88f492d449ab6"/><file name="Uize.Class.js" hash="440c5c3e1a3ce4b0fde0d7a0d79da981"/><file name="Uize.Color.js" hash="b500bafac7a8ac7c486f98d398b7628b"/><file name="Uize.Color.xCmyk.js" hash="e369244304866560cd3f4213429fd041"/><file name="Uize.Color.xHsv.js" hash="67288511ed209463ba1786c8ba77ed3a"/><file name="Uize.Color.xSvgColors.js" hash="bbbab4fac2710ed9e8277717749e82e8"/><file name="Uize.Color.xUtil.js" hash="120830b9a3ec50220f499c13dffb9726"/><file name="Uize.Comm.Ajax.js" hash="e92f0af5c156f2c0e1749162466fc73e"/><file name="Uize.Comm.Iframe.Upload.js" hash="d140b00e21f7284868dcec4817e0f082"/><file name="Uize.Comm.Iframe.js" hash="5a006dd035374955d479624f32ca4a90"/><file name="Uize.Comm.Script.js" hash="8e639bc2c0ba30f13e77f45f2274e2a0"/><file name="Uize.Comm.js" hash="fc989966aa1fe24c0294de88317fe144"/><file name="Uize.Cookie.js" hash="4c12b969f764cb638cca43bf8de63c42"/><file name="Uize.Curve.Mod.js" hash="736846b970802e66b86be133a9bda036"/><file name="Uize.Curve.Rubber.js" hash="5b7ecf63eae301c373e408fc9545c1cf"/><file name="Uize.Curve.js" hash="dddb9779cb9c5895039bc5399c8db49a"/><file name="Uize.Data.Combinations.js" hash="e7a8fa8d9c51ced46a1b75fa4435f654"/><file name="Uize.Data.Csv.js" hash="75c2701cd1aa42c5b22a4be1a50bed10"/><file name="Uize.Data.Matches.js" hash="97c416cc604f06f77efe7f082b03eee4"/><file name="Uize.Data.NameValueRecords.js" hash="bfa797833bd498ca6ab6f8925fbc8e82"/><file name="Uize.Data.PathsTree.CompactString.js" hash="5079a25ced34efa6b6af81bea7565086"/><file name="Uize.Data.PathsTree.js" hash="703a0e513d2a865512ac7b4509cc7e2b"/><file name="Uize.Data.Simple.js" hash="6acb8b496b441fbb6b3780610ed97c2e"/><file name="Uize.Data.js" hash="08146010df94771ddc7c9172061ed6e8"/><file name="Uize.Date.Formatter.js" hash="e1177f9dd79e45fc39871bfb1f6948d4"/><file name="Uize.Date.js" hash="a0da3e5ea55550aa5e9102b71630f420"/><file name="Uize.Doc.Simple.js" hash="0aea30ecaaa8a8bdd1bf28d9bc17c8d6"/><file name="Uize.Doc.Sucker.js" hash="1b4831b080bfee5d9e4adee0a0d1ef92"/><file name="Uize.Doc.js" hash="b28e65a2fbdc35f3a89bfb4b3d21fc45"/><file name="Uize.Fade.js" hash="26f63a5b9c58f0f313e8eac2788d583b"/><file name="Uize.Fade.xFactory.js" hash="2c637988ebada46d666e11e74154f29d"/><file name="Uize.Fade.xSeries.js" hash="b97c53ffd42f57ba09bc91ead96a54aa"/><file name="Uize.Fx.js" hash="ac4ad1651ed09b867ff9281b9a176020"/><file name="Uize.Fx.xShadows.js" hash="24dc5bdafef6c296be48c7ea5e2bb605"/><file name="Uize.Fx.xTextShadow.js" hash="ca5b15caf68a41776464f09df3da06f3"/><file name="Uize.Json.js" hash="49debbc4b15d905aaa141d5aefb9f154"/><file name="Uize.Node.Classes.js" hash="5ab3c6a387e654034f6742949776cd15"/><file name="Uize.Node.Event.js" hash="8b28521a3b2bbab491b7bedc27fa41d0"/><file name="Uize.Node.Form.js" hash="4832a2e819f330541923e2735c6ba1a6"/><file name="Uize.Node.Tree.js" hash="46ee8fafe4fe68aa7db84b5d38a19275"/><file name="Uize.Node.Util.js" hash="128161cff9158aafe18b5a001ea1e8cb"/><file name="Uize.Node.VirtualEvent.Edge.js" hash="305ee1c644e6f4fa58010be65a339a57"/><file name="Uize.Node.VirtualEvent.js" hash="aab1c842a71af4efea79a3249a9ddd6f"/><file name="Uize.Node.js" hash="a57439c5827744de5d06ed96153a11bc"/><file name="Uize.Service.Adapter.js" hash="ec590ae504d4b6df6a08a0ee78fcfaa7"/><file name="Uize.Service.js" hash="c3d303d918ad5cf7d2ebaa412b1a5ffd"/><file name="Uize.Services.FileSystem.js" hash="2ae1bc0d6755fafd2952fe9f98b1b0c7"/><file name="Uize.Services.FileSystemAdapter.js" hash="6ad53d5a4b72fc45180caefd116fdfcf"/><file name="Uize.Services.FileSystemNode.js" hash="224f87e8b4fd094aa254759bebe4c81f"/><file name="Uize.Services.FileSystemWsh.js" hash="34244dc38e1f5fd882010b80e2391b94"/><file name="Uize.Services.Setup.js" hash="897a17a1681e884d83722a3662eca1cc"/><file name="Uize.Services.js" hash="1fd4c1cddefc0804173fd7fde21e8336"/><file name="Uize.String.Builder.js" hash="4e04a3dc29a72979c6a4e219febbc15a"/><file name="Uize.String.Discombobulator.js" hash="605d0f3be806c876cff09bc6fa5fd96a"/><file name="Uize.String.Lines.js" hash="4d5e9de5ff500808a0878b9ae53ba686"/><file name="Uize.String.js" hash="23f04e1313ae010595e81a94c0702f49"/><file name="Uize.Template.Module.js" hash="7b535d6a29dd28ad6f31bb74334ec082"/><file name="Uize.Template.js" hash="5e20bf981e4e1d0e59db0ac44cead6ed"/><file name="Uize.Templates.Calculator.js.jst" hash="ff933acad671517ea778558587fb4d14"/><file name="Uize.Templates.Calendar.js.jst" hash="a024dfd9f2cd718cd97408563dd95599"/><file name="Uize.Templates.Collection.js.jst" hash="8439ae77db09bcd632812c74079e9e37"/><file name="Uize.Templates.CollectionItem.js.jst" hash="fa6d9a7144228d1ebe1c956f93e599cb"/><file name="Uize.Templates.ColorInfo.js.jst" hash="eaa43fcbceb53558d58f7d9ce13ed833"/><file name="Uize.Templates.HashTable.js.jst" hash="135f6fc53f3974a13c376ef00cb5cfcd"/><file name="Uize.Templates.List.js" hash="5e53b3addddf7cbf6aab38eb8362c0a4"/><file name="Uize.Templates.Log.js.jst" hash="058643979139db8cdf9cc8ccebaf2455"/><file name="Uize.Templates.SevenSegmentDisplay.js.jst" hash="4837d0c3efa65af73c8bddcb09a8047c"/><file name="Uize.Templates.SevenSegmentDisplayDimsCss.js.jst" hash="7d6dcef72823c9a6b710b983a5f541aa"/><file name="Uize.Templates.SimpleDoc.js.jst" hash="a81759f6ee9310ba4bb24d051478f5c6"/><file name="Uize.Templates.js" hash="d87ba12d0c350277385e6d097039032c"/><file name="Uize.Test.Performance.ArrayBuildingStyles.js" hash="fa939b8eade778207fceabd196ac199e"/><file name="Uize.Test.Performance.js" hash="c0170839f61d96f1401b28430cd00874"/><file name="Uize.Test.Uize.Array.Dupes.js" hash="b380f4e0a0165e4c1faa2f75389b045c"/><file name="Uize.Test.Uize.Array.Order.js" hash="df5ac939d9a49295997de0ad68ec08d8"/><file name="Uize.Test.Uize.Array.Sort.js" hash="340fe288d1e292ca5d9185e3b18babcc"/><file name="Uize.Test.Uize.Array.Util.js" hash="8e96eb5330e1c40943476db427a621e3"/><file name="Uize.Test.Uize.Array.js" hash="dae49751b1e4184ae55667b97fd86acb"/><file name="Uize.Test.Uize.Class.js" hash="14643d943cd716a24878d441402842c7"/><file name="Uize.Test.Uize.Data.Combinations.js" hash="f078d471bae368aaae769c584da9ca02"/><file name="Uize.Test.Uize.Data.Csv.js" hash="c244f341c3df8fb66ec6ce914495798e"/><file name="Uize.Test.Uize.Data.Matches.js" hash="a23223cefcf7ce0ccd2a8ca850fb2555"/><file name="Uize.Test.Uize.Data.NameValueRecords.js" hash="d6badf14d873a3bb9dcf556020092a72"/><file name="Uize.Test.Uize.Data.PathsTree.CompactString.js" hash="f98dfe140dda4e31d3aef4b641318efc"/><file name="Uize.Test.Uize.Data.PathsTree.js" hash="30230c513fee2ca55d65ccb1c090f2c1"/><file name="Uize.Test.Uize.Data.js" hash="9e9dbd0511e8e10d81714a615a2519c2"/><file name="Uize.Test.Uize.Date.Formatter.js" hash="51dbbff18d1683583277ba70ce73aada"/><file name="Uize.Test.Uize.Date.js" hash="59b453fc47414978af4378155bdc1761"/><file name="Uize.Test.Uize.Doc.js" hash="398a92bc6c5de58134cc053ef7a55f21"/><file name="Uize.Test.Uize.Node.Classes.js" hash="aee8d643f7866cb8f74f05d213fa96c6"/><file name="Uize.Test.Uize.Node.js" hash="7bbcd5a3ae301f38a454ea5e35fe00b1"/><file name="Uize.Test.Uize.Service.js" hash="99d24009b03b96e8d7d1395175d1c3a9"/><file name="Uize.Test.Uize.Services.FileSystem.js" hash="e88fbd6a625bf3f3a5f0d1e3b868471a"/><file name="Uize.Test.Uize.Services.js" hash="09f2dfdd50938d4ab44423445eb36881"/><file name="Uize.Test.Uize.String.Builder.js" hash="1979b7fc6bb170d58b1ede48e093c68e"/><file name="Uize.Test.Uize.String.Lines.js" hash="0a9dd0e8ec4bb8f28c17945b7f96b71d"/><file name="Uize.Test.Uize.String.js" hash="6ccbe2f949c4aa90e94c172928e989f3"/><file name="Uize.Test.Uize.Template.js" hash="cdba1c44705e0a31a7cc9db8013d9011"/><file name="Uize.Test.Uize.Templates.Calculator.js" hash="48832202adeaf2fc4402137702f519b6"/><file name="Uize.Test.Uize.Templates.Calendar.js" hash="2ec44950a78f8ba837ee6d007a5aa26d"/><file name="Uize.Test.Uize.Templates.Collection.js" hash="3cb6f2da0eb99f3e54140a1aad934344"/><file name="Uize.Test.Uize.Templates.CollectionItem.js" hash="e8da8e17d7a60382b0cd1623038b9bb2"/><file name="Uize.Test.Uize.Templates.ColorInfo.js" hash="f90b2e79c87414b9b661a6f0086b02b3"/><file name="Uize.Test.Uize.Templates.HashTable.js" hash="7993d5d485f2a5b53b0ce2e8d4ae06e7"/><file name="Uize.Test.Uize.Templates.List.js" hash="00bc530d57c0a7b0c292beb0fe4c6c2d"/><file name="Uize.Test.Uize.Templates.SevenSegmentDisplay.js" hash="4bc8621104266fac09ca71428eac895d"/><file name="Uize.Test.Uize.Templates.js" hash="661104ed8e52a95c41d5be480a472227"/><file name="Uize.Test.Uize.Url.js" hash="aadca3277d202102a0f2f89a5160ffad"/><file name="Uize.Test.Uize.Util.PropertyAdapter.js" hash="f9e5ef83850959dd2f18a33921389c6f"/><file name="Uize.Test.Uize.Util.js" hash="419290980e88b45916ea20a139ad0342"/><file name="Uize.Test.Uize.Xml.js" hash="0989621e5780520fbde99621a26e5ca1"/><file name="Uize.Test.Uize.js" hash="c9488d6c4cf632813abd6e0f8c797d33"/><file name="Uize.Test.js" hash="4f67fa8a938b3dd735d6776e0e5955cb"/><file name="Uize.Tooltip.js" hash="1b6b8343404896bf49adc00aaa60ae31"/><file name="Uize.Url.js" hash="e17663294a5bd33fbd2c5d8f85b2ee90"/><file name="Uize.Util.Coupler.js" hash="1d1faf8d2a747addebc76cf12185b990"/><file name="Uize.Util.Cycle.js" hash="0a51605ebf5443e49d020391bcef56bb"/><file name="Uize.Util.Needs.js" hash="d7af6d2b6bb2bc3521d1652662a442f2"/><file name="Uize.Util.Oop.js" hash="1735ef9dafc942f271aee4c5ee6d7982"/><file name="Uize.Util.PropertyAdapter.js" hash="0ecd21e1277bf641aa83ad4ef170f838"/><file name="Uize.Util.js" hash="c106bcf2a60f9bc47bae1738bcc3bfca"/><file name="Uize.Widget.AutoSuggest.js" hash="684f837ce54816bf89c4325ce51543ec"/><file name="Uize.Widget.AutoTooltip.js" hash="719ae9de278152f4603cecc7f90a46fb"/><file name="Uize.Widget.Bar.Progress.js" hash="3444278a000c46351e8f2ad102d0a805"/><file name="Uize.Widget.Bar.Slider.Plus.js" hash="6000e4c16226f26abf60904fc8a5d59d"/><file name="Uize.Widget.Bar.Slider.js" hash="252ff86e11921a650f5d01725bee7d7d"/><file name="Uize.Widget.Bar.Slider.xSkin.js" hash="68792b3d7a8cafa88626befe6e03fb1c"/><file name="Uize.Widget.Bar.js" hash="fe1639e0e510aecbe7a37d52a5133128"/><file name="Uize.Widget.Beam.js" hash="4962697e7b57a6e48f678486d5673535"/><file name="Uize.Widget.Bevel.js" hash="f17228fd6a8c77103121c121b1277aa4"/><file name="Uize.Widget.Button.Checkbox.js" hash="2cc0a2399823897bab12ce88d1877c15"/><file name="Uize.Widget.Button.Filter.js" hash="ddbf73e8a4b84348ed59895a0e7b6f56"/><file name="Uize.Widget.Button.Toggle.js" hash="1c5ce73d92e0b0fdc1a757a05e14aac4"/><file name="Uize.Widget.Button.ValueDisplay.Selector.js" hash="90ac28149da53fae8c72cf3390f5287f"/><file name="Uize.Widget.Button.ValueDisplay.js" hash="7649d0fa4d283f072d0036cd2d01bf39"/><file name="Uize.Widget.Button.js" hash="c25f09c7cd6b99887bceca24a732f004"/><file name="Uize.Widget.Calculator.js" hash="32bc1716532407cd31bff64fed45ea65"/><file name="Uize.Widget.Calendar.js" hash="55fe75fa2b3a2560835c2ee049d1353c"/><file name="Uize.Widget.Captcha.Recaptcha.js" hash="3eaf5433a8c1651ce3cd9bd0a61d3a48"/><file name="Uize.Widget.Captcha.js" hash="49ae6bf10357e59aa036d1476020fb43"/><file name="Uize.Widget.Collapsy.js" hash="92944e5556cf882b74cdbc7575b36748"/><file name="Uize.Widget.Collection.Dynamic.Table.js" hash="74f90d0a468e30b78cc4a91ebd5376dd"/><file name="Uize.Widget.Collection.Dynamic.js" hash="7456607a00882cbcadd80adedb2aaafe"/><file name="Uize.Widget.Collection.js" hash="8af1a4f1cefc1e6bf1182e50ebe87312"/><file name="Uize.Widget.CollectionItem.Zooming.js" hash="a9cd61bc4095b87b3180143a2e8f3790"/><file name="Uize.Widget.CollectionItem.js" hash="e6da3fa827bc2b13a5601e6641c704e4"/><file name="Uize.Widget.ColorCube.Draggable.js" hash="dc20c853e1e9ad5e69b7a2b0f9575f9a"/><file name="Uize.Widget.ColorCube.js" hash="3567ef1524750b09181b6733e252d45a"/><file name="Uize.Widget.ColorInfo.js" hash="46b8e0aad370f09b73f62ca153b60b5c"/><file name="Uize.Widget.ColorPicker.js" hash="4b4c8f06f1e06e84e268fb3cc78611f0"/><file name="Uize.Widget.Committer.js" hash="6abb30292f21efa330f0e4752dde15af"/><file name="Uize.Widget.Count.js" hash="29b6da3a51ae92dc6d2c5359b4449c97"/><file name="Uize.Widget.Dialog.Confirm.js" hash="89d1372f3d41603b85f1248c657b0433"/><file name="Uize.Widget.Dialog.Form.js" hash="2d8cff680a722db651996e3087d89787"/><file name="Uize.Widget.Dialog.Iframe.js" hash="05f18bdd45441900ec142ec1a4aa67d0"/><file name="Uize.Widget.Dialog.Picker.Date.js" hash="9b24799b06785b50dbbb32ab2814ab31"/><file name="Uize.Widget.Dialog.Picker.Palette.Selector.js" hash="33eb4f8baa7199aefce51db621f65969"/><file name="Uize.Widget.Dialog.Picker.Palette.js" hash="246e59f4cb9d490790ba570f59ba7498"/><file name="Uize.Widget.Dialog.Picker.js" hash="1895d3d3373e7ed2e6b55db4297dc5b3"/><file name="Uize.Widget.Dialog.js" hash="07159f8a77b430a6d1d85f30884fcdcd"/><file name="Uize.Widget.Dialog.xResizable.js" hash="4793bedce60eb093efc2936a83ae430c"/><file name="Uize.Widget.DirectionalPad.js" hash="a3c211fa2dc9ecdb9bb90dddd399fbeb"/><file name="Uize.Widget.Drag.Move.js" hash="70388cd99ad0039cb6f8db756daca093"/><file name="Uize.Widget.Drag.js" hash="5eca863ed769a37c92d617982559d385"/><file name="Uize.Widget.EdgeHugger.js" hash="08639316c55e3950cd49edf5b19e182e"/><file name="Uize.Widget.EggTimer.js" hash="65b625bf808ad7d6640260bb67d381b7"/><file name="Uize.Widget.FilterGroups.js" hash="deaf92ec5fd8b21f725f51c884c09772"/><file name="Uize.Widget.Fleeting.js" hash="801831ec57eda9b18648bb1b29c141e5"/><file name="Uize.Widget.Flip.js" hash="346efea4d0ad5902c2cefff48c0ddef9"/><file name="Uize.Widget.Form.js" hash="d38c4f5cd52c50330f8b85d1343fea69"/><file name="Uize.Widget.FormDialog.js" hash="bba8a84c1d6d60720a7bb8a176b6549d"/><file name="Uize.Widget.FormElement.Select.js" hash="84894c896ce368c4b7febcf39f3fafd8"/><file name="Uize.Widget.FormElement.Text.js" hash="e938163c1171575e807ec1c6be48d892"/><file name="Uize.Widget.FormElement.js" hash="d071aa3a89aeb86f8a394c30057c7c00"/><file name="Uize.Widget.FormElements.js" hash="38a361a71c97a8f8836e85e9443f1fd6"/><file name="Uize.Widget.FormWarnings.js" hash="2842c364ffa4e57e58aa140aec06e7e0"/><file name="Uize.Widget.HoverFader.js" hash="c8934610725dfa495c1df2a91b56d19d"/><file name="Uize.Widget.ImagePort.Draggable.js" hash="55e3dba289c3a417f86289d536fef6c1"/><file name="Uize.Widget.ImagePort.js" hash="d72a64a1758954db790a7cc6c51e4f58"/><file name="Uize.Widget.ImageWipe.js" hash="64d29ab6065fe70ff398470e1448fadc"/><file name="Uize.Widget.ImageWipe.xPresets.js" hash="2651f07264ec8630a8d8340bf49779b6"/><file name="Uize.Widget.InlinePicker.Selector.js" hash="1e61b68e7d99b18d89d77e70e31cc0be"/><file name="Uize.Widget.InlinePicker.js" hash="f7f628c4df9e26b41aba70a66b32f33e"/><file name="Uize.Widget.ListEditor.js" hash="da54c3e56a209134bda67498e7b67f2e"/><file name="Uize.Widget.Log.InstanceEvents.js" hash="85be92792f3c8e8377cd332f9ba04c23"/><file name="Uize.Widget.Log.js" hash="af71b604f1272ef90146a9a493d0e697"/><file name="Uize.Widget.MagView.js" hash="ecbb8a678d77c3e0cd72b788adbacd3f"/><file name="Uize.Widget.Mask.js" hash="ee2df8f9bc6a44cd77f1c7d516b555c4"/><file name="Uize.Widget.Options.Accordion.js" hash="5265fcce6b35b4df23342ea54625fea0"/><file name="Uize.Widget.Options.FilterGroup.js" hash="65b760469990f5e481fd7af0c2edeed4"/><file name="Uize.Widget.Options.Popup.js" hash="60673eae63ff6e7c18bca0420fa0f184"/><file name="Uize.Widget.Options.Selector.js" hash="ce04206d428442a16bc01164ba8723b3"/><file name="Uize.Widget.Options.Tabbed.Fading.js" hash="73c10e9926ce9e88f0dafe6da8742789"/><file name="Uize.Widget.Options.Tabbed.js" hash="91ea8e9b656fdf0048a253c57ccc3934"/><file name="Uize.Widget.Options.js" hash="abe6d60b515c9d20eb544123ce3ecb26"/><file name="Uize.Widget.Page.js" hash="6bf51ac69d6f5fa68d43bea0e7238c96"/><file name="Uize.Widget.Page.xDeferredLinks.js" hash="e2a8bfadee11fed31d61334933371157"/><file name="Uize.Widget.Pagination.js" hash="4629555122deec93d4885c1faac607f5"/><file name="Uize.Widget.Picker.Date.js" hash="d7fcc4eeb850c6122375e294050d049e"/><file name="Uize.Widget.Picker.Palette.Selector.js" hash="b6a517dc7c84d6cd33b8d4a75239b1be"/><file name="Uize.Widget.Picker.Palette.js" hash="f7c5c349bd214d47ed9ebe142f280999"/><file name="Uize.Widget.Picker.js" hash="6011a6328439663f3ade3215b30afd69"/><file name="Uize.Widget.Population.js" hash="37007ef7605f181ec80d649008e9b7f9"/><file name="Uize.Widget.PopupPalette.js" hash="24218815109de31621056d3d4d63fea7"/><file name="Uize.Widget.Resizer.Marquee.js" hash="df1dc7450ca3e7fa77dab9bcd1d4f2a9"/><file name="Uize.Widget.Resizer.js" hash="d90f8d1d2934c3ded89e0845e66d8f5e"/><file name="Uize.Widget.Scrolly.js" hash="99b748d67a9e69916fdf90fdbb595773"/><file name="Uize.Widget.SegmentDisplay.Seven.js" hash="3378f8a477c9be9cd34883ae86e8e97b"/><file name="Uize.Widget.SegmentDisplay.js" hash="2d0dda6ed3e0fded8a1288f8cba1b8d6"/><file name="Uize.Widget.SlideShow.AutoAdvance.WithSlideSelectors.js" hash="b9f7e8e08598ac6c2aecaa75c8824305"/><file name="Uize.Widget.SlideShow.AutoAdvance.js" hash="be8a1324d41a006d21a388cd8ccc98a5"/><file name="Uize.Widget.SlideShow.js" hash="bc2322fab4c8ee05ba0e8a3195e35dab"/><file name="Uize.Widget.Stretchy.js" hash="a9ed34f8d946a0c17905991b23bfcdd7"/><file name="Uize.Widget.Swap.Deck.js" hash="fcd1ae4fcd09b974ee0665c44952b2eb"/><file name="Uize.Widget.Swap.Html.js" hash="3c3d4892a731748402a056e91636df78"/><file name="Uize.Widget.Swap.Image.Cycle.js" hash="a37da1b39eb21a4922a4bf28a2aa52b5"/><file name="Uize.Widget.Swap.Image.js" hash="660c2c34ca514130b56e19d66c70ded3"/><file name="Uize.Widget.Swap.js" hash="b112d3c4a50969f602e1d3e0e657b2c8"/><file name="Uize.Widget.Swap.xPresets.js" hash="8fef5910da00a9d46f7e8e3228979e7c"/><file name="Uize.Widget.TableSort.js" hash="db24df257dd616ab9e62112235a40f03"/><file name="Uize.Widget.TextInput.js" hash="1b0ad7b77f34c92b11ab6efbdd599699"/><file name="Uize.Widget.ThumbZoom.js" hash="18d4addfce77a82ae42481de2ef66835"/><file name="Uize.Widget.Tree.List.js" hash="3cf22a03c696c3a894b1ac47c2c53e0d"/><file name="Uize.Widget.Tree.Menu.js" hash="94c182930d698c5a91d0f44fd16a2b54"/><file name="Uize.Widget.Tree.Select.js" hash="d48930fcc10c2679fd70860aeb87ab14"/><file name="Uize.Widget.Tree.js" hash="3e820fc724b5253080ff94dcc836af0e"/><file name="Uize.Widget.js" hash="c4d3b1ac01cd56a39975b9f7f6ffc72d"/><file name="Uize.Wsh.js" hash="21999977b560b676b368ca77164a750e"/><file name="Uize.Xml.js" hash="3de665c5430178f968b5c858573cab7c"/><file name="Uize.js" hash="4e27541f196b1c81287a341cbde48c02"/><file name="UizeSite.Build.BuildCodeSitemap.js" hash="b900b903c86eb092fb2797961422ed81"/><file name="UizeSite.Build.BuildIndexPages.js" hash="65a712a864df07065a00b8dafd0ebddb"/><file name="UizeSite.Build.BuildJsModules.js" hash="94596ddc025c8a2345643746073771a0"/><file name="UizeSite.Build.BuildPagesFromSourceCode.js" hash="e1090e251ac76144527fea7017af71da"/><file name="UizeSite.Build.BuildSimpleDataPages.js" hash="56d81f810f7f24bd6f1c27c35ee54b8f"/><file name="UizeSite.Build.BuildSimpleDocPages.js" hash="3c28605e53f088a496b92cfd3a4a9b65"/><file name="UizeSite.Build.BuildSotu.js" hash="6dcfde7a3e3ece45fecad7f46420f2c9"/><file name="UizeSite.Build.BuildStaticPages.js" hash="573dc8bb2aacc4351d85241be66f5e60"/><file name="UizeSite.Build.BuildWidgetPages.js" hash="b89b34e208552248d614ec95f8ba279b"/><file name="UizeSite.Build.Deploy.js" hash="02380a33bfee11ff3b96f96e30cf486e"/><file name="UizeSite.Build.File.js" hash="93f00f0f505a44a85ce4a2ab35adb91c"/><file name="UizeSite.Build.FileBuilders.js" hash="4a86214937c9d53c0f6948f8af7c5bfc"/><file name="UizeSite.Build.WebServer.js" hash="8da4777dce575600b47c54a116a17e81"/><file name="UizeSite.Build.js" hash="1d1f605928a760ee54af860ea2e61e9c"/><file name="UizeSite.Delve.js" hash="3cd5e298dfe5b9b96923a5e15339de4f"/><file name="UizeSite.Delve.library.js" hash="f3829dcd37f1aa456a6434fa2a945b18"/><file name="UizeSite.DelvePageWriter.js" hash="eaa3e60d7c1afbd70582b8a2467f8a3b"/><file name="UizeSite.DialogConfirm.js" hash="f0ba9906eae16d702a20897939a21a47"/><file name="UizeSite.DialogDate.js" hash="682f3d5c9dd428b2fd4446752e0a791e"/><file name="UizeSite.Page.Doc.js" hash="e1295d7746c4b9a485d73460ea7fd193"/><file name="UizeSite.Page.Doc.library.js" hash="7acafea6f8095519de9f4fae62febfe2"/><file name="UizeSite.Page.Example.Test.js" hash="68fb11e1a6700bb9e6236b68bf6d71cc"/><file name="UizeSite.Page.Example.Test.library.js" hash="64073d2e6b572af05be05d76b76f7730"/><file name="UizeSite.Page.Example.js" hash="a2b2a7870a691b04bbd4f46503eebeae"/><file name="UizeSite.Page.Example.library.js" hash="73ae4ecd9eadbd4a1411ec26089d7fe6"/><file name="UizeSite.Page.Home.js" hash="eda2104d78ccc9486f673413f869d4bb"/><file name="UizeSite.Page.Home.library.js" hash="fb16fd1f63b09392e70d72b4ab375dcc"/><file name="UizeSite.Page.Index.js" hash="d229b0b851b132ee0751f309d714c639"/><file name="UizeSite.Page.js" hash="42218e09bff5b732f322d1d83958f761"/><file name="UizeSite.Page.library.js" hash="6722ca479156e5796c9f589b64d10050"/><file name="UizeSite.ParamsInspector.InlinePresets.js" hash="085965463872eb0f64bc3b4d87b860b5"/><file name="UizeSite.ParamsInspector.js" hash="b8bd6ddb3462a5c32da0630588a03ab4"/><file name="UizeSite.SiteMap.js" hash="595cac7426e97889b7ab7e60d1db5609"/><file name="UizeSite.Templates.DataBar.js.jst" hash="8195b580a2783b5ec7ea2aa3d40dbf83"/><file name="UizeSite.Templates.DelvePageHtml.js.jst" hash="93638d97888d91e75c9ac4b499855242"/><file name="UizeSite.Templates.DelveUiHtml.js.jst" hash="3ab43de151b84c51cce6a1a4b5c96d7b"/><file name="UizeSite.Templates.Dialog.Confirm.js.jst" hash="55fb4bc147e2aff1685b4f6362859859"/><file name="UizeSite.Templates.Dialog.Picker.Date.js.jst" hash="5f20e03bff02569b04c5aa84d1d030e8"/><file name="UizeSite.Templates.Dialog.Picker.js.jst" hash="a480ff32113567ac9e394f922600d5b1"/><file name="UizeSite.Templates.Dialog.js.jst" hash="bd6f120b476ebb134d84184ca5206fcf"/><file name="UizeSite.Templates.Footer.js.jst" hash="5e9f474caa60a8a479a8def9027cd62c"/><file name="UizeSite.Templates.IndexPage.js.jst" hash="751936b4aaeab3a55b9f4c4bf6235bb9"/><file name="UizeSite.Templates.JavaScriptSourceSample.js.jst" hash="025b6cb45cb7efe697a0f70aa30ef5c8"/><file name="UizeSite.Templates.ListingsPage.js.jst" hash="72cf2ea4455c06d8d0c1fc468c6c29b0"/><file name="UizeSite.Templates.ParamsInspector.js.jst" hash="d507f30c1dead90d5d245119c93b15e2"/><file name="UizeSite.Templates.ParamsTable.js.jst" hash="50b060a9a11b0efd74ac19d027b71a31"/><file name="UizeSite.Templates.ShareThisPanel.js.jst" hash="2c8c4f4ee470d1e94805b8accfd18af0"/><file name="UizeSite.Templates.SimpleDoc.js.jst" hash="b488d018a6bea5507f08d001fd24104c"/><file name="UizeSite.Templates.SimpleDocSample.js.jst" hash="bc3b993b3eb3621afa72e15e738d815f"/><file name="UizeSite.Templates.SlideShow.Basic.js.jst" hash="e29ed3a34c54bd1d13ed63a4c161f8ad"/><file name="UizeSite.Templates.SlideShow.Wipes.js.jst" hash="0930fba6a62535a89f37dea015de48a0"/><file name="UizeSite.Templates.SlideShow.js.jst" hash="66790a98d00ff2683f401f2ad10e419b"/><file name="UizeSite.Templates.Tour.js.jst" hash="343ddf547cabd928f05b7b4692255860"/><file name="UizeSite.Templates.WidgetToGoTitle.js.jst" hash="383cba3644faa15f7a843e97c674fd52"/><file name="UizeSite.Templates.js" hash="61ff069ddd54e428f5f248ef6a29cfd5"/><file name="UizeSite.TestDataFruits.js" hash="c69ba8bcb281353abb252f5367a02281"/><file name="UizeSite.TestDataObject.js" hash="7d89d2661d681569690fe4824e691008"/><file name="UizeSite.TestDataPhotos.js" hash="fb9adda89d62bc18b9e5bb67a9012e66"/><file name="UizeSite.TestWidget.js" hash="70393268e03823b20a1dc8bd6594ebdb"/><file name="UizeSite.WidgetToGoPage.Calculator.js" hash="6dce02e686f470a89a7f14d1c5d2ac16"/><file name="UizeSite.WidgetToGoPage.Calculator.library.js" hash="5ebe568c1c131e1d7222bd835522ebaf"/><file name="UizeSite.WidgetToGoPage.Calendar.js" hash="d76511565dc8639bba268463563586af"/><file name="UizeSite.WidgetToGoPage.Calendar.library.js" hash="f3fd0f26f700ab8041872a4e1e986fce"/><file name="UizeSite.WidgetToGoPage.js" hash="97c1132816dee96416f324f6724d31a8"/><file name="UizeSite.js" hash="9e6b627355f541b234d05dc9373dcd59"/><dir name="Uize_Widget_Bar_Progress"><file name="full-bg.gif" hash="771b349d415e4efe149d7d0393ac641b"/><file name="track-bg.gif" hash="ae26c0f7db8323ebe167781577ff2361"/></dir><dir name="Uize_Widget_Bar_Slider"><file name="border-bl.gif" hash="26009df3315fcef416b7dc6a7d0a1ea6"/><file name="border-br.gif" hash="f53897b011a9e1245e9af1252c8426d9"/><file name="border-h.gif" hash="b61aff88496caefae9d40434978f1374"/><file name="border-tl.gif" hash="099d6f0e268455c1b327d3036df85b7b"/><file name="border-tr.gif" hash="4b083197a22be7f3331f93b507dd3d5a"/><file name="border-v.gif" hash="0fc328534e92fc3dd88e8b35e7e8cba1"/><file name="knob-horizontal.gif" hash="a3cb25cc375aa5fe2fa9dd2ba23731c7"/><file name="knob-vertical.gif" hash="74b36a675fe0e9cba79b22df8e144905"/><file name="track-bg-horizontal.gif" hash="c511fa1939358cbbc545192ff437c9f8"/><file name="track-bg-vertical.gif" hash="6c02d3d38a721bf25a3f8d1c0cea08b0"/></dir><dir name="Uize_Widget_Beam"><file name="diamond-bottom-left.gif" hash="9f99d89a94b28b6ce0a4d3b21322f78a"/><file name="diamond-bottom-right.gif" hash="2e0285b25f22922728cca6d14d8ccaee"/><file name="diamond-top-left.gif" hash="aae2068b2a1f3ccfda34b01a9ae6cf6d"/><file name="diamond-top-right.gif" hash="6c4bb7095a189f91bcbbd88cb387961e"/></dir><dir name="Uize_Widget_Tree_List"><file name="arrows-black-bullet.gif" hash="e0469e86364796a97293816881c65167"/><file name="arrows-black-collapsed.gif" hash="06bfc006a6a15e1b1ba37145db355c35"/><file name="arrows-black-expanded.gif" hash="e7507eac6e97c5e3310ef611f769a1e3"/><file name="arrows-black-on-white-bullet.gif" hash="cede143c398ce59695e6d15410099bb7"/><file name="arrows-black-on-white-collapsed.gif" hash="288ab5cad56c766cbef52982c2449d13"/><file name="arrows-black-on-white-expanded.gif" hash="a105a8394ee6cd019b187acbbf23188d"/><file name="arrows-bullet.gif" hash="73ccd239e28174ecae099f6496294704"/><file name="arrows-collapsed.gif" hash="c48397d4ac1d824100b9d1062529b113"/><file name="arrows-expanded.gif" hash="116f72fc1738318f5d7b26672a13ad96"/><file name="arrows-orange-bullet.gif" hash="fdc145d3895c04eb83fa8aa6c8f42d01"/><file name="arrows-orange-collapsed.gif" hash="df912cf9c86bcf6347192c14042f506e"/><file name="arrows-orange-expanded.gif" hash="b21cb063c6322546f6ffc88fc1fc6f1c"/><file name="plus-minus-bullet.gif" hash="b4b7b5d624885f79482c54cb8a3a08a1"/><file name="plus-minus-collapsed.gif" hash="2f82f3804044ea6b630b4df55cee430a"/><file name="plus-minus-expanded.gif" hash="db2ae2f7aa3fe83c7e364df57cc3bb7b"/></dir><file name="animals.js" hash="7857aa71a4a9872bc9ab3a55dd75ef18"/><file name="bootstrap-image-gallery.min.js" hash="8d0476e61ea2d0c7a42b9af420d764fe"/><file name="bootstrap.min.js" hash="266ba64fb1c21e3c743d0cce42f955f3"/><file name="canvas-to-blob.min.js" hash="f1b353d74742a0d0d8dba4a82f07c050"/><dir name="cors"><file name="jquery.postmessage-transport.js" hash="11fe256b13a09546f7280198d8e98239"/><file name="jquery.xdr-transport.js" hash="0927262e8bbd59ec33eda07237e6f19a"/></dir><file name="html5.js" hash="69431f1ec831bacf31013dff2872cba0"/><file name="jquery.fileupload-fp.js" hash="ccadbaf7dc309e09950eb4c06677d356"/><file name="jquery.fileupload-ui.js" hash="6cd54f58a3953ee8849d93b665b5ab51"/><file name="jquery.fileupload.js" hash="a3eeecf59ed91a98880370c8385c869f"/><file name="jquery.iframe-transport.js" hash="64c4919f8d8d06d25f1174f11d7a14e4"/><file name="jquery183.js" hash="b25b0460d7ddea993dad32005f56d255"/><file name="load-image.min.js" hash="6d3317f8c6fe137a18e720dc0a79a8d1"/><file name="main.js" hash="f1ecba9477cc6e3242d26f751ddcbe8c"/><file name="plants.js" hash="d27d443afe7ecf25ea46cf6f0ad33989"/><file name="tmpl.min.js" hash="411df7e2bc659d35015f7fdb7432b331"/><dir name="vendor"><file name="jquery.ui.widget.js" hash="acc1687c624523c960fb56c5c67f1442"/></dir><dir name="~experimental"><file name="Uize.Color.xSvgColorNames.js" hash="8b33ca3ea12f3cf75190831be0eee1fd"/><file name="Uize.Widget.Button-touch1.js" hash="5df5bd3d608820c6a8d21c0eaa0197ec"/><file name="Uize.Widget.Button-touch2.js" hash="c92d3b3ea2c90fe1bcff889ed425cbb5"/><file name="Uize.Widget.Button-touch3.js" hash="3b2fd34fd2a7fec5f43d997185197a8c"/><file name="Uize.Widget.ImagePort.AutoPan.js" hash="0ea22a5e725f6aa5de970e494bf63362"/><file name="Uize.Widget.Page.js" hash="04ed8eb10923f070924bfb6635b59c5b"/><file name="Uize.Widget.Pagination.js" hash="c998fabad59bb27c7413c05d45f3cd7c"/><file name="Uize.Widget.js" hash="dc74ca75b94c8ef7d48126f4b188c27a"/></dir></dir></dir><file name="favicon.ico" hash="88733ee53676a47fc354a61c32516e82"/></dir></dir></dir></target><target name="mageetc"><dir name="modules"><file name="Blog4mail_Customproduct.xml" hash="453fb0d6f4a3fd6394b708d2c08bafed"/></dir></target></contents>
|
23 |
+
<compatible/>
|
24 |
+
<dependencies><required><php><min>5.2.0</min><max>6.0.0</max></php><package><name></name><channel>connect.magentocommerce.com/core</channel><min></min><max></max></package><extension><name>imagick</name><min></min><max></max></extension><extension><name>gd</name><min></min><max></max></extension></required></dependencies>
|
25 |
+
</package>
|
skin/frontend/default/customproduct/css/oauth-simple.css
ADDED
@@ -0,0 +1,239 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* Magento
|
3 |
+
*
|
4 |
+
* NOTICE OF LICENSE
|
5 |
+
*
|
6 |
+
* This source file is subject to the Academic Free License (AFL 3.0)
|
7 |
+
* that is bundled with this package in the file LICENSE_AFL.txt.
|
8 |
+
* It is also available through the world-wide-web at this URL:
|
9 |
+
* http://opensource.org/licenses/afl-3.0.php
|
10 |
+
* If you did not receive a copy of the license and are unable to
|
11 |
+
* obtain it through the world-wide-web, please send an email
|
12 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
13 |
+
*
|
14 |
+
* DISCLAIMER
|
15 |
+
*
|
16 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
17 |
+
* versions in the future. If you wish to customize Magento for your
|
18 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
19 |
+
*
|
20 |
+
* @category design
|
21 |
+
* @package default_default
|
22 |
+
* @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
|
23 |
+
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
24 |
+
*/
|
25 |
+
|
26 |
+
/* Reset ================================================================================= */
|
27 |
+
* { margin:0; padding:0; }
|
28 |
+
body { background:#496778 50% 0 repeat-y; font:12px/1.55 Arial, Helvetica, sans-serif; color:#2f2f2f; text-align:center; }
|
29 |
+
img { border:0; vertical-align:top; }
|
30 |
+
a { color:#1e7ec8; text-decoration:underline; }
|
31 |
+
a:hover { text-decoration:none; }
|
32 |
+
:focus { outline:0; }
|
33 |
+
|
34 |
+
/* Headings */
|
35 |
+
h1,h2,h3,
|
36 |
+
h4,h5,h6 { margin:0 0 5px; line-height:1.35; color:#0a263c; }
|
37 |
+
h1 { font-size:20px; font-weight:normal; }
|
38 |
+
h2 { font-size:18px; font-weight:normal; }
|
39 |
+
h3 { font-size:16px; font-weight:bold; }
|
40 |
+
h4 { font-size:14px; font-weight:bold; }
|
41 |
+
h5 { font-size:12px; font-weight:bold; }
|
42 |
+
h6 { font-size:11px; font-weight:bold; }
|
43 |
+
|
44 |
+
/* Forms */
|
45 |
+
form { display:inline; }
|
46 |
+
fieldset { border:0; }
|
47 |
+
legend { display:none; }
|
48 |
+
|
49 |
+
/* Table */
|
50 |
+
table { border:0; /*border-collapse:collapse;*/ border-spacing:0; empty-cells:show; font-size:100%; }
|
51 |
+
caption,th,td { vertical-align:top; text-align:left; font-weight:normal; }
|
52 |
+
|
53 |
+
/* Content */
|
54 |
+
p { margin:0 0 10px; }
|
55 |
+
strong { font-weight:bold; }
|
56 |
+
address { font-style:normal; line-height:1.35; }
|
57 |
+
cite { font-style:normal; }
|
58 |
+
q,
|
59 |
+
blockquote { quotes:none; }
|
60 |
+
q:before,
|
61 |
+
q:after { content:''; }
|
62 |
+
small,big { font-size:1em; }
|
63 |
+
/*sup { font-size:1em; vertical-align:top; }*/
|
64 |
+
|
65 |
+
/* Lists */
|
66 |
+
ul,ol { list-style:none; }
|
67 |
+
|
68 |
+
/* Tools */
|
69 |
+
.hidden { display:block !important; border:0 !important; margin:0 !important; padding:0 !important; font-size:0 !important; line-height:0 !important; width:0 !important; height:0 !important; overflow:hidden !important; }
|
70 |
+
.nobr { white-space:nowrap !important; }
|
71 |
+
.wrap { white-space:normal !important; }
|
72 |
+
.a-left { text-align:left !important; }
|
73 |
+
.a-center { text-align:center !important; }
|
74 |
+
.a-right { text-align:right !important; }
|
75 |
+
.v-top { vertical-align:top; }
|
76 |
+
.v-middle { vertical-align:middle; }
|
77 |
+
.f-left,
|
78 |
+
.left { float:left !important; }
|
79 |
+
.f-right,
|
80 |
+
.right { float:right !important; }
|
81 |
+
.f-none { float:none !important; }
|
82 |
+
.f-fix { float:left; width:100%; }
|
83 |
+
.no-display { display:none; }
|
84 |
+
.no-margin { margin:0 !important; }
|
85 |
+
.no-padding { padding:0 !important; }
|
86 |
+
.no-bg { background:none !important; }
|
87 |
+
/* ======================================================================================= */
|
88 |
+
|
89 |
+
/* Default styles ======================================================================== */
|
90 |
+
/* boxes.css*/
|
91 |
+
.notification-global {
|
92 |
+
background: url("./../images/error_msg_icon.gif") no-repeat scroll 27px 5px #FFF9E9;
|
93 |
+
border-bottom: 1px solid #EEE2BE;
|
94 |
+
border-top: 1px solid #EEE2BE;
|
95 |
+
color: #444444;
|
96 |
+
font-size: 11px;
|
97 |
+
line-height: 16px;
|
98 |
+
margin: 0 0 -3px;
|
99 |
+
padding: 5px 27px 5px 47px;
|
100 |
+
position: relative;
|
101 |
+
}
|
102 |
+
.notification-global-notice {
|
103 |
+
background-image: url("./../images/note_msg_icon.gif");
|
104 |
+
}
|
105 |
+
.notification-global .label {
|
106 |
+
color: #EB5E00;
|
107 |
+
}
|
108 |
+
.notification-global .clickable {
|
109 |
+
cursor: pointer;
|
110 |
+
}
|
111 |
+
.notification-global span.critical {
|
112 |
+
color: #D20000;
|
113 |
+
}
|
114 |
+
.notification-global a:hover {
|
115 |
+
text-decoration: none;
|
116 |
+
}
|
117 |
+
.error, a.error span, .required, .validation-advice {
|
118 |
+
color: #D40707 !important;
|
119 |
+
font-weight: bold !important;
|
120 |
+
}
|
121 |
+
.notice {
|
122 |
+
color: #EA7601;
|
123 |
+
}
|
124 |
+
.messages ul {
|
125 |
+
border: 0 none !important;
|
126 |
+
}
|
127 |
+
.messages li {
|
128 |
+
font-size: 0.95em !important;
|
129 |
+
font-weight: bold !important;
|
130 |
+
margin-bottom: 11px !important;
|
131 |
+
min-height: 23px !important;
|
132 |
+
padding: 8px 8px 2px 32px !important;
|
133 |
+
}
|
134 |
+
.messages ul li {
|
135 |
+
border: 0 none !important;
|
136 |
+
margin: 0 0 3px !important;
|
137 |
+
padding: 0 !important;
|
138 |
+
}
|
139 |
+
.error-msg {
|
140 |
+
background: url("./../images/error_msg_icon.gif") no-repeat scroll 10px 10px #FAEBE7 !important;
|
141 |
+
border: 1px solid #F16048 !important;
|
142 |
+
color: #DF280A !important;
|
143 |
+
}
|
144 |
+
.success-msg {
|
145 |
+
background: url("./../images/success_msg_icon.gif") no-repeat scroll 10px 10px #EFF5EA !important;
|
146 |
+
border: 1px solid #95A486 !important;
|
147 |
+
color: #3D6611 !important;
|
148 |
+
}
|
149 |
+
.notice-msg {
|
150 |
+
background: url("./../images/note_msg_icon.gif") no-repeat scroll 10px 10px #FFFBF0 !important;
|
151 |
+
border: 1px solid #FFD967 !important;
|
152 |
+
color: #3D6611 !important;
|
153 |
+
}
|
154 |
+
.warning-msg {
|
155 |
+
background: url("./../images/warning_msg_icon.gif") no-repeat scroll 10px 10px #E6E6E6 !important;
|
156 |
+
border: 1px solid #666E73 !important;
|
157 |
+
color: #000000 !important;
|
158 |
+
}
|
159 |
+
|
160 |
+
button:hover, .form-button:hover {
|
161 |
+
background: #F77C16;
|
162 |
+
}
|
163 |
+
button:active, .form-button:active {
|
164 |
+
background: #F77C16;
|
165 |
+
}
|
166 |
+
button span {
|
167 |
+
background-position: 0 50%;
|
168 |
+
background-repeat: no-repeat;
|
169 |
+
line-height: 1.35em;
|
170 |
+
}
|
171 |
+
button span span {
|
172 |
+
background: none repeat scroll 0 0 transparent !important;
|
173 |
+
display: inline !important;
|
174 |
+
margin: 0 !important;
|
175 |
+
padding: 0 !important;
|
176 |
+
}
|
177 |
+
|
178 |
+
|
179 |
+
input.input-text, textarea, select {
|
180 |
+
background: none repeat scroll 0 0 #FFFFFF;
|
181 |
+
border-color: #AAAAAA #C8C8C8 #C8C8C8 #AAAAAA;
|
182 |
+
border-style: solid;
|
183 |
+
border-width: 1px;
|
184 |
+
font: 12px arial,helvetica,sans-serif;
|
185 |
+
}
|
186 |
+
input.input-text, textarea {
|
187 |
+
padding: 2px;
|
188 |
+
}
|
189 |
+
button, .form-button {
|
190 |
+
background: #FFAC47;
|
191 |
+
border-color: #ED6502 #A04300 #A04300 #ED6502;
|
192 |
+
border-style: solid;
|
193 |
+
border-width: 1px;
|
194 |
+
color: #FFFFFF;
|
195 |
+
cursor: pointer;
|
196 |
+
font: bold 12px arial,helvetica,sans-serif;
|
197 |
+
padding: 0 7px 1px;
|
198 |
+
text-align: center !important;
|
199 |
+
white-space: nowrap;
|
200 |
+
}
|
201 |
+
/* ======================================================================================= */
|
202 |
+
|
203 |
+
|
204 |
+
*, html {text-align: left;}
|
205 |
+
|
206 |
+
h1 {
|
207 |
+
color: #D12C01;
|
208 |
+
font-size: 22px;
|
209 |
+
font-weight: normal;
|
210 |
+
margin: 0;
|
211 |
+
text-align: left;
|
212 |
+
}
|
213 |
+
|
214 |
+
h2 {
|
215 |
+
color: #444444;
|
216 |
+
font: 16px Arial,Helvetica,sans-serif;
|
217 |
+
margin: 0 0 5px;
|
218 |
+
text-align: left;
|
219 |
+
}
|
220 |
+
|
221 |
+
body,
|
222 |
+
.main-container,
|
223 |
+
.header-container {background: none;}
|
224 |
+
|
225 |
+
.header-simple {height: 60px; text-align: left; padding: 10px 10px 0 10px; border-bottom: 1px solid #CFCFCF;}
|
226 |
+
.header-top img {height: 60px;}
|
227 |
+
|
228 |
+
.login-box > div {padding: 10px;}
|
229 |
+
.page-title {margin-bottom: 0; border-bottom: 1px solid #CFCFCF;}
|
230 |
+
|
231 |
+
.form-box {border-bottom: 1px solid #CFCFCF;}
|
232 |
+
.form-box .fieldset, .form-box fieldset {width: 320px; margin: 0 auto;}
|
233 |
+
|
234 |
+
.input-box {margin-bottom: 10px;}
|
235 |
+
.input-box label {width: 95px; font-weight: bold; display: block; float: left; text-align: right; padding-right: 10px;}
|
236 |
+
.input-box input {width: 209px;}
|
237 |
+
|
238 |
+
.required {font-weight: normal; color: #D40707 !important; font-size: 11px;}
|
239 |
+
.form-buttons {text-align: right;}
|
skin/frontend/default/customproduct/css/print.css
ADDED
@@ -0,0 +1,40 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* Magento
|
3 |
+
*
|
4 |
+
* NOTICE OF LICENSE
|
5 |
+
*
|
6 |
+
* This source file is subject to the Academic Free License (AFL 3.0)
|
7 |
+
* that is bundled with this package in the file LICENSE_AFL.txt.
|
8 |
+
* It is also available through the world-wide-web at this URL:
|
9 |
+
* http://opensource.org/licenses/afl-3.0.php
|
10 |
+
* If you did not receive a copy of the license and are unable to
|
11 |
+
* obtain it through the world-wide-web, please send an email
|
12 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
13 |
+
*
|
14 |
+
* DISCLAIMER
|
15 |
+
*
|
16 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
17 |
+
* versions in the future. If you wish to customize Magento for your
|
18 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
19 |
+
*
|
20 |
+
* @category design
|
21 |
+
* @package default_default
|
22 |
+
* @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
|
23 |
+
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
24 |
+
*/
|
25 |
+
* { background:none !important; text-align:left !important; }
|
26 |
+
html { margin:0 !important; padding:0 !important; }
|
27 |
+
body { background:#fff !important; font-size:9pt !important; padding:0 !important; margin:10px !important; }
|
28 |
+
a { color:#2976c9 !important; }
|
29 |
+
th,td { color:#2f2f2f !important; border-color:#ccc !important; }
|
30 |
+
|
31 |
+
.header-container,
|
32 |
+
.nav-container,
|
33 |
+
.footer-container,
|
34 |
+
.pager,
|
35 |
+
.toolbar,
|
36 |
+
.actions,
|
37 |
+
.buttons-set { display:none !important; }
|
38 |
+
|
39 |
+
.page-print .data-table .cart-tax-total { background-position:100% -54px; }
|
40 |
+
.page-print .data-table .cart-tax-info { display:block !important; }
|
skin/frontend/default/customproduct/css/styles-ie.css
ADDED
@@ -0,0 +1,149 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* Magento
|
3 |
+
*
|
4 |
+
* NOTICE OF LICENSE
|
5 |
+
*
|
6 |
+
* This source file is subject to the Academic Free License (AFL 3.0)
|
7 |
+
* that is bundled with this package in the file LICENSE_AFL.txt.
|
8 |
+
* It is also available through the world-wide-web at this URL:
|
9 |
+
* http://opensource.org/licenses/afl-3.0.php
|
10 |
+
* If you did not receive a copy of the license and are unable to
|
11 |
+
* obtain it through the world-wide-web, please send an email
|
12 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
13 |
+
*
|
14 |
+
* DISCLAIMER
|
15 |
+
*
|
16 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
17 |
+
* versions in the future. If you wish to customize Magento for your
|
18 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
19 |
+
*
|
20 |
+
* @category design
|
21 |
+
* @package default_default
|
22 |
+
* @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
|
23 |
+
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
24 |
+
*/
|
25 |
+
|
26 |
+
/* IE 6 only */
|
27 |
+
* html .validation-advice { height:13px; }
|
28 |
+
* html .error-msg,
|
29 |
+
* html .success-msg,
|
30 |
+
* html .note-msg,
|
31 |
+
* html .notice-msg { height:24px; }
|
32 |
+
* html .main { height:400px; }
|
33 |
+
* html .account-login .content { height:240px; }
|
34 |
+
.block li.item,
|
35 |
+
.block-poll li,
|
36 |
+
.opc li.section { vertical-align:top; }
|
37 |
+
* html .window-overlay { background:#ccc; filter:alpha(opacity=50); }
|
38 |
+
|
39 |
+
/* Doubled Margin Fixes */
|
40 |
+
.product-view .product-img-box .more-views li,
|
41 |
+
.product-view .box-tags .form-add .input-box,
|
42 |
+
.sp-methods select.month { display:inline; }
|
43 |
+
|
44 |
+
/********** < Navigation styles */
|
45 |
+
#nav li,
|
46 |
+
#nav li a { zoom:1; }
|
47 |
+
#nav li { vertical-align:top; }
|
48 |
+
/********** < Navigation styles */
|
49 |
+
|
50 |
+
select { margin-bottom:1px; }
|
51 |
+
input.radio { width:13px; height:13px; }
|
52 |
+
input.checkbox { width:13px; height:13px; }
|
53 |
+
button.button { height:21px; }
|
54 |
+
button.button span { position:relative; }
|
55 |
+
button.btn-checkout { height:40px; }
|
56 |
+
#opc-review .sp-methods .input-box { float:left; }
|
57 |
+
.form-list label { position:relative; z-index:0; }
|
58 |
+
.form-list label.required em { position:absolute; top:0; right:-8px; }
|
59 |
+
|
60 |
+
table { scrollbar-face-color:expression(runtimeStyle.scrollbarFaceColor = '#fff', cellSpacing = 0); }
|
61 |
+
|
62 |
+
.product-view .product-img-box .zoom.disabled { filter:alpha(opacity=30); }
|
63 |
+
|
64 |
+
.gift-messages-form { position:relative; zoom:1; }
|
65 |
+
|
66 |
+
.tool-tip .btn-close a { margin:0; }
|
67 |
+
|
68 |
+
.product-view .box-tags .product-tags li,
|
69 |
+
.footer li { padding:0 4px 0 7px; }
|
70 |
+
|
71 |
+
.product-options dd .time-picker select { margin:0; padding:0; }
|
72 |
+
|
73 |
+
/* Clearer */
|
74 |
+
.clearer { display:block; clear:both; font-size:0; line-height:0; height:0; overflow:hidden; }
|
75 |
+
|
76 |
+
/* Clears and hasLayout fixes */
|
77 |
+
.header-container,
|
78 |
+
.header-container .top-container,
|
79 |
+
.header,
|
80 |
+
.header .quick-access,
|
81 |
+
#nav,
|
82 |
+
.main,
|
83 |
+
.footer,
|
84 |
+
.footer-container .bottom-container,
|
85 |
+
.col-main,
|
86 |
+
.col2-set,
|
87 |
+
.col3-set,
|
88 |
+
.col3-layout .product-options-bottom .price-box,
|
89 |
+
.col4-set,
|
90 |
+
.messages li,
|
91 |
+
.search-autocomplete li,
|
92 |
+
.block,
|
93 |
+
.block .block-content,
|
94 |
+
.block .actions,
|
95 |
+
.block li.item,
|
96 |
+
.block-poll li,
|
97 |
+
.block-poll .label,
|
98 |
+
.block-layered-nav .currently li,
|
99 |
+
.block-account .block-content li a,
|
100 |
+
.mini-products-list .product-details,
|
101 |
+
.page-title,
|
102 |
+
.rss-title h1,
|
103 |
+
.products-grid,
|
104 |
+
.products-list li.item,
|
105 |
+
.box-account .box-head,
|
106 |
+
.dashboard .box .box-title,
|
107 |
+
.box-reviews li.item,
|
108 |
+
.box-tags li.item,
|
109 |
+
.pager,
|
110 |
+
.sorter,
|
111 |
+
.ratings,
|
112 |
+
.add-to-box,
|
113 |
+
.add-to-cart,
|
114 |
+
.product-essential,
|
115 |
+
.product-collateral,
|
116 |
+
.product-view .product-img-box .more-views ul,
|
117 |
+
.product-view .box-tags .form-add,
|
118 |
+
.product-view .product-shop .short-description,
|
119 |
+
.product-view .box-description,
|
120 |
+
.product-options .options-list li,
|
121 |
+
.product-options,
|
122 |
+
.product-options-bottom,
|
123 |
+
.truncated,
|
124 |
+
.truncated .truncated_full_value,
|
125 |
+
.product-review,
|
126 |
+
.cart,
|
127 |
+
.cart-collaterals,
|
128 |
+
.cart .crosssell li.item,
|
129 |
+
.cart .discount,
|
130 |
+
.opc .step-title,
|
131 |
+
.opc .step,
|
132 |
+
.multiple-checkout,
|
133 |
+
.sp-methods,
|
134 |
+
.checkout-progress,
|
135 |
+
.multiple-checkout .place-order,
|
136 |
+
.form-list li,
|
137 |
+
.form-list .field,
|
138 |
+
.group-select li,
|
139 |
+
.buttons-set,
|
140 |
+
.page-print .print-head,
|
141 |
+
.cart-tax-total,
|
142 |
+
.advanced-search-summary,
|
143 |
+
.advanced-search-summary p,
|
144 |
+
.gift-messages-form .item,
|
145 |
+
.send-friend .form-list li p,
|
146 |
+
.centinel .authentication { zoom:1; }
|
147 |
+
|
148 |
+
/* Hover Fix */
|
149 |
+
iframe.hover-fix { position:absolute; left:-1px; top:-1px; z-index:-1; background:transparent; filter:progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0); }
|
skin/frontend/default/customproduct/css/styles.css
ADDED
@@ -0,0 +1,1788 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/**
|
2 |
+
* Magento
|
3 |
+
*
|
4 |
+
* NOTICE OF LICENSE
|
5 |
+
*
|
6 |
+
* This source file is subject to the Academic Free License (AFL 3.0)
|
7 |
+
* that is bundled with this package in the file LICENSE_AFL.txt.
|
8 |
+
* It is also available through the world-wide-web at this URL:
|
9 |
+
* http://opensource.org/licenses/afl-3.0.php
|
10 |
+
* If you did not receive a copy of the license and are unable to
|
11 |
+
* obtain it through the world-wide-web, please send an email
|
12 |
+
* to license@magentocommerce.com so we can send you a copy immediately.
|
13 |
+
*
|
14 |
+
* DISCLAIMER
|
15 |
+
*
|
16 |
+
* Do not edit or add to this file if you wish to upgrade Magento to newer
|
17 |
+
* versions in the future. If you wish to customize Magento for your
|
18 |
+
* needs please refer to http://www.magentocommerce.com for more information.
|
19 |
+
*
|
20 |
+
* @category design
|
21 |
+
* @package default_default
|
22 |
+
* @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
|
23 |
+
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
|
24 |
+
*/
|
25 |
+
|
26 |
+
/* Reset ================================================================================= */
|
27 |
+
* { margin:0; padding:0; }
|
28 |
+
|
29 |
+
body { background:#496778 url(../images/bkg_body.gif) 50% 0 repeat-y; font:12px/1.55 Arial, Helvetica, sans-serif; color:#2f2f2f; text-align:center; }
|
30 |
+
|
31 |
+
img { border:0; vertical-align:top; }
|
32 |
+
|
33 |
+
a { color:#1e7ec8; text-decoration:underline; }
|
34 |
+
a:hover { text-decoration:none; }
|
35 |
+
:focus { outline:0; }
|
36 |
+
|
37 |
+
/* Headings */
|
38 |
+
h1,h2,h3,
|
39 |
+
h4,h5,h6 { margin:0 0 5px; line-height:1.35; color:#0a263c; }
|
40 |
+
h1 { font-size:20px; font-weight:normal; }
|
41 |
+
h2 { font-size:18px; font-weight:normal; }
|
42 |
+
h3 { font-size:16px; font-weight:bold; }
|
43 |
+
h4 { font-size:14px; font-weight:bold; }
|
44 |
+
h5 { font-size:12px; font-weight:bold; }
|
45 |
+
h6 { font-size:11px; font-weight:bold; }
|
46 |
+
|
47 |
+
/* Forms */
|
48 |
+
form { display:inline; }
|
49 |
+
fieldset { border:0; }
|
50 |
+
legend { display:none; }
|
51 |
+
|
52 |
+
/* Table */
|
53 |
+
table { border:0; /*border-collapse:collapse;*/ border-spacing:0; empty-cells:show; font-size:100%; }
|
54 |
+
caption,th,td { vertical-align:top; text-align:left; font-weight:normal; }
|
55 |
+
|
56 |
+
/* Content */
|
57 |
+
p { margin:0 0 10px; }
|
58 |
+
strong { font-weight:bold; }
|
59 |
+
address { font-style:normal; line-height:1.35; }
|
60 |
+
cite { font-style:normal; }
|
61 |
+
q,
|
62 |
+
blockquote { quotes:none; }
|
63 |
+
q:before,
|
64 |
+
q:after { content:''; }
|
65 |
+
small,big { font-size:1em; }
|
66 |
+
/*sup { font-size:1em; vertical-align:top; }*/
|
67 |
+
|
68 |
+
/* Lists */
|
69 |
+
ul,ol { list-style:none; }
|
70 |
+
|
71 |
+
/* Tools */
|
72 |
+
.hidden { display:block !important; border:0 !important; margin:0 !important; padding:0 !important; font-size:0 !important; line-height:0 !important; width:0 !important; height:0 !important; overflow:hidden !important; }
|
73 |
+
.nobr { white-space:nowrap !important; }
|
74 |
+
.wrap { white-space:normal !important; }
|
75 |
+
.a-left { text-align:left !important; }
|
76 |
+
.a-center { text-align:center !important; }
|
77 |
+
.a-right { text-align:right !important; }
|
78 |
+
.v-top { vertical-align:top; }
|
79 |
+
.v-middle { vertical-align:middle; }
|
80 |
+
.f-left,
|
81 |
+
.left { float:left !important; }
|
82 |
+
.f-right,
|
83 |
+
.right { float:right !important; }
|
84 |
+
.f-none { float:none !important; }
|
85 |
+
.f-fix { float:left; width:100%; }
|
86 |
+
.no-display { display:none; }
|
87 |
+
.no-margin { margin:0 !important; }
|
88 |
+
.no-padding { padding:0 !important; }
|
89 |
+
.no-bg { background:none !important; }
|
90 |
+
/* ======================================================================================= */
|
91 |
+
|
92 |
+
|
93 |
+
/* Layout ================================================================================ */
|
94 |
+
.wrapper { min-width:954px; }
|
95 |
+
.page {}
|
96 |
+
.page-print { background:#fff; padding:25px 30px; text-align:left; }
|
97 |
+
.page-empty { background:#fff; padding:20px; text-align:left; }
|
98 |
+
.page-popup { background:#fff; padding:25px 30px; text-align:left; }
|
99 |
+
.main-container { background:#fbfaf6 url(../images/bkg_main1.gif) 50% 0 no-repeat; }
|
100 |
+
.main { width:900px; margin:0 auto; min-height:400px; padding:25px 25px 80px; background:#fffffe url(../images/bkg_main2.gif) 0 0 no-repeat; text-align:left; }
|
101 |
+
|
102 |
+
/* Base Columns */
|
103 |
+
.col-left { float:left; width:195px; padding:0 0 1px; }
|
104 |
+
.col-main { float:left; width:685px; padding:0 0 1px; }
|
105 |
+
.col-right { float:right; width:195px; padding:0 0 1px; }
|
106 |
+
|
107 |
+
/* 1 Column Layout */
|
108 |
+
.col1-layout .col-main { float:none; width:auto; }
|
109 |
+
|
110 |
+
/* 2 Columns Layout */
|
111 |
+
.col2-left-layout .col-main { float:right; }
|
112 |
+
.col2-right-layout .col-main {}
|
113 |
+
|
114 |
+
/* 3 Columns Layout */
|
115 |
+
.col3-layout .col-main { width:475px; margin-left:17px; }
|
116 |
+
.col3-layout .col-wrapper { float:left; width:687px; }
|
117 |
+
.col3-layout .col-wrapper .col-main { float:right; }
|
118 |
+
|
119 |
+
/* Content Columns */
|
120 |
+
.col2-set .col-1 { float:left; width:48.5%; }
|
121 |
+
.col2-set .col-2 { float:right; width:48.5%; }
|
122 |
+
.col2-set .col-narrow { width:32%; }
|
123 |
+
.col2-set .col-wide { width:65%; }
|
124 |
+
|
125 |
+
.col3-set .col-1 { float:left; width:32%; }
|
126 |
+
.col3-set .col-2 { float:left; width:32%; margin-left:2%; }
|
127 |
+
.col3-set .col-3 { float:right; width:32%; }
|
128 |
+
|
129 |
+
.col4-set .col-1 { float:left; width:23.5%; }
|
130 |
+
.col4-set .col-2 { float:left; width:23.5%; margin:0 2%; }
|
131 |
+
.col4-set .col-3 { float:left; width:23.5%; }
|
132 |
+
.col4-set .col-4 { float:right; width:23.5%; }
|
133 |
+
/* ======================================================================================= */
|
134 |
+
|
135 |
+
|
136 |
+
/* Global Styles ========================================================================= */
|
137 |
+
/* Form Elements */
|
138 |
+
input,select,textarea,button { font:12px/15px Arial, Helvetica, sans-serif; vertical-align:middle; color:#2f2f2f; }
|
139 |
+
input.input-text,select,textarea { background:#fff; border:1px solid #b6b6b6; }
|
140 |
+
input.input-text,textarea { padding:2px; }
|
141 |
+
select { padding:1px; }
|
142 |
+
select option { padding-right:10px; }
|
143 |
+
select.multiselect option { border-bottom:1px solid #b6b6b6; padding:2px 5px; }
|
144 |
+
select.multiselect option:last-child { border-bottom:0; }
|
145 |
+
textarea { overflow:auto; }
|
146 |
+
input.radio { margin-right:3px; }
|
147 |
+
input.checkbox { margin-right:3px; }
|
148 |
+
input.qty { width:2.5em !important; }
|
149 |
+
button.button::-moz-focus-inner { padding:0; border:0; } /* FF Fix */
|
150 |
+
button.button { -webkit-border-fit:lines; } /* <- Safari & Google Chrome Fix */
|
151 |
+
button.button { overflow:visible; width:auto; border:0; padding:0; margin:0; background:transparent; cursor:pointer; }
|
152 |
+
button.button span { display:block; height:19px; border:1px solid #de5400; background:#f18200; padding:0 8px; font:bold 12px/19px Arial, Helvetica, sans-serif; text-align:center; white-space:nowrap; color:#fff; }
|
153 |
+
button.button span span { border:0; padding:0; }
|
154 |
+
button.disabled span { border-color:#bbb !important; background:#bbb !important; }
|
155 |
+
|
156 |
+
button.btn-checkout span { height:40px; border:0; background:url(../images/btn_checkout.gif) 0 0 no-repeat; padding:0 0 0 9px; font:bold 15px/40px Arial, Helvetica, sans-serif; color:#fff; }
|
157 |
+
button.btn-checkout span span { background-position:100% 0; padding:0 25px 0 16px; }
|
158 |
+
button.btn-checkout.no-checkout span { background-position:0 100%; color:#b8baba; }
|
159 |
+
button.btn-checkout.no-checkout span span { background-position:100% 100%; }
|
160 |
+
|
161 |
+
p.control input.checkbox,
|
162 |
+
p.control input.radio { margin-right:6px; }
|
163 |
+
/* Form Highlight */
|
164 |
+
input.input-text:focus,select:focus,textarea:focus { background-color:#edf7fd; }
|
165 |
+
/*.highlight { background:#efefef; }*/
|
166 |
+
|
167 |
+
/* Form lists */
|
168 |
+
/* Grouped fields */
|
169 |
+
/*.form-list { width:535px; margin:0 auto; overflow:hidden; }*/
|
170 |
+
.form-list li { margin:0 0 8px; }
|
171 |
+
.form-list label { float:left; color:#666; font-weight:bold; position:relative; z-index:0; }
|
172 |
+
.form-list label.required {}
|
173 |
+
.form-list label.required em { float:right; font-style:normal; color:#eb340a; position:absolute; top:0; right:-8px; }
|
174 |
+
.form-list li.control label { float:none; }
|
175 |
+
.form-list li.control input.radio,
|
176 |
+
.form-list li.control input.checkbox { margin-right:6px; }
|
177 |
+
.form-list li.control .input-box { clear:none; display:inline; width:auto; }
|
178 |
+
/*.form-list li.fields { margin-right:-15px; }*/
|
179 |
+
.form-list .input-box { display:block; clear:both; width:260px; }
|
180 |
+
.form-list .field { float:left; width:275px; }
|
181 |
+
.form-list input.input-text { width:254px; }
|
182 |
+
.form-list textarea { width:254px; height:10em; }
|
183 |
+
.form-list select { width:260px; }
|
184 |
+
.form-list li.wide .input-box { width:535px; }
|
185 |
+
.form-list li.wide input.input-text { width:529px; }
|
186 |
+
.form-list li.wide textarea { width:529px; }
|
187 |
+
.form-list li.wide select { width:535px; }
|
188 |
+
.form-list li.additional-row { border-top:1px solid #ccc; margin-top:10px; padding-top:7px; }
|
189 |
+
.form-list li.additional-row .btn-remove { float:right; margin:5px 0 0; }
|
190 |
+
.form-list .input-range input.input-text { width:74px; }
|
191 |
+
|
192 |
+
.form-list-narrow li { margin-bottom:0; }
|
193 |
+
.form-list-narrow li .input-box { margin-bottom:6px; }
|
194 |
+
.form-list-narrow li.wide .input-box { width:260px; }
|
195 |
+
.form-list-narrow li.wide input.input-text,
|
196 |
+
.form-list-narrow li.wide textarea { width:254px }
|
197 |
+
.form-list-narrow li.wide select { width:260px; }
|
198 |
+
|
199 |
+
/* Customer */
|
200 |
+
.form-list .customer-name-prefix .input-box,
|
201 |
+
.form-list .customer-name-suffix .input-box,
|
202 |
+
.form-list .customer-name-prefix-suffix .input-box,
|
203 |
+
.form-list .customer-name-prefix-middlename .input-box,
|
204 |
+
.form-list .customer-name-middlename-suffix .input-box,
|
205 |
+
.form-list .customer-name-prefix-middlename-suffix .input-box { width:auto; }
|
206 |
+
|
207 |
+
.form-list .name-prefix { width:65px; }
|
208 |
+
.form-list .name-prefix select { width:55px; }
|
209 |
+
.form-list .name-prefix input.input-text { width:49px; }
|
210 |
+
|
211 |
+
.form-list .name-suffix { width:65px; }
|
212 |
+
.form-list .name-suffix select { width:55px; }
|
213 |
+
.form-list .name-suffix input.input-text { width:49px; }
|
214 |
+
|
215 |
+
.form-list .name-middlename { width:70px; }
|
216 |
+
.form-list .name-middlename input.input-text { width:49px; }
|
217 |
+
|
218 |
+
.form-list .customer-name-prefix-middlename-suffix .name-firstname,
|
219 |
+
.form-list .customer-name-prefix-middlename .name-firstname { width:140px; }
|
220 |
+
.form-list .customer-name-prefix-middlename-suffix .name-firstname input.input-text,
|
221 |
+
.form-list .customer-name-prefix-middlename .name-firstname input.input-text { width:124px; }
|
222 |
+
.form-list .customer-name-prefix-middlename-suffix .name-lastname { width:205px; }
|
223 |
+
.form-list .customer-name-prefix-middlename-suffix .name-lastname input.input-text { width:189px; }
|
224 |
+
|
225 |
+
.form-list .customer-name-prefix-suffix .name-firstname { width:210px; }
|
226 |
+
.form-list .customer-name-prefix-suffix .name-lastname { width:205px; }
|
227 |
+
.form-list .customer-name-prefix-suffix .name-firstname input.input-text,
|
228 |
+
.form-list .customer-name-prefix-suffix .name-lastname input.input-text { width:189px; }
|
229 |
+
|
230 |
+
.form-list .customer-name-prefix-suffix .name-firstname { width:210px; }
|
231 |
+
.form-list .customer-name-prefix-suffix .name-lastname { width:205px; }
|
232 |
+
.form-list .customer-name-prefix-suffix .name-firstname input.input-text,
|
233 |
+
.form-list .customer-name-prefix-suffix .name-lastname input.input-text { width:189px; }
|
234 |
+
|
235 |
+
.form-list .customer-name-prefix .name-firstname,
|
236 |
+
.form-list .customer-name-middlename .name-firstname { width:210px; }
|
237 |
+
|
238 |
+
.form-list .customer-name-suffix .name-lastname,
|
239 |
+
.form-list .customer-name-middlename .name-firstname,
|
240 |
+
.form-list .customer-name-middlename-suffix .name-firstname,
|
241 |
+
.form-list .customer-name-middlename-suffix .name-lastname { width:205px; }
|
242 |
+
|
243 |
+
.form-list .customer-name-prefix .name-firstname input.input-text,
|
244 |
+
.form-list .customer-name-suffix .name-lastname input.input-text,
|
245 |
+
.form-list .customer-name-middlename .name-firstname input.input-text,
|
246 |
+
.form-list .customer-name-middlename-suffix .name-firstname input.input-text,
|
247 |
+
.form-list .customer-name-middlename-suffix .name-lastname input.input-text { width:189px; }
|
248 |
+
|
249 |
+
.form-list .customer-dob .dob-month,
|
250 |
+
.form-list .customer-dob .dob-day,
|
251 |
+
.form-list .customer-dob .dob-year { float:left; width:85px; }
|
252 |
+
.form-list .customer-dob input.input-text { display:block; width:74px; }
|
253 |
+
.form-list .customer-dob label { font-size:10px; font-weight:normal; color:#888; }
|
254 |
+
.form-list .customer-dob .dob-day,
|
255 |
+
.form-list .customer-dob .dob-month { width:60px; }
|
256 |
+
.form-list .customer-dob .dob-day input.input-text,
|
257 |
+
.form-list .customer-dob .dob-month input.input-text { width:46px; }
|
258 |
+
.form-list .customer-dob .dob-year { width:140px; }
|
259 |
+
.form-list .customer-dob .dob-year input.input-text { width:134px; }
|
260 |
+
|
261 |
+
/* Independent fields */
|
262 |
+
/*.form-list li { margin:0 0 8px; }
|
263 |
+
.form-list li.fields { margin:0; }
|
264 |
+
.form-list .field { display:block; margin:0 0 8px; }
|
265 |
+
.form-list li.control {}
|
266 |
+
.form-list label { float:left; width:150px; padding:2px 10px 0 0; text-align:right; }
|
267 |
+
.form-list label.required { font-weight:bold; }
|
268 |
+
.form-list label.required em { font-variant:normal; color:#eb340a; margin-right:3px; }
|
269 |
+
.form-list .input-box { float:left; width:260px; }
|
270 |
+
.form-list input.input-text,
|
271 |
+
.form-list textarea { width:254px; }
|
272 |
+
.form-list select { width:260px; }
|
273 |
+
.form-list li.additional-row { border-top:1px solid #ddd; margin-top:10px; }
|
274 |
+
.form-list li.additional-row .btn-remove { float:right; margin:5px 5px 0 0; }
|
275 |
+
.form-list .input-range input.input-text { width:96px; }*/
|
276 |
+
/* Customer */
|
277 |
+
/*.form-list .customer-dob .dob-month,
|
278 |
+
.form-list .customer-dob .dob-day,
|
279 |
+
.form-list .customer-dob .dob-year { float:left; width:85px; }
|
280 |
+
.form-list .customer-dob input.input-text { display:block; width:74px; }
|
281 |
+
.form-list .customer-dob label { font-size:11px; font-weight:normal; color:#777; text-align:left; }
|
282 |
+
.form-list .customer-dob .dob-day,
|
283 |
+
.form-list .customer-dob .dob-month { width:60px; }
|
284 |
+
.form-list .customer-dob .dob-day input.input-text,
|
285 |
+
.form-list .customer-dob .dob-month input.input-text { width:46px; }
|
286 |
+
.form-list .customer-dob .dob-year { width:140px; }
|
287 |
+
.form-list .customer-dob .dob-year input.input-text { width:134px; }*/
|
288 |
+
|
289 |
+
.buttons-set { clear:both; margin:4em 0 0; padding:8px 0 0; border-top:1px solid #e4e4e4; text-align:right; }
|
290 |
+
.buttons-set p.required { margin:0 0 10px; }
|
291 |
+
.buttons-set .back-link { float:left; margin:0; }
|
292 |
+
.buttons-set button.button { float:right; margin-left:5px; }
|
293 |
+
|
294 |
+
.buttons-set-order { margin:10px 0 0; }
|
295 |
+
.buttons-set-order .please-wait { padding:12px 7px 0 0; }
|
296 |
+
|
297 |
+
.fieldset { border:1px solid #bbafa0; background:#fbfaf6; padding:22px 25px 12px 33px; margin:28px 0; }
|
298 |
+
.fieldset .legend { float:left; font-weight:bold; font-size:13px; border:1px solid #f19900; background:#f9f3e3; color:#e76200; margin:-33px 0 0 -10px; padding:0 8px; position:relative; }
|
299 |
+
|
300 |
+
/* Form Validation */
|
301 |
+
.validation-advice { clear:both; min-height:13px; margin:3px 0 0; padding-left:17px; font-size:11px; font-weight:bold; line-height:13px; background:url(../images/validation_advice_bg.gif) 2px 0 no-repeat; color:#eb340a; }
|
302 |
+
.validation-failed { border:1px dashed #eb340a !important; background:#faebe7 !important; }
|
303 |
+
.validation-passed {}
|
304 |
+
p.required { font-size:11px; text-align:right; color:#EB340A; }
|
305 |
+
/* Expiration date and CVV number validation fix */
|
306 |
+
.v-fix { float:left; }
|
307 |
+
.v-fix .validation-advice { display:block; width:12em; margin-right:-12em; position:relative; }
|
308 |
+
|
309 |
+
/* Global Messages */
|
310 |
+
.success { color:#3d6611; font-weight:bold; }
|
311 |
+
.error { color:#df280a; font-weight:bold; }
|
312 |
+
.notice { color:#e26703; }
|
313 |
+
|
314 |
+
.messages,
|
315 |
+
.messages ul { list-style:none !important; margin:0 !important; padding:0 !important; }
|
316 |
+
.messages { width:100%; overflow:hidden; }
|
317 |
+
.messages li { margin:0 0 10px !important; }
|
318 |
+
.messages li li { margin:0 0 3px !important; }
|
319 |
+
.error-msg,
|
320 |
+
.success-msg,
|
321 |
+
.note-msg,
|
322 |
+
.notice-msg { border-style:solid !important; border-width:1px !important; background-position:10px 9px !important; background-repeat:no-repeat !important; min-height:24px !important; padding:8px 8px 8px 32px !important; font-size:11px !important; font-weight:bold !important; }
|
323 |
+
.error-msg { border-color:#f16048; background-color:#faebe7; background-image:url(../images/i_msg-error.gif); color:#df280a; }
|
324 |
+
.success-msg { border-color:#446423; background-color:#eff5ea; background-image:url(../images/i_msg-success.gif); color:#3d6611; }
|
325 |
+
.note-msg,
|
326 |
+
.notice-msg { border-color:#fcd344; background-color:#fafaec; background-image:url(../images/i_msg-note.gif); color:#3d6611; }
|
327 |
+
|
328 |
+
/* BreadCrumbs */
|
329 |
+
.breadcrumbs { font-size:11px; line-height:1.25; margin:0 0 13px; }
|
330 |
+
.breadcrumbs li { display:inline; }
|
331 |
+
.breadcrumbs li strong { font-weight:bold; }
|
332 |
+
|
333 |
+
/* Page Heading */
|
334 |
+
.page-title { width:100%; overflow:hidden; border-bottom:1px solid #ccc; margin:0 0 25px; }
|
335 |
+
.page-title h1,
|
336 |
+
.page-title h2 { margin:0; font-size:20px; color:#0a263c; }
|
337 |
+
.page-title .separator { margin:0 3px; }
|
338 |
+
.page-title .link-rss { float:right; margin:7px 0 0; }
|
339 |
+
.title-buttons { text-align:right; }
|
340 |
+
.title-buttons h1,
|
341 |
+
.title-buttons h2,
|
342 |
+
.title-buttons h3,
|
343 |
+
.title-buttons h4,
|
344 |
+
.title-buttons h5,
|
345 |
+
.title-buttons h6 { float:left; }
|
346 |
+
|
347 |
+
.subtitle,
|
348 |
+
.sub-title { clear:both; padding:15px 0 0; font-size:15px; font-weight:bold; margin:0 0 6px; color:#e25203; }
|
349 |
+
|
350 |
+
/* Pager */
|
351 |
+
.pager { font-size:11px; background:#fff url(../images/bkg_toolbar.gif) 0 100% repeat-x; padding:4px 8px; border-top:1px solid #e2e2e2; text-align:center; }
|
352 |
+
.pager .amount { float:left; margin:0; }
|
353 |
+
.pager .limiter { float:right; }
|
354 |
+
.pager .limiter label { vertical-align:middle; }
|
355 |
+
.pager .limiter select { padding:0; margin:0 0 1px; vertical-align:middle; }
|
356 |
+
.pager .pages { margin:0 140px; }
|
357 |
+
.pager .pages ol { display:inline; }
|
358 |
+
.pager .pages li { display:inline; margin:0 2px; }
|
359 |
+
.pager .pages .current {}
|
360 |
+
|
361 |
+
/* Sorter */
|
362 |
+
.sorter { font-size:11px; background:#fff url(../images/bkg_toolbar.gif) 0 100% repeat-x; padding:3px 8px; border-top:1px solid #e2e2e2; }
|
363 |
+
.sorter .view-mode { float:left; margin:0; }
|
364 |
+
.sorter .sort-by { float:right; padding-right:36px; }
|
365 |
+
.sorter .sort-by label { vertical-align:middle; }
|
366 |
+
.sorter .sort-by select { padding:0; margin:0 0 1px; vertical-align:middle; }
|
367 |
+
.sorter .link-feed {}
|
368 |
+
|
369 |
+
/* Toolbar */
|
370 |
+
.toolbar {}
|
371 |
+
.toolbar .pager { padding:3px 8px; border-bottom:1px solid #fff; }
|
372 |
+
.toolbar .sorter { border-bottom:1px solid #fff; }
|
373 |
+
.toolbar-bottom {}
|
374 |
+
|
375 |
+
/* Data Table */
|
376 |
+
.data-table { width:100%; border:1px solid #bebcb7; }
|
377 |
+
.data-table .odd { background:#f8f7f5 }
|
378 |
+
.data-table .even { background:#eeeded; }
|
379 |
+
/*.data-table tr.odd:hover,
|
380 |
+
.data-table tr.even:hover { background:#ebf1f6; }*/
|
381 |
+
.data-table td.last,
|
382 |
+
.data-table th.last { border-right:0; }
|
383 |
+
.data-table tr.last th,
|
384 |
+
.data-table tr.last td { border-bottom:0 !important; }
|
385 |
+
.data-table th { padding:3px 8px; font-weight:bold; }
|
386 |
+
.data-table td { padding:3px 8px; }
|
387 |
+
|
388 |
+
.data-table thead th { font-weight:bold; border-right:1px solid #c2d3e0; padding:2px 8px; color:#0a263c; white-space:nowrap; vertical-align:middle; }
|
389 |
+
.data-table thead th.wrap { white-space:normal; }
|
390 |
+
.data-table thead th a,
|
391 |
+
.data-table thead th a:hover { color:#fff; }
|
392 |
+
.data-table thead th { background:url(../images/bkg_th.gif) repeat-x 0 100% #d9e5ee; }
|
393 |
+
.data-table thead th .tax-flag { font-size:11px; white-space:nowrap; }
|
394 |
+
|
395 |
+
.data-table tfoot { border-bottom:1px solid #d9dde3; }
|
396 |
+
.data-table tfoot tr.first td { background:url(../images/bkg_tfoot.gif) 0 0 repeat-x; }
|
397 |
+
.data-table tfoot tr { background-color:#dee5e8 !important; }
|
398 |
+
.data-table tfoot td { padding-top:1px; padding-bottom:1px; border-bottom:0; border-right:1px solid #d9dde3; }
|
399 |
+
.data-table tfoot strong { font-size:16px; }
|
400 |
+
|
401 |
+
.data-table tbody th,
|
402 |
+
.data-table tbody td { border-bottom:1px solid #d9dde3; border-right:1px solid #d9dde3; }
|
403 |
+
/* Bundle products tables */
|
404 |
+
.data-table tbody.odd tr { background:#f8f7f5 !important; }
|
405 |
+
.data-table tbody.even tr { background:#f6f6f6 !important; }
|
406 |
+
.data-table tbody.odd tr td,
|
407 |
+
.data-table tbody.even tr td { border-bottom:0; }
|
408 |
+
.data-table tbody.odd tr.border td,
|
409 |
+
.data-table tbody.even tr.border td { border-bottom:1px solid #d9dde3; }
|
410 |
+
|
411 |
+
.data-table tbody td .option-label { font-weight:bold; font-style:italic; }
|
412 |
+
.data-table tbody td .option-value { padding-left:10px; }
|
413 |
+
|
414 |
+
/* Generic Info Box */
|
415 |
+
.info-box { background:#fff url(../images/bkg_block-title.gif) 0 0 repeat-x; border:1px solid #d0cbc1; padding:12px 15px; margin:0 0 15px; }
|
416 |
+
.info-box h2 { font-weight:bold; font-size:13px; }
|
417 |
+
|
418 |
+
.info-table th { font-weight:bold; padding:2px 15px 2px 0; }
|
419 |
+
.info-table td { padding:2px 0; }
|
420 |
+
|
421 |
+
/* Shopping cart total summary row expandable to details */
|
422 |
+
tr.summary-total { cursor:pointer; }
|
423 |
+
tr.summary-total td {}
|
424 |
+
tr.summary-total .summary-collapse { float:right; text-align:right; padding-left:20px; background:url(../images/bkg_collapse.gif) 0 5px no-repeat; cursor:pointer; }
|
425 |
+
tr.show-details .summary-collapse { background-position:0 -52px; }
|
426 |
+
tr.show-details td {}
|
427 |
+
tr.summary-details td { font-size:11px; background-color:#dae1e4; color:#626465; }
|
428 |
+
tr.summary-details-first td { border-top:1px solid #d2d8db; }
|
429 |
+
tr.summary-details-excluded { font-style:italic; }
|
430 |
+
|
431 |
+
/* Shopping cart tax info */
|
432 |
+
.cart-tax-info { display:block; }
|
433 |
+
.cart-tax-info,
|
434 |
+
.cart-tax-info .cart-price { padding-right:20px; }
|
435 |
+
.cart-tax-total { display:block; padding-right:20px; background:url(../images/bkg_collapse.gif) 100% 5px no-repeat; cursor:pointer; }
|
436 |
+
.cart-tax-info .price,
|
437 |
+
.cart-tax-total .price { display:inline !important; font-weight:normal !important; }
|
438 |
+
.cart-tax-total-expanded { background-position:100% -52px; }
|
439 |
+
|
440 |
+
/* Class: std - styles for admin-controlled content */
|
441 |
+
.std .subtitle { padding:0; }
|
442 |
+
.std ol.ol { list-style:decimal outside; padding-left:1.5em; }
|
443 |
+
.std ul.disc { list-style:disc outside; padding-left:18px; margin:0 0 10px; }
|
444 |
+
.std dl dt { font-weight:bold; }
|
445 |
+
.std dl dd { margin:0 0 10px; }
|
446 |
+
.std ul,
|
447 |
+
.std ol,
|
448 |
+
.std dl,
|
449 |
+
.std p,
|
450 |
+
.std address,
|
451 |
+
.std blockquote { margin:0 0 1em; padding:0; }
|
452 |
+
.std ul { list-style:disc outside; padding-left:1.5em; }
|
453 |
+
.std ol { list-style:decimal outside; padding-left:1.5em; }
|
454 |
+
.std ul ul { list-style-type:circle; }
|
455 |
+
.std ul ul,
|
456 |
+
.std ol ol,
|
457 |
+
.std ul ol,
|
458 |
+
.std ol ul { margin:.5em 0; }
|
459 |
+
.std dt { font-weight:bold; }
|
460 |
+
.std dd { padding:0 0 0 1.5em; }
|
461 |
+
.std blockquote { font-style:italic; padding:0 0 0 1.5em; }
|
462 |
+
.std address { font-style:normal; }
|
463 |
+
.std b,
|
464 |
+
.std strong { font-weight:bold; }
|
465 |
+
.std i,
|
466 |
+
.std em { font-style:italic; }
|
467 |
+
|
468 |
+
/* Misc */
|
469 |
+
.links li { display:inline; }
|
470 |
+
.links li.first { padding-left:0 !important; }
|
471 |
+
.links li.last { background:none !important; padding-right:0 !important; }
|
472 |
+
|
473 |
+
.link-cart { color:#dc6809 !important; font-weight:bold; }
|
474 |
+
.link-wishlist { color:#dc6809 !important; font-weight:bold; }
|
475 |
+
.link-reorder { font-weight:bold; color:#dc6809 !important; }
|
476 |
+
.link-compare { font-weight:bold; }
|
477 |
+
.link-print { /*background:url(../images/i_print.gif) 0 2px no-repeat; padding:2px 0 2px 25px;*/ font-weight:bold; color:#dc6809; }
|
478 |
+
.link-rss { background:url(../images/i_rss.gif) 0 2px no-repeat; padding-left:18px; line-height:14px; white-space:nowrap; }
|
479 |
+
.btn-remove { display:block; width:11px; height:11px; font-size:0; line-height:0; background:url(../images/btn_remove.gif) 0 0 no-repeat; text-indent:-999em; overflow:hidden; }
|
480 |
+
.btn-previous { display:block; width:11px; height:11px; font-size:0; line-height:0; background:url(../images/btn_previous.gif) 0 0 no-repeat; text-indent:-999em; overflow:hidden; }
|
481 |
+
.btn-remove2 { display:block; width:16px; height:16px; font-size:0; line-height:0; background:url(../images/btn_trash.gif) 0 0 no-repeat; text-indent:-999em; overflow:hidden; }
|
482 |
+
.btn-edit { display:block; width:11px; height:11px; font-size:0; line-height:0; background:url(../images/btn_edit.gif) 0 0 no-repeat; text-indent:-999em; overflow:hidden; }
|
483 |
+
|
484 |
+
.cards-list dt { margin:5px 0 0; }
|
485 |
+
.cards-list .offset { padding:2px 0 2px 20px; }
|
486 |
+
|
487 |
+
.separator { margin:0 3px; }
|
488 |
+
|
489 |
+
.divider { clear:both; display:block; font-size:0; line-height:0; height:1px; margin:10px 0; background:url(../images/bkg_divider1.gif) 0 50% repeat-x; text-indent:-999em; overflow:hidden; }
|
490 |
+
|
491 |
+
/* Global site notices */
|
492 |
+
.global-site-notice { border:1px solid #cfcfcf; border-width:0 0 1px; background:#ffff90; font-size:12px; line-height:1.25; text-align:center; color:#2f2f2f; }
|
493 |
+
.global-site-notice .notice-inner { width:860px; margin:0 auto; padding:12px 0 12px 80px; background:url(../images/i_notice.gif) 20px 25px no-repeat; text-align:left; }
|
494 |
+
.global-site-notice .notice-inner p { margin:0; border:1px dotted #cccc73; padding:10px; }
|
495 |
+
.global-site-notice .notice-inner .actions { padding-top:10px; }
|
496 |
+
|
497 |
+
/* Cookie Notice */
|
498 |
+
.notice-cookie { }
|
499 |
+
|
500 |
+
/* Noscript Notice */
|
501 |
+
.noscript {}
|
502 |
+
|
503 |
+
/* Demo Notice */
|
504 |
+
.demo-notice { margin:0; padding:6px 10px; background:#d75f07; font-size:12px; line-height:1.15; border:0; text-align:center; color:#fff; }
|
505 |
+
.demo-notice .notice-inner { width:auto; padding:0; background:none; text-align:center; }
|
506 |
+
.demo-notice .notice-inner p { padding:0; border:0; }
|
507 |
+
|
508 |
+
/* ======================================================================================= */
|
509 |
+
|
510 |
+
|
511 |
+
/* Header ================================================================================ */
|
512 |
+
.logo { float:left; }
|
513 |
+
.header-container { border-top:5px solid #0d2131; border-bottom:1px solid #415966; background:url(../images/bkg_header.jpg) 50% 0 repeat; }
|
514 |
+
.header { width:930px; margin:0 auto; padding:10px; text-align:right; position:relative; z-index:10; }
|
515 |
+
.header .logo { float:left; margin:3px 0 10px 12px; text-decoration:none !important; }
|
516 |
+
.header .logo strong { position:absolute; top:-999em; left:-999em; width:0; height:0; font-size:0; line-height:0; text-indent:-999em; overflow:hidden; }
|
517 |
+
.header h1.logo { margin:0; }
|
518 |
+
.header .quick-access { float:right; width:600px; padding:28px 10px 0 0; }
|
519 |
+
.header .welcome-msg { margin:0; color:#fff; text-align:right; }
|
520 |
+
.header .welcome-msg a { color:#ebbc58; }
|
521 |
+
.header .form-search { position:absolute; top:0; right:29px; width:315px; height:30px; background:url(../images/bkg_form-search.gif) 0 0 no-repeat; padding:1px 0 0 16px; }
|
522 |
+
.header .form-search label { float:left; width:24px; height:21px; text-align:left; text-indent:-999em; overflow:hidden; }
|
523 |
+
.header .form-search input.input-text { float:left; border-color:#5c7989; width:209px; margin-right:4px; }
|
524 |
+
.header .form-search button.button { float:left; }
|
525 |
+
.header .form-search button.button span { border:0; height:21px; background:url(../images/btn_search.gif) 0 0 no-repeat; padding:0 0 0 3px; font:bold 11px/21px Tahoma, Verdana, Arial, sans-serif; }
|
526 |
+
.header .form-search button.button span span { background-position:100% 0; padding:0 6px 0 3px; }
|
527 |
+
.header .form-search .search-autocomplete { z-index:999; left:40px !important; top:22px !important; }
|
528 |
+
.header .form-search .search-autocomplete ul { border:1px solid #5c7989; background-color:#f9f5f0; }
|
529 |
+
.header .form-search .search-autocomplete li { text-align:left; border-bottom:1px solid #f4eee7; padding:2px 8px 1px 8px; cursor:pointer; }
|
530 |
+
.header .form-search .search-autocomplete li .amount { float:right; font-weight:bold; }
|
531 |
+
.header .form-search .search-autocomplete li.odd { background-color:#fffefb; }
|
532 |
+
.header .form-search .search-autocomplete li.selected { background-color:#f7e8dd; }
|
533 |
+
.header .form-language { clear:both; padding:5px 0 0; text-align:right; }
|
534 |
+
.header .form-language label { font-weight:bold; padding-right:5px; color:#a7c6dd; vertical-align:middle; }
|
535 |
+
.header .form-language select { padding:0; }
|
536 |
+
.header .form-language select.flags option { background-position:4px 50%; background-repeat:no-repeat; padding-left:25px; }
|
537 |
+
.header .links { float:right; margin:0 0 6px; }
|
538 |
+
.header .links li { float:left; font-size:11px; background:url(../images/bkg_pipe1.gif) 100% 60% no-repeat; padding:0 8px 0 7px; }
|
539 |
+
.header .links a { color:#ebbc58; }
|
540 |
+
.header-container .top-container { clear:both; padding:5px 10px 0 12px; text-align:right; }
|
541 |
+
.header-container .top-container a { font-size:11px; color:#ebbc58; }
|
542 |
+
|
543 |
+
/********** < Navigation */
|
544 |
+
.nav-container { background:#0a263d url(../images/bkg_nav0.jpg) 50% 0 repeat-y; }
|
545 |
+
#nav { width:918px; margin:0 auto; padding:0 16px; font-size:13px; }
|
546 |
+
|
547 |
+
/* All Levels */ /* Style consistent throughout all nav levels */
|
548 |
+
#nav li { position:relative; text-align:left; }
|
549 |
+
#nav li.over { z-index:998; }
|
550 |
+
#nav a,
|
551 |
+
#nav a:hover { display:block; line-height:1.3em; text-decoration:none; }
|
552 |
+
#nav span { display:block; cursor:pointer; white-space:nowrap; }
|
553 |
+
#nav li ul span {white-space:normal; }
|
554 |
+
#nav ul li.parent a { background:url(../images/bkg_nav2.gif) 100% 100% no-repeat; }
|
555 |
+
#nav ul li.parent li a { background-image:none; }
|
556 |
+
|
557 |
+
/* 0 Level */
|
558 |
+
#nav li { float:left; }
|
559 |
+
#nav li.active a { color:#d96708; }
|
560 |
+
#nav a { float:left; padding:5px 12px 6px 8px; color:#a7c6dd; font-weight:bold; }
|
561 |
+
#nav li.over a,
|
562 |
+
#nav a:hover { color:#d96708; }
|
563 |
+
|
564 |
+
/* 1st Level */
|
565 |
+
#nav ul li,
|
566 |
+
#nav ul li.active { float:none; margin:0; padding-bottom:1px; background:#ecf3f6 url(../images/bkg_nav1.gif) 0 100% repeat-x; }
|
567 |
+
#nav ul li.last { background:#ecf3f6; padding-bottom:0; }
|
568 |
+
|
569 |
+
#nav ul a,
|
570 |
+
#nav ul a:hover { float:none; padding:0; background:none; }
|
571 |
+
#nav ul li a { font-weight:normal !important; }
|
572 |
+
|
573 |
+
/* 2nd Level */
|
574 |
+
#nav ul,
|
575 |
+
#nav div { position:absolute; width:15em; top:27px; left:-10000px; border:1px solid #899ba5; }
|
576 |
+
#nav div ul { position:static; width:auto; border:none; }
|
577 |
+
|
578 |
+
/* 3rd+ Level */
|
579 |
+
#nav ul ul,
|
580 |
+
#nav ul div { top:5px; }
|
581 |
+
|
582 |
+
#nav ul li a { background:#ecf3f6; }
|
583 |
+
#nav ul li a:hover { background:#d5e4eb; }
|
584 |
+
#nav ul li a,
|
585 |
+
#nav ul li a:hover { color:#2f2f2f !important; }
|
586 |
+
#nav ul span,
|
587 |
+
#nav ul li.last li span { padding:3px 15px 4px 15px; }
|
588 |
+
|
589 |
+
/* Show menu */
|
590 |
+
#nav li ul.shown-sub,
|
591 |
+
#nav li div.shown-sub { left:0; z-index:999; }
|
592 |
+
#nav li .shown-sub ul.shown-sub,
|
593 |
+
#nav li .shown-sub li div.shown-sub { left:100px; }
|
594 |
+
/********** Navigation > */
|
595 |
+
/* ======================================================================================= */
|
596 |
+
|
597 |
+
|
598 |
+
/* Sidebar =============================================================================== */
|
599 |
+
.block { border:1px solid #c4c1bc; margin:0 0 15px; }
|
600 |
+
.block .block-title { background:url(../images/bkg_block-title.gif) 0 0 repeat-x; border-bottom:1px solid #ddd; padding:2px 9px; }
|
601 |
+
.block .block-title strong { display:block; font:bold 12px/16px Arial, Helvetica, sans-serif; min-height:16px; padding:1px 0 1px; text-transform:uppercase; color:#e26703; }
|
602 |
+
.block .block-title strong span {}
|
603 |
+
.block .block-title a { text-decoration:none !important; }
|
604 |
+
.block .block-subtitle { margin:0; padding:5px 9px; font-size:1em; font-weight:bold; color:#0a263c; }
|
605 |
+
.block .block-content { background:#f8f7f5; }
|
606 |
+
.block .block-content li.item { padding:7px 9px; }
|
607 |
+
.block .block-content .product-name { color:#1e7ec8; }
|
608 |
+
.block .btn-remove,
|
609 |
+
.block .btn-edit { float:right; margin:1px 0 2px 5px; }
|
610 |
+
.block .actions { background:#dee5e8 url(../images/bkg_block-actions.gif) 0 0 repeat-x; padding:6px 9px; text-align:right; }
|
611 |
+
.block .actions a { float:left; }
|
612 |
+
.block .actions button.button { float:right; }
|
613 |
+
.block .empty { margin:0; padding:5px 9px; }
|
614 |
+
|
615 |
+
.block li.odd { background-color:#f4f3f3; }
|
616 |
+
.block li.even { background-color:#fafafa; }
|
617 |
+
|
618 |
+
/* Mini Blocks */
|
619 |
+
.block-cart,
|
620 |
+
.block-wishlist,
|
621 |
+
.block-subscribe,
|
622 |
+
.block-compare,
|
623 |
+
.block-reorder,
|
624 |
+
.block-poll,
|
625 |
+
.block-viewed,
|
626 |
+
.block-compared,
|
627 |
+
.block-related,
|
628 |
+
.block-tags,
|
629 |
+
.block-login { font-size:11px; line-height:1.25; }
|
630 |
+
.block-cart .block-title strong,
|
631 |
+
.block-wishlist .block-title strong,
|
632 |
+
.block-subscribe .block-title strong,
|
633 |
+
.block-compare .block-title strong,
|
634 |
+
.block-reorder .block-title strong,
|
635 |
+
.block-poll .block-title strong,
|
636 |
+
.block-viewed .block-title strong,
|
637 |
+
.block-compared .block-title strong,
|
638 |
+
.block-related .block-title strong,
|
639 |
+
.block-tags .block-title strong,
|
640 |
+
.block-login .block-title strong { background-position:0 0; background-repeat:no-repeat; padding-left:21px; }
|
641 |
+
|
642 |
+
/* Mini Products List */
|
643 |
+
.mini-products-list .product-image { float:left; width:50px; border:1px solid #a9a9a9; }
|
644 |
+
.mini-products-list .product-details { margin-left:60px; }
|
645 |
+
.block-cart .mini-products-list .product-details .product-name,
|
646 |
+
.block-cart .mini-products-list .product-details .nobr small { word-wrap:break-word; }
|
647 |
+
.block-cart .mini-products-list .product-details .nobr { white-space:normal !important; }
|
648 |
+
|
649 |
+
/* Block: Account */
|
650 |
+
.block-account { border-color:#bbb; }
|
651 |
+
.block-account .block-title { background:#fc9d36 url(../images/bkg_block-title-account.gif) 0 100% repeat-x; border:0; padding:3px 10px; }
|
652 |
+
.block-account .block-title strong { font-size:13px; color:#fff; }
|
653 |
+
.block-account .block-content { background:#fbfaf6; padding:7px 10px 7px; }
|
654 |
+
.block-account .block-content li a { display:block; border-bottom:1px solid #ddd; padding:3px 0; color:#5f5d5c; text-decoration:none !important; }
|
655 |
+
.block-account .block-content li a:hover { color:#ea7900; }
|
656 |
+
.block-account .block-content li.last a { border-bottom:0; }
|
657 |
+
.block-account .block-content li.current { border-bottom:1px solid #ddd; padding:3px 0; color:#ea7900; }
|
658 |
+
.block-account .block-content li.current.last { border-bottom:0; }
|
659 |
+
|
660 |
+
/* Block: Currency Switcher */
|
661 |
+
.block-currency { border:0; background:url(../images/bkg_block-currency.gif) 0 0 no-repeat; padding:7px 12px 10px; height:51px; }
|
662 |
+
.block-currency .block-title { background:none; border:0; padding:0; margin:0 0 5px; }
|
663 |
+
.block-currency .block-title strong { font:bold 13px/21px Arial, Helvetica, sans-serif; background:url(../images/i_block-currency.gif) 0 50% no-repeat; padding:0 0 0 21px; text-transform:none; color:#fff; }
|
664 |
+
.block-currency .block-content { background:none; padding:0; }
|
665 |
+
.block-currency .block-content select { width:100%; padding:0; }
|
666 |
+
|
667 |
+
/* Block: Layered Navigation */
|
668 |
+
.block-layered-nav { border:0; }
|
669 |
+
.block-layered-nav .block-title { border:0; padding:0; height:24px; background:url(../images/bkg_block-layered-title.gif) 0 0 no-repeat; text-indent:-999em; overflow:hidden; }
|
670 |
+
.block-layered-nav .block-subtitle { line-height:1.35; background:#d5e8ff url(../images/bkg_block-layered1.gif) 0 50% repeat; padding:3px 9px; border:1px solid #b9ccdd; border-width:1px 0; text-transform:uppercase; color:#1f5070; }
|
671 |
+
.block-layered-nav .block-content { border:1px solid #a0b3c3; background:#e7f1f4; }
|
672 |
+
.block-layered-nav dt { background:url(../images/bkg_block-layered-dt.gif) 9px 11px no-repeat; padding:7px 10px 0 25px; font-weight:bold; text-transform:uppercase; }
|
673 |
+
.block-layered-nav dd { padding:0 12px 12px; background:url(../images/bkg_block-layered-dd.gif) 0 100% repeat-x; }
|
674 |
+
.block-layered-nav dd.last { background:none; }
|
675 |
+
.block-layered-nav .currently li { background:#fff url(../images/bkg_block-layered-li.gif) 0 100% repeat-x; padding:6px 24px 6px 10px; position:relative; z-index:1; line-height:1.5; }
|
676 |
+
.block-layered-nav .currently .label { font-weight:bold; padding-left:15px; background:url(../images/bkg_block-layered-label.gif) 0 4px no-repeat; text-transform:uppercase; display:inline-block; vertical-align:top; }
|
677 |
+
.block-layered-nav .currently .value { display:inline-block; vertical-align:top; }
|
678 |
+
.block-layered-nav .currently .btn-previous,
|
679 |
+
.block-layered-nav .currently .btn-remove { position:absolute; right:4px; top:9px; margin:0; }
|
680 |
+
.block-layered-nav .currently .btn-previous { right:17px; }
|
681 |
+
.block-layered-nav .actions { font-size:11px; padding:4px 5px 4px 9px; background:#cad6e4; border:1px solid #dee5e8; border-width:1px 0; text-align:right; }
|
682 |
+
.block-layered-nav .actions a { float:none; }
|
683 |
+
|
684 |
+
/* Block: Cart */
|
685 |
+
.block-cart .block-title { /*border-bottom:0;*/ }
|
686 |
+
.block-cart .block-title strong { background-image:url(../images/i_block-cart.gif); }
|
687 |
+
.block-cart .summary { background:#fff; padding:2px 8px 8px; margin:-1px 0 0; position:relative; z-index:1; }
|
688 |
+
.block-cart .amount { margin:0; }
|
689 |
+
.block-cart .amount a { font-weight:bold; }
|
690 |
+
.block-cart .subtotal { margin:5px 0 0; padding:2px 0; background:#fbebd9; text-align:center; }
|
691 |
+
.block-cart .subtotal .price { font-weight:bold; }
|
692 |
+
.block-cart .actions { border-bottom:1px solid #c2c2c2; }
|
693 |
+
.block-cart .actions .paypal-logo { float:left; width:100%; margin:3px 0 0; text-align:right; }
|
694 |
+
.block-cart .actions .paypal-logo .paypal-or { clear:both; display:block; padding:0 55px 8px 0; }
|
695 |
+
|
696 |
+
/* Block: Wishlist */
|
697 |
+
.block-wishlist .block-title strong { background-image:url(../images/i_block-wishlist.gif); }
|
698 |
+
.block-wishlist .actions { text-align:right; }
|
699 |
+
.block-wishlist .actions a { float:none; }
|
700 |
+
|
701 |
+
/* Block: Related */
|
702 |
+
.block-related .block-title strong { background-image:url(../images/i_block-related.gif); background-position:0 1px; }
|
703 |
+
.block-related input.checkbox { float:left; }
|
704 |
+
.block-related .product { margin-left:20px; }
|
705 |
+
|
706 |
+
/* Block: Compare Products */
|
707 |
+
.block-compare .block-title strong { background-image:url(../images/i_block-list.gif); background-position:0 1px; }
|
708 |
+
.block-compare button.button span { border-color:#406a83; background:#618499; }
|
709 |
+
.page-popup .link-print { background:url(../images/i_print.gif) 0 2px no-repeat; padding:2px 0 2px 25px; font-weight:bold; color:#1e7ec8; }
|
710 |
+
.compare-table { border:0; }
|
711 |
+
.compare-table thead tr.first th,
|
712 |
+
.compare-table thead tr.first td { border:0; background:none; padding:0; font-size:0; line-height:0; }
|
713 |
+
.compare-table .btn-remove { float:right; background-image:url(../images/btn_remove2.gif); width:72px; height:15px; }
|
714 |
+
.compare-table tbody th { background:#d9e5ee url(../images/bkg_th-v.gif) 100% 0 repeat-y; }
|
715 |
+
.compare-table tbody th,
|
716 |
+
.compare-table tbody td { padding:10px; border:0; border-top:1px solid #ccc; border-left:1px solid #ccc; }
|
717 |
+
.compare-table tbody td.last { border-right:1px solid #ccc; }
|
718 |
+
.compare-table tbody tr.last th,
|
719 |
+
.compare-table tbody tr.last td { border-bottom:1px solid #ccc !important; }
|
720 |
+
.compare-table tr.add-to-row td { background:#fffada; text-align:center; }
|
721 |
+
.compare-table tr.first td { text-align:center; }
|
722 |
+
.compare-table tr.first td .product-name { font-size:13px; font-weight:bold; margin:0 0 5px; color:#203548; }
|
723 |
+
.compare-table tr.first td .product-name a { color:#203548; }
|
724 |
+
.compare-table tr.first td .ratings { width:69px; margin:0 auto; }
|
725 |
+
.compare-table tr.first td p,
|
726 |
+
.compare-table tr.add-to-row td p { margin:0; }
|
727 |
+
|
728 |
+
/* Block: Recently Viewed */
|
729 |
+
.block-viewed .block-title strong { background-image:url(../images/i_block-viewed.gif); }
|
730 |
+
|
731 |
+
/* Block: Recently Compared */
|
732 |
+
.block-compared .block-title strong { background-image:url(../images/i_block-list.gif); background-position:0 1px; }
|
733 |
+
|
734 |
+
/* Block: Poll */
|
735 |
+
.block-poll .block-title strong { background-image:url(../images/i_block-poll.gif); }
|
736 |
+
.block-poll .block-subtitle { font-size:12px; }
|
737 |
+
.block-poll label { color:#777; font-weight:bold; }
|
738 |
+
.block-poll input.radio { float:left; margin:1px -18px 0 0; }
|
739 |
+
.block-poll .label { display:block; margin-left:18px; }
|
740 |
+
.block-poll li { padding:3px 9px; }
|
741 |
+
.block-poll .actions { margin:5px 0 0; }
|
742 |
+
.block-poll button.button span { border-color:#406a83; background:#618499; }
|
743 |
+
.block-poll .answer { font-weight:bold; }
|
744 |
+
.block-poll .votes { float:right; margin-left:10px; }
|
745 |
+
|
746 |
+
/* Block: Tags */
|
747 |
+
.block-tags .block-title strong { background-image:url(../images/i_block-tags.gif); }
|
748 |
+
.block-tags .block-content .tags-list { background:none; border:0; font-size:12px; }
|
749 |
+
.block-tags .block-content a { color:#1b2d3b; }
|
750 |
+
.block-tags .actions { text-align:right; }
|
751 |
+
.block-tags .actions a { float:none; }
|
752 |
+
|
753 |
+
/* Block: Subscribe */
|
754 |
+
.block-subscribe .block-content { padding:5px 10px; }
|
755 |
+
.block-subscribe .block-title strong { background-image:url(../images/i_block-subscribe.gif); }
|
756 |
+
.block-subscribe label { font-weight:bold; color:#666; }
|
757 |
+
.block-subscribe input.input-text { display:block; width:167px; margin:3px 0; }
|
758 |
+
.block-subscribe .actions { background:none; padding:0; margin:3px 0 0; text-align:left; }
|
759 |
+
.block-subscribe .actions button.button { float:none; }
|
760 |
+
.block-subscribe .actions button.button span { border-color:#406a83; background:#618499; }
|
761 |
+
|
762 |
+
/* Block: Reorder */
|
763 |
+
.block-reorder .block-title strong { background-image:url(../images/i_block-list.gif); }
|
764 |
+
.block-reorder input.checkbox { float:left; margin:2px -20px 0 0; }
|
765 |
+
.block-reorder .product-name { margin-left:20px; }
|
766 |
+
.block-reorder .validation-advice { margin:3px 9px 7px; }
|
767 |
+
|
768 |
+
/* Block: Banner */
|
769 |
+
.block-banner { border:0; }
|
770 |
+
.block-banner .block-content { padding:0; text-align:center; }
|
771 |
+
|
772 |
+
/* Block: Login */
|
773 |
+
.block-login .block-title strong { background-image:url(../images/i_ma-info.gif); }
|
774 |
+
.block-login .block-content { padding:5px 10px; }
|
775 |
+
.block-login label { font-weight:bold; color:#666; }
|
776 |
+
.block-login input.input-text { display:block; width:167px; margin:3px 0; }
|
777 |
+
.block-login .actions { background:none; padding:0; margin:3px 0 0; }
|
778 |
+
.block-login .actions button.button span { border-color:#406a83; background:#618499; }
|
779 |
+
|
780 |
+
/* Paypal */
|
781 |
+
.sidebar .paypal-logo { display:block; margin:10px 0; text-align:center; }
|
782 |
+
.sidebar .paypal-logo a { float:none; }
|
783 |
+
/* ======================================================================================= */
|
784 |
+
|
785 |
+
|
786 |
+
/* Category Page ========================================================================= */
|
787 |
+
.category-title { border:0; margin:0 0 7px; }
|
788 |
+
.category-image { width:100%; overflow:hidden; margin:0 0 10px; text-align:center; }
|
789 |
+
.category-image img {}
|
790 |
+
.category-description { margin:0 0 10px; }
|
791 |
+
.category-products {}
|
792 |
+
|
793 |
+
/* View Type: Grid */
|
794 |
+
.products-grid { border-bottom:1px solid #d9ddd3; background:url(../images/bkg_grid.gif) 0 0 repeat; position:relative; }
|
795 |
+
.products-grid.last { border-bottom:0; }
|
796 |
+
.products-grid li.item { float:left; width:138px; padding:12px 10px 80px; }
|
797 |
+
.products-grid .product-image { display:block; width:135px; height:135px; margin:0 0 10px; }
|
798 |
+
.products-grid .product-name { /*min-height:2.7em;*/ margin:0 0 5px; font-weight:bold; font-size:13px; color:#203548; }
|
799 |
+
.products-grid .product-name a { color:#203548; }
|
800 |
+
.products-grid .price-box { margin:5px 0; }
|
801 |
+
.products-grid .availability { line-height:21px; }
|
802 |
+
.products-grid .actions { position:absolute; bottom:12px; }
|
803 |
+
.col2-left-layout .products-grid,
|
804 |
+
.col2-right-layout .products-grid { width:632px; margin:0 auto; }
|
805 |
+
.col1-layout .products-grid { width:790px; margin:0 auto; }
|
806 |
+
|
807 |
+
/* View Type: List */
|
808 |
+
.products-list li.item { border-bottom:1px solid #d9ddd3; padding:12px 10px; }
|
809 |
+
.products-list li.item.last { border-bottom:0; }
|
810 |
+
.products-list .product-image { float:left; width:135px; height:135px; margin:0 0 10px; }
|
811 |
+
.products-list .product-shop { margin-left:150px; }
|
812 |
+
.products-list .product-name { margin:0 0 5px; font-weight:bold; font-size:13px; color:#203548; }
|
813 |
+
.products-list .product-name a { color:#203548; }
|
814 |
+
.products-list .price-box { float:left; margin:3px 13px 5px 0; }
|
815 |
+
.products-list .availability { float:left; margin:3px 0 0; }
|
816 |
+
.products-list .desc { clear:both; padding:6px 0 0; margin:0 0 15px; line-height:1.35; }
|
817 |
+
.products-list .desc .link-learn { font-size:11px; }
|
818 |
+
.products-list .add-to-links { clear:both; }
|
819 |
+
.products-list .add-to-links li { display:inline; }
|
820 |
+
.products-list .add-to-links .separator { display:inline; margin:0 2px; }
|
821 |
+
/* ======================================================================================= */
|
822 |
+
|
823 |
+
|
824 |
+
/* Product View ========================================================================== */
|
825 |
+
/* Rating */
|
826 |
+
.no-rating { margin:0; }
|
827 |
+
|
828 |
+
.ratings { font-size:11px; line-height:1.25; margin:7px 0; }
|
829 |
+
.ratings strong { float:left; margin:1px 3px 0 0; }
|
830 |
+
.ratings .rating-links { margin:0; }
|
831 |
+
.ratings .rating-links .separator { margin:0 2px; }
|
832 |
+
.ratings dt {}
|
833 |
+
.ratings dd {}
|
834 |
+
.rating-box { width:69px; height:13px; font-size:0; line-height:0; background:url(../images/bkg_rating.gif) 0 0 repeat-x; text-indent:-999em; overflow:hidden; }
|
835 |
+
.rating-box .rating { float:left; height:13px; background:url(../images/bkg_rating.gif) 0 100% repeat-x; }
|
836 |
+
.ratings .rating-box { float:left; margin-right:3px; }
|
837 |
+
.ratings .amount {}
|
838 |
+
|
839 |
+
.ratings-table th,
|
840 |
+
.ratings-table td { font-size:11px; line-height:1.15; padding:3px 0; }
|
841 |
+
.ratings-table th { font-weight:bold; padding-right:8px; }
|
842 |
+
|
843 |
+
/* Availability */
|
844 |
+
.availability { margin:0; }
|
845 |
+
.availability span { font-weight:bold; }
|
846 |
+
.availability.in-stock span {}
|
847 |
+
.availability.out-of-stock span { color:#d83820; }
|
848 |
+
|
849 |
+
.availability-only { margin:10px 0 7px; line-height:16px; background:url(../images/i_availability_only.gif) 0 50% no-repeat; padding-left:15px; }
|
850 |
+
.availability-only span,
|
851 |
+
.availability-only a { border-bottom:1px dashed #751d02; color:#000; }
|
852 |
+
.availability-only a { background:url(../images/i_availability_only_arrow.gif) 100% 0 no-repeat; cursor:pointer; padding-right:15px; text-decoration:none; }
|
853 |
+
.availability-only .expanded { background-position:100% -15px; }
|
854 |
+
.availability-only strong { color:#be2c00; }
|
855 |
+
|
856 |
+
.availability-only-details { margin:0 0 7px; }
|
857 |
+
.availability-only-details th { background:#d2d6d9; font-size:10px; padding:0 8px; }
|
858 |
+
.availability-only-details td { background:#ebf0f3; border-bottom:1px solid #fff; font-size:11px; padding:2px 8px 1px; }
|
859 |
+
.availability-only-details tr.odd td.last { color:#d95e00; font-weight:bold; }
|
860 |
+
|
861 |
+
.product-view .product-shop .availability { font-size:11px; }
|
862 |
+
.product-view .product-shop .availability span { font-weight:normal; }
|
863 |
+
|
864 |
+
/* Email to a Friend */
|
865 |
+
.email-friend { margin:0; }
|
866 |
+
|
867 |
+
/* Alerts */
|
868 |
+
.alert-price { margin:0; font-size:11px; }
|
869 |
+
.alert-stock { margin:0; font-size:11px; }
|
870 |
+
|
871 |
+
/********** < Product Prices */
|
872 |
+
.price { white-space:nowrap !important; }
|
873 |
+
|
874 |
+
.price-box { margin:5px 0; }
|
875 |
+
.price-box .price { font-weight:bold; color:#c76200; }
|
876 |
+
|
877 |
+
/* Regular price */
|
878 |
+
.regular-price { color:#c76200; }
|
879 |
+
.regular-price .price { font-weight:bold; font-size:13px; color:#c76200; }
|
880 |
+
.block .regular-price,
|
881 |
+
.block .regular-price .price { color:#2f2f2f; }
|
882 |
+
|
883 |
+
/* Old price */
|
884 |
+
.old-price { margin:0; }
|
885 |
+
.old-price .price-label { white-space:nowrap; color:#999; }
|
886 |
+
.old-price .price { font-weight:bold; color:#c76200; text-decoration:line-through; }
|
887 |
+
|
888 |
+
/* Special price */
|
889 |
+
.special-price { margin:0; padding:3px 0; }
|
890 |
+
.special-price .price-label { font-size:13px; font-weight:bold; white-space:nowrap; color:#cd5033; }
|
891 |
+
.special-price .price { font-size:13px; font-weight:bold; color:#c76200; }
|
892 |
+
|
893 |
+
/* Minimal price (as low as) */
|
894 |
+
.minimal-price { margin:0; }
|
895 |
+
.minimal-price .price-label { font-weight:bold; white-space:nowrap; }
|
896 |
+
|
897 |
+
.minimal-price-link { display:block; }
|
898 |
+
.minimal-price-link .label {color:#1e7ec8;}
|
899 |
+
.minimal-price-link .price { font-weight:normal; color:#1e7ec8; }
|
900 |
+
|
901 |
+
/* Excluding tax */
|
902 |
+
.price-excluding-tax { display:block; color:#999; }
|
903 |
+
.price-excluding-tax .label { white-space:nowrap; color:#999; }
|
904 |
+
.price-excluding-tax .price { font-size:13px; font-weight:normal; color:#c76200; }
|
905 |
+
|
906 |
+
/* Including tax */
|
907 |
+
.price-including-tax { display:block; color:#999; }
|
908 |
+
.price-including-tax .label { white-space:nowrap; color:#999; }
|
909 |
+
.price-including-tax .price { font-size:13px; font-weight:bold; color:#c76200; }
|
910 |
+
|
911 |
+
/* Configured price */
|
912 |
+
.configured-price { margin:0; }
|
913 |
+
.configured-price .price-label { font-weight:bold; white-space:nowrap; }
|
914 |
+
.configured-price .price { font-weight:bold; }
|
915 |
+
|
916 |
+
/* FPT */
|
917 |
+
.weee { display:block; font-size:11px; color:#444; }
|
918 |
+
.weee .price { font-size:11px; font-weight:normal; }
|
919 |
+
|
920 |
+
/* Excl tax (for order tables) */
|
921 |
+
.price-excl-tax { display:block; }
|
922 |
+
.price-excl-tax .label { display:block; white-space:nowrap; }
|
923 |
+
.price-excl-tax .price { display:block; }
|
924 |
+
|
925 |
+
/* Incl tax (for order tables) */
|
926 |
+
.price-incl-tax { display:block; }
|
927 |
+
.price-incl-tax .label { display:block; white-space:nowrap; }
|
928 |
+
.price-incl-tax .price { display:block; font-weight:bold; }
|
929 |
+
|
930 |
+
/* Price range */
|
931 |
+
.price-from { margin:0; }
|
932 |
+
.price-from .price-label { font-weight:bold; white-space:nowrap; }
|
933 |
+
|
934 |
+
.price-to { margin:0; }
|
935 |
+
.price-to .price-label { font-weight:bold; white-space:nowrap; }
|
936 |
+
|
937 |
+
/* Price notice next to the options */
|
938 |
+
.price-notice { padding-left:10px; color:#999; }
|
939 |
+
.price-notice .price { font-weight:bold; color:#2f2f2f; }
|
940 |
+
|
941 |
+
/* Price as configured */
|
942 |
+
.price-as-configured { margin:0; }
|
943 |
+
.price-as-configured .price-label { font-weight:bold; white-space:nowrap; }
|
944 |
+
|
945 |
+
.price-box-bundle { padding:0 0 10px 0; }
|
946 |
+
.price-box-bundle .price-box { margin:0 !important; padding:0 !important; }
|
947 |
+
.price-box-bundle .price { color:#555; }
|
948 |
+
/********** Product Prices > */
|
949 |
+
|
950 |
+
/* Tier Prices */
|
951 |
+
.product-pricing,
|
952 |
+
.tier-prices { margin:10px 0; padding:10px; background-color:#f4f7f7; border:1px solid #dadddd; color:#424242; }
|
953 |
+
.tier-prices li { line-height:1.4; background:url(../images/i_tier.gif) no-repeat 0 3px; padding:2px 0 2px 10px; }
|
954 |
+
.tier-prices .benefit { font-style:italic; font-weight:bold; color:#2f2f2f; }
|
955 |
+
.tier-prices .price { font-weight:bold; color:#2f2f2f; }
|
956 |
+
|
957 |
+
.tier-prices-grouped li { padding:2px 0; color:#e26703; }
|
958 |
+
.tier-prices-grouped li .price { font-weight:bold; }
|
959 |
+
|
960 |
+
/* Add to Links */
|
961 |
+
.add-to-links { font-size:11px; margin:5px 0 0; }
|
962 |
+
.add-to-links .separator { display:none; }
|
963 |
+
|
964 |
+
/* Add to Cart */
|
965 |
+
.add-to-cart label { float:left; margin-right:5px; font-weight:bold; color:#666; }
|
966 |
+
.add-to-cart .qty { float:left; margin-right:5px; }
|
967 |
+
.add-to-cart button.button { float:left; }
|
968 |
+
.add-to-cart .paypal-logo { clear:left; margin:0; text-align:right; }
|
969 |
+
.add-to-cart .paypal-logo .paypal-or { clear:both; display:block; margin:5px 60px 5px 0; }
|
970 |
+
.product-view .add-to-cart .paypal-logo { margin:0; }
|
971 |
+
|
972 |
+
/* Add to Links + Add to Cart */
|
973 |
+
.add-to-box { margin:10px 0; }
|
974 |
+
.add-to-box .add-to-cart { float:left; }
|
975 |
+
.add-to-box .or { float:left; font-weight:bold; margin:0 7px; color:#666; }
|
976 |
+
.add-to-box .add-to-links { float:left; margin:0; font-size:12px !important; line-height:1.25 !important; text-align:left !important; }
|
977 |
+
.add-to-box .add-to-links li { display:block !important; }
|
978 |
+
.add-to-box .add-to-links li .separator { display:none !important; }
|
979 |
+
|
980 |
+
|
981 |
+
.product-view { border:1px solid #c4c6c8; }
|
982 |
+
|
983 |
+
.product-essential { padding:25px; background:#fff url(../images/bkg_product-view.gif) 100% 0 no-repeat; }
|
984 |
+
.product-essential h2 { font:bold 13px/1.35 Arial, Helvetica, sans-serif; }
|
985 |
+
|
986 |
+
.product-collateral { background:#faf7ee url(../images/bkg_product_collateral.gif) 0 0 repeat-x; padding:25px; }
|
987 |
+
.product-collateral h2 { font-weight:bold; font-size:15px; color:#e26703; border-bottom:1px solid #e5dcc3; padding:0 0 1px; margin:0 0 15px; }
|
988 |
+
.product-collateral .box-collateral { margin:0 0 25px; }
|
989 |
+
|
990 |
+
/* Product Images */
|
991 |
+
.product-view .product-img-box { float:left; width:267px; }
|
992 |
+
.col3-layout .product-view .product-img-box { float:none; margin:0 auto; }
|
993 |
+
.product-view .product-img-box .product-image { margin:0 0 13px; }
|
994 |
+
.product-view .product-img-box .product-image-zoom { position:relative; width:265px; height:265px; overflow:hidden; z-index:9; }
|
995 |
+
.product-view .product-img-box .product-image-zoom img { position:absolute; left:0; top:0; cursor:move; }
|
996 |
+
.product-view .product-img-box .zoom-notice { font-size:11px; margin:0 0 5px; text-align:center; }
|
997 |
+
.product-view .product-img-box .zoom { position:relative; z-index:9; height:18px; margin:0 auto 13px; padding:0 28px; background:url(../images/slider_bg.gif) 50% 50% no-repeat; cursor:pointer; }
|
998 |
+
.product-view .product-img-box .zoom.disabled { -moz-opacity:.3; -webkit-opacity:.3; -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=30)";/*IE8*/ opacity:.3; }
|
999 |
+
.product-view .product-img-box .zoom #track { position:relative; height:18px; }
|
1000 |
+
.product-view .product-img-box .zoom #handle { position:absolute; left:0; top:-1px; width:9px; height:22px; background:url(../images/magnifier_handle.gif) 0 0 no-repeat; }
|
1001 |
+
.product-view .product-img-box .zoom .btn-zoom-out { position:absolute; left:2px; top:0; }
|
1002 |
+
.product-view .product-img-box .zoom .btn-zoom-in { position:absolute; right:2px; top:0; }
|
1003 |
+
.product-view .product-img-box .more-views h2 { font-size:11px; border-bottom:1px solid #ccc; margin:0 0 8px; text-transform:uppercase; }
|
1004 |
+
.product-view .product-img-box .more-views ul { margin-left:-9px }
|
1005 |
+
.product-view .product-img-box .more-views li { float:left; margin:0 0 8px 9px; }
|
1006 |
+
.product-view .product-img-box .more-views li a { float:left; width:56px; height:56px; border:2px solid #ddd; overflow:hidden; }
|
1007 |
+
|
1008 |
+
.product-image-popup { margin:0 auto; }
|
1009 |
+
.product-image-popup .buttons-set { float:right; clear:none; border:0; margin:0; padding:0; }
|
1010 |
+
.product-image-popup .nav { font-weight:bold; margin:0 100px; text-align:center; }
|
1011 |
+
.product-image-popup .image { display:block; margin:10px 0; }
|
1012 |
+
.product-image-popup .image-label { font-size:13px; font-weight:bold; margin:0 0 10px; color:#2f2f2f; }
|
1013 |
+
|
1014 |
+
/* Product Shop */
|
1015 |
+
.product-view .product-shop { float:right; width:330px; }
|
1016 |
+
.col1-layout .product-view .product-shop { float:right; width:545px; }
|
1017 |
+
.col3-layout .product-view .product-shop { float:none; width:auto; }
|
1018 |
+
.product-view .product-shop .product-name { margin:0 0 5px; }
|
1019 |
+
.product-view .product-shop .product-name h1 { margin:0; font:bold 15px/1.35 Arial, Helvetica, sans-serif; }
|
1020 |
+
.product-view .product-shop .availability { margin:10px 0; }
|
1021 |
+
.product-view .product-shop .short-description { margin:10px 0; background:url(../images/bkg_divider1.gif) 0 0 repeat-x; padding:10px 0 0; }
|
1022 |
+
.product-view .product-shop .price-box { margin:10px 0; }
|
1023 |
+
.product-view .product-shop .add-to-links { margin:0; }
|
1024 |
+
.product-view .product-shop .add-to-links { font-size:12px; text-align:right; }
|
1025 |
+
.product-view .product-shop .add-to-links li,
|
1026 |
+
.product-view .product-shop .add-to-links li .separator { display:inline; }
|
1027 |
+
.product-view .product-shop .add-to-links a { color:#1E7EC8 !important; font-weight:normal !important; }
|
1028 |
+
|
1029 |
+
/* Product Options */
|
1030 |
+
.product-options { margin:20px 0 0; padding:10px 15px 20px; position:relative; background-color:#f6f6f6; border:1px solid #e4e4e4; }
|
1031 |
+
.product-options dt { padding:10px 0 0; font-weight:normal; }
|
1032 |
+
.product-options dt label { font-weight:bold; color:#2f2f2f; }
|
1033 |
+
.product-options dt label.required em { color:#eb340a; margin-left:5px; }
|
1034 |
+
.product-options dd .qty-holder { display:block; padding:10px 0 0; }
|
1035 |
+
.product-options dd .qty-holder label { vertical-align:middle; }
|
1036 |
+
.product-options dt .qty-disabled { background:none; border:0; padding:3px; color:#2f2f2f; }
|
1037 |
+
.product-options dd { padding:5px 10px 15px; margin:0 0 5px; border-bottom:1px solid #e4e4e4; }
|
1038 |
+
.product-options dl.last dd.last { border-bottom:0; padding-bottom:5px; margin-bottom:0; }
|
1039 |
+
.product-options dd input.input-text { width:98%; }
|
1040 |
+
.product-options dd input.datetime-picker { width:150px; }
|
1041 |
+
.product-options dd .time-picker { display:-moz-inline-box; display:inline-block; padding:2px 0; vertical-align:middle; }
|
1042 |
+
.product-options dd textarea { width:98%; height:8em; }
|
1043 |
+
.product-options dd select { width:99%; }
|
1044 |
+
.product-options dd .multiselect option { border-bottom:1px dotted #d9e5ee; padding:2px 4px; }
|
1045 |
+
.product-options ul.options-list { margin-right:5px; }
|
1046 |
+
.product-options ul.options-list li { line-height:1.5; padding:2px 0; }
|
1047 |
+
.product-options ul.options-list input.radio { float:left; margin-top:3px; }
|
1048 |
+
.product-options ul.options-list input.checkbox { float:left; margin-top:3px; }
|
1049 |
+
.product-options ul.options-list .label { display:block; margin-left:18px; }
|
1050 |
+
.product-options ul.options-list label { font-weight:normal; }
|
1051 |
+
.product-options ul.validation-failed { padding:0 7px; }
|
1052 |
+
.product-options p.note { margin:0; font-size:11px; }
|
1053 |
+
.product-options p.required { position:absolute; right:20px; top:20px; }
|
1054 |
+
|
1055 |
+
.product-options-bottom { background-color:#fffada; padding:15px 20px; border:1px solid #e4e4e4; border-top:0; }
|
1056 |
+
.product-options-bottom .product-pricing,
|
1057 |
+
.product-options-bottom .tier-prices { margin:0; padding:0 0 10px; border:0; background:0; color:#e26703; }
|
1058 |
+
.product-options-bottom .tier-prices li { background:0; padding:2px 0; }
|
1059 |
+
.product-options-bottom .tier-prices .price,
|
1060 |
+
.product-options-bottom .tier-prices .benefit { color:#e26703; }
|
1061 |
+
.product-options-bottom .price-box { float:left; margin:0; padding:0; }
|
1062 |
+
.product-options-bottom .add-to-links { clear:both; padding:5px 0 0; text-align:right; }
|
1063 |
+
.col3-layout .product-options-bottom .price-box { float:none; padding:0 0 5px; }
|
1064 |
+
.product-options-bottom .price-label { float:left; padding-right:5px; }
|
1065 |
+
.product-options-bottom .price-tax { float:left; }
|
1066 |
+
.product-options-bottom .add-to-cart { float:right; }
|
1067 |
+
.product-shop .product-options-bottom { margin:0 0 10px; }
|
1068 |
+
.product-shop .product-options-bottom .price-box { float:none; margin:0 0 5px; }
|
1069 |
+
.product-shop .product-options-bottom .price-label { float:none; padding-right:0; }
|
1070 |
+
.product-shop .product-options-bottom .price-tax { float:none; }
|
1071 |
+
.product-shop .product-options-bottom .add-to-cart-box { clear:both; float:left; padding-top:12px; }
|
1072 |
+
.product-shop .product-options-bottom .add-to-links { clear:both; padding:5px 0 0; text-align:right; }
|
1073 |
+
|
1074 |
+
/* Grouped Product */
|
1075 |
+
.product-view .grouped-items-table .price-box { margin:0; padding:0; }
|
1076 |
+
|
1077 |
+
/* Block: Description */
|
1078 |
+
.product-view .box-description {}
|
1079 |
+
|
1080 |
+
/* Block: Additional */
|
1081 |
+
.product-view .box-additional .data-table th,
|
1082 |
+
.product-view .box-additional .data-table td { line-height:1.25; }
|
1083 |
+
|
1084 |
+
/* Block: Upsell */
|
1085 |
+
.product-view .box-up-sell h2 { border-bottom:0; padding:0; margin:0 0 8px; }
|
1086 |
+
.product-view .box-up-sell .products-grid { width:100%; border:1px solid #e5dcc3; }
|
1087 |
+
.product-view .box-up-sell .products-grid td { width:25%; background:#f6f2e7; border-right:1px solid #e5dcc3; border-bottom:1px solid #e5dcc3; padding:15px 10px 12px; line-height:1.6em; }
|
1088 |
+
.product-view .box-up-sell .products-grid tr.last td { border-bottom:0; }
|
1089 |
+
.product-view .box-up-sell .products-grid td.last { border-right:0; }
|
1090 |
+
.product-view .box-up-sell .products-grid td img { border:1px solid #e5dcc3; }
|
1091 |
+
.product-view .box-up-sell .products-grid .product-image { text-align:center; }
|
1092 |
+
.product-view .box-up-sell .products-grid td.empty { border-right:0; background:#f1ecdb; }
|
1093 |
+
.product-view .box-up-sell .products-grid .ratings .rating-box { float:none; display:block; margin:0 0 3px; }
|
1094 |
+
|
1095 |
+
/* Block: Tags */
|
1096 |
+
.product-view .box-tags { margin:0; }
|
1097 |
+
.product-view .box-tags h3 { font-size:13px; }
|
1098 |
+
.product-view .box-tags .product-tags { display:block; margin:0 0 15px; }
|
1099 |
+
.product-view .box-tags .product-tags li { display:inline; background:url(../images/bkg_pipe3.gif) 100% 4px no-repeat; padding:0 7px 0 4px; }
|
1100 |
+
.product-view .box-tags .product-tags li.first { padding-left:0; }
|
1101 |
+
.product-view .box-tags .product-tags li.last { background:none; padding-right:0; }
|
1102 |
+
.product-view .box-tags .form-add label { display:block; font-size:13px; font-weight:bold; margin:0 0 5px; color:#0a263c;}
|
1103 |
+
.product-view .box-tags .form-add .input-box { float:left; width:305px; margin:0 5px 0 0; background:url(../images/i_tag_add.gif) 0 2px no-repeat; padding:0 0 0 23px; }
|
1104 |
+
.product-view .box-tags .form-add input.input-text { width:299px; }
|
1105 |
+
.product-view .box-tags .form-add button.button span { border-color:#406a83; background:#618499; }
|
1106 |
+
.product-view .box-tags .note { margin:3px 0 0; padding:0 0 0 23px; font-size:11px; }
|
1107 |
+
|
1108 |
+
/* Block: Reviews */
|
1109 |
+
.product-view .box-reviews dl { margin:15px 0; }
|
1110 |
+
.product-view .box-reviews dt a,
|
1111 |
+
.product-view .box-reviews dt span { font-weight:bold; }
|
1112 |
+
.product-view .box-reviews dd { margin:0 0 15px; }
|
1113 |
+
.product-view .box-reviews dd small { font-style:italic; }
|
1114 |
+
.product-view .box-reviews .form-add { margin:15px 0 0; }
|
1115 |
+
.product-view .box-reviews .form-add h3 { font-size:13px; font-weight:normal; }
|
1116 |
+
.product-view .box-reviews .form-add h3 span { font-weight:bold; }
|
1117 |
+
.product-view .box-reviews .form-add h4 { font-size:12px; }
|
1118 |
+
.product-view .box-reviews .form-add .data-table td { text-align:center; }
|
1119 |
+
.product-view .box-reviews .form-add .form-list { margin:15px 0 0; }
|
1120 |
+
.product-view .box-reviews .form-add .form-list .input-box { width:360px; }
|
1121 |
+
.product-view .box-reviews .form-add .form-list input.input-text,
|
1122 |
+
.product-view .box-reviews .form-add .form-list textarea { width:354px; }
|
1123 |
+
|
1124 |
+
/* Send a Friend */
|
1125 |
+
.send-friend .form-list { width:615px; overflow:hidden; }
|
1126 |
+
.send-friend .form-list li { margin-right:-15px; }
|
1127 |
+
.send-friend .form-list li p { margin:0 15px 0 0; }
|
1128 |
+
.send-friend .form-list .field { width:315px; }
|
1129 |
+
.send-friend .form-list .input-box { width:300px; }
|
1130 |
+
.send-friend .form-list input.input-text,
|
1131 |
+
.send-friend .form-list textarea { width:294px; }
|
1132 |
+
.send-friend .form-list li.wide .input-box { width:612px; }
|
1133 |
+
.send-friend .form-list li.wide textarea { width:609px; }
|
1134 |
+
.send-friend .buttons-set .limit { float:right; margin:0 7px 0 0; font-size:11px; line-height:21px; }
|
1135 |
+
/* ======================================================================================= */
|
1136 |
+
|
1137 |
+
|
1138 |
+
/* Content Styles ================================================================= */
|
1139 |
+
.product-name { margin:0; font-size:1em; font-weight:normal; }
|
1140 |
+
.product-name a { color:#1e7ec8; }
|
1141 |
+
|
1142 |
+
/* Product Tags */
|
1143 |
+
.tags-list { display:block; font-size:13px; border:1px solid #c1c4bc; background:#f8f7f5; padding:10px; }
|
1144 |
+
.tags-list li { display:inline !important; margin:0 4px 0 0; }
|
1145 |
+
.tags-list li a { color:#1b2d3b; }
|
1146 |
+
|
1147 |
+
/* Advanced Search */
|
1148 |
+
.advanced-search .form-list label { width:160px; padding-right:10px; }
|
1149 |
+
.advanced-search .form-list .input-box,
|
1150 |
+
.advanced-search .form-list .input-range { float:left; clear:none; }
|
1151 |
+
.advanced-search-amount { margin:0 0 10px; }
|
1152 |
+
.advanced-search-summary { margin:10px 0; border:1px solid #e9d7c9; background:#fff6f1; padding:10px; }
|
1153 |
+
.advanced-search-summary ul { float:left; width:49%; }
|
1154 |
+
.advanced-search-summary strong { color:#E17C24; padding-left:15px; background:url(../images/i_search_criteria.gif) 0 3px no-repeat; }
|
1155 |
+
.advanced-search-summary p { clear:both; font-weight:bold; margin:0; }
|
1156 |
+
|
1157 |
+
/* CMS Home Page */
|
1158 |
+
.cms-home .subtitle {}
|
1159 |
+
.cms-index-index .subtitle {}
|
1160 |
+
|
1161 |
+
/* Sitemap */
|
1162 |
+
.page-sitemap .links { text-align:right; margin:0 8px -22px 0; }
|
1163 |
+
.page-sitemap .links a { text-decoration:none; position:relative; }
|
1164 |
+
.page-sitemap .links a:hover { text-decoration:underline; }
|
1165 |
+
.page-sitemap .sitemap { margin:12px; }
|
1166 |
+
.page-sitemap .sitemap a { color:#1b2d3b; }
|
1167 |
+
.page-sitemap .sitemap li { margin:3px 0; }
|
1168 |
+
.page-sitemap .sitemap li.level-0 { margin:10px 0 0; font-weight:bold; }
|
1169 |
+
.page-sitemap .sitemap li.level-0 a { color:#1e7ec8; }
|
1170 |
+
|
1171 |
+
/* RSS */
|
1172 |
+
.rss-title h1 { background:url(../images/i_rss-big.png) 0 4px no-repeat; padding-left:27px; }
|
1173 |
+
.rss-table .link-rss { display:block; line-height:1.55; background-position:0 4px; }
|
1174 |
+
/* ======================================================================================= */
|
1175 |
+
|
1176 |
+
|
1177 |
+
/* Shopping Cart ========================================================================= */
|
1178 |
+
.cart .page-title { border-bottom:0; margin:0 0 12px; }
|
1179 |
+
.cart .page-title h1 { margin:10px 0 0; }
|
1180 |
+
|
1181 |
+
/* Checkout Types */
|
1182 |
+
.cart .page-title .checkout-types li { margin:0 0 5px; }
|
1183 |
+
.cart .title-buttons .checkout-types { float:right; }
|
1184 |
+
.cart .title-buttons .checkout-types li { float:left; margin:0 0 5px 5px; }
|
1185 |
+
.cart .checkout-types .paypal-or { margin:0 8px; line-height:2.3; }
|
1186 |
+
.cart .totals .checkout-types .paypal-or { clear:both; display:block; padding:8px 55px 0 0; line-height:1.0; font-size:11px; }
|
1187 |
+
|
1188 |
+
/* Shopping Cart Table */
|
1189 |
+
.cart-table th { padding:2px 10px; }
|
1190 |
+
.cart-table td { padding:10px; }
|
1191 |
+
.cart-table .product-name { font-weight:bold; margin:0 0 5px; color:#2f2f2f; }
|
1192 |
+
.cart-table .item-msg { margin:5px 0; font-size:11px; font-weight:bold; color:#df280a; }
|
1193 |
+
.cart-table tfoot td { padding:5px 10px; }
|
1194 |
+
.cart-table .btn-continue { float:left; }
|
1195 |
+
.cart-table .btn-empty span,
|
1196 |
+
.cart-table .btn-continue span,
|
1197 |
+
.cart-table .btn-update span { border-color:#406a83; background:#618499; }
|
1198 |
+
.cart-table .btn-update,
|
1199 |
+
.cart-table .btn-empty { float:right; }
|
1200 |
+
.cart-table .btn-update { margin-left:10px; }
|
1201 |
+
|
1202 |
+
/* Shopping Cart Collateral boxes */
|
1203 |
+
.cart .cart-collaterals { padding:25px 0 0; }
|
1204 |
+
.cart .cart-collaterals .col2-set { float:left; width:605px; }
|
1205 |
+
.cart .cart-collaterals .col2-set .col-2 { width:294px; }
|
1206 |
+
|
1207 |
+
.cart .crosssell { border:1px solid #cec3b6; background:#fafaec; padding:12px 15px; }
|
1208 |
+
.cart .crosssell h2 { font-size:13px; font-weight:bold; }
|
1209 |
+
.cart .crosssell .product-image { float:left; width:75px; height:75px; border:1px solid #d0cdc9; }
|
1210 |
+
.cart .crosssell .product-details { margin-left:90px; }
|
1211 |
+
.cart .crosssell .product-name { font-weight:bold; }
|
1212 |
+
.cart .crosssell li.item { margin:12px 0; }
|
1213 |
+
.cart .crosssell .link-compare { font-weight:normal; }
|
1214 |
+
|
1215 |
+
/* Discount Codes & Estimate Shipping and Tax Boxes */
|
1216 |
+
.cart .discount,
|
1217 |
+
.cart .shipping { border:1px solid #d0cbc1; background:#fff url(../images/bkg_block-title.gif) 0 0 repeat-x; padding:12px 15px; margin:0 0 18px; }
|
1218 |
+
.cart .discount h2,
|
1219 |
+
.cart .shipping h2 { background-position:0 0; background-repeat:no-repeat; font:bold 13px/16px Arial, Helvetica, sans-serif; padding:0 0 0 21px; color:#e26703; text-transform:uppercase; }
|
1220 |
+
.cart .discount button span,
|
1221 |
+
.cart .shipping button span { border-color:#406a83; background:#618499; }
|
1222 |
+
.cart .discount .buttons-set,
|
1223 |
+
.cart .shipping .buttons-set { margin:10px 0 0; border:0; padding:0; text-align:left; }
|
1224 |
+
.cart .discount .buttons-set button.button,
|
1225 |
+
.cart .shipping .buttons-set button.button { float:none; margin-left:0; }
|
1226 |
+
|
1227 |
+
.cart .discount h2 { background-image:url(../images/i_discount.gif); }
|
1228 |
+
.cart .discount .input-box { margin:8px 0 0; width:260px; }
|
1229 |
+
.cart .discount input.input-text { width:254px; }
|
1230 |
+
|
1231 |
+
.cart .shipping h2 { background-image:url(../images/i_shipping.gif); }
|
1232 |
+
.cart .shipping .sp-methods { margin:10px 0 0; padding:5px 0 0; background:url(../images/bkg_divider1.gif) 0 0 repeat-x; }
|
1233 |
+
|
1234 |
+
/* Shopping Cart Totals */
|
1235 |
+
.cart .totals { float:right; width:268px; background:#dee5e8; border:1px solid #bebcb7; }
|
1236 |
+
.cart .totals table { width:100%; margin:7px 0; }
|
1237 |
+
.cart .totals td { padding:1px 15px 1px 7px; }
|
1238 |
+
.cart .totals tr.last td {}
|
1239 |
+
.cart .totals tfoot th { padding:5px 15px 5px 7px; }
|
1240 |
+
.cart .totals tfoot td { padding-top:5px; padding-bottom:5px; }
|
1241 |
+
.cart .totals tfoot th strong,
|
1242 |
+
.cart .totals tfoot td strong { font-size:15px; }
|
1243 |
+
.cart .totals .checkout-types { font-size:13px; padding:8px 15px 15px; text-align:right; }
|
1244 |
+
.cart .totals .checkout-types li { clear:both; margin:10px 0; }
|
1245 |
+
|
1246 |
+
/* Options Tool Tip */
|
1247 |
+
.item-options dt { font-weight:bold; font-style:italic; }
|
1248 |
+
.item-options dd { padding-left:10px; margin:0 0 6px; }
|
1249 |
+
.truncated { cursor:help; }
|
1250 |
+
.truncated a.dots { cursor:help; }
|
1251 |
+
.truncated a.details { cursor:help; }
|
1252 |
+
.truncated .truncated_full_value { position:relative; z-index:999; }
|
1253 |
+
.truncated .truncated_full_value .item-options { position:absolute; top:-99999em; left:-99999em; z-index:999; width:250px; padding:8px; border:1px solid #ddd; background-color:#f6f6f6; }
|
1254 |
+
.truncated .truncated_full_value .item-options > p { font-weight:bold; text-transform:uppercase; }
|
1255 |
+
.truncated .show .item-options { top:-20px; left:50%; }
|
1256 |
+
.col-left .truncated .show .item-options { left:15px; top:7px; }
|
1257 |
+
.col-right .truncated .show .item-options { left:-240px; top:7px; }
|
1258 |
+
/* ======================================================================================= */
|
1259 |
+
|
1260 |
+
|
1261 |
+
/* Checkout ============================================================================== */
|
1262 |
+
/********** < Common Checkout Styles */
|
1263 |
+
/* Shipping and Payment methods */
|
1264 |
+
.sp-methods { margin:0 0 8px; }
|
1265 |
+
.sp-methods dt { margin:13px 0 5px; font-weight:bold; }
|
1266 |
+
.sp-methods dd {}
|
1267 |
+
.sp-methods dd li { margin:5px 0; }
|
1268 |
+
.sp-methods label { font-weight:bold; color:#666; }
|
1269 |
+
.sp-methods .price { font-weight:bold; }
|
1270 |
+
.sp-methods .form-list { padding-left:20px; }
|
1271 |
+
.sp-methods .form-list li { margin:0 0 8px; }
|
1272 |
+
.sp-methods select.month { width:154px; margin-right:10px; }
|
1273 |
+
.sp-methods select.year { width:96px; }
|
1274 |
+
.sp-methods input.cvv { width:3em !important; }
|
1275 |
+
|
1276 |
+
.sp-methods .checkmo-list li { margin:0 0 5px; }
|
1277 |
+
.sp-methods .checkmo-list label { width:135px; padding-right:10px; text-align:right; }
|
1278 |
+
.sp-methods .checkmo-list address { float:left; }
|
1279 |
+
|
1280 |
+
.sp-methods .centinel-logos a { margin-right:3px; }
|
1281 |
+
.sp-methods .centinel-logos img { vertical-align:middle; }
|
1282 |
+
|
1283 |
+
.sp-methods .release-amounts { margin:0.5em 0; }
|
1284 |
+
.sp-methods .release-amounts button { float:left; margin:5px 10px 0 0; }
|
1285 |
+
|
1286 |
+
.please-wait { float:right; }
|
1287 |
+
.please-wait img { vertical-align:middle; }
|
1288 |
+
.cvv-what-is-this { font-size:11px; cursor:help; margin-left:10px; }
|
1289 |
+
|
1290 |
+
/* Tooltip */
|
1291 |
+
.tool-tip { border:1px solid #7BA7C9; background:#EAF6FF; padding:15px 20px; position:absolute; z-index:9999; }
|
1292 |
+
.tool-tip .btn-close { margin:-9px -14px 0; text-align:right; }
|
1293 |
+
.tool-tip .btn-close a { display:block; margin:0 0 0 auto; width:15px; height:15px; background:url(../images/btn_window_close.gif) 100% 0 no-repeat; text-align:left; text-indent:-999em; overflow:hidden; }
|
1294 |
+
.tool-tip .tool-tip-content { padding:5px; }
|
1295 |
+
|
1296 |
+
/* Gift Messages */
|
1297 |
+
.gift-messages h3 { font-size:12px; font-weight:bold; color:#e87403; }
|
1298 |
+
.gift-messages p.control { color:#8e8d8b; }
|
1299 |
+
.gift-messages-form { position:relative; }
|
1300 |
+
.gift-messages-form label { float:none !important; position:static !important; }
|
1301 |
+
.gift-messages-form h4 { font-size:12px; font-weight:bold; color:#e87403; }
|
1302 |
+
.gift-messages-form .whole-order { margin:0 0 25px; }
|
1303 |
+
.gift-messages-form .item { margin:0 0 10px; }
|
1304 |
+
.gift-messages-form .item .product-img-box { float:left; width:75px; }
|
1305 |
+
.gift-messages-form .item .product-image { margin:0 0 7px; }
|
1306 |
+
.gift-messages-form .item .number { margin:0; font-weight:bold; text-align:center; color:#8a8987; }
|
1307 |
+
.gift-messages-form .item .details { margin-left:90px; }
|
1308 |
+
.gift-messages-form .item .details .product-name { font-size:13px; font-weight:bold; margin:0 0 10px; }
|
1309 |
+
.gift-messages-form .item .details .form-list .field { width:255px; }
|
1310 |
+
.gift-messages-form .item .details .form-list .input-box { width:240px; }
|
1311 |
+
.gift-messages-form .item .details .form-list input.input-text { width:234px; }
|
1312 |
+
.gift-messages-form .item .details .form-list li.wide .input-box { width:500px; }
|
1313 |
+
.gift-messages-form .item .details .form-list li.wide textarea { width:494px; }
|
1314 |
+
|
1315 |
+
.gift-message-link { font-size:11px; background:url(../images/bkg_collapse-gm.gif) 100% 6px no-repeat; padding-right:7px; }
|
1316 |
+
.gift-message-link.expanded { background-position:100% -40px; }
|
1317 |
+
.gift-message-row { background:#f2efe9; }
|
1318 |
+
.gift-message-row .btn-close { float:right; width:16px; height:16px; background:url(../images/btn_gm-close.gif) 0 0 no-repeat; font-size:0; line-height:0; text-indent:-999em; overflow:hidden; }
|
1319 |
+
|
1320 |
+
/* Checkout Agreements */
|
1321 |
+
.checkout-agreements li { margin:30px 0; }
|
1322 |
+
.checkout-agreements .agreement-content { overflow:auto; height:12em; padding:10px; background-color:#fbfaf6; border:1px solid #bbb6a5; }
|
1323 |
+
.checkout-agreements .agree { margin:0; padding:10px 0 10px 11px; }
|
1324 |
+
.checkout-agreements .agree input.checkbox { margin-right:6px; }
|
1325 |
+
.checkout-agreements .agree label { font-weight:bold; color:#666; }
|
1326 |
+
|
1327 |
+
.opc .checkout-agreements { border:1px solid #d9dde3; border-width:0 1px; padding:5px 30px; }
|
1328 |
+
.opc .checkout-agreements li { margin:20px 0 0; }
|
1329 |
+
.opc .checkout-agreements .agreement-content { background-color:#fff; border-color:#e4e4e4; padding:5px; }
|
1330 |
+
.opc .checkout-agreements .agree { padding-left:6px; }
|
1331 |
+
|
1332 |
+
/* Centinel */
|
1333 |
+
.centinel {}
|
1334 |
+
.centinel .authentication { border:1px solid #ddd; background:#fff; }
|
1335 |
+
.centinel .authentication iframe { width:99%; height:400px; background:transparent !important; margin:0 !important; padding:0 !important; border:0 !important; }
|
1336 |
+
|
1337 |
+
.opc .centinel { border:1px solid #bbb6a5; border-width:0 1px 1px; padding:10px 30px; }
|
1338 |
+
|
1339 |
+
/* Generic Info Set */
|
1340 |
+
.info-set { background:#fbfaf6 url(../images/bkg_checkout.gif) 0 0 repeat-x; border:1px solid #bbb6a5; margin:0 0 25px; padding:20px; }
|
1341 |
+
.info-set h2 { font-size:13px; font-weight:bold; margin:0 0 10px; }
|
1342 |
+
.info-set h3,
|
1343 |
+
.info-set h4 { font-size:13px; font-weight:bold; color:#E26703; }
|
1344 |
+
.info-set h2 a,
|
1345 |
+
.info-set h3 a,
|
1346 |
+
.info-set h4 a { font-weight:normal; }
|
1347 |
+
.info-set h2.legend { margin:-20px -20px 15px; padding:5px 10px; background:#f9f3e3; border-bottom:1px solid #bbafa0; position:relative; }
|
1348 |
+
.info-set h3.legend { margin:0 0 10px; color:#0a263c; }
|
1349 |
+
.info-set .divider { margin:0 -20px; padding:25px 0; position:relative; }
|
1350 |
+
.info-set .box { margin:0 0 15px; }
|
1351 |
+
.info-set .box h2 { color:#e26703; }
|
1352 |
+
.info-set .data-table .product-name { font-size:1em !important; font-weight:bold !important; color:#1e7ec8 !important; }
|
1353 |
+
.info-set .data-table .product-name a { font-weight:bold !important; }
|
1354 |
+
.info-set .data-table .item-options { margin:5px 0 0; }
|
1355 |
+
/********** Common Checkout Styles > */
|
1356 |
+
|
1357 |
+
/* One Page Checkout */
|
1358 |
+
.block-progress { border:0; margin:0; }
|
1359 |
+
.block-progress .block-title { background:none; border:0; padding:0; margin:0 0 5px; }
|
1360 |
+
.block-progress .block-title strong { font-size:13px; color:#0a263c; }
|
1361 |
+
.block-progress .block-content { background:none; }
|
1362 |
+
.block-progress dt { font-size:13px; font-weight:bold; line-height:1.35; background:#eee; border:1px solid #a3aeb3; margin:0 0 6px; padding:2px 8px; color:#999; }
|
1363 |
+
.block-progress dd { background:#eee; border:1px solid #a3aeb3; border-top:0; padding:8px 13px; margin:0 0 6px; }
|
1364 |
+
.block-progress dt.complete { margin:0; background:#d0dce1; color:#5e8ab4; }
|
1365 |
+
.block-progress dd.complete {}
|
1366 |
+
.block-progress p { margin:0; }
|
1367 |
+
.block-progress .cards-list dt { background:none; border:0 none; color:inherit; font-size:12px; margin:5px 0; padding:0; }
|
1368 |
+
.block-progress .cards-list dd { border:0 none; margin:0; padding:0; }
|
1369 |
+
.block-progress .cards-list .info-table th { font-weight:normal; }
|
1370 |
+
|
1371 |
+
.opc .buttons-set { margin-top:0; padding-top:2em; }
|
1372 |
+
.opc .buttons-set p.required { margin:0; padding:0 0 10px; }
|
1373 |
+
.opc .buttons-set .back-link small { display:none; }
|
1374 |
+
.opc .buttons-set .back-link a { background:url(../images/i_arrow-top.gif) 0 50% no-repeat; padding-left:16px; }
|
1375 |
+
.opc .buttons-set.disabled button.button { display:none; }
|
1376 |
+
.opc .buttons-set .please-wait { height:21px; line-height:21px; }
|
1377 |
+
.opc .ul { list-style:disc outside; padding-left:18px; }
|
1378 |
+
|
1379 |
+
.opc { position:relative; }
|
1380 |
+
.opc li.section {}
|
1381 |
+
|
1382 |
+
.opc .step-title { border-width:0 1px; border-style:solid; border-color:#fff #d9dde3 #d9dde3; background:#eee url(../images/bkg_opc-title-off.gif) 0 100% repeat-x; padding:4px 8px 6px; text-align:right; }
|
1383 |
+
.opc .step-title .number { float:left; background:#fff; border:1px solid #fff; padding:0 4px; margin:0 5px 0 0; font:bold 11px/14px arial, helvetica, sans-serif; color:#999; }
|
1384 |
+
.opc .step-title h2 { float:left; margin:0; font:bold 13px/16px Arial, Helvetica, sans-serif; color:#999; }
|
1385 |
+
.opc .step-title a { display:none; float:right; font-size:11px; line-height:16px; }
|
1386 |
+
|
1387 |
+
.opc .allow .step-title { background:#d0dce1; border:1px solid #a3aeb3; border-bottom:0; color:#a4b3b9; cursor:pointer; }
|
1388 |
+
.opc .allow .step-title .number { background:#dbe6eb; border-color:#dbe6eb; color:#a4b3b9; }
|
1389 |
+
.opc .allow .step-title h2 { color:#a4b3b9; }
|
1390 |
+
/*.opc .allow .step-title a { display:block; }*/
|
1391 |
+
|
1392 |
+
.opc .active .step-title { background:#f9f3e3; border:1px solid #bbafa0; padding-bottom:5px; color:#f18200; cursor:default; }
|
1393 |
+
.opc .active .step-title .number { background:#f18200; border-color:#f19900; color:#fff; }
|
1394 |
+
.opc .active .step-title h2 { color:#f18200; }
|
1395 |
+
/*.opc .active .step-title a { display:none; }*/
|
1396 |
+
|
1397 |
+
.opc .step { border:1px solid #bbafa0; border-top:0; background:#fbfaf6 url(../images/bkg_checkout.gif) 0 0 repeat-x; padding:15px 30px; position:relative; }
|
1398 |
+
.opc .step .tool-tip { right:30px; }
|
1399 |
+
|
1400 |
+
#opc-login .buttons-set { border-top:0; }
|
1401 |
+
#opc-login h3 { font-size:13px; border-bottom:1px solid #e4e4e4; padding-bottom:2px; text-transform:uppercase; }
|
1402 |
+
#opc-login h4 { font-size:1em; font-weight:bold; margin:0; color:#2f2f2f; }
|
1403 |
+
|
1404 |
+
#opc-shipping_method .buttons-set { border-top:0; }
|
1405 |
+
.opc .gift-messages-form { margin:0 -30px; background:#f6f1eb; border:1px solid #e9e4de; border-width:1px 0; padding:22px 24px 22px 30px; }
|
1406 |
+
.opc .gift-messages-form .inner-box { padding:5px; height:260px; overflow:auto; }
|
1407 |
+
|
1408 |
+
#opc-review .step { border:0; padding:0; }
|
1409 |
+
#opc-review .product-name { font-weight:bold; color:#0a263c; }
|
1410 |
+
#opc-review .item-options { margin:5px 0 0; }
|
1411 |
+
#opc-review .buttons-set { padding:20px 30px; border:1px solid #d9dde3; border-width:0 1px 1px; }
|
1412 |
+
#opc-review .buttons-set p { margin:0; line-height:40px; }
|
1413 |
+
#opc-review .buttons-set .please-wait { height:40px; line-height:40px; }
|
1414 |
+
#opc-review .authentication { margin:0 auto; width:570px; }
|
1415 |
+
#opc-review .warning-message { color:#222; font-weight:bold; text-align:center; padding:10px 10px 0; }
|
1416 |
+
|
1417 |
+
/* Multiple Addresses Checkout */
|
1418 |
+
.checkout-progress { padding:0 90px; margin:0 0 20px; }
|
1419 |
+
.checkout-progress li { float:left; width:19%; margin:0 3px 0 0; border-top:10px solid #999; padding:2px 0 0; font-weight:bold; text-align:center; color:#abb5ba; }
|
1420 |
+
.checkout-progress li.active { border-top-color:#e96200; color:#e96200; }
|
1421 |
+
|
1422 |
+
.multiple-checkout h2 { font-size:13px; font-weight:bold; margin:0 0 10px; }
|
1423 |
+
.multiple-checkout h3,
|
1424 |
+
.multiple-checkout h4 { font-size:13px; font-weight:bold; color:#E26703; }
|
1425 |
+
.multiple-checkout h2 a,
|
1426 |
+
.multiple-checkout h3 a,
|
1427 |
+
.multiple-checkout h4 a { font-weight:normal; }
|
1428 |
+
.multiple-checkout .data-table .product-name { font-size:1em !important; font-weight:bold !important; color:#1e7ec8 !important; }
|
1429 |
+
.multiple-checkout .data-table .product-name a { font-weight:bold !important; }
|
1430 |
+
.multiple-checkout .data-table .item-options { margin:5px 0 0; }
|
1431 |
+
|
1432 |
+
.multiple-checkout .gift-messages { margin:15px 0 0; }
|
1433 |
+
|
1434 |
+
.multiple-checkout .tool-tip { top:50%; margin-top:-120px; right:20px; }
|
1435 |
+
|
1436 |
+
.multiple-checkout .col2-set,
|
1437 |
+
.multiple-checkout .col3-set { background:#fbfaf6 url(../images/bkg_checkout.gif) 0 0 repeat-x; border:1px solid #bbb6a5; margin:0 0 25px; padding:20px; }
|
1438 |
+
.multiple-checkout .col2-set h2.legend { margin:-20px -20px 15px; padding:5px 10px; background:#f9f3e3; border-bottom:1px solid #bbafa0; position:relative; }
|
1439 |
+
.multiple-checkout .col2-set h3.legend { margin:0 0 10px; color:#0a263c; }
|
1440 |
+
.multiple-checkout .col2-set .divider { margin:0 -20px; padding:25px 0; position:relative; }
|
1441 |
+
.multiple-checkout .box { margin:0 0 15px; }
|
1442 |
+
.multiple-checkout .box h2 { color:#e26703; }
|
1443 |
+
|
1444 |
+
.multiple-checkout .place-order .please-wait { float:right; padding:27px 7px 0 0; }
|
1445 |
+
.multiple-checkout .place-order .grand-total { float:right; height:71px; font-size:1.5em; padding:0 0 0 21px; background:url(../images/bkg_grand-total.gif) 0 0 no-repeat; overflow:hidden; }
|
1446 |
+
.multiple-checkout .place-order .grand-total .inner { float:left; height:57px; padding:14px 21px 0 0; background:url(../images/bkg_grand-total.gif) 100% 0 no-repeat; }
|
1447 |
+
.multiple-checkout .place-order .grand-total .inner div { display:inline; }
|
1448 |
+
.multiple-checkout .place-order .grand-total big { display:inline; margin-right:12px; }
|
1449 |
+
.multiple-checkout .place-order .grand-total .price { color:#E26703; }
|
1450 |
+
.multiple-checkout .place-order .grand-total button.button span { font-size:16px; }
|
1451 |
+
.multiple-checkout .place-order .grand-total button.button span span { padding:0 45px 0 36px; }
|
1452 |
+
|
1453 |
+
/* Step 1 */
|
1454 |
+
.multiple-checkout .title-buttons button.button span { border-color:#406a83; background:#618499; }
|
1455 |
+
#multiship-addresses-table td { padding:10px; }
|
1456 |
+
#multiship-addresses-table tfoot td { padding:5px 10px; }
|
1457 |
+
#multiship-addresses-table tfoot button.button span { border-color:#406a83; background:#618499; }
|
1458 |
+
|
1459 |
+
/* Step 2 */
|
1460 |
+
.multiple-checkout .gift-messages-form .item .details .form-list { width:100%; overflow:hidden; }
|
1461 |
+
.multiple-checkout .gift-messages-form .item .details .form-list li { margin-right:-15px; }
|
1462 |
+
.multiple-checkout .gift-messages-form .item .details .form-list .field { width:230px; }
|
1463 |
+
.multiple-checkout .gift-messages-form .item .details .form-list .input-box { width:215px; }
|
1464 |
+
.multiple-checkout .gift-messages-form .item .details .form-list input.input-text { width:209px; }
|
1465 |
+
.multiple-checkout .gift-messages-form .item .details .form-list li.wide .input-box { width:445px; }
|
1466 |
+
.multiple-checkout .gift-messages-form .item .details .form-list li.wide textarea { width:439px; }
|
1467 |
+
.checkout-multishipping-shipping .box-sp-methods { border:1px solid #d9d2be; background:#f9f3e3; padding:13px; position:relative; }
|
1468 |
+
.checkout-multishipping-shipping .box-sp-methods .pointer { position:absolute; top:-20px; right:-40px; width:178px; height:41px; background:url(../images/bkg_sp-methods.gif) 0 0 no-repeat; overflow:hidden; }
|
1469 |
+
|
1470 |
+
/* Step 3 */
|
1471 |
+
.checkout-multishipping-billing .multiple-checkout { position:relative; }
|
1472 |
+
/* ======================================================================================= */
|
1473 |
+
|
1474 |
+
|
1475 |
+
/* Account Login/Create Pages ============================================================ */
|
1476 |
+
.account-login .content { min-height:345px; padding:14px 21px; background:#faf7ee url(../images/bkg_login-box.gif) 0 0 repeat-x; border:1px solid #bbb6a5; border-bottom:0; }
|
1477 |
+
.account-login .content h2 { font-weight:bold; font-size:13px; margin:0 0 14px; padding:0 0 5px 23px; border-bottom:1px solid #ddd; background-position:0 1px; background-repeat:no-repeat; text-transform:uppercase; color:#e76200; }
|
1478 |
+
.account-login .new-users h2 { background-image:url(../images/i_page1.gif)}
|
1479 |
+
.account-login .registered-users h2 { background-image:url(../images/i_page2.gif); }
|
1480 |
+
.account-login .buttons-set { border:1px solid #bbb6a5; border-top:0; margin:0; padding:8px 13px; background:#dee5e8 url(../images/bkg_buttons-set1.gif) 0 0 repeat-x; }
|
1481 |
+
|
1482 |
+
.account-create {}
|
1483 |
+
|
1484 |
+
/* Captcha ================================================================================ */
|
1485 |
+
.captcha-note { clear:left; padding-top:5px; }
|
1486 |
+
.captcha-image { float:left; display:inline; margin:0; position:relative; width:258px; }
|
1487 |
+
.captcha-image .captcha-img { border:1px solid #b6b6b6; vertical-align:bottom; width:100%; }
|
1488 |
+
.registered-users .captcha-image { margin:0;}
|
1489 |
+
.captcha-reload { cursor:pointer; position:absolute; top:2px; right:2px;}
|
1490 |
+
.captcha-reload.refreshing { animation:rotate 1.5s infinite linear; -webkit-animation:rotate 1.5s infinite linear; -moz-animation:rotate 1.5s infinite linear; }
|
1491 |
+
|
1492 |
+
@-webkit-keyframes rotate {
|
1493 |
+
0% { -webkit-transform:rotate(0); }
|
1494 |
+
0% { -webkit-transform:rotate(-360deg); }
|
1495 |
+
}
|
1496 |
+
@-moz-keyframes rotate {
|
1497 |
+
0% { -moz-transform:rotate(0); }
|
1498 |
+
0% { -moz-transform:rotate(-360deg); }
|
1499 |
+
}
|
1500 |
+
@keyframes rotate {
|
1501 |
+
0% { transform:rotate(0); }
|
1502 |
+
0% { transform:rotate(-360deg); }
|
1503 |
+
}
|
1504 |
+
|
1505 |
+
/* Remember Me Popup ===================================================================== */
|
1506 |
+
.window-overlay { background:url(../images/window_overlay.png) repeat; background:rgba(0, 0, 0, 0.35); position:absolute; top:0; left:0; height:100%; width:100%; z-index:990; }
|
1507 |
+
|
1508 |
+
.remember-me label { float:none; margin:0 6px; }
|
1509 |
+
.remember-me-popup { background:#fff; border:1px solid #ccc; left:50%; top:50%; position:absolute; margin:-85px 0 0 -200px; width:400px; text-align:left; -moz-box-shadow:0 0 6px #ccc; -webkit-box-shadow:0 0 6px #ccc; -box-shadow:0 0 6px #ccc; z-index:1000; }
|
1510 |
+
.remember-me-popup h3 { background:#d9e5ee; border-bottom:1px solid #ccc; font-size:14px; padding:5px 10px; }
|
1511 |
+
.remember-me-popup .remember-me-popup-head { position:relative; }
|
1512 |
+
.remember-me-popup .remember-me-popup-head .remember-me-popup-close { background:url(../images/btn_window_close.gif) no-repeat; display:block; position:absolute; top:7px; right:7px; height:15px; width:15px; text-indent:-9999em; }
|
1513 |
+
.remember-me-popup .remember-me-popup-body { padding:10px; }
|
1514 |
+
.remember-me-popup .remember-me-popup-body a { display:inline-block; height:19px; border:1px solid #de5400; background:#f18200; padding:0 8px; font:bold 12px/19px Arial, Helvetica, sans-serif; text-align:center; text-decoration:none; white-space:nowrap; color:#fff; }
|
1515 |
+
/* Remember Me Popup ===================================================================== */
|
1516 |
+
|
1517 |
+
|
1518 |
+
/* My Account ============================================================================= */
|
1519 |
+
.my-account .title-buttons .link-rss { float:none; margin:0; }
|
1520 |
+
|
1521 |
+
/********** < Dashboard */
|
1522 |
+
.dashboard .welcome-msg { margin:0 8em 1.5em 0; }
|
1523 |
+
.dashboard .welcome-msg p { margin:0; }
|
1524 |
+
.dashboard .col2-set { margin:0 0 15px; }
|
1525 |
+
|
1526 |
+
/* General Box */
|
1527 |
+
.box-account { background:#fff url(../images/bkg_account_box.gif) 0 0 repeat-x; border:1px solid #ccc; border-color:#ccc #999 #999 #ccc; padding:15px; margin: 0 0 20px; }
|
1528 |
+
.box-account .box-head { border-bottom:1px solid #d9dde3; margin:0 0 10px; text-align:right; }
|
1529 |
+
.box-account .box-head h2 { float:left; margin:0; font-size:13px; font-weight:bold; text-transform:uppercase; background-position:0 0; background-repeat:no-repeat; padding-left:21px; color:#e65505; }
|
1530 |
+
|
1531 |
+
.dashboard .box .box-title { background:url(../images/bkg_divider1.gif) 0 100% repeat-x; padding:0 0 2px; margin:0 0 8px; text-align:right; }
|
1532 |
+
.dashboard .box .box-title h3,
|
1533 |
+
.dashboard .box .box-title h4 { float:left; font-size:13px; font-weight:bold; margin:0; }
|
1534 |
+
|
1535 |
+
/* Block: Recent Orders */
|
1536 |
+
.dashboard .box-recent .box-head h2 { background-image:url(../images/i_folder-table.gif); }
|
1537 |
+
|
1538 |
+
/* Block: Account Information */
|
1539 |
+
.dashboard .box-info .box-head h2 { background-image:url(../images/i_ma-info.gif); }
|
1540 |
+
.dashboard .box-info h4 { font-size:11px; font-weight:bold; text-transform:uppercase; }
|
1541 |
+
|
1542 |
+
/* Block: Reviews */
|
1543 |
+
.dashboard .box-reviews .box-head h2 { background-image:url(../images/i_ma-reviews.gif); }
|
1544 |
+
.dashboard .box-reviews .number { float:left; font-size:10px; font-weight:bold; line-height:1; color:#fff; margin:3px -20px 0 0; padding:2px 3px; background:#0a263c; }
|
1545 |
+
.dashboard .box-reviews .details { margin-left:20px; }
|
1546 |
+
.dashboard .box-reviews li.item { margin:0 0 7px; }
|
1547 |
+
.dashboard .box-reviews li.item.last { margin:0; }
|
1548 |
+
.dashboard .box-reviews .ratings { margin:7px 0 0; }
|
1549 |
+
|
1550 |
+
/* Block: Tags */
|
1551 |
+
.dashboard .box-tags .box-head h2 { background-image:url(../images/i_ma-tags.gif); }
|
1552 |
+
.dashboard .box-tags .number { float:left; font-size:10px; font-weight:bold; line-height:1; color:#fff; margin:3px -20px 0 0; padding:2px 3px; background:#0a263c; }
|
1553 |
+
.dashboard .box-tags .details { margin-left:20px; }
|
1554 |
+
.dashboard .box-tags li.item { margin:0 0 7px; }
|
1555 |
+
.dashboard .box-tags li.item.last { margin:0; }
|
1556 |
+
.dashboard .box-tags .tags strong,
|
1557 |
+
.dashboard .box-tags .tags ul,
|
1558 |
+
.dashboard .box-tags .tags ul li { display:inline; }
|
1559 |
+
/********** Dashboard > */
|
1560 |
+
|
1561 |
+
/* Address Book */
|
1562 |
+
.addresses-list h2 { font-weight:bold; font-size:13px; color:#e26703; text-transform:uppercase; }
|
1563 |
+
.addresses-list h3 { font-weight:bold; font-size:13px; }
|
1564 |
+
.addresses-list address { margin:0 0 3px; }
|
1565 |
+
.addresses-list p { margin:0; }
|
1566 |
+
.addresses-list a { font-weight:bold; }
|
1567 |
+
.addresses-list .link-remove { color:#646464; }
|
1568 |
+
.addresses-list .separator { margin:0 3px; }
|
1569 |
+
.addresses-list li.item { background:#fff url(../images/bkg_account_box.gif) 0 0 repeat-x; border:1px solid #ccc; padding:10px 13px; margin:0 0 10px; }
|
1570 |
+
.addresses-list li.empty { background:none; border:0; padding:0; }
|
1571 |
+
.addresses-list li.empty p { font-weight:bold; }
|
1572 |
+
.addresses-list .addresses-additional li.item { background:none; border:0; padding:0; }
|
1573 |
+
|
1574 |
+
/* Order View */
|
1575 |
+
.order-info { background:#dee5e8; border:1px solid #d0cbc1; padding:4px 8px; margin:0 0 8px; }
|
1576 |
+
.order-info dt,
|
1577 |
+
.order-info dd,
|
1578 |
+
.order-info ul,
|
1579 |
+
.order-info li { display:inline; }
|
1580 |
+
.order-info .current { font-weight:bold; }
|
1581 |
+
.order-info li { margin:0 3px; }
|
1582 |
+
|
1583 |
+
.order-date { margin:10px 0; }
|
1584 |
+
|
1585 |
+
.order-info-box { background:#fff url(../images/bkg_block-title.gif) 0 0 repeat-x; border:1px solid #d0cbc1; padding:12px 15px; margin:0 0 15px; }
|
1586 |
+
.order-info-box h2 { font-weight:bold; font-size:13px; }
|
1587 |
+
.order-info-box .box-payment p { margin:0 0 3px; }
|
1588 |
+
.order-info-box .box-payment th { font-weight:bold; padding-right:7px; }
|
1589 |
+
|
1590 |
+
.order-items { width:100%; overflow-x:auto; }
|
1591 |
+
.order-items h2,
|
1592 |
+
.order-items h3 { clear:none; font-weight:bold; font-size:13px; padding:0; margin:0 0 5px; color:#0a263c; }
|
1593 |
+
.order-items .product-name { font-size:1em !important; font-weight:bold !important; }
|
1594 |
+
.order-items .link-print { color:#1e7ec8; font-weight:normal; }
|
1595 |
+
.order-items .order-links { text-align:right; }
|
1596 |
+
|
1597 |
+
.order-additional { margin:15px 0; }
|
1598 |
+
/* Order Gift Message */
|
1599 |
+
.gift-message dt strong { color:#666; }
|
1600 |
+
.gift-message dd { font-size:13px; margin:5px 0 0; }
|
1601 |
+
/* Order Comments */
|
1602 |
+
.order-about dt { font-weight:bold; }
|
1603 |
+
.order-about dd { font-size:13px; margin:0 0 7px; }
|
1604 |
+
|
1605 |
+
.tracking-table { margin:0 0 15px; }
|
1606 |
+
.tracking-table th { font-weight:bold; white-space:nowrap; }
|
1607 |
+
|
1608 |
+
.tracking-table-popup { width:100%; }
|
1609 |
+
.tracking-table-popup th { font-weight:bold; white-space:nowrap; }
|
1610 |
+
.tracking-table-popup th,
|
1611 |
+
.tracking-table-popup td { padding:1px 8px; }
|
1612 |
+
|
1613 |
+
/* Order Print Pages */
|
1614 |
+
.page-print .print-head { margin:0 0 15px; }
|
1615 |
+
.page-print .print-head .logo { float:left; }
|
1616 |
+
.page-print .print-head address { float:left; margin-left:15px; }
|
1617 |
+
.page-print h1 { font-size:16px; font-weight:bold; }
|
1618 |
+
.page-print h2,
|
1619 |
+
.page-print h3 { font-size:13px; font-weight:bold; }
|
1620 |
+
.page-print h2.h2 { font-size:16px; font-weight:bold; }
|
1621 |
+
.page-print .order-date { background:url(../images/bkg_divider1.gif) 0 100% repeat-x; padding:0 0 10px; margin:0 0 10px; }
|
1622 |
+
.page-print .col2-set { margin:0 0 10px; }
|
1623 |
+
/* Price Rewrites */
|
1624 |
+
.page-print .gift-message-link { display:none; }
|
1625 |
+
.page-print .price-excl-tax,
|
1626 |
+
.page-print .price-incl-tax { display:block; white-space:nowrap; }
|
1627 |
+
.page-print .cart-price,
|
1628 |
+
.page-print .price-excl-tax .label,
|
1629 |
+
.page-print .price-incl-tax .label,
|
1630 |
+
.page-print .price-excl-tax .price,
|
1631 |
+
.page-print .price-incl-tax .price { display:inline; }
|
1632 |
+
|
1633 |
+
/* My Wishlist */
|
1634 |
+
.my-wishlist .data-table td { padding:10px; }
|
1635 |
+
.my-wishlist .product-image { display:block; width:113px; height:113px; margin:0 0 5px; }
|
1636 |
+
.my-wishlist textarea { display:block; width:97%; height:109px; }
|
1637 |
+
.my-wishlist .buttons-set { margin-top:2em; }
|
1638 |
+
.my-wishlist .buttons-set button.button { float:none; }
|
1639 |
+
.my-wishlist .buttons-set .btn-add span,
|
1640 |
+
.my-wishlist .buttons-set .btn-share span { border-color:#406a83; background:#618499; }
|
1641 |
+
#wishlist-table .add-to-links { white-space:nowrap; }
|
1642 |
+
|
1643 |
+
/* My Tags */
|
1644 |
+
.my-tag-edit { float:left; margin:0 0 10px; }
|
1645 |
+
.my-tag-edit .btn-remove { float:right; margin:4px 0 0 5px; }
|
1646 |
+
#my-tags-table { clear:both; }
|
1647 |
+
#my-tags-table td { padding:10px; }
|
1648 |
+
#my-tags-table .add-to-links { white-space:nowrap; }
|
1649 |
+
|
1650 |
+
/* My Reviews */
|
1651 |
+
#my-reviews-table td { padding:10px; }
|
1652 |
+
|
1653 |
+
.product-review .product-img-box { float:left; width:140px; }
|
1654 |
+
.product-review .product-img-box .product-image { display:block; width:125px; height:125px; }
|
1655 |
+
.product-review .product-img-box .label { font-size:11px; margin:0 0 3px; }
|
1656 |
+
.product-review .product-img-box .ratings .rating-box { float:none; display:block; margin:0 0 3px; }
|
1657 |
+
.product-review .product-details { margin-left:150px; }
|
1658 |
+
.product-review .product-name { font-size:16px; font-weight:bold; margin:0 0 10px; }
|
1659 |
+
.product-review h3 { font-size:12px; margin:0 0 3px; color:#2f2f2f; }
|
1660 |
+
.product-review .ratings-table { margin:0 0 10px; }
|
1661 |
+
.product-review dt { font-weight:bold; }
|
1662 |
+
.product-review dd { font-size:13px; margin:5px 0 0; }
|
1663 |
+
|
1664 |
+
/* Billing Agreements */
|
1665 |
+
.billing-agreements .info-box{ margin:15px 0; }
|
1666 |
+
.billing-agreements .form-list li select { float:left; }
|
1667 |
+
.billing-agreements .form-list li button.button { float:left; margin-left:10px; }
|
1668 |
+
.billing-agreements .table-caption { font-weight:bold; font-size:13px; }
|
1669 |
+
/* ======================================================================================= */
|
1670 |
+
|
1671 |
+
|
1672 |
+
/* MAP Popup============================================================================== */
|
1673 |
+
.cart-msrp-totals { color:red; font-size:12px !important; font-weight:bold; margin:10px 10px 0; padding:10px; text-align:right; text-transform:uppercase;}
|
1674 |
+
.map-cart-sidebar-total { color:red; display:block; font-size:10px; font-weight:bold; text-align:left; padding:2px 5px; text-shadow:0 1px 0 #fff; }
|
1675 |
+
|
1676 |
+
.map-popup { background:#fff; border:1px solid #aaa; margin:12px 0 0; position:absolute; -moz-box-shadow:0 0 6px #ccc; -webkit-box-shadow:0 0 6px #ccc; box-shadow:0 0 6px #ccc; text-align:left; width:300px; z-index:100; }
|
1677 |
+
.map-popup-heading { background:#d9e5ee; border-bottom:1px solid #ccc; padding:5px 30px 5px 10px; width:260px; }
|
1678 |
+
.map-popup-heading h2 { font-size:16px; margin:0; text-shadow:0 1px 0 #f6f6f6; overflow:hidden; white-space:nowrap; word-wrap:break-word; text-align:left; text-overflow:ellipsis; }
|
1679 |
+
.map-popup-arrow { background:url(../images/map_popup_arrow.gif) no-repeat; position:absolute; left:50%; top:-10px; height:10px; width:19px; }
|
1680 |
+
.map-popup-close { background:url(../images/btn_window_close.gif) no-repeat; display:block; position:absolute; top:8px; right:10px; height:15px; width:15px; text-indent:-9999em; -moz-box-shadow:0 0 3px #999; -webkit-box-shadow:0 0 3px #999; box-shadow:0 0 3px #999; -moz-border-radius:2px; -webkit-border-radius:2px; border-radius:2px; }
|
1681 |
+
.map-popup-content { border-top:1px solid #eee; padding:10px; overflow:hidden; text-align:left; width:280px; }
|
1682 |
+
.map-popup-checkout { display:inline; float:right; text-align:right; }
|
1683 |
+
.map-popup-checkout span { display:block; padding-right:30px; }
|
1684 |
+
.map-popup-checkout .paypal-logo { margin:0 0 5px; }
|
1685 |
+
.map-popup-price .price-box,
|
1686 |
+
.map-popup-price .price-box .special-price { margin:0; padding:0; }
|
1687 |
+
.map-popup-price { margin:5px 0 0; }
|
1688 |
+
.map-popup-text { clear:right; margin:0 10px; padding:10px 0; text-align:left; word-wrap:break-word; }
|
1689 |
+
.map-popup-only-text { border-top:1px solid #ddd; }
|
1690 |
+
/* ======================================================================================= */
|
1691 |
+
|
1692 |
+
|
1693 |
+
/* Footer ================================================================================ */
|
1694 |
+
.footer-container { border-top:15px solid #b6d1e2; }
|
1695 |
+
.footer { width:930px; margin:0 auto; padding:10px 10px 50px; }
|
1696 |
+
.footer .store-switcher { display:inline; margin:0 5px 0 0; color:#fff; }
|
1697 |
+
.footer .store-switcher label { font-weight:bold; vertical-align:middle; }
|
1698 |
+
.footer .store-switcher select { padding:0; vertical-align:middle; }
|
1699 |
+
.footer a { color:#fff; text-decoration:none; }
|
1700 |
+
.footer a:hover { text-decoration:underline; }
|
1701 |
+
.footer .bugs { margin:13px 0 0; color:#ecf3f6; }
|
1702 |
+
.footer .bugs a { color:#ecf3f6; text-decoration:underline; }
|
1703 |
+
.footer .bugs a:hover { text-decoration:none; }
|
1704 |
+
.footer address { margin:0 0 20px; color:#ecf3f6; }
|
1705 |
+
.footer address a { color:#ecf3f6; text-decoration:underline; }
|
1706 |
+
.footer address a:hover { text-decoration:none; }
|
1707 |
+
.footer ul { display:inline; }
|
1708 |
+
.footer ul.links { display:block; }
|
1709 |
+
.footer li { display:inline; background:url(../images/bkg_pipe2.gif) 100% 60% no-repeat; padding:0 7px 0 4px; }
|
1710 |
+
.footer li.last { background:none !important; padding-right:0 !important; }
|
1711 |
+
.footer-container .bottom-container { margin:0 0 5px; }
|
1712 |
+
/* ======================================================================================= */
|
1713 |
+
|
1714 |
+
/* Sample Data============================================================================ */
|
1715 |
+
.home-callout { margin-bottom:12px; }
|
1716 |
+
.home-callout img { display:block }
|
1717 |
+
.home-spot { float:left; width:470px; margin-left:20px; }
|
1718 |
+
.best-selling h3 { margin:12px 0 6px 0; color:#e25203; font-size:1.2em; }
|
1719 |
+
.best-selling table { border-top:1px solid #ccc; }
|
1720 |
+
.best-selling tr.odd { background:#eee url(../images/best_selling_tr_odd_bg.gif) 0 100% repeat-x; }
|
1721 |
+
.best-selling tr.even { background:#fff url(../images/best_selling_tr_even_bg.gif) 0 100% repeat-x; }
|
1722 |
+
.best-selling td { width:50%; border-bottom:1px solid #ccc; padding:8px 10px 8px 8px; font-size:11px; }
|
1723 |
+
.best-selling .product-img { float:left; border:2px solid #dcdcdc; }
|
1724 |
+
.best-selling .product-description { margin-left:107px; line-height:1.3em; }
|
1725 |
+
.best-selling a.product-name,
|
1726 |
+
.home-spot .best-selling a.product-name:hover { color:#203548; }
|
1727 |
+
/* ======================================================================================= */
|
1728 |
+
|
1729 |
+
|
1730 |
+
/* Clears ================================================================================ */
|
1731 |
+
.clearer:after,
|
1732 |
+
.header-container:after,
|
1733 |
+
.header-container .top-container:after,
|
1734 |
+
.header:after,
|
1735 |
+
.header .quick-access:after,
|
1736 |
+
#nav:after,
|
1737 |
+
.main:after,
|
1738 |
+
.footer:after,
|
1739 |
+
.footer-container .bottom-container:after,
|
1740 |
+
.col-main:after,
|
1741 |
+
.col2-set:after,
|
1742 |
+
.col3-set:after,
|
1743 |
+
.col3-layout .product-options-bottom .price-box:after,
|
1744 |
+
.col4-set:after,
|
1745 |
+
.search-autocomplete li:after,
|
1746 |
+
.block .block-content:after,
|
1747 |
+
.block .actions:after,
|
1748 |
+
.block li.item:after,
|
1749 |
+
.block-poll li:after,
|
1750 |
+
.block-layered-nav .currently li:after,
|
1751 |
+
.page-title:after,
|
1752 |
+
.products-grid:after,
|
1753 |
+
.products-list li.item:after,
|
1754 |
+
.box-account .box-head:after,
|
1755 |
+
.dashboard .box .box-title:after,
|
1756 |
+
.box-reviews li.item:after,
|
1757 |
+
.box-tags li.item:after,
|
1758 |
+
.pager:after,
|
1759 |
+
.sorter:after,
|
1760 |
+
.ratings:after,
|
1761 |
+
.add-to-box:after,
|
1762 |
+
.add-to-cart:after,
|
1763 |
+
.product-essential:after,
|
1764 |
+
.product-collateral:after,
|
1765 |
+
.product-view .product-img-box .more-views ul:after,
|
1766 |
+
.product-view .box-tags .form-add:after,
|
1767 |
+
.product-view .product-shop .short-description:after,
|
1768 |
+
.product-view .box-description:after,
|
1769 |
+
.product-options .options-list li:after,
|
1770 |
+
.product-options-bottom:after,
|
1771 |
+
.product-review:after,
|
1772 |
+
.cart:after,
|
1773 |
+
.cart-collaterals:after,
|
1774 |
+
.cart .crosssell li.item:after,
|
1775 |
+
.opc .step-title:after,
|
1776 |
+
.checkout-progress:after,
|
1777 |
+
.multiple-checkout .place-order:after,
|
1778 |
+
.group-select li:after,
|
1779 |
+
.form-list li:after,
|
1780 |
+
.form-list .field:after,
|
1781 |
+
.buttons-set:after,
|
1782 |
+
.page-print .print-head:after,
|
1783 |
+
.advanced-search-summary:after,
|
1784 |
+
.gift-messages-form .item:after,
|
1785 |
+
.send-friend .form-list li p:after { display:block; content:"."; clear:both; font-size:0; line-height:0; height:0; overflow:hidden; }
|
1786 |
+
/* ======================================================================================= */
|
1787 |
+
|
1788 |
+
.guest-select {width:305px !important;}
|
skin/frontend/default/customproduct/favicon.ico
ADDED
Binary file
|
skin/frontend/default/customproduct/images/addtext.png
ADDED
Binary file
|
skin/frontend/default/customproduct/images/best_selling_tr_even_bg.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/best_selling_tr_odd_bg.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bgimage.png
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bgimage7.png
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_account_box.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_block-actions.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_block-currency.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_block-layered-dd.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_block-layered-dt.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_block-layered-label.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_block-layered-li.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_block-layered-title.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_block-layered1.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_block-title-account.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_block-title.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_body.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_buttons-set1.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_checkout.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_collapse-gm.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_collapse.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_divider1.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_form-search.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_grand-total.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_grid.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_header.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_login-box.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_main1.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_main2.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_nav0.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_nav1.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_nav2.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_opc-title-off.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_pipe1.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_pipe2.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_pipe3.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_product-view.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_product_collateral.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_rating.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_sp-methods.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_tfoot.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_th-v.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_th.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/bkg_toolbar.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/btn_checkout.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/btn_edit.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/btn_gm-close.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/btn_google_checkout.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/btn_paypal_checkout.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/btn_place_order.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/btn_previous.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/btn_proceed_to_checkout.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/btn_proceed_to_checkout_dis.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/btn_remove.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/btn_remove2.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/btn_search.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/btn_trash.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/btn_window_close.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/button1.png
ADDED
Binary file
|
skin/frontend/default/customproduct/images/button2.png
ADDED
Binary file
|
skin/frontend/default/customproduct/images/button3.png
ADDED
Binary file
|
skin/frontend/default/customproduct/images/calendar.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/catalog/product/placeholder/image.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/catalog/product/placeholder/small_image.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/catalog/product/placeholder/thumbnail.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/cvv.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/cvv.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/fam_book_open.png
ADDED
Binary file
|
skin/frontend/default/customproduct/images/free_shipping_callout.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/grid-cal.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/home_left_callout.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/home_main_callout.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_arrow-top.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_asc_arrow.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_availability_only.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_availability_only_arrow.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_block-cart.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_block-currency.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_block-list.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_block-poll.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_block-related.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_block-subscribe.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_block-tags.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_block-viewed.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_block-wishlist.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_desc_arrow.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_discount.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_folder-table.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_ma-info.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_ma-reviews.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_ma-tags.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_msg-error.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_msg-note.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_msg-success.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_notice.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_page1.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_page2.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_pager-next.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_pager-prev.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_print.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_rss-big.png
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_rss.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_search_criteria.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_shipping.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_tag_add.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_tier.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_type_grid.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/i_type_list.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/logo.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/logo_email.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/logo_print.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/magnifier_handle.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/map_popup_arrow.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/404_callout1.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/404_callout2.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/about_us_img.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/best_selling_img01.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/best_selling_img02.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/best_selling_img03.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/best_selling_img04.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/best_selling_img05.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/best_selling_img06.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/cell_phone_landing_banner1.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/col_left_callout.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/col_right_callout.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/electronics_cellphones.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/electronics_digitalcameras.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/electronics_laptops.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/furniture_callout_spot.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/furnitures_bed_room.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/furnitures_living_room.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/head_electronics_cellphones.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/head_electronics_digicamera.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/head_electronics_laptops.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/laptop_callout_mid1.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/laptop_callout_mid2.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/laptop_callout_mid3.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/laptop_callout_spot.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/media/shirts_landing_banner1.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/np_cart_thumb.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/np_more_img.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/np_product_main.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/np_thumb.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/np_thumb2.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/opc-ajax-loader.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/pager_arrow_left.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/pager_arrow_right.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/ph_callout_left_rebel.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/ph_callout_left_top.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/product_zoom_overlay_magnif.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/slider_bg.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/slider_btn_zoom_in.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/slider_btn_zoom_out.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/spacer.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/textimage.png
ADDED
Binary file
|
skin/frontend/default/customproduct/images/validation_advice_bg.gif
ADDED
Binary file
|
skin/frontend/default/customproduct/images/xmlconnect/catalog/category/placeholder/image.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/xmlconnect/catalog/category/placeholder/small_image.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/xmlconnect/catalog/category/placeholder/thumbnail.jpg
ADDED
Binary file
|
skin/frontend/default/customproduct/images/xmlconnect/tab_account.png
ADDED
Binary file
|
skin/frontend/default/customproduct/images/xmlconnect/tab_cart.png
ADDED
Binary file
|
skin/frontend/default/customproduct/images/xmlconnect/tab_home.png
ADDED
Binary file
|
skin/frontend/default/customproduct/images/xmlconnect/tab_more.png
ADDED
Binary file
|
skin/frontend/default/customproduct/images/xmlconnect/tab_page.png
ADDED
Binary file
|
skin/frontend/default/customproduct/images/xmlconnect/tab_search.png
ADDED
Binary file
|
skin/frontend/default/customproduct/images/xmlconnect/tab_shop.png
ADDED
Binary file
|
skin/frontend/default/customproduct/js/Uize.Array.Dupes.js
ADDED
@@ -0,0 +1,188 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Array.Dupes Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2011-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 1
|
15 |
+
codeCompleteness: 50
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 0
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Array.Dupes= module provides functionality to deal with arrays containing duplicate values.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
### Key Features
|
27 |
+
- high performance
|
28 |
+
- linear time complexity (even when removing object reference duplicates)
|
29 |
+
- can remove duplicates from source array, rather than always returning new array, and removes duplicates efficiently
|
30 |
+
- supports strict type checking
|
31 |
+
- supports object values
|
32 |
+
- supports optional target
|
33 |
+
- supports optional canonicalizer function, such as a lowercasing function for string values
|
34 |
+
*/
|
35 |
+
|
36 |
+
Uize.module ({
|
37 |
+
name:'Uize.Array.Dupes',
|
38 |
+
required:'Uize.Data.Matches',
|
39 |
+
builder:function () {
|
40 |
+
/*** Variables for Scruncher Optimization ***/
|
41 |
+
var
|
42 |
+
_package = function () {},
|
43 |
+
_true = true,
|
44 |
+
_false = false,
|
45 |
+
_undefined,
|
46 |
+
_Uize = Uize
|
47 |
+
;
|
48 |
+
|
49 |
+
/*** Utility Objects ***/
|
50 |
+
var _ValueIndexer = (
|
51 |
+
function () {
|
52 |
+
var
|
53 |
+
_objectTaggerValue = {},
|
54 |
+
_class = function (_canonicalizer) {
|
55 |
+
this._canonicalizer = _canonicalizer;
|
56 |
+
this._valuesLookup = _Uize.lookup (_undefined,1,_true);
|
57 |
+
},
|
58 |
+
_classPrototype = _class.prototype
|
59 |
+
;
|
60 |
+
|
61 |
+
_classPrototype.isIn = function (_value,_addToIfNot) {
|
62 |
+
var
|
63 |
+
_this = this,
|
64 |
+
_canonicalizer = _this._canonicalizer,
|
65 |
+
_canonicalizedValue = _canonicalizer ? _canonicalizer (_value) : _value,
|
66 |
+
_wasIn = _false
|
67 |
+
;
|
68 |
+
if (
|
69 |
+
_Uize.isPrimitive (_canonicalizedValue) ||
|
70 |
+
!(_Uize.isObject (_canonicalizedValue) || _Uize.isFunction (_canonicalizedValue))
|
71 |
+
) {
|
72 |
+
var
|
73 |
+
_typeofCanonicalizedValue = typeof _canonicalizedValue,
|
74 |
+
_valuesLookup = _this._valuesLookup
|
75 |
+
;
|
76 |
+
if (
|
77 |
+
(_valuesLookup [_canonicalizedValue] || (_valuesLookup [_canonicalizedValue] = {})) [
|
78 |
+
_typeofCanonicalizedValue
|
79 |
+
]
|
80 |
+
) {
|
81 |
+
_wasIn = _true;
|
82 |
+
} else if (_addToIfNot) {
|
83 |
+
_valuesLookup [_canonicalizedValue] [_typeofCanonicalizedValue] = _true;
|
84 |
+
}
|
85 |
+
} else {
|
86 |
+
if (_canonicalizedValue.tagged == _objectTaggerValue) {
|
87 |
+
_wasIn = _true;
|
88 |
+
} else if (_addToIfNot) {
|
89 |
+
(_this._taggedObjects || (_this._taggedObjects = [])).push ({
|
90 |
+
_object:_canonicalizedValue,
|
91 |
+
_hadTaggedProperty:_canonicalizedValue.hasOwnProperty ('tagged'),
|
92 |
+
_taggedPropertyOldValue:_canonicalizedValue.tagged
|
93 |
+
});
|
94 |
+
_canonicalizedValue.tagged = _objectTaggerValue;
|
95 |
+
}
|
96 |
+
}
|
97 |
+
return _wasIn;
|
98 |
+
};
|
99 |
+
|
100 |
+
_classPrototype.addTo = function (_value) {
|
101 |
+
return !this.isIn (_value,_true);
|
102 |
+
};
|
103 |
+
|
104 |
+
_classPrototype.cleanUp = function () {
|
105 |
+
var _taggedObjects = this._taggedObjects;
|
106 |
+
if (_taggedObjects) {
|
107 |
+
for (
|
108 |
+
var _taggedObjectNo = _taggedObjects.length, _taggedObject, _object;
|
109 |
+
--_taggedObjectNo >= 0;
|
110 |
+
) {
|
111 |
+
_object = (_taggedObject = _taggedObjects [_taggedObjectNo])._object;
|
112 |
+
_taggedObject._hadTaggedProperty
|
113 |
+
? (_object.tagged = _taggedObject._taggedPropertyOldValue)
|
114 |
+
: delete _object.tagged
|
115 |
+
;
|
116 |
+
}
|
117 |
+
}
|
118 |
+
};
|
119 |
+
|
120 |
+
return _class;
|
121 |
+
}) ();
|
122 |
+
|
123 |
+
function _untagObjects (_taggedObjects) {
|
124 |
+
}
|
125 |
+
|
126 |
+
/*** Public Static Methods ***/
|
127 |
+
_package.dedupe = function (_source,_canonicalizer,_target) {
|
128 |
+
_target = _source;
|
129 |
+
/* TO DO
|
130 |
+
- support canonicalizers that can achieve the effect of loose type comparison
|
131 |
+
- one approach for a simple canonicalizer to perform loose type deduping would canonicalize primitive type values to strings, and map both null and undefined to a nully value object stand-in object
|
132 |
+
|
133 |
+
...............................
|
134 |
+
var nullyValueStandin = {};
|
135 |
+
function (value) {
|
136 |
+
return (
|
137 |
+
Uize.isPrimitive (value)
|
138 |
+
? value + ''
|
139 |
+
: Uize.isNully (value)
|
140 |
+
? nullyValueStandin
|
141 |
+
: value
|
142 |
+
);
|
143 |
+
}
|
144 |
+
...............................
|
145 |
+
|
146 |
+
- an alternative approach would allow a canonicalizer to return multiple equivalent canonical values
|
147 |
+
- when the canonicalizer sees a number value, it would return the number value, the string serialization of the number, and the boolean equivalent of the number
|
148 |
+
- when the canonicalizer sees a boolean value, it would return the number equivalent of the boolean, and the string serialization of the boolean
|
149 |
+
- when the canonicalizer sees the value null, it would return the value null, the value 0, and the value undefined
|
150 |
+
- problems with this approach are...
|
151 |
+
- canonicalizers should be able to return array values, so how would a canonicalizer that is to return multiple values differentiate that intent from simply returning an array as a canonicalized result? Perhaps the canonicalizer would have to have a property on it to indicate that it uses this signature, so that the return value would not have to be overloaded.
|
152 |
+
- if a canonicalizer could return multiple values, code that currently does the lookup and the insert would have to be wrapped in a loop to do multiple lookups and multiple inserts
|
153 |
+
*/
|
154 |
+
var _valueIndexer = new _ValueIndexer (_canonicalizer);
|
155 |
+
_target = _Uize.Data.Matches.remove (
|
156 |
+
_source,function (_value) {return _valueIndexer.isIn (_value,_true)},null,_target
|
157 |
+
);
|
158 |
+
_valueIndexer.cleanUp ();
|
159 |
+
return _target;
|
160 |
+
};
|
161 |
+
|
162 |
+
function _removeOrRetainValues (_source,_valuesToRemove,_canonicalizer,_target,_retain) {
|
163 |
+
var _valueIndexer = new _ValueIndexer (_canonicalizer);
|
164 |
+
_Uize.forEach (
|
165 |
+
_valuesToRemove,
|
166 |
+
function (_valueToRemove) {_valueIndexer.isIn (_valueToRemove,_true)},
|
167 |
+
0,
|
168 |
+
_true
|
169 |
+
);
|
170 |
+
_target = _Uize.Data.Matches.retain (
|
171 |
+
_source,function (_value) {return _valueIndexer.isIn (_value) == _retain},null,_target
|
172 |
+
);
|
173 |
+
_valueIndexer.cleanUp ();
|
174 |
+
return _target;
|
175 |
+
}
|
176 |
+
|
177 |
+
_package.removeValues = function (_source,_valuesToRemove,_canonicalizer,_target) {
|
178 |
+
return _removeOrRetainValues (_source,_valuesToRemove,_canonicalizer,_target,_false);
|
179 |
+
};
|
180 |
+
|
181 |
+
_package.retainValues = function (_source,_valuesToRemove,_canonicalizer,_target) {
|
182 |
+
return _removeOrRetainValues (_source,_valuesToRemove,_canonicalizer,_target,_true);
|
183 |
+
};
|
184 |
+
|
185 |
+
return _package;
|
186 |
+
}
|
187 |
+
});
|
188 |
+
|
skin/frontend/default/customproduct/js/Uize.Array.Order.js
ADDED
@@ -0,0 +1,338 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Array.Order Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2010-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 2
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 100
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Array.Order= module provides utility methods for reordering the elements of arrays, with support for reversing, jumbling, inside to out, etc.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
In a Nutshell
|
27 |
+
Reordering Ins't Sorting
|
28 |
+
Unlike sorting an array based upon its elements' values, the methods of the =Uize.Array.Order= module allow you to reorder the elements according to different patterns - without respect to the element values.
|
29 |
+
|
30 |
+
As an example, the =Uize.Array.Order.reverse= method reverses the order of the elements in an array.
|
31 |
+
|
32 |
+
Types of Reordering
|
33 |
+
Reverse
|
34 |
+
The elements in an array can be reversed by using the =Uize.Array.Order.reverse= method, or by using the =Uize.Array.Order.reorder= method and specifying the value ='reverse'= for the method's =reorderingModeSTR= parameter.
|
35 |
+
|
36 |
+
EXAMPLE
|
37 |
+
....................................................................................
|
38 |
+
Uize.Array.Order.reverse ([1,2,3,4,5,6,7,8]); // returns the array [8,7,6,5,4,3,2,1]
|
39 |
+
....................................................................................
|
40 |
+
|
41 |
+
While JavaScript's built-in =Array= object *does* provide a =reverse= instance method, the =Uize.Array.Order.reverse= method offers a `Versatile Target` facility that is lacking with the built-in =reverse= method, which always modifies the source array.
|
42 |
+
|
43 |
+
For a more in-depth explanation, consult the reference for the =Uize.Array.Order.reverse= method.
|
44 |
+
|
45 |
+
Jumble
|
46 |
+
The elements of an array can be jumbled (randomly shuffled) by using the =Uize.Array.Order.jumble= static method, or by using the =Uize.Array.Order.reorder= method and specifying the value ='jumbled'= for the method's =reorderingModeSTR= parameter.
|
47 |
+
|
48 |
+
EXAMPLE
|
49 |
+
.......................................................................................
|
50 |
+
Uize.Array.Order.jumble ([1,2,3,4,5,6,7,8]); // returns an array like [2,8,4,1,6,3,7,5]
|
51 |
+
.......................................................................................
|
52 |
+
|
53 |
+
For a more in-depth explanation, consult the reference for the =Uize.Array.Order.jumble= method.
|
54 |
+
|
55 |
+
Inside to Out
|
56 |
+
The elements of an array can be reordered from inside to out by using the =Uize.Array.Order.insideOut= static method, or by using the =Uize.Array.Order.reorder= method and specifying the value ='inside out'= for the method's =reorderingModeSTR= parameter.
|
57 |
+
|
58 |
+
EXAMPLE
|
59 |
+
......................................................................................
|
60 |
+
Uize.Array.Order.insideOut ([1,2,3,4,5,6,7,8]); // returns the array [4,5,3,6,2,7,1,8]
|
61 |
+
......................................................................................
|
62 |
+
|
63 |
+
For a more in-depth explanation, consult the reference for the =Uize.Array.Order.insideOut= method.
|
64 |
+
|
65 |
+
Outside to In
|
66 |
+
The elements of an array can be reordered from outside to in by using the =Uize.Array.Order.insideOut= static method, or by using the =Uize.Array.Order.reorder= method and specifying the value ='outside in'= for the method's =reorderingModeSTR= parameter.
|
67 |
+
|
68 |
+
EXAMPLE
|
69 |
+
......................................................................................
|
70 |
+
Uize.Array.Order.outsideIn ([1,2,3,4,5,6,7,8]); // returns the array [1,8,2,7,3,6,4,5]
|
71 |
+
......................................................................................
|
72 |
+
|
73 |
+
For a more in-depth explanation, consult the reference for the =Uize.Array.Order.outsideIn= method.
|
74 |
+
|
75 |
+
Versatile Target
|
76 |
+
The methods of the =Uize.Array.Order= module support a versatile target facility that allows the processed elements of the source array to be targeted either to the source array, to a fresh array, or to a specified target array.
|
77 |
+
|
78 |
+
With JavaScript's built-in =Array= object, some instance methods will modify the source array while others will create a fresh array. For example, the =splice= and =reverse= methods will modify the source array. On the other hand, the =concat= and =slice= methods return new arrays. In contrast, the methods of the =Uize.Array.Order= module let you specify the target behavior for the processed elements of the source array. A target is specified using the optional =targetARRAYorBOOL= parameter. Essentially three behaviors are supported: 1) modify the source array, 2) create a fresh array, or 3) use a specified target array.
|
79 |
+
|
80 |
+
For a more in-depth discussion, consult the reference for the =targetARRAYorBOOL= value type.
|
81 |
+
*/
|
82 |
+
|
83 |
+
Uize.module ({
|
84 |
+
name:'Uize.Array.Order',
|
85 |
+
builder:function () {
|
86 |
+
/*** Variables for Scruncher Optimization ***/
|
87 |
+
var _package = function () {};
|
88 |
+
|
89 |
+
/*** Utility Functions ***/
|
90 |
+
function _randomSorter () {return Math.random () - .5}
|
91 |
+
|
92 |
+
/*** Public Static Methods ***/
|
93 |
+
var _reorder = _package.reorder = function (_source,_reorderScheme,_target) {
|
94 |
+
if (typeof _target != 'object')
|
95 |
+
_target = _target === false ? _source : []
|
96 |
+
;
|
97 |
+
if (
|
98 |
+
_target == _source &&
|
99 |
+
(_reorderScheme == 'normal' || _reorderScheme == 'reverse' || _reorderScheme == 'jumbled')
|
100 |
+
) {
|
101 |
+
_reorderScheme == 'reverse'
|
102 |
+
? _source.reverse ()
|
103 |
+
: _reorderScheme == 'jumbled'
|
104 |
+
? _source.sort (_randomSorter)
|
105 |
+
: 0
|
106 |
+
;
|
107 |
+
} else {
|
108 |
+
if (_target == _source) _source = _source.concat ();
|
109 |
+
var
|
110 |
+
_sourceLength = _source.length,
|
111 |
+
_sourceLengthMinus1 = _sourceLength - 1,
|
112 |
+
_indexMapper
|
113 |
+
;
|
114 |
+
if (_reorderScheme == 'reverse') {
|
115 |
+
_indexMapper = function (_index) {return _sourceLengthMinus1 - _index};
|
116 |
+
} else if (_reorderScheme == 'inside out') {
|
117 |
+
var
|
118 |
+
_startLeft = _sourceLength % 2,
|
119 |
+
_rightInnerNo = Math.ceil (_sourceLengthMinus1 / 2)
|
120 |
+
;
|
121 |
+
_indexMapper = function (_index) {
|
122 |
+
return (
|
123 |
+
_index % 2 == _startLeft
|
124 |
+
? _rightInnerNo - 1 - (_index >> 1)
|
125 |
+
: _rightInnerNo + (_index >> 1)
|
126 |
+
);
|
127 |
+
};
|
128 |
+
} else if (_reorderScheme == 'outside in') {
|
129 |
+
_indexMapper = function (_index) {
|
130 |
+
return _index % 2 ? _sourceLengthMinus1 - (_index >> 1) : _index >> 1;
|
131 |
+
};
|
132 |
+
} else if (_reorderScheme == 'normal') {
|
133 |
+
_indexMapper = Uize.returnX;
|
134 |
+
} else {
|
135 |
+
var _jumbledOrder = Uize.map (_sourceLength,'key').sort (_randomSorter);
|
136 |
+
_indexMapper = function (_index) {return _jumbledOrder [_index]};
|
137 |
+
}
|
138 |
+
for (var _elementNo = -1; ++_elementNo <= _sourceLengthMinus1;)
|
139 |
+
_target [_elementNo] = _source [_indexMapper (_elementNo)]
|
140 |
+
;
|
141 |
+
}
|
142 |
+
return _target;
|
143 |
+
/*?
|
144 |
+
Static Methods
|
145 |
+
Uize.Array.Order.reorder
|
146 |
+
Returns an array, being a reordered version of the specified source array, using the specified reordering mode.
|
147 |
+
|
148 |
+
SYNTAX
|
149 |
+
..........................................................................
|
150 |
+
reorderedARRAY = Uize.Array.Order.reorder (sourceARRAY,reorderingModeSTR);
|
151 |
+
..........................................................................
|
152 |
+
|
153 |
+
VARIATION 1
|
154 |
+
.............................................................................
|
155 |
+
reorderedARRAY =
|
156 |
+
Uize.Array.Order.reorder (sourceARRAY,reorderingModeSTR,targetARRAYorBOOL)
|
157 |
+
;
|
158 |
+
.............................................................................
|
159 |
+
|
160 |
+
By default, the =Uize.Array.Order.reorder= method packages the reordered array elements into a new array and does not modify the source array (ie. it's non-destructive). Specifying the optional =targetARRAYorBOOL= parameter allows you to explicitly specify a target for the operation, into which the reordered elements will be packaged.
|
161 |
+
|
162 |
+
VARIATION 2
|
163 |
+
......................................................
|
164 |
+
jumbledARRAY = Uize.Array.Order.reorder (sourceARRAY);
|
165 |
+
......................................................
|
166 |
+
|
167 |
+
When only a =sourceARRAY= parameter is specified, then the default behavior is to reorder the source array using the ='jumble'= mode and package the results into a new array.
|
168 |
+
|
169 |
+
reorderingModeSTR
|
170 |
+
The =reorderingModeSTR= parameter is a string, specifying the reordering mode that should be employed, and can have the following values...
|
171 |
+
|
172 |
+
- ='jumbled'= (default) - reorders the specified source array in the same way as the =Uize.Array.Order.jumble= static method
|
173 |
+
- ='reverse'= - reorders the specified source array in the same way as the =Uize.Array.Order.reverse= static method
|
174 |
+
- ='inside out'= - reorders the specified source array in the same way as the =Uize.Array.Order.insideOut= static method
|
175 |
+
- ='outside in'= - reorders the specified source array in the same way as the =Uize.Array.Order.outsideIn= static method
|
176 |
+
- ='normal'= - leaves the order of elements unchanged
|
177 |
+
|
178 |
+
NOTES
|
179 |
+
- see the related =Uize.Array.Order.insideOut=, =Uize.Array.Order.jumble=, =Uize.Array.Order.outsideIn=, and =Uize.Array.Order.reverse= static methods
|
180 |
+
*/
|
181 |
+
};
|
182 |
+
|
183 |
+
_package.insideOut = function (_elements,_target) {
|
184 |
+
return _reorder (_elements,'inside out',_target)
|
185 |
+
/*?
|
186 |
+
Static Methods
|
187 |
+
Uize.Array.Order.insideOut
|
188 |
+
Returns an array, being the specified source array reordered from inside to out.
|
189 |
+
|
190 |
+
SYNTAX
|
191 |
+
..........................................................
|
192 |
+
reorderedARRAY = Uize.Array.Order.insideOut (sourceARRAY);
|
193 |
+
..........................................................
|
194 |
+
|
195 |
+
When an array is reordered from inside to out, the new order is formed by starting with the inner elements and moving outwards in both directions to reach the start and the end of the array. Consider the following example...
|
196 |
+
|
197 |
+
EXAMPLE
|
198 |
+
......................................................................................
|
199 |
+
Uize.Array.Order.insideOut ([1,2,3,4,5,6,7,8]); // returns the array [4,5,3,6,2,7,1,8]
|
200 |
+
......................................................................................
|
201 |
+
|
202 |
+
In the above example, at the center of the array being reordered are the values =4= and =5=. These are the first two elements of the reordered array. Moving outwards in both directions, the next two values are =3= and =6=, so these are the next two elements in the reordered array. Moving outwards further, the next two values are =2= and =7=, which become the next two elements in the reordered array. Finally, we get to the first and last values in the array being reordered, =1= and =9=, which become the last two elements of the reordered array.
|
203 |
+
|
204 |
+
VARIATION
|
205 |
+
............................................................................
|
206 |
+
reorderedARRAY = Uize.Array.Order.insideOut (sourceARRAY,targetARRAYorBOOL);
|
207 |
+
............................................................................
|
208 |
+
|
209 |
+
When the optional =targetARRAYorBOOL= parameter is specified, the target destination for the reordered elements can be controlled (for more info, see the reference for the =targetARRAYorBOOL= value type).
|
210 |
+
|
211 |
+
NOTES
|
212 |
+
- see the related =Uize.Array.Order.jumble=, =Uize.Array.Order.outsideIn=, =Uize.Array.Order.reorder=, and =Uize.Array.Order.reverse= static methods
|
213 |
+
*/
|
214 |
+
};
|
215 |
+
|
216 |
+
_package.jumble = function (_elements,_target) {
|
217 |
+
return _reorder (_elements,'jumbled',_target)
|
218 |
+
/*?
|
219 |
+
Static Methods
|
220 |
+
Uize.Array.Order.jumble
|
221 |
+
Returns an array, being a jumbled (randomly shuffled) version of the specified source array.
|
222 |
+
|
223 |
+
SYNTAX
|
224 |
+
.......................................................
|
225 |
+
reorderedARRAY = Uize.Array.Order.jumble (sourceARRAY);
|
226 |
+
.......................................................
|
227 |
+
|
228 |
+
EXAMPLE
|
229 |
+
.......................................................................................
|
230 |
+
Uize.Array.Order.jumble ([1,2,3,4,5,6,7,8]); // returns an array like [2,8,4,1,6,3,7,5]
|
231 |
+
.......................................................................................
|
232 |
+
|
233 |
+
In the above example, the order of the elements in the jumbled array will very likely be different for every different time that the =Uize.Array.Order.jumble= method is called.
|
234 |
+
|
235 |
+
VARIATION
|
236 |
+
.........................................................................
|
237 |
+
reorderedARRAY = Uize.Array.Order.jumble (sourceARRAY,targetARRAYorBOOL);
|
238 |
+
.........................................................................
|
239 |
+
|
240 |
+
When the optional =targetARRAYorBOOL= parameter is specified, the target destination for the jumbled elements can be controlled (for more info, see the reference for the =targetARRAYorBOOL= value type).
|
241 |
+
|
242 |
+
NOTES
|
243 |
+
- see the related =Uize.Array.Order.insideOut=, =Uize.Array.Order.outsideIn=, =Uize.Array.Order.reorder=, and =Uize.Array.Order.reverse= static methods
|
244 |
+
*/
|
245 |
+
};
|
246 |
+
|
247 |
+
_package.outsideIn = function (_elements,_target) {
|
248 |
+
return _reorder (_elements,'outside in',_target)
|
249 |
+
/*?
|
250 |
+
Static Methods
|
251 |
+
Uize.Array.Order.outsideIn
|
252 |
+
Returns an array, being the specified source array reordered from outside to in.
|
253 |
+
|
254 |
+
SYNTAX
|
255 |
+
..........................................................
|
256 |
+
reorderedARRAY = Uize.Array.Order.outsideIn (sourceARRAY);
|
257 |
+
..........................................................
|
258 |
+
|
259 |
+
When an array is reordered from outside to in, the new order is formed by starting with the start and the end of the array and moving inwards in both directions to reach the inner elements. Consider the following example...
|
260 |
+
|
261 |
+
EXAMPLE
|
262 |
+
......................................................................................
|
263 |
+
Uize.Array.Order.outsideIn ([1,2,3,4,5,6,7,8]); // returns the array [1,8,2,7,3,6,4,5]
|
264 |
+
......................................................................................
|
265 |
+
|
266 |
+
In the above example, at the start and end of the array being reordered are the values =1= and =8=. These are the first two elements of the reordered array. Moving inwards in both directions, the next two values are =2= and =7=, so these are the next two elements in the reordered array. Moving inwards further, the next two values are =3= and =6=, which become the next two elements in the reordered array. Finally, we get to the inner values in the array being reordered, =4= and =5=, which become the last two elements of the reordered array.
|
267 |
+
|
268 |
+
VARIATION
|
269 |
+
............................................................................
|
270 |
+
reorderedARRAY = Uize.Array.Order.outsideIn (sourceARRAY,targetARRAYorBOOL);
|
271 |
+
............................................................................
|
272 |
+
|
273 |
+
When the optional =targetARRAYorBOOL= parameter is specified, the target destination for the reordered elements can be controlled (for more info, see the reference for the =targetARRAYorBOOL= value type).
|
274 |
+
|
275 |
+
NOTES
|
276 |
+
- see the related =Uize.Array.Order.insideOut=, =Uize.Array.Order.jumble=, =Uize.Array.Order.reorder=, and =Uize.Array.Order.reverse= static methods
|
277 |
+
*/
|
278 |
+
};
|
279 |
+
|
280 |
+
_package.reverse = function (_elements,_target) {
|
281 |
+
return _reorder (_elements,'reverse',_target)
|
282 |
+
/*?
|
283 |
+
Static Methods
|
284 |
+
Uize.Array.Order.reverse
|
285 |
+
Returns an array, being a reversed version of the specified source array.
|
286 |
+
|
287 |
+
SYNTAX
|
288 |
+
........................................................
|
289 |
+
reorderedARRAY = Uize.Array.Order.reverse (sourceARRAY);
|
290 |
+
........................................................
|
291 |
+
|
292 |
+
EXAMPLE
|
293 |
+
....................................................................................
|
294 |
+
Uize.Array.Order.reverse ([1,2,3,4,5,6,7,8]); // returns the array [8,7,6,5,4,3,2,1]
|
295 |
+
....................................................................................
|
296 |
+
|
297 |
+
VARIATION
|
298 |
+
..........................................................................
|
299 |
+
reorderedARRAY = Uize.Array.Order.reverse (sourceARRAY,targetARRAYorBOOL);
|
300 |
+
..........................................................................
|
301 |
+
|
302 |
+
When the optional =targetARRAYorBOOL= parameter is specified, the target destination for the reversed elements can be controlled (for more info, see the reference for the =targetARRAYorBOOL= value type).
|
303 |
+
|
304 |
+
NOTES
|
305 |
+
- see the related =Uize.Array.Order.insideOut=, =Uize.Array.Order.jumble=, =Uize.Array.Order.outsideIn=, and =Uize.Array.Order.reorder= static methods
|
306 |
+
*/
|
307 |
+
};
|
308 |
+
|
309 |
+
/*?
|
310 |
+
Value Types
|
311 |
+
For the sake of not redundantly describing the value types for certain method parameters and return values repeatedly, some common value types are described here.
|
312 |
+
|
313 |
+
sourceARRAY
|
314 |
+
An array reference, specifying an array that should be processed by an array method.
|
315 |
+
|
316 |
+
Values of this type can be accepted by the =Uize.Array.Order.insideOut=, =Uize.Array.Order.jumble=, =Uize.Array.Order.outsideIn=, =Uize.Array.Order.reorder=, and =Uize.Array.Order.reverse= static methods.
|
317 |
+
|
318 |
+
Array-like Values
|
319 |
+
Methods that accept parameters of the =sourceARRAY= value type can also support array-like objects, such as collections of DOM nodes - provided that the source array is not also specified as the target for reordered elements.
|
320 |
+
|
321 |
+
targetARRAYorBOOL
|
322 |
+
An array reference or boolean value, which lets you specify where the result of an array method's processing should be packaged.
|
323 |
+
|
324 |
+
Values of this type can be accepted by the =Uize.Array.Order.insideOut=, =Uize.Array.Order.jumble=, =Uize.Array.Order.outsideIn=, =Uize.Array.Order.reorder=, and =Uize.Array.Order.reverse= static methods.
|
325 |
+
|
326 |
+
VALUES
|
327 |
+
|
328 |
+
- When the *boolean* value =true= is specified (the default value for the =targetARRAYorBOOL= parameter if it is omitted), then the result of an array method's processing will be packaged into a new array.
|
329 |
+
|
330 |
+
- When the *boolean* value =false= is specified (not the same as not specifying a value), then the result of an array method's processing will be packaged into the source array that was supplied to the array method in its =sourceARRAY= parameter (ie. the method won't use a different target).
|
331 |
+
|
332 |
+
- When an *array* is explicitly specified, then the result of an array method's processing will be packaged into the specified target array. This is convenient if you already have an array into which you wish to package the result. Incidentally, specifying the source array that you supplied to an array method as also the target array has the same effect as specifying the value =false= for =targetARRAYorBOOL= (ie. use the source as the target, don't use a different target).
|
333 |
+
*/
|
334 |
+
|
335 |
+
return _package;
|
336 |
+
}
|
337 |
+
});
|
338 |
+
|
skin/frontend/default/customproduct/js/Uize.Array.Sort.js
ADDED
@@ -0,0 +1,510 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Array.Sort Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2010-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 2
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 100
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Array.Sort= module provides a powerful array sorting method that is very versatile and highly optimized for performance.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
Key Features
|
27 |
+
The =Uize.Array.Sort= module offers a number of important features, as outlined below...
|
28 |
+
|
29 |
+
Sort Value Generator
|
30 |
+
The =Uize.Array.Sort.sortBy= static method allows an array to be sorted by sort values that are generated for elements of the array by a sort value generator, which can be specified as either a `Sort Value Generator Expression` or a `Value Generator Function`.
|
31 |
+
|
32 |
+
Why a Sort Value Generator?
|
33 |
+
When one sorts an array using the =sort= instance method of JavaScript's =Array= object, the =sort= method compares the raw values of the array's elements - unless one specifies a custom comparison function.
|
34 |
+
|
35 |
+
When one *does* specify a comparison function, it may be called many times to compare the same value to some other value. If it is necessary to derive a value for use in the comparison, rather than simply using the raw value for an element, then the code to derive a value to be used in the comparison might be executed redundantly many times. This can be particularly costly when sorting a large array and where the code to derive a value for comparison involves more significant processing.
|
36 |
+
|
37 |
+
To illustrate this point, consider the example of a case-insensitive sort. If one simply uses the =Array= object's =sort= instance method, then one might write the sort code as follows...
|
38 |
+
|
39 |
+
POOR PERFORMANCE
|
40 |
+
.......................................................................................
|
41 |
+
firstNames.sort (function (a,b) {return a.toLowerCase () < b.toLowerCase () ? -1 : 1});
|
42 |
+
.......................................................................................
|
43 |
+
|
44 |
+
In the above example, the =toLowerCase= instance method of the =Array= object is being used to convert both string values being compared to lower case - this ensures that the case of individual characters in the two strings has no effect on the sort order, and the sort is thereby made case-insensitive. Problem is, the =toLowerCase= method may be called multiple times for the same element, just because of how the =sort= method is implemented. This could become a very serious performance problem when sorting large arrays of very long strings using this approach. This is where the =Uize.Array.Sort.sortBy= method comes in. Using this method, the above example could be rewritten as follows...
|
45 |
+
|
46 |
+
IMPROVED PERFORMANCE
|
47 |
+
...........................................................
|
48 |
+
Uize.Array.Sort.sortBy (firstNames,'value.toLowerCase ()');
|
49 |
+
...........................................................
|
50 |
+
|
51 |
+
Now that we're using the =Uize.Array.Sort.sortBy= method, we no longer specify a comparison function. Instead, we're specifying the string ='value.toLowerCase ()'= as a `Sort Value Generator Expression`. This expression will be used for every element of the array being sorted. The array will then be sorted using the sort values generated for each of the array's elements. Instead of using the array's element values in the comparison function, the =Uize.Array.Sort.sortBy= method will use the generated sort values. This means that the =toLowerCase= method is guaranteed to only be called once for every element of the array.
|
52 |
+
|
53 |
+
Sort Value Generator Function
|
54 |
+
A Sort Value Generator Function is a `Sort Value Generator` specified in the form of a function.
|
55 |
+
|
56 |
+
When a function is specified for the Sort Value Generator, it should expect to receive two parameters: the value for an element of the array being sorted, and the index / key for that element. The function should return the generated sort value. Generated sort values should be of a type that can be used with the boolean less than and greater than comparison operators - numbers and strings are the typical types that are appropriate for generated sort values. This is all illustrated well in the following example...
|
57 |
+
|
58 |
+
EXAMPLE
|
59 |
+
..................................................................................
|
60 |
+
Uize.Array.Sort.sortBy (names,function (value,key) {return value.toLowerCase ()});
|
61 |
+
..................................................................................
|
62 |
+
|
63 |
+
In the above example, the =names= array is an array of string values. It is being sorted in ASCIIbetical order, using a Sort Value Generator Function that renders the sort case-insensitive. The function accepts =value= and =key= parameters, using the =value= parameter to generate a sort value that is an element's value converted to all lower case. As you'll notice, the function is not actually using the =key= parameter, so it could just as well be omitted, as follows...
|
64 |
+
|
65 |
+
WITHOUT THE KEY PARAMETER
|
66 |
+
..............................................................................
|
67 |
+
Uize.Array.Sort.sortBy (names,function (value) {return value.toLowerCase ()});
|
68 |
+
..............................................................................
|
69 |
+
|
70 |
+
For an example of how an element's key might be used in generating sort values, see the section `Using an Element's Key To Generate a Sort Value`.
|
71 |
+
|
72 |
+
Sort Value Generator Expression
|
73 |
+
A Sort Value Generator Expression is a `Sort Value Generator` specified in the form of an expression string.
|
74 |
+
|
75 |
+
When an expression string is specified for the Sort Value Generator, it should expect two variables to be defined in the scope of the expression's code: the =value= variable contains the value for an element of the array being sorted, and the =key= variable contains that element's index / key. The expression should produce the generated sort value. Generated sort values should be of a type that can be used with the boolean less than and greater than comparison operators - numbers and strings are the typical types that are appropriate for generated sort values. This is all illustrated well in the following example...
|
76 |
+
|
77 |
+
EXAMPLE
|
78 |
+
......................................................
|
79 |
+
Uize.Array.Sort.sortBy (names,'value.toLowerCase ()');
|
80 |
+
......................................................
|
81 |
+
|
82 |
+
In the above example, the =names= array is an array of string values. It is being sorted in ASCIIbetical order, using a Sort Value Generator Expression that renders the sort case-insensitive. The expression is using the =value= variable to generate a sort value that is an element's value converted to all lower case. As you'll notice, using a `Sort Value Generator Expression` can be more concise than using a `Sort Value Generator Function`. And since you're just specifying a JavaScript expression and not defining a function, there is no =return= statement in the expression.
|
83 |
+
|
84 |
+
You'll also notice that the expression is not using the =key= variable in generating the sort value. For an example of how an element's key might be used in generating sort values, see the section `Using an Element's Key To Generate a Sort Value`.
|
85 |
+
|
86 |
+
Using an Element's Key To Generate a Sort Value
|
87 |
+
The key for an element is very seldom used when performing a sort using the =Uize.Array.Sort.sortBy= method, but the following hypothetical example demonstrates how it might be used...
|
88 |
+
|
89 |
+
USING THE KEY
|
90 |
+
.............................................................................
|
91 |
+
Uize.Array.Sort.sortBy (values,'key + (key % 2 ? ' + names.length + ' : 0)');
|
92 |
+
.............................................................................
|
93 |
+
|
94 |
+
In the above example, the =values= array is being "sorted" so that all even numbered elements are clumped at the beginning and all odd numbered elements are clumped at the end. So, if the contents of the values array was =['a','b','c','d','e','f','g','h']=, then the sorted values would be =['a','c','e','g','b','d','f','h']=. The reason this works is because the generated sort value is the key for even numbered elements, and the key plus the length of the array for odd numbered elements, achieved by using the =%= (mod) operator with a ternary operator expression. This preserves the order of the elements within the even numbered and odd numbered clumps of elements, but pushes all the odd numbered elements to after the even numbered elements. Generated sort values are not required to map in any way to the indexes of elements in the array being sorted, so it's ok than the sort values in this case extend beyond the length of the array, and that there are gaps between consecutive sort values.
|
95 |
+
|
96 |
+
When the values of an array's elements are not used when generating sort values, then what you're doing is more like a reordering algorithm than a sort. Of course, there's no saying you can't use both the value and the index / key for elements when generating sort values.
|
97 |
+
|
98 |
+
Sort Order Direction
|
99 |
+
As a convenience, the sort direction for sorts performed by the =Uize.Array.Sort.sortBy= method can be controlled via its optional =directionINT= parameter.
|
100 |
+
|
101 |
+
Specifying the value =-1= for the =directionINT= parameter will reverse the sort direction for a sort. Consider the following example...
|
102 |
+
|
103 |
+
EXAMPLE
|
104 |
+
.........................................................
|
105 |
+
Uize.Array.Sort.sortBy (names,'value.toLowerCase ()',-1);
|
106 |
+
.........................................................
|
107 |
+
|
108 |
+
In the above example, the =names= array is an array of string values. It is being sorted in descending ASCIIbetical order, using a `Sort Value Generator Expression` that renders the sort case-insensitive. Using the =directionINT= parameter when you want to perform a sort in descending order is more efficient than first performing the sort and then reversing the sorted array using the array's =reverse= instance method. This is because the =Uize.Array.Sort.sortBy= method takes the sort direction into account during the sort operation's reordering of the array's elements.
|
109 |
+
|
110 |
+
Easy Data Table Sorting
|
111 |
+
The =Uize.Array.Sort= module's =Uize.Array.Sort.sortBy= method makes it very easy to sort a data table by the values of a specific column, simply by the number of the column to sort the table by for the method's =sortColumnINT= parameter.
|
112 |
+
|
113 |
+
A data table is an array of arrays, where each array type element represents a row of data in the table. Consider the following example...
|
114 |
+
|
115 |
+
EXAMPLE
|
116 |
+
..................................
|
117 |
+
var
|
118 |
+
fruits = [
|
119 |
+
['Apples',52,13.81,2.4],
|
120 |
+
['Avocados',160,8.53,6.7],
|
121 |
+
['Bananas',89,22.84,2.6],
|
122 |
+
['Dates',277,74.97,6.7],
|
123 |
+
['Grapefruits',42,10.66,1.6]
|
124 |
+
]
|
125 |
+
;
|
126 |
+
Uize.Array.Sort.sortBy (fruits,1);
|
127 |
+
..................................
|
128 |
+
|
129 |
+
In the above example, the =fruits= array is a data table array where each row contains data describing a fruit. Each row array contains information for fruit name, calorie count, total carbohydrates, and dietary fiber. We're using the =Uize.Array.Sort.sortBy= method to sort the fruits in order of their caloric content, from lowest calorie count to highest calorie count. Specifying the value =1= for the =sortColumnINT= parameter indicates that the values of the second column (column numbers are zero-based) should be used as the sort values, so the sort values used to drive the sort of the =fruits= array is an array of calorie count numbers.
|
130 |
+
|
131 |
+
Easy Record Array Sorting
|
132 |
+
With the use of a simple `Sort Value Generator Expression`, the =Uize.Array.Sort= module's =Uize.Array.Sort.sortBy= method makes it a very concise thing to sort an array of records by a specific record field.
|
133 |
+
|
134 |
+
A records array is an array of objects, where each object represents a record and contains properties that represent the fields of the record. Consider the following example...
|
135 |
+
|
136 |
+
EXAMPLE
|
137 |
+
.......................................................................
|
138 |
+
var
|
139 |
+
fruits = [
|
140 |
+
{name:'Apples',calories:52,totalCarbs:13.81,dietaryFiber:2.4},
|
141 |
+
{name:'Avocados',calories:160,totalCarbs:8.53,dietaryFiber:6.7},
|
142 |
+
{name:'Bananas',calories:89,totalCarbs:22.84,dietaryFiber:2.6},
|
143 |
+
{name:'Dates',calories:277,totalCarbs:74.97,dietaryFiber:6.7},
|
144 |
+
{name:'Grapefruits',calories:42,totalCarbs:10.66,dietaryFiber:1.6}
|
145 |
+
]
|
146 |
+
;
|
147 |
+
Uize.Array.Sort.sortBy (fruits,'value.calories');
|
148 |
+
.......................................................................
|
149 |
+
|
150 |
+
In the above example, the =fruits= array is a records array where each record describes a fruit and contains the fields =name=, =calories=, =totalCarbs=, and =dietaryFiber=. We're using the =Uize.Array.Sort.sortBy= method to sort the fruits in order of their caloric content, from lowest calorie count to highest calorie count. The `Sort Value Generator Expression` used here simply dereferences the =calories= property for a record, so the generated sort values used to drive the sort of the =fruits= array is an array of calorie count numbers.
|
151 |
+
|
152 |
+
Optimized For Performance
|
153 |
+
The =Uize.Array.Sort= method of the =Uize.Array.Sort= module is optimized for performance.
|
154 |
+
|
155 |
+
The =Uize.Array.Sort= method sorts an array based upon sort values that are generated for all of the array's elements. These sort values are generated in the first pass of the sorting operation, and as a one time operation, unlike the traditional approach of generating comparison values every time one element is compared to another. This is illustrated well in the classic example of performing a case-insensitive ASCIIbetical sort of an array of strings, where a typical use of the =sort= instance method of JavaScript's =Array= object would be quite inefficient. That's because the same string value may be lowercased repeatedly - each time a given element is compared to some other element. The typical, inefficient solution might look as follows...
|
156 |
+
|
157 |
+
INEFFICIENT CLASSIC SOLUTION
|
158 |
+
..................................................................................
|
159 |
+
names.sort (function (a,b) {return a.toLowerCase () < b.toLowerCase () ? -1 : 1});
|
160 |
+
..................................................................................
|
161 |
+
|
162 |
+
A more efficient solution is to use the =Uize.Array.Sort.sortBy= method, because it ensures that the lowercasing will only be performed once per element of the source array.
|
163 |
+
|
164 |
+
EFFICIENT SOLUTION
|
165 |
+
......................................................
|
166 |
+
Uize.Array.Sort.sortBy (names,'value.toLowerCase ()');
|
167 |
+
......................................................
|
168 |
+
|
169 |
+
Sorts Are More Concise
|
170 |
+
Besides being `Optimized For Performance`, the =Uize.Array.Sort.sortBy= method of the ==Uize.Array.Sort= module also produces more concise code than using the traditional approach.
|
171 |
+
|
172 |
+
To illustrate this point, consider the following before-and-after examples...
|
173 |
+
|
174 |
+
BEFORE-AFTER: Sort a Strings Array in Case-insensitive ASCIIbetical Order
|
175 |
+
BEFORE
|
176 |
+
.......................................................................................
|
177 |
+
firstNames.sort (function (a,b) {return a.toLowerCase () < b.toLowerCase () ? -1 : 1});
|
178 |
+
.......................................................................................
|
179 |
+
|
180 |
+
AFTER
|
181 |
+
......................................................
|
182 |
+
Uize.Array.Sort.sortBy (names,'value.toLowerCase ()');
|
183 |
+
......................................................
|
184 |
+
|
185 |
+
BEFORE-AFTER: Sort a Data Table Array By the Values of the Second Column
|
186 |
+
BEFORE
|
187 |
+
............................................................
|
188 |
+
table.sort (function (a,b) {return a [1] < b [1] ? -1 : 1});
|
189 |
+
............................................................
|
190 |
+
|
191 |
+
AFTER
|
192 |
+
.................................
|
193 |
+
Uize.Array.Sort.sortBy (table,1);
|
194 |
+
.................................
|
195 |
+
|
196 |
+
BEFORE-AFTER: Sort a Records Array by the name Field
|
197 |
+
BEFORE
|
198 |
+
................................................................
|
199 |
+
records.sort (function (a,b) {return a.name < b.name ? -1 : 1});
|
200 |
+
................................................................
|
201 |
+
|
202 |
+
AFTER
|
203 |
+
..............................................
|
204 |
+
Uize.Array.Sort.sortBy (records,'value.name');
|
205 |
+
..............................................
|
206 |
+
*/
|
207 |
+
|
208 |
+
Uize.module ({
|
209 |
+
name:'Uize.Array.Sort',
|
210 |
+
builder:function () {
|
211 |
+
/*** Variables for Scruncher Optimization ***/
|
212 |
+
var _package = function () {};
|
213 |
+
|
214 |
+
/*** General Variables ***/
|
215 |
+
var
|
216 |
+
_sortValues = [],
|
217 |
+
_ascendingSort = new Function ('a','b','return a.v<b.v?-1:a.v>b.v?1:0'),
|
218 |
+
_descendingSort = new Function ('a','b','return a.v<b.v?1:a.v>b.v?-1:0'),
|
219 |
+
_ascendingSimpleSort = new Function ('a','b','return a<b?-1:a>b?1:0'),
|
220 |
+
_descendingSimpleSort = new Function ('a','b','return a<b?1:a>b?-1:0')
|
221 |
+
;
|
222 |
+
|
223 |
+
/*** Public Static Methods ***/
|
224 |
+
_package.sortBy = function (_elements,_sortValueGenerator,_direction) {
|
225 |
+
var _elementsLength = _elements.length;
|
226 |
+
if (_elementsLength > 1) {
|
227 |
+
if (_sortValueGenerator != null) {
|
228 |
+
var _sortValue;
|
229 |
+
if (!Uize.isFunction (_sortValueGenerator)) {
|
230 |
+
if (typeof _sortValueGenerator == 'number')
|
231 |
+
_sortValueGenerator = 'value [' + _sortValueGenerator + ']'
|
232 |
+
;
|
233 |
+
_sortValueGenerator = Uize.resolveTransformer (_sortValueGenerator);
|
234 |
+
};
|
235 |
+
/*** build sortValues array ***/
|
236 |
+
for (var _elementNo = _sortValues.length = _elementsLength; --_elementNo >= 0;) {
|
237 |
+
(_sortValue = _sortValues [_elementNo] || (_sortValues [_elementNo] = {})).v =
|
238 |
+
_sortValueGenerator (
|
239 |
+
_sortValue._element = _elements [_sortValue._elementNo = _elementNo],
|
240 |
+
_elementNo
|
241 |
+
)
|
242 |
+
;
|
243 |
+
}
|
244 |
+
|
245 |
+
/*** sort sortValues array ***/
|
246 |
+
_sortValues.sort (_direction == -1 ? _descendingSort : _ascendingSort);
|
247 |
+
|
248 |
+
/*** re-populate array to be sorted, using sortValues array ***/
|
249 |
+
for (var _elementNo = _elementsLength; --_elementNo >= 0;) {
|
250 |
+
if (_elementNo != (_sortValue = _sortValues [_elementNo])._elementNo)
|
251 |
+
_elements [_elementNo] = _sortValue._element
|
252 |
+
;
|
253 |
+
_sortValue._element = _sortValue.v = null;
|
254 |
+
}
|
255 |
+
} else {
|
256 |
+
_elements.sort (_direction == -1 ? _descendingSimpleSort : _ascendingSimpleSort);
|
257 |
+
}
|
258 |
+
}
|
259 |
+
return _elements;
|
260 |
+
/*?
|
261 |
+
Static Methods
|
262 |
+
Uize.Array.Sort.sortBy
|
263 |
+
Returns an array, being the specified source array sorted by the values generated by the specified value generator (the source array is modified by this method).
|
264 |
+
|
265 |
+
SYNTAX
|
266 |
+
..........................................................................
|
267 |
+
sourceARRAY = Uize.Array.Sort.sortBy (sourceARRAY,sortValueGeneratorFUNC);
|
268 |
+
..........................................................................
|
269 |
+
|
270 |
+
The =Uize.Array.Sort.sortBy= method is engineered for high performance when sorting arrays where the sort order is determined by values that are derived from the source array's element values (see `Optimized For Performance` for more details).
|
271 |
+
|
272 |
+
When the =Uize.Array.Sort.sortBy= method sorts an array, it first generates sort values for all the elements of the array, using a `Sort Value Generator` that can be specified either in the form of a `Sort Value Generator Function` or a `Sort Value Generator Expression`. The method then sorts the array of generated sort values, and then applies that sort order back to the elements of the source array. This lets you drive the sorting of the source array by something other than the exact values of the source array's elements.
|
273 |
+
|
274 |
+
To illustrate this, let's take the simple example of performing a case-insensitive ASCIIbetical sort...
|
275 |
+
|
276 |
+
EXAMPLE
|
277 |
+
......................................................
|
278 |
+
Uize.Array.Sort.sortBy (names,'value.toLowerCase ()');
|
279 |
+
......................................................
|
280 |
+
|
281 |
+
In the above example, when the =Uize.Array.Sort.sortBy= method is called, a sort values array is generated by iterating over the elements of the =names= array, and for each element executing the specified sort value generator. In this case, the sort value generator uses the value for an element of the names array and then produces the lowercased version of that string as the sort value. The lowercased names are then sorted, and the resulting sort order determines the new order for the elements of the source array.
|
282 |
+
|
283 |
+
Generated Sort Values Only For Determining Sort Order
|
284 |
+
It's worth emphasizing that the generated sort values are only used in determining the sort ordering of the elements of the source array.
|
285 |
+
|
286 |
+
Therefore, in the case-insensitive ASCIIbetical sort example, the sorted values would be the original, non-lowercased values - *NOT* the lowercased sort values.
|
287 |
+
|
288 |
+
Variations
|
289 |
+
The =Uize.Array.Sort.sortBy= method supports the following variations...
|
290 |
+
|
291 |
+
VARIATION 1
|
292 |
+
.........................................................................
|
293 |
+
sourceARRAY = Uize.Array.Sort.sortBy (sourceARRAY,sortValueGeneratorSTR);
|
294 |
+
.........................................................................
|
295 |
+
|
296 |
+
When a =sortValueGeneratorSTR= parameter is specified in place of the =sortValueGeneratorFUNC= parameter, then a more concise JavaScript expression string can be specified for the sort value generator. For a more in-depth discussion of this feature and to see an example, consult the section `Sort Value Generator Expression`.
|
297 |
+
|
298 |
+
VARIATION 2
|
299 |
+
.................................................................
|
300 |
+
sourceARRAY = Uize.Array.Sort.sortBy (sourceARRAY,sortColumnINT);
|
301 |
+
.................................................................
|
302 |
+
|
303 |
+
When a =sortColumnINT= parameter is specified in place of the =sortValueGeneratorFUNC= parameter, then a data table (an array of row arrays) can be easily sorted by the values in one of its columns, by specifying the number of the column to sort the table by for the =sortColumnINT= parameter. For an example of this, see the section `Easy Data Table Sorting`.
|
304 |
+
|
305 |
+
VARIATIONS 3 & 4
|
306 |
+
.............................................................
|
307 |
+
sourceARRAY = Uize.Array.Sort.sortBy (sourceARRAY,null);
|
308 |
+
sourceARRAY = Uize.Array.Sort.sortBy (sourceARRAY,undefined);
|
309 |
+
.............................................................
|
310 |
+
|
311 |
+
When the value =null= or =undefined= is specified in place of the =sortValueGeneratorFUNC= parameter, then the =Uize.Array.Sort.sortBy= method will sort the specified array using the raw values of the array's elements as the sort values.
|
312 |
+
|
313 |
+
VARIATIONS 5, 6, 7, 8 & 9
|
314 |
+
.......................................................................................
|
315 |
+
sourceARRAY = Uize.Array.Sort.sortBy (sourceARRAY,sortValueGeneratorFUNC,directionINT);
|
316 |
+
sourceARRAY = Uize.Array.Sort.sortBy (sourceARRAY,sortValueGeneratorSTR,directionINT);
|
317 |
+
sourceARRAY = Uize.Array.Sort.sortBy (sourceARRAY,sortColumnINT,directionINT);
|
318 |
+
sourceARRAY = Uize.Array.Sort.sortBy (sourceARRAY,null,directionINT);
|
319 |
+
sourceARRAY = Uize.Array.Sort.sortBy (sourceARRAY,undefined,directionINT);
|
320 |
+
.......................................................................................
|
321 |
+
|
322 |
+
By default, the sort direction of the =Uize.Array.Sort.sortBy= method is ascending. When the optional =directionINT= parameter is specified, the direction for a sort can be controlled. Specifying the value =-1= for the =directionINT= parameter will cause the sort direction to be descending (ie. reversed), while specifying the value =1= will cause the sort direction to be ascending (the default).
|
323 |
+
|
324 |
+
VARIATION 10
|
325 |
+
...................................................
|
326 |
+
sourceARRAY = Uize.Array.Sort.sortBy (sourceARRAY);
|
327 |
+
...................................................
|
328 |
+
|
329 |
+
When only a =sourceARRAY= parameter is specified, the =Uize.Array.Sort.sortBy= method behaves in the same way as when the value =null= or =undefined= is specified for the sort value generator and no optional =directionINT= parameter is specified, performing the sort using the raw values of the source array's elements as the sort values.
|
330 |
+
|
331 |
+
Examples
|
332 |
+
Sort an Array of Strings by Length, Shortest to Longest
|
333 |
+
An array of strings can be sorted by length with a simple `Sort Value Generator Expression` that returns the value of the =length= property of a value.
|
334 |
+
|
335 |
+
EXAMPLE
|
336 |
+
................................................
|
337 |
+
Uize.Array.Sort.sortBy (strings,'value.length');
|
338 |
+
................................................
|
339 |
+
|
340 |
+
Sort an Array of People Records by lastName Property
|
341 |
+
A records array, where each element is an object containing data for a person, can be sorted by last name with a simple `Sort Value Generator Expression` that returns the value of the =lastName= property of a value.
|
342 |
+
|
343 |
+
EXAMPLE
|
344 |
+
........................................................
|
345 |
+
Uize.Array.Sort.sortBy (peopleRecords,'value.lastName');
|
346 |
+
........................................................
|
347 |
+
|
348 |
+
Sort an Array of People Records in lastName,firstName Order
|
349 |
+
A records array, where each element is an object containing data for a person, can be sorted by last name and subsorted by first name, with a `Sort Value Generator Expression` that concatenates the values of the =lastName= and =firstName= properties of a value.
|
350 |
+
|
351 |
+
EXAMPLE
|
352 |
+
................................................................................
|
353 |
+
Uize.Array.Sort.sortBy (peopleRecords,'value.lastName + "," + value.firstName');
|
354 |
+
................................................................................
|
355 |
+
|
356 |
+
Notice that a "," (comma character) is used as a delimiter between last name and first name. This is in order to avoid ambiguities that may arise if a first segment of one person's last name is coincidentally a last segment of someone else's first name. The comma forces a reliable split between the sort and subsort, because nobody's first or last name will contain a comma.
|
357 |
+
|
358 |
+
Sort an Array of Row Arrays By The Second Column
|
359 |
+
A rows array, where each element is an array representing a row of data in a data table, can be sorted by a specific column simply by specifying the column number for the =Uize.Array.Sort.sortBy= method's =sortColumnINT= parameter.
|
360 |
+
|
361 |
+
EXAMPLE
|
362 |
+
................................
|
363 |
+
Uize.Array.Sort.sortBy (rows,1);
|
364 |
+
................................
|
365 |
+
|
366 |
+
Column indexes are zero based, so specifying the value =1= in the above example will sort the =rows= data table array by the values in the second column.
|
367 |
+
|
368 |
+
Sort an Array of Strings That Are Decimal Numbers
|
369 |
+
An array of strings that are decimal formatted numbers can be sorted numerically (rather than ASCIIbetically), by specifying a simple `Sort Value Generator Expression` that returns an element's value coerced to a number.
|
370 |
+
|
371 |
+
EXAMPLE
|
372 |
+
................................................
|
373 |
+
Uize.Array.Sort.sortBy (numberStrings,'+value');
|
374 |
+
................................................
|
375 |
+
|
376 |
+
Coercing the string type element values to numbers is accomplished quite easily by simply prefixing the "+" (plus) operator in the expression.
|
377 |
+
|
378 |
+
Sort an Array of Strings That are Hex Formatted Numbers
|
379 |
+
An array of strings that are hexadecimal formatted numbers can be sorted numerically (rather than ASCIIbetically), by specifying a simple `Sort Value Generator Expression` that returns an element's value coerced to a decimal number.
|
380 |
+
|
381 |
+
EXAMPLE
|
382 |
+
............................................................
|
383 |
+
Uize.Array.Sort.sortBy (hexNumberStrings,'+("0x" + value)');
|
384 |
+
............................................................
|
385 |
+
|
386 |
+
It is assumed in this example that the hex formatted numbers are *not* prefixed with any kind of hex formatting indicator (such as "0x" for programming languages, or "#" for RGB color values in CSS). The hex numbers are coerced to decimal by prepending the "0x" and then coercing the resulting string to a number by prefixing the "+" (plus) operator in the `Sort Value Generator Expression`.
|
387 |
+
|
388 |
+
Sort an Array of Date Strings
|
389 |
+
An array of correctly formatted date strings can be sorted into chronological order, by specifying a `Sort Value Generator Expression` that transforms a date string value into a number, representing the date as the number of milliseconds elapsed since January 1st, 1970 (ie. POSIX time).
|
390 |
+
|
391 |
+
EXAMPLE
|
392 |
+
...........................................................
|
393 |
+
Uize.Array.Sort.sortBy (dateStrings,'+(new Date (value))');
|
394 |
+
...........................................................
|
395 |
+
|
396 |
+
A date string value is transformed into a POSIX time number by first using JavaScript's built-in =Date= object to parse the date string and create a =Date= object instance. The =Date= object instance is then coerced to a number by using the "+" (plus) operator, which invokes the =Date= object's =valueOf Intrinsic Method=.
|
397 |
+
|
398 |
+
Sort an Array of Date Objects
|
399 |
+
An array of =Date= object instances can be sorted into chronological order, by specifying a `Sort Value Generator Expression` that transforms a =Date= object instance into a number, representing the date as the number of milliseconds elapsed since January 1st, 1970 (ie. POSIX time).
|
400 |
+
|
401 |
+
EXAMPLE
|
402 |
+
..............................................
|
403 |
+
Uize.Array.Sort.sortBy (dateObjects,'+value');
|
404 |
+
..............................................
|
405 |
+
|
406 |
+
A =Date= object instance is transformed into a POSIX time number by simply using the "+" (plus) operator, which invokes the =Date= object's =valueOf Intrinsic Method=.
|
407 |
+
|
408 |
+
Sort Cubes by Volume, Smallest to Largest
|
409 |
+
An array of objects representing geometric cubes can be sorted according to their volumes, from smallest volume to largest volume, by specifying a `Sort Value Generator Expression` that calculates the volume for a cube from its =width=, =height=, and =depth= properties.
|
410 |
+
|
411 |
+
EXAMPLE
|
412 |
+
..........................................................................
|
413 |
+
Uize.Array.Sort.sortBy (cubes,'value.width * value.height * value.depth');
|
414 |
+
..........................................................................
|
415 |
+
|
416 |
+
Each value of the =cubes= array is an object containing =width=, =height=, and =depth= properties that describe a cube's dimensions. A `Sort Value Generator Expression` can calculate the volume for an element of the =cubes= array by dereferencing the =width=, =height=, and =depth= properties on the =value= variable and multiplying them together.
|
417 |
+
|
418 |
+
Sort Rectangles by Squarest, Most Square to Least Square
|
419 |
+
An array of objects representing rectangles can be sorted according to their squareness, from most square to least square, by specifying a `Sort Value Generator Expression` that calculates an aspect ratio for a rectangle from its =width= and =height= properties.
|
420 |
+
|
421 |
+
EXAMPLE
|
422 |
+
..............................................................................
|
423 |
+
Uize.Array.Sort.sortBy (
|
424 |
+
rectangles,
|
425 |
+
'Math.max (value.width,value.height) / Math.min (value.width,value.height)'
|
426 |
+
);
|
427 |
+
..............................................................................
|
428 |
+
|
429 |
+
Each value of the =rectangles= array is an object containing =width= and =height= properties that describe a rectangle's dimensions. A `Sort Value Generator Expression` can calculate the aspect ratio for an element of the =rectangles= array by dereferencing the =width= and =height= properties of the =value= variable and dividing the maximum axis dimension by the minimum axis dimension.
|
430 |
+
|
431 |
+
According to this calculation, a perfectly square rectangle will have an aspect ratio of =1=. The more unsquare a rectangle is, the higher the calculated aspect ratio value. By always dividing the maximum axis dimension by the minimum axis dimension, the aspect ratio is guaranteed to always be =1= or greater, rather than being less than =1= for rectangles whose =width= is smaller than their =height= (ie. where orientation is landscape rather than portrait). Now, sorting the generated sort values into ascending order, the elements of the =rectangles= array are sorted according to how close to square they are.
|
432 |
+
|
433 |
+
Sort Array of Numbers By Closeness to a Reference Number
|
434 |
+
An array of numbers can be sorted according to how close they are to a reference number, from closest to furthest away, by specifying a `Sort Value Generator Expression` that calculates for a number its absolute distance from the reference number.
|
435 |
+
|
436 |
+
EXAMPLE
|
437 |
+
..............................................................................
|
438 |
+
Uize.Array.Sort.sortBy (numbers,'Math.abs (' + referenceNumber + ' - value)');
|
439 |
+
..............................................................................
|
440 |
+
|
441 |
+
Because we are using a `Sort Value Generator Expression` rather than a `Sort Value Generator Function` in our example, we can fix the value of the =referenceNumber= variable into the expression using string concatenation. We use the =Math.abs= method of JavaScript's built-in =Math= object to ensure that the calculated distance is always positive - this ensures that numbers are sorted based on their closeness to the reference number, regardless of on which side of the reference number they fall. Now, sorting the generated sort values into ascending order, the elements of the =numbers= array are sorted according to how close they are to the reference number.
|
442 |
+
|
443 |
+
Sort Array of Names in Case-insensitive ASCIIbetical Order
|
444 |
+
An array of strings can be sorted into case-insensitive ASCIIbetical order, by specifying a `Sort Value Generator Expression` that generates a lower case version of a string value.
|
445 |
+
|
446 |
+
EXAMPLE
|
447 |
+
......................................................
|
448 |
+
Uize.Array.Sort.sortBy (names,'value.toLowerCase ()');
|
449 |
+
......................................................
|
450 |
+
|
451 |
+
In this example, when the elements of the =names= array are sorted according to the lower case, generated sort values, the elements are effectively sorted in a case-insensitive manner, since all the letters of all the sort value strings are guaranteed to be lower case.
|
452 |
+
|
453 |
+
Sort Array of RGB Color Objects By Blackness, Blackest to Whitest
|
454 |
+
An array of objects representing RGB colors can be sorted according to their blackness, from blackest to whitest, by specifying a `Sort Value Generator Function` that calculates the distance of a color from black in three dimensional RGB color space.
|
455 |
+
|
456 |
+
EXAMPLE
|
457 |
+
.................................................................................
|
458 |
+
Uize.Array.Sort.sortBy (
|
459 |
+
rgbColorObjects,
|
460 |
+
function (rgb) {
|
461 |
+
return Math.sqrt (
|
462 |
+
Math.pow (Math.sqrt (Math.pow (rgb.red,2) + Math.pow (rgb.green,2)),2) +
|
463 |
+
Math.pow (rgb.blue,2)
|
464 |
+
);
|
465 |
+
}
|
466 |
+
);
|
467 |
+
.................................................................................
|
468 |
+
|
469 |
+
Each value of the =rgbColorObjects= array is an object containing =red=, =green=, and =blue= properties that indicate the values of the three RGB color channels for a color. A `Sort Value Generator Function` can calculate a color's distance from black in three dimensional RGB color space by simply treating the color channels as dimensions like width, height, and depth.
|
470 |
+
|
471 |
+
Calculating distance in three dimensional space involves two successive hypotenuse-of-a-triangle calculations (square root of the sum of the squares) - the first calculates a distance in two of the three dimensions, and the second uses the first distance as one of the sides of a right angled triangle to calculate the final distance in three dimensional space. Our calculation in the `Sort Value Generator Function` is made simpler by the fact that our reference color is black, which is represented by zeros for each of the color channels, so there is no delta calculation needed for each of the color channels.
|
472 |
+
|
473 |
+
Randomly Shuffle the Elements in an Array
|
474 |
+
The order of the elements in an array can be randomly shuffled, by specifying a `Sort Value Generator Function` that generates a random number.
|
475 |
+
|
476 |
+
EXAMPLE
|
477 |
+
..............................................
|
478 |
+
Uize.Array.Sort.sortBy (elements,Math.random);
|
479 |
+
..............................................
|
480 |
+
|
481 |
+
Randomly shuffling the order of elements in an array is not influenced by the values of the elements, nor is this process influenced by the original order of the elements, so we use neither the =value= nor the =key= variable in our expression. Instead, we simply supply a `Sort Value Generator Function` that doesn't expect any input parameters and that always returns a random number. The =Math.random= method of JavaScript's built-in =Math= object fits the bill. Sorting the array using a set of randomly generated sort values has the effect of randomly shuffling the order of the elements in the array.
|
482 |
+
|
483 |
+
While the above technique works, it's worth noting that a better performing way of shuffling the elements of an array is to use the =Uize.Array.Order.jumble= static method of the =Uize.Array.Order= module.
|
484 |
+
|
485 |
+
Reverse the Elements in an Array
|
486 |
+
The order of the elements in an array can be reversed, by specifying a `Sort Value Generator Expression` that subtracts the index for an element from the length of the array.
|
487 |
+
|
488 |
+
EXAMPLE
|
489 |
+
.............................................................
|
490 |
+
Uize.Array.Sort.sortBy (elements,elements.length + ' - key');
|
491 |
+
.............................................................
|
492 |
+
|
493 |
+
Because we are using a `Sort Value Generator Expression` rather than a `Sort Value Generator Function` in our example, we can fix the array's length into the expression using string concatenation. Reversing the order of elements in an array is not influenced by the values of the elements, so we don't use the =value= variable in our expression. Instead, we use the =key= variable and subtract that from the array's length. This results in sort values that descend in value, starting from the length of the array for the first element, and ending with the value =1= for the last element. Sorting the array using these sort values has the effect of reversing the order of the elements.
|
494 |
+
|
495 |
+
While the above technique works, it's worth noting that a better performing way of reversing the order of the elements of an array is to use the =Uize.Array.Order.reverse= static method of the =Uize.Array.Order= module, or the =reverse= instance method of JavaScript's built-in =Array= object.
|
496 |
+
|
497 |
+
It should also be noted that the order of the elements in an array can be reversed by specifying the value =-1= for the =Uize.Array.Sort.sortBy= method's optional =directionINT= parameter, as follows...
|
498 |
+
|
499 |
+
...........................................
|
500 |
+
Uize.Array.Sort.sortBy (elements,'key',-1);
|
501 |
+
...........................................
|
502 |
+
|
503 |
+
When we use the =directionINT= parameter to reverse the sort direction, we no longer need to use the array's length in the `Sort Value Generator Expression`. Instead, we can have a simpler expression that simply returns the key / index.
|
504 |
+
*/
|
505 |
+
};
|
506 |
+
|
507 |
+
return _package;
|
508 |
+
}
|
509 |
+
});
|
510 |
+
|
skin/frontend/default/customproduct/js/Uize.Array.Util.js
ADDED
@@ -0,0 +1,206 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Array.Util Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2011-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 1
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 100
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Array.Util= module provides a number of miscellaneous utility methods for manipulating arrays.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
*/
|
26 |
+
|
27 |
+
Uize.module ({
|
28 |
+
name:'Uize.Array.Util',
|
29 |
+
builder:function () {
|
30 |
+
/*** Variables for Scruncher Optimization ***/
|
31 |
+
var
|
32 |
+
_package = function () {},
|
33 |
+
_undefined = undefined,
|
34 |
+
_ArrayPrototype = Array.prototype,
|
35 |
+
_ArrayPush = _ArrayPrototype.push,
|
36 |
+
_ArrayConcat = _ArrayPrototype.concat,
|
37 |
+
_ArraySplice = _ArrayPrototype.splice,
|
38 |
+
_Infinity = Infinity,
|
39 |
+
_fullArraySpliceArgs = [0,_Infinity]
|
40 |
+
;
|
41 |
+
|
42 |
+
/*** Public Static Methods ***/
|
43 |
+
_package.replaceContents = function (_array1,_array2) {
|
44 |
+
if (_array1 != _array2) {
|
45 |
+
_array1.length = 0;
|
46 |
+
_array2 && _array2.length && _ArrayPush.apply (_array1,_array2);
|
47 |
+
}
|
48 |
+
return _array1;
|
49 |
+
/*?
|
50 |
+
Static Methods
|
51 |
+
Uize.Array.Util.replaceContents
|
52 |
+
Replaces the contents of the first array with the contents of the second array, and returns a reference to the first array.
|
53 |
+
|
54 |
+
SYNTAX
|
55 |
+
........................................................................
|
56 |
+
array1ARRAY = Uize.Array.Util.replaceContents (array1ARRAY,array2ARRAY);
|
57 |
+
........................................................................
|
58 |
+
|
59 |
+
EXAMPLE
|
60 |
+
............................................................
|
61 |
+
var
|
62 |
+
foods = ['bacon','sausage','omelette'],
|
63 |
+
vegetables = ['potato','beans','mushrooms']
|
64 |
+
;
|
65 |
+
Uize.Array.Util.replaceContents (foods,vegetables);
|
66 |
+
alert (foods); // displays the text "potato,beans,mushrooms"
|
67 |
+
............................................................
|
68 |
+
|
69 |
+
In the above example, the contents of the =foods= array (which clearly contains some rather unhealthy food types) is being replaced with the contents of the healthier =vegetables= array. When the value of the =foods= array is then alerted, we see the text "potato,beans,mushrooms".
|
70 |
+
|
71 |
+
VARIATION
|
72 |
+
............................................................
|
73 |
+
array1ARRAY = Uize.Array.Util.replaceContents (array1ARRAY);
|
74 |
+
............................................................
|
75 |
+
|
76 |
+
When no =array2ARRAY= parameter is specified, or if the value =undefined= or =null= is specified for the =array2ARRAY= parameter, then the array specified by the =array1ARRAY= parameter will be emptied out.
|
77 |
+
|
78 |
+
NOTES
|
79 |
+
- see the related =Uize.Array.Util.swapContents= static method
|
80 |
+
*/
|
81 |
+
};
|
82 |
+
|
83 |
+
_package.swapContents = function (_array1,_array2) {
|
84 |
+
if (_array1 != _array2) {
|
85 |
+
_ArrayPush.apply (
|
86 |
+
_array1,
|
87 |
+
_ArraySplice.apply (_array2,_fullArraySpliceArgs.concat (_array1.splice (0,_Infinity)))
|
88 |
+
);
|
89 |
+
}
|
90 |
+
return _array1;
|
91 |
+
/*?
|
92 |
+
Static Methods
|
93 |
+
Uize.Array.Util.swapContents
|
94 |
+
Swaps the contents of the two specified arrays, and returns a reference to the first array.
|
95 |
+
|
96 |
+
SYNTAX
|
97 |
+
.....................................................................
|
98 |
+
array1ARRAY = Uize.Array.Util.swapContents (array1ARRAY,array2ARRAY);
|
99 |
+
.....................................................................
|
100 |
+
|
101 |
+
EXAMPLE
|
102 |
+
......................................................................
|
103 |
+
var
|
104 |
+
healthyFoods = ['bacon','sausage','omelette'],
|
105 |
+
unhealthyFoods = ['potato','beans','mushrooms']
|
106 |
+
;
|
107 |
+
Uize.Array.Util.swapContents (healthyFoods,unhealthyFoods);
|
108 |
+
alert (healthyFoods); // displays the text "potato,beans,mushrooms"
|
109 |
+
alert (unhealthyFoods); // displays the text "bacon,sausage,omelette"
|
110 |
+
......................................................................
|
111 |
+
|
112 |
+
In the above example, the contents of the =healthyFoods= and =unhealthyFoods= arrays are clearly mixed up. In order to correct this, the contents of the two arrays can be swapped. We can't just swap the variable references around, since other code may already have references to the arrays. What we really want to do is fix their contents. We can do this using the =Uize.Array.Util.swapContents= method.
|
113 |
+
|
114 |
+
NOTES
|
115 |
+
- see the related =Uize.Array.Util.replaceContents= static method
|
116 |
+
*/
|
117 |
+
};
|
118 |
+
|
119 |
+
_package.flatten = function (_sourceArray,_depth,_target) {
|
120 |
+
_depth = _depth == _undefined ? _Infinity : +_depth || 0;
|
121 |
+
var
|
122 |
+
_workingArray = _sourceArray,
|
123 |
+
_workingArrayPreviousLength,
|
124 |
+
_flattenedDepth = 0
|
125 |
+
;
|
126 |
+
while (_flattenedDepth++ < _depth && _workingArray.length != _workingArrayPreviousLength) {
|
127 |
+
_workingArrayPreviousLength = _workingArray.length;
|
128 |
+
_workingArray = _ArrayConcat.apply ([],_workingArray);
|
129 |
+
}
|
130 |
+
return (
|
131 |
+
_target !== true
|
132 |
+
? _package.replaceContents (_target || _sourceArray,_workingArray)
|
133 |
+
: _workingArray != _sourceArray
|
134 |
+
? _workingArray
|
135 |
+
: _sourceArray.concat ()
|
136 |
+
);
|
137 |
+
/*?
|
138 |
+
Static Methods
|
139 |
+
Uize.Array.Util.flatten
|
140 |
+
Flattens the elements of the specified source array and returns the flattened array.
|
141 |
+
|
142 |
+
SYNTAX
|
143 |
+
..................................................................................
|
144 |
+
flattenedARRAY = Uize.Array.Util.flatten (sourceARRAY,depthINT,targetARRAYorBOOL);
|
145 |
+
..................................................................................
|
146 |
+
|
147 |
+
VARIATION 1
|
148 |
+
................................................................
|
149 |
+
flattenedARRAY = Uize.Array.Util.flatten (sourceARRAY,depthINT);
|
150 |
+
................................................................
|
151 |
+
|
152 |
+
When the optional =depthINT= parameter is specified, then the depth level to which the source array should be flattened can be controlled. When the value =0= is specified for this parameter, the source array will remain unflattened. When the value =1= is specified, then this method will `flatten an array to one level deep`. When the value =2= is specified, then this method will `flatten an array to two levels deep`. When the =depthINT= parameter is not specified, then this method will `flatten an array to infinite depth`.
|
153 |
+
|
154 |
+
VARIATION 2
|
155 |
+
................................................................
|
156 |
+
flattenedARRAY = Uize.Array.Util.flatten (sourceARRAY,depthINT,targetARRAYorBOOL);
|
157 |
+
................................................................
|
158 |
+
|
159 |
+
When the optional =targetARRAYorBOOL= parameter is specified, then the target for the flattened contents of the source array can be controlled. When the value =true= is specified for the =targetARRAYorBOOL= parameter, then the target for the flattened contents of the source array will be a new array and the source array will not be modified. When the =false= is specified for the =targetARRAYorBOOL= parameter, then the flattened contents of the source array will replace the unflattened contents of the source array. When an array is specified for the =targetARRAYorBOOL= parameter, then the flattened contents of the source array will replace the contents of the specified target array.
|
160 |
+
|
161 |
+
Examples
|
162 |
+
Flatten an Array to One Level Deep
|
163 |
+
When the value =1= is specified for the optional =depthINT= parameter, then the source array will be flattened one level deep.
|
164 |
+
|
165 |
+
EXAMPLE
|
166 |
+
......................................................................
|
167 |
+
Uize.Array.Util.flatten ([0,[1,[2,[3,[4,[5,[6,6],5],4],3],2],1],0],1);
|
168 |
+
......................................................................
|
169 |
+
|
170 |
+
RESULT
|
171 |
+
.......................................
|
172 |
+
[0,1,[2,[3,[4,[5,[6,6],5],4],3],2],1,0]
|
173 |
+
.......................................
|
174 |
+
|
175 |
+
Flatten an Array to Two Levels Deep
|
176 |
+
When the value =2= is specified for the optional =depthINT= parameter, then the source array will be flattened one level deep.
|
177 |
+
|
178 |
+
EXAMPLE
|
179 |
+
......................................................................
|
180 |
+
Uize.Array.Util.flatten ([0,[1,[2,[3,[4,[5,[6,6],5],4],3],2],1],0],2);
|
181 |
+
......................................................................
|
182 |
+
|
183 |
+
RESULT
|
184 |
+
.....................................
|
185 |
+
[0,1,2,[3,[4,[5,[6,6],5],4],3],2,1,0]
|
186 |
+
.....................................
|
187 |
+
|
188 |
+
Flatten an Array to Infinite Depth
|
189 |
+
When the optional =depthINT= parameter is not specified, then the source array will be flattened to infinite depth (ie. until all elements are no longer arrays).
|
190 |
+
|
191 |
+
EXAMPLE
|
192 |
+
....................................................................
|
193 |
+
Uize.Array.Util.flatten ([0,[1,[2,[3,[4,[5,[6,6],5],4],3],2],1],0]);
|
194 |
+
....................................................................
|
195 |
+
|
196 |
+
RESULT
|
197 |
+
.............................
|
198 |
+
[0,1,2,3,4,5,6,6,5,4,3,2,1,0]
|
199 |
+
.............................
|
200 |
+
*/
|
201 |
+
};
|
202 |
+
|
203 |
+
return _package;
|
204 |
+
}
|
205 |
+
});
|
206 |
+
|
skin/frontend/default/customproduct/js/Uize.Array.js
ADDED
@@ -0,0 +1,28 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Array Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2010-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 4
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 100
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Array= module defines a namespace for various modules that provide array specific functionality or utilities.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
*/
|
26 |
+
|
27 |
+
Uize.module ({name:'Uize.Array'});
|
28 |
+
|
skin/frontend/default/customproduct/js/Uize.Build.All.js
ADDED
@@ -0,0 +1,68 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Build.All Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2010-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 7
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 2
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Build.All= module provides a method for running all the build scripts necessary for building the UIZE JavaScript Framework in the correct sequence.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
*/
|
26 |
+
|
27 |
+
Uize.module ({
|
28 |
+
name:'Uize.Build.All',
|
29 |
+
required:'Uize.Build.Util',
|
30 |
+
builder:function () {
|
31 |
+
var _package = function () {};
|
32 |
+
|
33 |
+
/*** Public Static Methods ***/
|
34 |
+
_package.perform = function (_params) {
|
35 |
+
var
|
36 |
+
_startTime = Uize.now (),
|
37 |
+
_buildSequence = _params.buildSequence,
|
38 |
+
_buildError
|
39 |
+
;
|
40 |
+
Uize.require (
|
41 |
+
_buildSequence,
|
42 |
+
function () {
|
43 |
+
Uize.forEach (
|
44 |
+
_buildSequence,
|
45 |
+
function (_buildModuleName) {
|
46 |
+
eval (_buildModuleName).perform (
|
47 |
+
Uize.copyInto ({},_params,{logFilePath:'logs/' + _buildModuleName + '.log'})
|
48 |
+
);
|
49 |
+
}
|
50 |
+
);
|
51 |
+
if (_params.test == 'true')
|
52 |
+
_buildError = Uize.Build.Util.runScripts (_params.testSequence)
|
53 |
+
;
|
54 |
+
_params.silent == 'true' ||
|
55 |
+
alert (
|
56 |
+
_buildError
|
57 |
+
? ('BUILD FAILED IN THE FOLLOWING SCRIPT:\n\n' + _buildError.script)
|
58 |
+
: 'BUILD ALL COMPLETE!!! (duration: ' + Math.round ((Uize.now () - _startTime) / 1000) + 's)'
|
59 |
+
)
|
60 |
+
;
|
61 |
+
}
|
62 |
+
);
|
63 |
+
};
|
64 |
+
|
65 |
+
return _package;
|
66 |
+
}
|
67 |
+
});
|
68 |
+
|
skin/frontend/default/customproduct/js/Uize.Build.AuditStrings.js
ADDED
@@ -0,0 +1,215 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Build.AuditStrings Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2009-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 1
|
15 |
+
codeCompleteness: 90
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 5
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Build.AuditStrings= package provides a method to audit all JavaScript files in a folder for literal strings - useful for internationalization.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
The =Uize.Build.AuditStrings= module is designed specifically to run in the context of Windows Script Host.
|
27 |
+
*/
|
28 |
+
|
29 |
+
/*
|
30 |
+
TO DO:
|
31 |
+
What's still being missed that should be recognized as non-internationalizable...
|
32 |
+
250x155 - width x height in pixels
|
33 |
+
|
34 |
+
imageTextSpacingX - not being recognized as camelCase identifier because last capital is not followed by any lowercase characters
|
35 |
+
|
36 |
+
disableGSDProducts, fixedPPI - consecutive caps
|
37 |
+
|
38 |
+
& - any single entity should be filtered out
|
39 |
+
|
40 |
+
<zz:error_image_src> - just a tag, without contents should be detectable (open or close tags)
|
41 |
+
</tr><tr> - catch one or more just tags in a row (eg. <br/><br/><br/>)
|
42 |
+
|
43 |
+
Content-length, Content-type - specific HTTP headers
|
44 |
+
|
45 |
+
-1000px - /^(-?\d+)?px$/
|
46 |
+
|
47 |
+
womens_laceup_heel_womens5.5 - it looks like an identifier with underscores, but there's a period
|
48 |
+
|
49 |
+
sz500 - a word with multiple digits
|
50 |
+
|
51 |
+
top= - fragments of code (how to identify them?)
|
52 |
+
|
53 |
+
-jiggler - hyphen starts a word
|
54 |
+
|
55 |
+
pd - two or more adjacent letters with no vowels (lowercase or uppercase)
|
56 |
+
|
57 |
+
- ff00ff - six letter hex format strings should be filtered to LIKELY NON-INTERNATIONALIZABLE STRINGS
|
58 |
+
|
59 |
+
- miscellaneous
|
60 |
+
price?input=js&output=js
|
61 |
+
MultiProductFactory_form-designData
|
62 |
+
?private=true
|
63 |
+
&end=
|
64 |
+
create/
|
65 |
+
icon_medium icon_medium-
|
66 |
+
.value
|
67 |
+
_ctgy_in.value
|
68 |
+
window.parent.parent.document.frmParms.mat
|
69 |
+
resizable=yes,status=no,scrollbars=yes,location=no,toolbar=no,directories=no,menubar=no,width=470,innerWidth=470,height=400,innerHeight=400
|
70 |
+
|
71 |
+
- switches
|
72 |
+
- a switch for levels of doubt
|
73 |
+
1: show only LIKELY INTERNATIONALIZABLE STRINGS
|
74 |
+
2: show LIKELY INTERNATIONALIZABLE STRINGS, POSSIBLY INTERNATIONALIZABLE STRINGS
|
75 |
+
3: show LIKELY INTERNATIONALIZABLE STRINGS, POSSIBLY INTERNATIONALIZABLE STRINGS, LIKELY NON-INTERNATIONALIZABLE STRINGS
|
76 |
+
4: show LIKELY INTERNATIONALIZABLE STRINGS, POSSIBLY INTERNATIONALIZABLE STRINGS, LIKELY NON-INTERNATIONALIZABLE STRINGS, NON-INTERNATIONALIZABLE STRINGS
|
77 |
+
- a switch for not showing headings for empty buckets
|
78 |
+
- a switch for not showing files for which all buckets that would be displayed are empty
|
79 |
+
|
80 |
+
- summary for overal totals for all buckets, per file, and for all files
|
81 |
+
- ability to supply additional dictionaries of known non-internationalizable strings and likely non-internationalizable strings, and regular expressions as well
|
82 |
+
- idea: summary for cases where creating a variable for a string that is repeatedly used would save some space when the file is scrunched
|
83 |
+
*/
|
84 |
+
|
85 |
+
Uize.module ({
|
86 |
+
name:'Uize.Build.AuditStrings',
|
87 |
+
required:[
|
88 |
+
'Uize.Build.Util',
|
89 |
+
'Uize.Build.Scruncher',
|
90 |
+
'Uize.String'
|
91 |
+
],
|
92 |
+
builder:function () {
|
93 |
+
/*** Variables for Scruncher Optimization ***/
|
94 |
+
var _package = function () {};
|
95 |
+
|
96 |
+
/*** General Variables ***/
|
97 |
+
var
|
98 |
+
_eventNames = [
|
99 |
+
'abort', 'activate', 'afterupdate', 'beforedeactivate', 'beforeeditfocus', 'beforeupdate', 'blur', 'cellchange', 'change', 'click', 'dblclick', 'deactivate', 'drag', 'dragend', 'dragenter', 'dragleave', 'dragover', 'drop', 'error', 'finish', 'focus', 'help', 'keydown', 'keypress', 'keyup', 'load', 'losecapture', 'mousedown', 'mousemove', 'mouseup', 'mouseout', 'mouseover', 'propertychange', 'readystatechange', 'rowenter', 'rowexit', 'rowsdelete', 'rowsinserted', 'scroll', 'submit', 'start', 'unload'
|
100 |
+
],
|
101 |
+
_nonI18nStringsDictionary = [
|
102 |
+
/*** pretty JavaScript-specific value types ***/
|
103 |
+
'function', 'object', 'string', 'undefined', // maybe these should be in a likely list?
|
104 |
+
|
105 |
+
/*** properties/attributes that are distinctive enough ***/
|
106 |
+
'alt', 'href', 'src',
|
107 |
+
|
108 |
+
/*** JavaScript-specific acronyms ***/
|
109 |
+
'ajax', 'json', 'CSS1Compat',
|
110 |
+
|
111 |
+
/*** HTML tag names that are distinctive enough ***/
|
112 |
+
'div', 'DIV', 'hr', 'HR', 'iframe', 'IFRAME', 'img', 'IMG', 'li', 'LI', 'ol', 'OL', 'span', 'SPAN', 'td', 'TD', 'textarea', 'TEXTAREA', 'tr', 'TR', 'ul', 'UL',
|
113 |
+
|
114 |
+
/*** file extensions ***/
|
115 |
+
'.asp', '.ASP', '.gif', '.html', '.jpg', '.js', '.jst', '.png', '.PNG', '.txt', '.xhtml', '.xml' // this could be in a regular expression, with leading period optional, and case insensitive, perhaps it would be good to add a filename match, to catch things like, filename.gif, .gif, and gif (ie. patterns like [[filename].]gif|jpg|html)
|
116 |
+
].concat (
|
117 |
+
_eventNames,
|
118 |
+
Uize.map (_eventNames,'\'on\' + value')
|
119 |
+
),
|
120 |
+
_nonI18nStringsDictionaryLookup
|
121 |
+
;
|
122 |
+
|
123 |
+
/*** Public Static Methods ***/
|
124 |
+
_package.perform = function (_params) {
|
125 |
+
var
|
126 |
+
_endsWithDotJsRegExp = /\.js$/,
|
127 |
+
_sourceFolderName = _params.sourceFolderName
|
128 |
+
;
|
129 |
+
if (!_nonI18nStringsDictionaryLookup)
|
130 |
+
_nonI18nStringsDictionaryLookup = Uize.lookup (_nonI18nStringsDictionary)
|
131 |
+
;
|
132 |
+
Uize.Build.Util.buildFiles (
|
133 |
+
Uize.copyInto (
|
134 |
+
{
|
135 |
+
targetFolderPathCreator:function (_folderPath) {
|
136 |
+
return Uize.String.endsWith (_folderPath,_sourceFolderName) ? _folderPath : null;
|
137 |
+
},
|
138 |
+
targetFilenameCreator:function (_sourceFileName) {
|
139 |
+
return _endsWithDotJsRegExp.test (_sourceFileName) ? _sourceFileName : null;
|
140 |
+
},
|
141 |
+
fileBuilder:function (_sourceFileName,_sourceFileText) {
|
142 |
+
var
|
143 |
+
_scruncherResult = Uize.Build.Scruncher.scrunch (_sourceFileText,{AUDITSTRINGS:true}),
|
144 |
+
_stringsMap = _scruncherResult.stringsMap,
|
145 |
+
_strings = Uize.keys (_stringsMap),
|
146 |
+
_nonI18nStrings = [],
|
147 |
+
_likelyNonI18nStrings = [],
|
148 |
+
_possibleI18nStrings = [],
|
149 |
+
_likelyI18nStrings = []
|
150 |
+
;
|
151 |
+
_strings.sort ();
|
152 |
+
for (var _stringNo = -1, _stringsLength = _strings.length; ++_stringNo < _stringsLength;) {
|
153 |
+
var _string = _strings [_stringNo];
|
154 |
+
(
|
155 |
+
_nonI18nStringsDictionaryLookup [_string] ||
|
156 |
+
// ignore strings that are recognized as non-internationalizable strings
|
157 |
+
!/\S/.test (_string) ||
|
158 |
+
// ignore strings that are only whitespace (spaces, tabs, linebreaks, etc.)
|
159 |
+
!/[a-zA-Z]/.test (_string) ||
|
160 |
+
// ignore strings that have no letter characters
|
161 |
+
/^(#|0x)([0-9a-fA-F]{3}){1,2}$/.test (_string) ||
|
162 |
+
// ignore hex RGB color values
|
163 |
+
/^[A-Z][a-zA-Z0-9$_]*(\.[a-zA-Z0-9$_]+)+$/.test (_string) ||
|
164 |
+
// ignore what look like module names
|
165 |
+
/^Uize/i.test (_string) ||
|
166 |
+
// if it starts with "Uize", it's related to the framework
|
167 |
+
/^[a-zA-Z0-9$_]*_[a-zA-Z0-9$_]*$/.test (_string) ||
|
168 |
+
// ignore what look like underscore delimited identifiers
|
169 |
+
/^Changed\.(\*|[a-zA-Z0-1]+)$/.test (_string) ||
|
170 |
+
// ignore Changed.[propertyName] events
|
171 |
+
/^\S*[\/\\][\w_]+[\/\\]\S*$/.test (_string) ||
|
172 |
+
// ignore what look like URL paths
|
173 |
+
/^\$?[a-zA-Z][a-z0-9]*([A-Z][a-z0-9]+)+$/.test (_string)
|
174 |
+
// ignore what look obviously like camelCase identifiers
|
175 |
+
/* TO DO: catch strings that are only numbers */
|
176 |
+
? _nonI18nStrings
|
177 |
+
: (
|
178 |
+
/[a-zA-Z]{2,}/.test (_string) &&
|
179 |
+
// string must have at least two consecutive word characters
|
180 |
+
!/^\S*[\w_]+[\/\\][\w_]+\S*$/.test (_string)
|
181 |
+
// ignore what could be short URL snippets
|
182 |
+
? (
|
183 |
+
/\b[a-zA-Z][a-z]*\s[a-z]+\s[a-zA-Z][a-z]*\b/.test (_string)
|
184 |
+
? _likelyI18nStrings
|
185 |
+
: _possibleI18nStrings
|
186 |
+
) : _likelyNonI18nStrings
|
187 |
+
)
|
188 |
+
).push (_string + ' --- ' + _stringsMap [_string]);
|
189 |
+
}
|
190 |
+
return {
|
191 |
+
logDetails:
|
192 |
+
'\t\tNON-INTERNATIONALIZABLE STRINGS\n' +
|
193 |
+
Uize.String.hugJoin (_nonI18nStrings,'\t\t\t','\n') + '\n' +
|
194 |
+
'\t\tLIKELY NON-INTERNATIONALIZABLE STRINGS\n' +
|
195 |
+
Uize.String.hugJoin (_likelyNonI18nStrings,'\t\t\t','\n') + '\n' +
|
196 |
+
'\t\tPOSSIBLY INTERNATIONALIZABLE STRINGS\n' +
|
197 |
+
Uize.String.hugJoin (_possibleI18nStrings,'\t\t\t','\n') + '\n' +
|
198 |
+
'\t\tLIKELY INTERNATIONALIZABLE STRINGS\n' +
|
199 |
+
Uize.String.hugJoin (_likelyI18nStrings,'\t\t\t','\n')
|
200 |
+
};
|
201 |
+
}
|
202 |
+
},
|
203 |
+
_params,
|
204 |
+
{
|
205 |
+
alwaysBuild:true,
|
206 |
+
dryRun:true
|
207 |
+
}
|
208 |
+
)
|
209 |
+
);
|
210 |
+
};
|
211 |
+
|
212 |
+
return _package;
|
213 |
+
}
|
214 |
+
});
|
215 |
+
|
skin/frontend/default/customproduct/js/Uize.Build.AutoScruncher.js
ADDED
@@ -0,0 +1,217 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Build.AutoScruncher Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2005-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 8
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 2
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Build.AutoScruncher= package provides a method to recurse a folder structure and scrunch (minify / compress) and obfuscate JavaScript source.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
The =Uize.Build.AutoScruncher= module is designed specifically to run in the context of Windows Script Host.
|
27 |
+
*/
|
28 |
+
|
29 |
+
Uize.module ({
|
30 |
+
name:'Uize.Build.AutoScruncher',
|
31 |
+
required:[
|
32 |
+
'Uize.Wsh',
|
33 |
+
'Uize.Build.Util',
|
34 |
+
'Uize.Build.Scruncher',
|
35 |
+
'Uize.Date',
|
36 |
+
'Uize.String',
|
37 |
+
'Uize.String.Lines',
|
38 |
+
'Uize.Util.Oop'
|
39 |
+
],
|
40 |
+
builder:function () {
|
41 |
+
/*** Variables for Scruncher Optimization ***/
|
42 |
+
var _package = function () {};
|
43 |
+
|
44 |
+
/*** Public Static Methods ***/
|
45 |
+
_package.perform = function (_params) {
|
46 |
+
var
|
47 |
+
_buildDate = Uize.Date.toIso8601 (),
|
48 |
+
_endsWithDotJsRegExp = /\.js$/,
|
49 |
+
_buildScriptName = WScript.ScriptName,
|
50 |
+
_scrunchedHeadComments = _params.scrunchedHeadComments || {},
|
51 |
+
_scruncherPrefixChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ',
|
52 |
+
_currentFolderPath,
|
53 |
+
_buildFolderPath = _params.buildFolderPath,
|
54 |
+
_sourceFolderName = _params.sourceFolderName,
|
55 |
+
_rootPath = Uize.Wsh.getScriptFolderPath (),
|
56 |
+
_fullModuleFolderPath = _rootPath + '\\' + _params.moduleFolderPath
|
57 |
+
;
|
58 |
+
function _targetFolderPathCreator (_folderPath) {
|
59 |
+
var _sourceFolderNameLength = _sourceFolderName ? _sourceFolderName.length : 0;
|
60 |
+
return (
|
61 |
+
_sourceFolderNameLength
|
62 |
+
? (
|
63 |
+
_folderPath.slice (-_sourceFolderNameLength) == _sourceFolderName
|
64 |
+
? _folderPath.slice (0,-_sourceFolderNameLength - 1)
|
65 |
+
: null
|
66 |
+
)
|
67 |
+
: _buildFolderPath && _rootPath + '/' + _buildFolderPath + _folderPath.substr (_rootPath.length)
|
68 |
+
);
|
69 |
+
}
|
70 |
+
|
71 |
+
/*** scrunch eligible JavaScript files ***/
|
72 |
+
Uize.Wsh.buildFiles (
|
73 |
+
Uize.copyInto (
|
74 |
+
{
|
75 |
+
logFilePath:_buildScriptName.replace (_endsWithDotJsRegExp,'-js-files.log'),
|
76 |
+
targetFolderPathCreator:_targetFolderPathCreator,
|
77 |
+
targetFilenameCreator:function (_sourceFileName) {
|
78 |
+
return _endsWithDotJsRegExp.test (_sourceFileName) ? _sourceFileName : null;
|
79 |
+
},
|
80 |
+
fileBuilder:function (_sourceFileName,_sourceFileText) {
|
81 |
+
var
|
82 |
+
_moduleName = _sourceFileName.replace (_endsWithDotJsRegExp,''),
|
83 |
+
_scruncherSettings = {},
|
84 |
+
_headComment =
|
85 |
+
_scrunchedHeadComments [_sourceFileName.slice (0,_sourceFileName.indexOf ('.'))],
|
86 |
+
_keepHeadComment = _headComment == undefined
|
87 |
+
;
|
88 |
+
if (!_keepHeadComment)
|
89 |
+
_scruncherSettings.KEEPHEADCOMMENT = 'FALSE'
|
90 |
+
;
|
91 |
+
if (_currentFolderPath == _fullModuleFolderPath)
|
92 |
+
Uize.require (
|
93 |
+
_moduleName,
|
94 |
+
function (_module) {
|
95 |
+
var _inheritanceDepth = Uize.Util.Oop.getInheritanceChain (_module).length;
|
96 |
+
_scruncherSettings.MAPPINGS =
|
97 |
+
'=' +
|
98 |
+
(_inheritanceDepth ? _scruncherPrefixChars.charAt (_inheritanceDepth - 1) : '') +
|
99 |
+
',' + _moduleName.replace (/\./g,'_')
|
100 |
+
;
|
101 |
+
}
|
102 |
+
)
|
103 |
+
;
|
104 |
+
var _scruncherResult = Uize.Build.Scruncher.scrunch (_sourceFileText,_scruncherSettings);
|
105 |
+
return {
|
106 |
+
outputText:
|
107 |
+
(
|
108 |
+
_keepHeadComment
|
109 |
+
? ''
|
110 |
+
: Uize.substituteInto (
|
111 |
+
_headComment,
|
112 |
+
{buildDate:_buildDate,moduleName:_moduleName},
|
113 |
+
'{KEY}'
|
114 |
+
)
|
115 |
+
) + _scruncherResult.scrunchedCode,
|
116 |
+
logDetails:Uize.String.Lines.indent (_scruncherResult.report,2) + '\n'
|
117 |
+
};
|
118 |
+
}
|
119 |
+
},
|
120 |
+
_params
|
121 |
+
)
|
122 |
+
);
|
123 |
+
|
124 |
+
/*** build .library.js files ***/
|
125 |
+
var
|
126 |
+
_contentsCommentRegExp = /\/\*\s*Library\s*Contents/i,
|
127 |
+
_lineStartsWithIdentifierCharRegExp = /^[a-zA-Z_$]/,
|
128 |
+
_scrunchedModuleFolderPath = _targetFolderPathCreator (_fullModuleFolderPath),
|
129 |
+
_libraryUsesUizeModulesHeader =
|
130 |
+
'/*______________\n' +
|
131 |
+
'| ______ | B U I L T O N U I Z E F R A M E W O R K\n' +
|
132 |
+
'| / / | ---------------------------------------------------\n' +
|
133 |
+
'| / O / | This JavaScript application is developed using the object\n' +
|
134 |
+
'| / / / | oriented UIZE JavaScript framework as its foundation.\n' +
|
135 |
+
'| / / / /| |\n' +
|
136 |
+
'| /____/ /__/_| | ONLINE : http://www.uize.com\n' +
|
137 |
+
'| /___ | LICENSE : Available under MIT License or GNU General Public License\n' +
|
138 |
+
'|_______________| http://www.uize.com/license.html\n' +
|
139 |
+
'*/\n\n'
|
140 |
+
;
|
141 |
+
Uize.Wsh.buildFiles (
|
142 |
+
Uize.copyInto (
|
143 |
+
{
|
144 |
+
targetFolderPathCreator:_targetFolderPathCreator,
|
145 |
+
targetFilenameCreator:function (_sourceFileName) {
|
146 |
+
return /\.library.js$/.test (_sourceFileName) ? _sourceFileName : null;
|
147 |
+
},
|
148 |
+
fileBuilder:function (_sourceFileName,_sourceFileText) {
|
149 |
+
function _stripModuleHeaderComment (_moduleText) {
|
150 |
+
var _moduleHeaderCommentPos = _moduleText.indexOf ('/*');
|
151 |
+
return (
|
152 |
+
_moduleHeaderCommentPos > -1
|
153 |
+
? (
|
154 |
+
_moduleText.slice (0,_moduleHeaderCommentPos) +
|
155 |
+
_moduleText.slice (_moduleText.indexOf ('*/',_moduleHeaderCommentPos + 2) + 2)
|
156 |
+
)
|
157 |
+
: _moduleText
|
158 |
+
);
|
159 |
+
}
|
160 |
+
var
|
161 |
+
_libraryContentsChunks = [],
|
162 |
+
_libraryUsesUizeModules
|
163 |
+
;
|
164 |
+
for (
|
165 |
+
var
|
166 |
+
_moduleNo = -1,
|
167 |
+
_contentsCommentStartPos = _sourceFileText.search (_contentsCommentRegExp),
|
168 |
+
_contentsCommentEndPos = _sourceFileText.indexOf ('*/',_contentsCommentStartPos),
|
169 |
+
_modules = Uize.String.Lines.split (
|
170 |
+
_contentsCommentStartPos > -1
|
171 |
+
?
|
172 |
+
_sourceFileText.slice (_contentsCommentStartPos,_contentsCommentEndPos)
|
173 |
+
.replace (_contentsCommentRegExp,'')
|
174 |
+
: _sourceFileText
|
175 |
+
),
|
176 |
+
_modulesLength = _modules.length
|
177 |
+
;
|
178 |
+
++_moduleNo < _modulesLength;
|
179 |
+
) {
|
180 |
+
var _moduleName = Uize.String.trim (_modules [_moduleNo]);
|
181 |
+
if (_moduleName && _lineStartsWithIdentifierCharRegExp.test (_moduleName)) {
|
182 |
+
if (!_libraryUsesUizeModules)
|
183 |
+
_libraryUsesUizeModules = Uize.String.startsWith (_moduleName,'Uize')
|
184 |
+
;
|
185 |
+
_libraryContentsChunks.push (
|
186 |
+
'\n' +
|
187 |
+
_stripModuleHeaderComment (
|
188 |
+
Uize.Wsh.readFile (
|
189 |
+
_scrunchedModuleFolderPath + '\\' + _moduleName +
|
190 |
+
(_endsWithDotJsRegExp.test (_moduleName) ? '' : '.js')
|
191 |
+
)
|
192 |
+
)
|
193 |
+
);
|
194 |
+
}
|
195 |
+
}
|
196 |
+
return {
|
197 |
+
outputText:
|
198 |
+
(_libraryUsesUizeModules ? _libraryUsesUizeModulesHeader : '') +
|
199 |
+
_sourceFileText.slice (0,_contentsCommentStartPos) +
|
200 |
+
_libraryContentsChunks.join ('\n') +
|
201 |
+
_sourceFileText.slice (_contentsCommentEndPos + 2)
|
202 |
+
};
|
203 |
+
}
|
204 |
+
},
|
205 |
+
_params,
|
206 |
+
{
|
207 |
+
alwaysBuild:true,
|
208 |
+
logFilePath:_buildScriptName.replace (_endsWithDotJsRegExp,'-libraries.log')
|
209 |
+
}
|
210 |
+
)
|
211 |
+
);
|
212 |
+
};
|
213 |
+
|
214 |
+
return _package;
|
215 |
+
}
|
216 |
+
});
|
217 |
+
|
skin/frontend/default/customproduct/js/Uize.Build.ModuleInfo.js
ADDED
@@ -0,0 +1,104 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Build.ModuleInfo Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 2
|
15 |
+
codeCompleteness: 0
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 0
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Build.ModuleInfo= module provides various methods for obtaining information about modules JavaScript modules.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
*/
|
26 |
+
|
27 |
+
Uize.module ({
|
28 |
+
name:'Uize.Build.ModuleInfo',
|
29 |
+
required:'Uize.Services.FileSystem',
|
30 |
+
builder:function () {
|
31 |
+
/*** Variables for Scruncher Optimization ***/
|
32 |
+
var
|
33 |
+
_package = function () {},
|
34 |
+
_true = true,
|
35 |
+
_false = false,
|
36 |
+
_undefined,
|
37 |
+
_trueFlagValue = {},
|
38 |
+
_forEach = Uize.forEach
|
39 |
+
;
|
40 |
+
|
41 |
+
/*** General Variables ***/
|
42 |
+
var _fileSystem = Uize.Services.FileSystem.singleton ();
|
43 |
+
|
44 |
+
/*** Public Static Methods ***/
|
45 |
+
_package.getDefinitionFromCode = function (_moduleCode) {
|
46 |
+
var
|
47 |
+
_result,
|
48 |
+
Uize = {module: function (_definition) {_result = _definition}}
|
49 |
+
;
|
50 |
+
eval (_moduleCode);
|
51 |
+
return _result;
|
52 |
+
};
|
53 |
+
|
54 |
+
_package.getDefinition = function (_moduleName) {
|
55 |
+
var _definition = {name:_moduleName};
|
56 |
+
if (_moduleName != 'Uize') {
|
57 |
+
try {
|
58 |
+
Uize.moduleLoader (
|
59 |
+
_moduleName,
|
60 |
+
function (_moduleText) {_definition = _package.getDefinitionFromCode (_moduleText)}
|
61 |
+
);
|
62 |
+
} catch (_error) {
|
63 |
+
// if a module cannot be loaded because it is missing, ignore it
|
64 |
+
}
|
65 |
+
}
|
66 |
+
return _definition;
|
67 |
+
};
|
68 |
+
|
69 |
+
var _getDirectDependencies = _package.getDirectDependencies = function (_moduleName) {
|
70 |
+
var _definition = _package.getDefinition (_moduleName);
|
71 |
+
return _definition ? Uize.resolveModuleDefinition (_definition).required : [];
|
72 |
+
};
|
73 |
+
|
74 |
+
_package.traceDependencies = function (_modules,_excludeModules) {
|
75 |
+
var
|
76 |
+
_excludeModulesLookup = {},
|
77 |
+
_modulesNeeded = []
|
78 |
+
;
|
79 |
+
_forEach (
|
80 |
+
_excludeModules,
|
81 |
+
function (_excludeModule) {_excludeModulesLookup [_excludeModule] = _trueFlagValue}
|
82 |
+
);
|
83 |
+
|
84 |
+
function _traceDependencies (_modules) {
|
85 |
+
_forEach (
|
86 |
+
_modules.sort (),
|
87 |
+
function (_moduleName) {
|
88 |
+
if (_excludeModulesLookup [_moduleName] != _trueFlagValue) {
|
89 |
+
_excludeModulesLookup [_moduleName] = _trueFlagValue;
|
90 |
+
_traceDependencies (_getDirectDependencies (_moduleName));
|
91 |
+
_modulesNeeded.push (_moduleName);
|
92 |
+
}
|
93 |
+
}
|
94 |
+
);
|
95 |
+
}
|
96 |
+
_traceDependencies (['Uize'].concat (typeof _modules == 'string' ? [_modules] : _modules));
|
97 |
+
|
98 |
+
return _modulesNeeded;
|
99 |
+
};
|
100 |
+
|
101 |
+
return _package;
|
102 |
+
}
|
103 |
+
});
|
104 |
+
|
skin/frontend/default/customproduct/js/Uize.Build.NeatenJsFiles.js
ADDED
@@ -0,0 +1,74 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Build.NeatenJsFiles Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2010-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 1
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 4
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Build.NeatenJsFiles= package provides a way to recurse folder structures and neaten all JavaScript (.js) files by removing unnecessary trailing whitespace.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
The =Uize.Build.NeatenJsFiles= module is designed specifically to run in the context of Windows Script Host.
|
27 |
+
*/
|
28 |
+
|
29 |
+
Uize.module ({
|
30 |
+
name:'Uize.Build.NeatenJsFiles',
|
31 |
+
required:[
|
32 |
+
'Uize.Build.Util',
|
33 |
+
'Uize.String.Lines',
|
34 |
+
'Uize.Build.AutoScruncher'
|
35 |
+
],
|
36 |
+
builder:function () {
|
37 |
+
/*** Variables for Scruncher Optimization ***/
|
38 |
+
var _package = function () {};
|
39 |
+
|
40 |
+
/*** Public Static Methods ***/
|
41 |
+
_package.perform = function (_params) {
|
42 |
+
Uize.Build.Util.buildFiles (
|
43 |
+
Uize.copyInto (
|
44 |
+
{
|
45 |
+
targetFolderPathCreator:function (_folderPath) {
|
46 |
+
return _folderPath;
|
47 |
+
},
|
48 |
+
targetFilenameCreator:function (_sourceFileName) {
|
49 |
+
return /\.js$/.test (_sourceFileName) ? _sourceFileName : null;
|
50 |
+
},
|
51 |
+
fileBuilder:function (_sourceFileName,_sourceFileText) {
|
52 |
+
var _neatenedSourceFileText = Uize.String.Lines.trimRight (_sourceFileText);
|
53 |
+
return (
|
54 |
+
_neatenedSourceFileText != _sourceFileText
|
55 |
+
? {
|
56 |
+
outputText:_neatenedSourceFileText,
|
57 |
+
logDetails:
|
58 |
+
'\t\tTrailing Whitespace Characters Removed: ' +
|
59 |
+
(_sourceFileText.length - _neatenedSourceFileText.length) + '\n'
|
60 |
+
}
|
61 |
+
: {logDetails:'\t\tFILE ALREADY OK\n'}
|
62 |
+
);
|
63 |
+
}
|
64 |
+
},
|
65 |
+
_params,
|
66 |
+
{alwaysBuild:true}
|
67 |
+
)
|
68 |
+
);
|
69 |
+
};
|
70 |
+
|
71 |
+
return _package;
|
72 |
+
}
|
73 |
+
});
|
74 |
+
|
skin/frontend/default/customproduct/js/Uize.Build.RunUnitTest.js
ADDED
@@ -0,0 +1,41 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Build.RunUnitTest Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 1
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 2
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Build.RunUnitTest= module provides a method for testing a specified JavaScript module.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
*/
|
26 |
+
|
27 |
+
Uize.module ({
|
28 |
+
name:'Uize.Build.RunUnitTest',
|
29 |
+
required:'Uize.Build.Util',
|
30 |
+
builder:function () {
|
31 |
+
var _package = function () {};
|
32 |
+
|
33 |
+
/*** Public Static Methods ***/
|
34 |
+
_package.perform = function (_params) {
|
35 |
+
Uize.Build.Util.runUnitTests (_params.testModule,_params.silent == 'true');
|
36 |
+
};
|
37 |
+
|
38 |
+
return _package;
|
39 |
+
}
|
40 |
+
});
|
41 |
+
|
skin/frontend/default/customproduct/js/Uize.Build.RunUnitTests.js
ADDED
@@ -0,0 +1,89 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Build.RunUnitTests Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2010-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 3
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 2
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Build.RunUnitTests= module provides a method for testing all modules of the UIZE JavaScript Framework.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
*/
|
26 |
+
|
27 |
+
Uize.module ({
|
28 |
+
name:'Uize.Build.RunUnitTests',
|
29 |
+
required:[
|
30 |
+
'Uize.Services.FileSystem',
|
31 |
+
'Uize.Test',
|
32 |
+
'Uize.Build.Util',
|
33 |
+
'Uize.Build.ModuleInfo',
|
34 |
+
'Uize.Data.Matches'
|
35 |
+
],
|
36 |
+
builder:function () {
|
37 |
+
/*** Variables for Scruncher Optimization ***/
|
38 |
+
var _package = function () {};
|
39 |
+
|
40 |
+
/*** General Variables ***/
|
41 |
+
var _fileSystem = Uize.Services.FileSystem.singleton ();
|
42 |
+
|
43 |
+
/*** Public Static Methods ***/
|
44 |
+
_package.perform = function (_params) {
|
45 |
+
var
|
46 |
+
_dotJsRegExp = /\.js$/i,
|
47 |
+
_dotLibraryDotJsRegExp = /\.library\.js$/i,
|
48 |
+
_modules = _fileSystem.getFiles ({
|
49 |
+
path:_params.moduleFolderPath,
|
50 |
+
pathMatcher:function (_filePath) {
|
51 |
+
return _dotJsRegExp.test (_filePath) && !_dotLibraryDotJsRegExp.test (_filePath)
|
52 |
+
},
|
53 |
+
pathTransformer:function (_filePath) {
|
54 |
+
return Uize.Url.from (_filePath).fileName;
|
55 |
+
}
|
56 |
+
}).sort (),
|
57 |
+
_modulesLookup = Uize.lookup (_modules),
|
58 |
+
_correspondingTestModuleName,
|
59 |
+
_testModuleRegExp = /^[a-zA-Z_\$][a-zA-Z0-9_\$]*\.Test($|\.)/,
|
60 |
+
_modulesInDependencyOrder = Uize.Build.ModuleInfo.traceDependencies (
|
61 |
+
Uize.Data.Matches.values (
|
62 |
+
_modules,
|
63 |
+
function (_moduleName) {return !_testModuleRegExp.test (_moduleName)} // ignore test modules
|
64 |
+
)
|
65 |
+
),
|
66 |
+
_unitTestSuite = Uize.Test.declare ({
|
67 |
+
title:'Unit Tests Suite',
|
68 |
+
test:Uize.map (
|
69 |
+
_modulesInDependencyOrder,
|
70 |
+
function (_moduleName) {
|
71 |
+
return (
|
72 |
+
_modulesLookup [
|
73 |
+
_correspondingTestModuleName =
|
74 |
+
_moduleName.match (/([^\.]*)(\.|$)/) [1] + '.Test.' + _moduleName
|
75 |
+
]
|
76 |
+
? Uize.Test.testModuleTest (_correspondingTestModuleName)
|
77 |
+
: Uize.Test.requiredModulesTest (_moduleName)
|
78 |
+
);
|
79 |
+
}
|
80 |
+
)
|
81 |
+
})
|
82 |
+
;
|
83 |
+
Uize.Build.Util.runUnitTests (_unitTestSuite,_params.silent == 'true',_params.logFilePath);
|
84 |
+
};
|
85 |
+
|
86 |
+
return _package;
|
87 |
+
}
|
88 |
+
});
|
89 |
+
|
skin/frontend/default/customproduct/js/Uize.Build.Scruncher.js
ADDED
@@ -0,0 +1,515 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Build.Scruncher Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)1997-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 8
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Build.Scruncher= package provides a method for scrunching (compressing / minifying) JavaScript source code into compact / obfuscated scrunched code.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
*/
|
26 |
+
|
27 |
+
/* NOTES
|
28 |
+
- whitespace is regarded as being any continuous segment of tab and/or space characters
|
29 |
+
- for any amount of whitespace that is necessary for separating tokens, a single space will be substituted
|
30 |
+
- if whitespace is being used to separate identifiers and operators and is therefore not essential, it should be removed
|
31 |
+
- whitespace is considered necessary when it
|
32 |
+
- separates reserved words, identifiers, and literals
|
33 |
+
eg. function blah () {} BECOMES--> function blah(){}
|
34 |
+
- separates consecutive operators
|
35 |
+
eg. a += ++b; BECOMES--> a+= ++b;
|
36 |
+
- whitespace is considered unnecessary when it
|
37 |
+
- occurs at the start of a line, before any non-whitespace characters
|
38 |
+
eg.
|
39 |
+
function blah () {
|
40 |
+
a++;
|
41 |
+
}
|
42 |
+
|
43 |
+
BECOMES-->
|
44 |
+
|
45 |
+
function blah(){
|
46 |
+
a++;
|
47 |
+
}
|
48 |
+
|
49 |
+
- separates reserved words, identifiers, or literals from operators
|
50 |
+
eg. a += b; BECOMES--> a+=b;
|
51 |
+
- separates reserved words, identifiers, or literals from delimiters
|
52 |
+
eg. a += 2 * (b - 3) BECOMES--> a+=2*(b-3)
|
53 |
+
eg. myArray [5] BECOMES--> myArray[5]
|
54 |
+
eg. a++ ; BECOMES--> a++;
|
55 |
+
eg. myFunction ( 2 , 'hello' , 7 ); BECOMES--> myFunction(2,'hello',7);
|
56 |
+
- separates delimiters from each other
|
57 |
+
eg. myFunction () ; BECOMES--> myFunction();
|
58 |
+
eg. myArray1 [myArray2 [5] ] ; BECOMES--> myArray1[myArray2[5]];
|
59 |
+
- separates operators from delimiters
|
60 |
+
eg. a ++ ; BECOMES--> a++;
|
61 |
+
eg. myVariable += (myArray [a ++ ] - 5) ; BECOMES--> myVariable+=(myArray[a++]-5);
|
62 |
+
*/
|
63 |
+
|
64 |
+
Uize.module({
|
65 |
+
name:'Uize.Build.Scruncher',
|
66 |
+
required:[
|
67 |
+
'Uize.Xml',
|
68 |
+
'Uize.String'
|
69 |
+
],
|
70 |
+
builder:function () {
|
71 |
+
/*** Variables for Scruncher Optimization ***/
|
72 |
+
var
|
73 |
+
_package = function () {},
|
74 |
+
_true = true,
|
75 |
+
_false = false
|
76 |
+
;
|
77 |
+
|
78 |
+
/*** Utility Functions ***/
|
79 |
+
function _makeCharLookup (_charsStr,_lookupValue) {
|
80 |
+
return Uize.lookup (_charsStr.split (''),_lookupValue != null ? _lookupValue : _true);
|
81 |
+
}
|
82 |
+
|
83 |
+
/*** General Variables ***/
|
84 |
+
var
|
85 |
+
/*** token types ***/
|
86 |
+
_NONE = 0,
|
87 |
+
_WORD = 1,
|
88 |
+
_NUMBER = 2,
|
89 |
+
_DELIMITER = 3,
|
90 |
+
_STRINGLITERAL = 4,
|
91 |
+
_COMMENT = 5,
|
92 |
+
_OPERATOR = 6,
|
93 |
+
_LINEBREAK = 7,
|
94 |
+
|
95 |
+
/*** char lookups ***/
|
96 |
+
_operatorCharsLookup = _makeCharLookup ('+-*/%&|^~<>=!?:',_OPERATOR),
|
97 |
+
_delimiterCharsLookup = _makeCharLookup ('.,()[]{};',_DELIMITER),
|
98 |
+
_quoteCharsLookup = _makeCharLookup ('"\'',_STRINGLITERAL),
|
99 |
+
_linebreakCharsLookup = _makeCharLookup ('\n\r',_LINEBREAK),
|
100 |
+
_wordStarterCharsLookup = _makeCharLookup (
|
101 |
+
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$',
|
102 |
+
_WORD
|
103 |
+
),
|
104 |
+
_digitsLookup = _makeCharLookup ('0123456789',_NUMBER),
|
105 |
+
_numberCharsLookup = Uize.copyInto (_digitsLookup,{x:_NUMBER}),
|
106 |
+
_tokenStarterCharsLookup = Uize.copyInto (
|
107 |
+
{},
|
108 |
+
_linebreakCharsLookup,
|
109 |
+
_operatorCharsLookup,
|
110 |
+
_delimiterCharsLookup,
|
111 |
+
_quoteCharsLookup,
|
112 |
+
_numberCharsLookup,
|
113 |
+
_wordStarterCharsLookup
|
114 |
+
),
|
115 |
+
_wordCharsLookup = Uize.copyInto ({},_wordStarterCharsLookup,_numberCharsLookup),
|
116 |
+
_closeParenOrSquareBracketMap = _makeCharLookup (')]'),
|
117 |
+
|
118 |
+
_identifierChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.split (''),
|
119 |
+
_totalIdentifierChars = _identifierChars.length,
|
120 |
+
_invalidOperatorRegExp = /^(:|!+|\*|-|\+|\||\|\||&|&&|%|>|>>|<|<<|=|==|\?|\^)\/$/
|
121 |
+
/* EXAMPLES */
|
122 |
+
// object = {prop:/\w+/g}
|
123 |
+
// if (!/\w+/g.test (sourceStr)) {...}
|
124 |
+
// if (!!/\w+/g.test (sourceStr)) {...}
|
125 |
+
// 2*/\w+/g.test (sourceStr)
|
126 |
+
// 2-/\w+/g.test (sourceStr)
|
127 |
+
// 1+/\w+/g.test (sourceStr)
|
128 |
+
// 1|/\w+/g.test (sourceStr)
|
129 |
+
// bool||/\w+/g.test (sourceStr)
|
130 |
+
// 1&/\w+/g.test (sourceStr)
|
131 |
+
// bool&&/\w+/g.test (sourceStr)
|
132 |
+
// 10%/\w+/g.test (sourceStr)
|
133 |
+
// 1>/\w+/g.test (sourceStr)
|
134 |
+
// 1>>/\w+/g.test (sourceStr)
|
135 |
+
// 1</\w+/g.test (sourceStr)
|
136 |
+
// 1<</\w+/g.test (sourceStr)
|
137 |
+
// variable=/\w+/g.test (sourceStr)
|
138 |
+
// bool==/\w+/g.test (sourceStr)
|
139 |
+
// bool?/\w+/g.test (sourceStr):{}
|
140 |
+
// 1^/\w+/g.test (sourceStr):{}
|
141 |
+
/* TODO:
|
142 |
+
There might be a better way of handling this. Perhaps one builds up an operator as large as one can make it without it becoming not a valid operator, at which point one terminates the token. This approach would involve maintaining a list of valid operators, rather than a list of valid operator characters and an exception mechanism for detecting invalid operators.
|
143 |
+
*/
|
144 |
+
;
|
145 |
+
|
146 |
+
/*** Private Static Properties ***/
|
147 |
+
var _settings = {};
|
148 |
+
|
149 |
+
/*** Public Static Methods ***/
|
150 |
+
_package.scrunch = function (_sourceCode,_scruncherSettings) {
|
151 |
+
var
|
152 |
+
/*** report variables ***/
|
153 |
+
_uniqueIdentifiersScrunched = 0,
|
154 |
+
_incidencesOfIdentifiersScrunched = 0,
|
155 |
+
_savingsFromScrunchedIdentifiers = 0,
|
156 |
+
_savingsFromRemovedWhitespace = 0,
|
157 |
+
_savingsFromRemovedComments = 0,
|
158 |
+
_savingsFromRemovedLinebreaks = 0,
|
159 |
+
_totalCommentsRemoved = 0,
|
160 |
+
|
161 |
+
_mappings,
|
162 |
+
_endOfHeadComment = _false,
|
163 |
+
_lineNo = 1,
|
164 |
+
_scrunchedCode = _scrunchedCodeHeader = '',
|
165 |
+
_comments = [],
|
166 |
+
_stringsMap = {},
|
167 |
+
_leaveNextComment = _false,
|
168 |
+
_commentType,
|
169 |
+
_quoteChar,
|
170 |
+
_currentChar = '',
|
171 |
+
_previousChar,
|
172 |
+
_inEscape = _false,
|
173 |
+
_tokenType = _NONE,
|
174 |
+
_previousAddedToken = '',
|
175 |
+
_previousAddedTokenType = _NONE,
|
176 |
+
_currentToken = '',
|
177 |
+
_tokenTerminated = _false,
|
178 |
+
_currentBlock = '',
|
179 |
+
_currentLine = '',
|
180 |
+
_Uize_String_startsWith = Uize.String.startsWith
|
181 |
+
;
|
182 |
+
/*** initialize settings ***/
|
183 |
+
/* IDEA:
|
184 |
+
make this switchable, so that it doesn't always have to be performed for each scrunch (and so that groups of files can be scrunched in the same namespace?)
|
185 |
+
*/
|
186 |
+
_settings.LINECOMPACTING = 'TRUE';
|
187 |
+
_settings.MAXLINELENGTH = 1024;
|
188 |
+
_settings.MAPPINGS = '';
|
189 |
+
_settings.KEEPHEADCOMMENT = 'TRUE';
|
190 |
+
_settings.AUDITSTRINGS = 'FALSE';
|
191 |
+
|
192 |
+
function _Mapping (_sourcePrefix,_targetPrefix) {
|
193 |
+
/*** Constructor Properties ***/
|
194 |
+
this._sourcePrefix = _sourcePrefix;
|
195 |
+
this._targetPrefix = _targetPrefix || _sourcePrefix;
|
196 |
+
|
197 |
+
/*** Private Instance Properties ***/
|
198 |
+
this._scrunchMap = [];
|
199 |
+
this._totalIdentifiers = 0;
|
200 |
+
}
|
201 |
+
|
202 |
+
function _parseScruncherSettings (_scruncherSettings) {
|
203 |
+
function _stringToBoolean (_value) {
|
204 |
+
_value = (_value + '').toUpperCase ();
|
205 |
+
return _value == 'TRUE' || _value == 'ON' || _value == '1';
|
206 |
+
}
|
207 |
+
|
208 |
+
Uize.copyInto (
|
209 |
+
_settings,
|
210 |
+
typeof _scruncherSettings == 'string'
|
211 |
+
? Uize.Xml.fromAttributes (_scruncherSettings,{nameCase:'upper'})
|
212 |
+
: _scruncherSettings
|
213 |
+
);
|
214 |
+
|
215 |
+
/*** update/resolve settings ***/
|
216 |
+
_settings.LINECOMPACTING = _stringToBoolean (_settings.LINECOMPACTING);
|
217 |
+
_settings.KEEPHEADCOMMENT = _stringToBoolean (_settings.KEEPHEADCOMMENT);
|
218 |
+
_settings.AUDITSTRINGS = _stringToBoolean (_settings.AUDITSTRINGS);
|
219 |
+
|
220 |
+
/*** parse mappings to create mapping objects ***/
|
221 |
+
_mappings = [];
|
222 |
+
var _mappingPairs = _settings.MAPPINGS.split (',');
|
223 |
+
for (var _pairNo = -1; ++_pairNo < _mappingPairs.length;) {
|
224 |
+
var _sourcePrefixAndTargetPrefix = Uize.String.splitInTwo (_mappingPairs [_pairNo],'=');
|
225 |
+
_mappings [_pairNo] = new _Mapping (
|
226 |
+
_sourcePrefixAndTargetPrefix [0],
|
227 |
+
_sourcePrefixAndTargetPrefix [1]
|
228 |
+
);
|
229 |
+
}
|
230 |
+
}
|
231 |
+
_parseScruncherSettings (_scruncherSettings);
|
232 |
+
|
233 |
+
for (
|
234 |
+
var
|
235 |
+
_charNo = -1,
|
236 |
+
_sourceCodeLength = _sourceCode.length,
|
237 |
+
_sourceCodeLengthMinus1 = _sourceCodeLength - 1
|
238 |
+
;
|
239 |
+
++_charNo <= _sourceCodeLength;
|
240 |
+
) {
|
241 |
+
_previousChar = _currentChar;
|
242 |
+
if (_charNo > _sourceCodeLengthMinus1) {
|
243 |
+
_currentChar = '';
|
244 |
+
_tokenTerminated = _true;
|
245 |
+
} else {
|
246 |
+
_currentChar = _sourceCode.charAt (_charNo);
|
247 |
+
(_currentChar == '\r' || (_currentChar == '\n' && _previousChar != '\r')) &&
|
248 |
+
_lineNo++
|
249 |
+
;
|
250 |
+
if (_tokenType == _WORD) {
|
251 |
+
if (!_wordCharsLookup [_currentChar]) _tokenTerminated = _true;
|
252 |
+
} else if (_tokenType == _NUMBER) {
|
253 |
+
if (!_numberCharsLookup [_currentChar]) _tokenTerminated = _true;
|
254 |
+
} else if (_tokenType == _DELIMITER) {
|
255 |
+
if (!_delimiterCharsLookup [_currentChar]) _tokenTerminated = _true;
|
256 |
+
} else if (_tokenType == _STRINGLITERAL) {
|
257 |
+
if (_inEscape) {
|
258 |
+
_inEscape = _false;
|
259 |
+
} else if (_currentChar == '\\') {
|
260 |
+
_inEscape = _true;
|
261 |
+
} else if (_currentChar == _quoteChar) {
|
262 |
+
if (_settings.AUDITSTRINGS && _quoteChar != '/') {
|
263 |
+
var
|
264 |
+
_string = _currentToken.slice (1),
|
265 |
+
_stringProfile = _stringsMap [_string]
|
266 |
+
;
|
267 |
+
(_stringProfile instanceof Array ? _stringProfile : (_stringsMap [_string] = []))
|
268 |
+
.push (_lineNo) // must handle the case of the valueOf and toString natives
|
269 |
+
;
|
270 |
+
}
|
271 |
+
_currentToken += _currentChar;
|
272 |
+
_currentChar = '';
|
273 |
+
_tokenTerminated = _true;
|
274 |
+
}
|
275 |
+
} else if (_tokenType == _COMMENT) {
|
276 |
+
if (_commentType == '//') {
|
277 |
+
if (_currentChar == '\n' || _currentChar == '\r') _tokenTerminated = _true;
|
278 |
+
} else if (_commentType == '/*') {
|
279 |
+
if (_currentToken.length > 2 && _previousChar + _currentChar == '*/') {
|
280 |
+
/* NOTE:
|
281 |
+
making sure the length is greater than 2 when evaluating the current character avoids terminating a comment that's a forward slash + star + forward slash, where technically there is a comment opener and a comment closer, but they both share a star
|
282 |
+
*/
|
283 |
+
_currentToken += _currentChar;
|
284 |
+
_tokenTerminated = _true;
|
285 |
+
_currentChar = '';
|
286 |
+
}
|
287 |
+
}
|
288 |
+
} else if (_tokenType == _OPERATOR) {
|
289 |
+
if (_currentToken == '/' && (_currentChar == '/' || _currentChar == '*')) {
|
290 |
+
_tokenType = _COMMENT;
|
291 |
+
_commentType = _currentToken + _currentChar;
|
292 |
+
/* NOTE:
|
293 |
+
Following code is an optimization, to seek ahead to the end of the comment, rather than running through the characters one by one (which slows down scrunching dramatically).
|
294 |
+
*/
|
295 |
+
var _commentCloserPos;
|
296 |
+
if (_currentChar == '*') {
|
297 |
+
_commentCloserPos = _sourceCode.indexOf ('*/',_charNo + 1);
|
298 |
+
if (_commentCloserPos < 0) _commentCloserPos = _sourceCodeLength;
|
299 |
+
} else {
|
300 |
+
var
|
301 |
+
_nextLineFeed = _sourceCode.indexOf ('\n',_charNo + 1),
|
302 |
+
_nextCarriageReturn = _sourceCode.indexOf ('\r',_charNo + 1)
|
303 |
+
;
|
304 |
+
_commentCloserPos = Math.min (
|
305 |
+
_nextLineFeed < 0 ? _sourceCodeLength : _nextLineFeed,
|
306 |
+
_nextCarriageReturn < 0 ? _sourceCodeLength : _nextCarriageReturn
|
307 |
+
);
|
308 |
+
}
|
309 |
+
_currentToken = _sourceCode.slice (_charNo - 1,_commentCloserPos - 1);
|
310 |
+
_currentChar = _sourceCode.charAt (_charNo = _commentCloserPos - 1);
|
311 |
+
} else if (
|
312 |
+
_currentToken == '/' &&
|
313 |
+
(_previousAddedTokenType != _WORD || _previousAddedToken == 'return') &&
|
314 |
+
_previousAddedTokenType != _NUMBER &&
|
315 |
+
_previousAddedTokenType != _STRINGLITERAL &&
|
316 |
+
!(
|
317 |
+
_previousAddedTokenType == _DELIMITER &&
|
318 |
+
_closeParenOrSquareBracketMap [_previousAddedToken.slice (-1)]
|
319 |
+
)
|
320 |
+
) {
|
321 |
+
/* regular expression handling
|
322 |
+
NOTE: by setting the _currentChar to an empty string and decrementing the _charNo counter, we force re-evualtion of the current character, now that we know we're in a regular expression
|
323 |
+
*/
|
324 |
+
_tokenType = _STRINGLITERAL;
|
325 |
+
_quoteChar = '/';
|
326 |
+
_currentChar = '';
|
327 |
+
_charNo--;
|
328 |
+
} else if (
|
329 |
+
!_operatorCharsLookup [_currentChar] ||
|
330 |
+
_invalidOperatorRegExp.test (_currentToken + _currentChar)
|
331 |
+
) {
|
332 |
+
_tokenTerminated = _true;
|
333 |
+
}
|
334 |
+
} else if (_tokenType == _LINEBREAK) {
|
335 |
+
if (_currentChar != '\n' && _currentChar != '\r') _tokenTerminated = _true;
|
336 |
+
}
|
337 |
+
_endOfHeadComment =
|
338 |
+
_endOfHeadComment ||
|
339 |
+
(_tokenType && _tokenType != _COMMENT && (_tokenType != _LINEBREAK || _currentToken.length > 1))
|
340 |
+
;
|
341 |
+
}
|
342 |
+
if (_tokenTerminated) {
|
343 |
+
if (_tokenType == _WORD) {
|
344 |
+
for (var _mappingNo = -1; ++_mappingNo < _mappings.length;) {
|
345 |
+
var _mapping = _mappings [_mappingNo];
|
346 |
+
if (_Uize_String_startsWith (_currentToken,_mapping._sourcePrefix + '_')) {
|
347 |
+
_incidencesOfIdentifiersScrunched++;
|
348 |
+
var _scrunchedToken = _mapping._scrunchMap [_currentToken] || '';
|
349 |
+
if (!_scrunchedToken) {
|
350 |
+
_uniqueIdentifiersScrunched++;
|
351 |
+
var _numberToConvert = _mapping._totalIdentifiers++;
|
352 |
+
do {
|
353 |
+
_scrunchedToken =
|
354 |
+
_identifierChars [
|
355 |
+
_numberToConvert -
|
356 |
+
_totalIdentifierChars * (
|
357 |
+
_numberToConvert = Math.floor (_numberToConvert / _totalIdentifierChars)
|
358 |
+
)
|
359 |
+
] + _scrunchedToken
|
360 |
+
;
|
361 |
+
} while (_numberToConvert > 0);
|
362 |
+
_scrunchedToken =
|
363 |
+
_mapping._scrunchMap [_currentToken] = _mapping._targetPrefix + '_' + _scrunchedToken
|
364 |
+
;
|
365 |
+
}
|
366 |
+
_savingsFromScrunchedIdentifiers +=
|
367 |
+
_currentToken.length - (_currentToken = _scrunchedToken).length
|
368 |
+
;
|
369 |
+
break;
|
370 |
+
}
|
371 |
+
}
|
372 |
+
} else if (_tokenType == _COMMENT) {
|
373 |
+
_comments.push (_currentToken);
|
374 |
+
_savingsFromRemovedComments += _currentToken.length;
|
375 |
+
var _isScruncherDirective = _false;
|
376 |
+
if (/^\/[\*\/]\s*scruncher/i.test (_currentToken)) {
|
377 |
+
if (_currentToken.substr (2,17).toLowerCase () == 'scrunchersettings') {
|
378 |
+
_isScruncherDirective = _true;
|
379 |
+
_parseScruncherSettings (
|
380 |
+
_currentToken.slice (2,_currentToken.length - (_commentType == '/*') * 2)
|
381 |
+
);
|
382 |
+
_currentToken = '';
|
383 |
+
} else if (/^\/[\*\/]\s*scruncher:leave next comment/i.test (_currentToken)) {
|
384 |
+
_isScruncherDirective = _leaveNextComment = _true;
|
385 |
+
_currentToken = '';
|
386 |
+
}
|
387 |
+
}
|
388 |
+
if (!_isScruncherDirective) {
|
389 |
+
if ((_endOfHeadComment || !_settings.KEEPHEADCOMMENT) && !_leaveNextComment) {
|
390 |
+
_currentToken = '';
|
391 |
+
} else if (_commentType == '/*') {
|
392 |
+
if (_leaveNextComment) {
|
393 |
+
if (_settings.LINECOMPACTING) _currentToken = '\n' + _currentToken + '\n';
|
394 |
+
_leaveNextComment = _false;
|
395 |
+
}
|
396 |
+
_currentToken += '\n';
|
397 |
+
}
|
398 |
+
}
|
399 |
+
if (!_currentToken) _totalCommentsRemoved++;
|
400 |
+
_savingsFromRemovedComments -= _currentToken.length;
|
401 |
+
} else if (_tokenType == _LINEBREAK) {
|
402 |
+
_savingsFromRemovedLinebreaks += _currentToken.length;
|
403 |
+
_currentToken = '';
|
404 |
+
if (
|
405 |
+
!_settings.LINECOMPACTING ||
|
406 |
+
(_currentBlock.length + _currentLine.length > _settings.MAXLINELENGTH)
|
407 |
+
) {
|
408 |
+
_scrunchedCode += _currentBlock + '\n';
|
409 |
+
_savingsFromRemovedLinebreaks--;
|
410 |
+
_currentBlock = '';
|
411 |
+
}
|
412 |
+
_currentBlock += _currentLine;
|
413 |
+
_currentLine = '';
|
414 |
+
}
|
415 |
+
if (
|
416 |
+
((_tokenType == _WORD || _tokenType == _OPERATOR) && _previousAddedTokenType == _tokenType) ||
|
417 |
+
(
|
418 |
+
_tokenType == _NUMBER &&
|
419 |
+
_digitsLookup [_currentToken.charAt (0)] &&
|
420 |
+
_previousAddedTokenType == _WORD
|
421 |
+
)
|
422 |
+
) {
|
423 |
+
/* NOTE: whitespace is necessary when it separates...
|
424 |
+
- two adjacent words (eg. function myFunction)
|
425 |
+
- two adjacent operators (eg. myVariable += ++ myOtherVariable)
|
426 |
+
- a word followed by a number that starts with a digit, rather than "+", "-", or "." (eg. return 1)
|
427 |
+
*/
|
428 |
+
_currentToken = ' ' + _currentToken;
|
429 |
+
_savingsFromRemovedWhitespace--;
|
430 |
+
}
|
431 |
+
_tokenTerminated = _false;
|
432 |
+
if (_currentToken) {
|
433 |
+
_currentLine += _currentToken;
|
434 |
+
_previousAddedToken = _currentToken;
|
435 |
+
_previousAddedTokenType = _tokenType;
|
436 |
+
}
|
437 |
+
_currentToken = '';
|
438 |
+
_tokenType = _NONE;
|
439 |
+
}
|
440 |
+
if (!_tokenType && _currentChar) {
|
441 |
+
_tokenType = _tokenStarterCharsLookup [_currentChar];
|
442 |
+
if (_tokenType == _STRINGLITERAL)
|
443 |
+
_quoteChar = _currentChar
|
444 |
+
;
|
445 |
+
}
|
446 |
+
_tokenType
|
447 |
+
? (_currentToken += _currentChar)
|
448 |
+
: (_savingsFromRemovedWhitespace += _currentChar.length)
|
449 |
+
;
|
450 |
+
}
|
451 |
+
return {
|
452 |
+
scrunchedCode:_scrunchedCode += _currentBlock + _currentLine,
|
453 |
+
comments:_comments,
|
454 |
+
stringsMap:_stringsMap,
|
455 |
+
report:
|
456 |
+
'Unique Identifiers Scrunched: ' + _uniqueIdentifiersScrunched + '\n' +
|
457 |
+
'Incidences of Identifiers Scrunched: ' + _incidencesOfIdentifiersScrunched + '\n' +
|
458 |
+
'Savings From Scrunched Identifiers: ' + _savingsFromScrunchedIdentifiers + '\n' +
|
459 |
+
'Savings From Removed Whitespace: ' + _savingsFromRemovedWhitespace + '\n' +
|
460 |
+
'Total Comments Removed: ' + _totalCommentsRemoved + '\n' +
|
461 |
+
'Savings From Removed Comments: ' + _savingsFromRemovedComments + '\n' +
|
462 |
+
'Savings From Removed Linebreaks: ' + _savingsFromRemovedLinebreaks + '\n' +
|
463 |
+
'Supposed Total Savings: ' + (_savingsFromScrunchedIdentifiers + _savingsFromRemovedWhitespace + _savingsFromRemovedComments + _savingsFromRemovedLinebreaks - _scrunchedCodeHeader.length) + '\n' +
|
464 |
+
'Real Total Savings: ' + (_sourceCode.length - _scrunchedCode.length) + '\n\n' +
|
465 |
+
'FINAL SIZE: ' + _scrunchedCode.length
|
466 |
+
};
|
467 |
+
/*?
|
468 |
+
Static Methods
|
469 |
+
Uize.Build.Scruncher.scrunch
|
470 |
+
Scrunches the specified source code string and returns an object, containing a string property for the scrunched form of the code, a string property with a report summarizing the savings from scrunching the code, and an array property containing all the comments from the source.
|
471 |
+
|
472 |
+
SYNTAX
|
473 |
+
..................................................................
|
474 |
+
scruncherResultOBJ = Uize.Build.Scruncher.scrunch (sourceCodeSTR);
|
475 |
+
..................................................................
|
476 |
+
|
477 |
+
The returned object has the following composition...
|
478 |
+
|
479 |
+
..........................................................................
|
480 |
+
{
|
481 |
+
scrunchedCode:scrunchedCodeSTR, // the scrunched form of the code
|
482 |
+
report:reportSTR, // a multi-line summary of size savings
|
483 |
+
comments:commentsARRAY // an array of strings
|
484 |
+
}
|
485 |
+
..........................................................................
|
486 |
+
|
487 |
+
The multi-line report contained in the =report= string property summarizes the file size savings from removed whitespace, removed comments, removed linebreaks, and scrunched identifiers. The comments array specified by the =comments= property can be used in the generation of comment-based documentation, as is done by the =Uize.Doc.Sucker= package.
|
488 |
+
|
489 |
+
VARIATION
|
490 |
+
.......................................................................................
|
491 |
+
scruncherResultOBJ = Uize.Build.Scruncher.scrunch (sourceCodeSTR,scruncherSettingsSTR);
|
492 |
+
.......................................................................................
|
493 |
+
|
494 |
+
When the optional =scruncherSettingsSTR= parameter is specified, the specified Scruncher settings string will be parsed and applied to the scrunching process. This is done after the Scruncher settings have been initialized and before any of the specified source file has been parsed, so before any Scruncher settings inside the source code are encountered. Therefore, Scruncher settings inside the code being scrunched will take precedence and will override any Scruncher settings specified in the =scruncherSettingsSTR= parameter.
|
495 |
+
|
496 |
+
The value of the =scruncherSettingsSTR= parameter should have the following syntax...
|
497 |
+
|
498 |
+
.................................................................
|
499 |
+
[setting0Name]="[setting0Value]" [settingNName]="[settingNValue]"
|
500 |
+
.................................................................
|
501 |
+
|
502 |
+
This parameter is useful for providing initial values for Scruncher settings that may not be specified inside a file (or files) being scrunched, and is particularly useful when using the Scruncher in build scripts.
|
503 |
+
|
504 |
+
EXAMPLE
|
505 |
+
..........................................................................................
|
506 |
+
var scruncherResult = Uize.Build.Scruncher.scrunch (sourceCode,'KeepHeadComment="FALSE"');
|
507 |
+
..........................................................................................
|
508 |
+
|
509 |
+
In the above example, the =scruncherSettingsSTR= parameter is being used to direct the Scruncher to omit the source code's head comment when scrunching it.
|
510 |
+
*/
|
511 |
+
};
|
512 |
+
|
513 |
+
return _package;
|
514 |
+
}
|
515 |
+
});
|
skin/frontend/default/customproduct/js/Uize.Build.ServicesSetup.js
ADDED
@@ -0,0 +1,51 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Build.ServicesSetup Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 5
|
15 |
+
codeCompleteness: 0
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 5
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Build.ServicesSetup= package....
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
*/
|
26 |
+
|
27 |
+
Uize.module ({
|
28 |
+
name:'Uize.Build.ServicesSetup',
|
29 |
+
required:'Uize.Services.Setup',
|
30 |
+
builder:function () {
|
31 |
+
/*** Variables for Scruncher Optimization ***/
|
32 |
+
var _package = function () {};
|
33 |
+
|
34 |
+
/*** Public Static Methods ***/
|
35 |
+
_package.setup = function () {
|
36 |
+
/*** provide setup for FileSystem service ***/
|
37 |
+
var _isWsh = typeof ActiveXObject != 'undefined';
|
38 |
+
Uize.Services.Setup.provideServiceSetup (
|
39 |
+
'Uize.Services.FileSystem',
|
40 |
+
_isWsh ? 'Uize.Services.FileSystemWsh' : 'Uize.Services.FileSystemNode',
|
41 |
+
function (_service,_doneWithSetup) {
|
42 |
+
_service.init ();
|
43 |
+
_doneWithSetup ();
|
44 |
+
}
|
45 |
+
);
|
46 |
+
};
|
47 |
+
|
48 |
+
return _package;
|
49 |
+
}
|
50 |
+
});
|
51 |
+
|
skin/frontend/default/customproduct/js/Uize.Build.UpdateCopyrightNotices.js
ADDED
@@ -0,0 +1,94 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Build.UpdateCopyrightNotices Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2011-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 1
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 4
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Build.UpdateCopyrightNotices= package provides a way to recurse folder structures and update the copyright notices for all JavaScript (.js) files to cover the current year.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
The =Uize.Build.UpdateCopyrightNotices= module is designed specifically to run in the context of Windows Script Host.
|
27 |
+
*/
|
28 |
+
|
29 |
+
Uize.module ({
|
30 |
+
name:'Uize.Build.UpdateCopyrightNotices',
|
31 |
+
required:'Uize.Build.Util',
|
32 |
+
builder:function () {
|
33 |
+
/*** Variables for Scruncher Optimization ***/
|
34 |
+
var _package = function () {};
|
35 |
+
|
36 |
+
/*** General Variables ***/
|
37 |
+
var
|
38 |
+
_copyrightNoticeRegExp = /\(c\)\s*\d{4}(?:\s*-\s*(\d{4}))?/i,
|
39 |
+
_copyrightNoticeEndYearRegExp = /(-\s*)(\d{4})/
|
40 |
+
;
|
41 |
+
|
42 |
+
/*** Public Static Methods ***/
|
43 |
+
_package.perform = function (_params) {
|
44 |
+
var _thisYear = (new Date).getFullYear ();
|
45 |
+
Uize.Build.Util.buildFiles (
|
46 |
+
Uize.copyInto (
|
47 |
+
{
|
48 |
+
targetFolderPathCreator:function (_folderPath) {
|
49 |
+
return _folderPath;
|
50 |
+
},
|
51 |
+
targetFilenameCreator:function (_sourceFileName) {
|
52 |
+
return /\.(js|jst)$/.test (_sourceFileName) ? _sourceFileName : null;
|
53 |
+
},
|
54 |
+
fileBuilder:function (_sourceFileName,_sourceFileText) {
|
55 |
+
var _copyrightNoticeMatch = _sourceFileText.match (_copyrightNoticeRegExp);
|
56 |
+
if (_copyrightNoticeMatch) {
|
57 |
+
var _oldCopyrightNotice = _copyrightNoticeMatch [0];
|
58 |
+
if (_oldCopyrightNotice == '(c)' + _thisYear) {
|
59 |
+
_copyrightNoticeMatch = null;
|
60 |
+
} else {
|
61 |
+
var
|
62 |
+
_endYearMatch = _oldCopyrightNotice.match (_copyrightNoticeEndYearRegExp),
|
63 |
+
_newCopyrightNotice = _endYearMatch
|
64 |
+
? _oldCopyrightNotice.replace (_copyrightNoticeEndYearRegExp,'$1' + _thisYear)
|
65 |
+
: _oldCopyrightNotice + '-' + _thisYear,
|
66 |
+
_updatedaSourceFileText =
|
67 |
+
_sourceFileText.replace (_oldCopyrightNotice,_newCopyrightNotice)
|
68 |
+
;
|
69 |
+
}
|
70 |
+
}
|
71 |
+
return (
|
72 |
+
_copyrightNoticeMatch &&
|
73 |
+
_updatedaSourceFileText != _sourceFileText
|
74 |
+
? {
|
75 |
+
outputText:_updatedaSourceFileText,
|
76 |
+
logDetails:
|
77 |
+
'\t\tCopyright Notice Updated:\n' +
|
78 |
+
'\t\t\tWAS: ' + _oldCopyrightNotice + '\n' +
|
79 |
+
'\t\t\tNOW: ' + _newCopyrightNotice + '\n'
|
80 |
+
}
|
81 |
+
: {logDetails:'\t\tFILE ALREADY OK\n'}
|
82 |
+
);
|
83 |
+
}
|
84 |
+
},
|
85 |
+
_params,
|
86 |
+
{alwaysBuild:true}
|
87 |
+
)
|
88 |
+
);
|
89 |
+
};
|
90 |
+
|
91 |
+
return _package;
|
92 |
+
}
|
93 |
+
});
|
94 |
+
|
skin/frontend/default/customproduct/js/Uize.Build.Util.js
ADDED
@@ -0,0 +1,359 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Build.Util Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2010-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 3
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 2
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Build.Util= package provides various utility methods to facilitate building of pages for a Web site project.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
*/
|
26 |
+
|
27 |
+
Uize.module ({
|
28 |
+
name:'Uize.Build.Util',
|
29 |
+
required:[
|
30 |
+
'Uize.Url',
|
31 |
+
'Uize.Template',
|
32 |
+
'Uize.Data.Simple',
|
33 |
+
'Uize.String',
|
34 |
+
'Uize.String.Lines',
|
35 |
+
'Uize.Json',
|
36 |
+
'Uize.Array.Sort',
|
37 |
+
'Uize.Services.FileSystem'
|
38 |
+
],
|
39 |
+
builder:function () {
|
40 |
+
/*** Variables for Scruncher Optimization ***/
|
41 |
+
var
|
42 |
+
_package = function () {},
|
43 |
+
_undefined
|
44 |
+
;
|
45 |
+
|
46 |
+
/*** General Variables ***/
|
47 |
+
var
|
48 |
+
_fileSystem = Uize.Services.FileSystem.singleton (),
|
49 |
+
_compiledJstFilesByPath = {}
|
50 |
+
;
|
51 |
+
|
52 |
+
/*** Public Static Methods ***/
|
53 |
+
_package.getHtmlFileInfo = function (_filePath,_titleExtractor) {
|
54 |
+
var
|
55 |
+
_fileText = _fileSystem.readFile ({path:_filePath}),
|
56 |
+
_keywordsMatch = _fileText.match (/<meta name="keywords" content="(.*?)"\/>/),
|
57 |
+
_descriptionMatch = _fileText.match (/<meta name="description" content="(.*?)"\/>/),
|
58 |
+
_imageSrcMatch = _fileText.match (/<link rel="image_src" href="(.*?)"\/>/)
|
59 |
+
;
|
60 |
+
return {
|
61 |
+
path:_filePath,
|
62 |
+
title:_titleExtractor (_fileText.match (/<title>(.*?)<\/title>/) [1]),
|
63 |
+
keywords:_keywordsMatch ? _keywordsMatch [1] : '',
|
64 |
+
description:_descriptionMatch ? _descriptionMatch [1] : '',
|
65 |
+
imageSrc:_imageSrcMatch ? Uize.Url.toAbsolute (_folderToIndex,_imageSrcMatch [1]) : ''
|
66 |
+
};
|
67 |
+
};
|
68 |
+
|
69 |
+
_package.getHtmlFilesInfo = function (_folderToIndex,_titleExtractor) {
|
70 |
+
if (!_titleExtractor) _titleExtractor = Uize.returnX;
|
71 |
+
return Uize.Array.Sort.sortBy (
|
72 |
+
Uize.map (
|
73 |
+
_fileSystem.getFiles ({
|
74 |
+
path:_folderToIndex,
|
75 |
+
pathMatcher:function (_path) {
|
76 |
+
var _urlParts = Uize.Url.from (_path);
|
77 |
+
return _urlParts.fileType == 'html' && !Uize.String.startsWith (_urlParts.file,'~');
|
78 |
+
}
|
79 |
+
}),
|
80 |
+
function (_path) {
|
81 |
+
return _package.getHtmlFileInfo (
|
82 |
+
_folderToIndex + '/' + Uize.Url.from (_path).file,
|
83 |
+
_titleExtractor
|
84 |
+
);
|
85 |
+
}
|
86 |
+
),
|
87 |
+
'value.title.toLowerCase ()'
|
88 |
+
);
|
89 |
+
};
|
90 |
+
|
91 |
+
_package.readSimpleDataFile = function (_simpleDataFilePath) {
|
92 |
+
return Uize.Data.Simple.parse ({
|
93 |
+
simple:_fileSystem.readFile ({path:_simpleDataFilePath}),
|
94 |
+
collapseChildren:true
|
95 |
+
});
|
96 |
+
};
|
97 |
+
|
98 |
+
_package.compileJstFile = function (_jstTemplatePath) {
|
99 |
+
var _template = _compiledJstFilesByPath [_jstTemplatePath];
|
100 |
+
if (!_template) {
|
101 |
+
if (!_fileSystem.fileExists ({path:_jstTemplatePath})) return;
|
102 |
+
_template = _compiledJstFilesByPath [_jstTemplatePath] = Uize.Template.compile (
|
103 |
+
_fileSystem.readFile ({path:_jstTemplatePath}),
|
104 |
+
{result:'full'}
|
105 |
+
);
|
106 |
+
Uize.require (_template.required);
|
107 |
+
}
|
108 |
+
return _template.templateFunction;
|
109 |
+
};
|
110 |
+
|
111 |
+
_package.processJstFile = function (_jstTemplatePath,_input) {
|
112 |
+
var _template = _package.compileJstFile (_jstTemplatePath);
|
113 |
+
_template &&
|
114 |
+
_fileSystem.writeFile ({path:_jstTemplatePath.replace (/\.jst$/,''),contents:_template (_input)})
|
115 |
+
;
|
116 |
+
};
|
117 |
+
|
118 |
+
_package.runScripts = function (_scripts) {
|
119 |
+
var _error;
|
120 |
+
if (!Uize.isArray (_scripts)) _scripts = [_scripts];
|
121 |
+
for (
|
122 |
+
var
|
123 |
+
_scriptNo = -1,
|
124 |
+
_scriptsLength = _scripts.length,
|
125 |
+
_wshShell = new ActiveXObject ('WScript.Shell'),
|
126 |
+
_errorCode
|
127 |
+
;
|
128 |
+
++_scriptNo < _scriptsLength && !_error;
|
129 |
+
)
|
130 |
+
if (_errorCode = _wshShell.Run ('WScript ' + _scripts [_scriptNo],0,true))
|
131 |
+
_error = {
|
132 |
+
script:_scripts [_scriptNo],
|
133 |
+
errorCode:_errorCode
|
134 |
+
}
|
135 |
+
;
|
136 |
+
return _error;
|
137 |
+
};
|
138 |
+
|
139 |
+
_package.runUnitTests = function (_unitTestsClass,_silent,_logFilePath) {
|
140 |
+
function _runUnitTests (_unitTestsClass) {
|
141 |
+
var
|
142 |
+
_unitTests = new _unitTestsClass,
|
143 |
+
_logChunks = []
|
144 |
+
;
|
145 |
+
_unitTests.wire ({
|
146 |
+
Start:
|
147 |
+
function (_event) {
|
148 |
+
_logChunks.push (
|
149 |
+
Uize.String.repeat ('\t',_event.source.getDepth ()) + _event.source.get ('title')
|
150 |
+
);
|
151 |
+
},
|
152 |
+
Done:
|
153 |
+
function (_event) {
|
154 |
+
var
|
155 |
+
_test = _event.source,
|
156 |
+
_reasonForFailure = _test.get ('reasonForFailure')
|
157 |
+
;
|
158 |
+
/*** add to log ***/
|
159 |
+
_logChunks.push (
|
160 |
+
Uize.String.repeat ('\t',_test.getDepth () + 1) +
|
161 |
+
(
|
162 |
+
_test.get ('result')
|
163 |
+
? ('PASSED!!! (duration: ' + _test.get ('duration') + 'ms)')
|
164 |
+
: ('*** FAILED *** ' + (_reasonForFailure || ''))
|
165 |
+
)
|
166 |
+
);
|
167 |
+
_reasonForFailure && _logChunks.push ('','',_test.getSynopsis ());
|
168 |
+
|
169 |
+
/*** finish up if the test fails or if unit tests complete ***/
|
170 |
+
if (_test == _unitTests || !_test.get ('result')) {
|
171 |
+
_silent || alert (_test.getSynopsis ());
|
172 |
+
_logFilePath &&
|
173 |
+
_fileSystem.writeFile ({path:_logFilePath,contents:_logChunks.join ('\n')})
|
174 |
+
;
|
175 |
+
_test.get ('result') || WScript.Quit (1);
|
176 |
+
}
|
177 |
+
}
|
178 |
+
});
|
179 |
+
_unitTests.run ();
|
180 |
+
}
|
181 |
+
typeof _unitTestsClass == 'string'
|
182 |
+
? Uize.require (_unitTestsClass,_runUnitTests)
|
183 |
+
: _runUnitTests (_unitTestsClass)
|
184 |
+
;
|
185 |
+
};
|
186 |
+
|
187 |
+
_package.dataAsModule = function (_moduleName,_moduleData) {
|
188 |
+
return [
|
189 |
+
'Uize.module ({',
|
190 |
+
' name:\'' + _moduleName + '\',',
|
191 |
+
' superclass:\'\',',
|
192 |
+
' builder:function () {',
|
193 |
+
' return function () {',
|
194 |
+
' return ' + Uize.String.Lines.indent (Uize.Json.to (_moduleData),3,'\t',false) + ';',
|
195 |
+
' };',
|
196 |
+
' }',
|
197 |
+
'});'
|
198 |
+
].join ('\n');
|
199 |
+
};
|
200 |
+
|
201 |
+
_package.writeDataModule = function (_moduleFolderPath,_moduleName,_moduleData) {
|
202 |
+
_fileSystem.writeFile ({
|
203 |
+
path:_moduleFolderPath + '/' + _moduleName + '.js',
|
204 |
+
contents:_package.dataAsModule (_moduleName,_moduleData)
|
205 |
+
});
|
206 |
+
};
|
207 |
+
|
208 |
+
_package.buildFiles = function (_params) {
|
209 |
+
var
|
210 |
+
_alwaysBuild = _params.alwaysBuild,
|
211 |
+
_dryRun = _params.dryRun,
|
212 |
+
_doNotEnter = _params.doNotEnter,
|
213 |
+
_logFilePath = _params.logFilePath,
|
214 |
+
_logChunks = []
|
215 |
+
;
|
216 |
+
if (Uize.isArray (_doNotEnter))
|
217 |
+
_doNotEnter = new RegExp ('^(' + _doNotEnter.join ('|') + ')$')
|
218 |
+
;
|
219 |
+
function _processFolder (_folderPath) {
|
220 |
+
var _targetFolderPath = _doNotEnter && _doNotEnter.test (_folderPath)
|
221 |
+
? false
|
222 |
+
: _params.targetFolderPathCreator (_folderPath)
|
223 |
+
;
|
224 |
+
if (typeof _targetFolderPath == 'string') {
|
225 |
+
Uize.forEach (
|
226 |
+
_fileSystem.getFiles ({path:_folderPath}),
|
227 |
+
function (_sourceFileName) {
|
228 |
+
var
|
229 |
+
_sourceFilePath = _folderPath + (_folderPath && '/') + _sourceFileName,
|
230 |
+
_targetFileName = _params.targetFilenameCreator (_sourceFileName)
|
231 |
+
;
|
232 |
+
if (_targetFileName) {
|
233 |
+
var
|
234 |
+
_targetFilePath = _targetFolderPath + '/' + _targetFileName,
|
235 |
+
_buildReason = _alwaysBuild
|
236 |
+
? 'ALWAYS BUILD'
|
237 |
+
: (
|
238 |
+
_fileSystem.fileExists ({path:_targetFilePath})
|
239 |
+
? (
|
240 |
+
_fileSystem.getModifiedDate ({path:_sourceFilePath}) >
|
241 |
+
_fileSystem.getModifiedDate ({path:_targetFilePath})
|
242 |
+
? 'WAS OUT OF DATE'
|
243 |
+
: ''
|
244 |
+
)
|
245 |
+
: 'DIDN\'T EXIST'
|
246 |
+
)
|
247 |
+
,
|
248 |
+
_buildDuration,
|
249 |
+
_logDetails = ''
|
250 |
+
;
|
251 |
+
if (_buildReason) {
|
252 |
+
var
|
253 |
+
_timeBeforeBuild = Uize.now (),
|
254 |
+
_processingResult = _params.fileBuilder (
|
255 |
+
_sourceFileName,
|
256 |
+
_fileSystem.readFile ({path:_sourceFilePath})
|
257 |
+
),
|
258 |
+
_outputText = _processingResult.outputText
|
259 |
+
;
|
260 |
+
_logDetails = _processingResult.logDetails || '';
|
261 |
+
!_dryRun && _outputText != _undefined &&
|
262 |
+
_fileSystem.writeFile ({path:_targetFilePath,contents:_outputText})
|
263 |
+
;
|
264 |
+
_buildDuration = Uize.now () - _timeBeforeBuild;
|
265 |
+
}
|
266 |
+
_logChunks.push (
|
267 |
+
(_buildReason ? '***** ' : '') + _sourceFilePath + '\n' +
|
268 |
+
'\tTARGET FILE: ' + _targetFilePath + '\n' +
|
269 |
+
'\t' +
|
270 |
+
(
|
271 |
+
_buildReason
|
272 |
+
? ('BUILT (' + _buildReason + '), BUILD DURATION: ' + _buildDuration + 'ms')
|
273 |
+
: 'no action, file is current'
|
274 |
+
) + '\n' +
|
275 |
+
_logDetails +
|
276 |
+
'\n'
|
277 |
+
);
|
278 |
+
}
|
279 |
+
}
|
280 |
+
);
|
281 |
+
}
|
282 |
+
_targetFolderPath !== false &&
|
283 |
+
Uize.forEach (
|
284 |
+
_fileSystem.getFolders ({path:_folderPath}),
|
285 |
+
function (_folderName) {_processFolder (_folderPath + (_folderPath && '/') + _folderName)}
|
286 |
+
)
|
287 |
+
;
|
288 |
+
}
|
289 |
+
_processFolder (_params.rootFolderPath);
|
290 |
+
_logFilePath && _fileSystem.writeFile ({path:_logFilePath,contents:_logChunks.join ('')});
|
291 |
+
/*?
|
292 |
+
Static Methods
|
293 |
+
Uize.Build.Util.buildFiles
|
294 |
+
Facilitates iterating through a folder hierarchy, processing specific files, and writing the results of processing to a specified log file.
|
295 |
+
|
296 |
+
SYNTAX
|
297 |
+
....................................................................
|
298 |
+
Uize.Build.Util.buildFiles ({
|
299 |
+
targetFolderPathCreator:targetFolderPathCreatorFUNC, // REQUIRED
|
300 |
+
targetFilenameCreator:targetFilenameCreatorFUNC, // REQUIRED
|
301 |
+
fileBuilder:fileBuilderFUNC, // REQUIRED
|
302 |
+
|
303 |
+
rootFolderPath:rootFolderPathSTR, // optional
|
304 |
+
alwaysBuild:alwaysBuildBOOL, // optional
|
305 |
+
doNotEnter:doNotEnterARRAYorREGEXP, // optional
|
306 |
+
logFilePath:logFilePathSTR // optional
|
307 |
+
});
|
308 |
+
....................................................................
|
309 |
+
|
310 |
+
This method starts iterating through files in the folder that contains the build script being executed and then recursively iterates through subfolders.
|
311 |
+
|
312 |
+
targetFolderPathCreator
|
313 |
+
A function reference, specifying a function that should be used to create a target folder path for the output of the files being built.
|
314 |
+
|
315 |
+
The function specified by this parameter should expect to receive one string parameter, being the folder path of the files being built. The function should return a string, being the path of the target folder where the built versions of the files should be written.
|
316 |
+
|
317 |
+
In a special case, if the function returns a boolean, then the files in the current folder being processed will not be built, and the boolean value will determine if the method recurses deeper into the current folder's subfolders. This provides a way to skip building the files in the current folder but recurse deeper, or to ignore a particular folder and all its contents - files *and* subfolders.
|
318 |
+
|
319 |
+
targetFilenameCreator
|
320 |
+
A function reference, specifying a function that should be used to create the target filenames for the output of the files being built.
|
321 |
+
|
322 |
+
The function specified by this parameter should expect to receive one string parameter, being the filename of the file being built. The function should return a string, being the target filename for where the built version of the file should be written. If the source file is not to be built, based upon interrogating the source filename (perhaps it's not a type of file that should be built), then the function should return an empty string or the value =false=.
|
323 |
+
|
324 |
+
fileBuilder
|
325 |
+
A function reference, specifying a function that should be used for processing the source file to create output that should be written as the target file.
|
326 |
+
|
327 |
+
The function specified by this parameter should expect to receive two string parameters, being the filename of the source file being built and the text contents of that file. The function should return an object containing the property =outputText=, being the output text for the built version of the file, and an optional =logDetails= property that can be used to specify any extra log information to summarize or describe how the file was built.
|
328 |
+
|
329 |
+
When a file is built, the output of the function specified by the =fileBuilder= parameter will be written as a file of the name determined by the =targetFilenameCreator= function, into a folder of the path determined by the =targetFolderPathCreator= function.
|
330 |
+
|
331 |
+
rootFolderPath
|
332 |
+
A string, specifying the path of a folder to serve as the root folder from which to start building files.
|
333 |
+
|
334 |
+
alwaysBuild
|
335 |
+
An optional boolean, indicating whether or not eligible files should always be built, or whether the need to build should be determined automatically.
|
336 |
+
|
337 |
+
For any file within the folder hierarchy that would be processed by the =Uize.Build.Util.buildFiles= method (given the configuration of this method by all its parameter values), a decision to build the file will normally be made automatically by this method, based upon the target file either not existing or having an older modified date than the source file. This is the behavior for the optional =alwaysBuild= parameter's default value of =false=. When the value =true= is specified, then the file will always be built, even if it is considered to have been previously built and up-to-date.
|
338 |
+
|
339 |
+
doNotEnter
|
340 |
+
An optional array or regular expression, specifying a folder (or folders) that should not be entered when recursing through the folder hierarchy.
|
341 |
+
|
342 |
+
Any folders specified by this parameter will terminate recursion at that point in the folder tree, and any folders contained inside these dead end folders will not be processed. If a regular expression is specified for this parameter, then this regular expression will be tested against the folder name currently being processed by the =Uize.Build.Util.buildFiles= method. If the regular expression matches, then the method will not enter the folder.
|
343 |
+
|
344 |
+
This parameter is useful for build scripts that should ignore files generated by the build script (or other build scripts) and that are stored in a special build directory. Your site project may also contain a folder of build scripts, and you may not wish any build script using the =Uize.Build.Util.buildFiles= method to process any of the files contained therein.
|
345 |
+
|
346 |
+
logFilePath
|
347 |
+
An optional string, specifying the filename of a file within the same folder as the build script that should be used for writing out the log of the build process.
|
348 |
+
|
349 |
+
Basic information is automatically placed into the log file by the =Uize.Build.Util.buildFiles= method, but additional information for each built file can be added by returning text for the optional =logDetails= property of your =fileBuilder= function's return object.
|
350 |
+
|
351 |
+
NOTES
|
352 |
+
- If no =logFilePath= parameter is specified, or if it's value is an empty string, =null=, or =undefined=, then the filename for the log file will be derived from the filename of the build script, with the ".js" file extension replaced with the extension ".log".
|
353 |
+
*/
|
354 |
+
};
|
355 |
+
|
356 |
+
return _package;
|
357 |
+
}
|
358 |
+
});
|
359 |
+
|
skin/frontend/default/customproduct/js/Uize.Build.js
ADDED
@@ -0,0 +1,28 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Build Namespace
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Namespace
|
14 |
+
importance: 1
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 100
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Build= module defines a namespace for the various build scripts offered by the UIZE JavaScript Framework.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
*/
|
26 |
+
|
27 |
+
Uize.module ({name:'Uize.Build'});
|
28 |
+
|
skin/frontend/default/customproduct/js/Uize.Class.Value.js
ADDED
@@ -0,0 +1,44 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Class.Value Class
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Class
|
14 |
+
importance: 1
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Class.Value= class is a simple class that merely implements the `value interface` (ie. it registers a =value= state property).
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
Methods of a number of different UIZE modules implement special handling for parameter values that are instances of =Uize.Class= subclasses that support the `value interface`. The =Uize.Class.Value= class is intended primarily for use in various unit tests that test the behavior of such methods.
|
27 |
+
*/
|
28 |
+
|
29 |
+
Uize.module ({
|
30 |
+
name:'Uize.Class.Value',
|
31 |
+
superclass:'Uize.Class',
|
32 |
+
builder:function (_superclass) {
|
33 |
+
/*** Class Constructor ***/
|
34 |
+
var _class = _superclass.subclass ();
|
35 |
+
|
36 |
+
/*** Register Properties ***/
|
37 |
+
_class.registerProperties ({
|
38 |
+
_value:'value'
|
39 |
+
});
|
40 |
+
|
41 |
+
return _class;
|
42 |
+
}
|
43 |
+
});
|
44 |
+
|
skin/frontend/default/customproduct/js/Uize.Class.js
ADDED
@@ -0,0 +1,2288 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Class Base Class
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2003-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Class
|
14 |
+
importance: 10
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 40
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Class= module defines a base class from which many of the classes in the UIZE JavaScript Framework inherit.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
Key Features
|
27 |
+
Event System
|
28 |
+
The =Uize.Class= module implements a powerful and versatile event system, which can be used for application events outside the context of browser DOM events.
|
29 |
+
|
30 |
+
Event System Methods
|
31 |
+
The `event system` of the =Uize.Class= module is exposed through the following methods...
|
32 |
+
|
33 |
+
- =fire= - fires an event on an instance
|
34 |
+
- =unwire= - unwires handlers for one or more events on an instance
|
35 |
+
- =wire= - wires handlers for one or more events on an instance
|
36 |
+
- =Uize.Class.fire= - fires an event on a class
|
37 |
+
- =Uize.Class.unwire= - unwires handlers for one or more events on a class
|
38 |
+
- =Uize.Class.wire= - wires handlers for one or more events on a class
|
39 |
+
|
40 |
+
For an in-depth discussion of events, consult the [[../explainers/javascript-event-system.html][JavaScript Event System]] explainer.
|
41 |
+
|
42 |
+
Condition System
|
43 |
+
The =Uize.Class= module implements a condition system in the form of state properties combined with convenience methods that allow state properties to be treated semantically as conditions.
|
44 |
+
|
45 |
+
Condition System Methods
|
46 |
+
The `condition system` of the =Uize.Class= module is exposed through the following methods...
|
47 |
+
|
48 |
+
- =is= - returns whether or not a condition has been met
|
49 |
+
- =once= - registers code that is to be executed once a condition has been met
|
50 |
+
- =met= - sets a condition as having been met
|
51 |
+
- =unmet= - sets a condition as having not been met / no longer being met
|
52 |
+
|
53 |
+
The "no new" Mechanism
|
54 |
+
The JavaScript =new= operator is optional when creating instances of =Uize.Class= subclasses, and you can make the =new= operator optional for your own object constructors using the newly added =Uize.noNew= static method.
|
55 |
+
|
56 |
+
Creating Instances of Uize Classes
|
57 |
+
Because the =Uize.Class= base class utilizes `the "no new" mechanism`, one can create instances of any =Uize.Class= subclass either using the =new= operator or not.
|
58 |
+
|
59 |
+
EXAMPLE
|
60 |
+
................................................................................
|
61 |
+
// this works
|
62 |
+
var mySlider1 = new Uize.Widget.Bar.Slider ({minValue:0,maxValue:100,value:50});
|
63 |
+
|
64 |
+
// Look ma, no "new"!!!
|
65 |
+
var mySlider2 = Uize.Widget.Bar.Slider ({minValue:0,maxValue:100,value:50});
|
66 |
+
................................................................................
|
67 |
+
|
68 |
+
All Uize Classes Get the Benefit
|
69 |
+
Because of the way in which `the "no new" mechanism` is implemented in the =Uize.Class= base class, any class that is derived from a =Uize.Class= base class using the =subclass= method gets the same benefit, including classes that you create for your own applications.
|
70 |
+
|
71 |
+
This means, for example, that any widget class you create by subclassing the =Uize.Widget= class will get the same benefit. Consider the following example...
|
72 |
+
|
73 |
+
EXAMPLE
|
74 |
+
..................................................
|
75 |
+
// we create a widget class
|
76 |
+
var MyWidgetClass = Uize.Widget.subclass ();
|
77 |
+
|
78 |
+
// this works
|
79 |
+
var myWidgetClassInstance1 = new MyWidgetClass ();
|
80 |
+
|
81 |
+
// Look ma, no "new"!!!
|
82 |
+
var myWidgetClassInstance2 = MyWidgetClass ();
|
83 |
+
..................................................
|
84 |
+
|
85 |
+
Applies for Other Uize Objects
|
86 |
+
`The "no new" mechanism`, that is implemented in the =Uize.noNew= static method, has been applied to various other =Uize= objects (such as the =Uize.Color= object) that are lightweight objects rather than full =Uize.Class= subclasses.
|
87 |
+
|
88 |
+
So, for example, one can create instances of the =Uize.Color= object or the =Uize.String.Builder= object without needing to use the =new= operator. Consider the following example...
|
89 |
+
|
90 |
+
EXAMPLE
|
91 |
+
.........................................
|
92 |
+
// this works
|
93 |
+
var fuchsia = new Uize.Color ('#ff0fff');
|
94 |
+
|
95 |
+
// Look ma, no "new"!!!
|
96 |
+
var olive = Uize.Color ('#808000');
|
97 |
+
.........................................
|
98 |
+
|
99 |
+
Using the Uize.noNew Method
|
100 |
+
An object constructor that supports `the "no new" mechanism` can easily be created using the =Uize.noNew= static method.
|
101 |
+
|
102 |
+
In cases where you're creating =Uize.Class= subclasses, you don't need to worry about the =Uize.noNew= method because `the "no new" mechanism` is built right into the =Uize.Class= base class, so `all Uize classes get the benefit`. However, in cases where you're defining your own lightweight objects, you can use the =Uize.noNew= method to create an object constructor where the =new= operator is optional. Consider the following example...
|
103 |
+
|
104 |
+
EXAMPLE
|
105 |
+
............................................................
|
106 |
+
// define the Food object
|
107 |
+
var Food = Uize.noNew (
|
108 |
+
function (name,type) {
|
109 |
+
this.name = name;
|
110 |
+
this.type = type;
|
111 |
+
}
|
112 |
+
);
|
113 |
+
|
114 |
+
// create an instance of Food using the new operator
|
115 |
+
var apple = new Food ('apple','fruit');
|
116 |
+
alert (apple.type); // alerts the text "fruit"
|
117 |
+
|
118 |
+
// create an instance of Food without using the new operator
|
119 |
+
var rice = Food ('rice','grain');
|
120 |
+
alert (rice.type); // alerts the text "grain"
|
121 |
+
............................................................
|
122 |
+
|
123 |
+
What you'll notice from the above example is that the =Uize.noNew= method is quite simple - it takes a single parameter, which is the constructor function that initializes the new instance. This means that you can easily take an existing object constructor function and upgrade it to one that supports `the "no new" mechanism` by wrapping it inside a call to the =Uize.noNew= method, which then returns a wrapper constructor that becomes your new object constructor. Consider the following before-and-after example...
|
124 |
+
|
125 |
+
BEFORE
|
126 |
+
..............................................
|
127 |
+
// must always use "new" with this constructor
|
128 |
+
function Food (name,type) {
|
129 |
+
this.name = name;
|
130 |
+
this.type = type;
|
131 |
+
}
|
132 |
+
..............................................
|
133 |
+
|
134 |
+
AFTER
|
135 |
+
..........................................
|
136 |
+
// "new" is optional with this constructor
|
137 |
+
var Food = Uize.noNew (
|
138 |
+
function (name,type) {
|
139 |
+
this.name = name;
|
140 |
+
this.type = type;
|
141 |
+
}
|
142 |
+
);
|
143 |
+
..........................................
|
144 |
+
|
145 |
+
Notice that you need to assign the result of the =Uize.noNew= method call, and so your original constructor function no longer should have the name.
|
146 |
+
*/
|
147 |
+
|
148 |
+
Uize.module ({
|
149 |
+
name:'Uize.Class',
|
150 |
+
builder:function (_superclass) {
|
151 |
+
/*** Variables for Scruncher Optimization ***/
|
152 |
+
var
|
153 |
+
_undefined,
|
154 |
+
_typeString = 'string',
|
155 |
+
_typeObject = 'object',
|
156 |
+
|
157 |
+
/*** references to utility methods of Uize ***/
|
158 |
+
_Uize = Uize,
|
159 |
+
_clone = _Uize.clone,
|
160 |
+
_copyInto = _Uize.copyInto,
|
161 |
+
_forEach = _Uize.forEach,
|
162 |
+
_map = _Uize.map,
|
163 |
+
_lookup = _Uize.lookup,
|
164 |
+
_getClass = _Uize.getClass,
|
165 |
+
_getGuid = _Uize.getGuid,
|
166 |
+
_globalEval = _Uize.globalEval,
|
167 |
+
_isArray = _Uize.isArray,
|
168 |
+
_isFunction = _Uize.isFunction,
|
169 |
+
_isInstance = _Uize.isInstance,
|
170 |
+
_isObject = _Uize.isObject,
|
171 |
+
_noNew = _Uize.noNew,
|
172 |
+
_pairUp = _Uize.pairUp
|
173 |
+
;
|
174 |
+
|
175 |
+
/*** General Variables ***/
|
176 |
+
var
|
177 |
+
_sacredEmptyArray = [],
|
178 |
+
_sacredEmptyObject = {}
|
179 |
+
;
|
180 |
+
|
181 |
+
/*** Class Constructor ***/
|
182 |
+
var
|
183 |
+
_class = _createSubclass (
|
184 |
+
function () {},
|
185 |
+
/*** alphastructor ***/
|
186 |
+
function () {
|
187 |
+
/*** Public Instance Properties ***/
|
188 |
+
this.instanceId = _getGuid ();
|
189 |
+
/*?
|
190 |
+
Instance Properties
|
191 |
+
instanceId
|
192 |
+
An automatically generated name, that can be used as a means of identifying the specific instance in other code.
|
193 |
+
|
194 |
+
When designing JavaScript classes, it is sometimes necessary in the class's implementation to set intervals, timeouts, or the event handlers of HTML nodes that make up an instance's user interface, so that they execute methods of the instance. Sometimes this must be done by generating JavaScript code that is to be interpreted. This generated code must, therefore, be able to reference its instance using a global identifier, because the code will be executed in a global context.
|
195 |
+
|
196 |
+
If the constructor of your class uses the automatically generated value of an instance's =instanceId= property to assign a global reference to the instance, with a statement like =window [_this.instanceId] = _this=, then the =instanceId= property can be used when generating JavaScript code that is to execute methods on the instance. Consider the following example...
|
197 |
+
|
198 |
+
..................................................................
|
199 |
+
MyClass.prototype.click = function () {
|
200 |
+
// do something when the button is clicked
|
201 |
+
};
|
202 |
+
|
203 |
+
MyClass.prototype.insertButton = function () {
|
204 |
+
document.writeln (
|
205 |
+
'<input ' +
|
206 |
+
'type="button" ' +
|
207 |
+
'onclick="' + this.instanceId + '.click (); return false"' +
|
208 |
+
'/>'
|
209 |
+
);
|
210 |
+
};
|
211 |
+
..................................................................
|
212 |
+
|
213 |
+
In the above example, we see a segment of the implementation for a =Uize.Class= subclass named =MyClass=. The =insertButton= instance method is writing HTML into the document, and the =input= tag that is created has an =onclick= attribute that registers an event handler that will execute the =click= method of that instance when clicked. That's because the global identifier by the name stored in the =instanceId= property is a reference to the instance.
|
214 |
+
|
215 |
+
NOTES
|
216 |
+
- the =instanceId= property's value is guaranteed to be unique for all instances of all =Uize.Class= subclasses in a document, but not across frames in a frameset, or across multiple pages in a Web site
|
217 |
+
*/
|
218 |
+
},
|
219 |
+
/*** omegastructor ***/
|
220 |
+
function (_properties) {
|
221 |
+
/*** Initialize Properties ***/
|
222 |
+
_properties || (_properties = _sacredEmptyObject);
|
223 |
+
var
|
224 |
+
_propertiesForSet = {},
|
225 |
+
_instancePropertyDefaults = this.Class._instancePropertyDefaults,
|
226 |
+
_property,
|
227 |
+
_propertyDefault
|
228 |
+
;
|
229 |
+
for (_property in _instancePropertyDefaults) {
|
230 |
+
if (_property in _properties)
|
231 |
+
_propertiesForSet [_property] = _properties [_property];
|
232 |
+
else if ((_propertyDefault = _instancePropertyDefaults [_property]) !== _undefined)
|
233 |
+
_propertiesForSet [_property] = _propertyDefault
|
234 |
+
;
|
235 |
+
}
|
236 |
+
for (_property in _properties)
|
237 |
+
_property in _propertiesForSet || (_propertiesForSet [_property] = _properties [_property])
|
238 |
+
;
|
239 |
+
this.set (_propertiesForSet);
|
240 |
+
}
|
241 |
+
),
|
242 |
+
_classPrototype = _class.prototype,
|
243 |
+
_classNonInheritableStatics = _class.nonInheritableStatics
|
244 |
+
;
|
245 |
+
|
246 |
+
/*** Property System Support Code ***/
|
247 |
+
function _getPropertyProfile (_this,_propertyPublicOrPrivateName) {
|
248 |
+
var _class = _getClass (_this);
|
249 |
+
return (
|
250 |
+
_class._propertyProfilesByPublicNames [_propertyPublicOrPrivateName] ||
|
251 |
+
_class._propertyProfilesByPrivateNames [_propertyPublicOrPrivateName]
|
252 |
+
);
|
253 |
+
}
|
254 |
+
|
255 |
+
function _getPropertyPrivateName (_this,_propertyPublicOrPrivateName) {
|
256 |
+
var _propertyProfile = _getPropertyProfile (_this,_propertyPublicOrPrivateName);
|
257 |
+
return _propertyProfile ? _propertyProfile._privateName : _propertyPublicOrPrivateName;
|
258 |
+
}
|
259 |
+
|
260 |
+
/*** Private Instance-Static Methods ***/
|
261 |
+
/*** Event System Methods ***/
|
262 |
+
_class._abstractEventName = _classPrototype._abstractEventName = function (_eventName,_managementFunction) {
|
263 |
+
if (_eventName.charCodeAt (0) == 67 && !_eventName.indexOf ('Changed.')) {
|
264 |
+
var
|
265 |
+
_this = this,
|
266 |
+
_propertyPublicName = _eventName.slice (8),
|
267 |
+
_propertyProfile = _getPropertyProfile (_this,_propertyPublicName)
|
268 |
+
;
|
269 |
+
if (_propertyProfile && _propertyPublicName != _propertyProfile._publicName)
|
270 |
+
// use the canonical public name, since a pseudonym could have been specified
|
271 |
+
_eventName = 'Changed.' + (_propertyPublicName = _propertyProfile._publicName)
|
272 |
+
;
|
273 |
+
_managementFunction (_eventName);
|
274 |
+
(_this._hasChangedHandlers || (_this._hasChangedHandlers = {})) [_propertyPublicName] =
|
275 |
+
_this._eventHandlers && _this._eventHandlers [_eventName]
|
276 |
+
;
|
277 |
+
} else {
|
278 |
+
_managementFunction (_eventName);
|
279 |
+
}
|
280 |
+
};
|
281 |
+
|
282 |
+
/*** Public Instance-Static Methods ***/
|
283 |
+
/*** Event System Methods ***/
|
284 |
+
_class.wire = _classPrototype.wire = function (_eventNameOrEventsMap,_handler) {
|
285 |
+
var _this = this;
|
286 |
+
if (arguments.length == 2) {
|
287 |
+
_this._abstractEventName (
|
288 |
+
_eventNameOrEventsMap,
|
289 |
+
function (_eventName) {
|
290 |
+
var _eventHandlers = _this._eventHandlers || (_this._eventHandlers = {});
|
291 |
+
(_eventHandlers [_eventName] || (_eventHandlers [_eventName] = [])).push (
|
292 |
+
{
|
293 |
+
_eventName:_eventName,
|
294 |
+
_handler:
|
295 |
+
_isFunction (_handler)
|
296 |
+
? _handler
|
297 |
+
: typeof _handler == _typeString
|
298 |
+
? new Function (_handler)
|
299 |
+
: function (_event) {_handler.fire (_event)},
|
300 |
+
_originalHandler:_handler
|
301 |
+
}
|
302 |
+
);
|
303 |
+
}
|
304 |
+
);
|
305 |
+
} else if (_isObject (_eventNameOrEventsMap)) {
|
306 |
+
for (var _eventName in _eventNameOrEventsMap)
|
307 |
+
this.wire (_eventName,_eventNameOrEventsMap [_eventName])
|
308 |
+
;
|
309 |
+
}
|
310 |
+
/*?
|
311 |
+
Instance Methods
|
312 |
+
wire
|
313 |
+
Lets you wire a handler for a specific instance event, or handlers for multiple instance events.
|
314 |
+
|
315 |
+
SYNTAX
|
316 |
+
........................................................
|
317 |
+
myInstance.wire (eventNameSTR,eventHandlerSTRorFNorOBJ);
|
318 |
+
........................................................
|
319 |
+
|
320 |
+
Event handlers registered using this method will handle events fired for the instance using the =fire= instance method, and not those events fired using the =Uize.Class.fire= static method. A =Uize.Class= subclass may not provide any instance events, so you should consult the reference documentation for a class to learn more about its suite of events. Handlers specified by the =eventHandlerSTRorFNorOBJ= parameter may be of string, function, or object type.
|
321 |
+
|
322 |
+
EXAMPLE
|
323 |
+
...........................................................
|
324 |
+
mySlider.wire (
|
325 |
+
'Changed.value',
|
326 |
+
function () {Uize.Node.setValue ('valueField',mySlider)}
|
327 |
+
);
|
328 |
+
...........................................................
|
329 |
+
|
330 |
+
VARIATION
|
331 |
+
.............................................
|
332 |
+
myInstance.wire (eventNamesToHandlersMapOBJ);
|
333 |
+
.............................................
|
334 |
+
|
335 |
+
When only a single =eventNamesToHandlersMapOBJ= parameter is specified, then event handlers for multiple events can be specified using an object hash. This variation is provided as a convenience and has the effect of iteratively calling the =wire= instance method for each event-name-to-handler mapping in the =eventNamesToHandlersMapOBJ= object.
|
336 |
+
|
337 |
+
EXAMPLE
|
338 |
+
...................................................................................
|
339 |
+
mySlider.wire ({
|
340 |
+
'Changed.value':
|
341 |
+
function () {Uize.Node.setValue ('valueField',mySlider)},
|
342 |
+
'Changed.maxValue':
|
343 |
+
function () {Uize.Node.setValue ('maxValueField',mySlider.get ('maxValue'))},
|
344 |
+
'Changed.minValue':
|
345 |
+
function () {Uize.Node.setValue ('minValueField',mySlider.get ('minValue'))}
|
346 |
+
});
|
347 |
+
...................................................................................
|
348 |
+
|
349 |
+
SPECIAL VALUES
|
350 |
+
- the string value ="*"= acts as a wildcard when specified for the =eventNameSTR= parameter, meaning that the specified handler should be executed for all events of the instance
|
351 |
+
|
352 |
+
NOTES
|
353 |
+
- see the related =fire= and =unwire= instance methods
|
354 |
+
- compare to the =Uize.Class.fire=, =Uize.Class.wire=, and =Uize.Class.unwire= static methods
|
355 |
+
|
356 |
+
Static Methods
|
357 |
+
Uize.Class.wire
|
358 |
+
Lets you wire a handler for a static event of the class, or handlers for multiple static events.
|
359 |
+
|
360 |
+
SYNTAX
|
361 |
+
.....................................................
|
362 |
+
MyClass.wire (eventNameSTR,eventHandlerSTRorFNorOBJ);
|
363 |
+
.....................................................
|
364 |
+
|
365 |
+
Event handlers registered using this method will handle events fired for the class using the =Uize.Class.fire= static method, and not those events fired using the =fire= instance method. A =Uize.Class= subclass may not provide any static events, so you should consult the reference documentation for a class to learn more about its suite of events. Handlers specified by the =eventHandlerSTRorFNorOBJ= parameter may be of string, function, or object type.
|
366 |
+
|
367 |
+
VARIATION
|
368 |
+
..........................................
|
369 |
+
MyClass.wire (eventNamesToHandlersMapOBJ);
|
370 |
+
..........................................
|
371 |
+
|
372 |
+
When only a single =eventNamesToHandlersMapOBJ= parameter is specified, then event handlers for multiple events can be specified using an object hash. This variation is provided as a convenience and has the effect of iteratively calling the =Uize.Class.wire= static method for each event-name-to-handler mapping in the =eventNamesToHandlersMapOBJ= object.
|
373 |
+
|
374 |
+
SPECIAL VALUES
|
375 |
+
- the string value ="*"= acts as a wildcard when specified for the =eventNameSTR= parameter, meaning that the specified handler should be executed for all events of the class
|
376 |
+
|
377 |
+
NOTES
|
378 |
+
- see the related =Uize.Class.fire= and =Uize.Class.unwire= static methods
|
379 |
+
- compare to the =fire=, =wire=, and =unwire= instance methods
|
380 |
+
|
381 |
+
Parameters
|
382 |
+
eventHandlerSTRorFNorOBJ
|
383 |
+
All of the instance and static methods for adding and removing event handlers allow handlers to be specified in a number of different ways.
|
384 |
+
|
385 |
+
Function Type Handlers
|
386 |
+
By far the most common type of handler used when wiring event handlers is a function reference.
|
387 |
+
|
388 |
+
A function registered as a handler for an event should expect to receive one parameter, being a reference to the event object that is associated to the event.
|
389 |
+
|
390 |
+
String Type Handlers
|
391 |
+
When a string value is specified for the =eventHandlerSTRorFNorOBJ= parameter, a function object will be constructed from that string for the purpose of handling the event.
|
392 |
+
|
393 |
+
One limitation of this handler type is that, unlike `Function Type Handlers`, a code string specified by the =eventHandlerSTRorFNorOBJ= parameter cannot reference the event object.
|
394 |
+
|
395 |
+
Object Type Handlers
|
396 |
+
When a reference to a =Uize.Class= subclass or an instance of a =Uize.Class= subclass is specified for the =eventHandlerSTRorFNorOBJ= parameter, then the event for which the handler is registered will be fired on that instance or class.
|
397 |
+
|
398 |
+
This facility provides a means for "relaying" instance or class events to another instance or class.
|
399 |
+
|
400 |
+
EXAMPLE
|
401 |
+
.....................................................
|
402 |
+
myWidget.children.someButton.wire ('Click',myWidget);
|
403 |
+
.....................................................
|
404 |
+
|
405 |
+
In the above example, a handler is being registered for the ='Click'= event of a button (an instance of the =Uize.Widget.Button= class) that is a child widget of =myWidget=. By specifying =myWidget= as the handler for the =Click= event, that event will get relayed to =myWidget=. This means that other code can now register handlers on the =Click= event for =myWidget=, and those handlers will handle the =Click= event being relayed from the button widget.
|
406 |
+
|
407 |
+
Object handlers added in this way can be removed by using the =unwire= instance method and the =Uize.Class.unwire= static method, just as with any other type of handler, as in...
|
408 |
+
|
409 |
+
.......................................................
|
410 |
+
myWidget.children.someButton.unwire ('Click',myWidget);
|
411 |
+
.......................................................
|
412 |
+
|
413 |
+
Value for Removing Must Match Value Used for Adding
|
414 |
+
However a handler is specified when wiring an event, that is how it must be specified in order to unwire the event.
|
415 |
+
|
416 |
+
If you specified a function reference as the handler when wiring an event, then you must specify that same, identical function reference in order to unwire that event. If you specified a code string as the handler, then you must specify the exact same code string in order to unwire that event. If you specified a reference to a =Uize.Class= subclass or an instance of a =Uize.Class= subclass as the handler when wiring an event, then you must specify the exact same object reference in order to unwire the event.
|
417 |
+
|
418 |
+
eventNamesToHandlersMapOBJ
|
419 |
+
An object, specifying handlers for multiple events using event-name-to-handler mappings, where the key of each property is an event name and the value of each property is an event's corresponding handler.
|
420 |
+
|
421 |
+
The contents of this object should be of the form...
|
422 |
+
|
423 |
+
........................................
|
424 |
+
{
|
425 |
+
event1Name:event1HandlerSTRorFNorOBJ,
|
426 |
+
event2Name:event2HandlerSTRorFNorOBJ,
|
427 |
+
...
|
428 |
+
eventNName:eventNHandlerSTRorFNorOBJ
|
429 |
+
}
|
430 |
+
........................................
|
431 |
+
|
432 |
+
The value for each property in this object should conform to the =eventHandlerSTRorFNorOBJ= parameter type.
|
433 |
+
*/
|
434 |
+
};
|
435 |
+
|
436 |
+
_class.fire = _classPrototype.fire = function (_event) {
|
437 |
+
/* NOTES
|
438 |
+
- this code is deliberately optimized for performance and not code size, since event firing is a mechanism that is heavily utilized. This will explain some patterns here that may seem slightly out of character, with seemingly redundant code or a lack of typical factoring out.
|
439 |
+
*/
|
440 |
+
if (typeof _event != _typeObject) _event = {name:_event};
|
441 |
+
var
|
442 |
+
_this = this,
|
443 |
+
_eventHandlers = _this._eventHandlers
|
444 |
+
;
|
445 |
+
if (_eventHandlers) {
|
446 |
+
var
|
447 |
+
_handlersForThisEvent = _eventHandlers [_event.name],
|
448 |
+
_handlersForAnyEvent = _eventHandlers ['*']
|
449 |
+
;
|
450 |
+
if (_handlersForThisEvent || _handlersForAnyEvent) {
|
451 |
+
_event.source || (_event.source = _this);
|
452 |
+
var
|
453 |
+
_handlers = _handlersForAnyEvent && _handlersForThisEvent
|
454 |
+
? _handlersForAnyEvent.concat (_handlersForThisEvent)
|
455 |
+
: _handlersForAnyEvent || _handlersForThisEvent
|
456 |
+
,
|
457 |
+
_totalHandlers = _handlers.length
|
458 |
+
;
|
459 |
+
if (_totalHandlers == 1) {
|
460 |
+
_handlers [0]._handler (_event);
|
461 |
+
} else if (_totalHandlers == 2) {
|
462 |
+
/* NOTE:
|
463 |
+
Since we make a copy of the handlers array in the case of multiple handlers (in order to avoid issues where the handlers array may be modified by the handlers themselves), this optimization for two handlers catches most cases of multiple handlers in a complex application. This avoids copying an array and also the overhead of an iterator.
|
464 |
+
*/
|
465 |
+
var
|
466 |
+
_handler0 = _handlers [0]._handler,
|
467 |
+
_handler1 = _handlers [1]._handler
|
468 |
+
;
|
469 |
+
_handler0 (_event);
|
470 |
+
_handler1 (_event);
|
471 |
+
} else {
|
472 |
+
if (!_handlersForAnyEvent || !_handlersForThisEvent)
|
473 |
+
_handlers = _handlers.concat ()
|
474 |
+
;
|
475 |
+
/* NOTE:
|
476 |
+
When executing multiple handlers, it is necessary to make a copy of the handlers array, since it is possible that one of the handlers might execute code that affects the handlers array (eg. by using the removeHandler method).
|
477 |
+
|
478 |
+
What this means is that when an event is fired, all the handlers registered for that event at the time that it fires will be executed. Event handlers for that event that are removed by one of its handlers will still be executed, and event handlers for that event that are added by one of its handlers will not be executed.
|
479 |
+
*/
|
480 |
+
for (var _handlerNo = -1; ++_handlerNo < _totalHandlers;)
|
481 |
+
_handlers [_handlerNo]._handler (_event)
|
482 |
+
;
|
483 |
+
}
|
484 |
+
}
|
485 |
+
}
|
486 |
+
if (_event.bubble && _this.parent && _isInstance (_this)) {
|
487 |
+
_event.source || (_event.source = _this);
|
488 |
+
_this.parent.fire (_event);
|
489 |
+
}
|
490 |
+
return _event;
|
491 |
+
/*?
|
492 |
+
Instance Methods
|
493 |
+
fire
|
494 |
+
Lets you fire an event for an instance of the class.
|
495 |
+
|
496 |
+
SYNTAX
|
497 |
+
..........................................
|
498 |
+
eventOBJ = myInstance.fire (eventNameSTR);
|
499 |
+
..........................................
|
500 |
+
|
501 |
+
VARIATION
|
502 |
+
......................................
|
503 |
+
eventOBJ = myInstance.fire (eventOBJ);
|
504 |
+
......................................
|
505 |
+
|
506 |
+
When an object is specified instead of a string value, then extra event properties can be bundled with the event and will then be available to all handlers that are executed. When using this form, the =eventOBJ= object must have a =name= property that specifies the name of the event being fired.
|
507 |
+
|
508 |
+
NOTES
|
509 |
+
- see the related =wire= and =unwire= instance methods
|
510 |
+
- compare to the =Uize.Class.fire=, =Uize.Class.wire=, and =Uize.Class.unwire= static methods
|
511 |
+
|
512 |
+
Static Methods
|
513 |
+
Uize.Class.fire
|
514 |
+
Lets you fire a static event for the class.
|
515 |
+
|
516 |
+
SYNTAX
|
517 |
+
.......................................
|
518 |
+
eventOBJ = MyClass.fire (eventNameSTR);
|
519 |
+
.......................................
|
520 |
+
|
521 |
+
VARIATION
|
522 |
+
........................
|
523 |
+
MyClass.fire (eventOBJ);
|
524 |
+
........................
|
525 |
+
|
526 |
+
When an object is specified instead of a string value, then extra event properties can be bundled with the event and will then be available to all handlers that are executed. When using this form, the =eventOBJ= object must have a =name= property that specifies the name of the event being fired.
|
527 |
+
|
528 |
+
NOTES
|
529 |
+
- see the related =Uize.Class.wire= and =Uize.Class.unwire= static methods
|
530 |
+
- compare to the =fire=, =wire=, and =unwire= instance methods
|
531 |
+
*/
|
532 |
+
};
|
533 |
+
|
534 |
+
_class.unwire = _classPrototype.unwire = function (_eventNameOrEventsMap,_handler) {
|
535 |
+
var
|
536 |
+
_this = this,
|
537 |
+
_eventHandlers = _this._eventHandlers
|
538 |
+
;
|
539 |
+
if (_eventHandlers) {
|
540 |
+
if (_isObject (_eventNameOrEventsMap)) {
|
541 |
+
for (var _eventName in _eventNameOrEventsMap)
|
542 |
+
_this.unwire (_eventName,_eventNameOrEventsMap [_eventName])
|
543 |
+
;
|
544 |
+
} else {
|
545 |
+
_this._abstractEventName (
|
546 |
+
_eventNameOrEventsMap,
|
547 |
+
function (_eventName) {
|
548 |
+
var _handlersForEventName = _eventHandlers [_eventName];
|
549 |
+
if (_handlersForEventName) {
|
550 |
+
if (_handler) {
|
551 |
+
/* TO DO:
|
552 |
+
this is a candidate for factoring out as a generally useful array manipulation method: removeAllOfValue
|
553 |
+
*/
|
554 |
+
for (var _handlerNo = _handlersForEventName.length; --_handlerNo >= 0;)
|
555 |
+
_handlersForEventName [_handlerNo]._originalHandler == _handler && _handlersForEventName.splice (_handlerNo,1)
|
556 |
+
;
|
557 |
+
}
|
558 |
+
(_handler && _handlersForEventName.length) || delete _eventHandlers [_eventName];
|
559 |
+
}
|
560 |
+
}
|
561 |
+
);
|
562 |
+
}
|
563 |
+
}
|
564 |
+
/*?
|
565 |
+
Instance Methods
|
566 |
+
unwire
|
567 |
+
Lets you remove a handler previously wired to an instance event, or handlers wired for multiple instance events.
|
568 |
+
|
569 |
+
SYNTAX
|
570 |
+
..........................................................
|
571 |
+
myInstance.unwire (eventNameSTR,eventHandlerSTRorFNorOBJ);
|
572 |
+
..........................................................
|
573 |
+
|
574 |
+
VARIATION 1
|
575 |
+
.................................
|
576 |
+
myInstance.unwire (eventNameSTR);
|
577 |
+
.................................
|
578 |
+
|
579 |
+
When no =eventHandlerSTRorFNorOBJ= parameter is specified, then all handlers registered for the event specified in the =eventNameSTR= parameter will be removed.
|
580 |
+
|
581 |
+
VARIATION 2
|
582 |
+
...............................................
|
583 |
+
myInstance.unwire (eventNamesToHandlersMapOBJ);
|
584 |
+
...............................................
|
585 |
+
|
586 |
+
When only a single =eventNamesToHandlersMapOBJ= parameter is specified, then event handlers for multiple events can be specified using an object hash. This variation is provided as a convenience and has the effect of iteratively calling the =unwire= instance method for each event-name-to-handler mapping in the =eventNamesToHandlersMapOBJ= object.
|
587 |
+
|
588 |
+
NOTES
|
589 |
+
- see the related =fire= and =wire= instance methods
|
590 |
+
- compare to the =Uize.Class.fire=, =Uize.Class.wire=, and =Uize.Class.unwire= static methods
|
591 |
+
|
592 |
+
Static Methods
|
593 |
+
Uize.Class.unwire
|
594 |
+
Lets you remove a handler previously wired to a static event, or handlers wired for multiple static events.
|
595 |
+
|
596 |
+
SYNTAX
|
597 |
+
.......................................................
|
598 |
+
MyClass.unwire (eventNameSTR,eventHandlerSTRorFNorOBJ);
|
599 |
+
.......................................................
|
600 |
+
|
601 |
+
VARIATION 1
|
602 |
+
..............................
|
603 |
+
MyClass.unwire (eventNameSTR);
|
604 |
+
..............................
|
605 |
+
|
606 |
+
When no =eventHandlerSTRorFNorOBJ= parameter is specified, then all handlers registered for the event specified in the =eventNameSTR= parameter will be removed.
|
607 |
+
|
608 |
+
VARIATION 2
|
609 |
+
............................................
|
610 |
+
MyClass.unwire (eventNamesToHandlersMapOBJ);
|
611 |
+
............................................
|
612 |
+
|
613 |
+
When only a single =eventNamesToHandlersMapOBJ= parameter is specified, then event handlers for multiple events can be specified using an object hash. This variation is provided as a convenience and has the effect of iteratively calling the =Uize.Class.unwire= static method for each event-name-to-handler mapping in the =eventNamesToHandlersMapOBJ= object.
|
614 |
+
|
615 |
+
NOTES
|
616 |
+
- see the related =Uize.Class.fire= and =Uize.Class.wire= static methods
|
617 |
+
- compare to the =fire=, =wire=, and =unwire= instance methods
|
618 |
+
*/
|
619 |
+
};
|
620 |
+
|
621 |
+
|
622 |
+
var _newFunction = new Function (
|
623 |
+
'a', // arguments
|
624 |
+
'b', // body
|
625 |
+
'var f; return eval ("f = function (" + a.join (",") + ") {" + b + "}")'
|
626 |
+
);
|
627 |
+
|
628 |
+
var _derivationCache = {};
|
629 |
+
function _resolveDerivation (_derivation) {
|
630 |
+
/* NOTE: this code will eventually be used also for derived properties */
|
631 |
+
var
|
632 |
+
_derivationCacheKey = _derivation + '',
|
633 |
+
_resolvedDerivation = _derivationCache [_derivationCacheKey]
|
634 |
+
;
|
635 |
+
function _getDeterminantsFromListStr (_determinantsStr) {
|
636 |
+
return _determinantsStr.replace (/\s+/g,'').split (',');
|
637 |
+
}
|
638 |
+
if (!_resolvedDerivation) {
|
639 |
+
var
|
640 |
+
_determinants,
|
641 |
+
_determiner
|
642 |
+
;
|
643 |
+
if (Uize.isFunction (_derivation)) {
|
644 |
+
_determinants = _getDeterminantsFromListStr ((_derivation + '').match (/\(([^\)]*)\)/) [1]);
|
645 |
+
_determiner = _derivation;
|
646 |
+
} else {
|
647 |
+
if (typeof _derivation == 'string') {
|
648 |
+
var _separatorPos = _derivation.indexOf (':');
|
649 |
+
if (_separatorPos > -1) {
|
650 |
+
_determiner = _newFunction (
|
651 |
+
_determinants = _getDeterminantsFromListStr (_derivation.slice (0,_separatorPos)),
|
652 |
+
'return ' + _derivation.slice (_separatorPos + 1)
|
653 |
+
);
|
654 |
+
} else {
|
655 |
+
_derivation = _getDeterminantsFromListStr (_derivation);
|
656 |
+
}
|
657 |
+
}
|
658 |
+
if (Uize.isArray (_derivation)) {
|
659 |
+
_determinants = [];
|
660 |
+
if (_derivation.length) {
|
661 |
+
var
|
662 |
+
_determinerArgs = [],
|
663 |
+
_determinerOperands = []
|
664 |
+
;
|
665 |
+
_forEach (
|
666 |
+
_derivation,
|
667 |
+
function (_determinant,_determinantNo) {
|
668 |
+
var
|
669 |
+
_inverted = _determinant.charCodeAt (0) == 33,
|
670 |
+
_argName = 'a' + _determinantNo
|
671 |
+
;
|
672 |
+
_determinants.push (_inverted ? _determinant.slice (1) : _determinant);
|
673 |
+
_determinerArgs.push (_argName);
|
674 |
+
_determinerOperands.push ((_inverted ? '!' : '') + _argName);
|
675 |
+
}
|
676 |
+
);
|
677 |
+
_determiner = _newFunction (_determinerArgs,'return ' + _determinerOperands.join (' && '));
|
678 |
+
} else {
|
679 |
+
_determiner = _Uize.returnTrue;
|
680 |
+
}
|
681 |
+
}
|
682 |
+
}
|
683 |
+
_resolvedDerivation = _derivationCache [_derivationCacheKey] = {
|
684 |
+
_determinants:_determinants,
|
685 |
+
_determinantsValuesHarvester:new Function (
|
686 |
+
'return [' + _map (_determinants,'"this.get(\'" + value + "\')"').join (',') + ']'
|
687 |
+
),
|
688 |
+
_determiner:_determiner,
|
689 |
+
_changedEventNames:_map (_determinants,'"Changed." + value')
|
690 |
+
};
|
691 |
+
}
|
692 |
+
return _resolvedDerivation;
|
693 |
+
}
|
694 |
+
|
695 |
+
_classPrototype.once = function (_condition,_handler) {
|
696 |
+
var
|
697 |
+
_this = this,
|
698 |
+
_derivation = _resolveDerivation (_condition),
|
699 |
+
_determinants = _derivation._determinants,
|
700 |
+
_determinantsValuesHarvester = _derivation._determinantsValuesHarvester,
|
701 |
+
_determiner = _derivation._determiner,
|
702 |
+
_wirings
|
703 |
+
;
|
704 |
+
function _isConditionMet () {
|
705 |
+
var
|
706 |
+
_determinantsValues = _determinantsValuesHarvester.call (_this),
|
707 |
+
_conditionMet = _determiner.apply (0,_determinantsValues)
|
708 |
+
;
|
709 |
+
if (_conditionMet) {
|
710 |
+
_wirings && _this.unwire (_wirings);
|
711 |
+
_handler.apply (0,_determinantsValues);
|
712 |
+
}
|
713 |
+
return _conditionMet;
|
714 |
+
}
|
715 |
+
if (_isConditionMet ()) {
|
716 |
+
_wirings = {};
|
717 |
+
} else {
|
718 |
+
_this.wire (_wirings = _lookup (_derivation._changedEventNames,_isConditionMet));
|
719 |
+
}
|
720 |
+
return _wirings;
|
721 |
+
/*?
|
722 |
+
Instance Methods
|
723 |
+
once
|
724 |
+
Lets you register a handler that should be executed only once a condition is met.
|
725 |
+
|
726 |
+
The =once= method is useful when using one or more state properties to form a condition, and where you wish to register code that should be executed once the condition has been met, and immediately if the condition is already met at the time that the =once= method is called.
|
727 |
+
|
728 |
+
DIFFERENT USAGES
|
729 |
+
|
730 |
+
`Execute Code Once a State Property is Truthy or Falsy`
|
731 |
+
................................................................
|
732 |
+
wiringsOBJ = myInstance.once (propertyConditionSTR,handlerFUNC);
|
733 |
+
................................................................
|
734 |
+
|
735 |
+
`Execute Code Once Multiple State Properties Are Truthy or Falsy`
|
736 |
+
.........................................................................
|
737 |
+
wiringsOBJ = myInstance.once (propertiesConditionARRAYorSTR,handlerFUNC);
|
738 |
+
.........................................................................
|
739 |
+
|
740 |
+
`Execute Code Once a Compound Condition is Met`
|
741 |
+
......................................................................
|
742 |
+
wiringsOBJ = myInstance.once (compoundConditionSTRorFUNC,handlerFUNC);
|
743 |
+
......................................................................
|
744 |
+
|
745 |
+
Execute Code Once a State Property is Truthy or Falsy
|
746 |
+
In its most basic usage, code can be registered to be executed once a single state property becomes truthy or falsy.
|
747 |
+
|
748 |
+
SYNTAX
|
749 |
+
................................................................
|
750 |
+
wiringsOBJ = myInstance.once (propertyConditionSTR,handlerFUNC);
|
751 |
+
................................................................
|
752 |
+
|
753 |
+
The =propertyConditionSTR= parameter specifies the name of a state property, with an optional "!" (exclamation mark) prefix for indicating `condition inversion`. If simply the name of a state property is specified, then the handler code specified by the =handlerFUNC= parameter will be executed once the property is truthy. If the optional "!" prefix is specified, then the handler code will be executed once the property is falsy.
|
754 |
+
|
755 |
+
EXAMPLE 1
|
756 |
+
........................................................
|
757 |
+
myWidget.once (
|
758 |
+
'wired',
|
759 |
+
function () {
|
760 |
+
// do something now that the widget has been wired
|
761 |
+
}
|
762 |
+
);
|
763 |
+
........................................................
|
764 |
+
|
765 |
+
In the above example, a handler is being registered to be executed once the widget =myWidget= has been wired (ie. the value of its =wired= state property becomes =true=).
|
766 |
+
|
767 |
+
EXAMPLE 2
|
768 |
+
................................................................
|
769 |
+
myCollectionWidget.once (
|
770 |
+
'!isEmpty',
|
771 |
+
function () {
|
772 |
+
// do something now that the collection is no longer empty
|
773 |
+
}
|
774 |
+
);
|
775 |
+
................................................................
|
776 |
+
|
777 |
+
In the above example, code is being registered to execute once the =isEmpty= state property is =false=.
|
778 |
+
|
779 |
+
Execute Code Once Multiple State Properties Are Truthy or Falsy
|
780 |
+
Code can be registered to be executed once all properties in a set of state properties become truthy or falsy, by specifying the state properties as an array of property names or as a comma-separated list string.
|
781 |
+
|
782 |
+
SYNTAX
|
783 |
+
.........................................................................
|
784 |
+
wiringsOBJ = myInstance.once (propertiesConditionARRAYorSTR,handlerFUNC);
|
785 |
+
.........................................................................
|
786 |
+
|
787 |
+
propertiesConditionARRAYorSTR
|
788 |
+
The value specified for the =propertiesConditionARRAYorSTR= parameter may be an array of property names or a comma-separated list string.
|
789 |
+
|
790 |
+
Whichever form is used, any property name can be prefixed with a "!" (exclamation mark) to achieve `condition inversion` for the property.
|
791 |
+
|
792 |
+
Summary of different forms...
|
793 |
+
|
794 |
+
- array of property names: =['phase1Done','phase2Done','phase3Done']=
|
795 |
+
- array of property names with `condition inversion`: =['wired','!isEmpty']=
|
796 |
+
- comma-separated list string: ='phase1Done, phase2Done, phase3Done'=
|
797 |
+
- comma-separated list with `condition inversion`: ='wired, !isEmpty'=
|
798 |
+
|
799 |
+
Whitespace Ignored for Comma-separated List String
|
800 |
+
If a comma-separated list string is specified, all whitespace in the string is ignored.
|
801 |
+
|
802 |
+
This means that whitespace around the property names is ignored, so the value ='phase1Done,phase2Done,phase3Done'= is equivalent to the value ='phase1Done, phase2Done , phase3Done'=. This also means that whitespace around the optional "!" (exclamation mark) prefix is ignored, so the value ='wired, !isEmpty'= is equivalent to the value ='wired, ! isEmpty'=.
|
803 |
+
|
804 |
+
Examples
|
805 |
+
The following examples illustrate the different ways in which multiple properties can be specified.
|
806 |
+
|
807 |
+
EXAMPLE: Array of Property Names
|
808 |
+
Multiple state properties can be specified using an array of state property names.
|
809 |
+
|
810 |
+
EXAMPLE
|
811 |
+
........................................................
|
812 |
+
myInstance.once (
|
813 |
+
['phase1Done','phase2Done','phase3Done'],
|
814 |
+
function () {
|
815 |
+
// execute code now that all three phases are done
|
816 |
+
}
|
817 |
+
);
|
818 |
+
........................................................
|
819 |
+
|
820 |
+
EXAMPLE: Comma-separated List String
|
821 |
+
Multiple state properties can be specified using a comma-separated list string.
|
822 |
+
|
823 |
+
EXAMPLE
|
824 |
+
........................................................
|
825 |
+
myInstance.once (
|
826 |
+
'phase1Done, phase2Done, phase3Done',
|
827 |
+
function () {
|
828 |
+
// execute code now that all three phases are done
|
829 |
+
}
|
830 |
+
);
|
831 |
+
........................................................
|
832 |
+
|
833 |
+
EXAMPLE: Array of Property Names, with Condition Inversion
|
834 |
+
Multiple state properties can be specified using an array of state property names, where some of the property names in the array are prefixed with the optional "!" to indicate `condition inversion`.
|
835 |
+
|
836 |
+
EXAMPLE
|
837 |
+
.................................................................................
|
838 |
+
myCollection.once (
|
839 |
+
['wired','!isEmpty'],
|
840 |
+
function () {
|
841 |
+
// execute code now that the collection widget is wired and no longer empty
|
842 |
+
}
|
843 |
+
);
|
844 |
+
.................................................................................
|
845 |
+
|
846 |
+
EXAMPLE: Comma-separated List String, with Condition Inversion
|
847 |
+
Multiple state properties can be specified using a comma-separated list string, where some of the property names in the list are prefixed with the optional "!" to indicate `condition inversion`.
|
848 |
+
|
849 |
+
EXAMPLE
|
850 |
+
.................................................................................
|
851 |
+
myCollection.once (
|
852 |
+
'wired, !isEmpty',
|
853 |
+
function () {
|
854 |
+
// execute code now that the collection widget is wired and no longer empty
|
855 |
+
}
|
856 |
+
);
|
857 |
+
.................................................................................
|
858 |
+
|
859 |
+
Execute Code Once a Compound Condition is Met
|
860 |
+
Code can be registered to be executed once a compound condition is met, by specifying the compound condition in the form of a condition function or condition expression string.
|
861 |
+
|
862 |
+
SYNTAX
|
863 |
+
......................................................................
|
864 |
+
wiringsOBJ = myInstance.once (compoundConditionSTRorFUNC,handlerFUNC);
|
865 |
+
......................................................................
|
866 |
+
|
867 |
+
Condition Function
|
868 |
+
A compound condition can be specified as a function, where the names of the function's arguments indicate the state properties that affect the condition and where the function's body evaluates the condition.
|
869 |
+
|
870 |
+
EXAMPLE
|
871 |
+
..............................................................................
|
872 |
+
myFishTankWater.once (
|
873 |
+
function (width,height,depth) {return width * height * depth > 1000},
|
874 |
+
function () {
|
875 |
+
// execute code, now that the water volume of the fish tank exceeds 1000
|
876 |
+
}
|
877 |
+
}
|
878 |
+
..............................................................................
|
879 |
+
|
880 |
+
In the above example, a compound condition is specified using a function. The arguments of the function - =width=, =height=, and =depth= - indicate that the condition is affected by the =width=, =height=, and =depth= state properties of the =myFishTankWater= instance. The function's body, =return width * height * depth > 1000=, evaluates the condition to be =true= when the volume of the fish tank's water is greater than =1000=.
|
881 |
+
|
882 |
+
When code is registered to be executed once the product of the =width=, =height=, and =depth= properties is greater than =1000=, if this condition is not yet met when the =once= method is called, the method will wire handlers for the =Changed.width=, =Changed.height=, and =Changed.depth= events and will re-evaluate the condition function every time any of the properties that affect the condition change value. Once the condition function returns a truthy result, the handler for the compound condition will be executed and the handlers that were wired for the =Changed.*= events will be unwired.
|
883 |
+
|
884 |
+
Condition Expression String
|
885 |
+
A compound condition can be specified as an expression string, where the names of the state properties affecting the condition are specified along with an expression string for evaluating the condition.
|
886 |
+
|
887 |
+
A condition expression string is formatted with two parts separated by a ":" (colon) delimiter, where the part before the colon is a comma-separated list of the state properties affecting the condition, and the part after the colon is an expression to be used for evaluating the condition.
|
888 |
+
|
889 |
+
EXAMPLE
|
890 |
+
..............................................................................
|
891 |
+
myFishTankWater.once (
|
892 |
+
'width, height, depth : width * height * depth > 1000',
|
893 |
+
function () {
|
894 |
+
// execute code, now that the water volume of the fish tank exceeds 1000
|
895 |
+
}
|
896 |
+
}
|
897 |
+
..............................................................................
|
898 |
+
|
899 |
+
In the above example, a compound condition is specified using a `condition expression string`. In this string, the part before the colon - "width, height, depth" - indicates that the condition is affected by the =width=, =height=, and =depth= state properties of the =myFishTankWater= instance. The part after the colon - "width * height * depth > 1000" - evaluates the condition to be =true= when the volume of the fish tank's water (ie. the product of the =width=, =height=, and =depth= properties) is greater than =1000=.
|
900 |
+
|
901 |
+
Immediate Execution if Condition Already Met
|
902 |
+
If the condition specified in the call to the =once= method is already met at the time that the method is called, then the handler specified by the =handlerFUNC= parameter will be executed immediately.
|
903 |
+
|
904 |
+
Otherwise, handlers will be wired for the =Changed.*= (value change) events for all the state properties that affect the condition. The condition evaluator will be executed each time any of the watched properties change value. As soon as the condition becomes met (ie. the condition evaluator produces a truthy result), the handlers wired to watch the value change events of the properties will be unwired and the handler function registered for the condition will be executed. By design, the handler is only executed for the first time that the condition becomes met.
|
905 |
+
|
906 |
+
Condition Inversion
|
907 |
+
As a convenience, the =once= method supports condition inversion through an optional "!" (logical not) prefix that can be placed before the condition name.
|
908 |
+
|
909 |
+
EXAMPLE
|
910 |
+
................................................................
|
911 |
+
myCollectionWidget.once (
|
912 |
+
'!isEmpty',
|
913 |
+
function () {
|
914 |
+
// do something now that the collection is no longer empty
|
915 |
+
}
|
916 |
+
);
|
917 |
+
................................................................
|
918 |
+
|
919 |
+
In the above example, code is being registered to execute once the =isEmpty= state property is =false=. This is done by prefixing the "isEmpty" condition name with a "!" (bang / exclamation) character to indicate that the code should execute only once the collection is not empty (ie. the value of the =isEmpty= state property becomes =false=). The `condition inversion` facility is convenient in situations like this where you wish to execute code only once a property's value becomes falsy, rather than once the property's value becomes truthy (which is the standard behavior for the =once= method).
|
920 |
+
|
921 |
+
Condition Inversion with Multiple Property Conditions
|
922 |
+
Condition inversion can be used both with single state property conditions as well as multiple property conditions.
|
923 |
+
|
924 |
+
EXAMPLE
|
925 |
+
................................................................
|
926 |
+
myCollectionWidget.once (
|
927 |
+
['wired','!isEmpty'],
|
928 |
+
function () {
|
929 |
+
// do something now that the collection is wired and no longer empty
|
930 |
+
}
|
931 |
+
);
|
932 |
+
...........................................................................
|
933 |
+
|
934 |
+
In the above example, code is being registered to be executed once the =wired= state property is truthy and the =isEmpty= state property is falsy. Condition inversion can also be used when the state properties are specified as a comma-separated list string, so specifying the condition as =['wired','!isEmpty']= is equivalent to specifying it as ='wired, !isEmpty'=.
|
935 |
+
|
936 |
+
Wirings Object
|
937 |
+
The =once= method returns a wirings object that can be supplied to the =unwire= method in order to unwire the handler, in the unlikely event that one may wish to remove the handler before the condition becomes met.
|
938 |
+
|
939 |
+
This case is unlikely to arise except in exceptional situations, but the means is provided. In most cases, you will simply discard / ignore the return value of the =once= method. In the event that the condition is met when the =once= method is called, then the returned wirings object will be an empty object.
|
940 |
+
|
941 |
+
Handler Arguments
|
942 |
+
The handler code that is registered to be executed once a condition is met will be passed the values of all the state properties that affect the condition as arguments.
|
943 |
+
|
944 |
+
EXAMPLE
|
945 |
+
...................................................................
|
946 |
+
myFishTankWater.once (
|
947 |
+
'width, height, depth : width * height * depth > 1000',
|
948 |
+
function (width,height,depth) {
|
949 |
+
alert (width + '(W) x ' + height + '(H) x ' + depth + '(D)');
|
950 |
+
}
|
951 |
+
}
|
952 |
+
|
953 |
+
myFishTankWater.set ({
|
954 |
+
width:10,
|
955 |
+
height:11,
|
956 |
+
depth:12
|
957 |
+
});
|
958 |
+
...................................................................
|
959 |
+
|
960 |
+
In the above example, code is being registered to be executed once the product of the =width=, =height=, and =depth= properties of the =myFishTankWater= instance exceeds =1000=. Once the call to the =set= method has been executed, the volume of the fish tank's water will be =1320= and the handler will be executed.
|
961 |
+
|
962 |
+
Now, because the properties affecting the condition have been specified as "width, height, depth", the value of these state properties will be passed as arguments to the handler in the order =width=, =height=, and =depth=. In this case, the handler function is choosing to declare these function arguments, using the same names for the sake of clarity - you could ignore the arguments if you didn't care about the specific values at the time the condition is met, or you could use the arguments but name them differently. In this example, the =alert= statement will alert the text "10(W) x 11(H) x 12(D)".
|
963 |
+
|
964 |
+
NOTES
|
965 |
+
- see the other `condition system methods`
|
966 |
+
*/
|
967 |
+
};
|
968 |
+
|
969 |
+
_classPrototype.is = function (_property) {
|
970 |
+
return !!this [_getPropertyPrivateName (this,_property)];
|
971 |
+
/*?
|
972 |
+
Instance Methods
|
973 |
+
is
|
974 |
+
Returns a boolean, indicating whether or not the specified condition is met (ie. the specified condition state property's value is truthy).
|
975 |
+
|
976 |
+
SYNTAX
|
977 |
+
................................
|
978 |
+
myInstance.is (propertyNameSTR);
|
979 |
+
................................
|
980 |
+
|
981 |
+
The =is= method is offered as a convenience to improve the semantics of code that is using state properties to represent conditions, and is a very thin wrapper around the =get= instance method. The statement =myInstance.is ('myCondition')= is equivalent to the statement =!!myInstance.get ('myCondition')=.
|
982 |
+
|
983 |
+
EXAMPLE
|
984 |
+
...........................................
|
985 |
+
if (myWidget.is ('enabled')) {
|
986 |
+
// do something if the widget is enabled
|
987 |
+
}
|
988 |
+
...........................................
|
989 |
+
|
990 |
+
In the above example, some code is being executed conditionally, based upon whether or not a widget is enabled. The =Uize.Widget= base class provides an =enabled= state property, whose value is a boolean. One could use the =get= method in this code example to achieve the same effect, but using the =is= method make the code more readable.
|
991 |
+
|
992 |
+
NOTES
|
993 |
+
- see the other `condition system methods`
|
994 |
+
*/
|
995 |
+
};
|
996 |
+
|
997 |
+
_classPrototype.met = function (_propertyOrProperties) {
|
998 |
+
this.set (_propertyOrProperties,true);
|
999 |
+
/*?
|
1000 |
+
Instance Methods
|
1001 |
+
met
|
1002 |
+
Sets the specified condition (or conditions) as having been met.
|
1003 |
+
|
1004 |
+
DIFFERENT USAGES
|
1005 |
+
|
1006 |
+
`Set a Single Condition as Having Been Met`
|
1007 |
+
.................................
|
1008 |
+
myInstance.met (propertyNameSTR);
|
1009 |
+
.................................
|
1010 |
+
|
1011 |
+
`Set Multiple Conditions as Having Been Met`
|
1012 |
+
....................................
|
1013 |
+
myInstance.met (propertyNamesARRAY);
|
1014 |
+
....................................
|
1015 |
+
|
1016 |
+
For Improved Semantics
|
1017 |
+
The =met= method is offered as a convenience to improve the semantics of code that is using state properties to represent conditions, and is a very thin wrapper around the =set= instance method.
|
1018 |
+
|
1019 |
+
The statement =myInstance.met ('myCondition')= is equivalent to the statement =myInstance.set ('myCondition',true)=. When using a state property to represent a condition, the =met= method is a semantically elegant way to set the value of the property to =true= to indicate that the condition represented by the property has been met.
|
1020 |
+
|
1021 |
+
EXAMPLE
|
1022 |
+
.............................................
|
1023 |
+
MyClass.prototype.initialize = function () {
|
1024 |
+
// some code here to do the initialization
|
1025 |
+
this.met ('initialized');
|
1026 |
+
};
|
1027 |
+
.............................................
|
1028 |
+
|
1029 |
+
In the above example, an =initialize= instance method is defined for the class =MyClass=. In the method's implementation, after all the initialization has been performed, the =met= method is being called to indicate that the =initialized= condition has been met, where =initialized= is the name of a state property provided in =MyClass=. Now, other code can be registered to be executed only once an instance has been initialized by using the =once= instance method, as follows...
|
1030 |
+
|
1031 |
+
.............................................................
|
1032 |
+
myInstance.once (
|
1033 |
+
'initialized',
|
1034 |
+
function () {
|
1035 |
+
// do some stuff once the instance has been initialized
|
1036 |
+
}
|
1037 |
+
);
|
1038 |
+
.............................................................
|
1039 |
+
|
1040 |
+
Set a Single Condition as Having Been Met
|
1041 |
+
In its most typical usage, a single condition can be set as having been met by specifying the name of the condition for the =propertyNameSTR= parameter.
|
1042 |
+
|
1043 |
+
SYNTAX
|
1044 |
+
.................................
|
1045 |
+
myInstance.met (propertyNameSTR);
|
1046 |
+
.................................
|
1047 |
+
|
1048 |
+
EXAMPLE
|
1049 |
+
..........................
|
1050 |
+
this.met ('someSelected');
|
1051 |
+
..........................
|
1052 |
+
|
1053 |
+
Set Multiple Conditions as Having Been Met
|
1054 |
+
In cases where you wish to set multiple conditions as having been met, the names of those conditions can be supplied by specifying an array for the =propertyNamesARRAY= parameter.
|
1055 |
+
|
1056 |
+
SYNTAX
|
1057 |
+
....................................
|
1058 |
+
myInstance.met (propertyNamesARRAY);
|
1059 |
+
....................................
|
1060 |
+
|
1061 |
+
EXAMPLE
|
1062 |
+
....................................
|
1063 |
+
this.met (['initialized', 'ready']);
|
1064 |
+
....................................
|
1065 |
+
|
1066 |
+
NOTES
|
1067 |
+
- see the companion =unmet= instance method
|
1068 |
+
- see the other `condition system methods`
|
1069 |
+
*/
|
1070 |
+
};
|
1071 |
+
|
1072 |
+
_classPrototype.unmet = function (_propertyOrProperties) {
|
1073 |
+
this.set (_propertyOrProperties,false);
|
1074 |
+
/*?
|
1075 |
+
Instance Methods
|
1076 |
+
unmet
|
1077 |
+
Sets the specified condition (or conditions) as being unmet.
|
1078 |
+
|
1079 |
+
DIFFERENT USAGES
|
1080 |
+
|
1081 |
+
`Set a Single Condition as Being Unmet`
|
1082 |
+
...................................
|
1083 |
+
myInstance.unmet (propertyNameSTR);
|
1084 |
+
...................................
|
1085 |
+
|
1086 |
+
`Set Multiple Conditions as Being Unmet`
|
1087 |
+
......................................
|
1088 |
+
myInstance.unmet (propertyNamesARRAY);
|
1089 |
+
......................................
|
1090 |
+
|
1091 |
+
For Improved Semantics
|
1092 |
+
The =unmet= method is offered as a convenience to improve the semantics of code that is using state properties to represent conditions, and is a very thin wrapper around the =set= instance method.
|
1093 |
+
|
1094 |
+
The statement =myInstance.unmet ('myCondition')= is equivalent to the statement =myInstance.set ('myCondition',false)=. When using a state property to represent a condition, the =unmet= method is a semantically elegant way to set the value of the property to =false= to indicate that the condition represented by the property is not met / no longer met.
|
1095 |
+
|
1096 |
+
EXAMPLE
|
1097 |
+
..............................................
|
1098 |
+
MyClass.prototype.die = function () {
|
1099 |
+
// some code here to tear down the instance
|
1100 |
+
this.unmet ('initialized');
|
1101 |
+
};
|
1102 |
+
..............................................
|
1103 |
+
|
1104 |
+
In the above example, a =die= instance method is defined for the class =MyClass=. In the method's implementation, after all the tear down steps have been performed, the =unmet= method is being called to indicate that the =initialized= condition is no longer met, where =initialized= is the name of a state property provided in =MyClass=. It is assumed that some other method, such as an =initialize= instance method for the class, is responsible for setting the condition as having been met with a statement like =this.met ('initialized')=.
|
1105 |
+
|
1106 |
+
Set a Single Condition as Being Unmet
|
1107 |
+
In its most typical usage, a single condition can be set as being unmet by specifying the name of the condition for the =propertyNameSTR= parameter.
|
1108 |
+
|
1109 |
+
SYNTAX
|
1110 |
+
...................................
|
1111 |
+
myInstance.unmet (propertyNameSTR);
|
1112 |
+
...................................
|
1113 |
+
|
1114 |
+
EXAMPLE
|
1115 |
+
............................
|
1116 |
+
this.unmet ('someSelected');
|
1117 |
+
............................
|
1118 |
+
|
1119 |
+
Set Multiple Conditions as Being Unmet
|
1120 |
+
In cases where you wish to set multiple conditions as being unmet, the names of those conditions can be supplied by specifying an array for the =propertyNamesARRAY= parameter.
|
1121 |
+
|
1122 |
+
SYNTAX
|
1123 |
+
......................................
|
1124 |
+
myInstance.unmet (propertyNamesARRAY);
|
1125 |
+
......................................
|
1126 |
+
|
1127 |
+
EXAMPLE
|
1128 |
+
......................................
|
1129 |
+
this.unmet (['initialized', 'ready']);
|
1130 |
+
......................................
|
1131 |
+
|
1132 |
+
NOTES
|
1133 |
+
- see the companion =met= instance method
|
1134 |
+
- see the other `condition system methods`
|
1135 |
+
*/
|
1136 |
+
};
|
1137 |
+
|
1138 |
+
/*** State Property System Methods ***/
|
1139 |
+
_class.get = _classPrototype.get = function (_property) {
|
1140 |
+
if (typeof _property == _typeString) {
|
1141 |
+
/* NOTE:
|
1142 |
+
Because the get method gets hit so heavily, optimize it to do as little as possible in the most common use case (where parameter is a string, being the name of the property), so no creation of and assignment to local variables.
|
1143 |
+
*/
|
1144 |
+
return this [_getPropertyPrivateName (this,_property)];
|
1145 |
+
} else {
|
1146 |
+
var
|
1147 |
+
_this = this,
|
1148 |
+
_result = {}
|
1149 |
+
;
|
1150 |
+
if (!_property) {
|
1151 |
+
/* NOTE:
|
1152 |
+
Driven off of private names to ensure that there is only one property in the object for each actual state property, otherwise you can end up in bad situations.
|
1153 |
+
*/
|
1154 |
+
var
|
1155 |
+
_class = _getClass (_this),
|
1156 |
+
_propertyProfilesByPrivateNames = _class._propertyProfilesByPrivateNames
|
1157 |
+
;
|
1158 |
+
for (var _propertyPrivateName in _propertyProfilesByPrivateNames)
|
1159 |
+
_result [_propertyProfilesByPrivateNames [_propertyPrivateName]._publicName] =
|
1160 |
+
_this [_propertyPrivateName]
|
1161 |
+
;
|
1162 |
+
} else if (_isArray (_property)) {
|
1163 |
+
for (
|
1164 |
+
var _subPropertyNo = -1, _totalSubProperties = _property.length;
|
1165 |
+
++_subPropertyNo < _totalSubProperties;
|
1166 |
+
) {
|
1167 |
+
var _subProperty = _property [_subPropertyNo];
|
1168 |
+
_result [_subProperty] = _this [_getPropertyPrivateName (_this,_subProperty)];
|
1169 |
+
}
|
1170 |
+
} else {
|
1171 |
+
for (var _subProperty in _property)
|
1172 |
+
_result [_subProperty] = _this [_getPropertyPrivateName (_this,_subProperty)]
|
1173 |
+
;
|
1174 |
+
}
|
1175 |
+
return _result;
|
1176 |
+
}
|
1177 |
+
/*?
|
1178 |
+
Instance Methods
|
1179 |
+
get
|
1180 |
+
Lets you query the value of one of an instance's state properties.
|
1181 |
+
|
1182 |
+
DIFFERENT USAGES
|
1183 |
+
|
1184 |
+
`Get the Value of a Single Property`
|
1185 |
+
........................................................
|
1186 |
+
propertyValueANYTYPE = myInstance.get (propertyNameSTR);
|
1187 |
+
........................................................
|
1188 |
+
|
1189 |
+
`Get Values for Multiples Properties, by Specifying a Property Names Array`
|
1190 |
+
........................................................
|
1191 |
+
propertyValuesOBJ = myInstance.get (propertyNamesARRAY);
|
1192 |
+
........................................................
|
1193 |
+
|
1194 |
+
`Get Values for Multiples Properties, by Specifying a Properties Object`
|
1195 |
+
...................................................
|
1196 |
+
propertyValuesOBJ = myInstance.get (propertiesOBJ);
|
1197 |
+
...................................................
|
1198 |
+
|
1199 |
+
`Get Values for All Properties`
|
1200 |
+
.........................................
|
1201 |
+
allPropertyValuesOBJ = myInstance.get ();
|
1202 |
+
.........................................
|
1203 |
+
|
1204 |
+
Get the Value of a Single Property
|
1205 |
+
In the most typical usage of the =get= instance method, a =propertyNameSTR= parameter can be specified in order to get the value of a single state property.
|
1206 |
+
|
1207 |
+
SYNTAX
|
1208 |
+
........................................................
|
1209 |
+
propertyValueANYTYPE = myInstance.get (propertyNameSTR);
|
1210 |
+
........................................................
|
1211 |
+
|
1212 |
+
EXAMPLE
|
1213 |
+
......................................................
|
1214 |
+
var mySlider = Uize.Widget.Bar.Slider ({
|
1215 |
+
minValue:0,
|
1216 |
+
maxValue:100,
|
1217 |
+
value:57
|
1218 |
+
});
|
1219 |
+
|
1220 |
+
alert (mySlider.get ('value')); // alerts the text "57
|
1221 |
+
......................................................
|
1222 |
+
|
1223 |
+
Get Values for Multiples Properties, by Specifying a Property Names Array
|
1224 |
+
When a =propertyNamesARRAY= parameter is specified in place of the =propertyNameSTR= parameter, the values for the instance state properties specified in the array will be populated into an object and returned.
|
1225 |
+
|
1226 |
+
SYNTAX
|
1227 |
+
........................................................
|
1228 |
+
propertyValuesOBJ = myInstance.get (propertyNamesARRAY);
|
1229 |
+
........................................................
|
1230 |
+
|
1231 |
+
EXAMPLE
|
1232 |
+
.....................................................................
|
1233 |
+
mySlider.set ('minValue',0);
|
1234 |
+
mySlider.set ('maxValue,100);
|
1235 |
+
mySlider.set ('value',57);
|
1236 |
+
|
1237 |
+
sliderValueAndRange = mySlider.get (['minValue','maxValue','value']);
|
1238 |
+
.....................................................................
|
1239 |
+
|
1240 |
+
After the above code has been executed, the =sliderValueAndRange= variable would have the value ={minValue:0,maxValue:100,value:57}=.
|
1241 |
+
|
1242 |
+
Get Values for Multiples Properties, by Specifying a Properties Object
|
1243 |
+
When a =propertyNamesARRAY= parameter is specified in place of the =propertyNameSTR= parameter, the values for the instance state properties specified in the array will be populated into an object and returned.
|
1244 |
+
|
1245 |
+
SYNTAX
|
1246 |
+
...................................................
|
1247 |
+
propertyValuesOBJ = myInstance.get (propertiesOBJ);
|
1248 |
+
...................................................
|
1249 |
+
|
1250 |
+
EXAMPLE
|
1251 |
+
.....................................................................
|
1252 |
+
mySlider.set ('minValue',0);
|
1253 |
+
mySlider.set ('maxValue,100);
|
1254 |
+
mySlider.set ('value',57);
|
1255 |
+
|
1256 |
+
sliderValueAndRange = mySlider.get ({minValue:0,maxValue:0,value:0});
|
1257 |
+
.....................................................................
|
1258 |
+
|
1259 |
+
After the above code has been executed, the =sliderValueAndRange= variable would have the value ={minValue:0,maxValue:100,value:57}=. The values of the properties in the properties object, as specified by the =propertiesOBJ= parameter, are immaterial - for whatever properties exist in the object, the values for the corresponding state properties of the instance will be returned.
|
1260 |
+
|
1261 |
+
Get Values for All Properties
|
1262 |
+
When no parameter is specified, the =get= instance method will return an object containing values for all the state properties of the instance.
|
1263 |
+
|
1264 |
+
SYNTAX
|
1265 |
+
.........................................
|
1266 |
+
allPropertyValuesOBJ = myInstance.get ();
|
1267 |
+
.........................................
|
1268 |
+
|
1269 |
+
For one thing, this variation makes it easy to create a new instance of a class with the same state as an existing instance.
|
1270 |
+
|
1271 |
+
EXAMPLE
|
1272 |
+
.........................................
|
1273 |
+
copyOfMyFade = Uize.Fade (myFade.get ());
|
1274 |
+
.........................................
|
1275 |
+
|
1276 |
+
In this example, an instance of the class =Uize.Fade= is being created by passing the constructor all the state property values obtained from the =myFade= instance using the =get= method. The new instance created will then have the same state as the =myFade= instance.
|
1277 |
+
|
1278 |
+
NOTES
|
1279 |
+
- see also the =set= instance method
|
1280 |
+
- see also the =Uize.Class.get= and =Uize.Class.set= static methods
|
1281 |
+
|
1282 |
+
Static Methods
|
1283 |
+
Uize.Class.get
|
1284 |
+
Lets you query the initial value for one of the class's state properties.
|
1285 |
+
|
1286 |
+
SYNTAX
|
1287 |
+
........................................................
|
1288 |
+
propertyValueANYTYPE = Uize.Class.get (propertyNameSTR);
|
1289 |
+
........................................................
|
1290 |
+
|
1291 |
+
VARIATIONS
|
1292 |
+
........................................................
|
1293 |
+
propertyValuesOBJ = Uize.Class.get (propertyNamesARRAY);
|
1294 |
+
........................................................
|
1295 |
+
|
1296 |
+
When a =propertyNamesARRAY= parameter is specified in place of the =propertyNameSTR= parameter, the values for the class state properties specified in the array will be populated into an object and returned. So, for example =Uize.Widget.get (['enabled','busy','built'])= would return a result like ={enabled:'inherit',busy:'inherit',built:true}=.
|
1297 |
+
|
1298 |
+
.........................................
|
1299 |
+
allPropertyValuesOBJ = Uize.Class.get ();
|
1300 |
+
.........................................
|
1301 |
+
|
1302 |
+
When no parameter is specified, the =Uize.Class.get= static method will return an object containing values for all the registered state properties of the class.
|
1303 |
+
|
1304 |
+
NOTES
|
1305 |
+
- see also the =Uize.Class.set= static method
|
1306 |
+
- see also the =get= and =set= instance methods
|
1307 |
+
*/
|
1308 |
+
};
|
1309 |
+
|
1310 |
+
_class.registerProperties = function (_propertyProfiles) {
|
1311 |
+
var
|
1312 |
+
_this = this,
|
1313 |
+
_propertyProfilesByPrivateNames = _this._propertyProfilesByPrivateNames,
|
1314 |
+
_propertyProfilesByPublicNames = _this._propertyProfilesByPublicNames
|
1315 |
+
;
|
1316 |
+
for (var _propertyPrivateName in _propertyProfiles) {
|
1317 |
+
var
|
1318 |
+
_propertyData = _propertyProfiles [_propertyPrivateName],
|
1319 |
+
_propertyDataIsObject = _isObject (_propertyData),
|
1320 |
+
_propertyPublicName =
|
1321 |
+
(_propertyDataIsObject ? _propertyData.name : _propertyData) || _propertyPrivateName,
|
1322 |
+
_propertyPrimaryPublicName = _propertyPublicName,
|
1323 |
+
_propertyProfile = _propertyProfilesByPrivateNames [_propertyPrivateName] = {_privateName:_propertyPrivateName}
|
1324 |
+
;
|
1325 |
+
if (_propertyPublicName.indexOf ('|') > -1) {
|
1326 |
+
var _pseudonyms = _propertyPublicName.split ('|');
|
1327 |
+
_propertyPrimaryPublicName = _pseudonyms [0];
|
1328 |
+
_lookup (_pseudonyms,_propertyProfile,_propertyProfilesByPublicNames);
|
1329 |
+
} else {
|
1330 |
+
_propertyProfilesByPublicNames [_propertyPublicName] = _propertyProfile;
|
1331 |
+
}
|
1332 |
+
_propertyProfile._publicName = _propertyPrimaryPublicName;
|
1333 |
+
if (_propertyDataIsObject) {
|
1334 |
+
if (_propertyData.onChange) _propertyProfile._onChange = _propertyData.onChange;
|
1335 |
+
if (_propertyData.conformer) _propertyProfile._conformer = _propertyData.conformer;
|
1336 |
+
_this [_propertyPrivateName] = _propertyData.value;
|
1337 |
+
}
|
1338 |
+
}
|
1339 |
+
_this._instancePropertyDefaults = this.get ();
|
1340 |
+
/*?
|
1341 |
+
Static Methods
|
1342 |
+
Uize.Class.registerProperties
|
1343 |
+
Lets you register properties for the class.
|
1344 |
+
|
1345 |
+
SYNTAX
|
1346 |
+
.....................................................
|
1347 |
+
MyClass.registerProperties (propertiesDefinitionOBJ);
|
1348 |
+
.....................................................
|
1349 |
+
|
1350 |
+
The object specified in =propertiesDefinitionOBJ= parameter must conform to a specific structure. Each property of this object represents a property to be registered for the class, where the property name specifies the internal name to be used for the class property and the property's string value specifies the class property's public name. As an alternative to a string value, the property's value can be an object whose =name= property specifies the class property's public name and where an optional =onChange= property specifies a handler function that should be executed every time the value of the class property changes. This is all best illustrated with an example...
|
1351 |
+
|
1352 |
+
EXAMPLE
|
1353 |
+
...........................................................................
|
1354 |
+
MyClass.registerProperties (
|
1355 |
+
{
|
1356 |
+
_propertylName:'property1Name',
|
1357 |
+
_property2Name:'property2Name',
|
1358 |
+
_property3Name:{
|
1359 |
+
name:'property3Name',
|
1360 |
+
onChange:function () {
|
1361 |
+
// code to be performed when the value of this property changes
|
1362 |
+
}
|
1363 |
+
}
|
1364 |
+
}
|
1365 |
+
);
|
1366 |
+
...........................................................................
|
1367 |
+
|
1368 |
+
NOTES
|
1369 |
+
- calls to this method are cumulative, so it is possible to register properties in multiple separate batches
|
1370 |
+
*/
|
1371 |
+
};
|
1372 |
+
|
1373 |
+
_class.set = _classPrototype.set = function (_properties) {
|
1374 |
+
/* NOTE:
|
1375 |
+
Yes, there are functions _getClass and _getPropertyPrivateName that could be used (and were at one point), but this code needs to be tuned for performance since set is a touch point in so many places.
|
1376 |
+
*/
|
1377 |
+
var
|
1378 |
+
_arguments = arguments,
|
1379 |
+
_argumentsLength = _arguments.length
|
1380 |
+
;
|
1381 |
+
if (_argumentsLength > 1)
|
1382 |
+
/* NOTE:
|
1383 |
+
- support for...
|
1384 |
+
set (propertyNameSTR,propertyValueANYTYPE)
|
1385 |
+
|
1386 |
+
or...
|
1387 |
+
|
1388 |
+
set (
|
1389 |
+
property1NameSTR,property1ValueANYTYPE,
|
1390 |
+
property2NameSTR,property2ValueANYTYPE,
|
1391 |
+
...
|
1392 |
+
propertyNNameSTR,propertyNValueANYTYPE
|
1393 |
+
)
|
1394 |
+
|
1395 |
+
or...
|
1396 |
+
|
1397 |
+
set (propertyNamesARRAY,propertyValueANYTYPE)
|
1398 |
+
*/
|
1399 |
+
_properties = _argumentsLength > 2 || typeof _properties == _typeString
|
1400 |
+
? _pairUp.apply (0,_arguments)
|
1401 |
+
: _lookup (_properties,_arguments [1])
|
1402 |
+
;
|
1403 |
+
var
|
1404 |
+
_this = this,
|
1405 |
+
_thisIsInstance = _isInstance (_this),
|
1406 |
+
_class = _thisIsInstance ? _this.Class : _this,
|
1407 |
+
_propertyProfilesByPublicNames = _class._propertyProfilesByPublicNames,
|
1408 |
+
_propertyProfilesByPrivateNames = _class._propertyProfilesByPrivateNames,
|
1409 |
+
_propertyProfile,
|
1410 |
+
_onChangeHandlers,
|
1411 |
+
_onChangeHandlerAddedFlagName,
|
1412 |
+
_onChangeHandler,
|
1413 |
+
_hasChangedHandlers = _thisIsInstance && _this._hasChangedHandlers,
|
1414 |
+
_hasChangedDotStarHandlers = _hasChangedHandlers && _hasChangedHandlers ['*'],
|
1415 |
+
_propertiesForChangedDotStar,
|
1416 |
+
_changedEventsToFire,
|
1417 |
+
_propertyPrivateName,
|
1418 |
+
_propertyPublicName,
|
1419 |
+
_propertiesToRegister,
|
1420 |
+
_propertyValue,
|
1421 |
+
_propertiesBeingSet
|
1422 |
+
;
|
1423 |
+
for (var _propertyPublicOrPrivateName in _properties) {
|
1424 |
+
_propertyValue = _properties [_propertyPublicOrPrivateName];
|
1425 |
+
if (
|
1426 |
+
_propertyProfile =
|
1427 |
+
_propertyProfilesByPublicNames [_propertyPublicOrPrivateName] ||
|
1428 |
+
_propertyProfilesByPrivateNames [_propertyPublicOrPrivateName]
|
1429 |
+
) {
|
1430 |
+
_propertyPrivateName = _propertyProfile._privateName;
|
1431 |
+
_propertyPublicName = _propertyProfile._publicName;
|
1432 |
+
} else {
|
1433 |
+
(_propertiesToRegister || (_propertiesToRegister = {})) [
|
1434 |
+
_propertyPrivateName = _propertyPublicName = _propertyPublicOrPrivateName
|
1435 |
+
] =
|
1436 |
+
_propertyProfile = _thisIsInstance ? {} : {value:_propertyValue}
|
1437 |
+
;
|
1438 |
+
}
|
1439 |
+
if (_thisIsInstance)
|
1440 |
+
(_propertiesBeingSet || (_propertiesBeingSet = {})) [_propertyPublicName] =
|
1441 |
+
_propertyProfile._conformer
|
1442 |
+
? (
|
1443 |
+
/*** if there's a registered conformer, execute it and adjust the value ***/
|
1444 |
+
_propertyValue = _propertyProfile._conformer.call (
|
1445 |
+
_this,_propertyValue,_this [_propertyPrivateName]
|
1446 |
+
)
|
1447 |
+
)
|
1448 |
+
: _propertyValue
|
1449 |
+
;
|
1450 |
+
|
1451 |
+
if (_propertyValue !== _this [_propertyPrivateName]) {
|
1452 |
+
if (_thisIsInstance) {
|
1453 |
+
/*** build up list of events to fire for 'Changed.' event handlers ***/
|
1454 |
+
_hasChangedDotStarHandlers && (
|
1455 |
+
(_propertiesForChangedDotStar || (_propertiesForChangedDotStar = {}))
|
1456 |
+
[_propertyPublicName] = _propertyValue
|
1457 |
+
);
|
1458 |
+
_hasChangedHandlers && _hasChangedHandlers [_propertyPublicName] &&
|
1459 |
+
(_changedEventsToFire || (_changedEventsToFire = [])).push (_propertyPublicName)
|
1460 |
+
;
|
1461 |
+
/*** build up list of onChange handlers to execute ***/
|
1462 |
+
function _processOnChangeHandler (_onChangeHandler) {
|
1463 |
+
if (_isFunction (_onChangeHandler)) {
|
1464 |
+
if (!_onChangeHandlers) {
|
1465 |
+
_onChangeHandlers = [];
|
1466 |
+
_onChangeHandlerAddedFlagName = _this.instanceId + '_handlerAlreadyAdded';
|
1467 |
+
}
|
1468 |
+
if (!_onChangeHandler [_onChangeHandlerAddedFlagName]) {
|
1469 |
+
_onChangeHandler [_onChangeHandlerAddedFlagName] = 1;
|
1470 |
+
_onChangeHandlers.push (_onChangeHandler);
|
1471 |
+
}
|
1472 |
+
} else if (typeof _onChangeHandler == _typeString) {
|
1473 |
+
_processOnChangeHandler (_this [_onChangeHandler]);
|
1474 |
+
} else if (_isArray (_onChangeHandler)) {
|
1475 |
+
_forEach (_onChangeHandler,_processOnChangeHandler);
|
1476 |
+
}
|
1477 |
+
}
|
1478 |
+
_propertyProfile._onChange && _processOnChangeHandler (_propertyProfile._onChange);
|
1479 |
+
}
|
1480 |
+
_this [_propertyPrivateName] = _propertyValue;
|
1481 |
+
}
|
1482 |
+
}
|
1483 |
+
_propertiesToRegister && _class.registerProperties (_propertiesToRegister);
|
1484 |
+
if (_thisIsInstance) {
|
1485 |
+
if (_onChangeHandlers) {
|
1486 |
+
for (
|
1487 |
+
var _handlerNo = -1, _onChangeHandlersLength = _onChangeHandlers.length;
|
1488 |
+
++_handlerNo < _onChangeHandlersLength;
|
1489 |
+
) {
|
1490 |
+
delete (_onChangeHandler = _onChangeHandlers [_handlerNo]) [_onChangeHandlerAddedFlagName];
|
1491 |
+
_onChangeHandler.call (_this,_propertiesBeingSet);
|
1492 |
+
}
|
1493 |
+
}
|
1494 |
+
_propertiesForChangedDotStar && _this.fire ({name:'Changed.*',properties:_propertiesForChangedDotStar});
|
1495 |
+
if (_changedEventsToFire) {
|
1496 |
+
for (
|
1497 |
+
var _changedEventNo = -1, _changedEventsToFireLength = _changedEventsToFire.length;
|
1498 |
+
++_changedEventNo < _changedEventsToFireLength;
|
1499 |
+
)
|
1500 |
+
_this.fire ('Changed.' + _changedEventsToFire [_changedEventNo])
|
1501 |
+
;
|
1502 |
+
/*?
|
1503 |
+
Instance Events
|
1504 |
+
Changed.*
|
1505 |
+
The =Changed.*= instance event is a wildcard event that is fired whenever one or more state properties change value as a result of a call to the =set= instance method.
|
1506 |
+
|
1507 |
+
This event will only be fired once for all state properties that have changed value during a call to the =set= method. The event object for this event will contain a =properties= property, which is an object indicating which state properties have changed value, being a mapping between the public names of state properties that have changed and their new values.
|
1508 |
+
|
1509 |
+
NOTES
|
1510 |
+
- compare to the related =Changed.[propertyName]= instance event
|
1511 |
+
- wiring a handler for the =Changed.*= event may have a slight performance impact, since this event will be fired any time that any state property changes value
|
1512 |
+
|
1513 |
+
Changed.[propertyName]
|
1514 |
+
The =Uize.Class= base class implements a generalized mechanism for firing events when the values of state properties are changed.
|
1515 |
+
|
1516 |
+
This means that for any state property that is registered through the =Uize.Class.registerProperties= static method, a handler can be registered for a change in the value of that property without having to write any additional code to fire an event.
|
1517 |
+
|
1518 |
+
Event Naming
|
1519 |
+
The name of a changed event that fires is of the form =Changed.[propertyName]=, where =propertyName= is the primary public name of the state property. For example, if you registered a state property named =value=, then a =Changed.value= event would fire each time this property is changed.
|
1520 |
+
|
1521 |
+
Property Aliases
|
1522 |
+
If a state property has aliases, handlers can be registered for the property's changed event using any of the aliases. However, the name of the event when it fires will always be derived from the primary public name (ie. first in the alias list) of the property. So, for example, if a state property was registered with the public names =color= and =hexRgb=, both =Changed.color= and =Changed.hexRgb= would be treated as equivalent.
|
1523 |
+
|
1524 |
+
EXAMPLE
|
1525 |
+
..........................................................
|
1526 |
+
function handleColorChange () {
|
1527 |
+
// do stuff
|
1528 |
+
}
|
1529 |
+
myColorWidget.wire ('Changed.color',handleColorChange);
|
1530 |
+
myColorWidget.unwire ('Changed.hexRgb',handleColorChange);
|
1531 |
+
..........................................................
|
1532 |
+
|
1533 |
+
In this example, the =handleColorChange= function would not be executed when the value of the =color= state property changes, because =Changed.color= and =Changed.hexRgb= are treated as equivalent and therefore the =unwire= statement effectively removes the handler registered in the previous statement.
|
1534 |
+
|
1535 |
+
Must Use the set Method
|
1536 |
+
The =Changed.[propertyName]= event will only fire for a particular state property if the value for that property is set using the =set= method, since it is within the =set= method that change detection occurs and the event is fired. If you simply assign a value by directly accessing the private name of the property, then the event will not fire.
|
1537 |
+
|
1538 |
+
Only On Change, Not Every Set
|
1539 |
+
The =Changed.[propertyName]= event only fires for a particular state property when the value for that property is *changed* by using the =set= method. So, if the =set= method is called but the value that is specified is already the value of the property, then there will be no change and no event will be fired.
|
1540 |
+
|
1541 |
+
Additionally, if a =conformer= is registered for the property and the action of the conformer results in the property value not being changed, then no event will be fired - even if the value specified in the =set= call is different to the current value of the property. This can be the case if the value is at an edge of its valid range, an attempt is made to set the value outside of its valid range, and the conformer has the action of constraining the value so that it remains at the same edge of its valid range.
|
1542 |
+
|
1543 |
+
NOTES
|
1544 |
+
- compare to the related =Changed.*= instance event
|
1545 |
+
*/
|
1546 |
+
}
|
1547 |
+
} else {
|
1548 |
+
_class._instancePropertyDefaults = this.get ();
|
1549 |
+
}
|
1550 |
+
/*?
|
1551 |
+
Instance Methods
|
1552 |
+
set
|
1553 |
+
Lets you set values for one or more of an instance's state properties.
|
1554 |
+
|
1555 |
+
DIFFERENT USAGES
|
1556 |
+
|
1557 |
+
`Set Values for One or More Properties with a Names/Values Object`
|
1558 |
+
........................................
|
1559 |
+
myInstance.set (propertyNamesValuesOBJ);
|
1560 |
+
........................................
|
1561 |
+
|
1562 |
+
`Set the Value for a Property with Name and Value Arguments`
|
1563 |
+
......................................................
|
1564 |
+
myInstance.set (propertyNameSTR,propertyValueANYTYPE);
|
1565 |
+
......................................................
|
1566 |
+
|
1567 |
+
`Set Values for Multiple Properties with Multiple Name and Value Arguments`
|
1568 |
+
.........................................
|
1569 |
+
myInstance.set (
|
1570 |
+
property1NameSTR,property1ValueANYTYPE,
|
1571 |
+
property2NameSTR,property2ValueANYTYPE,
|
1572 |
+
... ... ...
|
1573 |
+
propertyNNameSTR,propertyNValueANYTYPE
|
1574 |
+
);
|
1575 |
+
.........................................
|
1576 |
+
|
1577 |
+
`Set the Same Value for Multiple Properties`
|
1578 |
+
.........................................................
|
1579 |
+
myInstance.set (propertyNamesARRAY,propertyValueANYTYPE);
|
1580 |
+
.........................................................
|
1581 |
+
|
1582 |
+
Set Values for One or More Properties with a Names/Values Object
|
1583 |
+
In the standard usage, a single =propertyNamesValuesOBJ= parameter can be passed to the =set= method in order to set values for one or more properties.
|
1584 |
+
|
1585 |
+
SYNTAX
|
1586 |
+
........................................
|
1587 |
+
myInstance.set (propertyNamesValuesOBJ);
|
1588 |
+
........................................
|
1589 |
+
|
1590 |
+
Each key of the =propertyNamesValuesOBJ= object represents the name of a state property whose value should be set, and each corresponding value represents the value that a property should be set to.
|
1591 |
+
|
1592 |
+
EXAMPLE 1
|
1593 |
+
...............................
|
1594 |
+
myWidget.set ({enabled:false});
|
1595 |
+
...............................
|
1596 |
+
|
1597 |
+
In the above example, the =set= method is being used to set the value of just one property - the =enabled= property of a widget instance.
|
1598 |
+
|
1599 |
+
EXAMPLE 2
|
1600 |
+
................
|
1601 |
+
mySlider.set ({
|
1602 |
+
maxValue:100,
|
1603 |
+
minValue:0,
|
1604 |
+
value:23
|
1605 |
+
});
|
1606 |
+
................
|
1607 |
+
|
1608 |
+
In the above example, the =set= method is being used to set values for multiple properties - the =maxValue=, =minValue=, and =value= properties of a slider widget instance.
|
1609 |
+
|
1610 |
+
Set the Value for a Property with Name and Value Arguments
|
1611 |
+
The value of a state property can be set by providing two parameters to the =set= method: a string parameter specifying the name of a property, and a value parameter that can be of any type.
|
1612 |
+
|
1613 |
+
SYNTAX
|
1614 |
+
......................................................
|
1615 |
+
myInstance.set (propertyNameSTR,propertyValueANYTYPE);
|
1616 |
+
......................................................
|
1617 |
+
|
1618 |
+
This variation of the =set= method is particularly useful in cases where you wish to use a variable or an expression to determine the state property whose value should be set. Consider the following example...
|
1619 |
+
|
1620 |
+
EXAMPLE
|
1621 |
+
..............................................................
|
1622 |
+
MyClass.prototype.increment = function (propertyName,amount) {
|
1623 |
+
this.set (propertyName,this.get (propertyName) + amount);
|
1624 |
+
}
|
1625 |
+
..............................................................
|
1626 |
+
|
1627 |
+
In the above example, a generic incrementer instance method is being implemented. It receives a =propertyName= parameter that specifies the state property to increment, and it passes the value of this parameter as the first parameter in the call to the =set= method.
|
1628 |
+
|
1629 |
+
Slightly Less Performant
|
1630 |
+
This variation of the =set= method is very slightly less performant than the variation that accepts a single =propertyNamesValuesOBJ= parameter.
|
1631 |
+
|
1632 |
+
This variation is offered primarily as a convenience for when the names of properties to be set need to be supplied through variables or expressions. While there is not much cost to using this variation when not necessary, it is advised to generally use the form that accepts a =propertyNamesValuesOBJ= parameter whenever possible (see `Set Values for One or More Properties with a Names/Values Object`).
|
1633 |
+
|
1634 |
+
Set Values for Multiple Properties with Multiple Name and Value Arguments
|
1635 |
+
The values for an arbitrary number of state properties can be set by providing the names and values of the properties using an arbitrary number of name-value pair arguments, where even numbered arguments are property names and odd numbered arguments are property values.
|
1636 |
+
|
1637 |
+
SYNTAX
|
1638 |
+
.........................................
|
1639 |
+
myInstance.set (
|
1640 |
+
property1NameSTR,property1ValueANYTYPE,
|
1641 |
+
property2NameSTR,property2ValueANYTYPE,
|
1642 |
+
... ... ...
|
1643 |
+
propertyNNameSTR,propertyNValueANYTYPE
|
1644 |
+
);
|
1645 |
+
.........................................
|
1646 |
+
|
1647 |
+
This variation of the =set= method is an extension of the variation that lets you `set the value for a property with name and value arguments`, and has the same benefits and performance considerations.
|
1648 |
+
|
1649 |
+
Set the Same Value for Multiple Properties
|
1650 |
+
The same value can be set for multiple state properties by specifying the names of the properties that should all be set to the same value in a =propertyNamesARRAY= parameter, and by specifying the value they should all be set to in a =propertyValueANYTYPE= parameter.
|
1651 |
+
|
1652 |
+
SYNTAX
|
1653 |
+
.........................................................
|
1654 |
+
myInstance.set (propertyNamesARRAY,propertyValueANYTYPE);
|
1655 |
+
.........................................................
|
1656 |
+
|
1657 |
+
EXAMPLE
|
1658 |
+
..............................................................
|
1659 |
+
myWidget.set (['initialized','ready','enabled','busy'],false);
|
1660 |
+
..............................................................
|
1661 |
+
|
1662 |
+
In the above example, the properties =initialized=, =ready=, =enabled=, and =busy= of a widget instance are all being set to =false=.
|
1663 |
+
|
1664 |
+
This variation of the =set= method can be useful in cases where you wish to set a good number of properties to the same value and where it would be more concise to use this form, or in cases where you are receiving an array of properties that should be set to some desired value. This variation can also be convenient when the value that you wish to set multiple properties to is the result of an expression and where you would otherwise need to create a local variable in order to avoid recalculating the expression for each property.
|
1665 |
+
|
1666 |
+
INSTEAD OF...
|
1667 |
+
.......................................................................................
|
1668 |
+
var initValue = env.config.hasOwnProperty ('initValue') ? env.config.initValue : false;
|
1669 |
+
myInstance.set ({
|
1670 |
+
foo:initValue,
|
1671 |
+
bar:initValue,
|
1672 |
+
baz:initValue
|
1673 |
+
});
|
1674 |
+
.......................................................................................
|
1675 |
+
|
1676 |
+
USE...
|
1677 |
+
.........................................................................
|
1678 |
+
myInstance.set (
|
1679 |
+
['foo','bar','baz'],
|
1680 |
+
env.config.hasOwnProperty ('initValue') ? env.config.initValue : false
|
1681 |
+
);
|
1682 |
+
.........................................................................
|
1683 |
+
|
1684 |
+
NOTES
|
1685 |
+
- see the companion =get= instance method
|
1686 |
+
- see also the =Uize.Class.get= and =Uize.Class.set= static methods
|
1687 |
+
|
1688 |
+
Static Methods
|
1689 |
+
Uize.Class.set
|
1690 |
+
Lets you set initial values for one or more of a class's state properties.
|
1691 |
+
|
1692 |
+
DIFFERENT USAGES
|
1693 |
+
|
1694 |
+
`Set Initial Values for One or More Properties with a Names/Values Object`
|
1695 |
+
.....................................
|
1696 |
+
MyClass.set (propertyNamesValuesOBJ);
|
1697 |
+
.....................................
|
1698 |
+
|
1699 |
+
`Set the Initial Value for a Property with Name and Value Arguments`
|
1700 |
+
...................................................
|
1701 |
+
MyClass.set (propertyNameSTR,propertyValueANYTYPE);
|
1702 |
+
...................................................
|
1703 |
+
|
1704 |
+
`Set Initial Values for Multiple Properties with Multiple Name and Value Arguments`
|
1705 |
+
.........................................
|
1706 |
+
MyClass.set (
|
1707 |
+
property1NameSTR,property1ValueANYTYPE,
|
1708 |
+
property2NameSTR,property2ValueANYTYPE,
|
1709 |
+
... ... ...
|
1710 |
+
propertyNNameSTR,propertyNValueANYTYPE
|
1711 |
+
);
|
1712 |
+
.........................................
|
1713 |
+
|
1714 |
+
`Set the Same Initial Value for Multiple Properties`
|
1715 |
+
......................................................
|
1716 |
+
MyClass.set (propertyNamesARRAY,propertyValueANYTYPE);
|
1717 |
+
......................................................
|
1718 |
+
|
1719 |
+
Set Initial Values for One or More Properties with a Names/Values Object
|
1720 |
+
In the standard usage, a single =propertyNamesValuesOBJ= parameter can be passed to the =Uize.Class.set= method in order to set initial values for one or more properties.
|
1721 |
+
|
1722 |
+
SYNTAX
|
1723 |
+
.....................................
|
1724 |
+
MyClass.set (propertyNamesValuesOBJ);
|
1725 |
+
.....................................
|
1726 |
+
|
1727 |
+
Each key of the =propertyNamesValuesOBJ= object represents the name of a state property whose initial value should be set, and each corresponding value represents the initial value that should be set for a property.
|
1728 |
+
|
1729 |
+
EXAMPLE 1
|
1730 |
+
....................................
|
1731 |
+
MyWidgetClass.set ({enabled:false});
|
1732 |
+
....................................
|
1733 |
+
|
1734 |
+
In the above example, the =Uize.Class.set= method is being used to set the initial value for just one property - the =enabled= property of a widget class.
|
1735 |
+
|
1736 |
+
EXAMPLE 2
|
1737 |
+
.............................
|
1738 |
+
Uize.Widget.Bar.Slider.set ({
|
1739 |
+
maxValue:100,
|
1740 |
+
minValue:0,
|
1741 |
+
value:0
|
1742 |
+
});
|
1743 |
+
.............................
|
1744 |
+
|
1745 |
+
In the above example, the =Uize.Class.set= method is being used to set initial values for multiple properties - the =maxValue=, =minValue=, and =value= properties of the =Uize.Widget.Bar.Slider= widget class.
|
1746 |
+
|
1747 |
+
Set the Initial Value for a Property with Name and Value Arguments
|
1748 |
+
The initial value for a state property can be set by providing two parameters to the =Uize.Class.set= method: a string parameter specifying the name of a property, and a value parameter that can be of any type.
|
1749 |
+
|
1750 |
+
SYNTAX
|
1751 |
+
...................................................
|
1752 |
+
MyClass.set (propertyNameSTR,propertyValueANYTYPE);
|
1753 |
+
...................................................
|
1754 |
+
|
1755 |
+
This variation of the =Uize.Class.set= method is particularly useful in cases where you wish to use a variable or an expression to determine the state property whose initial value should be set. Consider the following example...
|
1756 |
+
|
1757 |
+
EXAMPLE
|
1758 |
+
............................................................
|
1759 |
+
MyClass.increment = function (propertyName,amount) {
|
1760 |
+
this.set (propertyName,this.get (propertyName) + amount);
|
1761 |
+
}
|
1762 |
+
............................................................
|
1763 |
+
|
1764 |
+
In the above example, a generic incrementer static method is being implemented. It receives a =propertyName= parameter that specifies the state property whose initial value should be incremented, and it passes the value of this parameter as the first parameter in the call to the =Uize.Class.set= method.
|
1765 |
+
|
1766 |
+
Slightly Less Performant
|
1767 |
+
This variation of the =Uize.Class.set= method is very slightly less performant than the variation that accepts a single =propertyNamesValuesOBJ= parameter.
|
1768 |
+
|
1769 |
+
This variation is offered primarily as a convenience for when the names of properties whose initial values are to be set need to be supplied through variables or expressions. While there is not much cost to using this variation when not necessary, it is advised to generally use the form that accepts a =propertyNamesValuesOBJ= parameter whenever possible (see `Set Initial Values for One or More Properties with a Names/Values Object`).
|
1770 |
+
|
1771 |
+
Set Initial Values for Multiple Properties with Multiple Name and Value Arguments
|
1772 |
+
The initial values for an arbitrary number of state properties can be set by providing the names and values of the properties using an arbitrary number of name-value pair arguments, where even numbered arguments are property names and odd numbered arguments are property values.
|
1773 |
+
|
1774 |
+
SYNTAX
|
1775 |
+
.........................................
|
1776 |
+
MyClass.set (
|
1777 |
+
property1NameSTR,property1ValueANYTYPE,
|
1778 |
+
property2NameSTR,property2ValueANYTYPE,
|
1779 |
+
... ... ...
|
1780 |
+
propertyNNameSTR,propertyNValueANYTYPE
|
1781 |
+
);
|
1782 |
+
.........................................
|
1783 |
+
|
1784 |
+
This variation of the =Uize.Class.set= method is an extension of the variation that lets you `set the initial value for a property with name and value arguments`, and has the same benefits and performance considerations.
|
1785 |
+
|
1786 |
+
Set the Same Initial Value for Multiple Properties
|
1787 |
+
The same initial value can be set for multiple state properties by specifying the names of the properties whose initial values should all be set to the same value in a =propertyNamesARRAY= parameter, and by specifying the initial value that should be set for them all in a =propertyValueANYTYPE= parameter.
|
1788 |
+
|
1789 |
+
SYNTAX
|
1790 |
+
......................................................
|
1791 |
+
MyClass.set (propertyNamesARRAY,propertyValueANYTYPE);
|
1792 |
+
......................................................
|
1793 |
+
|
1794 |
+
EXAMPLE
|
1795 |
+
...................................................................
|
1796 |
+
MyWidgetClass.set (['initialized','ready','enabled','busy'],false);
|
1797 |
+
...................................................................
|
1798 |
+
|
1799 |
+
In the above example, the initial value for the properties =initialized=, =ready=, =enabled=, and =busy= of a widget class is being set to =false=.
|
1800 |
+
|
1801 |
+
This variation of the =Uize.Class.set= method can be useful in cases where you wish to set the initial value for a good number of properties to the same value and where it would be more concise to use this form, or in cases where you are receiving an array of properties whose initial values should all be set to some desired value. This variation can also be convenient when the initial value that you wish to set for multiple properties is the result of an expression and where you would otherwise need to create a local variable in order to avoid recalculating the expression for each property.
|
1802 |
+
|
1803 |
+
INSTEAD OF...
|
1804 |
+
.......................................................................................
|
1805 |
+
var initValue = env.config.hasOwnProperty ('initValue') ? env.config.initValue : false;
|
1806 |
+
MyClass.set ({
|
1807 |
+
foo:initValue,
|
1808 |
+
bar:initValue,
|
1809 |
+
baz:initValue
|
1810 |
+
});
|
1811 |
+
.......................................................................................
|
1812 |
+
|
1813 |
+
USE...
|
1814 |
+
.........................................................................
|
1815 |
+
MyClass.set (
|
1816 |
+
['foo','bar','baz'],
|
1817 |
+
env.config.hasOwnProperty ('initValue') ? env.config.initValue : false
|
1818 |
+
);
|
1819 |
+
.........................................................................
|
1820 |
+
|
1821 |
+
NOTES
|
1822 |
+
- see the companion =Uize.Class.get= static method
|
1823 |
+
- see also the =get= and =set= instance methods
|
1824 |
+
|
1825 |
+
*/
|
1826 |
+
};
|
1827 |
+
|
1828 |
+
_class.toggle = _classPrototype.toggle = function (_propertyName) {
|
1829 |
+
var _value = !this.get (_propertyName);
|
1830 |
+
this.set (_propertyName,_value);
|
1831 |
+
return _value;
|
1832 |
+
/*?
|
1833 |
+
Instance Methods
|
1834 |
+
toggle
|
1835 |
+
Toggles the value of the specified boolean instance state property.
|
1836 |
+
|
1837 |
+
SYNTAX
|
1838 |
+
.......................................................
|
1839 |
+
toggledValueBOOL = myInstance.toggle (propertyNameSTR);
|
1840 |
+
.......................................................
|
1841 |
+
|
1842 |
+
The =toggle= instance method is provided purely as a convenience. The following two statements are equivalent...
|
1843 |
+
|
1844 |
+
.............................................................
|
1845 |
+
myInstance.toggle ('myProperty');
|
1846 |
+
myInstance.set ({myProperty:!myInstance.get ('myProperty')});
|
1847 |
+
.............................................................
|
1848 |
+
|
1849 |
+
As you can see, using the =toggle= method produces more concise code.
|
1850 |
+
|
1851 |
+
Static Methods
|
1852 |
+
Uize.Class.toggle
|
1853 |
+
Toggles the value of the specified boolean static state property.
|
1854 |
+
|
1855 |
+
SYNTAX
|
1856 |
+
.......................................................
|
1857 |
+
toggledValueBOOL = Uize.Class.toggle (propertyNameSTR);
|
1858 |
+
.......................................................
|
1859 |
+
|
1860 |
+
The =Uize.Class.toggle= static method is provided purely as a convenience. The following two statements are equivalent...
|
1861 |
+
|
1862 |
+
.............................................................
|
1863 |
+
Uize.Class.toggle ('myProperty');
|
1864 |
+
Uize.Class.set ({myProperty:!Uize.Class.get ('myProperty')});
|
1865 |
+
.............................................................
|
1866 |
+
|
1867 |
+
As you can see, using the =Uize.Class.toggle= method produces more concise code.
|
1868 |
+
*/
|
1869 |
+
};
|
1870 |
+
|
1871 |
+
/*** Public Instance Methods ***/
|
1872 |
+
_classPrototype.kill = function () {
|
1873 |
+
var _instanceId = this.instanceId;
|
1874 |
+
_globalEval ('if(typeof ' + _instanceId + '!=\'undefined\')' + _instanceId + '=null');
|
1875 |
+
/*?
|
1876 |
+
Instance Methods
|
1877 |
+
kill
|
1878 |
+
Nulls out the global variable (or property of the =window= object) of the name =instanceId=.
|
1879 |
+
|
1880 |
+
This method may be useful if global (or window object level) references are made to instances of a class, usually for the purpose of group management, or the implementation of certain kinds of state exclusivity amongst instances of a class. This method is also intended to be overridden by subclasses where additional destructor style code may be desired.
|
1881 |
+
*/
|
1882 |
+
};
|
1883 |
+
|
1884 |
+
/*** Inheritance Mechanism ***/
|
1885 |
+
function _createSubclass (_class,_alphastructor,_omegastructor) {
|
1886 |
+
function _toString () {
|
1887 |
+
var
|
1888 |
+
_propertiesLines = [],
|
1889 |
+
_Uize_toString = _Uize.toString
|
1890 |
+
;
|
1891 |
+
_forEach (
|
1892 |
+
this.get (),
|
1893 |
+
function (_propertyValue,_propertyName) {
|
1894 |
+
_propertiesLines.push (
|
1895 |
+
_propertyName + ' : ' +
|
1896 |
+
(
|
1897 |
+
_propertyValue && (_isInstance (_propertyValue) || _isFunction (_propertyValue))
|
1898 |
+
? _Uize_toString.call (_propertyValue)
|
1899 |
+
: _propertyValue
|
1900 |
+
)
|
1901 |
+
);
|
1902 |
+
}
|
1903 |
+
);
|
1904 |
+
return _Uize_toString.call (this) + '\n\n' + _propertiesLines.sort ().join ('\n');
|
1905 |
+
}
|
1906 |
+
|
1907 |
+
function _valueOf () {
|
1908 |
+
return this [_getPropertyPrivateName (this,'value')];
|
1909 |
+
/*?
|
1910 |
+
Instance Methods
|
1911 |
+
toString Intrinsic Method
|
1912 |
+
Returns a string, providing summary info for the instance on which the method is called.
|
1913 |
+
|
1914 |
+
SYNTAX
|
1915 |
+
............................................
|
1916 |
+
instanceSummarySTR = myInstance.toString ();
|
1917 |
+
............................................
|
1918 |
+
|
1919 |
+
The string returned by this method provides a summary that includes the instance's class name and the state of its state properties. Among other things, this method provides a convenient and lightweight way to gather information about instances of =Uize.Class= subclasses during debugging and troubleshooting. The =toString Intrinsic Method= is invoked automatically in certain contexts in order to convert an object to a string form, such as when alerting an object using the =alert= global function.
|
1920 |
+
|
1921 |
+
EXAMPLE
|
1922 |
+
.............................
|
1923 |
+
alert (page.children.slider);
|
1924 |
+
.............................
|
1925 |
+
|
1926 |
+
In the above example, if the =page= widget has a =slider= child widget that is an instance of the class =Uize.Widget.Bar.Slider=, then the output of the =alert= statement could look something like...
|
1927 |
+
|
1928 |
+
EXAMPLE OUTPUT
|
1929 |
+
........................................
|
1930 |
+
[object Uize.Widget.Bar.Slider]
|
1931 |
+
|
1932 |
+
built : true
|
1933 |
+
busy : inherit
|
1934 |
+
busyInherited : false
|
1935 |
+
confirm : undefined
|
1936 |
+
container : undefined
|
1937 |
+
decimalPlacesToDisplay : undefined
|
1938 |
+
enabled : inherit
|
1939 |
+
enabledInherited : true
|
1940 |
+
html : undefined
|
1941 |
+
idPrefix : page_slider
|
1942 |
+
idPrefixConstruction : concatenated
|
1943 |
+
inDrag : false
|
1944 |
+
increments : 1
|
1945 |
+
inform : undefined
|
1946 |
+
insertionMode: undefined
|
1947 |
+
localized : undefined
|
1948 |
+
maxValidValue : undefined
|
1949 |
+
maxValue : 200
|
1950 |
+
minValidValue : undefined
|
1951 |
+
minValue : 0
|
1952 |
+
name : slider
|
1953 |
+
nodeMap : undefined
|
1954 |
+
orientation : vertical
|
1955 |
+
parent : [class UizeSite.Page.Example]
|
1956 |
+
restTime : 250
|
1957 |
+
scaleFunc : [object Function]
|
1958 |
+
value : 0
|
1959 |
+
valueFunc : [object Function]
|
1960 |
+
wired : true
|
1961 |
+
........................................
|
1962 |
+
|
1963 |
+
In certain contexts, providing a reference to a =Uize.Class= subclass instance as a parameter to some method will result in the =valueOf Intrinsic Method= of that instance being invoked in order to coerce it to a simple value. If it is your desire to have the instance summary be used rather than the instance's value, then you should explicitly call the =toString Intrinsic Method=, as follows...
|
1964 |
+
|
1965 |
+
EXAMPLE
|
1966 |
+
........................................................................................
|
1967 |
+
Uize.Node.setInnerHtml ('sliderWidgetSummaryForDebug',page.children.slider.toString ());
|
1968 |
+
Uize.Node.setInnerHtml ('sliderWidgetCurrentValue',page.children.slider);
|
1969 |
+
........................................................................................
|
1970 |
+
|
1971 |
+
In this example, the =sliderWidgetSummaryForDebug= node will contain the summary info for the instance, while the =sliderWidgetCurrentValue= node will just show the slider widget's current value.
|
1972 |
+
|
1973 |
+
NOTES
|
1974 |
+
- see also the =Uize.toString= static intrinsic method
|
1975 |
+
|
1976 |
+
valueOf Intrinsic Method
|
1977 |
+
Returns the value of the instance's =value= state property.
|
1978 |
+
|
1979 |
+
SYNTAX
|
1980 |
+
.............................................
|
1981 |
+
instanceValueANYTYPE = myInstance.valueOf ();
|
1982 |
+
.............................................
|
1983 |
+
|
1984 |
+
The =valueOf Intrinsic Method= is invoked automatically in certain contexts in order to convert an object to a value, such as when using an object reference in an expression.
|
1985 |
+
|
1986 |
+
EXAMPLE
|
1987 |
+
..........................................................................
|
1988 |
+
var markedUpPrice = price * (1 + page.children.markupPercentSlider / 100);
|
1989 |
+
..........................................................................
|
1990 |
+
|
1991 |
+
In the above example, the page widget has a slider child widget that is an instance of the class =Uize.Widget.Bar.Slider= and that lets the user choose a markup percentage between =0= and =100=. In the above expression, the slider widget is being divided by 100. Rather than giving you a hundred *really* tiny slider widgets (not all that useful), JavaScript automatically invokes the =valueOf Intrinsic Method=. The implementation of this instance method in the =Uize.Class= base class results in the slider's current value being returned so that it can then be used in the expression.
|
1992 |
+
|
1993 |
+
The following three statements are equivalent...
|
1994 |
+
|
1995 |
+
....................................................................................
|
1996 |
+
markedUpPrice = price * (1 + page.children.markupPercentSlider.get ('value') / 100);
|
1997 |
+
markedUpPrice = price * (1 + page.children.markupPercentSlider.valueOf () / 100);
|
1998 |
+
markedUpPrice = price * (1 + page.children.markupPercentSlider / 100);
|
1999 |
+
....................................................................................
|
2000 |
+
|
2001 |
+
In certain contexts, providing a reference to a =Uize.Class= subclass instance as a parameter to some method will result in the =toString Intrinsic Method= of that instance being invoked in order to resolve it to a string value. If it is your desire to have the value used rather than the instance summary, then you should explicitly call the =valueOf Intrinsic Method=, as follows...
|
2002 |
+
|
2003 |
+
EXAMPLE
|
2004 |
+
.....................................................
|
2005 |
+
alert (page.children.markupPercentSlider.valueOf ());
|
2006 |
+
.....................................................
|
2007 |
+
|
2008 |
+
In this example, the current value of the =markupPercentSlider= widget will be displayed in the alert dialog, rather than the instance summary. You can also use shortcuts, as follows...
|
2009 |
+
|
2010 |
+
COERCE TO NUMBER
|
2011 |
+
...........................................
|
2012 |
+
alert (+page.children.markupPercentSlider);
|
2013 |
+
...........................................
|
2014 |
+
|
2015 |
+
COERCE TO STRING
|
2016 |
+
................................................
|
2017 |
+
alert (page.children.titleTextInputWidget + '');
|
2018 |
+
................................................
|
2019 |
+
|
2020 |
+
Both of the above examples will cause JavaScript to invoke the =valueOf Intrinsic Method= rather than the =toString Intrinsic Method=, but the first will coerce the value to a number type, while the second will coerce the value to a string type.
|
2021 |
+
|
2022 |
+
NOTES
|
2023 |
+
- compare to the =toString Intrinsic Method=, and the =Uize.toString= static intrinsic method
|
2024 |
+
- see also the =Uize.Class.valueOf= static intrinsic method
|
2025 |
+
- if the instance's class does not register a =value= state property, then this method will return the value of the instance's =value= property, and if the instance has no =value= property, then this method will simply return =undefined=
|
2026 |
+
|
2027 |
+
Static Methods
|
2028 |
+
Uize.Class.valueOf
|
2029 |
+
Returns the value of the class' =value= state property.
|
2030 |
+
|
2031 |
+
SYNTAX
|
2032 |
+
.......................................
|
2033 |
+
classValueANYTYPE = MyClass.valueOf ();
|
2034 |
+
.......................................
|
2035 |
+
|
2036 |
+
The =Uize.Class.valueOf= static intrinsic method is invoked automatically in certain contexts in order to convert a class to a value, such as when using a class reference in an expression (eg. =Uize.Widget.Bar.Slider + 0=). This static method is implemented primarily to provide parity with the =valueOf Intrinsic Method=. Its behavior is largely equivalent to that of the instance method, excepting that it applies to the static value of the =value= state property.
|
2037 |
+
|
2038 |
+
NOTES
|
2039 |
+
- compare to the =toString Intrinsic Method=, and the =Uize.toString= static intrinsic method
|
2040 |
+
- see also the =valueOf Intrinsic Method=
|
2041 |
+
- if the class does not register a =value= state property, then this method will return the value of the class' =value= property, and if the class has no =value= property, then this method will simply return =undefined=
|
2042 |
+
*/
|
2043 |
+
}
|
2044 |
+
|
2045 |
+
var
|
2046 |
+
_classPrototype = _class.prototype,
|
2047 |
+
_subclass = _noNew (
|
2048 |
+
function () {
|
2049 |
+
for (
|
2050 |
+
var _alphastructorNo = -1, _alphastructorsLength = _alphastructors.length;
|
2051 |
+
++_alphastructorNo < _alphastructorsLength;
|
2052 |
+
)
|
2053 |
+
_alphastructors [_alphastructorNo].apply (this,arguments)
|
2054 |
+
;
|
2055 |
+
for (
|
2056 |
+
var _omegastructorNo = -1, _omegastructorsLength = _omegastructors.length;
|
2057 |
+
++_omegastructorNo < _omegastructorsLength;
|
2058 |
+
)
|
2059 |
+
_omegastructors [_omegastructorNo].apply (this,arguments)
|
2060 |
+
;
|
2061 |
+
}
|
2062 |
+
),
|
2063 |
+
_subclassPrototype = _subclass.prototype
|
2064 |
+
;
|
2065 |
+
|
2066 |
+
/*** Inherit static properties (excluding prototype) and methods from base class ***/
|
2067 |
+
var
|
2068 |
+
_propertyValue,
|
2069 |
+
_nonInheritableStatics = _class.nonInheritableStatics || _sacredEmptyObject
|
2070 |
+
;
|
2071 |
+
for (var _property in _class)
|
2072 |
+
if (
|
2073 |
+
!_nonInheritableStatics [_property] &&
|
2074 |
+
(_propertyValue = _class [_property]) != _classPrototype &&
|
2075 |
+
!(
|
2076 |
+
_isFunction (_propertyValue) &&
|
2077 |
+
_propertyValue.moduleName &&
|
2078 |
+
/[A-Z]/.test (_property.charAt (0))
|
2079 |
+
)
|
2080 |
+
)
|
2081 |
+
_subclass [_property] = _clone (_propertyValue)
|
2082 |
+
;
|
2083 |
+
|
2084 |
+
/*** Prepare instance properties and methods ***/
|
2085 |
+
/*** Inherit instance properties and methods from base class (from prototype) ***/
|
2086 |
+
_copyInto (_subclassPrototype,_classPrototype);
|
2087 |
+
|
2088 |
+
/*** Make sure toString and valueOf are copied ***/
|
2089 |
+
/* NOTE: in IE, toString and valueOf aren't enumerable properties of the prototype object */
|
2090 |
+
_subclassPrototype.toString = _toString;
|
2091 |
+
_subclassPrototype.valueOf = _valueOf;
|
2092 |
+
|
2093 |
+
/*** Non-inherited Public Instance Properties ***/
|
2094 |
+
_subclassPrototype.Class = _subclass;
|
2095 |
+
/*?
|
2096 |
+
Instance Properties
|
2097 |
+
Class
|
2098 |
+
A reference to the class's constructor.
|
2099 |
+
|
2100 |
+
You can use this to interrogate an object instance to see if it is of a certain class, as illustrated in the following example...
|
2101 |
+
|
2102 |
+
EXAMPLE
|
2103 |
+
.......................................................
|
2104 |
+
if (myInstance.Class == Uize.Widget.Bar.Slider) {
|
2105 |
+
// do something for sliders
|
2106 |
+
} else if (myInstance.Class == Uize.Widget.Tree.Menu) {
|
2107 |
+
// do something for tree menus
|
2108 |
+
} else if (myInstance.Class == Uize.Widget.ImageWipe) {
|
2109 |
+
// do something for wipes
|
2110 |
+
}
|
2111 |
+
.......................................................
|
2112 |
+
|
2113 |
+
The above example is admittedly a little abstract. It is hard to imagine the exact scenario that may come up where some code is handed object instances where their class will not be known. But, when such a case comes up, the =Class= property has got your back.
|
2114 |
+
*/
|
2115 |
+
|
2116 |
+
/*** Non-inherited Public Static Properties ***/
|
2117 |
+
_subclass.nonInheritableStatics = {_singletons:1,nonInheritableStatics:1,toString:0,valueOf:0};
|
2118 |
+
/*?
|
2119 |
+
Static Properties
|
2120 |
+
Uize.Class.nonInheritableStatics
|
2121 |
+
A lookup object, automatically created for a class, in which you can register the static features (methods or properties) of the class that should *not* be inherited when that class is subclassed.
|
2122 |
+
|
2123 |
+
Each property of the =Uize.Class.nonInheritableStatics= lookup object represents a single static feature of the class that should not be inherited by subclasses, where the name of each property should be the name of a static feature (excluding the module name), and the value of each property should be a truthy value (such as =true=, =1=, ='foo'=, =[]=, ={}=, etc.). After a class has been created, non-inheritable statics can be registered for that class by assigning properties to the class' =MyClass.nonInheritableStatics= static property, as shown in the example below...
|
2124 |
+
|
2125 |
+
EXAMPLE
|
2126 |
+
...........................................................................
|
2127 |
+
MyClass = Uize.Class.subclass ();
|
2128 |
+
MyClass.someUtilityFunction = function () {
|
2129 |
+
// do something of great utility
|
2130 |
+
};
|
2131 |
+
MyClass.nonInheritableStatics.someUtilityFunction = 1;
|
2132 |
+
|
2133 |
+
MyClassSubclass = MyClass.subclass ();
|
2134 |
+
alert (MyClassSubclass.someUtilityFunction); // alerts the text "undefined"
|
2135 |
+
...........................................................................
|
2136 |
+
|
2137 |
+
In the above example, the =MyClass.someUtilityFunction= static method of the class =MyClass= has been registered as a non-inheritable static. This is done by the statement =MyClass.nonInheritableStatics.someUtilityFunction = 1=. Now, when the =MyClassSubclass= class is created by calling the =MyClass.subclass= method, the new subclass that is created does not get the =someUtilityFunction= static feature. Therefore, the =alert= statement displays the text "undefined" in the alert dialog.
|
2138 |
+
|
2139 |
+
nonInheritableStatics is a Non-inheritable Static
|
2140 |
+
When a class is created, the =MyClass.nonInheritableStatics= static property is automatically initialized on that class to a fresh object with the value ={nonInheritableStatics:1}=.
|
2141 |
+
|
2142 |
+
This initial mapping means that the =MyClass.nonInheritableStatics= static property is, itself, not inheritable by subclasses - subclasses get their own fresh object. So, in our example, when the =MyClassSubclass= subclass is created, its fresh =MyClassSubclass.nonInheritableStatics= property does *not* have an entry for the =someUtilityFunction= static feature, because it does not have that static feature and the contents of the =MyClass.someUtilityFunction= object is not inherited by the =MyClassSubclass= class.
|
2143 |
+
*/
|
2144 |
+
|
2145 |
+
_subclass.superclass = _class;
|
2146 |
+
/*?
|
2147 |
+
Static Properties
|
2148 |
+
Uize.Class.superclass
|
2149 |
+
A reference to the class' superclass.
|
2150 |
+
|
2151 |
+
SYNTAX
|
2152 |
+
....................................
|
2153 |
+
superclassOBJ = classOBJ.superclass;
|
2154 |
+
....................................
|
2155 |
+
|
2156 |
+
EXAMPLE
|
2157 |
+
............................................................................
|
2158 |
+
var MyWidgetClass = Uize.Widget.subclass ();
|
2159 |
+
alert (MyWidgetClass.superclass == Uize.Widget); // displays the text "true"
|
2160 |
+
............................................................................
|
2161 |
+
*/
|
2162 |
+
|
2163 |
+
/*** Non-inherited Public Static Methods ***/
|
2164 |
+
_subclass.toString = _toString;
|
2165 |
+
_subclass.valueOf = _valueOf;
|
2166 |
+
|
2167 |
+
/*** Initialize Alphastructors and Omegastructors ***/
|
2168 |
+
var
|
2169 |
+
_alphastructors = _subclass._alphastructors = (_class._alphastructors || _sacredEmptyArray).concat (),
|
2170 |
+
_omegastructors = _subclass._omegastructors = (_class._omegastructors || _sacredEmptyArray).concat ()
|
2171 |
+
;
|
2172 |
+
_alphastructor && _alphastructors.push (_alphastructor);
|
2173 |
+
_omegastructor && _omegastructors.push (_omegastructor);
|
2174 |
+
|
2175 |
+
_subclass._propertyProfilesByPrivateNames || (_subclass._propertyProfilesByPrivateNames = {});
|
2176 |
+
_subclass._propertyProfilesByPublicNames || (_subclass._propertyProfilesByPublicNames = {});
|
2177 |
+
|
2178 |
+
return _subclass;
|
2179 |
+
};
|
2180 |
+
|
2181 |
+
_class.subclass = function (_alphastructor,_omegastructor) {
|
2182 |
+
return _createSubclass (this,_alphastructor,_omegastructor);
|
2183 |
+
/*?
|
2184 |
+
Static Methods
|
2185 |
+
Uize.Class.subclass
|
2186 |
+
Lets you subclass the =Uize.Class= base class or any subclass of =Uize.Class=.
|
2187 |
+
|
2188 |
+
SYNTAX
|
2189 |
+
......................................................
|
2190 |
+
MyClass = Uize.Class.subclass (subclassConstructorFN);
|
2191 |
+
......................................................
|
2192 |
+
|
2193 |
+
Consider the following example...
|
2194 |
+
|
2195 |
+
EXAMPLE
|
2196 |
+
.......................................
|
2197 |
+
MyClass = Uize.Class.subclass (
|
2198 |
+
function () {
|
2199 |
+
this.foo = 'How unoriginal!';
|
2200 |
+
}
|
2201 |
+
);
|
2202 |
+
|
2203 |
+
MySubclass = MyClass.subclass (
|
2204 |
+
function () {
|
2205 |
+
this.bar = this.foo + ' Indeed!';
|
2206 |
+
}
|
2207 |
+
);
|
2208 |
+
.......................................
|
2209 |
+
|
2210 |
+
In the above example, =MySubclass= is a subclass of =MyClass=, which is in turn a subclass of the =Uize.Class= base class. Now, when an instance of =MySubSubclass= gets created, the constructor of =MyClass= and then the constructor of =MySubSubclass= will be executed in the initialization of the instance, and the instance will have both =foo= and =bar= properties, where the =bar= property will have a value of "How unoriginal! Indeed!".
|
2211 |
+
*/
|
2212 |
+
};
|
2213 |
+
|
2214 |
+
_class.singleton = function (_scope,_properties) {
|
2215 |
+
var
|
2216 |
+
_singletons = this._singletons || (this._singletons = {}),
|
2217 |
+
_singleton = _singletons [_scope || (_scope = '')]
|
2218 |
+
;
|
2219 |
+
_singleton
|
2220 |
+
? _properties && _singleton.set (_properties)
|
2221 |
+
: (_singleton = _singletons [_scope] = this (_properties))
|
2222 |
+
;
|
2223 |
+
return _singleton;
|
2224 |
+
/*?
|
2225 |
+
Static Methods
|
2226 |
+
Uize.Class.singleton
|
2227 |
+
Returns a singleton for the class for the optionally specified scope (default is empty scope).
|
2228 |
+
|
2229 |
+
DIFFERENT USAGES
|
2230 |
+
|
2231 |
+
`Get a Singleton for a Class`
|
2232 |
+
....................................
|
2233 |
+
singletonOBJ = MyClass.singleton ();
|
2234 |
+
....................................
|
2235 |
+
|
2236 |
+
`Get a Singleton for a Class for a Specific Scope`
|
2237 |
+
............................................
|
2238 |
+
singletonOBJ = MyClass.singleton (scopeSTR);
|
2239 |
+
............................................
|
2240 |
+
|
2241 |
+
`Get a Singleton for a Class for a Specific Scope, Specifying Initial State`
|
2242 |
+
..........................................................
|
2243 |
+
singletonOBJ = MyClass.singleton (scopeSTR,propertiesOBJ);
|
2244 |
+
..........................................................
|
2245 |
+
|
2246 |
+
Get a Singleton for a Class
|
2247 |
+
When no parameters are specified, this method will return a singleton for the class in the default scope.
|
2248 |
+
|
2249 |
+
SYNTAX
|
2250 |
+
....................................
|
2251 |
+
singletonOBJ = MyClass.singleton ();
|
2252 |
+
....................................
|
2253 |
+
|
2254 |
+
When the =Uize.Class.singleton= static method is called on a class, if a singleton instance has already been created for the default scope, then that instance will be returned. Otherwise, a singleton instance will be created for the default scope and then returned.
|
2255 |
+
|
2256 |
+
Get a Singleton for a Class for a Specific Scope
|
2257 |
+
When the optional =scopeSTR= parameter is specified, this method will return a singleton for the class in the specified scope.
|
2258 |
+
|
2259 |
+
SYNTAX
|
2260 |
+
............................................
|
2261 |
+
singletonOBJ = MyClass.singleton (scopeSTR);
|
2262 |
+
............................................
|
2263 |
+
|
2264 |
+
When the =Uize.Class.singleton= static method is called on a class, if a singleton instance has already been created for the specified scope, then that instance will be returned. Otherwise, a singleton instance will be created for the specified scope and then returned.
|
2265 |
+
|
2266 |
+
Get a Singleton for a Class for a Specific Scope, Specifying Initial State
|
2267 |
+
When the optional =propertiesOBJ= parameter is specified, then this method will return a singleton for the class in the specified scope, and with the state of its state properties set using the =propertiesOBJ= object.
|
2268 |
+
|
2269 |
+
SYNTAX
|
2270 |
+
..........................................................
|
2271 |
+
singletonOBJ = MyClass.singleton (scopeSTR,propertiesOBJ);
|
2272 |
+
..........................................................
|
2273 |
+
|
2274 |
+
When the =Uize.Class.singleton= static method is called on a class, if a singleton instance has already been created for the specified scope, then that instance will be set to the state specified by the =propertiesOBJ= parameter and then returned. Otherwise, a singleton instance will be created for the specified scope, with its state initialized using the =propertiesOBJ= parameter, and then returned.
|
2275 |
+
|
2276 |
+
Singleton Scope
|
2277 |
+
As a convenience, the =Uize.Class.singleton= static method lets you optionally specify a scope when getting singleton instances, using the =scopeSTR= parameter.
|
2278 |
+
|
2279 |
+
If no =scopeSTR= parameter is specified when getting a singleton for a class, then the default scope (an empty string) will be used. Therefore, the statement =MyClass.singleton ()= is equivalent to the statement =MyClass.singleton ('')=.
|
2280 |
+
|
2281 |
+
A scope provides multiple different bits of related but distributed code to get a reference to the same singleton by specifying the same scope, while still allowing other code to share references to a different singleton created using a different scope.
|
2282 |
+
*/
|
2283 |
+
};
|
2284 |
+
|
2285 |
+
return _class;
|
2286 |
+
}
|
2287 |
+
});
|
2288 |
+
|
skin/frontend/default/customproduct/js/Uize.Color.js
ADDED
@@ -0,0 +1,1515 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Color Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)1997-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Object
|
14 |
+
importance: 7
|
15 |
+
codeCompleteness: 95
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 92
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Color= module provides support for `Color Spaces`, `Color Encodings`, `Named Colors`, the =sRGB= and =HSL= color spaces, and many color encodings.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
Not a Uize Subclass
|
27 |
+
First off, it's worth emphasizing that the =Uize.Color= object is not a =Uize.Class= subclass, but a very lightweight object.
|
28 |
+
|
29 |
+
As such, the =Uize.Color= object does not support events, does not provide state properties, does not inherit subclassing facilities from the =Uize.Class= base class, etc. This object is deliberately designed to be very lightweight and to have a really tiny footprint - in the spirit of JavaScript's native objects, such as =String=, =Number=, =Date=, and the like.
|
30 |
+
|
31 |
+
Key Features
|
32 |
+
The =Uize.Color= object provides the following key features...
|
33 |
+
|
34 |
+
A Framework for Defining Color Spaces
|
35 |
+
Colors can be represented using different color models and mapping functions. These are called [[http://en.wikipedia.org/wiki/Color_space][color spaces]]. Examples of color spaces include =sRGB=, =HSL=, =HSV=, and =CMYK=, but there are many more in existence.
|
36 |
+
|
37 |
+
A Framework for Defining Color Encodings
|
38 |
+
Colors can be represented using different formats and color models. In UIZE, the combination of a color space and format is called a color encoding.
|
39 |
+
|
40 |
+
The =Uize.Color= object supports a wide variety of built-in `Color Encodings`. Multiple encodings often exist for the same color space. For example, the =#hex= (eg. =#ff00ff=), =RGB string= (eg. =rgb(255,0,255)=), and =name= (eg. =fuchsia=) encodings are all encodings for the =sRGB= color space.
|
41 |
+
|
42 |
+
............................................................
|
43 |
+
<< table >>
|
44 |
+
|
45 |
+
title: EXAMPLES OF BUILT-IN ENCODINGS
|
46 |
+
data
|
47 |
+
:| ENCODING NAME | THE COLOR FUCHSIA IN THIS ENCODING |
|
48 |
+
:| color | Uize.Color ('fuchsia') |
|
49 |
+
:| hex | ff00ff |
|
50 |
+
:| #hex | #ff0fff |
|
51 |
+
:| name | fuchsia |
|
52 |
+
:| RGB array | [255,0,255] |
|
53 |
+
:| RGB int | 16711935 |
|
54 |
+
:| RGB object | {red:255,green:0,blue:255} |
|
55 |
+
:| RGB string | rgb(255,0,255) |
|
56 |
+
:| HSL array | [300,100,50] |
|
57 |
+
:| HSL object | {hue:300,saturation:100,lightness:50} |
|
58 |
+
:| HSL string | hsl(300,100%,50%) |
|
59 |
+
............................................................
|
60 |
+
|
61 |
+
Beyond the built-in encodings, further encodings are available in extension modules, such as the =Uize.Color.xHsv= module that defines the =HSV= color space. Further color spaces can be defined - your own custom color spaces, or those not yet supported.
|
62 |
+
|
63 |
+
Methods for Manipulating Colors
|
64 |
+
Using the =Uize.Color= object, colors can be converted across color spaces and formats.
|
65 |
+
|
66 |
+
Further utilities for dealing with colors are available in extension module, such as the =Uize.Color.xUtil= module, which provides methods for blending between colors, mixing multiple colors together, testing for color equivalence, etc.
|
67 |
+
|
68 |
+
A Framework for Defining Named Colors
|
69 |
+
`Named Colors` can be defined, and these colors can then be used wherever colors can be specified using the methods of the =Uize.Color= object.
|
70 |
+
|
71 |
+
And because the =Uize.Color= module is used by other modules, such as the =Uize.Fx= module, it is possible to use color names when specifying the values of color CSS style properties for fade effects. The SVG 1.0 and CSS 3 specifications define over a hundred additional named colors, and these become available when using the =Uize.Color.xSvgColors= extension module. You can also define your own custom named colors (see the section `Defining New Named Colors`).
|
72 |
+
|
73 |
+
Creating Instances
|
74 |
+
There are actually three different ways that a new instance of the =Uize.Color= object can be created.
|
75 |
+
|
76 |
+
Using the Constructor
|
77 |
+
Typically, you will create a new instance of the =Uize.Color= object using its constructor, as follows...
|
78 |
+
|
79 |
+
.............................................................
|
80 |
+
var myColor = Uize.Color ('#f0f'); // initialized to fuchsia
|
81 |
+
.............................................................
|
82 |
+
|
83 |
+
Using the Uize.Color.from Static Method
|
84 |
+
The =Uize.Color.from= static method is a factory method that decodes the specified color value and produces an instance of the =Uize.Color= object as a result.
|
85 |
+
|
86 |
+
..................................................................
|
87 |
+
var myColor = Uize.Color.from ('#f0f'); // initialized to fuchsia
|
88 |
+
..................................................................
|
89 |
+
|
90 |
+
Using the Uize.Color.to Static Method
|
91 |
+
The =Uize.Color.to= static method decodes the specified color value and then encodes it using the specified encoding. Using the =color= encoding encodes the source color as an instance of the =Uize.Color= object.
|
92 |
+
|
93 |
+
........................................................................
|
94 |
+
var myColor = Uize.Color.to ('#f0f','color'); // initialized to fuchsia
|
95 |
+
........................................................................
|
96 |
+
|
97 |
+
### to note
|
98 |
+
- decoding colors
|
99 |
+
- encoding colors
|
100 |
+
- doesn't modify internal tuple values, only for output
|
101 |
+
- similarly, encoding into a different color space doesn't modify internal tuple values
|
102 |
+
- changing color encoding / converting colors to different color spaces
|
103 |
+
- manipulating colors (eg. blending, mixing, sorting)
|
104 |
+
|
105 |
+
- defining custom encodings
|
106 |
+
- the tuplet string encoding naming scheme (eg. "RGB string")
|
107 |
+
- explain some things about blending...
|
108 |
+
- when blending two colors, first color is authority on encoding (and, therefore, color space)
|
109 |
+
- when blending colors, they are blended in the color space of the encoding (not the target encoding)
|
110 |
+
|
111 |
+
### Specifying Color Values
|
112 |
+
Automatic Encoding Detection
|
113 |
+
document...
|
114 |
+
|
115 |
+
Disambiguating Encoding
|
116 |
+
SYNTAX
|
117 |
+
...
|
118 |
+
{'encoding name':colorValueANYTYPE}
|
119 |
+
...
|
120 |
+
|
121 |
+
So, for example, the =HSL= tuple for the color white, which would be =[0,0,100]=, can be specified in a disambiguated form as ={'HSL array':[0,0,100]}=. Without this disambiguation, the automatic encoding detection will default to the =RGB array= encoding.
|
122 |
+
|
123 |
+
An Example
|
124 |
+
If you had two tuple arrays that each represented the three color components - hue, saturation, and brightness - of the =HSL= color space, then you could blend them as =HSL= colors by using the disambiguation facility, as follows...
|
125 |
+
|
126 |
+
EXAMPLE
|
127 |
+
.........................................................................................
|
128 |
+
var
|
129 |
+
color1HslTuple = [0,0,0], // black as an HSL tuple
|
130 |
+
color2HslTuple = [0,0,100] // white as an HSL tuple
|
131 |
+
;
|
132 |
+
alert (
|
133 |
+
Uize.Color.blend ({'HSL array':color1HslTuple},{'HSL array':color2HslTuple},.5,'name')
|
134 |
+
);
|
135 |
+
.........................................................................................
|
136 |
+
|
137 |
+
In the above example, the =alert= statement will display the text "grey" in the dialog.
|
138 |
+
*/
|
139 |
+
|
140 |
+
Uize.module ({
|
141 |
+
name:'Uize.Color',
|
142 |
+
builder:function () {
|
143 |
+
/*** Variables for Scruncher Optimization ***/
|
144 |
+
var _undefined;
|
145 |
+
|
146 |
+
/*** General Variables ***/
|
147 |
+
var
|
148 |
+
_colorNamesLookup,
|
149 |
+
_tupleRegExp = /(\w+)\s*\(\s*([^,\)]+)\s*,\s*([^,\)]+)\s*,\s*([^,\)]+)\s*(?:,\s*([^,\)]+)\s*)?\)/i
|
150 |
+
;
|
151 |
+
|
152 |
+
/*** Utility Functions ***/
|
153 |
+
function _byte (_value) {
|
154 |
+
return Uize.constrain (Math.round (_value),0,255) || 0;
|
155 |
+
}
|
156 |
+
|
157 |
+
function _updateColorNamesLookup (_colors) {
|
158 |
+
var _colorInt;
|
159 |
+
for (var _colorName in _colors)
|
160 |
+
(_colorInt = _colors [_colorName]) in _colorNamesLookup || (_colorNamesLookup [_colorInt] = _colorName)
|
161 |
+
;
|
162 |
+
}
|
163 |
+
|
164 |
+
/*** Constructor ***/
|
165 |
+
var
|
166 |
+
_object = Uize.noNew (
|
167 |
+
function () {
|
168 |
+
/*** Public Instance Properties ***/
|
169 |
+
this.tuple = [];
|
170 |
+
|
171 |
+
_objectPrototype.from.apply (this,arguments);
|
172 |
+
}
|
173 |
+
/*?
|
174 |
+
Constructor
|
175 |
+
Lets you create an instance of the =Uize.Color= object.
|
176 |
+
|
177 |
+
SYNTAX
|
178 |
+
.....................................
|
179 |
+
colorOBJ = Uize.Color (colorANYTYPE);
|
180 |
+
.....................................
|
181 |
+
|
182 |
+
Initial color value can be specified in the =colorANYTYPE= parameter using any of the many `Color Encodings` supported by the =Uize.Color= module. The following examples illustrate this variety and flexibility...
|
183 |
+
|
184 |
+
EXAMPLES
|
185 |
+
..................................................................
|
186 |
+
Uize.Color (Uize.Color (255,0,255)); // color
|
187 |
+
Uize.Color ('ff00ff'); // hex
|
188 |
+
Uize.Color ('#ff00ff'); // #hex
|
189 |
+
Uize.Color ('fuchsia'); // name
|
190 |
+
Uize.Color ([255,0,255]); // RGB array
|
191 |
+
Uize.Color (0xff00ff); // RGB int
|
192 |
+
Uize.Color ({red:255,green:0,blue:255}); // RGB object
|
193 |
+
Uize.Color ('Rgb(255,0,255)'); // RGB string
|
194 |
+
Uize.Color ({'HSL array':[300,100,50]}); // HSL array
|
195 |
+
Uize.Color ({hue:300,saturation:100,lightness:50}); // HSL object
|
196 |
+
Uize.Color ('Hsl(300,100%,50%)'); // HSL string
|
197 |
+
..................................................................
|
198 |
+
|
199 |
+
VARIATION 1
|
200 |
+
.........................
|
201 |
+
colorOBJ = Uize.Color ();
|
202 |
+
.........................
|
203 |
+
|
204 |
+
When no parameter is specified, then the instance will be initialized to black (in the =sRGB= color space).
|
205 |
+
|
206 |
+
VARIATION 2
|
207 |
+
................................................
|
208 |
+
colorOBJ = Uize.Color (redINT,greenINT,blueINT);
|
209 |
+
................................................
|
210 |
+
|
211 |
+
When the three parameters =redINT=, =greenINT=, =blueINT= are specified, then the color will be initialized as though the arguments of the constructor represented an =RGB array= encoding.
|
212 |
+
|
213 |
+
EXAMPLE
|
214 |
+
........................................
|
215 |
+
var
|
216 |
+
yellow = Uize.Color (255,255,0),
|
217 |
+
alsoYellow = Uize.Color ([255,255,0])
|
218 |
+
;
|
219 |
+
........................................
|
220 |
+
|
221 |
+
NOTES
|
222 |
+
- in addition to using the constructor, there are two other methods for `Creating Instances` of the =Uize.Color= object
|
223 |
+
|
224 |
+
Instance Properties
|
225 |
+
encoding
|
226 |
+
A string, reflecting the name of the color encoding that is set for the instance.
|
227 |
+
|
228 |
+
This is a read-only property. In order to change the color encoding for an instance, you should use the =setEncoding= instance method. The =setEncoding= method handles the conversions necessary when switching to an encoding in a different color space and will automatically transform the color component values contained inside the =tuple= array.
|
229 |
+
|
230 |
+
NOTES
|
231 |
+
- this is a read-only property
|
232 |
+
- see the related =setEncoding= instance method
|
233 |
+
|
234 |
+
tuple
|
235 |
+
An array, containing typically three, but up to four floating point number elements, representing the values for the color components of the instance.
|
236 |
+
|
237 |
+
This property can be accessed by code that wishes to perform color computations, or by code that wishes to encode a color value in a custom manner - not using any of the `Color Encodings` supported by the =Uize.Color= object. This property can also be useful when implementing extension modules.
|
238 |
+
|
239 |
+
NOTES
|
240 |
+
- for three component color spaces, the =tuple= array may still contain four elements, where the value of the fourth element is =NaN= or =undefined=
|
241 |
+
- see the related =getTuple= instance method
|
242 |
+
*/
|
243 |
+
),
|
244 |
+
_objectPrototype = _object.prototype
|
245 |
+
;
|
246 |
+
|
247 |
+
/*** Public Instance Methods ***/
|
248 |
+
_objectPrototype.from = function (_color) {
|
249 |
+
var _this = this;
|
250 |
+
if (_color instanceof _object) {
|
251 |
+
_this.encoding = _color.encoding;
|
252 |
+
_setTupleFromArray (_color.tuple,_this.tuple);
|
253 |
+
} else {
|
254 |
+
var _encoding;
|
255 |
+
if (arguments.length == 3) {
|
256 |
+
_encoding = 'RGB array';
|
257 |
+
_color = _cloneTuple (arguments); // NOTE: can't just assign arguments to _color, since color is the first argument, and doing so will make the first argument a reference to arguments
|
258 |
+
} else {
|
259 |
+
if (_color == _undefined || typeof _color == 'number') {
|
260 |
+
_encoding = 'RGB int';
|
261 |
+
} else if (typeof _color == 'string') {
|
262 |
+
if (_colors [_color] != _undefined || _colors [_color.toLowerCase ()] != _undefined) {
|
263 |
+
_encoding = 'name';
|
264 |
+
} else {
|
265 |
+
var _tupleMatch = _color.match (_tupleRegExp);
|
266 |
+
_encoding = _tupleMatch
|
267 |
+
? _tupleMatch [1].toUpperCase () + ' string'
|
268 |
+
: _color.charCodeAt (0) == 35 ? '#hex' : 'hex'
|
269 |
+
;
|
270 |
+
}
|
271 |
+
} else if (typeof _color == 'object') {
|
272 |
+
if (_color.length) {
|
273 |
+
_encoding = 'RGB array';
|
274 |
+
} else if ('red' in _color) {
|
275 |
+
_encoding = 'RGB object';
|
276 |
+
} else if ('lightness' in _color) {
|
277 |
+
_encoding = 'HSL object';
|
278 |
+
} else {
|
279 |
+
for (_encoding in _color) break;
|
280 |
+
_color = _color [_encoding];
|
281 |
+
}
|
282 |
+
}
|
283 |
+
}
|
284 |
+
var _encodingProfile = _encodings [_encoding];
|
285 |
+
if (!_encodingProfile) {
|
286 |
+
_encodingProfile = _encodings [_encoding = 'RGB int'];
|
287 |
+
_color = 0;
|
288 |
+
}
|
289 |
+
_encodingProfile.from (_color,_this.tuple);
|
290 |
+
_this.encoding = _encoding;
|
291 |
+
}
|
292 |
+
|
293 |
+
return _this;
|
294 |
+
/*?
|
295 |
+
Instance Methods
|
296 |
+
from
|
297 |
+
Lets you set the color for the =Uize.Color= object instance from the specified color, by decoding the specified color as needed.
|
298 |
+
|
299 |
+
SYNTAX
|
300 |
+
........................................
|
301 |
+
colorOBJ = colorOBJ.from (colorANYTYPE);
|
302 |
+
........................................
|
303 |
+
|
304 |
+
The color specified by the =colorANYTYPE= parameter can be specified using any of the many `Color Encodings` supported by the =Uize.Color= module. The following examples illustrate this variety and flexibility...
|
305 |
+
|
306 |
+
EXAMPLES
|
307 |
+
....................................................................
|
308 |
+
myColor.from (Uize.Color (255,0,255)); // color
|
309 |
+
myColor.from ('ff00ff'); // hex
|
310 |
+
myColor.from ('#ff00ff'); // #hex
|
311 |
+
myColor.from ('fuchsia'); // name
|
312 |
+
myColor.from ([255,0,255]); // RGB array
|
313 |
+
myColor.from (0xff00ff); // RGB int
|
314 |
+
myColor.from ({red:255,green:0,blue:255}); // RGB object
|
315 |
+
myColor.from ('Rgb(255,0,255)'); // RGB string
|
316 |
+
myColor.from ({hue:300,saturation:100,lightness:50}); // HSL object
|
317 |
+
myColor.from ('Hsl(300,100%,50%)'); // HSL string
|
318 |
+
....................................................................
|
319 |
+
|
320 |
+
The above statements would all set the color of the instance =myColor= to the color "fuchsia" (=#ff00ff=).
|
321 |
+
|
322 |
+
VARIATION
|
323 |
+
.................
|
324 |
+
colorOBJ.from ();
|
325 |
+
.................
|
326 |
+
|
327 |
+
When no =colorANYTYPE= parameter is specified, the instance will be initialized to black (in the =sRGB= color space).
|
328 |
+
|
329 |
+
TIP
|
330 |
+
|
331 |
+
Because the =from= method returns the instance on which it is called, you can "daisy chain" method calls, as in...
|
332 |
+
|
333 |
+
..............................................................
|
334 |
+
fuchsiaHslObject = myColor.from ('fuchsia').to ('HSL object');
|
335 |
+
..............................................................
|
336 |
+
|
337 |
+
The above example first sets the =Uize.Color= object instance =myColor= to the color "fuchsia" and then encodes its value as =HSL object= and assigns that value to the variable =fuchsiaHslObject=.
|
338 |
+
|
339 |
+
NOTES
|
340 |
+
- see the related =Uize.Color.from= static method
|
341 |
+
*/
|
342 |
+
};
|
343 |
+
|
344 |
+
_objectPrototype.getTuple = function (_encodingOrColorSpace) {
|
345 |
+
var
|
346 |
+
_oldEncodingColorSpaceProfile = _colorSpaces [_encodings [this.encoding].colorSpace],
|
347 |
+
_newEncodingColorSpaceProfile = _encodingOrColorSpace
|
348 |
+
?
|
349 |
+
_colorSpaces [_encodingOrColorSpace] ||
|
350 |
+
_colorSpaces [_encodings [_encodingOrColorSpace].colorSpace]
|
351 |
+
:
|
352 |
+
_oldEncodingColorSpaceProfile
|
353 |
+
;
|
354 |
+
return (
|
355 |
+
_newEncodingColorSpaceProfile != _oldEncodingColorSpaceProfile
|
356 |
+
? _newEncodingColorSpaceProfile.fromHsl (_oldEncodingColorSpaceProfile.toHsl (this.tuple))
|
357 |
+
: this.tuple
|
358 |
+
);
|
359 |
+
/*?
|
360 |
+
Instance Methods
|
361 |
+
getTuple
|
362 |
+
Returns an array, being the the tuple of color components for the instance, transformed for the specified color encoding or color space.
|
363 |
+
|
364 |
+
SYNTAX
|
365 |
+
........................................................
|
366 |
+
tupleARRAY = myColor.getTuple (encodingOrColorSpaceSTR);
|
367 |
+
........................................................
|
368 |
+
|
369 |
+
If the color space of the instance's current encoding is the same as the color space defined by the =encodingOrColorSpaceSTR= parameter, then the value of the =tuple= instance property will be returned as is (ie. no transformation is performed). Otherwise, the necessary conversion functions will be employed to transform the instance's tuple for use in the desired color space.
|
370 |
+
|
371 |
+
This method can be used by other methods that wish to blend, mix, or otherwise process multiple tuples in a single color space.
|
372 |
+
|
373 |
+
VARIATION
|
374 |
+
.................................
|
375 |
+
tupleARRAY = myColor.getTuple ();
|
376 |
+
.................................
|
377 |
+
|
378 |
+
When no =encodingOrColorSpaceSTR= parameter is specified, then the value of the =tuple= instance property will be returned (ie. no transformation is performed).
|
379 |
+
|
380 |
+
EXAMPLE
|
381 |
+
................................
|
382 |
+
myColor.getTuple ('HSL');
|
383 |
+
myColor.getTuple ('HSL array');
|
384 |
+
myColor.getTuple ('HSL string');
|
385 |
+
................................
|
386 |
+
|
387 |
+
In the above example, the same =HSL= color space is implied by all statements, so all statements will return the same result. Note that the particular encoding has no bearing on how the tuple is returned - it is always an array of the components of the color. So, the value ='HSL string'= for =encodingOrColorSpaceSTR= still results in the tuple array being returned.
|
388 |
+
|
389 |
+
NOTES
|
390 |
+
- see the related =tuple= and =encoding= instance properties
|
391 |
+
*/
|
392 |
+
};
|
393 |
+
|
394 |
+
_objectPrototype.setEncoding = function (_newEncoding) {
|
395 |
+
_setTupleFromArray (
|
396 |
+
this.getTuple (_newEncoding && _newEncoding != 'color' ? _newEncoding : (_newEncoding = 'hex')),
|
397 |
+
this.tuple
|
398 |
+
);
|
399 |
+
this.encoding = _newEncoding;
|
400 |
+
return this;
|
401 |
+
/*?
|
402 |
+
Instance Methods
|
403 |
+
setEncoding
|
404 |
+
Lets you change the encoding for an instance.
|
405 |
+
|
406 |
+
Changing the encoding for an instance will have no effect on the instance's =tuple= values if the new encoding is of the same color space as the current encoding. However, if the color spaces differ, then the =tuple= values will be converted to be in the color space of the new encoding.
|
407 |
+
|
408 |
+
SYNTAX
|
409 |
+
..................................
|
410 |
+
myColor.setEncoding (encodingSTR);
|
411 |
+
..................................
|
412 |
+
|
413 |
+
NOTES
|
414 |
+
- see the related =encoding= instance property
|
415 |
+
*/
|
416 |
+
};
|
417 |
+
|
418 |
+
_objectPrototype.to = function (_newEncoding) {
|
419 |
+
return (
|
420 |
+
_newEncoding == 'color'
|
421 |
+
? new _object (this)
|
422 |
+
: _encodings [_newEncoding || this.encoding].to (this.getTuple (_newEncoding))
|
423 |
+
);
|
424 |
+
/*?
|
425 |
+
Instance Methods
|
426 |
+
to
|
427 |
+
Returns the current color of the instance, encoded to the specified color encoding.
|
428 |
+
|
429 |
+
SYNTAX
|
430 |
+
.........................................
|
431 |
+
encodedColor = colorOBJ.to (encodingSTR);
|
432 |
+
.........................................
|
433 |
+
|
434 |
+
The =encodingSTR= parameter supports a wide variety of different `Color Encodings`.
|
435 |
+
|
436 |
+
EXAMPLES
|
437 |
+
.............................................................................
|
438 |
+
var fuchsia = Uize.Color ('fuchsia');
|
439 |
+
fuchsia.to ('color'); // produces a new Uize.Color object
|
440 |
+
fuchsia.to ('hex'); // produces 'ff00ff'
|
441 |
+
fuchsia.to ('#hex'); // produces '#ff00ff'
|
442 |
+
fuchsia.to ('name'); // produces 'fuchsia'
|
443 |
+
fuchsia.to ('RGB array'); // produces [255,0,255]
|
444 |
+
fuchsia.to ('RGB int'); // produces 16711935
|
445 |
+
fuchsia.to ('RGB object'); // produces {red:255,green:0,blue:255}
|
446 |
+
fuchsia.to ('RGB string'); // produces 'rgb(255,0,255)'
|
447 |
+
fuchsia.to ('HSL array'); // produces [300,100,50]
|
448 |
+
fuchsia.to ('HSL object'); // produces {hue:300,saturation:100,lightness:50}
|
449 |
+
fuchsia.to ('HSL string'); // produces 'hsl(300,100,50)'
|
450 |
+
.............................................................................
|
451 |
+
|
452 |
+
NOTES
|
453 |
+
- see the related =Uize.Color.to= static method
|
454 |
+
*/
|
455 |
+
};
|
456 |
+
|
457 |
+
/*** Public Static Methods ***/
|
458 |
+
_object.adapter = function (_aEncoding,_bEncoding) {
|
459 |
+
return {
|
460 |
+
aToB:function (_value) {return Uize.Color.to (Uize.pairUp (_aEncoding,_value),_bEncoding)},
|
461 |
+
bToA:function (_value) {return Uize.Color.to (Uize.pairUp (_bEncoding,_value),_aEncoding)}
|
462 |
+
}
|
463 |
+
/*?
|
464 |
+
Static Methods
|
465 |
+
Uize.Color.adapter
|
466 |
+
Returns a value adapter object,
|
467 |
+
|
468 |
+
SYNTAX
|
469 |
+
.................................................................
|
470 |
+
valueAdapterOBJ = Uize.Color.adapter (aEncodingSTR,bEncodingSTR);
|
471 |
+
.................................................................
|
472 |
+
*/
|
473 |
+
};
|
474 |
+
|
475 |
+
_object.defineColors = function (_colorsToDefine) {
|
476 |
+
Uize.copyInto (_colors,_colorsToDefine);
|
477 |
+
_colorNamesLookup && _updateColorNamesLookup (_colorsToDefine);
|
478 |
+
/*?
|
479 |
+
Static Methods
|
480 |
+
Uize.Color.defineColors
|
481 |
+
Lets you define an arbitrary number of custom `Named Colors`, which will then be accessible to code that uses the =Uize.Color= module.
|
482 |
+
|
483 |
+
SYNTAX
|
484 |
+
.......................................
|
485 |
+
Uize.Color.defineColors (colorsMapOBJ);
|
486 |
+
.......................................
|
487 |
+
|
488 |
+
When you extend this object with new named colors, it will then be possible to use the names of those colors when creating instances of the =Uize.Color= object, or when setting the color of =Uize.Color= instances using the =from= instance method.
|
489 |
+
|
490 |
+
For more information, see the section `Defining New Named Colors`.
|
491 |
+
|
492 |
+
NOTES
|
493 |
+
- see the related =Uize.Color.colors= static property
|
494 |
+
- over a hundred additional named colors - as defined in the SVG 1.0 and CSS 3 specifications - are defined in the =Uize.Color.xSvgColors= extension module
|
495 |
+
*/
|
496 |
+
};
|
497 |
+
|
498 |
+
_object.from = function () {
|
499 |
+
return _objectPrototype.from.apply (new _object,arguments)
|
500 |
+
/*?
|
501 |
+
Static Methods
|
502 |
+
Uize.Color.from
|
503 |
+
Returns a freshly minted instance of the =Uize.Color= object, whose color is initialized to the specified color, by decoding the specified color as needed.
|
504 |
+
|
505 |
+
SYNTAX
|
506 |
+
..........................................
|
507 |
+
colorOBJ = Uize.Color.from (colorANYTYPE);
|
508 |
+
..........................................
|
509 |
+
|
510 |
+
The =Uize.Color.from= method is a factory method, is essentially equivalent to using the =Uize.Color= object's `Constructor`, and is mainly provided to have parity with the =Uize.Color.to= static method.
|
511 |
+
|
512 |
+
EXAMPLE
|
513 |
+
...........................
|
514 |
+
Uize.Color ('ff00ff');
|
515 |
+
Uize.Color.from ('ff00ff');
|
516 |
+
...........................
|
517 |
+
|
518 |
+
The above two statements would both return new instances of the =Uize.Color= object initialized to the color "fuchsia" (=#ff00ff=).
|
519 |
+
|
520 |
+
The color specified by the =colorANYTYPE= parameter can be specified using any of the many `Color Encodings` supported by the =Uize.Color= module. The following examples illustrate this variety and flexibility...
|
521 |
+
|
522 |
+
EXAMPLES
|
523 |
+
.......................................................................
|
524 |
+
Uize.Color.from (Uize.Color (255,0,255)); // color
|
525 |
+
Uize.Color.from ('ff00ff'); // hex
|
526 |
+
Uize.Color.from ('#ff00ff'); // #hex
|
527 |
+
Uize.Color.from ('fuchsia'); // name
|
528 |
+
Uize.Color.from ([255,0,255]); // RGB array
|
529 |
+
Uize.Color.from (0xff00ff); // RGB int
|
530 |
+
Uize.Color.from ({red:255,green:0,blue:255}); // RGB object
|
531 |
+
Uize.Color.from ('Rgb(255,0,255)'); // RGB string
|
532 |
+
Uize.Color.from ({hue:300,saturation:100,lightness:50}); // HSL object
|
533 |
+
Uize.Color.from ('Hsl(300,100%,50%)'); // HSL string
|
534 |
+
.......................................................................
|
535 |
+
|
536 |
+
The above statements would all return new instances of the =Uize.Color= object initialized to the color "fuchsia" (=#ff00ff=).
|
537 |
+
|
538 |
+
VARIATION
|
539 |
+
...................
|
540 |
+
Uize.Color.from ();
|
541 |
+
...................
|
542 |
+
|
543 |
+
When no =colorANYTYPE= parameter is specified, the new instance will be initialized to black (in the =sRGB= color space).
|
544 |
+
|
545 |
+
A Tip on Preserving Encoding
|
546 |
+
There might be times when you want to set the color value for an instance using a color that is specified in a different encoding - possibly even in a different color space - but you don't wish to change the encoding of the instance.
|
547 |
+
|
548 |
+
You can accomplish this by temporarily storing the instance's encoding, and then restoring it after setting the instance's color by using the =setEncoding= instance method, as in...
|
549 |
+
|
550 |
+
EXAMPLE
|
551 |
+
.......................................................
|
552 |
+
var oldEncoding = myColor.encoding;
|
553 |
+
myColor.from (newColorValue).setEncoding (oldEncoding);
|
554 |
+
.......................................................
|
555 |
+
|
556 |
+
Because the =from= instance method returns a reference to the instance, you can call the =setEncoding= method on the result.
|
557 |
+
|
558 |
+
NOTES
|
559 |
+
- see the related =from= instance method
|
560 |
+
*/
|
561 |
+
};
|
562 |
+
|
563 |
+
var _cloneTuple = _object.cloneTuple = function (_tuple) {
|
564 |
+
var _component3 = _tuple [3];
|
565 |
+
return (
|
566 |
+
isNaN (_component3) || _component3 == _undefined
|
567 |
+
? [_tuple [0],_tuple [1],_tuple [2]]
|
568 |
+
: [_tuple [0],_tuple [1],_tuple [2],_component3]
|
569 |
+
);
|
570 |
+
/*?
|
571 |
+
Static Methods
|
572 |
+
Uize.Color.cloneTuple
|
573 |
+
A method that is useful in the development of color space or encoding extensions, and that returns a tuple array, being a clone of the specified source tuple array.
|
574 |
+
|
575 |
+
SYNTAX
|
576 |
+
......................................................
|
577 |
+
clonedTupleARRAY = Uize.Color.cloneTuple (tupleARRAY);
|
578 |
+
......................................................
|
579 |
+
|
580 |
+
This method is intended primary for use in the implementation of `Color Encodings`.
|
581 |
+
|
582 |
+
NOTES
|
583 |
+
- see the related =Uize.Color.setTuple=, =Uize.Color.setTupleFromArray=, and =Uize.Color.setTupleFromString= static methods
|
584 |
+
*/
|
585 |
+
};
|
586 |
+
|
587 |
+
var _setTuple = _object.setTuple = function (_tuple,_component0,_component1,_component2,_component3) {
|
588 |
+
_tuple [0] = +_component0;
|
589 |
+
_tuple [1] = +_component1;
|
590 |
+
_tuple [2] = +_component2;
|
591 |
+
_tuple [3] = +_component3;
|
592 |
+
/*?
|
593 |
+
Static Methods
|
594 |
+
Uize.Color.setTuple
|
595 |
+
A method that is useful in the development of color space or encoding extensions, and that copies the specified values for up to four components of a tuple into the specified tuple array.
|
596 |
+
|
597 |
+
SYNTAX
|
598 |
+
..................................................................
|
599 |
+
Uize.Color.setTuple (
|
600 |
+
tupleARRAY,
|
601 |
+
component0FLOAT,component1FLOAT,component2FLOAT,component3FLOAT
|
602 |
+
);
|
603 |
+
..................................................................
|
604 |
+
|
605 |
+
This method is intended primary for use in the implementation of `Color Encodings`.
|
606 |
+
|
607 |
+
NOTES
|
608 |
+
- see the related =Uize.Color.cloneTuple=, =Uize.Color.setTupleFromArray=, and =Uize.Color.setTupleFromString= static methods
|
609 |
+
*/
|
610 |
+
};
|
611 |
+
|
612 |
+
var _setTupleFromArray = _object.setTupleFromArray = function (_array,_tuple) {
|
613 |
+
_setTuple (_tuple,_array [0],_array [1],_array [2],_array [3]);
|
614 |
+
/*?
|
615 |
+
Static Methods
|
616 |
+
Uize.Color.setTupleFromArray
|
617 |
+
A method that is useful in the development of color space or encoding extensions, and that copies the values of the first four elements of the specified source array into the specified tuple array.
|
618 |
+
|
619 |
+
SYNTAX
|
620 |
+
......................................................
|
621 |
+
Uize.Color.setTupleFromArray (sourceARRAY,tupleARRAY);
|
622 |
+
......................................................
|
623 |
+
|
624 |
+
This method is intended primary for use in the implementation of `Color Encodings`.
|
625 |
+
|
626 |
+
NOTES
|
627 |
+
- see the related =Uize.Color.cloneTuple=, =Uize.Color.setTuple=, and =Uize.Color.setTupleFromString= static methods
|
628 |
+
*/
|
629 |
+
};
|
630 |
+
|
631 |
+
var _setTupleFromString = _object.setTupleFromString = function (_tupleStr,_tuple) {
|
632 |
+
var _tupleMatch = _tupleStr.match (_tupleRegExp);
|
633 |
+
_setTuple (
|
634 |
+
_tuple,
|
635 |
+
parseFloat (_tupleMatch [2]),
|
636 |
+
parseFloat (_tupleMatch [3]),
|
637 |
+
parseFloat (_tupleMatch [4]),
|
638 |
+
parseFloat (_tupleMatch [5])
|
639 |
+
);
|
640 |
+
/*?
|
641 |
+
Static Methods
|
642 |
+
Uize.Color.setTupleFromString
|
643 |
+
A method that is useful in the development of color space or encoding extensions, and that parses up to four color components from the specified source string and copies the values of those components into the specified tuple array.
|
644 |
+
|
645 |
+
SYNTAX
|
646 |
+
.....................................................
|
647 |
+
Uize.Color.setTupleFromString (sourceSTR,tupleARRAY);
|
648 |
+
.....................................................
|
649 |
+
|
650 |
+
This method is intended primary for use in the implementation of `Color Encodings`.
|
651 |
+
|
652 |
+
NOTES
|
653 |
+
- see the related =Uize.Color.cloneTuple=, =Uize.Color.setTuple=, and =Uize.Color.setTupleFromArray= static methods
|
654 |
+
*/
|
655 |
+
};
|
656 |
+
|
657 |
+
_object.to = function (_colorValue,_encoding) {
|
658 |
+
return _dummyColor1.from (_colorValue).to (_encoding || 'hex')
|
659 |
+
/*?
|
660 |
+
Static Methods
|
661 |
+
Uize.Color.to
|
662 |
+
Encodes the specified color to the specified encoding / format.
|
663 |
+
|
664 |
+
SYNTAX
|
665 |
+
.......................................................................
|
666 |
+
encodedColorANYTYPE = Uize.Color.to (colorToEncodeANYTYPE,encodingSTR);
|
667 |
+
.......................................................................
|
668 |
+
|
669 |
+
This method's return value can be of any type, and is determined by the encoding specified in the =encodingSTR= parameter, which supports a wide variety of different `Color Encodings`. Moreover, the color to be encoded, as specified by the =colorToEncodeANYTYPE= parameter, can be specified in any of the supported encodings.
|
670 |
+
|
671 |
+
VARIATION
|
672 |
+
..........................................................
|
673 |
+
encodedColorHexSTR = Uize.Color.to (colorToEncodeANYTYPE);
|
674 |
+
..........................................................
|
675 |
+
|
676 |
+
When no =encodingSTR= parameter is specified, then the color specified by the =colorToEncodeANYTYPE= parameter will be encoded as =hex=.
|
677 |
+
|
678 |
+
EXAMPLES
|
679 |
+
..................................................................................
|
680 |
+
Uize.Color.to ('fuchsia','color'); // produces a new Uize.Color object
|
681 |
+
Uize.Color.to ('#f0f','HSL object'); // {hue:300,saturation:100,lightness:50}
|
682 |
+
Uize.Color.to ('Rgb(255,0,255)','name'); // produces 'fuchsia'
|
683 |
+
Uize.Color.to ('hsl(300,100,50)','#hex'); // produces '#ff00ff'
|
684 |
+
Uize.Color.to ('ff00ff','HSL string'); // produces 'hsl(300,100,50)'
|
685 |
+
Uize.Color.to ('fuchsia,'RGB string'); // produces 'rgb(255,0,255)'
|
686 |
+
Uize.Color.to ([255,0,255],'hex'); // produces 'ff00ff'
|
687 |
+
Uize.Color.to ([255,0,255]); // produces 'ff00ff'
|
688 |
+
..................................................................................
|
689 |
+
|
690 |
+
These are just a few examples to illustrate the versatility of this method. Given the wide variety of different `Color Encodings` supported by the =Uize.Color= module, there are a great many permutations to this method - too numerous to list.
|
691 |
+
|
692 |
+
NOTES
|
693 |
+
- see the related =to= instance method
|
694 |
+
*/
|
695 |
+
};
|
696 |
+
|
697 |
+
/*** Public Static Properties ***/
|
698 |
+
/*** Color Spaces ***/
|
699 |
+
var _colorSpaces = _object.colorSpaces = {
|
700 |
+
/*?
|
701 |
+
Static Properties
|
702 |
+
Uize.Color.colorSpaces
|
703 |
+
An object, containing definitions for `Color Spaces` supported by the =Uize.Color= object.
|
704 |
+
|
705 |
+
In general, color spaces are not explicitly specified when working with =Uize.Color= instances. Instead, a color space is implied by a given color encoding. Encodings specify their associated color spaces, and the profile that defines a color space is utilized automatically when encoding across color spaces, such as when encoding a color object that was initialized in the =sRGB= color space as =HSL string=, as shown in the following example...
|
706 |
+
|
707 |
+
EXAMPLE
|
708 |
+
................................................................................
|
709 |
+
var myRgbColor = Uize.Color ('#ff00ff');
|
710 |
+
alert (myRgbColor.to ('HSL string')); // displays "Hsl(300,100%,50%)" in dialog
|
711 |
+
................................................................................
|
712 |
+
|
713 |
+
You can define your own color spaces by extending the =Uize.Color.colorSpaces= static property. For more information, see the section `Defining New Color Spaces`.
|
714 |
+
|
715 |
+
NOTES
|
716 |
+
- compare to the =Uize.Color.encodings= static property
|
717 |
+
|
718 |
+
Color Spaces
|
719 |
+
The =Uize.Color= object provides a foundation for supporting multiple color spaces, and supports two built-in color spaces: =sRGB= and =HSL=.
|
720 |
+
|
721 |
+
A [[http://en.wikipedia.org/wiki/Color_space][color space]] provides a way to represent colors, and is the combination of a [[http://en.wikipedia.org/wiki/Color_model][color model]] and a mapping function. Certain color spaces are better suited to specific applications, and a wide variety of color spaces exist. In the computer world, =sRGB= is the dominant color space and is based around an additive color model. In the print world, =CMYK= is a dominant color space and is based around a subtractive color model.
|
722 |
+
|
723 |
+
|
724 |
+
*/
|
725 |
+
sRGB:{
|
726 |
+
fromHsl:function (_tuple) {
|
727 |
+
// http://en.wikipedia.org/wiki/HSL_color_space
|
728 |
+
var
|
729 |
+
_saturation = _tuple [1] / 100,
|
730 |
+
_lightness = _tuple [2] / 100
|
731 |
+
;
|
732 |
+
if (_saturation) {
|
733 |
+
var
|
734 |
+
_temp1 = _lightness < .5
|
735 |
+
? _lightness * (1 + _saturation)
|
736 |
+
: _lightness + _saturation - _lightness * _saturation,
|
737 |
+
_temp2 = 2 * _lightness - _temp1
|
738 |
+
;
|
739 |
+
var _hue = _tuple [0] / 360;
|
740 |
+
function _computeChannel (_level) {
|
741 |
+
return (
|
742 |
+
(_level = (_level + 1) % 1) < 1 / 6
|
743 |
+
? _temp2 + (_temp1 - _temp2) * 6 * _level
|
744 |
+
: _level < .5
|
745 |
+
? _temp1
|
746 |
+
: _level < 2 / 3
|
747 |
+
? _temp2 + (_temp1 - _temp2) * 6 * (2 / 3 - _level)
|
748 |
+
: _temp2
|
749 |
+
) * 255;
|
750 |
+
}
|
751 |
+
return [_computeChannel (_hue + 1 / 3),_computeChannel (_hue),_computeChannel (_hue - 1 / 3)];
|
752 |
+
} else {
|
753 |
+
var _channelLevel = _lightness * 255;
|
754 |
+
return [_channelLevel,_channelLevel,_channelLevel];
|
755 |
+
}
|
756 |
+
},
|
757 |
+
toHsl:function (_tuple) {
|
758 |
+
// http://en.wikipedia.org/wiki/HSL_color_space
|
759 |
+
var
|
760 |
+
_redLevel = _tuple [0] / 255,
|
761 |
+
_greenLevel = _tuple [1] / 255,
|
762 |
+
_blueLevel = _tuple [2] / 255,
|
763 |
+
_maxLevel = Math.max (_redLevel,_greenLevel,_blueLevel),
|
764 |
+
_minLevel = Math.min (_redLevel,_greenLevel,_blueLevel),
|
765 |
+
_maxMinLevelSum = _maxLevel + _minLevel,
|
766 |
+
_maxMinLevelDelta = _maxLevel - _minLevel,
|
767 |
+
_hue = 0,
|
768 |
+
_saturation = 0,
|
769 |
+
_lightness = _maxMinLevelSum / 2
|
770 |
+
;
|
771 |
+
if (_maxMinLevelDelta) {
|
772 |
+
_saturation = _maxMinLevelDelta / (_lightness < .5 ? _maxMinLevelSum : 2 - _maxMinLevelSum);
|
773 |
+
_hue =
|
774 |
+
(
|
775 |
+
(
|
776 |
+
_redLevel == _maxLevel
|
777 |
+
? 6 + (_greenLevel - _blueLevel) / _maxMinLevelDelta
|
778 |
+
: _greenLevel == _maxLevel
|
779 |
+
? 2 + (_blueLevel - _redLevel) / _maxMinLevelDelta
|
780 |
+
: 4 + (_redLevel - _greenLevel) / _maxMinLevelDelta
|
781 |
+
) * 60
|
782 |
+
) % 360
|
783 |
+
;
|
784 |
+
}
|
785 |
+
function _levelToPercent (_level) {return Uize.constrain (_level * 100,0,100)}
|
786 |
+
return [_hue,_levelToPercent (_saturation),_levelToPercent (_lightness)];
|
787 |
+
},
|
788 |
+
tuple:[
|
789 |
+
{name:'red',min:0,max:255},
|
790 |
+
{name:'green',min:0,max:255},
|
791 |
+
{name:'green',min:0,max:255}
|
792 |
+
]
|
793 |
+
/*?
|
794 |
+
Color Spaces
|
795 |
+
sRGB
|
796 |
+
The =Uize.Color.colorSpaces.sRGB= property defines the [[http://en.wikipedia.org/wiki/SRGB][sRGB]] (standard RGB) color space.
|
797 |
+
|
798 |
+
sRGB is the recommended color space for the Internet and is the color space used by the [[http://www.w3.org/TR/CSS21/colors.html][CSS 2.1 color specification]]. Because of this, it is also the default working color space for many digital cameras, phones, scanners, and other electronics devices.
|
799 |
+
|
800 |
+
*/
|
801 |
+
},
|
802 |
+
HSL:{
|
803 |
+
fromHsl:Object, // when called as a function with an object argument, Object just returns argument
|
804 |
+
toHsl:Object,
|
805 |
+
tuple:[
|
806 |
+
{name:'hue',min:0,max:360},
|
807 |
+
{name:'saturation',min:0,max:100},
|
808 |
+
{name:'lightness',min:0,max:100}
|
809 |
+
]
|
810 |
+
/*?
|
811 |
+
Color Spaces
|
812 |
+
HSL
|
813 |
+
The =Uize.Color.colorSpaces.HSL= property defines the [[http://en.wikipedia.org/wiki/HSL_color_space][HSL]] (Hue, Saturation, Lightness) color space.
|
814 |
+
|
815 |
+
The HSL color space is essentially an alternate representation / mapping of the =sRGB= color space, but might be considered to be a more intuitive representation of the qualities of color. Because of the benefits of this color space, it has been adopted in the [[http://www.w3.org/TR/css3-color/#hsl-color][CSS 3 color specification]] as another accepted way of specifying colors.
|
816 |
+
*/
|
817 |
+
}
|
818 |
+
/*?
|
819 |
+
Color Spaces
|
820 |
+
Additional Color Spaces
|
821 |
+
Additional color spaces are made available through extension modules, such as the =Uize.Color.xHsv= module that defines the =HSV= color space.
|
822 |
+
|
823 |
+
Implementing color spaces in extension modules avoids burdening the core code with having to support less common / more esoteric color spaces that are not as frequently used. This also allows applications built on the UIZE JavaScript Framework to be better optimized for code size.
|
824 |
+
|
825 |
+
Defining New Color Spaces
|
826 |
+
You can extend the =Uize.Color.colorSpaces= object in order to define new `Color Spaces`.
|
827 |
+
|
828 |
+
This can be done quite easily by setting a new property on the =Uize.Color.colorSpaces= object, as follows...
|
829 |
+
|
830 |
+
EXAMPLE
|
831 |
+
....................................................................
|
832 |
+
Uize.Color.colorSpaces.CMYK = {
|
833 |
+
fromHsl:function (_tuple) {
|
834 |
+
// this function should accept a tuple in the HSL colorspace
|
835 |
+
// and should return a new tuple that represents the color
|
836 |
+
// transformed to the CMYK color space
|
837 |
+
},
|
838 |
+
toHsl:function (_tuple) {
|
839 |
+
// this function should accept a tuple in the CMYK color space
|
840 |
+
// and should return a new tuple that represents the color
|
841 |
+
// transformed to the HSL color space
|
842 |
+
},
|
843 |
+
tuple:[
|
844 |
+
{name:'cyan',min:0,max:100},
|
845 |
+
{name:'magenta',min:0,max:100},
|
846 |
+
{name:'yellow',min:0,max:100},
|
847 |
+
{name:'black',min:0,max:100}
|
848 |
+
]
|
849 |
+
}
|
850 |
+
....................................................................
|
851 |
+
|
852 |
+
Typically one will define a new color space and also define new `Color Encodings` to accompany the new color space. The new encodings should specify the name of their associated color space in their =colorSpace= property.
|
853 |
+
|
854 |
+
The object that describes a color space is called a color space profile, and should have the following properties...
|
855 |
+
|
856 |
+
- =fromHsl= - This is a function that should accept a tuple in the =HSL= colorspace and should return a new tuple that represents the color transformed to your color space.
|
857 |
+
|
858 |
+
- =toHsl= - This function should accept a tuple in your color space and should return a new tuple that represents the color transformed to the =HSL= color space.
|
859 |
+
|
860 |
+
- =tuple (profile)= - This is an object that provides a profile for the tuple of color components of the color space - the "dimensions" of the color space, if you will. The tuple profile is an array of objects, one for each component of the color space, where each object is a profile for a component and should contain "name", "min", and "max" properties. The "name" property for a component profile is self-explanatory, and the "min" and "max" properties define the value range for the component.
|
861 |
+
|
862 |
+
The =fromHsl= and =toHsl= conversion functions that you provide as part of a color space profile are used for converting a tuple back and forth between your color space and the =HSL= color space. The =HSL= color space is essentially used as a canonical color space - a kind of "conduit" through which colors are converted in order to convert across `Color Spaces`. This avoids having to have an ever increasing number of cross conversion functions for every defined color space to every other. For example, if a =CMYK= color space were defined, then conversion from =sRGB= to =CMYK= would first involve conversion from =sRGB= to =HSL=, and then =HSL= to =CMYK=.
|
863 |
+
*/
|
864 |
+
};
|
865 |
+
|
866 |
+
/*** Encodings ***/
|
867 |
+
function _setTupleFromRgbHex (_color,_tuple) {
|
868 |
+
if (_color.charCodeAt (0) == 35)
|
869 |
+
_color = _color.slice (1) // strip "#"
|
870 |
+
;
|
871 |
+
var _hexDigits = _color.length;
|
872 |
+
_color = '0x' + _color - 0;
|
873 |
+
_hexDigits == 1
|
874 |
+
? _setTuple (_tuple,_color *= 17,_color,_color)
|
875 |
+
: _hexDigits == 3
|
876 |
+
? _setTuple (_tuple,((_color >> 8) & 15) * 17,((_color >> 4) & 15) * 17,(_color & 15) * 17)
|
877 |
+
: _setTuple (_tuple,(_color >> 16) & 255,(_color >> 8) & 255,_color & 255)
|
878 |
+
;
|
879 |
+
}
|
880 |
+
|
881 |
+
var _encodings = _object.encodings = {
|
882 |
+
/*?
|
883 |
+
Color Encodings
|
884 |
+
The =Uize.Color= module supports a wide variety of different color encodings / formats.
|
885 |
+
|
886 |
+
For methods that have color parameters, color values for these parameters can be flexibly specified in any of the many supported encodings. Additionally, many of the methods that produce a color as a result allow an encoding to optionally be specified for that return value.
|
887 |
+
|
888 |
+
Supported encodings are as follows...
|
889 |
+
|
890 |
+
color
|
891 |
+
An instance of the =Uize.Color= object.
|
892 |
+
|
893 |
+
Encoding
|
894 |
+
When a color is encoded as =color=, an instance of the =Uize.Color= object is created with its color initialized to that of the encoding source.
|
895 |
+
|
896 |
+
...........................................
|
897 |
+
<< table >>
|
898 |
+
|
899 |
+
title: EXAMPLES
|
900 |
+
data
|
901 |
+
:| COLOR NAME | color |
|
902 |
+
:| fuchsia | Uize.Color ('fuchsia') |
|
903 |
+
:| yellow | Uize.Color ('yellow') |
|
904 |
+
:| blue | Uize.Color ('blue') |
|
905 |
+
:| white | Uize.Color ('white') |
|
906 |
+
...........................................
|
907 |
+
|
908 |
+
Decoding
|
909 |
+
When a color is decoded from =color=, the value of the source =Uize.Color= object instance's =encoding= property and the component values in its =tuple= property are used for the resulting =Uize.Color= object.
|
910 |
+
|
911 |
+
Static Properties
|
912 |
+
Uize.Color.encodings
|
913 |
+
An object, containing definitions for color encodings supported by the =Uize.Color= object.
|
914 |
+
|
915 |
+
The =Uize.Color= object defines a wide variety of built-in encodings. For the full list, consult the section `Color Encodings`. You can also define your own color encoding by extending the =Uize.Color.encodings= static property. For more information, see the section `Defining New Color Encodings`.
|
916 |
+
|
917 |
+
NOTES
|
918 |
+
- see the related =Uize.Color.colorSpaces= static property
|
919 |
+
*/
|
920 |
+
hex:{
|
921 |
+
colorSpace:'sRGB',
|
922 |
+
from:_setTupleFromRgbHex,
|
923 |
+
to:function (_tuple) {
|
924 |
+
return (0x1000000 + _encodings ['RGB int'].to (_tuple)).toString (16).slice (1);
|
925 |
+
}
|
926 |
+
/*?
|
927 |
+
Color Encodings
|
928 |
+
hex
|
929 |
+
A six digit, three digit, or one digit hexadecimal string (eg. the color chartreuse is encoded as ='7fff00'=).
|
930 |
+
|
931 |
+
Encoding
|
932 |
+
When a color is encoded as =hex=, the hexadecimal number always contains six digits and is all lowercase.
|
933 |
+
|
934 |
+
...........................
|
935 |
+
<< table >>
|
936 |
+
|
937 |
+
title: EXAMPLES
|
938 |
+
data
|
939 |
+
:| COLOR NAME | hex |
|
940 |
+
:| fuchsia | ff00ff |
|
941 |
+
:| yellow | ffff00 |
|
942 |
+
:| blue | 0000ff |
|
943 |
+
:| white | ffffff |
|
944 |
+
...........................
|
945 |
+
|
946 |
+
Decoding
|
947 |
+
When a color is decoded from =hex=, the hexadecimal number may be specified using only one digit, three digits, or six digits, the "#" (pound) character is optional, and the digits may be in upper, lower, or mixed case (ie. *not* case sensitive).
|
948 |
+
|
949 |
+
.................................................................................
|
950 |
+
<< table >>
|
951 |
+
|
952 |
+
title: WHITE
|
953 |
+
data
|
954 |
+
:| lowercase | UPPERCASE | #lowercase | #UPPERCASE | MiXeD | #MiXeD |
|
955 |
+
:| ffffff | FFFFFF | #ffffff | #FFFFFF | FfFfFf | #FfFfFf |
|
956 |
+
:| fff | FFF | #fff | #FFF | FfF | #FfF |
|
957 |
+
:| f | F | #f | #F | | |
|
958 |
+
.................................................................................
|
959 |
+
*/
|
960 |
+
},
|
961 |
+
'#hex':{
|
962 |
+
colorSpace:'sRGB',
|
963 |
+
from:_setTupleFromRgbHex,
|
964 |
+
to:function (_tuple) {return '#' + _encodings ['hex'].to (_tuple)}
|
965 |
+
/*?
|
966 |
+
Color Encodings
|
967 |
+
#hex
|
968 |
+
A six digit, three digit, or one digit hexadecimal string, with a "#" (pound) character prefixed (eg. the color chartreuse is encoded as ='#7fff00'=).
|
969 |
+
|
970 |
+
Encoding
|
971 |
+
When a color is encoded as =#hex=, the hexadecimal number always contains six digits, is all lowercase, and is prefixed with a "#" (pound) character.
|
972 |
+
|
973 |
+
............................
|
974 |
+
<< table >>
|
975 |
+
|
976 |
+
title: EXAMPLES
|
977 |
+
data
|
978 |
+
:| COLOR NAME | #hex |
|
979 |
+
:| fuchsia | #ff00ff |
|
980 |
+
:| yellow | #ffff00 |
|
981 |
+
:| blue | #0000ff |
|
982 |
+
:| white | #ffffff |
|
983 |
+
............................
|
984 |
+
|
985 |
+
Decoding
|
986 |
+
When a color is decoded from =#hex=, the hexadecimal number may be specified using only one digit, three digits, or six digits, the "#" (pound) character is optional, and the digits may be in upper, lower, or mixed case (ie. *not* case sensitive).
|
987 |
+
|
988 |
+
.................................................................................
|
989 |
+
<< table >>
|
990 |
+
|
991 |
+
title: WHITE
|
992 |
+
data
|
993 |
+
:| lowercase | UPPERCASE | #lowercase | #UPPERCASE | MiXeD | #MiXeD |
|
994 |
+
:| ffffff | FFFFFF | #ffffff | #FFFFFF | FfFfFf | #FfFfFf |
|
995 |
+
:| fff | FFF | #fff | #FFF | FfF | #FfF |
|
996 |
+
:| f | F | #f | #F | | |
|
997 |
+
.................................................................................
|
998 |
+
*/
|
999 |
+
},
|
1000 |
+
name:{
|
1001 |
+
colorSpace:'sRGB',
|
1002 |
+
from:function (_colorName,_tuple) {
|
1003 |
+
_encodings ['RGB int'].from (
|
1004 |
+
_colorName in _colors ? _colors [_colorName] : _colors [_colorName.toLowerCase ()],
|
1005 |
+
_tuple
|
1006 |
+
);
|
1007 |
+
},
|
1008 |
+
to:function (_tuple) {
|
1009 |
+
if (!_colorNamesLookup) {
|
1010 |
+
_colorNamesLookup = {};
|
1011 |
+
_updateColorNamesLookup (_colors);
|
1012 |
+
}
|
1013 |
+
return _colorNamesLookup [_encodings ['RGB int'].to (_tuple)] || _encodings ['hex'].to (_tuple);
|
1014 |
+
}
|
1015 |
+
/*?
|
1016 |
+
Color Encodings
|
1017 |
+
name
|
1018 |
+
A string, representing the name for a color (eg. the color chartreuse is encoded as ='chartreuse'=).
|
1019 |
+
|
1020 |
+
Encoding
|
1021 |
+
When a color is encoded as =name=, the name string is all lowercase. If no named color is defined that matches the color being encoded, then the encoding source will be encoded as =hex= as a fallback.
|
1022 |
+
|
1023 |
+
............................
|
1024 |
+
<< table >>
|
1025 |
+
|
1026 |
+
title: EXAMPLES
|
1027 |
+
data
|
1028 |
+
:| COLOR NAME | name |
|
1029 |
+
:| fuchsia | fuchsia |
|
1030 |
+
:| yellow | yellow |
|
1031 |
+
:| blue | blue |
|
1032 |
+
:| white | white |
|
1033 |
+
............................
|
1034 |
+
|
1035 |
+
Decoding
|
1036 |
+
When a color is decoded from =name=, the name may be in upper, lower, or mixed case (ie. *not* case sensitive). If no named color is defined by the name specified, then the color will be decoded as black (in the =sRGB= color space).
|
1037 |
+
|
1038 |
+
EXAMPLES
|
1039 |
+
.......
|
1040 |
+
fuchsia
|
1041 |
+
YELLOW
|
1042 |
+
Blue
|
1043 |
+
whITE
|
1044 |
+
.......
|
1045 |
+
|
1046 |
+
NOTES
|
1047 |
+
- for a list of all the color names supported by the =Uize.Color= module, see the section `Named Colors`
|
1048 |
+
- further named colors may be defined using the =Uize.Color.defineColors= static method (see the section `Defining New Named Colors`)
|
1049 |
+
- over a hundred additional named colors - as defined in the SVG 1.0 and CSS 3 specifications - are defined in the =Uize.Color.xSvgColors= extension module
|
1050 |
+
*/
|
1051 |
+
},
|
1052 |
+
'RGB array':{
|
1053 |
+
colorSpace:'sRGB',
|
1054 |
+
from:_setTupleFromArray,
|
1055 |
+
to:_cloneTuple
|
1056 |
+
/*?
|
1057 |
+
Color Encodings
|
1058 |
+
RGB array
|
1059 |
+
An array, containing three elements for the red, green, and blue channels of an =sRGB= color, whose values are integers (eg. the color chartreuse is encoded as =[127,255,0]=).
|
1060 |
+
|
1061 |
+
Encoding
|
1062 |
+
When a color is encoded as =RGB array=, the resulting array is made up of three number type elements that represent the values of the source color's red, green, and blue channels, respectively.
|
1063 |
+
|
1064 |
+
..................................
|
1065 |
+
<< table >>
|
1066 |
+
|
1067 |
+
title: EXAMPLES
|
1068 |
+
data
|
1069 |
+
:| COLOR NAME | RGB array |
|
1070 |
+
:| fuchsia | [255,0,255] |
|
1071 |
+
:| yellow | [255,255,0] |
|
1072 |
+
:| blue | [0,0,255] |
|
1073 |
+
:| white | [255,255,255] |
|
1074 |
+
..................................
|
1075 |
+
|
1076 |
+
Decoding
|
1077 |
+
When a color is decoded from =RGB array=, the values of the array's three elements may be numbers, strings, or any object that implements a =valueOf interface= (such as an instance of a =Uize.Class= subclass that implements the =value= state property).
|
1078 |
+
|
1079 |
+
EXAMPLES
|
1080 |
+
..................................
|
1081 |
+
[255,0,255] // fuchsia
|
1082 |
+
[255.5,0.23,254.7] // fuchsia
|
1083 |
+
['255','0','255'] // fuchsia
|
1084 |
+
[redSlider,greenSlider,blueSlider]
|
1085 |
+
..................................
|
1086 |
+
|
1087 |
+
NOTES
|
1088 |
+
- the values of the color components will be coerced to number type by invoking the =valueOf Intrinsic Method=
|
1089 |
+
*/
|
1090 |
+
},
|
1091 |
+
'RGB int':{
|
1092 |
+
colorSpace:'sRGB',
|
1093 |
+
from:function (_rgbInt,_tuple) {
|
1094 |
+
_rgbInt = Uize.constrain (Math.round (_rgbInt),0,16777215);
|
1095 |
+
_setTuple (_tuple,(_rgbInt >> 16) & 255,(_rgbInt >> 8) & 255,_rgbInt & 255);
|
1096 |
+
},
|
1097 |
+
to:function (_tuple) {
|
1098 |
+
return (_byte (_tuple [0]) << 16) + (_byte (_tuple [1]) << 8) + _byte (_tuple [2]);
|
1099 |
+
}
|
1100 |
+
/*?
|
1101 |
+
Color Encodings
|
1102 |
+
RGB int
|
1103 |
+
An integer in the range of =0= to =16777215=, corresponding in value to the hexadecimal RGB representation of a color (eg. the color chartreuse is encoded as =8388352=, which is equivalent to the hex number representation =0x7fff00=).
|
1104 |
+
|
1105 |
+
Encoding
|
1106 |
+
When a color is encoded as =RGB int=, it is calculated as =red * 65536 + green * 255 + blue=.
|
1107 |
+
|
1108 |
+
.............................
|
1109 |
+
<< table >>
|
1110 |
+
|
1111 |
+
title: EXAMPLES
|
1112 |
+
data
|
1113 |
+
:| COLOR NAME | RGB int |
|
1114 |
+
:| fuchsia | 16711935 |
|
1115 |
+
:| yellow | 16776960 |
|
1116 |
+
:| blue | 255 |
|
1117 |
+
:| white | 16777215 |
|
1118 |
+
.............................
|
1119 |
+
|
1120 |
+
Decoding
|
1121 |
+
When a color is decoded from =RGB int=, the value is first rounded and then constrained to the range of =0= to =16777215=.
|
1122 |
+
|
1123 |
+
EXAMPLES
|
1124 |
+
.....................
|
1125 |
+
16711935 // fuchsia
|
1126 |
+
0xff00ff // fuchsia
|
1127 |
+
.....................
|
1128 |
+
|
1129 |
+
*TIP:* When specifying colors as =RGB int=, you can use JavaScript's facility for specifying numbers in hexadecimal format using the "0x" prefix. This way, you're specifying an integer that looks exactly like a =hex= or =#hex= encoded RGB color value, but with the benefit of not using a more costly (in terms of performance) string.
|
1130 |
+
*/
|
1131 |
+
},
|
1132 |
+
'RGB object':{
|
1133 |
+
colorSpace:'sRGB',
|
1134 |
+
from:function (_rgbObject,_tuple) {
|
1135 |
+
_setTuple (_tuple,_rgbObject.red,_rgbObject.green,_rgbObject.blue);
|
1136 |
+
},
|
1137 |
+
to:function (_tuple) {return {red:_tuple [0],green:_tuple [1],blue:_tuple [2]}}
|
1138 |
+
/*?
|
1139 |
+
Color Encodings
|
1140 |
+
RGB object
|
1141 |
+
An object, containing =red=, =green=, and =blue= properties for the three =sRGB= channels, whose values are integers (eg. the color chartreuse is encoded as ={red:127,green:255,blue:0}=).
|
1142 |
+
|
1143 |
+
Encoding
|
1144 |
+
When a color is encoded as =RGB object=, the resulting object will contain the three number type properties =red=, =green=, and =blue=, reflecting the values of the source color's red, green, and blue channels.
|
1145 |
+
|
1146 |
+
.................................................
|
1147 |
+
<< table >>
|
1148 |
+
|
1149 |
+
title: EXAMPLES
|
1150 |
+
data
|
1151 |
+
:| COLOR NAME | RGB object |
|
1152 |
+
:| fuchsia | {red:255,green:0,blue:255} |
|
1153 |
+
:| yellow | {red:255,green:255,blue:0} |
|
1154 |
+
:| blue | {red:0,green:0,blue:255} |
|
1155 |
+
:| white | {red:255,green:255,blue:255} |
|
1156 |
+
.................................................
|
1157 |
+
|
1158 |
+
Decoding
|
1159 |
+
When a color is decoded from =RGB object=, the values of the object's =red=, =green=, and =blue= properties may be numbers, strings, or any object that implements a =valueOf interface= interface (such as an instance of a =Uize.Class= subclass that implements the =value= state property).
|
1160 |
+
|
1161 |
+
EXAMPLES
|
1162 |
+
.................................................
|
1163 |
+
{red:255,green:0,blue:255} // fuchsia
|
1164 |
+
{red:255.5,green:0.23,blue:254.7} // fuchsia
|
1165 |
+
{red:'255',green:'0',blue:'255'} // fuchsia
|
1166 |
+
{red:redSlider,green:greenSlider,blue:blueSlider}
|
1167 |
+
.................................................
|
1168 |
+
|
1169 |
+
NOTES
|
1170 |
+
- the values of the color components will be coerced to number type by invoking the =valueOf Intrinsic Method=
|
1171 |
+
- the property names of the source =RGB object= must be all lowercase
|
1172 |
+
*/
|
1173 |
+
},
|
1174 |
+
'RGB string':{
|
1175 |
+
colorSpace:'sRGB',
|
1176 |
+
from:_setTupleFromString,
|
1177 |
+
to:function (_tuple) {
|
1178 |
+
return 'rgb(' + _byte (_tuple [0]) + ',' + _byte (_tuple [1]) + ',' + _byte (_tuple [2]) +')';
|
1179 |
+
}
|
1180 |
+
/*?
|
1181 |
+
Color Encodings
|
1182 |
+
RGB string
|
1183 |
+
An =Rgb(...)= formatted CSS color style property value (eg. the color chartreuse is encoded as ='rgb(127,255,0)'=)
|
1184 |
+
|
1185 |
+
Encoding
|
1186 |
+
When a color is encoded as =RGB string=, the resulting string will always be all lowercase, without any spaces, and the values of the red, green, and blue components will be rounded and constrained to the range of =0= to =255=.
|
1187 |
+
|
1188 |
+
.....................................
|
1189 |
+
<< table >>
|
1190 |
+
|
1191 |
+
title: EXAMPLES
|
1192 |
+
data
|
1193 |
+
:| COLOR NAME | RGB string |
|
1194 |
+
:| fuchsia | rgb(255,0,255) |
|
1195 |
+
:| yellow | rgb(255,255,0) |
|
1196 |
+
:| blue | rgb(0,0,255) |
|
1197 |
+
:| white | rgb(255,255,255) |
|
1198 |
+
.....................................
|
1199 |
+
|
1200 |
+
Decoding
|
1201 |
+
When a color is decoded from =RGB string=, the string may contain separating spaces, and may be in upper, lower, or mixed case (ie. *not* case sensitive).
|
1202 |
+
|
1203 |
+
FUCHSIA
|
1204 |
+
.....................
|
1205 |
+
rgb(255,0,255)
|
1206 |
+
RGB(255,0,255)
|
1207 |
+
Rgb (255, 0, 255)
|
1208 |
+
RGB ( 255 , 0 , 255 )
|
1209 |
+
.....................
|
1210 |
+
*/
|
1211 |
+
},
|
1212 |
+
'HSL array':{
|
1213 |
+
colorSpace:'HSL',
|
1214 |
+
from:_setTupleFromArray,
|
1215 |
+
to:_cloneTuple
|
1216 |
+
/*?
|
1217 |
+
Color Encodings
|
1218 |
+
HSL array
|
1219 |
+
An array, containing three elements for hue, saturation, and lightness, whose values may be floating point numbers (eg. the color chartreuse is encoded as =[90.11764705882354,100,50]=), and that specifies a color in the =HSL= color space.
|
1220 |
+
|
1221 |
+
Encoding
|
1222 |
+
When a color is encoded as =HSL array=, the resulting array is made up of three number type elements that represent the values of the source color's hue, saturation, and lightness, respectively.
|
1223 |
+
|
1224 |
+
.................................
|
1225 |
+
<< table >>
|
1226 |
+
|
1227 |
+
title: EXAMPLES
|
1228 |
+
data
|
1229 |
+
:| COLOR NAME | HSL array |
|
1230 |
+
:| fuchsia | [300,100,50] |
|
1231 |
+
:| yellow | [60,100,50] |
|
1232 |
+
:| blue | [240,100,50] |
|
1233 |
+
:| white | [0,0,100] |
|
1234 |
+
.................................
|
1235 |
+
|
1236 |
+
Decoding
|
1237 |
+
When a color is decoded from =HSL array=, the values of the array's three elements may be numbers, strings, or any object that implements a =valueOf interface= interface (such as an instance of a =Uize.Class= subclass that implements the =value= state property).
|
1238 |
+
|
1239 |
+
EXAMPLES
|
1240 |
+
............................................
|
1241 |
+
[300,100,50] // fuchsia
|
1242 |
+
['300','100','50'] // fuchsia
|
1243 |
+
[hueSlider,saturationSlider,lightnessSlider]
|
1244 |
+
............................................
|
1245 |
+
|
1246 |
+
NOTES
|
1247 |
+
- the values of the color components will be coerced to number type by invoking the =valueOf Intrinsic Method=
|
1248 |
+
- string values for the saturation and lightness components in the array *may not* contain a "%" (percent) suffix
|
1249 |
+
*/
|
1250 |
+
},
|
1251 |
+
'HSL object':{
|
1252 |
+
colorSpace:'HSL',
|
1253 |
+
from:function (_hslObject,_tuple) {
|
1254 |
+
_setTuple (_tuple,_hslObject.hue,_hslObject.saturation,_hslObject.lightness);
|
1255 |
+
},
|
1256 |
+
to:function (_tuple) {return {hue:_tuple [0],saturation:_tuple [1],lightness:_tuple [2]}}
|
1257 |
+
/*?
|
1258 |
+
Color Encodings
|
1259 |
+
HSL object
|
1260 |
+
An object, containing =hue=, =saturation=, and =lightness= properties, whose values may be floating point numbers (eg. the color chartreuse is encoded as ={hue:90.11764705882354,saturation:100,lightness:50}=), and that specifies a color in the =HSL= color space.
|
1261 |
+
|
1262 |
+
Encoding
|
1263 |
+
When a color is encoded as =HSL object=, the resulting object will contain the three number type properties =hue=, =saturation=, and =lightness=, reflecting the values of the source color's hue, saturation, and lightness.
|
1264 |
+
|
1265 |
+
..........................................................
|
1266 |
+
<< table >>
|
1267 |
+
|
1268 |
+
title: EXAMPLES
|
1269 |
+
data
|
1270 |
+
:| COLOR NAME | HSL object |
|
1271 |
+
:| fuchsia | {hue:300,saturation:100,lightness:50} |
|
1272 |
+
:| yellow | {hue:60,saturation:100,lightness:50} |
|
1273 |
+
:| blue | {hue:240,saturation:100,lightness:50} |
|
1274 |
+
:| white | {hue:0,saturation:0,lightness:100} |
|
1275 |
+
..........................................................
|
1276 |
+
|
1277 |
+
Decoding
|
1278 |
+
When a color is decoded from =HSL object=, the values of the object's =hue=, =saturation=, and =lightness= properties may be numbers, strings, or any object that implements a =valueOf interface= interface (such as an instance of a =Uize.Class= subclass that implements the =value= state property).
|
1279 |
+
|
1280 |
+
EXAMPLES
|
1281 |
+
.....................................................................
|
1282 |
+
{hue:300,saturation:100,lightness:50} // fuchsia
|
1283 |
+
{hue:'300',saturation:'100',lightness:'50'} // fuchsia
|
1284 |
+
{hue:hueSlider,saturation:saturationSlider,lightness:lightnessSlider}
|
1285 |
+
.....................................................................
|
1286 |
+
|
1287 |
+
NOTES
|
1288 |
+
- the values of the color components will be coerced to number type by invoking the =valueOf Intrinsic Method=
|
1289 |
+
- string values for the saturation and lightness components in the array *may not* contain a "%" (percent) suffix
|
1290 |
+
- the property names of the source =RGB object= must be all lowercase
|
1291 |
+
*/
|
1292 |
+
},
|
1293 |
+
'HSL string':{
|
1294 |
+
colorSpace:'HSL',
|
1295 |
+
from:_setTupleFromString,
|
1296 |
+
to:function (_tuple) {
|
1297 |
+
function _percentStr (_percent) {return Uize.constrain (Math.round (_percent),0,100) + '%'}
|
1298 |
+
return (
|
1299 |
+
'hsl(' +
|
1300 |
+
Math.round (_tuple [0]) + ',' +
|
1301 |
+
_percentStr (_tuple [1]) + ',' +
|
1302 |
+
_percentStr (_tuple [2]) +
|
1303 |
+
')'
|
1304 |
+
);
|
1305 |
+
}
|
1306 |
+
/*?
|
1307 |
+
Color Encodings
|
1308 |
+
HSL string
|
1309 |
+
An =Hsl(...)= formatted CSS color style property value (eg. the color chartreuse is encoded as ='hsl(90,100%,50%)'=) that specifies a color in the =HSL= color space.
|
1310 |
+
|
1311 |
+
Encoding
|
1312 |
+
When a color is encoded as =HSL string=, the resulting string will always be all lowercase, without any spaces.
|
1313 |
+
|
1314 |
+
Furthermore, the values for hue, saturation, and lightness will be rounded to the nearest integer, and a "%" (percent symbol) character will be appended to the values for saturation and lightness.
|
1315 |
+
|
1316 |
+
......................................
|
1317 |
+
<< table >>
|
1318 |
+
|
1319 |
+
title: EXAMPLES
|
1320 |
+
data
|
1321 |
+
:| COLOR NAME | HSL string |
|
1322 |
+
:| fuchsia | hsl(300,100%,50%) |
|
1323 |
+
:| yellow | hsl(60,100%,50%) |
|
1324 |
+
:| blue | hsl(240,100%,50%) |
|
1325 |
+
:| white | hsl(0,0%,100%) |
|
1326 |
+
......................................
|
1327 |
+
|
1328 |
+
NOTES
|
1329 |
+
- because encoding as =HSL string= rounds the values for hue, saturation, and lightness, colors encoded as =HSL string= may not produce exactly the same original color when decoding the encoded =HSL string=
|
1330 |
+
|
1331 |
+
Decoding
|
1332 |
+
When a color is decoded from =HSL string=, the string may contain separating spaces, may be in upper, lower, or mixed case (ie. *not* case sensitive), and the "%" (percent symbol) character for the saturation and lightness values may be omitted.
|
1333 |
+
|
1334 |
+
FUCHSIA
|
1335 |
+
........................
|
1336 |
+
hsl(300,100,50)
|
1337 |
+
hsl(300,100%,50%)
|
1338 |
+
HSL(300,100%,50%)
|
1339 |
+
Hsl (300, 100%, 50%)
|
1340 |
+
HSL ( 300 , 100% , 50% )
|
1341 |
+
Hsl ( 300 , 100 , 50 )
|
1342 |
+
........................
|
1343 |
+
*/
|
1344 |
+
}
|
1345 |
+
/*?
|
1346 |
+
Color Encodings
|
1347 |
+
Defining New Color Encodings
|
1348 |
+
You can extend the =Uize.Color.encodings= object in order to define new color encodings.
|
1349 |
+
|
1350 |
+
This can be done quite easily by setting a new property on the =Uize.Color.encodings= object, as follows...
|
1351 |
+
|
1352 |
+
EXAMPLE
|
1353 |
+
..................................................................
|
1354 |
+
Uize.Color.encodings ['RGB float array'] = {
|
1355 |
+
colorSpace:'sRGB',
|
1356 |
+
from:function (_colorValue,_tuple) {
|
1357 |
+
_tuple [0] = _colorValue [0] * 255;
|
1358 |
+
_tuple [1] = _colorValue [1] * 255;
|
1359 |
+
_tuple [2] = _colorValue [2] * 255;
|
1360 |
+
},
|
1361 |
+
to:function (_tuple) {
|
1362 |
+
return [_tuple [0] / 255,_tuple [1] / 255,_tuple [2] / 255];
|
1363 |
+
}
|
1364 |
+
}
|
1365 |
+
..................................................................
|
1366 |
+
|
1367 |
+
The above example defines an encoding named "RGB float aray", where the three elements of the array represent the values of the red, green, and blue channels as floating point numbers in the range of =0= to =1=. So, whereas the statement =Uize.Color.to ('purple','RGB array')= would produce the result =[128,0,128]=, the statement =Uize.Color.to ('purple','RGB float array')= would produce the result =[0.5019607843137255,0,0.5019607843137255]=. Conversely, the statement =Uize.Color.to ({'RGB float array':[.5,0,.5]},'name')= would produce the result ='purple'=.
|
1368 |
+
|
1369 |
+
The object that describes a color encoding is called a color encoding profile, and should have the following properties...
|
1370 |
+
|
1371 |
+
- =colorSpace= - This is the name of the color space that is associated with the encoding, and should be one of the `Color Spaces` defined in the =Uize.Color.colorSpaces= static property.
|
1372 |
+
|
1373 |
+
- =from (decoder function)= - This is a function that should set the values of the elements of the provided tuple array, based upon the provided color value. The function should expect two parameters: 1) the color value, and 2) the tuple. The function should decode (ie. process or parse) the color value as needed in order to set the appropriate values for the components of the color in the provided tuple array. The function does not need to return anything, and anything it returns will be ignored.
|
1374 |
+
|
1375 |
+
- =to (encoder function)= - This is a function that should use the values for the components of the color in the provided tuple array, and encode them as needed in order to produce a color value. The encoded color value should then be returned by the function.
|
1376 |
+
*/
|
1377 |
+
};
|
1378 |
+
|
1379 |
+
/*** Colors ***/
|
1380 |
+
var _colors = _object.colors = {
|
1381 |
+
white: 16777215, // 0xffffff
|
1382 |
+
silver: 12632256, // 0xc0c0c0
|
1383 |
+
gray: 8421504, // 0x808080
|
1384 |
+
black: 0, // 0x000000
|
1385 |
+
navy: 128, // 0x000080
|
1386 |
+
blue: 255, // 0x0000ff
|
1387 |
+
aqua: 65535, // 0x00ffff
|
1388 |
+
teal: 32896, // 0x008080
|
1389 |
+
green: 32768, // 0x008000
|
1390 |
+
olive: 8421376, // 0x808000
|
1391 |
+
lime: 65280, // 0x00ff00
|
1392 |
+
maroon: 8388608, // 0x800000
|
1393 |
+
red: 16711680, // 0xff0000
|
1394 |
+
orange: 16753920, // 0xffa500
|
1395 |
+
yellow: 16776960, // 0xffff00
|
1396 |
+
purple: 8388736, // 0x800080
|
1397 |
+
fuchsia: 16711935 // 0xff00ff
|
1398 |
+
/*?
|
1399 |
+
Static Properties
|
1400 |
+
Uize.Color.colors
|
1401 |
+
An object, containing presets for the standard color names supported in the CSS 2.1 specification.
|
1402 |
+
|
1403 |
+
Named colors defined in the =Uize.Color.colors= object can be used wherever color values can be specified in the methods of the =Uize.Color= object, and other modules that use this object for resolving color values.
|
1404 |
+
|
1405 |
+
EXAMPLE
|
1406 |
+
.....................................................................
|
1407 |
+
Uize.Color ('yellow'); // source encoding is name
|
1408 |
+
Uize.Color (Uize.Color.colors.yellow); // source encoding is RGB int
|
1409 |
+
.....................................................................
|
1410 |
+
|
1411 |
+
In the above example, each of the statements would create a new instance of the =Uize.Color= object initialized to primary yellow. In the first statement, the color yellow is specified using the =name= encoding. In the second statement, however, the color is specified using the =RGB int= encoding. That's because the values of the properties of the =Uize.Color.colors= static property are actually integers representing the RGB values of the colors.
|
1412 |
+
|
1413 |
+
For more information, see the section `Named Colors`. You can also define your own named colors by extending the =Uize.Color.colors= static property. For more information, see the section `Defining New Named Colors`.
|
1414 |
+
|
1415 |
+
NOTES
|
1416 |
+
- see the related =Uize.Color.defineColors= static method
|
1417 |
+
- over a hundred additional named colors - as defined in the SVG 1.0 and CSS 3 specifications - are defined in the =Uize.Color.xSvgColors= extension module
|
1418 |
+
|
1419 |
+
Named Colors
|
1420 |
+
The =Uize.Color= object defines a set of seventeen standard named colors (as defined in the [[http://www.w3.org/TR/CSS21/syndata.html#value-def-color][CSS 2.1 color specification]]) in the =Uize.Color.colors= object.
|
1421 |
+
|
1422 |
+
.............................
|
1423 |
+
<< table >>
|
1424 |
+
|
1425 |
+
title: NAMED COLORS
|
1426 |
+
data
|
1427 |
+
:| COLOR NAME | HEX VALUE |
|
1428 |
+
:| white | #ffffff |
|
1429 |
+
:| silver | #c0c0c0 |
|
1430 |
+
:| gray | #808080 |
|
1431 |
+
:| black | #000000 |
|
1432 |
+
:| navy | #000080 |
|
1433 |
+
:| blue | #0000ff |
|
1434 |
+
:| aqua | #00ffff |
|
1435 |
+
:| teal | #008080 |
|
1436 |
+
:| green | #008000 |
|
1437 |
+
:| olive | #808000 |
|
1438 |
+
:| lime | #00ff00 |
|
1439 |
+
:| maroon | #800000 |
|
1440 |
+
:| red | #ff0000 |
|
1441 |
+
:| orange | #ffa500 |
|
1442 |
+
:| yellow | #ffff00 |
|
1443 |
+
:| purple | #800080 |
|
1444 |
+
:| fuchsia | #ff00ff |
|
1445 |
+
.............................
|
1446 |
+
|
1447 |
+
Using Named Colors
|
1448 |
+
Named colors defined in the =Uize.Color.colors= object can be used wherever color values can be specified in the methods of the =Uize.Color= object, and other modules that use this object for resolving color values.
|
1449 |
+
|
1450 |
+
EXAMPLE 1
|
1451 |
+
.....................................
|
1452 |
+
var myColor = Uize.Color ('fuchsia');
|
1453 |
+
.....................................
|
1454 |
+
|
1455 |
+
In the above example, the =Uize.Color= instance =myColor= is being initialized to the color "fuchsia" (=#ff00ff=).
|
1456 |
+
|
1457 |
+
EXAMPLE 2
|
1458 |
+
......................................................
|
1459 |
+
var fuchsiaAsHexStr = Uize.Color.to ('fuchsia','hex');
|
1460 |
+
......................................................
|
1461 |
+
|
1462 |
+
In the above example, the color "fuchsia" is being converted to a hexadecimal string using the =hex= encoding.
|
1463 |
+
|
1464 |
+
EXAMPLE 3
|
1465 |
+
..............................................................................
|
1466 |
+
Uize.Fx.fadeStyle ('myNodeId',{borderColor:'purple'},{borderColor:'fuchsia'});
|
1467 |
+
..............................................................................
|
1468 |
+
|
1469 |
+
Because the =Uize.Color= module is used by other modules, such as the =Uize.Fx= module, it is also possible to use color names when specifying the values of color CSS style properties for fade effects.
|
1470 |
+
|
1471 |
+
Additional Named Colors
|
1472 |
+
Additional named colors are made available through extension modules, such as the =Uize.Color.xSvgColors= module that defines the SVG 1.0 / CSS 3 named colors.
|
1473 |
+
|
1474 |
+
Over a hundred additional named colors - as defined in the SVG 1.0 and CSS 3 specifications - are defined in the =Uize.Color.xSvgColors= extension module. Implementing further named colors in extension modules avoids burdening the core code with having to support less frequently used color sets. This also allows applications built on the UIZE JavaScript Framework to be better optimized for code size.
|
1475 |
+
|
1476 |
+
Defining New Named Colors
|
1477 |
+
You can extend the =Uize.Color.colors= object using the =Uize.Color.defineColors= static method in order to add your own named colors, which will then be accessible to code that uses the =Uize.Color= module.
|
1478 |
+
|
1479 |
+
EXAMPLE
|
1480 |
+
.............................................................................
|
1481 |
+
Uize.Color.defineColors ({darkmagenta:0x8b008b,lavenderblush:0xfff0f5});
|
1482 |
+
Uize.Fx.fadeStyle ('myNodeId',{color:'darkmagenta'},{color:'lavenderblush'});
|
1483 |
+
.............................................................................
|
1484 |
+
|
1485 |
+
When extending the =Uize.Color.colors= object, the names of added colors should be in all lowecase, and the values should be specified in the =RGB int= encoding (you can use JavaScript's hexadecimal notation for convenience, so that the =RGB int= encoding resembles the =hex= or =#hex= encodings).
|
1486 |
+
|
1487 |
+
INCORRECT
|
1488 |
+
.................................................................................
|
1489 |
+
Uize.Color.defineColors ({DarkMagenta:0x8b008b}); // DON'T USE MIXED CASE
|
1490 |
+
Uize.Color.defineColors ({lavenderblush:'#fff0f5'}); // DON'T USE OTHER ENCODING
|
1491 |
+
.................................................................................
|
1492 |
+
|
1493 |
+
CORRECT
|
1494 |
+
......................................................................................
|
1495 |
+
Uize.Color.defineColors ({darkmagenta:0x8b008b}); // OK TO USE HEX FORMATTED NUMBER
|
1496 |
+
Uize.Color.defineColors ({lavenderblush:16773365}); // OK TO USE DECIMAL NUMBER
|
1497 |
+
......................................................................................
|
1498 |
+
|
1499 |
+
NOTES
|
1500 |
+
- see the related =Uize.Color.colors= static property
|
1501 |
+
- see the related =Uize.Color.defineColors= static method
|
1502 |
+
- over a hundred additional named colors - as defined in the SVG 1.0 and CSS 3 specifications - are defined in the =Uize.Color.xSvgColors= extension module
|
1503 |
+
*/
|
1504 |
+
};
|
1505 |
+
|
1506 |
+
/*** dummy color objects for mixing and conversion ***/
|
1507 |
+
var
|
1508 |
+
_dummyColor1 = new _object,
|
1509 |
+
_dummyColor2 = new _object
|
1510 |
+
;
|
1511 |
+
|
1512 |
+
return _object;
|
1513 |
+
}
|
1514 |
+
});
|
1515 |
+
|
skin/frontend/default/customproduct/js/Uize.Color.xCmyk.js
ADDED
@@ -0,0 +1,237 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Color.xCmyk Object Extension
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2011-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Extension
|
14 |
+
importance: 1
|
15 |
+
codeCompleteness: 10
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Color.xCmyk= module extends the =Uize.Color= object by adding a profile for the =CMYK= color space, and by providing encodings for this color space.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
The =Uize.Color.colorSpaces.CMYK= property - defined in this extension - provides a profile for the [[http://en.wikipedia.org/wiki/Cmyk][CMYK]] (Cyan, Magenta, Yellow, Key) color space. The CMYK color model is a subtractive color model used to describe the printing process. Some examples of CMYK formatted colors can be viewed at [[http://www.december.com/html/spec/colorcmyk.html]].
|
27 |
+
|
28 |
+
Color Encodings
|
29 |
+
The =Uize.Color.xCmyk= extension implements support for the following color encodings / formats...
|
30 |
+
*/
|
31 |
+
|
32 |
+
Uize.module ({
|
33 |
+
name:'Uize.Color.xCmyk',
|
34 |
+
builder:function (_Uize_Color) {
|
35 |
+
var _sRgbColorSpace = _Uize_Color.colorSpaces.sRGB;
|
36 |
+
|
37 |
+
/*** Color Profile ***/
|
38 |
+
_Uize_Color.colorSpaces.CMYK = {
|
39 |
+
fromHsl:function (_tuple) {
|
40 |
+
// HSL to RGB first, then RGB to CMYK
|
41 |
+
_tuple = _sRgbColorSpace.fromHsl (_tuple);
|
42 |
+
var
|
43 |
+
_red = _tuple [0] / 255,
|
44 |
+
_green = _tuple [1] / 255,
|
45 |
+
_blue = _tuple [2] / 255,
|
46 |
+
_key = Math.min (1 - _red,1 - _green,1 - _blue),
|
47 |
+
_1minusKey = 1 - _key
|
48 |
+
;
|
49 |
+
return [
|
50 |
+
_1minusKey && ((_1minusKey - _red) / _1minusKey * 100),
|
51 |
+
_1minusKey && ((_1minusKey - _green) / _1minusKey * 100),
|
52 |
+
_1minusKey && ((_1minusKey - _blue) / _1minusKey * 100),
|
53 |
+
_key * 100
|
54 |
+
];
|
55 |
+
},
|
56 |
+
toHsl:function (_tuple) {
|
57 |
+
// CMYK to RGB first, then RGB to HSL
|
58 |
+
var
|
59 |
+
_key = _tuple [3] / 100,
|
60 |
+
_1minusKey = 1 - _key
|
61 |
+
;
|
62 |
+
return _sRgbColorSpace.toHsl ([
|
63 |
+
(1 - Math.min (1,_tuple [0] / 100 * _1minusKey + _key)) * 255,
|
64 |
+
(1 - Math.min (1,_tuple [1] / 100 * _1minusKey + _key)) * 255,
|
65 |
+
(1 - Math.min (1,_tuple [2] / 100 * _1minusKey + _key)) * 255
|
66 |
+
]);
|
67 |
+
}
|
68 |
+
};
|
69 |
+
|
70 |
+
/*** Color Encodings ***/
|
71 |
+
Uize.copyInto (
|
72 |
+
_Uize_Color.encodings,
|
73 |
+
{
|
74 |
+
'CMYK array':{
|
75 |
+
colorSpace:'CMYK',
|
76 |
+
from:_Uize_Color.setTupleFromArray,
|
77 |
+
to:_Uize_Color.cloneTuple
|
78 |
+
/*?
|
79 |
+
Color Encodings
|
80 |
+
CMYK array
|
81 |
+
An array, containing four elements for cyan, magenta, yellow, and key components of the color, whose values may be floating point numbers in the range of =0= to =100= (eg. the color chartreuse is encoded as =[50,0,100,0]=).
|
82 |
+
|
83 |
+
SYNTAX
|
84 |
+
..........................................................................
|
85 |
+
[ cyan0to100FLOAT, magenta0to100FLOAT, yellow0to100FLOAT, key0to100FLOAT ]
|
86 |
+
..........................................................................
|
87 |
+
|
88 |
+
Encoding
|
89 |
+
When a color is encoded as =CMYK array=, the resulting array is made up of four number type elements that represent the values of the source color's cyan, magenta, yellow, and key components, respectively.
|
90 |
+
|
91 |
+
...............................
|
92 |
+
<< table >>
|
93 |
+
|
94 |
+
title: EXAMPLES
|
95 |
+
data
|
96 |
+
:| COLOR NAME | CMYK array |
|
97 |
+
:| fuchsia | [0,100,0,0] |
|
98 |
+
:| yellow | [0,0,100,0] |
|
99 |
+
:| blue | [100,100,0,0] |
|
100 |
+
:| white | [0,0,0,0] |
|
101 |
+
...............................
|
102 |
+
|
103 |
+
Decoding
|
104 |
+
When a color is decoded from =CMYK array=, the values of the array's four elements may be numbers, strings, or any object that implements a =valueOf= interface (such as an instance of a =Uize.Class= subclass that implements the =value= state property).
|
105 |
+
|
106 |
+
The values will be coerced to number type by invoking the =valueOf Intrinsic Method=.
|
107 |
+
|
108 |
+
EXAMPLES
|
109 |
+
.................................................
|
110 |
+
[0,100,0,0] // fuchsia
|
111 |
+
['0','100','0','0'] // fuchsia
|
112 |
+
[cyanSlider,magentaSlider,yellowSlider,keySlider]
|
113 |
+
.................................................
|
114 |
+
|
115 |
+
NOTES
|
116 |
+
- string values for the elements of the array *may not* contain a "%" (percent) suffix
|
117 |
+
*/
|
118 |
+
},
|
119 |
+
'CMYK object':{
|
120 |
+
colorSpace:'CMYK',
|
121 |
+
from:function (_cmykObject,_tuple) {
|
122 |
+
_Uize_Color.setTuple (
|
123 |
+
_tuple,_cmykObject.cyan,_cmykObject.magenta,_cmykObject.yellow,_cmykObject.key
|
124 |
+
);
|
125 |
+
},
|
126 |
+
to:function (_tuple) {return {cyan:_tuple [0],magenta:_tuple [1],yellow:_tuple [2],key:_tuple [3]}}
|
127 |
+
/*?
|
128 |
+
Color Encodings
|
129 |
+
CMYK object
|
130 |
+
An object, containing =cyan=, =magenta=, =yellow=, and =key= properties, whose values may be floating point numbers in the range of =0= to =100= (eg. the color chartreuse is encoded as ={cyan:50,magenta:0,yellow:100,key:0}=).
|
131 |
+
|
132 |
+
SYNTAX
|
133 |
+
................................
|
134 |
+
{
|
135 |
+
cyan : cyan0to100FLOAT,
|
136 |
+
magenta : magenta0to100FLOAT,
|
137 |
+
yellow : yellow0to100FLOAT,
|
138 |
+
key : key0to100FLOAT
|
139 |
+
}
|
140 |
+
................................
|
141 |
+
|
142 |
+
Encoding
|
143 |
+
When a color is encoded as =CMYK object=, the resulting object will contain the four number type properties =cyan=, =magenta=, =yellow=, and =key=, reflecting the values of the source color's cyan, magenta, yellow, and key components, respectively.
|
144 |
+
|
145 |
+
.......................................................
|
146 |
+
<< table >>
|
147 |
+
|
148 |
+
title: EXAMPLES
|
149 |
+
data
|
150 |
+
:| COLOR NAME | CMYK object |
|
151 |
+
:| fuchsia | {cyan:0,magenta:100,yellow:0,key:0} |
|
152 |
+
:| yellow | {cyan:0,magenta:0,yellow:100,key:0} |
|
153 |
+
:| blue | {cyan:100,magenta:100,yellow:0,key:0} |
|
154 |
+
:| white | {cyan:0,magenta:0,yellow:0,key:0} |
|
155 |
+
.......................................................
|
156 |
+
|
157 |
+
Decoding
|
158 |
+
When a color is decoded from =CMYK object=, the values of the object's =cyan=, =magenta=, =yellow=, and =key= properties may be numbers, strings, or any object that implements a =valueOf= interface (such as an instance of a =Uize.Class= subclass that implements the =value= state property).
|
159 |
+
|
160 |
+
The values will be coerced to number type by invoking the =valueOf Intrinsic Method=.
|
161 |
+
|
162 |
+
EXAMPLES
|
163 |
+
.........................................................................
|
164 |
+
{cyan:0,magenta:100,yellow:0,key:0} // fuchsia
|
165 |
+
{cyan:'0',magenta:'100',yellow:'0',key:'0'} // fuchsia
|
166 |
+
{cyan:cyanSlider,magenta:magentaSlider,yellow:yellowSlider,key:keySlider}
|
167 |
+
.........................................................................
|
168 |
+
|
169 |
+
NOTES
|
170 |
+
- string values for the properties of the object *may not* contain a "%" (percent) suffix
|
171 |
+
*/
|
172 |
+
},
|
173 |
+
'CMYK string':{
|
174 |
+
colorSpace:'CMYK',
|
175 |
+
from:_Uize_Color.setTupleFromString,
|
176 |
+
to:function (_tuple) {
|
177 |
+
function _roundAndConstrainComponent (_componentNo) {
|
178 |
+
return Uize.constrain (Math.round (_tuple [_componentNo]),0,100);
|
179 |
+
}
|
180 |
+
return (
|
181 |
+
'cmyk(' +
|
182 |
+
_roundAndConstrainComponent (0) + '%,' +
|
183 |
+
_roundAndConstrainComponent (1) + '%,' +
|
184 |
+
_roundAndConstrainComponent (2) + '%,' +
|
185 |
+
_roundAndConstrainComponent (3) + '%' +
|
186 |
+
')'
|
187 |
+
);
|
188 |
+
}
|
189 |
+
/*?
|
190 |
+
Color Encodings
|
191 |
+
CMYK string
|
192 |
+
A =Cmyk(...)= formatted 4-tuple string (eg. the color chartreuse is encoded as ='cmyk(50%,0%,100%,0%)'=).
|
193 |
+
|
194 |
+
SYNTAX
|
195 |
+
.................................................................
|
196 |
+
cmyk([cyan0to100]%,[magenta0to100]%,[yellow0to100]%,[key0to100]%)
|
197 |
+
.................................................................
|
198 |
+
|
199 |
+
Encoding
|
200 |
+
When a color is encoded as =CMYK string=, the resulting string will always be all lowercase, without any spaces.
|
201 |
+
|
202 |
+
Furthermore, the values for cyan, magenta, yellow, and key components of the tuple will be rounded to the nearest integer and constrained to a range of =0= to =100=, with a "%" (percent symbol) character appended to each.
|
203 |
+
|
204 |
+
.......................................
|
205 |
+
<< table >>
|
206 |
+
|
207 |
+
title: EXAMPLES
|
208 |
+
data
|
209 |
+
:| COLOR NAME | CMYK string |
|
210 |
+
:| fuchsia | cmyk(0%,100%,0%,0%) |
|
211 |
+
:| yellow | cmyk(0%,0%,100%,0%) |
|
212 |
+
:| blue | cmyk(100%,100%,0%,0%) |
|
213 |
+
:| white | cmyk(0%,0%,0%,0%) |
|
214 |
+
.......................................
|
215 |
+
|
216 |
+
NOTES
|
217 |
+
- because encoding as =CMYK string= rounds the values for all four components of a color, colors encoded as =CMYK string= may not produce exactly the same original color when decoding the encoded =CMYK string=
|
218 |
+
|
219 |
+
Decoding
|
220 |
+
When a color is decoded from =CMYK string=, the string may contain separating spaces, may be in upper, lower, or mixed case (ie. *not* case sensitive), and the "%" (percent symbol) character for the saturation and value values may be omitted.
|
221 |
+
|
222 |
+
FUCHSIA
|
223 |
+
............................
|
224 |
+
cmyk(0,100,0,0)
|
225 |
+
cmyk(0%,100%,0%,0%)
|
226 |
+
CMYK(0%,100%,0%,0%)
|
227 |
+
Cmyk (0%, 100%, 0%, 0%)
|
228 |
+
CMYK ( 0% , 100% , 0% , 0% )
|
229 |
+
Cmyk ( 0 , 100 , 0 , 0 )
|
230 |
+
............................
|
231 |
+
*/
|
232 |
+
}
|
233 |
+
}
|
234 |
+
);
|
235 |
+
}
|
236 |
+
});
|
237 |
+
|
skin/frontend/default/customproduct/js/Uize.Color.xHsv.js
ADDED
@@ -0,0 +1,223 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Color.xHsv Object Extension
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2009-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Extension
|
14 |
+
importance: 3
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Color.xHsv= module extends the =Uize.Color= object by adding a profile for the =HSV= color space, and by providing encodings for this color space.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
The =Uize.Color.colorSpaces.HSV= property - defined in this extension - provides a profile for the [[http://en.wikipedia.org/wiki/HSL_color_space][HSV]] (Hue, Saturation, Value) color space. The HSV color space is essentially an alternate representation / mapping of the =sRGB= color space, but might be considered to be a more intuitive representation of the qualities of color.
|
27 |
+
|
28 |
+
Color Encodings
|
29 |
+
The =Uize.Color.xHsv= extension implements support for the following color encodings / formats...
|
30 |
+
*/
|
31 |
+
|
32 |
+
Uize.module ({
|
33 |
+
name:'Uize.Color.xHsv',
|
34 |
+
builder:function (_Uize_Color) {
|
35 |
+
/*** Color Profile ***/
|
36 |
+
_Uize_Color.colorSpaces.HSV = {
|
37 |
+
fromHsl:function (_tuple) {
|
38 |
+
// http://en.wikipedia.org/wiki/HSL_color_space
|
39 |
+
var
|
40 |
+
_lightness = _tuple [2] / 100,
|
41 |
+
_maxMinLevelDelta = _tuple [1] / 50 * (_lightness < .5 ? _lightness : 1 - _lightness),
|
42 |
+
_maxLevel = _lightness + _maxMinLevelDelta / 2
|
43 |
+
;
|
44 |
+
return [_tuple [0],_maxLevel ? _maxMinLevelDelta / _maxLevel * 100 : 0,_maxLevel * 100];
|
45 |
+
},
|
46 |
+
toHsl:function (_tuple) {
|
47 |
+
// http://en.wikipedia.org/wiki/HSL_color_space
|
48 |
+
var
|
49 |
+
_maxLevel = _tuple [2] / 100,
|
50 |
+
_minLevel = _maxLevel * (1 - _tuple [1] / 100),
|
51 |
+
_maxMinLevelDelta = _maxLevel - _minLevel,
|
52 |
+
_lightness = (_maxLevel + _minLevel) / 2
|
53 |
+
;
|
54 |
+
return [
|
55 |
+
_tuple [0],
|
56 |
+
_maxMinLevelDelta
|
57 |
+
? 50 * _maxMinLevelDelta / (_lightness < .5 ? _lightness : (1 - _lightness))
|
58 |
+
: 0,
|
59 |
+
_lightness * 100
|
60 |
+
];
|
61 |
+
}
|
62 |
+
};
|
63 |
+
|
64 |
+
/*** Color Encodings ***/
|
65 |
+
Uize.copyInto (
|
66 |
+
_Uize_Color.encodings,
|
67 |
+
{
|
68 |
+
'HSV array':{
|
69 |
+
colorSpace:'HSV',
|
70 |
+
from:_Uize_Color.setTupleFromArray,
|
71 |
+
to:_Uize_Color.cloneTuple
|
72 |
+
/*?
|
73 |
+
Color Encodings
|
74 |
+
HSV array
|
75 |
+
An array, containing three elements for hue, saturation, and value components of the color, whose values may be floating point numbers (eg. the color chartreuse is encoded as =[90,100,100]=).
|
76 |
+
|
77 |
+
SYNTAX
|
78 |
+
...........................................................
|
79 |
+
[ hue0to360FLOAT, saturation0to100FLOAT, value0to100FLOAT ]
|
80 |
+
...........................................................
|
81 |
+
|
82 |
+
Encoding
|
83 |
+
When a color is encoded as =HSV array=, the resulting array is made up of three number type elements that represent the values of the source color's hue, saturation, and value components, respectively.
|
84 |
+
|
85 |
+
...............................
|
86 |
+
<< table >>
|
87 |
+
|
88 |
+
title: EXAMPLES
|
89 |
+
data
|
90 |
+
:| COLOR NAME | HSV array |
|
91 |
+
:| fuchsia | [300,100,100] |
|
92 |
+
:| yellow | [60,100,100] |
|
93 |
+
:| blue | [240,100,100] |
|
94 |
+
:| white | [0,0,100] |
|
95 |
+
...............................
|
96 |
+
|
97 |
+
Decoding
|
98 |
+
When a color is decoded from =HSV array=, the values of the array's three elements may be numbers, strings, or any object that implements a =valueOf= interface (such as an instance of a =Uize.Class= subclass that implements the =value= state property).
|
99 |
+
|
100 |
+
The values will be coerced to number type by invoking the =valueOf Intrinsic Method=.
|
101 |
+
|
102 |
+
EXAMPLES
|
103 |
+
........................................
|
104 |
+
[300,100,100] // fuchsia
|
105 |
+
['300','100','100'] // fuchsia
|
106 |
+
[hueSlider,saturationSlider,valueSlider]
|
107 |
+
........................................
|
108 |
+
|
109 |
+
NOTES
|
110 |
+
- string values for the saturation and value components in the array *may not* contain a "%" (percent) suffix
|
111 |
+
*/
|
112 |
+
},
|
113 |
+
'HSV object':{
|
114 |
+
colorSpace:'HSV',
|
115 |
+
from:function (_hsvObject,_tuple) {
|
116 |
+
_Uize_Color.setTuple (_tuple,_hsvObject.hue,_hsvObject.saturation,_hsvObject.value);
|
117 |
+
},
|
118 |
+
to:function (_tuple) {return {hue:_tuple [0],saturation:_tuple [1],value:_tuple [2]}}
|
119 |
+
/*?
|
120 |
+
Color Encodings
|
121 |
+
HSV object
|
122 |
+
An object, containing =hue=, =saturation=, and =value= properties, whose values may be floating point numbers (eg. the color chartreuse is encoded as ={hue:90,saturation:100,value:100}=).
|
123 |
+
|
124 |
+
SYNTAX
|
125 |
+
................................................................................
|
126 |
+
{ hue:hue0to360FLOAT, saturation:saturation0to100FLOAT, value:value0to100FLOAT }
|
127 |
+
................................................................................
|
128 |
+
|
129 |
+
Encoding
|
130 |
+
When a color is encoded as =HSV object=, the resulting object will contain the three number type properties =hue=, =saturation=, and =value=, reflecting the values of the source color's hue, saturation, and value.
|
131 |
+
|
132 |
+
....................................................
|
133 |
+
<< table >>
|
134 |
+
|
135 |
+
title: EXAMPLES
|
136 |
+
data
|
137 |
+
:| COLOR NAME | HSV object |
|
138 |
+
:| fuchsia | {hue:300,saturation:100,value:100} |
|
139 |
+
:| yellow | {hue:60,saturation:100,value:100} |
|
140 |
+
:| blue | {hue:240,saturation:100,value:100} |
|
141 |
+
:| white | {hue:0,saturation:0,value:100} |
|
142 |
+
....................................................
|
143 |
+
|
144 |
+
Decoding
|
145 |
+
When a color is decoded from =HSV object=, the values of the object's =hue=, =saturation=, and =value= properties may be numbers, strings, or any object that implements a =valueOf= interface (such as an instance of a =Uize.Class= subclass that implements the =value= state property).
|
146 |
+
|
147 |
+
The values will be coerced to number type by invoking the =valueOf Intrinsic Method=.
|
148 |
+
|
149 |
+
EXAMPLES
|
150 |
+
.............................................................
|
151 |
+
{hue:300,saturation:100,value:100} // fuchsia
|
152 |
+
{hue:'300',saturation:'100',value:'100'} // fuchsia
|
153 |
+
{hue:hueSlider,saturation:saturationSlider,value:valueSlider}
|
154 |
+
.............................................................
|
155 |
+
|
156 |
+
NOTES
|
157 |
+
- string values for the =saturation= and =value= properties of the object *may not* contain a "%" (percent) suffix
|
158 |
+
*/
|
159 |
+
},
|
160 |
+
'HSV string':{
|
161 |
+
colorSpace:'HSV',
|
162 |
+
from:_Uize_Color.setTupleFromString,
|
163 |
+
to:function (_tuple) {
|
164 |
+
function _roundAndConstrainComponent (_componentNo,_minValue,_maxValue) {
|
165 |
+
return Uize.constrain (Math.round (_tuple [_componentNo]),_minValue,_maxValue);
|
166 |
+
}
|
167 |
+
return (
|
168 |
+
'hsv(' +
|
169 |
+
_roundAndConstrainComponent (0,0,360) + ',' +
|
170 |
+
_roundAndConstrainComponent (1,0,100) + '%,' +
|
171 |
+
_roundAndConstrainComponent (2,0,100) + '%' +
|
172 |
+
')'
|
173 |
+
);
|
174 |
+
}
|
175 |
+
/*?
|
176 |
+
Color Encodings
|
177 |
+
HSV string
|
178 |
+
An =Hsv(...)= formatted 3-tuple string (eg. the color chartreuse is encoded as ='hsv(90,100%,100%)'=).
|
179 |
+
|
180 |
+
SYNTAX
|
181 |
+
...................................................
|
182 |
+
hsv([hue0to360],[saturation0to100]%,[value0to100]%)
|
183 |
+
...................................................
|
184 |
+
|
185 |
+
Encoding
|
186 |
+
When a color is encoded as =HSV string=, the resulting string will always be all lowercase, without any spaces.
|
187 |
+
|
188 |
+
Furthermore, the values for hue, saturation, and value will be rounded to the nearest integer, the value for hue will be constrained to the range of =0= to =360=, and the values for saturation and value will be constrained to a range of =0= to =100= and a "%" (percent symbol) character will be appended to each.
|
189 |
+
|
190 |
+
.....................................
|
191 |
+
<< table >>
|
192 |
+
|
193 |
+
title: EXAMPLES
|
194 |
+
data
|
195 |
+
:| COLOR NAME | HSV string |
|
196 |
+
:| fuchsia | hsv(300,100%,100%) |
|
197 |
+
:| yellow | hsv(60,100%,100%) |
|
198 |
+
:| blue | hsv(240,100%,100%) |
|
199 |
+
:| white | hsv(0,0%,100%) |
|
200 |
+
.....................................
|
201 |
+
|
202 |
+
NOTES
|
203 |
+
- because encoding as =HSV string= rounds the values for hue, saturation, and value, colors encoded as =HSV string= may not produce exactly the same original color when decoding the encoded =HSV string=
|
204 |
+
|
205 |
+
Decoding
|
206 |
+
When a color is decoded from =HSV string=, the string may contain separating spaces, may be in upper, lower, or mixed case (ie. *not* case sensitive), and the "%" (percent symbol) character for the saturation and value values may be omitted.
|
207 |
+
|
208 |
+
FUCHSIA
|
209 |
+
.........................
|
210 |
+
hsv(300,100,100)
|
211 |
+
hsv(300,100%,100%)
|
212 |
+
HSV(300,100%,100%)
|
213 |
+
Hsv (300, 100%, 100%)
|
214 |
+
HSV ( 300 , 100% , 100% )
|
215 |
+
Hsv ( 300 , 100 , 100 )
|
216 |
+
.........................
|
217 |
+
*/
|
218 |
+
}
|
219 |
+
}
|
220 |
+
);
|
221 |
+
}
|
222 |
+
});
|
223 |
+
|
skin/frontend/default/customproduct/js/Uize.Color.xSvgColors.js
ADDED
@@ -0,0 +1,324 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Color.xSvgColors Object Extension
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2009-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Extension
|
14 |
+
importance: 2
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Color.xSvgColors= extension module extends the =Uize.Color= object by adding SVG 1.0 / CSS 3 color definitions to the =Uize.Color.colors= object.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
Using the Colors
|
27 |
+
When you extend the =Uize.Color= object using the =Uize.Color.xSvgColors= extension module, it will then be possible to use the names of the colors defined in this extension when creating instances of the =Uize.Color= object, or when setting the color of =Uize.Color= instances using the =from= instance method.
|
28 |
+
|
29 |
+
EXAMPLE
|
30 |
+
..............................................
|
31 |
+
Uize.Color ('#ffebcd');
|
32 |
+
Uize.Color ('BlanchedAlmond');
|
33 |
+
Uize.Color (Uize.Color.colors.blanchedalmond);
|
34 |
+
..............................................
|
35 |
+
|
36 |
+
Each of the above three statements would create a new instance of the =Uize.Color= object initialized to the SVG color "BlanchedAlmond". And because the =Uize.Color= module is used by other modules, such as the =Uize.Fx= module, it is possible to use color names when specifying the values of color CSS style properties for fade effects, as in...
|
37 |
+
|
38 |
+
.............................................................................
|
39 |
+
Uize.Fx.fadeStyle ('myNodeId',{color:'DarkMagenta'},{color:'LavenderBlush'});
|
40 |
+
.............................................................................
|
41 |
+
*/
|
42 |
+
|
43 |
+
Uize.module ({
|
44 |
+
name:'Uize.Color.xSvgColors',
|
45 |
+
builder:function (_Uize_Color) {
|
46 |
+
_Uize_Color.defineColors ({
|
47 |
+
aliceblue: 15792383, // 0xf0f8ff
|
48 |
+
antiquewhite: 16444375, // 0xfaebd7
|
49 |
+
aquamarine: 8388564, // 0x7fffd4
|
50 |
+
azure: 15794175, // 0xf0ffff
|
51 |
+
beige: 16119260, // 0xf5f5dc
|
52 |
+
bisque: 16770244, // 0xffe4c4
|
53 |
+
blanchedalmond: 16772045, // 0xffebcd
|
54 |
+
blueviolet: 9055202, // 0x8a2be2
|
55 |
+
brown: 10824234, // 0xa52a2a
|
56 |
+
burlywood: 14596231, // 0xdeb887
|
57 |
+
cadetblue: 6266528, // 0x5f9ea0
|
58 |
+
chartreuse: 8388352, // 0x7fff00
|
59 |
+
chocolate: 13789470, // 0xd2691e
|
60 |
+
coral: 16744272, // 0xff7f50
|
61 |
+
cornflowerblue: 6591981, // 0x6495ed
|
62 |
+
cornsilk: 16775388, // 0xfff8dc
|
63 |
+
crimson: 14423100, // 0xdc143c
|
64 |
+
cyan: 65535, // 0x00ffff
|
65 |
+
darkblue: 139, // 0x00008b
|
66 |
+
darkcyan: 35723, // 0x008b8b
|
67 |
+
darkgoldenrod: 12092939, // 0xb8860b
|
68 |
+
darkgray: 11119017, // 0xa9a9a9
|
69 |
+
darkgreen: 25600, // 0x006400
|
70 |
+
darkgrey: 11119017, // 0xa9a9a9
|
71 |
+
darkkhaki: 12433259, // 0xbdb76b
|
72 |
+
darkmagenta: 9109643, // 0x8b008b
|
73 |
+
darkolivegreen: 5597999, // 0x556b2f
|
74 |
+
darkorange: 16747520, // 0xff8c00
|
75 |
+
darkorchid: 10040012, // 0x9932cc
|
76 |
+
darkred: 9109504, // 0x8b0000
|
77 |
+
darksalmon: 15308410, // 0xe9967a
|
78 |
+
darkseagreen: 9419919, // 0x8fbc8f
|
79 |
+
darkslateblue: 4734347, // 0x483d8b
|
80 |
+
darkslategray: 3100495, // 0x2f4f4f
|
81 |
+
darkslategrey: 3100495, // 0x2f4f4f
|
82 |
+
darkturquoise: 52945, // 0x00ced1
|
83 |
+
darkviolet: 9699539, // 0x9400d3
|
84 |
+
deeppink: 16716947, // 0xff1493
|
85 |
+
deepskyblue: 49151, // 0x00bfff
|
86 |
+
dimgray: 6908265, // 0x696969
|
87 |
+
dimgrey: 6908265, // 0x696969
|
88 |
+
dodgerblue: 2003199, // 0x1e90ff
|
89 |
+
firebrick: 11674146, // 0xb22222
|
90 |
+
floralwhite: 16775920, // 0xfffaf0
|
91 |
+
forestgreen: 2263842, // 0x228b22
|
92 |
+
gainsboro: 14474460, // 0xdcdcdc
|
93 |
+
ghostwhite: 16316671, // 0xf8f8ff
|
94 |
+
gold: 16766720, // 0xffd700
|
95 |
+
goldenrod: 14329120, // 0xdaa520
|
96 |
+
greenyellow: 11403055, // 0xadff2f
|
97 |
+
grey: 8421504, // 0x808080
|
98 |
+
honeydew: 15794160, // 0xf0fff0
|
99 |
+
hotpink: 16738740, // 0xff69b4
|
100 |
+
indianred: 13458524, // 0xcd5c5c
|
101 |
+
indigo: 4915330, // 0x4b0082
|
102 |
+
ivory: 16777200, // 0xfffff0
|
103 |
+
khaki: 15787660, // 0xf0e68c
|
104 |
+
lavender: 15132410, // 0xe6e6fa
|
105 |
+
lavenderblush: 16773365, // 0xfff0f5
|
106 |
+
lawngreen: 8190976, // 0x7cfc00
|
107 |
+
lemonchiffon: 16775885, // 0xfffacd
|
108 |
+
lightblue: 11393254, // 0xadd8e6
|
109 |
+
lightcoral: 15761536, // 0xf08080
|
110 |
+
lightcyan: 14745599, // 0xe0ffff
|
111 |
+
lightgoldenrodyellow: 16448210, // 0xfafad2
|
112 |
+
lightgray: 13882323, // 0xd3d3d3
|
113 |
+
lightgreen: 9498256, // 0x90ee90
|
114 |
+
lightgrey: 13882323, // 0xd3d3d3
|
115 |
+
lightpink: 16758465, // 0xffb6c1
|
116 |
+
lightsalmon: 16752762, // 0xffa07a
|
117 |
+
lightseagreen: 2142890, // 0x20b2aa
|
118 |
+
lightskyblue: 8900346, // 0x87cefa
|
119 |
+
lightslategray: 7833753, // 0x778899
|
120 |
+
lightslategrey: 7833753, // 0x778899
|
121 |
+
lightsteelblue: 11584734, // 0xb0c4de
|
122 |
+
lightyellow: 16777184, // 0xffffe0
|
123 |
+
limegreen: 3329330, // 0x32cd32
|
124 |
+
linen: 16445670, // 0xfaf0e6
|
125 |
+
magenta: 16711935, // 0xff00ff
|
126 |
+
mediumaquamarine: 6737322, // 0x66cdaa
|
127 |
+
mediumblue: 205, // 0x0000cd
|
128 |
+
mediumorchid: 12211667, // 0xba55d3
|
129 |
+
mediumpurple: 9662683, // 0x9370db
|
130 |
+
mediumseagreen: 3978097, // 0x3cb371
|
131 |
+
mediumslateblue: 8087790, // 0x7b68ee
|
132 |
+
mediumspringgreen: 64154, // 0x00fa9a
|
133 |
+
mediumturquoise: 4772300, // 0x48d1cc
|
134 |
+
mediumvioletred: 13047173, // 0xc71585
|
135 |
+
midnightblue: 1644912, // 0x191970
|
136 |
+
mintcream: 16121850, // 0xf5fffa
|
137 |
+
mistyrose: 16770273, // 0xffe4e1
|
138 |
+
moccasin: 16770229, // 0xffe4b5
|
139 |
+
navajowhite: 16768685, // 0xffdead
|
140 |
+
oldlace: 16643558, // 0xfdf5e6
|
141 |
+
olivedrab: 7048739, // 0x6b8e23
|
142 |
+
orangered: 16729344, // 0xff4500
|
143 |
+
orchid: 14315734, // 0xda70d6
|
144 |
+
palegoldenrod: 15657130, // 0xeee8aa
|
145 |
+
palegreen: 10025880, // 0x98fb98
|
146 |
+
paleturquoise: 11529966, // 0xafeeee
|
147 |
+
palevioletred: 14381203, // 0xdb7093
|
148 |
+
papayawhip: 16773077, // 0xffefd5
|
149 |
+
peachpuff: 16767673, // 0xffdab9
|
150 |
+
peru: 13468991, // 0xcd853f
|
151 |
+
pink: 16761035, // 0xffc0cb
|
152 |
+
plum: 14524637, // 0xdda0dd
|
153 |
+
powderblue: 11591910, // 0xb0e0e6
|
154 |
+
rosybrown: 12357519, // 0xbc8f8f
|
155 |
+
royalblue: 4286945, // 0x4169e1
|
156 |
+
saddlebrown: 9127187, // 0x8b4513
|
157 |
+
salmon: 16416882, // 0xfa8072
|
158 |
+
sandybrown: 16032864, // 0xf4a460
|
159 |
+
seagreen: 3050327, // 0x2e8b57
|
160 |
+
seashell: 16774638, // 0xfff5ee
|
161 |
+
sienna: 10506797, // 0xa0522d
|
162 |
+
skyblue: 8900331, // 0x87ceeb
|
163 |
+
slateblue: 6970061, // 0x6a5acd
|
164 |
+
slategray: 7372944, // 0x708090
|
165 |
+
slategrey: 7372944, // 0x708090
|
166 |
+
snow: 16775930, // 0xfffafa
|
167 |
+
springgreen: 65407, // 0x00ff7f
|
168 |
+
steelblue: 4620980, // 0x4682b4
|
169 |
+
tan: 13808780, // 0xd2b48c
|
170 |
+
thistle: 14204888, // 0xd8bfd8
|
171 |
+
tomato: 16737095, // 0xff6347
|
172 |
+
turquoise: 4251856, // 0x40e0d0
|
173 |
+
violet: 15631086, // 0xee82ee
|
174 |
+
wheat: 16113331, // 0xf5deb3
|
175 |
+
whitesmoke: 16119285, // 0xf5f5f5
|
176 |
+
yellowgreen: 10145074 // 0x9acd32
|
177 |
+
});
|
178 |
+
/*?
|
179 |
+
The SVG 1.0 Colors
|
180 |
+
The =Uize.Color.xSvgColors= module defines over a hundred additional colors, as listed in the table below.
|
181 |
+
|
182 |
+
This is in addition to the seventeen standard CSS 2.1 colors defined in the =Uize.Color= module, which are =white=, =silver=, =gray=, =black=, =navy=, =blue=, =aqua=, =teal=, =green=, =olive=, =lime=, =maroon=, =red=, =orange=, =yellow=, =purple=, and =fuchsia=.
|
183 |
+
|
184 |
+
.........................................
|
185 |
+
<< table >>
|
186 |
+
|
187 |
+
title: SVG 1.0 COLORS
|
188 |
+
data
|
189 |
+
:| COLOR NAME | HEX VALUE |
|
190 |
+
:| aliceblue | #f0f8ff |
|
191 |
+
:| antiquewhite | #faebd7 |
|
192 |
+
:| aquamarine | #7fffd4 |
|
193 |
+
:| azure | #f0ffff |
|
194 |
+
:| beige | #f5f5dc |
|
195 |
+
:| bisque | #ffe4c4 |
|
196 |
+
:| blanchedalmond | #ffebcd |
|
197 |
+
:| blueviolet | #8a2be2 |
|
198 |
+
:| brown | #a52a2a |
|
199 |
+
:| burlywood | #deb887 |
|
200 |
+
:| cadetblue | #5f9ea0 |
|
201 |
+
:| chartreuse | #7fff00 |
|
202 |
+
:| chocolate | #d2691e |
|
203 |
+
:| coral | #ff7f50 |
|
204 |
+
:| cornflowerblue | #6495ed |
|
205 |
+
:| cornsilk | #fff8dc |
|
206 |
+
:| crimson | #dc143c |
|
207 |
+
:| cyan | #00ffff |
|
208 |
+
:| darkblue | #00008b |
|
209 |
+
:| darkcyan | #008b8b |
|
210 |
+
:| darkgoldenrod | #b8860b |
|
211 |
+
:| darkgray | #a9a9a9 |
|
212 |
+
:| darkgreen | #006400 |
|
213 |
+
:| darkgrey | #a9a9a9 |
|
214 |
+
:| darkkhaki | #bdb76b |
|
215 |
+
:| darkmagenta | #8b008b |
|
216 |
+
:| darkolivegreen | #556b2f |
|
217 |
+
:| darkorange | #ff8c00 |
|
218 |
+
:| darkorchid | #9932cc |
|
219 |
+
:| darkred | #8b0000 |
|
220 |
+
:| darksalmon | #e9967a |
|
221 |
+
:| darkseagreen | #8fbc8f |
|
222 |
+
:| darkslateblue | #483d8b |
|
223 |
+
:| darkslategray | #2f4f4f |
|
224 |
+
:| darkslategrey | #2f4f4f |
|
225 |
+
:| darkturquoise | #00ced1 |
|
226 |
+
:| darkviolet | #9400d3 |
|
227 |
+
:| deeppink | #ff1493 |
|
228 |
+
:| deepskyblue | #00bfff |
|
229 |
+
:| dimgray | #696969 |
|
230 |
+
:| dimgrey | #696969 |
|
231 |
+
:| dodgerblue | #1e90ff |
|
232 |
+
:| firebrick | #b22222 |
|
233 |
+
:| floralwhite | #fffaf0 |
|
234 |
+
:| forestgreen | #228b22 |
|
235 |
+
:| gainsboro | #dcdcdc |
|
236 |
+
:| ghostwhite | #f8f8ff |
|
237 |
+
:| gold | #ffd700 |
|
238 |
+
:| goldenrod | #daa520 |
|
239 |
+
:| greenyellow | #adff2f |
|
240 |
+
:| grey | #808080 |
|
241 |
+
:| honeydew | #f0fff0 |
|
242 |
+
:| hotpink | #ff69b4 |
|
243 |
+
:| indianred | #cd5c5c |
|
244 |
+
:| indigo | #4b0082 |
|
245 |
+
:| ivory | #fffff0 |
|
246 |
+
:| khaki | #f0e68c |
|
247 |
+
:| lavender | #e6e6fa |
|
248 |
+
:| lavenderblush | #fff0f5 |
|
249 |
+
:| lawngreen | #7cfc00 |
|
250 |
+
:| lemonchiffon | #fffacd |
|
251 |
+
:| lightblue | #add8e6 |
|
252 |
+
:| lightcoral | #f08080 |
|
253 |
+
:| lightcyan | #e0ffff |
|
254 |
+
:| lightgoldenrodyellow | #fafad2 |
|
255 |
+
:| lightgray | #d3d3d3 |
|
256 |
+
:| lightgreen | #90ee90 |
|
257 |
+
:| lightgrey | #d3d3d3 |
|
258 |
+
:| lightpink | #ffb6c1 |
|
259 |
+
:| lightsalmon | #ffa07a |
|
260 |
+
:| lightseagreen | #20b2aa |
|
261 |
+
:| lightskyblue | #87cefa |
|
262 |
+
:| lightslategray | #778899 |
|
263 |
+
:| lightslategrey | #778899 |
|
264 |
+
:| lightsteelblue | #b0c4de |
|
265 |
+
:| lightyellow | #ffffe0 |
|
266 |
+
:| limegreen | #32cd32 |
|
267 |
+
:| linen | #faf0e6 |
|
268 |
+
:| magenta | #ff00ff |
|
269 |
+
:| mediumaquamarine | #66cdaa |
|
270 |
+
:| mediumblue | #0000cd |
|
271 |
+
:| mediumorchid | #ba55d3 |
|
272 |
+
:| mediumpurple | #9370db |
|
273 |
+
:| mediumseagreen | #3cb371 |
|
274 |
+
:| mediumslateblue | #7b68ee |
|
275 |
+
:| mediumspringgreen | #00fa9a |
|
276 |
+
:| mediumturquoise | #48d1cc |
|
277 |
+
:| mediumvioletred | #c71585 |
|
278 |
+
:| midnightblue | #191970 |
|
279 |
+
:| mintcream | #f5fffa |
|
280 |
+
:| mistyrose | #ffe4e1 |
|
281 |
+
:| moccasin | #ffe4b5 |
|
282 |
+
:| navajowhite | #ffdead |
|
283 |
+
:| oldlace | #fdf5e6 |
|
284 |
+
:| olivedrab | #6b8e23 |
|
285 |
+
:| orangered | #ff4500 |
|
286 |
+
:| orchid | #da70d6 |
|
287 |
+
:| palegoldenrod | #eee8aa |
|
288 |
+
:| palegreen | #98fb98 |
|
289 |
+
:| paleturquoise | #afeeee |
|
290 |
+
:| palevioletred | #db7093 |
|
291 |
+
:| papayawhip | #ffefd5 |
|
292 |
+
:| peachpuff | #ffdab9 |
|
293 |
+
:| peru | #cd853f |
|
294 |
+
:| pink | #ffc0cb |
|
295 |
+
:| plum | #dda0dd |
|
296 |
+
:| powderblue | #b0e0e6 |
|
297 |
+
:| rosybrown | #bc8f8f |
|
298 |
+
:| royalblue | #4169e1 |
|
299 |
+
:| saddlebrown | #8b4513 |
|
300 |
+
:| salmon | #fa8072 |
|
301 |
+
:| sandybrown | #f4a460 |
|
302 |
+
:| seagreen | #2e8b57 |
|
303 |
+
:| seashell | #fff5ee |
|
304 |
+
:| sienna | #a0522d |
|
305 |
+
:| skyblue | #87ceeb |
|
306 |
+
:| slateblue | #6a5acd |
|
307 |
+
:| slategray | #708090 |
|
308 |
+
:| slategrey | #708090 |
|
309 |
+
:| snow | #fffafa |
|
310 |
+
:| springgreen | #00ff7f |
|
311 |
+
:| steelblue | #4682b4 |
|
312 |
+
:| tan | #d2b48c |
|
313 |
+
:| thistle | #d8bfd8 |
|
314 |
+
:| tomato | #ff6347 |
|
315 |
+
:| turquoise | #40e0d0 |
|
316 |
+
:| violet | #ee82ee |
|
317 |
+
:| wheat | #f5deb3 |
|
318 |
+
:| whitesmoke | #f5f5f5 |
|
319 |
+
:| yellowgreen | #9acd32 |
|
320 |
+
.........................................
|
321 |
+
*/
|
322 |
+
}
|
323 |
+
});
|
324 |
+
|
skin/frontend/default/customproduct/js/Uize.Color.xUtil.js
ADDED
@@ -0,0 +1,720 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Color.xUtil Object Extension
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)1997-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Extension
|
14 |
+
importance: 2
|
15 |
+
codeCompleteness: 90
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Color.xUtil= module is an extension module that extends the =Uize.Color= object by adding various instance and static utility methods.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
*/
|
26 |
+
|
27 |
+
Uize.module ({
|
28 |
+
name:'Uize.Color.xUtil',
|
29 |
+
required:'Uize.Array.Sort',
|
30 |
+
builder:function (_object) {
|
31 |
+
/*** Variables for Scruncher Optimization ***/
|
32 |
+
var
|
33 |
+
_undefined,
|
34 |
+
_objectPrototype = _object.prototype
|
35 |
+
;
|
36 |
+
|
37 |
+
/*** General Variables ***/
|
38 |
+
var
|
39 |
+
_dummyColor1 = new _object,
|
40 |
+
_dummyColor2 = new _object,
|
41 |
+
_sacredEmptyObject = {}
|
42 |
+
;
|
43 |
+
|
44 |
+
/*** Utility Functions ***/
|
45 |
+
function _blendValues (_valueA,_valueB,_blendAmount) {
|
46 |
+
return _valueA + (_valueB - _valueA) * _blendAmount
|
47 |
+
}
|
48 |
+
|
49 |
+
function _ensureSettingIsTuple (_setting,_default) {
|
50 |
+
if (_setting == _undefined) _setting = _default;
|
51 |
+
return Uize.isArray (_setting) ? _setting : [_setting,_setting,_setting,_setting];
|
52 |
+
}
|
53 |
+
|
54 |
+
/*** Public Instance Methods ***/
|
55 |
+
_objectPrototype.blend = function (_color1,_color2,_blendAmount) {
|
56 |
+
_blendAmount = Uize.toNumber (_blendAmount,.5);
|
57 |
+
_dummyColor1.from (_color1);
|
58 |
+
_dummyColor2.from (_color2);
|
59 |
+
var
|
60 |
+
_dummyColor1Tuple = _dummyColor1.tuple,
|
61 |
+
_dummyColor2Tuple = _dummyColor2.getTuple (_dummyColor1.encoding)
|
62 |
+
;
|
63 |
+
_object.setTuple (
|
64 |
+
this.tuple,
|
65 |
+
_blendValues (_dummyColor1Tuple [0],_dummyColor2Tuple [0],_blendAmount),
|
66 |
+
_blendValues (_dummyColor1Tuple [1],_dummyColor2Tuple [1],_blendAmount),
|
67 |
+
_blendValues (_dummyColor1Tuple [2],_dummyColor2Tuple [2],_blendAmount),
|
68 |
+
_blendValues (_dummyColor1Tuple [3],_dummyColor2Tuple [3],_blendAmount)
|
69 |
+
);
|
70 |
+
|
71 |
+
return this;
|
72 |
+
/*?
|
73 |
+
Instance Methods
|
74 |
+
blend
|
75 |
+
Blends between the two specified colors using the specified blend amount, and sets the current color of the instance to the new blended color.
|
76 |
+
|
77 |
+
SYNTAX
|
78 |
+
...........................................................
|
79 |
+
colorOBJ.blend (color1ANYTYPE,color2ANYTYPE,blendFRACTION);
|
80 |
+
...........................................................
|
81 |
+
|
82 |
+
The =blendFRACTION= parameter should be a floating point number in the range of =0= to =1=, where a value of =0= will result in =colorOBJ= being set to the color represented by the =color1ANYTYPE= parameter, the value =1= will result in =colorOBJ= being set to the color represented by the =color2ANYTYPE= parameter, and the value =.5= will result in =colorOBJ= being set to a color that is an equal blend of the colors represented by the =color1ANYTYPE= and =color2ANYTYPE= parameters.
|
83 |
+
|
84 |
+
Different values between =0= and =1= for the =blendFRACTION= parameter give you different blends between color one and color two...
|
85 |
+
|
86 |
+
EXAMPLES
|
87 |
+
..............................................................................
|
88 |
+
// a range of blends between black and white
|
89 |
+
|
90 |
+
myColor.blend ('000000','ffffff',0); // myColor now #000000, encoding "hex"
|
91 |
+
myColor.blend ('000000','ffffff',.25); // myColor now #404040, encoding "hex"
|
92 |
+
myColor.blend ('000000','ffffff',.5); // myColor now #808080, encoding "hex"
|
93 |
+
myColor.blend ('000000','ffffff',.75); // myColor now #bfbfbf, encoding "hex"
|
94 |
+
myColor.blend ('000000','ffffff',1); // myColor now #ffffff, encoding "hex"
|
95 |
+
..............................................................................
|
96 |
+
|
97 |
+
VARIATION
|
98 |
+
.............................................
|
99 |
+
colorOBJ.blend (color1ANYTYPE,color2ANYTYPE);
|
100 |
+
.............................................
|
101 |
+
|
102 |
+
When no =blendFRACTION= parameter is specified, the value for this parameter is defaulted to =.5=, producing an equal mix between =color1ANYTYPE= and =color2ANYTYPE=.
|
103 |
+
|
104 |
+
EXAMPLE
|
105 |
+
................................................................................
|
106 |
+
myColor.blend ('black','white'); // myColor now #808080 (gray), encoding "name"
|
107 |
+
................................................................................
|
108 |
+
|
109 |
+
Color one and color two - the source colors for the blending operation - can be specified using any of the many supported `Color Encodings`...
|
110 |
+
|
111 |
+
EXAMPLES
|
112 |
+
....................................................................................
|
113 |
+
// equal blend of black and white, specified using different encodings
|
114 |
+
|
115 |
+
myColor.blend ('000000','ffffff'); // myColor now #808080, encoding "hex"
|
116 |
+
myColor.blend ('black','white'); // myColor now #808080, encoding "name"
|
117 |
+
myColor.blend (0x000000,0xffffff); // myColor now #808080, encoding "RGB int"
|
118 |
+
myColor.blend ([0,0,0],[255,255,255]); // myColor now #808080, encoding "RGB array"
|
119 |
+
myColor.blend ('#000','#fff'); // myColor now #808080, encoding "#hex"
|
120 |
+
myColor.blend ('#0','#f'); // myColor now #808080, encoding "#hex"
|
121 |
+
....................................................................................
|
122 |
+
|
123 |
+
The `Color Encodings` for color one and color two do not have to be the same...
|
124 |
+
|
125 |
+
EXAMPLES
|
126 |
+
..................................................................................
|
127 |
+
// equal blend of black and white, using mixed encodings for source colors
|
128 |
+
|
129 |
+
myColor.blend ('#000000',0xffffff); // myColor now #808080, encoding "#hex"
|
130 |
+
myColor.blend ('black','#fff'); // myColor now #808080, encoding "name"
|
131 |
+
myColor.blend ([0,0,0],'ffffff'); // myColor now #808080, encoding "RGB array"
|
132 |
+
..................................................................................
|
133 |
+
|
134 |
+
To blend the instance's current color value with a different color, simply pass a reference to the color object instance as one of the colors to blend, as in...
|
135 |
+
|
136 |
+
EXAMPLE
|
137 |
+
................................................................................
|
138 |
+
myColor.blend (myColor,'white',.1); // blend in some white to lighten the color
|
139 |
+
................................................................................
|
140 |
+
|
141 |
+
NOTES
|
142 |
+
- see the related =Uize.Color.blend= static method
|
143 |
+
*/
|
144 |
+
};
|
145 |
+
|
146 |
+
_objectPrototype.equal = function (_color) {
|
147 |
+
_dummyColor1.from (_color).setEncoding (this.encoding);
|
148 |
+
var
|
149 |
+
_tuple = this.tuple,
|
150 |
+
_dummyColor1Tuple = _dummyColor1.tuple
|
151 |
+
;
|
152 |
+
return (
|
153 |
+
!Math.round (_tuple [0] - _dummyColor1Tuple [0]) &&
|
154 |
+
!Math.round (_tuple [1] - _dummyColor1Tuple [1]) &&
|
155 |
+
!Math.round (_tuple [2] - _dummyColor1Tuple [2]) &&
|
156 |
+
!Math.round (_tuple [3] - _dummyColor1Tuple [3])
|
157 |
+
);
|
158 |
+
/*?
|
159 |
+
Instance Methods
|
160 |
+
equal
|
161 |
+
Returns a boolean, indicating whether or not the specified color is equivalent to the color of the instance.
|
162 |
+
|
163 |
+
SYNTAX
|
164 |
+
...........................................
|
165 |
+
isEqualBOOL = myColor.equal (colorANYTYPE);
|
166 |
+
...........................................
|
167 |
+
|
168 |
+
EXAMPLES
|
169 |
+
........................................................................
|
170 |
+
var fuchsia = Uize.Color ('fuchsia');
|
171 |
+
fuchsia.equal (Uize.Color ('fuchsia')); // produces true
|
172 |
+
fuchsia.equal ('ff00ff'); // produces true
|
173 |
+
fuchsia.equal ('#ff00ff'); // produces true
|
174 |
+
fuchsia.equal ('fuchsia'); // produces true
|
175 |
+
fuchsia.equal ([255,0,255]); // produces true
|
176 |
+
fuchsia.equal (16711935); // produces true
|
177 |
+
fuchsia.equal ({red:255,green:0,blue:255}); // produces true
|
178 |
+
fuchsia.equal ('rgb(255,0,255)'); // produces true
|
179 |
+
fuchsia.equal ({'HSL array':[300,100,50]}); // produces true
|
180 |
+
fuchsia.equal ({hue:300,saturation:100,lightness:50}); // produces true
|
181 |
+
fuchsia.equal ('hsl(300,100,50)'); // produces true
|
182 |
+
........................................................................
|
183 |
+
|
184 |
+
In the above example, all the statements produce the result =true=. That's because all the colors that the =fuchsia= color object is being compared to are equivalent to the color "fuchsia" - regardless of the encoding used to specify them.
|
185 |
+
|
186 |
+
MORE EXAMPLES
|
187 |
+
..................................................................................
|
188 |
+
Uize.Color.blend ('red','black',.5,'color').equal ('maroon'); // produces true
|
189 |
+
Uize.Color.mix (['black','red']).equal ('maroon'); // produces true
|
190 |
+
Uize.Color.mix (['rgb(0,0,0)','#f00']).equal ('hsl(0,100%,25%)'); // produces true
|
191 |
+
..................................................................................
|
192 |
+
|
193 |
+
NOTES
|
194 |
+
- see the companion =Uize.Color.equal= static method
|
195 |
+
*/
|
196 |
+
};
|
197 |
+
|
198 |
+
_objectPrototype.random = function () {
|
199 |
+
for (
|
200 |
+
var
|
201 |
+
_components = _object.colorSpaces [_object.encodings [this.encoding].colorSpace].tuple,
|
202 |
+
_componentNo = _components.length,
|
203 |
+
_tuple = this.tuple
|
204 |
+
;
|
205 |
+
--_componentNo >= 0;
|
206 |
+
) {
|
207 |
+
var
|
208 |
+
_component = _components [_componentNo],
|
209 |
+
_componentMin = _component.min
|
210 |
+
;
|
211 |
+
_tuple [_componentNo] = _componentMin + Math.random () * (_component.max - _componentMin);
|
212 |
+
}
|
213 |
+
return this;
|
214 |
+
/*?
|
215 |
+
Instance Methods
|
216 |
+
random
|
217 |
+
Randomizes the color of the instance in the color space of the instance's current encoding.
|
218 |
+
|
219 |
+
SYNTAX
|
220 |
+
..................
|
221 |
+
myColor.random ();
|
222 |
+
..................
|
223 |
+
|
224 |
+
NOTES
|
225 |
+
- see the related =Uize.Color.random= static method
|
226 |
+
*/
|
227 |
+
};
|
228 |
+
|
229 |
+
/*** Public Static Methods ***/
|
230 |
+
_object.blend = function (_color1,_color2,_blendAmount,_encoding) {
|
231 |
+
return _dummyColor1.blend (_color1,_color2,_blendAmount).to (_encoding || _dummyColor1.encoding);
|
232 |
+
/*?
|
233 |
+
Static Methods
|
234 |
+
Uize.Color.blend
|
235 |
+
Blends between the two specified colors using the specified blend amount, and returns the blended color encoded using the specified encoding.
|
236 |
+
|
237 |
+
SYNTAX
|
238 |
+
............................................................................
|
239 |
+
colorANYTYPE = Uize.Color.blend (color1ANYTYPE,color2ANYTYPE,blendFRACTION);
|
240 |
+
............................................................................
|
241 |
+
|
242 |
+
The =blendFRACTION= parameter should be a floating point number in the range of =0= to =1=, where a value of =0= will result in returning the color represented by the =color1ANYTYPE= parameter, the value =1= will result in returning the color represented by the =color2ANYTYPE= parameter, and the value =.5= will result in returning a color that is an equal blend of the colors represented by the =color1ANYTYPE= and =color2ANYTYPE= parameters.
|
243 |
+
|
244 |
+
Different values between =0= and =1= for the =blendFRACTION= parameter give you different blends between color one and color two...
|
245 |
+
|
246 |
+
EXAMPLES
|
247 |
+
....................................................................
|
248 |
+
// a range of blends between black and white
|
249 |
+
|
250 |
+
Uize.Color.blend ('000000','ffffff',0); // returns '000000'
|
251 |
+
Uize.Color.blend ('000000','ffffff',.25); // returns '404040'
|
252 |
+
Uize.Color.blend ('000000','ffffff',.5); // returns '808080'
|
253 |
+
Uize.Color.blend ('000000','ffffff',.75); // returns 'bfbfbf'
|
254 |
+
Uize.Color.blend ('000000','ffffff',1); // returns 'ffffff'
|
255 |
+
....................................................................
|
256 |
+
|
257 |
+
VARIATION 1
|
258 |
+
........................................................................................
|
259 |
+
colorANYTYPE = Uize.Color.blend (color1ANYTYPE,color2ANYTYPE,blendFRACTION,encodingSTR);
|
260 |
+
........................................................................................
|
261 |
+
|
262 |
+
The resulting blended color can be encoded in any of the many supported `Color Encodings`, by using the optional =encodingSTR= parameter, as follows...
|
263 |
+
|
264 |
+
EXAMPLES
|
265 |
+
........................................................................
|
266 |
+
// equal blend of black and white, different encodings for the result
|
267 |
+
|
268 |
+
Uize.Color.blend ('black','white',.5,'color'); // new Uize.Color
|
269 |
+
Uize.Color.blend ('black','white',.5,'hex'); // 808080
|
270 |
+
Uize.Color.blend ('black','white',.5,'#hex'); // #808080
|
271 |
+
Uize.Color.blend ('black','white',.5,'name'); // gray
|
272 |
+
Uize.Color.blend ('black','white',.5,'RGB array'); // [128,128,128]
|
273 |
+
Uize.Color.blend ('black','white',.5,'RGB int'); // 8421504
|
274 |
+
Uize.Color.blend ('black','white',.5,'RGB string'); // rgb(128,128,128}
|
275 |
+
........................................................................
|
276 |
+
|
277 |
+
VARIATION 2
|
278 |
+
.............................................................
|
279 |
+
colorHexSTR = Uize.Color.blend (color1ANYTYPE,color2ANYTYPE);
|
280 |
+
.............................................................
|
281 |
+
|
282 |
+
When no =blendFRACTION= or =encodingSTR= parameters are specified, then the colors specified by the =color1ANYTYPE= and =color2ANYTYPE= parameters will be blended equally and the resulting color will be encoded using the encoding of the first color, as specified by the =color1ANYTYPE= parameter.
|
283 |
+
|
284 |
+
EXAMPLE
|
285 |
+
.................................................................................
|
286 |
+
var myColorHex = Uize.Color.blend ('fuchsia','olive'); // myColorHex is 'c04080'
|
287 |
+
.................................................................................
|
288 |
+
|
289 |
+
Color one and color two - the source colors for the blending operation - can be specified using any of the many supported `Color Encodings`...
|
290 |
+
|
291 |
+
EXAMPLES
|
292 |
+
...................................................................................
|
293 |
+
// equal blend of black and white, specified using different encodings
|
294 |
+
|
295 |
+
Uize.Color.blend ('000000','ffffff'); // returns '808080'
|
296 |
+
Uize.Color.blend ('black','white'); // returns 'gray'
|
297 |
+
Uize.Color.blend (0x000000,0xffffff); // returns 8421504
|
298 |
+
Uize.Color.blend ([0,0,0],[255,255,255]); // returns [127.5,127.5,127.5]
|
299 |
+
Uize.Color.blend ('#000','#fff'); // returns '#808080'
|
300 |
+
Uize.Color.blend ('#0','#f'); // returns '#808080'
|
301 |
+
Uize.Color.blend ('hsl(0,0%,0%)','hsl(0,0%,100%)'); // returns 'hsl(0,0%,50%)'
|
302 |
+
...................................................................................
|
303 |
+
|
304 |
+
The `Color Encodings` for color one and color two do not have to be the same...
|
305 |
+
|
306 |
+
EXAMPLES
|
307 |
+
..........................................................................
|
308 |
+
// equal blend of black and white, using mixed encodings for source colors
|
309 |
+
|
310 |
+
Uize.Color.blend ('#000000',0xffffff); // returns '#808080'
|
311 |
+
Uize.Color.blend ('black','#fff'); // returns 'gray'
|
312 |
+
Uize.Color.blend ([0,0,0],'ffffff'); // returns [127.5,127.5,127.5]
|
313 |
+
..........................................................................
|
314 |
+
|
315 |
+
In the above example, notice how the encoding of the first color is used for encoding the result.
|
316 |
+
|
317 |
+
NOTES
|
318 |
+
- see the related =blend= instance method
|
319 |
+
*/
|
320 |
+
};
|
321 |
+
|
322 |
+
_object.equal = function (_color1,_color2) {
|
323 |
+
return _dummyColor2.from (_color1).equal (_color2);
|
324 |
+
/*?
|
325 |
+
Static Methods
|
326 |
+
Uize.Color.equal
|
327 |
+
Returns a boolean, indicating whether or not the two specified colors are equivalent.
|
328 |
+
|
329 |
+
SYNTAX
|
330 |
+
..............................................................
|
331 |
+
areEqualBOOL = Uize.Color.equal (color1ANYTYPE,color2ANYTYPE);
|
332 |
+
..............................................................
|
333 |
+
|
334 |
+
EXAMPLES
|
335 |
+
............................................................................
|
336 |
+
Uize.Color.equal ('fuchsia',Uize.Color ('fuchsia')); // true
|
337 |
+
Uize.Color.equal ('ff00ff','#ff00ff'); // true
|
338 |
+
Uize.Color.equal ([255,0,255],'hsl(300,100,50)'); // true
|
339 |
+
Uize.Color.equal (16711935,{red:255,green:0,blue:255}); // true
|
340 |
+
Uize.Color.equal ('rgb(255,0,255)',{'HSL array':[300,100,50]}); // true
|
341 |
+
Uize.Color.equal ('fuchsia',{hue:300,saturation:100,lightness:50}); // true
|
342 |
+
............................................................................
|
343 |
+
|
344 |
+
In the above example, all the statements produce the result =true=. That's because all of the colors specified for the =color1ANYTYPE= and =color2ANYTYPE= parameters are equivalent to the color "fuchsia" - regardless of the encoding used to specify them.
|
345 |
+
|
346 |
+
MORE EXAMPLES
|
347 |
+
...............................................................................
|
348 |
+
Uize.Color.equal (Uize.Color.blend ('red','black'),'maroon'); // produces true
|
349 |
+
Uize.Color.equal (Uize.Color.blend ('white','black'),'gray'); // produces true
|
350 |
+
Uize.Color.equal (Uize.Color.blend ('red','blue'),'purple'); // produces true
|
351 |
+
...............................................................................
|
352 |
+
|
353 |
+
NOTES
|
354 |
+
- see the companion =equal= instance method
|
355 |
+
*/
|
356 |
+
};
|
357 |
+
|
358 |
+
_object.makeCombinations = function (_color1,_color2,_valuesPerComponent,_componentChaos,_outputEncoding) {
|
359 |
+
/*** default and conform settings ***/
|
360 |
+
_valuesPerComponent = _ensureSettingIsTuple (_valuesPerComponent,2);
|
361 |
+
_componentChaos = _ensureSettingIsTuple (_componentChaos,0);
|
362 |
+
_outputEncoding = _outputEncoding || 'color';
|
363 |
+
|
364 |
+
_dummyColor1.from (_color1);
|
365 |
+
_dummyColor2.from (_color2);
|
366 |
+
var
|
367 |
+
_result = [],
|
368 |
+
_dummyColor1Tuple = _dummyColor1.tuple,
|
369 |
+
_dummyColor2Tuple = _dummyColor2.getTuple (_dummyColor1.encoding),
|
370 |
+
_component0Divisions = _valuesPerComponent [0],
|
371 |
+
_component1Divisions = _valuesPerComponent [1],
|
372 |
+
_component2Divisions = _valuesPerComponent [2],
|
373 |
+
_color = Uize.Color (_dummyColor1),
|
374 |
+
_colorTuple = _color.tuple
|
375 |
+
;
|
376 |
+
|
377 |
+
function _blendComponent (_componentNo,_blendAmount) {
|
378 |
+
_colorTuple [_componentNo] = _blendValues (
|
379 |
+
_dummyColor1Tuple [_componentNo],
|
380 |
+
_dummyColor2Tuple [_componentNo],
|
381 |
+
_componentChaos [_componentNo]
|
382 |
+
? _blendValues (_blendAmount,Math.random (),_componentChaos [_componentNo])
|
383 |
+
: _blendAmount
|
384 |
+
);
|
385 |
+
}
|
386 |
+
for (var _component0ValueNo = -1; ++_component0ValueNo < _component0Divisions;) {
|
387 |
+
for (var _component1ValueNo = -1; ++_component1ValueNo < _component1Divisions;) {
|
388 |
+
for (var _component2ValueNo = -1; ++_component2ValueNo < _component2Divisions;) {
|
389 |
+
_blendComponent (0,_component0ValueNo / (_component0Divisions - 1));
|
390 |
+
_blendComponent (1,_component1ValueNo / (_component1Divisions - 1));
|
391 |
+
_blendComponent (2,_component2ValueNo / (_component2Divisions - 1));
|
392 |
+
_result.push (_color.to (_outputEncoding));
|
393 |
+
}
|
394 |
+
}
|
395 |
+
}
|
396 |
+
return _result;
|
397 |
+
/*?
|
398 |
+
Static Methods
|
399 |
+
Uize.Color.makeCombinations
|
400 |
+
Returns an array of colors, being a series of combinations produced from the two specified colors.
|
401 |
+
|
402 |
+
SYNTAX
|
403 |
+
...........................................
|
404 |
+
colorsARRAY = Uize.Color.makeCombinations (
|
405 |
+
color1ANYTYPE,
|
406 |
+
color2ANYTYPE,
|
407 |
+
valuesPerComponentINTorARRAY
|
408 |
+
);
|
409 |
+
...........................................
|
410 |
+
|
411 |
+
This method uses the two colors specified by the =color1ANYTYPE= and =color2ANYTYPE= parameters to produce a series of combination colors. A series of interpolated values is calculated for each component of the color space, with the first value being the value of the component for color 1, the last value being the value of the component for color 2, and a series of values calculated at intervals between the first value and the last value. Each value out of the series of values for each component is then combined with each other value for every other component, so producing a set of combinations in the color space of color 1.
|
412 |
+
|
413 |
+
The number of values per color component is specified by the =valuesPerComponentINTorARRAY= parameter. If an integer value is specified for this parameter, then there will be the same number of interpolated values for all components of the color space. For example, a value of =3= for the =valuesPerComponentINTorARRAY= parameter means that there will be three values for each of the red, green, and blue channels of the =sRGB= color space, producing a total of =27= combinations.
|
414 |
+
|
415 |
+
An array of integers can also be specified for the =valuesPerComponentINTorARRAY= parameter, in which case a desired number of interpolated values can be specified for each component of the color space. So, for example, the value =[2,3,4]= would specify two interpolated values for the red channel, three for the green channel, and four for the blue channel in the =sRGB= color space, producing a total of =24= combination colors.
|
416 |
+
|
417 |
+
VARIATION 1
|
418 |
+
........................................................................
|
419 |
+
colorsARRAY = Uize.Color.makeCombinations (color1ANYTYPE,color2ANYTYPE);
|
420 |
+
........................................................................
|
421 |
+
|
422 |
+
When no =valuesPerComponentINTorARRAY= parameter is specified, then there will be a default of two values per component, producing eight combinations for a three component color space (such as =sRGB=, =HSL=, =HSV=, etc.). The two values that are used for each component will be the value of that component for color 1 and the value of that component for color 2.
|
423 |
+
|
424 |
+
VARIATION 2
|
425 |
+
...........................................
|
426 |
+
colorsARRAY = Uize.Color.makeCombinations (
|
427 |
+
color1ANYTYPE,
|
428 |
+
color2ANYTYPE,
|
429 |
+
valuesPerComponentINTorARRAY,
|
430 |
+
componentChaosFLOATorARRAY
|
431 |
+
);
|
432 |
+
...........................................
|
433 |
+
|
434 |
+
When the optional =componentChaosFLOATorARRAY= parameter is specified, a certain amount of chaos can be introduced to the calculation of component values when making the combination colors. The value for =componentChaosFLOATorARRAY= can be a floating point number in the range of =0= to =1=, specifying the amount of chaos to be applied to all components of the color space, or it can be an array of floating point numbers in the range of =0= to =1=, specifying the amount of chaos to be applied to specific components.
|
435 |
+
|
436 |
+
A value of =0= means there will be no chaos, and values for a component will be calculated at regular intervals between the value of that component for color 1 and the value of that component for color 2. A value of =1= means that the calculation of values for a component will be completely chaotic, and chosen at random points between the value of that component for color 1 and the value of that component for color 2. A value of =.5= means that there will be an equal blend between regular intervals and chaos. Any degree of chaos - between none and total - can be introduced into the calculation of combination colors.
|
437 |
+
|
438 |
+
VARIATION 3
|
439 |
+
...........................................
|
440 |
+
colorsARRAY = Uize.Color.makeCombinations (
|
441 |
+
color1ANYTYPE,
|
442 |
+
color2ANYTYPE,
|
443 |
+
valuesPerComponentINTorARRAY,
|
444 |
+
componentChaosFLOATorARRAY,
|
445 |
+
outputEncodingSTR
|
446 |
+
);
|
447 |
+
...........................................
|
448 |
+
|
449 |
+
By default, this method generates its combination colors as an array of =Uize.Color= object instances. However, the optional =outputEncodingSTR= parameter lets you control the encoding of the color values in the generated array. You can specify any encoding - even an encoding that is not of the same color space as the colors specified by the =color1ANYTYPE= and =color2ANYTYPE= parameters. The output encoding will not, however, affect the color space in which the combination colors are generated, and this is determined by the encoding of the =color1ANYTYPE= parameter.
|
450 |
+
|
451 |
+
EXAMPLE
|
452 |
+
.....................................................................
|
453 |
+
var webSafeColors = Uize.Color.makeCombinations ('0','f',6,0,'#hex');
|
454 |
+
.....................................................................
|
455 |
+
|
456 |
+
In the above example, the =webSafeColors= variable will be an array containing all the [[http://en.wikipedia.org/wiki/Web_colors][web safe colors]], encoded in =#hex= format. The =Uize.Color.makeCombinations= method makes it easy to generate the web safe colors because they are defined as the combination colors with distinct 6 values per channel: =00=, =33=, =66=, =99=, =cc=, and =ff=. Now, if you wanted an array of =Uize.Color= instances instead, you could just specify the value ='color'= for the =outputEncodingSTR= parameter, instead of ='#hex'=.
|
457 |
+
*/
|
458 |
+
};
|
459 |
+
|
460 |
+
_object.mix = function (_colors,_encoding) {
|
461 |
+
var _colorsLength = _colors.length;
|
462 |
+
if (!_colorsLength) return new _object;
|
463 |
+
var
|
464 |
+
_component0Total = 0,
|
465 |
+
_component1Total = 0,
|
466 |
+
_component2Total = 0,
|
467 |
+
_component3Total = 0,
|
468 |
+
_primaryEncoding = _dummyColor1.from (_colors [0]).encoding
|
469 |
+
;
|
470 |
+
for (var _colorNo = _colorsLength; --_colorNo >= 0;) {
|
471 |
+
var _dummyColor1Tuple = _dummyColor1.from (_colors [_colorNo]).getTuple (_primaryEncoding);
|
472 |
+
_component0Total += _dummyColor1Tuple [0];
|
473 |
+
_component1Total += _dummyColor1Tuple [1];
|
474 |
+
_component2Total += _dummyColor1Tuple [2];
|
475 |
+
_component3Total += _dummyColor1Tuple [3];
|
476 |
+
}
|
477 |
+
_colorsLength = _colorsLength || 1;
|
478 |
+
_object.setTuple (
|
479 |
+
_dummyColor1.tuple,
|
480 |
+
_component0Total / _colorsLength,
|
481 |
+
_component1Total / _colorsLength,
|
482 |
+
_component2Total / _colorsLength,
|
483 |
+
_component3Total / _colorsLength
|
484 |
+
);
|
485 |
+
return _dummyColor1.to (_encoding || 'color');
|
486 |
+
/*?
|
487 |
+
Static Methods
|
488 |
+
Uize.Color.mix
|
489 |
+
Returns an instance of the =Uize.Color= object, whose color is initialized to the average of all the colors specified in the colors array.
|
490 |
+
|
491 |
+
SYNTAX
|
492 |
+
........................................
|
493 |
+
colorOBJ = Uize.Color.mix (colorsARRAY);
|
494 |
+
........................................
|
495 |
+
|
496 |
+
Color values specified in the =colorsARRAY= array can be specified in any of the many `Color Encodings` supported by the =Uize.Color= module, so the following statement is perfectly valid...
|
497 |
+
|
498 |
+
EXAMPLE
|
499 |
+
...............................................................
|
500 |
+
var mixedColor = Uize.Color.mix ([
|
501 |
+
'#f5f5dc', // beige
|
502 |
+
[255,0,0], // red
|
503 |
+
'fuchsia', // fuchsia
|
504 |
+
'Rgb(64,224,208)', // turquoise
|
505 |
+
{red:255,green:255,blue:0}, // yellow
|
506 |
+
0x808080, // gray
|
507 |
+
Uize.Color (245,255,250) // mintcream
|
508 |
+
]);
|
509 |
+
alert (mixedColor.to ()); // displays the text "#cf9e98"
|
510 |
+
...............................................................
|
511 |
+
|
512 |
+
The above example would produce a =Uize.Color= object set to the color with the =hex= RGB equivalent of =#cf9e98=. The expression =mixedColor.to ()= produces the output ='#cf9e98'= because the first color in the list is specified using the =#hex= encoding.
|
513 |
+
|
514 |
+
Primary Encoding
|
515 |
+
When mixing a series of colors, the color encoding of the first color in the series is used as the primary encoding for the mixing process.
|
516 |
+
|
517 |
+
This means that the =Uize.Color= object instance that is returned by this method will be set to that encoding. It also means that any color in the list that may be specified using an encoding that implies a color space other than that of the primary encoding will be automatically converted to the color space of the primary encoding.
|
518 |
+
|
519 |
+
VARIATION
|
520 |
+
....................................................
|
521 |
+
colorOBJ = Uize.Color.mix (colorsARRAY,encodingSTR);
|
522 |
+
....................................................
|
523 |
+
|
524 |
+
When the optional =encodingSTR= parameter is specified, rhe resulting mixed color can be encoded in any of the many supported `Color Encodings`.
|
525 |
+
|
526 |
+
EXAMPLE
|
527 |
+
....................................................
|
528 |
+
alert (
|
529 |
+
Uize.Color.mix (
|
530 |
+
[
|
531 |
+
'#f5f5dc', // beige
|
532 |
+
[255,0,0], // red
|
533 |
+
'fuchsia', // fuchsia
|
534 |
+
'Rgb(64,224,208)', // turquoise
|
535 |
+
{red:255,green:255,blue:0}, // yellow
|
536 |
+
0x808080, // gray
|
537 |
+
Uize.Color (245,255,250) // mintcream
|
538 |
+
],
|
539 |
+
'RGB string'
|
540 |
+
)
|
541 |
+
);
|
542 |
+
....................................................
|
543 |
+
|
544 |
+
In the above example, the =alert= statement would display the text "rgb(207,158,152)".
|
545 |
+
*/
|
546 |
+
};
|
547 |
+
|
548 |
+
_object.random = function (_encoding) {
|
549 |
+
return _dummyColor1.setEncoding (_encoding).random ().to (_encoding);
|
550 |
+
/*?
|
551 |
+
Static Methods
|
552 |
+
Uize.Color.random
|
553 |
+
Generates a random color with the specified encoding.
|
554 |
+
|
555 |
+
SYNTAX
|
556 |
+
...............................................
|
557 |
+
colorANYTYPE = Uize.Color.random (encodingSTR);
|
558 |
+
...............................................
|
559 |
+
|
560 |
+
EXAMPLE
|
561 |
+
................................................................................
|
562 |
+
Uize.Node.setStyle (
|
563 |
+
'myNodeId',
|
564 |
+
{color:Uize.Color.random ('#hex'),backgroundColor:Uize.Color.random ('#hex')}
|
565 |
+
);
|
566 |
+
................................................................................
|
567 |
+
|
568 |
+
In the above example, the text color and background color for the DOM node with the id "myNodeId" are being randomized.
|
569 |
+
|
570 |
+
VARIATION
|
571 |
+
......................................
|
572 |
+
colorRgbHexSTR = Uize.Color.random ();
|
573 |
+
......................................
|
574 |
+
|
575 |
+
When no =encodingSTR= parameter is specified, the default value ='hex'= will be used and the method will return a string value, being a hex formatted random RGB color value.
|
576 |
+
|
577 |
+
NOTES
|
578 |
+
- when the value ='color'= is specified for the =encodingSTR= parameter, then this method will return an instance of the =Uize.Color= object with its encoding set to ='hex'= (ie. in the =sRGB= color space)
|
579 |
+
- see the related =random= instance method
|
580 |
+
*/
|
581 |
+
};
|
582 |
+
|
583 |
+
var _returnTupleComponentAsIs = new Function ('tuple','componentNo','return tuple [componentNo]');
|
584 |
+
_object.sort = function (_colors,_referenceColor,_componentWeighting) {
|
585 |
+
if (_colors.length > 1) {
|
586 |
+
_componentWeighting = _ensureSettingIsTuple (_componentWeighting,1);
|
587 |
+
var
|
588 |
+
_getNormalizedComponent =
|
589 |
+
_componentWeighting [0] == 1 &&
|
590 |
+
_componentWeighting [1] == 1 &&
|
591 |
+
_componentWeighting [2] == 1 &&
|
592 |
+
(_componentWeighting [3] == 1 || _componentWeighting [3] === _undefined)
|
593 |
+
? _returnTupleComponentAsIs
|
594 |
+
: function (_tuple,_componentNo) {
|
595 |
+
return (
|
596 |
+
_componentWeighting [_componentNo] *
|
597 |
+
(_tuple [_componentNo] - _componentMins [_componentNo]) / _componentRanges [_componentNo]
|
598 |
+
);
|
599 |
+
},
|
600 |
+
_encoding = _dummyColor1.from (_referenceColor).encoding,
|
601 |
+
_colorSpaceTuple = _object.colorSpaces [_object.encodings [_encoding].colorSpace].tuple,
|
602 |
+
_componentMins = [
|
603 |
+
_colorSpaceTuple [0].min,
|
604 |
+
_colorSpaceTuple [1].min,
|
605 |
+
_colorSpaceTuple [2].min,
|
606 |
+
(_colorSpaceTuple [3] || _sacredEmptyObject).min
|
607 |
+
],
|
608 |
+
_componentRanges = [
|
609 |
+
_colorSpaceTuple [0].max - _componentMins [0],
|
610 |
+
_colorSpaceTuple [1].max - _componentMins [1],
|
611 |
+
_colorSpaceTuple [2].max - _componentMins [2],
|
612 |
+
(_colorSpaceTuple [3] || _sacredEmptyObject).max - _componentMins [3]
|
613 |
+
],
|
614 |
+
_dummyColor1Tuple = _dummyColor1.tuple,
|
615 |
+
_dummyColor1Component0Normalized = _getNormalizedComponent (_dummyColor1Tuple,0),
|
616 |
+
_dummyColor1Component1Normalized = _getNormalizedComponent (_dummyColor1Tuple,1),
|
617 |
+
_dummyColor1Component2Normalized = _getNormalizedComponent (_dummyColor1Tuple,2)
|
618 |
+
;
|
619 |
+
function _getDistanceBetweenCoords (_aX,_aY,_bX,_bY) {
|
620 |
+
return Math.sqrt ((_bX - _aX) * (_bX - _aX) + (_bY - _aY) * (_bY - _aY));
|
621 |
+
}
|
622 |
+
Uize.Array.Sort.sortBy (
|
623 |
+
_colors,
|
624 |
+
function (_color) {
|
625 |
+
var _dummyColor2Tuple = _dummyColor2.from (_color).getTuple (_encoding);
|
626 |
+
return _getDistanceBetweenCoords (
|
627 |
+
0,
|
628 |
+
_dummyColor1Component2Normalized,
|
629 |
+
_getDistanceBetweenCoords (
|
630 |
+
_dummyColor1Component0Normalized,
|
631 |
+
_dummyColor1Component1Normalized,
|
632 |
+
_getNormalizedComponent (_dummyColor2Tuple,0),
|
633 |
+
_getNormalizedComponent (_dummyColor2Tuple,1)
|
634 |
+
),
|
635 |
+
_getNormalizedComponent (_dummyColor2Tuple,2)
|
636 |
+
);
|
637 |
+
|
638 |
+
/* for sort with components as primary, secondary, and tertiary keys
|
639 |
+
return (
|
640 |
+
Math.round (
|
641 |
+
Math.abs (
|
642 |
+
_getNormalizedComponent (_dummyColor2Tuple,2) - _dummyColor1Component2Normalized
|
643 |
+
) * 999
|
644 |
+
) * 1000000 +
|
645 |
+
Math.round (
|
646 |
+
Math.abs (
|
647 |
+
_getNormalizedComponent (_dummyColor2Tuple,1) - _dummyColor1Component1Normalized
|
648 |
+
) * 999
|
649 |
+
) * 1000 +
|
650 |
+
Math.round (
|
651 |
+
Math.abs (
|
652 |
+
_getNormalizedComponent (_dummyColor2Tuple,0) - _dummyColor1Component0Normalized
|
653 |
+
) * 999
|
654 |
+
)
|
655 |
+
);
|
656 |
+
*/
|
657 |
+
}
|
658 |
+
)
|
659 |
+
}
|
660 |
+
return _colors;
|
661 |
+
/*?
|
662 |
+
Static Methods
|
663 |
+
Uize.Color.sort
|
664 |
+
Sorts the specified array of colors according to their proximity to a specified reference color, using the specified sort criteria.
|
665 |
+
|
666 |
+
SYNTAX
|
667 |
+
..................................................................
|
668 |
+
colorsARRAY = Uize.Color.sort (colorsARRAY,referenceColorANYTYPE);
|
669 |
+
..................................................................
|
670 |
+
|
671 |
+
This method sorts the colors specified by the =colorsARRAY= parameter, by how close they are to the reference color specified by the =referenceColorANYTYPE= parameter. Colors close to the head of the sorted array will be most like each other and most like the reference color, while colors towards the tail of the sorted array will be most unlike the reference color and will also tend to be most unlike one another. This will make the head of the sorted array appear more orderly, while making the tail appear more chaotic, since colors that are from the reference color may also be far from one another.
|
672 |
+
|
673 |
+
Color values in the array to sort can be specified using any of the `Color Encodings` supported by the =Uize.Color= object, but they will be sorted in the color space of the reference color, as specified by the =referenceColorANYTYPE= parameter. So, if the array of colors are specified using =sRGB= encodings and the reference color is specified using an =HSL= encoding, then the colors will be sorted in the =HSL= color space.
|
674 |
+
|
675 |
+
EXAMPLE
|
676 |
+
.......................................................................................
|
677 |
+
Uize.Color.sort (colors,'rgb(255,0,0)'); // sort redder colors to the head of the array
|
678 |
+
.......................................................................................
|
679 |
+
|
680 |
+
VARIATION 1
|
681 |
+
...............................
|
682 |
+
colorsARRAY = Uize.Color.sort (
|
683 |
+
colorsARRAY,
|
684 |
+
referenceColorANYTYPE,
|
685 |
+
componentWeightingARRAY
|
686 |
+
);
|
687 |
+
...............................
|
688 |
+
|
689 |
+
By default, the different components are normalized in order to give them equal weighting when calculating the proximity of colors being sorted to the reference color. However, specifying the optional =componentWeightingARRAY= parameter lets you specify a greater or lesser weighting for different components. For example, in the =HSL= color space, one may care more about how close colors are in terms of hue to the reference color than one cares about how close they are in terms of saturation or lightness.
|
690 |
+
|
691 |
+
The array specified by the =componentWeightingARRAY= parameter should contain a weighting factor for each component of the color space of the reference color. Each weighting factor should be a floating point number, where a value of =1= represents normal weighting, and a value of =0= means to effectively ignore the component. Weighting values greater than =1= may be specified. For example, a value for =componentWeightingARRAY= of =[2,1,1]= in the =HSL= color space means that hue is twice as important as saturation and lightness. And, for that matter, values of =[2,2,2]= and =[1,1,1]= for =componentWeightingARRAY= both indicate equal weighting for three components of a color space.
|
692 |
+
|
693 |
+
EXAMPLES
|
694 |
+
.................................................................................
|
695 |
+
Uize.Color.sort (colors,'hsl(0,0,0)',[0,0,1]); // darkest to lightest
|
696 |
+
Uize.Color.sort (colors,'hsl(0,0,100)',[0,0,1]); // lightest to darkest
|
697 |
+
Uize.Color.sort (colors,'hsl(0,100,0)',[0,1,0]); // most to least saturated
|
698 |
+
Uize.Color.sort (colors,'hsl(120,0,0)',[1,0,0]); // hue only, starting with green
|
699 |
+
.................................................................................
|
700 |
+
|
701 |
+
The above examples show different ways that different components in the color space can be completely ignored when sorting, simply by giving them a weight of =0=.
|
702 |
+
|
703 |
+
The "darkest to lightest" example sorts the array so that the darkest colors appear first. This is done by specifying a reference color in the =HSL= color space, with its lightness component set to =0= (ie. black), and with the components other than lightness given a weight of =0=. The "lightest to darkest" example operates in a similar way, excepting that the reference color for the sort has lightness set to =100= (ie. white). The "most to least saturated" example specifies weighting of =0= for hue and lightness so that only saturation affects the sort, and the saturation for the reference color is set to =100= (ie. most saturated first). The "hue only, starting with green" example makes hue the only component of importance, and the hue for the reference color is set to =120= (ie. green).
|
704 |
+
|
705 |
+
VARIATION 2
|
706 |
+
............................................
|
707 |
+
colorsARRAY = Uize.Color.sort (colorsARRAY);
|
708 |
+
............................................
|
709 |
+
|
710 |
+
When no =referenceColorANYTYPE= parameter is specified, then the reference color will be black in the RGB color space, and colors will be sorted on how close they are to black (so, essentially, darkest to lightest).
|
711 |
+
|
712 |
+
NOTES
|
713 |
+
- this method modifies the source array specified by the =colorsARRAY= parameter
|
714 |
+
- this method returns a reference to the array being sorted
|
715 |
+
*/
|
716 |
+
};
|
717 |
+
|
718 |
+
}
|
719 |
+
});
|
720 |
+
|
skin/frontend/default/customproduct/js/Uize.Comm.Ajax.js
ADDED
@@ -0,0 +1,108 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Comm.Ajax Class
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2004-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Class
|
14 |
+
importance: 9
|
15 |
+
codeCompleteness: 95
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 80
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Comm.Ajax= class implements support for [[http://en.wikipedia.org/wiki/Ajax_(programming)][Ajax]] (Asynchronous JavaScript And XML) communication through the XMLHttpRequest (XHR) object.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Jan Borgersen`, `Chris van Rensburg`, `Ben Ilegbodu`, `Tim Carter`, original code donated by `Zazzle Inc.`
|
25 |
+
|
26 |
+
In order to implement support for communication through the XMLHttpRequest object, this class overrides the implementation of the =performRequest= instance method inherited from the =Uize.Comm= base class. There are no additional methods or properties provided by this class - all the interface is provided in the =Uize.Comm= superclass.
|
27 |
+
*/
|
28 |
+
|
29 |
+
Uize.module ({
|
30 |
+
name:'Uize.Comm.Ajax',
|
31 |
+
required:'Uize.Url',
|
32 |
+
builder:function (_superclass) {
|
33 |
+
/*** Class Constructor ***/
|
34 |
+
var
|
35 |
+
_class = _superclass.subclass (),
|
36 |
+
_classPrototype = _class.prototype
|
37 |
+
;
|
38 |
+
|
39 |
+
/*** General Variables ***/
|
40 |
+
var _nop = Uize.nop;
|
41 |
+
|
42 |
+
/*** Public Instance Methods ***/
|
43 |
+
_classPrototype.performRequest = function (_request,_callback) {
|
44 |
+
var
|
45 |
+
_this = this,
|
46 |
+
_returnType = _request.returnType,
|
47 |
+
_returnTypeIsObject = _returnType == 'object',
|
48 |
+
_origUrl = Uize.Url.fromParams(_request.url),
|
49 |
+
_requestUrl = Uize.Url.resolve (
|
50 |
+
_request.url,
|
51 |
+
Uize.copyInto (
|
52 |
+
{
|
53 |
+
rnd:_request.cache == 'never' ? Uize.Url.getCacheDefeatStr () : null
|
54 |
+
},
|
55 |
+
_origUrl.comm_mode ? null : {comm_mode:'ajax'},
|
56 |
+
_origUrl.output ? null : {output:'js'}
|
57 |
+
)
|
58 |
+
),
|
59 |
+
_requestData = _request.data || '',
|
60 |
+
_requestMethod = _request.requestMethod,
|
61 |
+
_requestMethodIsPost = _requestMethod == 'POST'
|
62 |
+
;
|
63 |
+
if (!_this._xmlHttpRequest)
|
64 |
+
_this._xmlHttpRequest = window.XMLHttpRequest
|
65 |
+
? new XMLHttpRequest
|
66 |
+
: new ActiveXObject ('Microsoft.XMLHTTP')
|
67 |
+
;
|
68 |
+
_this._xmlHttpRequest.onreadystatechange = function () {
|
69 |
+
if (_this._xmlHttpRequest.readyState == 4) {
|
70 |
+
_this._xmlHttpRequest.onreadystatechange = _nop;
|
71 |
+
if (_this._xmlHttpRequest.status == 200) {
|
72 |
+
var _responseText = _this._xmlHttpRequest.responseText;
|
73 |
+
if (_returnTypeIsObject || _returnType == 'xml')
|
74 |
+
_request.responseXml = _this._xmlHttpRequest.responseXML
|
75 |
+
;
|
76 |
+
if (_returnTypeIsObject || _returnType == 'text')
|
77 |
+
_request.responseText = _responseText
|
78 |
+
;
|
79 |
+
if (_returnTypeIsObject || _returnType == 'json')
|
80 |
+
_request.responseJson = _responseText
|
81 |
+
? (new Function ('var a=[' + _responseText + '];return a.pop()')) ()
|
82 |
+
: null
|
83 |
+
;
|
84 |
+
_this._xmlHttpRequest.abort ();
|
85 |
+
_callback ();
|
86 |
+
} else {
|
87 |
+
//alert ('There was a problem retrieving the data:\n' + _this._xmlHttpRequest.statusText);
|
88 |
+
_this._xmlHttpRequest.abort ();
|
89 |
+
}
|
90 |
+
}
|
91 |
+
};
|
92 |
+
if (_requestMethodIsPost && !_requestData) {
|
93 |
+
var _queryPos = _requestUrl.indexOf ('?');
|
94 |
+
_requestData = _requestUrl.substr (_queryPos + 1);
|
95 |
+
_requestUrl = _requestUrl.slice (0,_queryPos);
|
96 |
+
}
|
97 |
+
_this._xmlHttpRequest.open (_requestMethod,_requestUrl,true);
|
98 |
+
if (_requestMethodIsPost) {
|
99 |
+
_this._xmlHttpRequest.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
|
100 |
+
_this._xmlHttpRequest.setRequestHeader('Content-length', _requestData.length);
|
101 |
+
}
|
102 |
+
_this._xmlHttpRequest.send (_requestData);
|
103 |
+
};
|
104 |
+
|
105 |
+
return _class;
|
106 |
+
}
|
107 |
+
});
|
108 |
+
|
skin/frontend/default/customproduct/js/Uize.Comm.Iframe.Upload.js
ADDED
@@ -0,0 +1,77 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Comm.Iframe.Upload Class
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2004-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Class
|
14 |
+
importance: 4
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 40
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Comm.Iframe.Upload= class implements support for file upload by submitting form data to a server and targeting its response back to an IFRAME.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Ben Ilegbodu`
|
25 |
+
|
26 |
+
In order to implement support for upload through an IFRAME, this class overrides the implementation of the =performRequest= instance method inherited from the =Uize.Comm.Iframe= base class. There are no additional methods or properties provided by this class - all the interface is provided in the =Uize.Comm= superclass.
|
27 |
+
*/
|
28 |
+
|
29 |
+
Uize.module ({
|
30 |
+
name:'Uize.Comm.Iframe.Upload',
|
31 |
+
required:[
|
32 |
+
'Uize.Node',
|
33 |
+
'Uize.Url'
|
34 |
+
],
|
35 |
+
builder:function (_superclass) {
|
36 |
+
/*** Class Constructor ***/
|
37 |
+
var
|
38 |
+
_class = _superclass.subclass (),
|
39 |
+
_classPrototype = _class.prototype
|
40 |
+
;
|
41 |
+
|
42 |
+
/*** Public Instance Methods ***/
|
43 |
+
_classPrototype.performRequest = function (_request,_callback) {
|
44 |
+
var
|
45 |
+
_this = this,
|
46 |
+
_iframe = Uize.Node.getById(_this.iframeId),
|
47 |
+
_uploadForm = _request.uploadForm,
|
48 |
+
_uploadFormTarget = _uploadForm.target,
|
49 |
+
_returnType = _request.returnType,
|
50 |
+
_returnTypeIsObject = _returnType == 'object'
|
51 |
+
;
|
52 |
+
handleResponse = function (_responseResult) {
|
53 |
+
if (_returnTypeIsObject || _returnType == 'json')
|
54 |
+
_request.responseJson = Uize.clone (_responseResult)
|
55 |
+
;
|
56 |
+
Uize.Node.isIe && _iframe.contentWindow.history.go (-1);
|
57 |
+
_uploadForm.target = _uploadFormTarget;
|
58 |
+
_callback ();
|
59 |
+
};
|
60 |
+
|
61 |
+
_uploadForm.action = Uize.Url.resolve(
|
62 |
+
_uploadForm.action,
|
63 |
+
{
|
64 |
+
comm_mode:'iframe',
|
65 |
+
output:'js',
|
66 |
+
rnd:Uize.Url.getCacheDefeatStr ()
|
67 |
+
}
|
68 |
+
);
|
69 |
+
|
70 |
+
_uploadForm.target = _iframe.name;
|
71 |
+
_uploadForm.submit();
|
72 |
+
};
|
73 |
+
|
74 |
+
return _class;
|
75 |
+
}
|
76 |
+
});
|
77 |
+
|
skin/frontend/default/customproduct/js/Uize.Comm.Iframe.js
ADDED
@@ -0,0 +1,106 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Comm.Iframe Class
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2004-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Class
|
14 |
+
importance: 5
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 50
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Comm.Iframe= class implements support for communication to a server by submitting form data to it and targeting its response to an IFRAME.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`, `Jan Borgersen`, original code donated by `Zazzle Inc.`
|
25 |
+
|
26 |
+
In order to implement support for communication through an IFRAME, this class overrides the implementation of the =performRequest= instance method inherited from the =Uize.Comm= base class. There are no additional methods or properties provided by this class - all the interface is provided in the =Uize.Comm= superclass.
|
27 |
+
*/
|
28 |
+
|
29 |
+
Uize.module ({
|
30 |
+
name:'Uize.Comm.Iframe',
|
31 |
+
required:[
|
32 |
+
'Uize.Url',
|
33 |
+
'Uize.Node'
|
34 |
+
],
|
35 |
+
builder:function (_superclass) {
|
36 |
+
/*** Class Constructor ***/
|
37 |
+
var
|
38 |
+
_class = _superclass.subclass (),
|
39 |
+
_classPrototype = _class.prototype
|
40 |
+
;
|
41 |
+
|
42 |
+
/*** General Variables ***/
|
43 |
+
var _iframeId;
|
44 |
+
|
45 |
+
/*** Public Instance Methods ***/
|
46 |
+
_classPrototype.performRequest = function (_request,_callback) {
|
47 |
+
var
|
48 |
+
_this = this,
|
49 |
+
_iframe = Uize.Node.getById (_iframeId),
|
50 |
+
_requestUrl = Uize.Url.resolve (
|
51 |
+
_request.url,
|
52 |
+
{
|
53 |
+
comm_mode:'ajax',
|
54 |
+
output:'js',
|
55 |
+
rnd:_request.cache == 'never' ? Uize.Url.getCacheDefeatStr () : null
|
56 |
+
}
|
57 |
+
),
|
58 |
+
_returnType = _request.returnType,
|
59 |
+
_returnTypeIsObject = _returnType == 'object'
|
60 |
+
;
|
61 |
+
handleResponse = function (_responseResult) {
|
62 |
+
if (_returnTypeIsObject || _returnType == 'json')
|
63 |
+
_request.responseJson = Uize.clone (_responseResult)
|
64 |
+
;
|
65 |
+
Uize.Node.isIe && _iframe.contentWindow.history.go (-1);
|
66 |
+
_callback ();
|
67 |
+
};
|
68 |
+
if (_request.requestMethod == 'POST') {
|
69 |
+
var
|
70 |
+
_form = Uize.Node.getById ('CommIframe_form'),
|
71 |
+
_paramsField = Uize.Node.getById ('CommIframe_params'),
|
72 |
+
_queryPos = _requestUrl.indexOf ('?')
|
73 |
+
;
|
74 |
+
_paramsField.value = _queryPos > -1 ? _requestUrl.substr (_queryPos + 1) : '';
|
75 |
+
_form.action = _requestUrl.slice (0,_queryPos);
|
76 |
+
_form.submit ();
|
77 |
+
} else {
|
78 |
+
_iframe.src = _requestUrl;
|
79 |
+
}
|
80 |
+
};
|
81 |
+
|
82 |
+
/*** Initialization ***/
|
83 |
+
if (typeof navigator != 'undefined') {
|
84 |
+
/* NOTE:
|
85 |
+
This puts the iframe in the page, but really the iframe should only be put into the page when the first instance of the class is created. Or, ideally, there should be a unique iframe per instance. The iframe insertion could even be deferred until the first request is performed.
|
86 |
+
*/
|
87 |
+
_iframeId = _classPrototype.iframeId = 'Uize_Comm_Iframe_iframe' + Uize.Url.getCacheDefeatStr ();
|
88 |
+
Uize.Node.injectHtml (
|
89 |
+
Uize.Node.getById ('globalContent') || document.body,
|
90 |
+
'<form id="CommIframe_form" style="display:none;" target="' + _iframeId + '" method="POST" accept-charset="utf-8">' +
|
91 |
+
'<input id="CommIframe_params" name="params" type="hidden"/>' +
|
92 |
+
'</form>' +
|
93 |
+
'<iframe id="' + _iframeId + '" name="' + _iframeId + '" width="1" height="1" src="/z.2/js/library/Zazzle_CommIframe/blank.html" frameborder="1" style="position:absolute; visibility:hidden;" scrolling="no"></iframe>' /* NOTE: this code shouldn't make an assumption about the library being served from this place - initial src URL should */
|
94 |
+
);
|
95 |
+
}
|
96 |
+
|
97 |
+
handleResponse = function () {
|
98 |
+
/*
|
99 |
+
a dummy version of this function in case the user navigates back to a page using this code and a cached iframe server response tries to call this function (ie. no requests have been made yet)
|
100 |
+
*/
|
101 |
+
};
|
102 |
+
|
103 |
+
return _class;
|
104 |
+
}
|
105 |
+
});
|
106 |
+
|
skin/frontend/default/customproduct/js/Uize.Comm.Script.js
ADDED
@@ -0,0 +1,115 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Comm.Script Class
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2008-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Class
|
14 |
+
importance: 7
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 80
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Comm.Script= class implements support for communication with a server via [[http://en.wikipedia.org/wiki/Cross-site_scripting][cross-site scripting]] through the insertion of script tags into the document.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Tim Carter`
|
25 |
+
|
26 |
+
In order to implement support for communication through =script= tags, this class overrides the implementation of the =performRequest= instance method inherited from the =Uize.Comm= base class. There are no additional methods provided by this class - all the interface is provided in the =Uize.Comm= superclass.
|
27 |
+
*/
|
28 |
+
|
29 |
+
Uize.module({
|
30 |
+
name:'Uize.Comm.Script',
|
31 |
+
required:'Uize.Url',
|
32 |
+
builder:function(_superclass) {
|
33 |
+
/*** Variables for Scruncher Optimization ***/
|
34 |
+
var _undefined;
|
35 |
+
|
36 |
+
/*** Constructor ***/
|
37 |
+
var
|
38 |
+
_class = _superclass.subclass(
|
39 |
+
function() {
|
40 |
+
for (this._callbackHashName in {_callbacks:1});
|
41 |
+
if (!_class._callbacks) _class._callbacks = [];
|
42 |
+
}
|
43 |
+
),
|
44 |
+
_classPrototype = _class.prototype
|
45 |
+
;
|
46 |
+
|
47 |
+
/*** Public Methods ***/
|
48 |
+
_classPrototype.performRequest = function(_request, _callback) {
|
49 |
+
var
|
50 |
+
_this = this,
|
51 |
+
_callbacks = _class._callbacks,
|
52 |
+
_serverHandlesCallback = _this._callbackMode == 'server',
|
53 |
+
_scriptNode = document.createElement('script')
|
54 |
+
;
|
55 |
+
_callbacks.push(
|
56 |
+
function(_response) {
|
57 |
+
_request['response' + Uize.capFirstChar (_request.returnType)] = _response;
|
58 |
+
_callback();
|
59 |
+
}
|
60 |
+
);
|
61 |
+
|
62 |
+
var _callbackName = 'Uize.Comm.Script.' + _this._callbackHashName + '[' + (_callbacks.length - 1) + ']';
|
63 |
+
|
64 |
+
_scriptNode.src = Uize.Url.resolve([
|
65 |
+
_request.url,
|
66 |
+
{comm_mode:'script'},
|
67 |
+
_serverHandlesCallback ? {callback:_callbackName} : _undefined,
|
68 |
+
_request.cache == 'never' ? {rnd:Uize.Url.getCacheDefeatStr()} : _undefined
|
69 |
+
]);
|
70 |
+
|
71 |
+
if (!_serverHandlesCallback) {
|
72 |
+
var _callbackFn = _class._callbacks[_callbacks.length - 1];
|
73 |
+
if (_scriptNode.readyState)
|
74 |
+
_scriptNode.onreadystatechange = function () {
|
75 |
+
if (_scriptNode.readyState == 'loaded' || _scriptNode.readyState == 'complete') {
|
76 |
+
_scriptNode.onreadystatechange = null;
|
77 |
+
_callbackFn ();
|
78 |
+
}
|
79 |
+
}
|
80 |
+
;
|
81 |
+
else
|
82 |
+
_scriptNode.onload = _callbackFn;
|
83 |
+
}
|
84 |
+
|
85 |
+
document.body.appendChild(_scriptNode);
|
86 |
+
};
|
87 |
+
|
88 |
+
/*** Register properties ***/
|
89 |
+
_class.registerProperties ({
|
90 |
+
_callbackMode:{
|
91 |
+
name:'callbackMode',
|
92 |
+
value:'server'
|
93 |
+
/*?
|
94 |
+
State Properties
|
95 |
+
callbackMode
|
96 |
+
A string, indicating whether the callback function should be handled by the server or client.
|
97 |
+
|
98 |
+
While traditional xss techniques pass the name of the callback to the server so that it can be included in the response, certain situations may arise where the server is not capable of handling the callback. For example, this may occur when some client code wishes to query a service that is built by a third-party, and thus not under the control of the client developer. In the preceding example, the developer can set the value of =callbackMode= to ='client'= so that =Uize.Comm.Script= handles the callback itself.
|
99 |
+
|
100 |
+
=Uize.Comm.Script= does this by inserting two script nodes into the DOM each time a request is made. The first request queries the server. The second calls the callback. This implementation assumes that the script tags are written synchronously, ie., the first finishes before the second is written out; this is the case for most modern browsers. As a result, the callback only gets executed once all the data from the server is in memory.
|
101 |
+
|
102 |
+
This does place some restrictions on the callback function. Unlike most callbacks in the =Uize.Comm= class and subclasses, the callback in ='client'= mode does not receive any parameters. Once the ='client'= callback is called, the only certainty that exists with regard to the server request is that it completed. It is the responsibility of the callback developer to know the nature of that data.
|
103 |
+
|
104 |
+
Values
|
105 |
+
The possible values for the =callbackMode= state property are ='client'= or ='server'=. ='server'= mode means that the callback function will be passed to the server and it is the server's responsibility to call it upon completion of the task. If ='client'= mode is set, =Uize.Comm.Script= will call the callback function after each request is made.
|
106 |
+
|
107 |
+
NOTES
|
108 |
+
- the initial value is ='server'=
|
109 |
+
*/
|
110 |
+
}
|
111 |
+
});
|
112 |
+
return _class;
|
113 |
+
}
|
114 |
+
});
|
115 |
+
|
skin/frontend/default/customproduct/js/Uize.Comm.js
ADDED
@@ -0,0 +1,518 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Comm Class
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2004-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Class
|
14 |
+
importance: 10
|
15 |
+
codeCompleteness: 90
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 80
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Comm= class provides functionality and interface that is shared by subclasses that implement support for specific communication protocols.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`, `Jan Borgersen`, original code donated by `Zazzle Inc.`
|
25 |
+
|
26 |
+
The =Uize.Comm= class serves as the base class for subclasses that implement support for specific communication protocols (such as =Uize.Comm.Ajax=, =Uize.Comm.Iframe=, and =Uize.Comm.Script=). The =Uize.Comm= base class provides support for queuing subsequent calls to allow sequenced server requests.
|
27 |
+
*/
|
28 |
+
|
29 |
+
Uize.module ({
|
30 |
+
name:'Uize.Comm',
|
31 |
+
superclass:'Uize.Class',
|
32 |
+
required:'Uize.Url',
|
33 |
+
builder:function (_superclass) {
|
34 |
+
/*** Variables for Scruncher Optimization ***/
|
35 |
+
var
|
36 |
+
_true = true,
|
37 |
+
_false = false,
|
38 |
+
_undefined
|
39 |
+
;
|
40 |
+
|
41 |
+
/*** Class Constructor ***/
|
42 |
+
var
|
43 |
+
_class = _superclass.subclass (
|
44 |
+
function () {
|
45 |
+
var _this = this;
|
46 |
+
|
47 |
+
/*** Private Instance Properties ***/
|
48 |
+
_this._requestQueue = [];
|
49 |
+
_this._responseCache = {};
|
50 |
+
|
51 |
+
/*** Public Instance Properties ***/
|
52 |
+
_this.requestQueue = _this._requestQueue;
|
53 |
+
/*?
|
54 |
+
Instance Properties
|
55 |
+
requestQueue
|
56 |
+
An array, containing all pending requests that have been queued up and are waiting to be performed.
|
57 |
+
|
58 |
+
NOTES
|
59 |
+
- see also the =flush=, =queueRequest=, and =useQueue= instance methods
|
60 |
+
*/
|
61 |
+
}
|
62 |
+
),
|
63 |
+
_classPrototype = _class.prototype
|
64 |
+
;
|
65 |
+
|
66 |
+
/*** Utility Functions ***/
|
67 |
+
function _getResponsePropertyNameForRequest (_request) {
|
68 |
+
return 'response' + Uize.capFirstChar (_request.returnType);
|
69 |
+
}
|
70 |
+
|
71 |
+
function _resolveRequestUrl (_request) {
|
72 |
+
_request.url = Uize.Url.resolve (_request.url) // resolves it, in case it's an array
|
73 |
+
}
|
74 |
+
|
75 |
+
/*** Private Instance Methods ***/
|
76 |
+
_classPrototype._getCachedResponse = function (_request) {
|
77 |
+
return _request.cache == 'memory' ? this._responseCache [_request.url] : null
|
78 |
+
};
|
79 |
+
|
80 |
+
_classPrototype._callResponseCallback = function (_request) {
|
81 |
+
var
|
82 |
+
_returnType = _request.returnType,
|
83 |
+
_requestCallback = _request.callback,
|
84 |
+
_cachedResponse = this._getCachedResponse (_request)
|
85 |
+
;
|
86 |
+
if (_cachedResponse) {
|
87 |
+
var _returnTypeIsObject = _returnType == 'object';
|
88 |
+
if (_requestCallback) {
|
89 |
+
_request.responseText = '';
|
90 |
+
_request.responseJson = _request.responseXml = null;
|
91 |
+
if (_returnTypeIsObject || _returnType == 'xml')
|
92 |
+
_request.responseXml = Uize.clone (_cachedResponse.responseXml)
|
93 |
+
;
|
94 |
+
if (_returnTypeIsObject || _returnType == 'text')
|
95 |
+
_request.responseText = _cachedResponse.responseText
|
96 |
+
;
|
97 |
+
if (_returnTypeIsObject || _returnType == 'json')
|
98 |
+
_request.responseJson = Uize.clone (_cachedResponse.responseJson)
|
99 |
+
;
|
100 |
+
}
|
101 |
+
} else {
|
102 |
+
if (_request.cache == 'memory')
|
103 |
+
this._responseCache [_request.url] = {
|
104 |
+
responseXml:Uize.clone (_request.responseXml),
|
105 |
+
responseJson:Uize.clone (_request.responseJson),
|
106 |
+
responseText:_request.responseText
|
107 |
+
}
|
108 |
+
;
|
109 |
+
}
|
110 |
+
_requestCallback &&
|
111 |
+
_requestCallback (
|
112 |
+
_returnType == 'object' ? _request : _request [_getResponsePropertyNameForRequest (_request)]
|
113 |
+
)
|
114 |
+
;
|
115 |
+
};
|
116 |
+
|
117 |
+
_classPrototype._fireRequestQueueUpdatedEvent = function () {
|
118 |
+
this.fire ('Request Queue Updated');
|
119 |
+
/*?
|
120 |
+
Instance Events
|
121 |
+
Request Queue Updated
|
122 |
+
The =Request Queue Updated= event is fired each time the =requestQueue= instance property is updated.
|
123 |
+
*/
|
124 |
+
};
|
125 |
+
|
126 |
+
/*** Public Instance Methods ***/
|
127 |
+
_classPrototype.performRequest = function (_request,_callback) {
|
128 |
+
_callback ();
|
129 |
+
/*?
|
130 |
+
Instance Methods
|
131 |
+
performRequest
|
132 |
+
A method that should be overrided in subclasses that implement support for specific communication protocols.
|
133 |
+
|
134 |
+
SYNTAX
|
135 |
+
...................................................
|
136 |
+
myInstance.performRequest (requestOBJ,callbackFUNC)
|
137 |
+
...................................................
|
138 |
+
|
139 |
+
This method is not intended to be called by application code. It is only public so that it can be overrided in subclasses. When implementing this method in a subclass, your method should expect to receive the two parameters =requestOBJ= and =callbackFUNC=. The =requestOBJ= parameter will contain all the information necessary for performing the request.
|
140 |
+
|
141 |
+
Once the request has been sucessfully completed, your implementation should place request results into =requestOBJ= and then call the callback function specified in the =callbackFUNC= parameter. It is not necessary to pass any parameters when calling the =callbackFUNC= function, since the request results are placed into =requestOBJ=.
|
142 |
+
*/
|
143 |
+
};
|
144 |
+
|
145 |
+
_classPrototype.flush = function () {
|
146 |
+
this._requestQueue.length = 0;
|
147 |
+
this._fireRequestQueueUpdatedEvent ();
|
148 |
+
/*?
|
149 |
+
Instance Methods
|
150 |
+
flush
|
151 |
+
A method that lets you flush the request queue.
|
152 |
+
|
153 |
+
SYNTAX
|
154 |
+
....................
|
155 |
+
myInstance.flush ();
|
156 |
+
....................
|
157 |
+
|
158 |
+
NOTES
|
159 |
+
- this method takes no parameters
|
160 |
+
- after flushing the request queue, the =Request Queue Updated= instance event will be fired
|
161 |
+
- see also the =queueRequest= and =useQueue= instance methods
|
162 |
+
- see also the =requestQueue= instance property
|
163 |
+
*/
|
164 |
+
};
|
165 |
+
|
166 |
+
_classPrototype.flushCache = function (_requestOrUrl) {
|
167 |
+
arguments.length
|
168 |
+
? delete this._responseCache [typeof _requestOrUrl == 'string' ? _requestOrUrl : _requestOrUrl.url]
|
169 |
+
: (this._responseCache = {})
|
170 |
+
;
|
171 |
+
/*?
|
172 |
+
Instance Methods
|
173 |
+
flushCache
|
174 |
+
Lets you flush the cached response for a specific request, or lets you flush the entire response cache for the instance.
|
175 |
+
|
176 |
+
SYNTAX
|
177 |
+
...................................
|
178 |
+
myInstance.flushCache (requestOBJ);
|
179 |
+
...................................
|
180 |
+
|
181 |
+
VARIATION 1
|
182 |
+
......................................
|
183 |
+
myInstance.flushCache (requestUrlSTR);
|
184 |
+
......................................
|
185 |
+
|
186 |
+
As an alternative to specifying a request by request object, a request can be specified by its URL (ie. the value of the =url= property of the request object).
|
187 |
+
|
188 |
+
VARIATION 2
|
189 |
+
.........................
|
190 |
+
myInstance.flushCache ();
|
191 |
+
.........................
|
192 |
+
|
193 |
+
When no parameter is specified, then the =flushCache= method will flush the entire response cache for the instance.
|
194 |
+
|
195 |
+
NOTES
|
196 |
+
- don't confuse this method with the =flush= instance method that flushes the request queue
|
197 |
+
*/
|
198 |
+
};
|
199 |
+
|
200 |
+
_classPrototype.request = function (_request) {
|
201 |
+
var _this = this;
|
202 |
+
_resolveRequestUrl (_request);
|
203 |
+
if (_this._getCachedResponse (_request)) {
|
204 |
+
setTimeout (function () {_this._callResponseCallback (_request)},0);
|
205 |
+
} else {
|
206 |
+
_this.queueRequest (_request);
|
207 |
+
_this.useQueue ();
|
208 |
+
}
|
209 |
+
/*?
|
210 |
+
Instance Methods
|
211 |
+
request
|
212 |
+
A method that lets you initiate a request.
|
213 |
+
|
214 |
+
SYNTAX
|
215 |
+
................................
|
216 |
+
myInstance.request (requestOBJ);
|
217 |
+
................................
|
218 |
+
|
219 |
+
All the information that governs the request is contained inside the =requestOBJ= parameter. The properties of this object will vary, depending on the communication protocol and are determined by the particular subclass =Uize.Comm= you are using.
|
220 |
+
|
221 |
+
SYNTAX (EXPLODED)
|
222 |
+
................................................
|
223 |
+
myInstance.request ({
|
224 |
+
// ...properties specific to comm protocol...
|
225 |
+
// ...properties specific to comm protocol...
|
226 |
+
// ...properties specific to comm protocol...
|
227 |
+
returnType:returnTypeSTR,
|
228 |
+
cache:cacheBOOLorSTR,
|
229 |
+
callback:callbackFUNC
|
230 |
+
});
|
231 |
+
................................................
|
232 |
+
|
233 |
+
requestOBJ Properties
|
234 |
+
The =Uize.Comm= base class handles the following properties of the =requestOBJ= parameter...
|
235 |
+
|
236 |
+
returnType
|
237 |
+
A string, specifying the data type that should be used when passing the response result to the callback function specified by the =callback= property.
|
238 |
+
|
239 |
+
VALUES
|
240 |
+
- ='text'= - the value of the =responseText= property of =requestOBJ= will be passed as the parameter to the =callback= function
|
241 |
+
- ='json'= - the value of the =responseJson= property of =requestOBJ= will be passed as the parameter to the =callback= function
|
242 |
+
- ='xml'= - the value of the =responseJson= property of =requestOBJ= will be passed as the parameter to the =callback= function
|
243 |
+
- ='object'= (default) - the =requestOBJ= object will be passed as the parameter to the =callback= function
|
244 |
+
|
245 |
+
NOTES
|
246 |
+
- the default value for this property is ='object'=
|
247 |
+
|
248 |
+
cache
|
249 |
+
A string, specifying the caching mode that should be employed when performing the request.
|
250 |
+
|
251 |
+
VALUES
|
252 |
+
- ='memory'= - a JavaScript memory based mechanism will be employed to cache the request's response. Using this caching mode, the browser's caching mechanism is preempted. Because this caching mode is memory based, the caching of responses in this mode is not persisted across page reloads or navigation. This mode is useful for requests that are likely to be hit heavily and repeatedly throughout a page session.
|
253 |
+
- ='browser'= - caching is left to the browser's built-in mechanism.
|
254 |
+
- ='never'= (default) - a cache defeat mechanism is employed to ensure that the request is never cached. This mode is useful for requests where the response will vary with repeated use - even with identical request parameters - because the response may be determined by data beyond that contained in the request, such as data contributed through community interaction with a Web application, or data that is updated in the user's session.
|
255 |
+
|
256 |
+
NOTES
|
257 |
+
- the default value for this property is ='never'=
|
258 |
+
|
259 |
+
callback
|
260 |
+
A function reference, specifying the function that should be called once the request has been performed.
|
261 |
+
|
262 |
+
The callback function you specify should expect to receive one parameter that will be of the type specified by the =returnType= property.
|
263 |
+
|
264 |
+
cutToHead
|
265 |
+
A boolean, specifying whether or not the request should cut to the head of the request queue.
|
266 |
+
|
267 |
+
If the value =false= is specified for the =cutToHead= property, or if this property is not specified, then the request is appended to the request queue. This is the default behavior. In some rare cases, such as when recovering from a request that returns a failure / error response, it might be desirable to push requests that are part of recovering from the failed request to the head of the queue. In such cases, such recovery requests can specify the value =true= for the =cutToHead= property.
|
268 |
+
*/
|
269 |
+
};
|
270 |
+
|
271 |
+
_classPrototype.queueRequest = function (_request) {
|
272 |
+
var _this = this;
|
273 |
+
_resolveRequestUrl (_request);
|
274 |
+
delete _request.completed; // in case the request object was already used for a previous request and completed was set to true (we don't want the repeated request wrapped up prematurely)
|
275 |
+
if (!_request.requestMethod) _request.requestMethod = 'GET';
|
276 |
+
if (!_request.returnType) _request.returnType = 'object';
|
277 |
+
if (typeof _request.cache != 'string')
|
278 |
+
_request.cache = _request.cache ? 'memory' : 'never'
|
279 |
+
;
|
280 |
+
_this._requestQueue [_request.cutToHead ? 'unshift' : 'push'] (_request);
|
281 |
+
_this._fireRequestQueueUpdatedEvent ();
|
282 |
+
};
|
283 |
+
|
284 |
+
_classPrototype.useQueue = function () {
|
285 |
+
var
|
286 |
+
_this = this,
|
287 |
+
_requestQueue = _this._requestQueue,
|
288 |
+
_requestQueueLength = _requestQueue.length
|
289 |
+
;
|
290 |
+
if (!_this._usingQueue && _requestQueueLength) {
|
291 |
+
_this._usingQueue = _true;
|
292 |
+
|
293 |
+
function _cleanFromQueue () {
|
294 |
+
var _request;
|
295 |
+
while ((_request = _requestQueue [0]) && (_this._getCachedResponse (_request) || _request.completed))
|
296 |
+
_this._callResponseCallback (_requestQueue.shift ())
|
297 |
+
;
|
298 |
+
_this._usingQueue = _false;
|
299 |
+
_this._fireRequestQueueUpdatedEvent ();
|
300 |
+
|
301 |
+
_requestQueue.length && setTimeout (function () {_this.useQueue ()},1);
|
302 |
+
/* TO DO:
|
303 |
+
- determine whether or not it's necessary and/or OK to set a timeout in the AJAX case
|
304 |
+
- determine if it's OK in the IFRAME case to do the location back before this timeout is set
|
305 |
+
*/
|
306 |
+
}
|
307 |
+
|
308 |
+
function _handleSingleRequest (_request) {
|
309 |
+
if (_this._getCachedResponse (_request)) {
|
310 |
+
_cleanFromQueue ();
|
311 |
+
} else {
|
312 |
+
_this.fire ({name:'Perform Request',request:_request});
|
313 |
+
/*?
|
314 |
+
Instance Events
|
315 |
+
Perform Request
|
316 |
+
The =Perform Request= instance event fires each time before a request is performed - for both single requests as well as batch requests. The event object contains a "request" property, which is a reference to the request object for the request about to be performed.
|
317 |
+
*/
|
318 |
+
_this.performRequest (
|
319 |
+
_request,
|
320 |
+
function () {
|
321 |
+
_request.completed = _true;
|
322 |
+
_cleanFromQueue ();
|
323 |
+
}
|
324 |
+
);
|
325 |
+
}
|
326 |
+
}
|
327 |
+
|
328 |
+
if (_requestQueueLength == 1) {
|
329 |
+
_handleSingleRequest (_requestQueue [0]);
|
330 |
+
} else {
|
331 |
+
var _requestsToBatch = [];
|
332 |
+
|
333 |
+
/*** determine list of requests to batch ***/
|
334 |
+
var _batchingAgent;
|
335 |
+
for (var _requestNo = -1; ++_requestNo < _requestQueueLength;) {
|
336 |
+
var
|
337 |
+
_request = _requestQueue [_requestNo],
|
338 |
+
_requestBatchingAgent = _request.batchingAgent
|
339 |
+
;
|
340 |
+
if (
|
341 |
+
!_requestBatchingAgent ||
|
342 |
+
(_batchingAgent && _requestBatchingAgent != _batchingAgent) ||
|
343 |
+
_request.cache == 'browser'
|
344 |
+
) {
|
345 |
+
break;
|
346 |
+
} else {
|
347 |
+
if (!_batchingAgent)
|
348 |
+
_batchingAgent = _requestBatchingAgent
|
349 |
+
;
|
350 |
+
_requestsToBatch.push (_request);
|
351 |
+
}
|
352 |
+
}
|
353 |
+
|
354 |
+
var _requestsToBatchLength = _requestsToBatch.length;
|
355 |
+
if (_requestsToBatchLength > 1) {
|
356 |
+
/*** handle batch request ***/
|
357 |
+
/*** find all the requests in the batch that aren't already memory cached ***/
|
358 |
+
var _requestsInBatchRequest = [];
|
359 |
+
for (var _requestNo = -1; ++_requestNo < _requestsToBatchLength;) {
|
360 |
+
var _request = _requestsToBatch [_requestNo];
|
361 |
+
if (!_this._getCachedResponse (_request)) {
|
362 |
+
_request.completed = _false;
|
363 |
+
_requestsInBatchRequest.push (_request);
|
364 |
+
}
|
365 |
+
}
|
366 |
+
|
367 |
+
/*** perform batch request and handle responses ***/
|
368 |
+
var _requestsInBatchRequestLength = _requestsInBatchRequest.length;
|
369 |
+
if (_requestsInBatchRequestLength) {
|
370 |
+
if (_requestsInBatchRequestLength == 1) {
|
371 |
+
_handleSingleRequest (_requestsInBatchRequest [0]);
|
372 |
+
} else {
|
373 |
+
/* NOTE:
|
374 |
+
only package up as a batch request if there turn out to be more than one non-cached requests
|
375 |
+
*/
|
376 |
+
var _batchRequest = _batchingAgent.buildRequest (_requestsInBatchRequest);
|
377 |
+
_this.fire ({name:'Perform Request',request:_batchRequest});
|
378 |
+
_this.performRequest (
|
379 |
+
_batchRequest,
|
380 |
+
function () {
|
381 |
+
var
|
382 |
+
_batchResponses = _batchingAgent.responseParser (_batchRequest),
|
383 |
+
_batchResponseNo = 0
|
384 |
+
;
|
385 |
+
for (var _requestNo = -1; ++_requestNo < _requestsToBatchLength;) {
|
386 |
+
var _request = _requestsToBatch [_requestNo];
|
387 |
+
if (_request.completed !== _undefined) {
|
388 |
+
_request [_getResponsePropertyNameForRequest (_request)] =
|
389 |
+
_batchResponses [_batchResponseNo++]
|
390 |
+
;
|
391 |
+
_request.completed = _true;
|
392 |
+
}
|
393 |
+
}
|
394 |
+
_cleanFromQueue ();
|
395 |
+
}
|
396 |
+
);
|
397 |
+
}
|
398 |
+
} else {
|
399 |
+
_cleanFromQueue ();
|
400 |
+
}
|
401 |
+
} else {
|
402 |
+
/*** handle single request ***/
|
403 |
+
_handleSingleRequest (_requestQueue [0]);
|
404 |
+
}
|
405 |
+
}
|
406 |
+
}
|
407 |
+
};
|
408 |
+
|
409 |
+
/*** Public Static Methods ***/
|
410 |
+
_class.processArrayAsync = function (_elements,_processElementAsync,_completion,_direction) {
|
411 |
+
if (!_direction) _direction = 1;
|
412 |
+
var
|
413 |
+
_elementsLengthMinus1 = _elements.length - 1,
|
414 |
+
_elementNo = (_direction > 0 ? 0 : _elementsLengthMinus1) - _direction
|
415 |
+
;
|
416 |
+
function _processNextElement (_mustContinue) {
|
417 |
+
(_elementNo += _direction) >= 0 && _elementNo <= _elementsLengthMinus1 && _mustContinue !== _false
|
418 |
+
? _processElementAsync (_elements [_elementNo],_processNextElement,_elementNo)
|
419 |
+
: _completion ? _completion (_elementsLengthMinus1 + 1) : 0
|
420 |
+
}
|
421 |
+
_processNextElement ();
|
422 |
+
/*?
|
423 |
+
Static Methods
|
424 |
+
Uize.Comm.processArrayAsync
|
425 |
+
A method that facilitates asynchronous iteration through and processing of the elements of an array.
|
426 |
+
|
427 |
+
SYNTAX
|
428 |
+
...................................................................................
|
429 |
+
Uize.Comm.processArrayAsync (elementsARRAY,processElementAsyncFUNC,completionFUNC);
|
430 |
+
...................................................................................
|
431 |
+
|
432 |
+
While asynchronous, the array specified by the =elementsARRAY= parameter is guaranteed to be iterated through sequentially. This method is useful for iterating through the elements of an array and using an asynchronous communication protocol, such as Ajax, in the processing of the elements.
|
433 |
+
|
434 |
+
The function you specify in the =processElementAsyncFUNC= parameter should be of the form...
|
435 |
+
|
436 |
+
......................................................................................
|
437 |
+
myAsyncElementProcessor (elementToProcessANYTYPE,processNextElementFUNC,elementNoINT);
|
438 |
+
......................................................................................
|
439 |
+
|
440 |
+
The value of the =elementToProcessANYTYPE= parameter will be the value of each successive element in the array that is being iterated through. In order to inform the =Uize.Comm.processArrayAsync= method that the asynchronous processing of the current element has been completed so that it can continue on with the iteration, the function specified by the =processNextElementFUNC= parameter should be called. This function does not need to be called with any parameters. However, if you call it with the value =false=, then the iteration will be terminated and any function that you specified for the =completionFUNC= parameter will be called.
|
441 |
+
|
442 |
+
Your processor function can optionally declare an =elementNoINT= parameter, to receive the array index of the current element being processed. This might be useful if you need to index into other corresponding support data structures, or use the number as part of the construction of some string or such. Naturally, your own element processor function can name these three parameters whatever it likes.
|
443 |
+
|
444 |
+
If you specified a value for the optional =completionFUNC= parameter, then your completion function will be called once the iteration is completed, with one parameter, being the length of the array that was processed.
|
445 |
+
|
446 |
+
TYPICAL USAGE SKELETON
|
447 |
+
...................................................................
|
448 |
+
Uize.Comm.processArrayAsync (
|
449 |
+
_elementsToIterateThrough,
|
450 |
+
function (_currentElement,_continueIterating) {
|
451 |
+
_doSomethingAsynchronous (
|
452 |
+
function () { // the callback for _doSomethingAsynchronous
|
453 |
+
// further processing of element
|
454 |
+
_continueIterating ();
|
455 |
+
}
|
456 |
+
);
|
457 |
+
},
|
458 |
+
function () {
|
459 |
+
// done iterating, wrap it all up
|
460 |
+
}
|
461 |
+
);
|
462 |
+
...................................................................
|
463 |
+
|
464 |
+
EXAMPLE
|
465 |
+
........................................................................................
|
466 |
+
var imagesInfoHtml = '';
|
467 |
+
Uize.Comm.processArrayAsync (
|
468 |
+
myPhotoStream.getImageIds (),
|
469 |
+
function (_imageId,_addInfoHtmlForNextImage) {
|
470 |
+
myAjaxCommObject.request ({
|
471 |
+
url:'/svc/getimageinfo?id=' + _imageId,
|
472 |
+
returnType:'json',
|
473 |
+
requestMethod:'GET',
|
474 |
+
callback:function (resonseJson) {
|
475 |
+
imagesInfoHtml +=
|
476 |
+
'title: ' + resonseJson.title + '<br/>' +
|
477 |
+
'description: ' + resonseJson.description + '<br/>' +
|
478 |
+
'dimensions: ' + resonseJson.width + 'x' + resonseJson.height + '<br/>' +
|
479 |
+
'<hr/>'
|
480 |
+
;
|
481 |
+
_addInfoHtmlForNextImage ();
|
482 |
+
}
|
483 |
+
});
|
484 |
+
},
|
485 |
+
function () {
|
486 |
+
Uize.Node.setInnerHtml ('imagesInfo',imagesInfoHtml);
|
487 |
+
}
|
488 |
+
);
|
489 |
+
........................................................................................
|
490 |
+
|
491 |
+
In this fictitious example, =Uize.Comm.processArrayAsync= is being used to iterate through an array of image IDs for a photo stream.
|
492 |
+
|
493 |
+
On each iteration, the processor function performs an asynchronous request, using an instance of =Uize.Comm.Ajax=, to the service "/svc/getimageinfo" in order to get info for each image. When the Ajax request returns with the image info, the callback registered for the request uses the image info to build image info HTML for the entire photo stream. After adding to the HTML string, the continuation function is called in order to continue the iteration. Once all the image IDs have been processed, the completion function is called, which spits out the constructed info HTML into the page.
|
494 |
+
|
495 |
+
One thing that this example demonstrates is that the parameters that your element processor function receives can be named to be semantically suitable to your application.
|
496 |
+
|
497 |
+
VARIATION 1
|
498 |
+
....................................................................
|
499 |
+
Uize.Comm.processArrayAsync (
|
500 |
+
elementsARRAY,processElementAsyncFUNC,completionFUNC,directionINT
|
501 |
+
);
|
502 |
+
....................................................................
|
503 |
+
|
504 |
+
The optional =directionINT= parameter lets you specify the increment (and, therefore, direction) of the asynchronous loop. By default, this method loops forward through the array - from the first element to the last element. Specifying a value of =-1= for the =directionINT= parameter will cause the iteration to start from the last element of the array and loop towards the first element - one element at a time. Specifying a value of =-2= will also result in a reverse loop, but will iterate backwards two elements at a time.
|
505 |
+
|
506 |
+
VARIATION 2
|
507 |
+
....................................................................
|
508 |
+
Uize.Comm.processArrayAsync (elementsARRAY,processElementAsyncFUNC);
|
509 |
+
....................................................................
|
510 |
+
|
511 |
+
When the optional =completionFUNC= parameter is not specified, then the caller of this method will not be notified when the process has been completed.
|
512 |
+
*/
|
513 |
+
};
|
514 |
+
|
515 |
+
return _class;
|
516 |
+
}
|
517 |
+
});
|
518 |
+
|
skin/frontend/default/customproduct/js/Uize.Cookie.js
ADDED
@@ -0,0 +1,115 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Cookie Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2005-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 2
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 20
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Cookie= module is a package under the =Uize= namespace, and provides a couple of methods for managing browser cookies.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
*/
|
26 |
+
|
27 |
+
Uize.module ({
|
28 |
+
name:'Uize.Cookie',
|
29 |
+
builder:function () {
|
30 |
+
/*** Variables for Scruncher Optimization ***/
|
31 |
+
var
|
32 |
+
_undefined,
|
33 |
+
_null = null,
|
34 |
+
_package = function () {}
|
35 |
+
;
|
36 |
+
|
37 |
+
/*** Public Static Methods ***/
|
38 |
+
_package.setCookie = function (_name,_value,_path,_expiration) {
|
39 |
+
if (_value === _undefined || _value == _null) {
|
40 |
+
_value = '';
|
41 |
+
_expiration = 'Mon, 1 Jan 1990 12:00:00 UTC';
|
42 |
+
} else {
|
43 |
+
if (_expiration === _undefined) {
|
44 |
+
var _expirationDate = new Date;
|
45 |
+
_expirationDate.setFullYear (_expirationDate.getFullYear () + 1);
|
46 |
+
_expiration = _expirationDate.toGMTString ();
|
47 |
+
}
|
48 |
+
}
|
49 |
+
document.cookie = escape (_name) + '=' + escape (_value) + ';' + ((_path !== _undefined && _path != _null) ? ('path=' + _path + ';') : '') + ((_expiration !== _null) ? ('expires=' + _expiration + ';') : '');
|
50 |
+
/*?
|
51 |
+
Static Methods
|
52 |
+
Uize.Cookie.setCookie
|
53 |
+
SYNTAX
|
54 |
+
...........................................................................
|
55 |
+
Uize.Cookie.setCookie (cookieNameSTR,cookieValueSTR,pathSTR,expirationSTR);
|
56 |
+
...........................................................................
|
57 |
+
|
58 |
+
VARIATIONS
|
59 |
+
|
60 |
+
.............................................................
|
61 |
+
Uize.Cookie.setCookie (cookieNameSTR,cookieValueSTR,pathSTR);
|
62 |
+
.............................................................
|
63 |
+
|
64 |
+
When no =expirationSTR= parameter is specified, the expiration will be set to one year from the time that the cookie value is set.
|
65 |
+
|
66 |
+
.....................................................
|
67 |
+
Uize.Cookie.setCookie (cookieNameSTR,cookieValueSTR);
|
68 |
+
.....................................................
|
69 |
+
|
70 |
+
When no =pathSTR= parameter is specified, then the path of the current page being used.
|
71 |
+
|
72 |
+
......................................
|
73 |
+
Uize.Cookie.setCookie (cookieNameSTR);
|
74 |
+
......................................
|
75 |
+
|
76 |
+
When only a =cookieNameSTR= parameter is specified, the cookie specified by that parameter will be cleared.
|
77 |
+
*/
|
78 |
+
};
|
79 |
+
|
80 |
+
_package.getCookie = function (_name) {
|
81 |
+
var
|
82 |
+
_value = '',
|
83 |
+
_cookieStr = document.cookie
|
84 |
+
;
|
85 |
+
if (typeof _cookieStr == 'string') {
|
86 |
+
_cookieStr = _cookieStr.replace (/ /g,'');
|
87 |
+
for (
|
88 |
+
var _cookieNo = -1, _cookies = _cookieStr.split (';'), _cookiesLength = _cookies.length;
|
89 |
+
++_cookieNo < _cookiesLength;
|
90 |
+
) {
|
91 |
+
var _cookie = _cookies [_cookieNo].split ('=');
|
92 |
+
if (unescape (_cookie [0]) == _name) {
|
93 |
+
_value = (typeof _cookie [1] == 'string') ? unescape (_cookie [1]) : '';
|
94 |
+
break;
|
95 |
+
}
|
96 |
+
}
|
97 |
+
}
|
98 |
+
return _value;
|
99 |
+
/*?
|
100 |
+
Static Methods
|
101 |
+
Uize.Cookie.getCookie
|
102 |
+
SYNTAX
|
103 |
+
.......................................................
|
104 |
+
cookieValueSTR = Uize.Cookie.getCookie (cookieNameSTR);
|
105 |
+
.......................................................
|
106 |
+
|
107 |
+
NOTES
|
108 |
+
- if there is no cookie stored by the specified name, then an empty string will be returned
|
109 |
+
*/
|
110 |
+
};
|
111 |
+
|
112 |
+
return _package;
|
113 |
+
}
|
114 |
+
});
|
115 |
+
|
skin/frontend/default/customproduct/js/Uize.Curve.Mod.js
ADDED
@@ -0,0 +1,522 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Curve.Mod Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2009-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 4
|
15 |
+
codeCompleteness: 90
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Curve.Mod= module defines various curve function modifiers, to enable creation of new curve functions by combining existing curve functions.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
In A Nutshell
|
27 |
+
Curve function modifiers are curve function generators that accept curve functions as their primary inputs.
|
28 |
+
|
29 |
+
The =Uize.Curve.Mod= module provides a good selection of these curve function modifiers. Curve function modifiers operate on the curve functions they are provided in order to produce new, modified curve functions. You can consider them as operators that operate on curve functions to produce new curve functions. They could also be thought of as specialized parameterized curve function generators, where some - or all - of the parameters just happen to be curve functions. As an example, the =Uize.Curve.Mod.blend= static method blends the two specified curve functions to produce a new curve function, with blend parameters that let you specify the blend between the two curve functions.
|
30 |
+
|
31 |
+
"What does it mean to blend two functions?" you may ask. No, JavaScript doesn't support some crazy new math that allows you to add or multiply functions. Blending two curve functions is carried out by returning a new curve function that takes an input value, uses each of the two curve functions that are to be blended and obtains a remapped value from each, then blends between those two values to produce a new output value. This has the effect of blending the curves that would be produced by the two curve functions that are being blended - across their entire input value range. So, effectively, you are blending two curve functions to produce a new curve function.
|
32 |
+
|
33 |
+
EXAMPLE
|
34 |
+
..............................................
|
35 |
+
// quickly to middle, hesitate, quickly to end
|
36 |
+
|
37 |
+
Uize.Curve.Mod.blend (
|
38 |
+
Uize.Curve.easeInSweetPow (1/6),
|
39 |
+
Uize.Curve.easeOutSweetPow (1/12),
|
40 |
+
Uize.Curve.line (0,1)
|
41 |
+
)
|
42 |
+
..............................................
|
43 |
+
|
44 |
+
In the above example, the curve function generated by the statement =Uize.Curve.easeInSweetPow (1/6)= is being blended with the curve function generated by the statement =Uize.Curve.easeOutSweetPow (1/12)=, with the blend biased towards the first curve function at the lower input values, and biased towards the second curve function at the higher input values.
|
45 |
+
|
46 |
+
VISUALIZE IT
|
47 |
+
|
48 |
+
To better visualize how curve function modifiers work and how they affect motion, visit the interactive [[../examples/curve-explorer.html][Curve Explorer]] tool.
|
49 |
+
|
50 |
+
BACKGROUND READING
|
51 |
+
|
52 |
+
For an in-depth discussion on animation in the UIZE JavaScript Framework, and for a discussion on how this module fits into the larger picture, consult the explainer [[../explainers/javascript-animation-and-effects.html][JavaScript Animation and Effects]] and read through the section `Curves`.
|
53 |
+
*/
|
54 |
+
|
55 |
+
Uize.module ({
|
56 |
+
name:'Uize.Curve.Mod',
|
57 |
+
builder:function (_host) {
|
58 |
+
/*** Variables for Scruncher Optimization ***/
|
59 |
+
var
|
60 |
+
_package = function () {},
|
61 |
+
_undefined,
|
62 |
+
_blendFloats = _host.blendFloats,
|
63 |
+
_resolve = _host.resolve,
|
64 |
+
_linear = _host.linear
|
65 |
+
;
|
66 |
+
|
67 |
+
/*** Public Static Methods ***/
|
68 |
+
_package.band = function (_curveFunction,_sizeX,_alignX,_sizeY,_alignY) {
|
69 |
+
_curveFunction = _resolve (_curveFunction);
|
70 |
+
if (_sizeY == _undefined) _sizeY = 1;
|
71 |
+
var
|
72 |
+
_startX = (1 - _sizeX) * (_alignX || 0),
|
73 |
+
_endX = _startX + _sizeX,
|
74 |
+
_startY = (1 - _sizeY) * (_alignY || 0),
|
75 |
+
_endY = _startY + _sizeY
|
76 |
+
;
|
77 |
+
return (
|
78 |
+
_sizeX == 1 && _sizeY == 1
|
79 |
+
? _curveFunction
|
80 |
+
: !_sizeY
|
81 |
+
? function () {return _startY}
|
82 |
+
: !_sizeX
|
83 |
+
? function (_value) {return _value < _startX ? _startY : _endY}
|
84 |
+
: function (_value) {
|
85 |
+
return _startY + _sizeY * (
|
86 |
+
_value < _startX ? 0 : _value > _endX ? 1 : _curveFunction ((_value - _startX) / _sizeX)
|
87 |
+
)
|
88 |
+
}
|
89 |
+
);
|
90 |
+
/*?
|
91 |
+
Static Methods
|
92 |
+
Uize.Curve.Mod.band
|
93 |
+
Returns a curve function, that is the specified source curve function compressed into the specified horizontal and vertical band.
|
94 |
+
|
95 |
+
SYNTAX
|
96 |
+
.................................................................................
|
97 |
+
curveFUNC = Uize.Curve.Mod.band (
|
98 |
+
curveFUNCorFLOAT,sizeX0to1FLOAT,alignX0to1FLOAT,sizeY0to1FLOAT,alignY0to1FLOAT
|
99 |
+
);
|
100 |
+
.................................................................................
|
101 |
+
|
102 |
+
Parameters
|
103 |
+
curveFUNCorFLOAT
|
104 |
+
A function reference for a curve function, or a numerical value that will be resolved to a power curve function using the =Uize.Curve.resolve= method, specifying the source curve function that should be compressed into the specified band.
|
105 |
+
|
106 |
+
For a linear curve, the value =1= can be specified for this parameter.
|
107 |
+
|
108 |
+
sizeX0to1FLOAT
|
109 |
+
A floating point number in the range of =0= to =1=, specifying the width of the horizontal band.
|
110 |
+
|
111 |
+
alignX0to1FLOAT
|
112 |
+
A floating point number in the range of =0= to =1=, specifying the horizontal alignment of the band.
|
113 |
+
|
114 |
+
The value =0= represents left aligned, the value =.5= represents center aligned, and the value =1= represents right aligned. Other values between =0= and =1= represent continuous horizontal alignment between left and right. When the value =1= is specified for the =sizeX0to1FLOAT= parameter, then the =alignX0to1FLOAT= parameter has no effect.
|
115 |
+
|
116 |
+
sizeY0to1FLOAT
|
117 |
+
A floating point number in the range of =0= to =1=, specifying the height of the vertical band.
|
118 |
+
|
119 |
+
alignY0to1FLOAT
|
120 |
+
A floating point number in the range of =0= to =1=, specifying the vertical alignment of the band.
|
121 |
+
|
122 |
+
The value =0= represents bottom aligned, the value =.5= represents center aligned, and the value =1= represents top aligned. Other values between =0= and =1= represent continuous vertical alignment between bottom and top. When the value =1= is specified for the =sizeY0to1FLOAT= parameter, then the =alignY0to1FLOAT= parameter has no effect.
|
123 |
+
|
124 |
+
VARIATION
|
125 |
+
..................................................................................
|
126 |
+
curveFUNC = Uize.Curve.Mod.band (curveFUNCorFLOAT,sizeX0to1FLOAT,alignX0to1FLOAT);
|
127 |
+
..................................................................................
|
128 |
+
|
129 |
+
When the =sizeY0to1FLOAT= and =alignY0to1FLOAT= parameters are not specified, then no vertical banding will be performed. This is equivalent to specifying the value =1= for the =sizeY0to1FLOAT= parameter. In order to only perform vertical banding and no horizontal banding, you can specify the value =1= for the =sizeX0to1FLOAT= parameter.
|
130 |
+
|
131 |
+
NOTES
|
132 |
+
- numerical values for the =curveFUNCorFLOAT= parameter are resolved to curve functions using the =Uize.Curve.resolve= static method
|
133 |
+
*/
|
134 |
+
};
|
135 |
+
|
136 |
+
_package.bend = function (_curveFunction,_horizontalBend,_verticalBend) {
|
137 |
+
_curveFunction = _resolve (_curveFunction);
|
138 |
+
var
|
139 |
+
_horizontalBendIsLinear = (_horizontalBend = _resolve (_horizontalBend,0,false,-1)) == _linear,
|
140 |
+
_verticalBendIsLinear = (_verticalBend = _resolve (_verticalBend,0)) == _linear
|
141 |
+
;
|
142 |
+
return (
|
143 |
+
_horizontalBendIsLinear && _verticalBendIsLinear
|
144 |
+
? _curveFunction
|
145 |
+
: !_horizontalBendIsLinear && !_verticalBendIsLinear
|
146 |
+
? function (_value) {return _verticalBend (_curveFunction (_horizontalBend (_value)))}
|
147 |
+
: _horizontalBendIsLinear
|
148 |
+
? function (_value) {return _verticalBend (_curveFunction (_value))}
|
149 |
+
: function (_value) {return _curveFunction (_horizontalBend (_value))}
|
150 |
+
);
|
151 |
+
/*?
|
152 |
+
Static Methods
|
153 |
+
Uize.Curve.Mod.bend
|
154 |
+
Returns a curve function, that is the specified source curve function bent in the specified manner in the x- and y-axes.
|
155 |
+
|
156 |
+
SYNTAX
|
157 |
+
.....................................................................................
|
158 |
+
curveFUNC = Uize.Curve.Mod.bend (curveFUNCorFLOAT,bendXFUNCorFLOAT,bendYFUNCorFLOAT);
|
159 |
+
.....................................................................................
|
160 |
+
|
161 |
+
Parameters
|
162 |
+
curveFUNCorFLOAT
|
163 |
+
A function reference for a curve function, or a numerical value that will be resolved to a power curve function using the =Uize.Curve.resolve= method.
|
164 |
+
|
165 |
+
For a linear curve, the value =1= can be specified for this parameter.
|
166 |
+
|
167 |
+
bendXFUNCorFLOAT
|
168 |
+
A function reference for a curve function, or a numerical value that will be resolved to a power curve function using the =Uize.Curve.resolve= method.
|
169 |
+
|
170 |
+
Values less than -1 will bend the curve towards the left. Values greater than =1= will bend the curve towards the right. When the value =null=, =undefined=, =1=, =0=, =-1=, or =Uize.Curve.linear= is specified, then there will be no bending in the x-axis. If a curve function is specified for =bendXFUNCorFLOAT=, then the source curve function will be bent horizontally according to the nature of the specified bend curve. An ease-in-out bend curve will pinch the source curve function towards the center horizontally. An ease-in-the-middle bend curve will squash the source curve function outwards horizontally towards the left and right sides.
|
171 |
+
|
172 |
+
bendYFUNCorFLOAT
|
173 |
+
A function reference for a curve function, or a numerical value that will be resolved to a power curve function using the =Uize.Curve.resolve= method.
|
174 |
+
|
175 |
+
Values less than -1 will bend the curve towards the bottom. Values greater than =1= will bend the curve towards the top. When the value =null=, =undefined=, =1=, =0=, =-1=, or =Uize.Curve.linear= is specified, then there will be no bending in the y-axis. If a curve function is specified for =bendYFUNCorFLOAT=, then the source curve function will be bent vertically according to the nature of the specified bend curve. An ease-in-out bend curve will pinch the source curve function towards the center vertically. An ease-in-the-middle bend curve will squash the source curve function outwards vertically towards the top and bottom sides.
|
176 |
+
|
177 |
+
VARIATION
|
178 |
+
....................................................................
|
179 |
+
curveFUNC = Uize.Curve.Mod.bend (curveFUNCorFLOAT,bendXFUNCorFLOAT);
|
180 |
+
....................................................................
|
181 |
+
|
182 |
+
When no =bendYFUNCorFLOAT= parameter is specified, there will be no bending in the y-axis.
|
183 |
+
|
184 |
+
NOTES
|
185 |
+
- numerical values for the =curveFUNCorFLOAT=, =bendXFUNCorFLOAT=, and =bendYFUNCorFLOAT= parameters are resolved to curve functions using the =Uize.Curve.resolve= static method
|
186 |
+
*/
|
187 |
+
};
|
188 |
+
|
189 |
+
_package.blend = function (_curveFunctionA,_curveFunctionB,_blend) {
|
190 |
+
if (_blend == _undefined) _blend = .5;
|
191 |
+
|
192 |
+
return (
|
193 |
+
(_curveFunctionA = _resolve (_curveFunctionA)) == (_curveFunctionB = _resolve (_curveFunctionB))
|
194 |
+
? _curveFunctionA
|
195 |
+
: _blend == .5
|
196 |
+
? function (_value) {return (_curveFunctionA (_value) + _curveFunctionB (_value)) / 2}
|
197 |
+
: Uize.isFunction (_blend)
|
198 |
+
?
|
199 |
+
function (_value) {
|
200 |
+
return _blendFloats (_curveFunctionA (_value),_curveFunctionB (_value),_blend (_value));
|
201 |
+
}
|
202 |
+
:
|
203 |
+
function (_value) {
|
204 |
+
return _blendFloats (_curveFunctionA (_value),_curveFunctionB (_value),_blend);
|
205 |
+
}
|
206 |
+
);
|
207 |
+
/*?
|
208 |
+
Static Methods
|
209 |
+
Uize.Curve.Mod.blend
|
210 |
+
Returns a curve function, that is a blend between the two specified source curve functions.
|
211 |
+
|
212 |
+
SYNTAX
|
213 |
+
......................................................................................
|
214 |
+
curveFUNC = Uize.Curve.Mod.blend (curve1FUNCorFLOAT,curve2FUNCorFLOAT,blend0to1FLOAT);
|
215 |
+
......................................................................................
|
216 |
+
|
217 |
+
When the value =0= is specified for the =blend0to1FLOAT= parameter, then the curve function
|
218 |
+
specified by the =curve1FUNCorFLOAT= parameter will be returned. Similarly, when the value =1= is specified, then the curve function specified by the =curve2FUNCorFLOAT= parameter will be returned. When the value =.5= is specified, the returned curve function will be an equal blend between the two specified source curve functions.
|
219 |
+
|
220 |
+
VARIATION 1
|
221 |
+
.......................................................................
|
222 |
+
curveFUNC = Uize.Curve.Mod.blend (curve1FUNCorFLOAT,curve2FUNCorFLOAT);
|
223 |
+
.......................................................................
|
224 |
+
|
225 |
+
When no =blend0to1FLOAT= parameter is specified, then the value =.5= will be used as the default for this parameter and the two curve functions specified by the =curve1FUNCorFLOAT= and =curve2FUNCorFLOAT= parameters will be blended equally.
|
226 |
+
|
227 |
+
VARIATION 2
|
228 |
+
......................................................................................
|
229 |
+
curveFUNC = Uize.Curve.Mod.blend (curve1FUNCorFLOAT,curve2FUNCorFLOAT,blendCurveFUNC);
|
230 |
+
......................................................................................
|
231 |
+
|
232 |
+
When the =blendCurveFUNC= parameter is specified in place of the =blend0to1FLOAT= parameter, then the blend between the two curve functions can vary across the range of input values. Consider the following example...
|
233 |
+
|
234 |
+
EXAMPLE
|
235 |
+
........................................................................
|
236 |
+
Uize.Curve.Mod.blend (
|
237 |
+
Uize.Curve.easeOutPow (4), // ease-out power curve function
|
238 |
+
Uize.Curve.saw (20,.5), // sawtooth curve function with 20 teeth
|
239 |
+
Uize.Curve.line (.25,.75) // line starting at .25 and ending at .75
|
240 |
+
)
|
241 |
+
........................................................................
|
242 |
+
|
243 |
+
In the above example, a quartic ease-out power curve function is being blended with a sawtooth curve function with twenty teeth. The =Uize.Curve.line= method is being used to create a value range from =.25= to =.75= to control the blend between the two curve functions across the range of input values. At the input value of =0=, the blend between the curves will be =.25=. At the input value of =1=, the blend between the curves will be =.75=. At the input value of =.5=, the blend between the curves will be =.5= (the midpoint value of the line curve).
|
244 |
+
|
245 |
+
Encapsulating a Curve
|
246 |
+
One useful technique that can employ the =Uize.Curve.Mod.blend= method is to encapsulate one curve between two other curves.
|
247 |
+
|
248 |
+
Basically, if you view the curve specified by the =curve1FUNCorFLOAT= parameter as being the ventral side of a "capsule", and view the curve specified by the =curve2FUNCorFLOAT= parameter as being the dorsal side of a "capsule", then a curve specified by the =blendCurveFUNC= parameter will essentially be fitted inbetween those two curves.
|
249 |
+
|
250 |
+
EXAMPLE
|
251 |
+
.............................................
|
252 |
+
// bouncing down the stairs
|
253 |
+
|
254 |
+
Uize.Curve.Mod.blend (
|
255 |
+
Uize.Curve.easeInPow (3),
|
256 |
+
Uize.Curve.easeOutPow (1.5),
|
257 |
+
Uize.Curve.Rubber.easeOutBounce (10,4,1.1)
|
258 |
+
)
|
259 |
+
.............................................
|
260 |
+
|
261 |
+
The above expression generates a curve function that can be used to produce a bouncing-down-the-stairs type of effect. The ease-out bounce curve is being encapsulated between the ease-in power curve and the ease-out power curve.
|
262 |
+
|
263 |
+
NOTES
|
264 |
+
- numerical values for the =curve1FUNCorFLOAT= and =curve2FUNCorFLOAT= parameters are resolved to curve functions using the =Uize.Curve.resolve= static method
|
265 |
+
*/
|
266 |
+
};
|
267 |
+
|
268 |
+
_package.multiply = function (_curveFunctionA,_curveFunctionB) {
|
269 |
+
_curveFunctionA = _resolve (_curveFunctionA);
|
270 |
+
_curveFunctionB = _resolve (_curveFunctionB);
|
271 |
+
return function (_value) {return _curveFunctionA (_value) * _curveFunctionB (_value)}
|
272 |
+
/*?
|
273 |
+
Static Methods
|
274 |
+
Uize.Curve.Mod.multiply
|
275 |
+
Returns a curve function, that is the two specified source curve functions multiplied together.
|
276 |
+
|
277 |
+
SYNTAX
|
278 |
+
..........................................................................
|
279 |
+
curveFUNC = Uize.Curve.Mod.multiply (curve1FUNCorFLOAT,curve2FUNCorFLOAT);
|
280 |
+
..........................................................................
|
281 |
+
|
282 |
+
Because curve functions produce values in the scale of =0= to =1=, multiplying two curve functions together will tend to produce a new curve function that bends downwards more extremely.
|
283 |
+
|
284 |
+
NOTES
|
285 |
+
- numerical values for the =curve1FUNCorFLOAT= and =curve2FUNCorFLOAT= parameters are resolved to curve functions using the =Uize.Curve.resolve= static method
|
286 |
+
*/
|
287 |
+
};
|
288 |
+
|
289 |
+
_package.quantize = function (_curveFunction,_steps,_stepCurveFunction) {
|
290 |
+
_curveFunction = _resolve (_curveFunction);
|
291 |
+
if (!_steps || _steps == Infinity) return _curveFunction;
|
292 |
+
if (typeof _stepCurveFunction == 'number') _stepCurveFunction = _package.band (1,0,_stepCurveFunction);
|
293 |
+
var _stepSize = 1 / _steps;
|
294 |
+
return function (_value) {
|
295 |
+
var _quantizedValue = Math.floor ((_value = _curveFunction (_value)) / _stepSize) * _stepSize;
|
296 |
+
return (
|
297 |
+
_stepCurveFunction
|
298 |
+
? _quantizedValue + _stepCurveFunction ((_value - _quantizedValue) / _stepSize) * _stepSize
|
299 |
+
: _quantizedValue
|
300 |
+
);
|
301 |
+
};
|
302 |
+
/*?
|
303 |
+
Static Methods
|
304 |
+
Uize.Curve.Mod.quantize
|
305 |
+
Returns a new curve function, that is the specified curve function that has been quantized to have the specified number of steps.
|
306 |
+
|
307 |
+
SYNTAX
|
308 |
+
................................................................
|
309 |
+
curveFUNC = Uize.Curve.Mod.quantize (curveFUNCorFLOAT,stepsINT);
|
310 |
+
................................................................
|
311 |
+
|
312 |
+
VARIATION 1
|
313 |
+
...................................................................................
|
314 |
+
curveFUNC = Uize.Curve.Mod.quantize (curveFUNCorFLOAT,stepsINT,stepAlign0to1FLOAT);
|
315 |
+
...................................................................................
|
316 |
+
|
317 |
+
By default, quantization steps stay at the low side of their output value range throughout their input value range. When the optional =stepAlign0to1FLOAT= parameter is specified, this behavior can be controlled. When the value =0= is specified, the step up to the next step is aligned to the left side of the input value range. When the value =1= is specified, the step up to the next step is aligned to the right side of the input value range. When the value =.5= is specified, the step up to the next step is aligned in the center of the input value range. Other values between =0= and =1= represent continuous horizontal alignment of the step up point between the left and right of each step's input value range.
|
318 |
+
|
319 |
+
VARIATION 2
|
320 |
+
..............................................................................
|
321 |
+
curveFUNC = Uize.Curve.Mod.quantize (curveFUNCorFLOAT,stepsINT,stepCurveFUNC);
|
322 |
+
..............................................................................
|
323 |
+
|
324 |
+
When the =stepCurveFUNC= parameter is specified in place of the =stepAlign0to1FLOAT= parameter, then the value distortion within the vertical quantization segment can be controlled. Ease-in-out curve functions can be used to squash the output values towards the top and bottom sides of the quantization segments, and ease-in-the-middle curve functions can be used to pinch the output values towards the center of the quantization segments. Needless to say, this is easier to visualize with a graph than describe with words.
|
325 |
+
|
326 |
+
NOTES
|
327 |
+
- compare to the =Uize.Curve.Mod.redraw= static method
|
328 |
+
- numerical values for the =curveFUNCorFLOAT= parameter are resolved to curve functions using the =Uize.Curve.resolve= static method
|
329 |
+
*/
|
330 |
+
};
|
331 |
+
|
332 |
+
_package.redraw = function (_curveFunction,_segments,_segmentCurveFunction,_alternatingRotate) {
|
333 |
+
_curveFunction = _resolve (_curveFunction);
|
334 |
+
if (!_segments || _segments == Infinity) return _curveFunction;
|
335 |
+
_segmentCurveFunction = _resolve (_segmentCurveFunction);
|
336 |
+
var _segmentSize = 1 / _segments;
|
337 |
+
return (
|
338 |
+
_segmentSize
|
339 |
+
? function (_value) {
|
340 |
+
var
|
341 |
+
_segmentNoFloat = _value / _segmentSize,
|
342 |
+
_segmentNo = Math.floor (_segmentNoFloat)
|
343 |
+
;
|
344 |
+
return _blendFloats (
|
345 |
+
_curveFunction (_segmentNo * _segmentSize),
|
346 |
+
_curveFunction (Math.ceil (_segmentNoFloat) * _segmentSize),
|
347 |
+
_alternatingRotate && _segmentNo % 2
|
348 |
+
? 1 - _segmentCurveFunction (1 - _segmentNoFloat + _segmentNo)
|
349 |
+
: _segmentCurveFunction (_segmentNoFloat - _segmentNo)
|
350 |
+
);
|
351 |
+
}
|
352 |
+
: _curveFunction
|
353 |
+
);
|
354 |
+
/*?
|
355 |
+
Static Methods
|
356 |
+
Uize.Curve.Mod.redraw
|
357 |
+
Returns a curve function, that is a redrawn version of the specified source curve function.
|
358 |
+
|
359 |
+
SYNTAX
|
360 |
+
.........................................................................................
|
361 |
+
curveFUNC = Uize.Curve.Mod.redraw (curveFUNCorFLOAT,segmentsINT,segmentCurveFUNCorFLOAT);
|
362 |
+
.........................................................................................
|
363 |
+
|
364 |
+
The =Uize.Curve.Mod.redraw= method divides the specified curve function into a number of segments in the x-axis, as specified by the =segmentsINT= parameter. It then redraws the curve between the ends of each segment by connecting the values at each end of a segment using the segment curve specified by the =segmentCurveFUNCorFLOAT= parameter. So, redraw is a little bit like quantization, but in the x-axis.
|
365 |
+
|
366 |
+
The =Uize.Curve.Mod.redraw= method removes detail from the original curve function and replaces it with new detail, as determined by the =segmentCurveFUNCorFLOAT= value. This method can have the effect of producing a simpler curve than the original, or producing a more complex curve. For example, a complex elastic curve function could be simplified by redrawing it using a small number of segments and replacing a lot of the complexity within those segments by redrawing using a simple linear segment curve function. On the other hand, a simple linear curve function could be made more complex by redrawing it using an elastic curve function for the segments.
|
367 |
+
|
368 |
+
VARIATION 1
|
369 |
+
.................................................................
|
370 |
+
curveFUNC = Uize.Curve.Mod.redraw (curveFUNCorFLOAT,segmentsINT);
|
371 |
+
.................................................................
|
372 |
+
|
373 |
+
When the =segmentCurveFUNCorFLOAT= parameter is not specified, then a linear curve function will be used for redrawing the segments.
|
374 |
+
|
375 |
+
VARIATION 2
|
376 |
+
.............................................................................
|
377 |
+
curveFUNC = Uize.Curve.Mod.redraw (
|
378 |
+
curveFUNCorFLOAT,segmentsINT,segmentCurveFUNCorFLOAT,alternatingRotateBOOL
|
379 |
+
);
|
380 |
+
.............................................................................
|
381 |
+
|
382 |
+
When the value =true= is specified for the optional =alternatingRotateBOOL= parameter, then each alternating segment will be redrawn with a 180 degree rotated version of the curve function specified by the =segmentCurveFUNCorFLOAT= parameter. In other words, the first segment will be normal, the second segment will be rotated, the third segment will be normal, the fourth segment will be rotated, etc.
|
383 |
+
|
384 |
+
NOTES
|
385 |
+
- compare to the =Uize.Curve.Mod.quantize= static method
|
386 |
+
- numerical values for the =curveFUNCorFLOAT= and =segmentCurveFUNCorFLOAT= parameters are resolved to curve functions using the =Uize.Curve.resolve= static method
|
387 |
+
*/
|
388 |
+
};
|
389 |
+
|
390 |
+
_package.repeat = function (_curveFunction,_repeats,_stairsDegree,_alternatingFlipHorz,_alternatingFlipVert) {
|
391 |
+
var
|
392 |
+
_curveFunctionLength = Uize.isArray (_curveFunction = _resolve (_curveFunction))
|
393 |
+
? _curveFunction.length
|
394 |
+
: 0,
|
395 |
+
_repeatHeight = _blendFloats (1,1 / _repeats,_stairsDegree || (_stairsDegree = 0))
|
396 |
+
;
|
397 |
+
return function (_value) {
|
398 |
+
var
|
399 |
+
_repeatNo = _value && Math.ceil (_value * _repeats) - 1,
|
400 |
+
_repeatPos = _repeatNo / _repeats,
|
401 |
+
_valueForRepeat = Uize.constrain ((_value - _repeatPos) * _repeats,0,1),
|
402 |
+
_isAlternate = _repeatNo % 2
|
403 |
+
;
|
404 |
+
_valueForRepeat =
|
405 |
+
(_curveFunctionLength ? _curveFunction [_repeatNo % _curveFunctionLength] : _curveFunction) (
|
406 |
+
_isAlternate && _alternatingFlipHorz ? 1 - _valueForRepeat : _valueForRepeat
|
407 |
+
)
|
408 |
+
;
|
409 |
+
if (_isAlternate && _alternatingFlipVert)
|
410 |
+
_valueForRepeat = 1 - _valueForRepeat
|
411 |
+
;
|
412 |
+
return (
|
413 |
+
_repeatNo == _repeats - 1 && _valueForRepeat == 1
|
414 |
+
? 1
|
415 |
+
: _repeatPos * _stairsDegree + _valueForRepeat * _repeatHeight
|
416 |
+
);
|
417 |
+
};
|
418 |
+
/*?
|
419 |
+
Static Methods
|
420 |
+
Uize.Curve.Mod.repeat
|
421 |
+
Returns a curve function, that is the specified curve function repeated the specified number of times.
|
422 |
+
|
423 |
+
SYNTAX
|
424 |
+
.......................................................................
|
425 |
+
curveFUNC = Uize.Curve.Mod.repeat (curveFUNCorFLOATorARRAY,repeatsINT);
|
426 |
+
.......................................................................
|
427 |
+
|
428 |
+
When an array is specified for the =curveFUNCorFLOATorARRAY= parameter, then the elements of the array should be curve functions, and these curve functions specified in the array will be cycled through for every successive repitition. There can be a different number of curve functions in the array than the value of the =repeatsINT= parameter. If the value of =repeatsINT= is greater than the length of the curve functions array, then the array will be cycled through more than once. If the value of =repeatsINT= is less than the length of array, then not all the curve functions in the array will be utilized.
|
429 |
+
|
430 |
+
VARIATION 1
|
431 |
+
...........................................................
|
432 |
+
curveFUNC = Uize.Curve.Mod.repeat (
|
433 |
+
curveFUNCorFLOATorARRAY,repeatsINT,stairsDegree0to1FLOAT
|
434 |
+
);
|
435 |
+
...........................................................
|
436 |
+
|
437 |
+
By default, the curve specified by the =curveFUNCorFLOATorARRAY= is repeated as thought it were a waveform, with each successive repitition occupying the full vertical range of =0= to =1=. Staircasing lets you stack the repititions along a diagonal line from left to right.
|
438 |
+
|
439 |
+
When the value =1= is specified for the =stairsDegree0to1FLOAT= parameter, the repititions are fully staircased, so that the top right of the previous repetition connects to the bottom left of the current repitition, allowing the curve line of the previous repitition to flow into the curve line of the next repitition. When ease-in-out or ease-in-the-middle curve functions are specified for the =curveFUNCorFLOATorARRAY= parameter, then the curve can be made seamless, because these types of curve functions are by design diagonally symmetrical.
|
440 |
+
|
441 |
+
When the value =0= is specified for the =stairsDegree0to1FLOAT= parameter, the repititions all occupy the full vertical range of =0= to =1=. This is the default behavior. Other values between =0= and =1= represent continuous degrees of staircasing, between no staircasing and complete staircasing.
|
442 |
+
|
443 |
+
VARIATION 2
|
444 |
+
...................................................................................
|
445 |
+
curveFUNC = Uize.Curve.Mod.repeat (
|
446 |
+
curveFUNCorFLOATorARRAY,repeatsINT,stairsDegree0to1FLOAT,alternatingFlipHorzBOOL
|
447 |
+
);
|
448 |
+
...................................................................................
|
449 |
+
|
450 |
+
When the optional =alternatingFlipHorzBOOL= parameter is specified, horizontal flipping for alternate repititions can be controlled. When the value =true= is specified for this parameter, the first repitition will be normal, the second repitition will be flipped, the third repitition will be normal, the fourth repitition will be flipped, etc.
|
451 |
+
|
452 |
+
VARIATION 3
|
453 |
+
...................................
|
454 |
+
curveFUNC = Uize.Curve.Mod.repeat (
|
455 |
+
curveFUNCorFLOATorARRAY,
|
456 |
+
repeatsINT,
|
457 |
+
stairsDegree0to1FLOAT,
|
458 |
+
alternatingFlipHorzBOOL,
|
459 |
+
alternatingFlipVertBOOL
|
460 |
+
);
|
461 |
+
...................................
|
462 |
+
|
463 |
+
When the optional =alternatingFlipVertBOOL= parameter is specified, vertical flipping for alternate repititions can be controlled. When the value =true= is specified for this parameter, the first repitition will be normal, the second repitition will be flipped, the third repitition will be normal, the fourth repitition will be flipped, etc. If you specify the value =true= for both the =alternatingFlipHorzBOOL= and =alternatingFlipVertBOOL= parameters, then alternating repititions will be rotated 180 degrees.
|
464 |
+
|
465 |
+
IMPORTANT
|
466 |
+
|
467 |
+
When not specifying the same value for both the =alternatingFlipHorzBOOL= and =alternatingFlipVertBOOL= parameters, you should be sure to specify an odd number for the =repeatsINT= parameter. Otherwise, you won't be able to guanrantee that the resulting curve function will end at the value =1=. By specifying an odd number of repeats you ensure that the last repitition will not be flipped horizontally or vertically, since only the alternating repititions are flipped.
|
468 |
+
|
469 |
+
NOTES
|
470 |
+
- numerical values for the =curveFUNCorFLOATorARRAY= parameter are resolved to curve functions using the =Uize.Curve.resolve= static method
|
471 |
+
*/
|
472 |
+
};
|
473 |
+
|
474 |
+
_package.rotate = function (_curveFunction,_blendOfRotated) {
|
475 |
+
_curveFunction = _resolve (_curveFunction);
|
476 |
+
return (
|
477 |
+
_blendOfRotated == _undefined || _blendOfRotated == 1
|
478 |
+
? _host.makeEaseOut (_curveFunction)
|
479 |
+
: _blendOfRotated
|
480 |
+
? function (_value) {
|
481 |
+
return _blendFloats (_curveFunction (_value),1 - _curveFunction (1 - _value),_blendOfRotated)
|
482 |
+
}
|
483 |
+
: _curveFunction
|
484 |
+
)
|
485 |
+
/*?
|
486 |
+
Static Methods
|
487 |
+
Uize.Curve.Mod.rotate
|
488 |
+
Returns a curve function, that is the 180 degree rotated version of the specified source curve function, or a blend between the specified curve function and the 180 degree rotated version of it.
|
489 |
+
|
490 |
+
SYNTAX
|
491 |
+
.....................................................
|
492 |
+
curveFUNC = Uize.Curve.Mod.rotate (curveFUNCorFLOAT);
|
493 |
+
.....................................................
|
494 |
+
|
495 |
+
VARIATION
|
496 |
+
.............................................................................
|
497 |
+
curveFUNC = Uize.Curve.Mod.rotate (curveFUNCorFLOAT,blendOfRotated0to1FLOAT);
|
498 |
+
.............................................................................
|
499 |
+
|
500 |
+
When the optional =blendOfRotated0to1FLOAT= parameter is specified, this method will return a blend between the unrotated curve function and the rotated version.
|
501 |
+
|
502 |
+
INSTEAD OF...
|
503 |
+
.......................................................................
|
504 |
+
Uize.Curve.Mod.blend (Uize.Curve.makeEaseOut (Math.sqrt),Math.sqrt,.5);
|
505 |
+
.......................................................................
|
506 |
+
|
507 |
+
USE...
|
508 |
+
.....................................
|
509 |
+
Uize.Curve.Mod.rotate (Math.sqrt,.5);
|
510 |
+
.....................................
|
511 |
+
|
512 |
+
Calling the =Uize.Curve.Mod.rotate= method without specifying the =blendOfRotated0to1FLOAT= parameter is equivalent to using the =Uize.Curve.makeEaseOut= static method. So, it's when you use the =blendOfRotated0to1FLOAT= parameter that this method becomes compelling.
|
513 |
+
|
514 |
+
NOTES
|
515 |
+
- numerical values for the =curveFUNCorFLOAT= parameter are resolved to curve functions using the =Uize.Curve.resolve= static method
|
516 |
+
*/
|
517 |
+
};
|
518 |
+
|
519 |
+
return _package;
|
520 |
+
}
|
521 |
+
});
|
522 |
+
|
skin/frontend/default/customproduct/js/Uize.Curve.Rubber.js
ADDED
@@ -0,0 +1,538 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Curve.Rubber Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2009-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 5
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Curve.Rubber= module defines various "rubbery" easing curve function generators that emulate qualities of motion, like bounce and elasticity.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`, with thanks to `Robert Penner` for his easing equations work
|
25 |
+
|
26 |
+
The =Uize.Curve.Rubber= module defines various "rubbery" easing curve function generators, some of which are based on the easing equations work of `Robert Penner`.
|
27 |
+
|
28 |
+
In A Nutshell
|
29 |
+
Whereas the =Uize.Curve= module provides some of the most commonly used ease-in, ease-out, ease-in-out, and ease-in-the-middle curve function generators, the =Uize.Curve.Rubber= module offers curve function generators for more exotic types of curves that emulate the complex properties of motion.
|
30 |
+
|
31 |
+
Credit Where Credit Is Due
|
32 |
+
Thanks go to `Robert Penner` for his work on [[http://www.robertpenner.com/easing/][his easing equations]], which provided a starting point and inspiration for work that has been done in the =Uize.Curve.Rubber= module.
|
33 |
+
|
34 |
+
In some cases, his original methods have merely been refactored, such as with the =Uize.Curve.Rubber.easeInElastic= method and related elastic easing curve function generators provided in this module. In other cases, the original implementations have been completely replaced, such as with the =Uize.Curve.Rubber.easeInBounce= method and related bounce easing curve function generators provided in this module, with the new implementation being much more versatile than the original. Either way, his excellent work has been an inspiration.
|
35 |
+
|
36 |
+
Using the Curve Function Generators
|
37 |
+
Using the curve function generators in the =Uize.Curve.Rubber= module is just as easy as using those contained inside the =Uize.Curve= module.
|
38 |
+
|
39 |
+
Simply call the curve function generator static method, supplying parameter values as needed in order to produce a curve with the desired properties, and then provide that curve function to an instance of the =Uize.Fade= class, an instance of the =Uize.Widget.HoverFader= class, a static method of the =Uize.Fx= module, or any method or instance of a class that uses the =Uize.Fade= class to drive its animation or value interpolation.
|
40 |
+
|
41 |
+
EXAMPLE
|
42 |
+
..................................................................................
|
43 |
+
page.addChild (
|
44 |
+
'hoverFader',
|
45 |
+
Uize.Widget.HoverFader,
|
46 |
+
{
|
47 |
+
defaultStyle:{width:150,marginLeft:90,letterSpacing:2,borderRightColor:'0'},
|
48 |
+
hoverStyle:{width:240,marginLeft:0,letterSpacing:9,borderRightColor:'f'},
|
49 |
+
fadeIn:{duration:1200,curve:Uize.Curve.Rubber.easeOutElastic (.2)},
|
50 |
+
fadeOut:{duration:1000,curve:Uize.Curve.Rubber.easeOutBounce (5,-2,1.5)}
|
51 |
+
}
|
52 |
+
);
|
53 |
+
..................................................................................
|
54 |
+
|
55 |
+
In the above example, an instance of the =Uize.Widget.HoverFader= class is being added as a child widget of the page widget (which is assumed to already exist). For the =fadeIn= state property of the =Uize.Widget.HoverFader= instance, an elastic ease-out curve function is being supplied as a curve. For the =fadeOut= state property, a bounce ease-out curve function is being supplied as a curve. This will make the fade-in to the hover style have an elastic quality to it, and the fade-out to the default style have a bounce quality to it.
|
56 |
+
|
57 |
+
VISUALIZE IT
|
58 |
+
|
59 |
+
To better visualize how the "rubbery" easing curve function generators work and how they affect motion, visit the interactive [[../examples/curve-explorer.html][Curve Explorer]] tool.
|
60 |
+
|
61 |
+
BACKGROUND READING
|
62 |
+
|
63 |
+
For an in-depth discussion on animation in the UIZE JavaScript Framework, and for a discussion on how this module fits into the larger picture, consult the explainer [[../explainers/javascript-animation-and-effects.html][JavaScript Animation and Effects]] and read through the section `Curves`.
|
64 |
+
*/
|
65 |
+
|
66 |
+
Uize.module ({
|
67 |
+
name:'Uize.Curve.Rubber',
|
68 |
+
builder:function (_host) {
|
69 |
+
var
|
70 |
+
_package = function () {},
|
71 |
+
_makeEasingCurveGenerators = _host.makeEasingCurveGenerators,
|
72 |
+
_resolve = _host.resolve
|
73 |
+
;
|
74 |
+
|
75 |
+
/*** Curve Function Generators ***/
|
76 |
+
/*** elastic easing ***/
|
77 |
+
_makeEasingCurveGenerators (
|
78 |
+
'elastic',
|
79 |
+
function (_period,_amplitude) {
|
80 |
+
/*** paramter defaulting ***/
|
81 |
+
if (!_period) _period = .3;
|
82 |
+
if (!_amplitude || _amplitude < 1) _amplitude = 1;
|
83 |
+
|
84 |
+
/*** capture some calculation results ***/
|
85 |
+
var
|
86 |
+
_2piDivPeriod = 2 * Math.PI / _period,
|
87 |
+
_someValueOffset = Math.asin (1 / _amplitude) / _2piDivPeriod
|
88 |
+
;
|
89 |
+
|
90 |
+
return function (_value) {
|
91 |
+
return (
|
92 |
+
_value && _value != 1
|
93 |
+
? (
|
94 |
+
-_amplitude * Math.pow (2,10 * (_value -= 1)) *
|
95 |
+
Math.sin ((_value - _someValueOffset) * _2piDivPeriod)
|
96 |
+
)
|
97 |
+
: _value
|
98 |
+
)
|
99 |
+
}
|
100 |
+
},
|
101 |
+
_package
|
102 |
+
/*?
|
103 |
+
Static Methods
|
104 |
+
Uize.Curve.Rubber.easeInElastic
|
105 |
+
Elastic easing in - exponentially growing sine wave.
|
106 |
+
|
107 |
+
SYNTAX
|
108 |
+
.........................................................................
|
109 |
+
curveFUNC = Uize.Curve.Rubber.easeInElastic (periodFLOAT,amplitudeFLOAT);
|
110 |
+
.........................................................................
|
111 |
+
|
112 |
+
Parameters
|
113 |
+
periodFLOAT
|
114 |
+
A floating point number between =0= to =25=, representing the width of a single elastic stretch-past and spring-back cycle as a fraction of the total curve width.
|
115 |
+
|
116 |
+
A value of =.1=, for example, will produce a curve with =10= stretch-past and spring-back cycles, whereas a value of =.2= will produce five such cycles. Ever higher values above =1= make the curve progressively more like an exponential curve. The default value for this parameter is =.3=.
|
117 |
+
|
118 |
+
amplitudeFLOAT
|
119 |
+
A floating point number in the range of =1= to =Infinity=.
|
120 |
+
|
121 |
+
Values greater than =1= produce more springy elastic curves with more pronounced peaks and greater overshoot. The default value for this parameter is =1=.
|
122 |
+
|
123 |
+
Variations
|
124 |
+
VARIATION 1
|
125 |
+
..........................................................
|
126 |
+
curveFUNC = Uize.Curve.Rubber.easeInElastic (periodFLOAT);
|
127 |
+
..........................................................
|
128 |
+
|
129 |
+
When the optional =amplitudeFLOAT= parameter is not specified, its value will be defaulted to =1=.
|
130 |
+
|
131 |
+
VARIATION 2
|
132 |
+
...............................................
|
133 |
+
curveFUNC = Uize.Curve.Rubber.easeInElastic ();
|
134 |
+
...............................................
|
135 |
+
|
136 |
+
When the optional =periodFLOAT= parameter is not specified, its value will be defaulted to =.3=.
|
137 |
+
|
138 |
+
NOTES
|
139 |
+
- see also the companion =Uize.Curve.Rubber.easeOutElastic=, =Uize.Curve.Rubber.easeInOutElastic=, and =Uize.Curve.Rubber.easeMiddleElastic= static methods
|
140 |
+
- thanks to `Robert Penner` for his original implementation
|
141 |
+
|
142 |
+
Uize.Curve.Rubber.easeOutElastic
|
143 |
+
Elastic easing out - exponentially decaying sine wave.
|
144 |
+
|
145 |
+
SYNTAX
|
146 |
+
..........................................................................
|
147 |
+
curveFUNC = Uize.Curve.Rubber.easeOutElastic (periodFLOAT,amplitudeFLOAT);
|
148 |
+
..........................................................................
|
149 |
+
|
150 |
+
VARIATIONS
|
151 |
+
...........................................................
|
152 |
+
curveFUNC = Uize.Curve.Rubber.easeOutElastic (periodFLOAT);
|
153 |
+
curveFUNC = Uize.Curve.Rubber.easeOutElastic ();
|
154 |
+
...........................................................
|
155 |
+
|
156 |
+
For a more in-depth discussion of this method's parameters and variations, consult the reference for the related =Uize.Curve.Rubber.easeInElastic= static method.
|
157 |
+
|
158 |
+
NOTES
|
159 |
+
- see also the companion =Uize.Curve.Rubber.easeInElastic=, =Uize.Curve.Rubber.easeInOutElastic=, and =Uize.Curve.Rubber.easeMiddleElastic= static methods
|
160 |
+
- thanks to `Robert Penner` for his original implementation
|
161 |
+
|
162 |
+
Uize.Curve.Rubber.easeInOutElastic
|
163 |
+
Elastic easing in/out - exponentially building then decaying sine wave.
|
164 |
+
|
165 |
+
SYNTAX
|
166 |
+
............................................................................
|
167 |
+
curveFUNC = Uize.Curve.Rubber.easeInOutElastic (periodFLOAT,amplitudeFLOAT);
|
168 |
+
............................................................................
|
169 |
+
|
170 |
+
VARIATIONS
|
171 |
+
.............................................................
|
172 |
+
curveFUNC = Uize.Curve.Rubber.easeInOutElastic (periodFLOAT);
|
173 |
+
curveFUNC = Uize.Curve.Rubber.easeInOutElastic ();
|
174 |
+
.............................................................
|
175 |
+
|
176 |
+
For a more in-depth discussion of this method's parameters and variations, consult the reference for the related =Uize.Curve.Rubber.easeInElastic= static method.
|
177 |
+
|
178 |
+
NOTES
|
179 |
+
- see also the companion =Uize.Curve.Rubber.easeInElastic=, =Uize.Curve.Rubber.easeOutElastic=, and =Uize.Curve.Rubber.easeMiddleElastic= static methods
|
180 |
+
- thanks to `Robert Penner` for his original implementation
|
181 |
+
|
182 |
+
Uize.Curve.Rubber.easeMiddleElastic
|
183 |
+
Elastic easing in the middle - exponentially decaying then building sine wave.
|
184 |
+
|
185 |
+
SYNTAX
|
186 |
+
.............................................................................
|
187 |
+
curveFUNC = Uize.Curve.Rubber.easeMiddleElastic (periodFLOAT,amplitudeFLOAT);
|
188 |
+
.............................................................................
|
189 |
+
|
190 |
+
VARIATIONS
|
191 |
+
..............................................................
|
192 |
+
curveFUNC = Uize.Curve.Rubber.easeMiddleElastic (periodFLOAT);
|
193 |
+
curveFUNC = Uize.Curve.Rubber.easeMiddleElastic ();
|
194 |
+
..............................................................
|
195 |
+
|
196 |
+
For a more in-depth discussion of this method's parameters and variations, consult the reference for the related =Uize.Curve.Rubber.easeInElastic= static method.
|
197 |
+
|
198 |
+
NOTES
|
199 |
+
- see also the companion =Uize.Curve.Rubber.easeInElastic=, =Uize.Curve.Rubber.easeOutElastic=, and =Uize.Curve.Rubber.easeInOutElastic= static methods
|
200 |
+
- thanks to `Robert Penner` for his original implementation
|
201 |
+
*/
|
202 |
+
);
|
203 |
+
|
204 |
+
/*** overshoot easing ***/
|
205 |
+
_makeEasingCurveGenerators (
|
206 |
+
'back',
|
207 |
+
function (_overshoot) {
|
208 |
+
/*** paramter defaulting ***/
|
209 |
+
if (_overshoot == null) _overshoot = 1.70158;
|
210 |
+
|
211 |
+
/*** capture some calculation results ***/
|
212 |
+
var _overshootPlus1 = _overshoot + 1;
|
213 |
+
|
214 |
+
return function (_value) {return _value * _value * (_overshootPlus1 * _value - _overshoot)};
|
215 |
+
},
|
216 |
+
_package
|
217 |
+
/*?
|
218 |
+
Static Methods
|
219 |
+
Uize.Curve.Rubber.easeInBack
|
220 |
+
Back easing in - backtracking slightly, then reversing direction and moving to target.
|
221 |
+
|
222 |
+
SYNTAX
|
223 |
+
..........................................................
|
224 |
+
curveFUNC = Uize.Curve.Rubber.easeInBack (overshootFLOAT);
|
225 |
+
..........................................................
|
226 |
+
|
227 |
+
The =overshootFLOAT= parameter controls the amount of overshoot, and is typically a value in the range of =0= to =Infinity= (although negative values are also supported). Higher positive values for this parameter will produce greater overshoot. The default value of =1.70158= produces 10% overshoot. A value of =0= produces a cubic easing curve with no overshoot. Negative values lower than =-3= for this parameter will produce increasing amounts of overshoot on the opposite side of output value range.
|
228 |
+
|
229 |
+
VARIATION
|
230 |
+
............................................
|
231 |
+
curveFUNC = Uize.Curve.Rubber.easeInBack ();
|
232 |
+
............................................
|
233 |
+
|
234 |
+
When the optional =overshootFLOAT= parameter is not specified, its value will be defaulted to =1.70158=.
|
235 |
+
|
236 |
+
NOTES
|
237 |
+
- see also the companion =Uize.Curve.Rubber.easeOutBack=, =Uize.Curve.Rubber.easeInOutBack=, and =Uize.Curve.Rubber.easeMiddleBack= static methods
|
238 |
+
- thanks to `Robert Penner` for his original implementation
|
239 |
+
|
240 |
+
Uize.Curve.Rubber.easeOutBack
|
241 |
+
Back easing out - moving towards target, overshooting it slightly, then reversing and coming back to target.
|
242 |
+
|
243 |
+
SYNTAX
|
244 |
+
...........................................................
|
245 |
+
curveFUNC = Uize.Curve.Rubber.easeOutBack (overshootFLOAT);
|
246 |
+
...........................................................
|
247 |
+
|
248 |
+
For an in-depth discussion of the =overshootFLOAT= parameter, consult the reference for the related =Uize.Curve.Rubber.easeInBack= static method.
|
249 |
+
|
250 |
+
VARIATION
|
251 |
+
.............................................
|
252 |
+
curveFUNC = Uize.Curve.Rubber.easeOutBack ();
|
253 |
+
.............................................
|
254 |
+
|
255 |
+
When the optional =overshootFLOAT= parameter is not specified, its value will be defaulted to =1.70158=.
|
256 |
+
|
257 |
+
NOTES
|
258 |
+
- see also the companion =Uize.Curve.Rubber.easeInBack=, =Uize.Curve.Rubber.easeInOutBack=, and =Uize.Curve.Rubber.easeMiddleBack= static methods
|
259 |
+
- thanks to `Robert Penner` for his original implementation
|
260 |
+
|
261 |
+
Uize.Curve.Rubber.easeInOutBack
|
262 |
+
Back easing in/out - backtracking slightly, then reversing direction and moving to target, then overshooting target, reversing, and finally coming back to target.
|
263 |
+
|
264 |
+
SYNTAX
|
265 |
+
.............................................................
|
266 |
+
curveFUNC = Uize.Curve.Rubber.easeInOutBack (overshootFLOAT);
|
267 |
+
.............................................................
|
268 |
+
|
269 |
+
For an in-depth discussion of the =overshootFLOAT= parameter, consult the reference for the related =Uize.Curve.Rubber.easeInBack= static method.
|
270 |
+
|
271 |
+
VARIATION
|
272 |
+
...............................................
|
273 |
+
curveFUNC = Uize.Curve.Rubber.easeInOutBack ();
|
274 |
+
...............................................
|
275 |
+
|
276 |
+
When the optional =overshootFLOAT= parameter is not specified, its value will be defaulted to =1.70158=.
|
277 |
+
|
278 |
+
NOTES
|
279 |
+
- see also the companion =Uize.Curve.Rubber.easeInBack=, =Uize.Curve.Rubber.easeOutBack=, and =Uize.Curve.Rubber.easeMiddleBack= static methods
|
280 |
+
- thanks to `Robert Penner` for his original implementation
|
281 |
+
|
282 |
+
Uize.Curve.Rubber.easeMiddleBack
|
283 |
+
Back easing in the middle - overshooting the middle, backtracking to the middle, then backtracking even further towards the beginning, then finally moving to target.
|
284 |
+
|
285 |
+
SYNTAX
|
286 |
+
..............................................................
|
287 |
+
curveFUNC = Uize.Curve.Rubber.easeMiddleBack (overshootFLOAT);
|
288 |
+
..............................................................
|
289 |
+
|
290 |
+
For an in-depth discussion of the =overshootFLOAT= parameter, consult the reference for the related =Uize.Curve.Rubber.easeInBack= static method.
|
291 |
+
|
292 |
+
VARIATION
|
293 |
+
................................................
|
294 |
+
curveFUNC = Uize.Curve.Rubber.easeMiddleBack ();
|
295 |
+
................................................
|
296 |
+
|
297 |
+
When the optional =overshootFLOAT= parameter is not specified, its value will be defaulted to =1.70158=.
|
298 |
+
|
299 |
+
NOTES
|
300 |
+
- see also the companion =Uize.Curve.Rubber.easeInBack=, =Uize.Curve.Rubber.easeOutBack=, and =Uize.Curve.Rubber.easeInOutBack= static methods
|
301 |
+
- thanks to `Robert Penner` for his original implementation
|
302 |
+
*/
|
303 |
+
);
|
304 |
+
|
305 |
+
/*** bounce easing ***/
|
306 |
+
var _defaultBouncePeakCurveFunction = _host.easeInSweetPow (1.76);
|
307 |
+
_makeEasingCurveGenerators (
|
308 |
+
'bounce',
|
309 |
+
function (_bounces,_bouncePeakCurveFunction,_bounceWidthRatio,_bounceCurveFunction) {
|
310 |
+
/*** parameter defaulting ***/
|
311 |
+
if (!_bounces) _bounces = 4;
|
312 |
+
_bouncePeakCurveFunction =
|
313 |
+
_resolve (_bouncePeakCurveFunction,_defaultBouncePeakCurveFunction,true)
|
314 |
+
;
|
315 |
+
_bounceWidthRatio = !_bounceWidthRatio
|
316 |
+
? 2 // 0, null, or undefined, so default to 2
|
317 |
+
: _bounceWidthRatio * _bounceWidthRatio == 1
|
318 |
+
? 1.0001 // 1 or -1, so make sure it's not 1, since 1 breaks formula
|
319 |
+
: _bounceWidthRatio < 0
|
320 |
+
? -1 / _bounceWidthRatio // negative, so negate and invert
|
321 |
+
: _bounceWidthRatio
|
322 |
+
;
|
323 |
+
_bounceCurveFunction = _resolve (_bounceCurveFunction,2);
|
324 |
+
|
325 |
+
/*** pre-calculate profiles for bounces ***/
|
326 |
+
function _cumulativeWidth (_bounces) {return (Math.pow (_base,_bounces) - 1) / (_base - 1)}
|
327 |
+
var
|
328 |
+
_base = _bounceWidthRatio,
|
329 |
+
_baseMinus1 = _base - 1,
|
330 |
+
_bouncesMinus1 = _bounces - 1,
|
331 |
+
_bouncesWidthShown =
|
332 |
+
_cumulativeWidth (_bounces) /* combined width of all bounces */ -
|
333 |
+
Math.pow (_base,_bouncesMinus1) /* width of widest bounce */ / 2,
|
334 |
+
_logBase = Math.log (_base),
|
335 |
+
_bounceProfiles = []
|
336 |
+
;
|
337 |
+
for (var _bounceNo = -1; ++_bounceNo < _bounces;) {
|
338 |
+
var
|
339 |
+
_bounceStartPos = _cumulativeWidth (_bounceNo),
|
340 |
+
_widthDiv2 = (_cumulativeWidth (_bounceNo + 1) /* bounce end pos */ - _bounceStartPos) / 2,
|
341 |
+
_bounceMidPos = _bounceStartPos + _widthDiv2
|
342 |
+
;
|
343 |
+
_bounceProfiles.push ({
|
344 |
+
_height:_bouncePeakCurveFunction (_bounceMidPos / _bouncesWidthShown),
|
345 |
+
_midPos:_bounceMidPos,
|
346 |
+
_widthDiv2:_widthDiv2
|
347 |
+
});
|
348 |
+
}
|
349 |
+
|
350 |
+
return function (_value) {
|
351 |
+
var
|
352 |
+
_pos = _value * _bouncesWidthShown,
|
353 |
+
_bounceProfile = _bounceProfiles [
|
354 |
+
Uize.constrain (Math.floor (Math.log (_pos * _baseMinus1 + 1) / _logBase),0,_bouncesMinus1)
|
355 |
+
]
|
356 |
+
;
|
357 |
+
return _bounceProfile._height * (
|
358 |
+
_bounceCurveFunction (1 - Math.abs (_pos - _bounceProfile._midPos) / _bounceProfile._widthDiv2)
|
359 |
+
);
|
360 |
+
}
|
361 |
+
},
|
362 |
+
_package
|
363 |
+
/*?
|
364 |
+
Static Methods
|
365 |
+
Uize.Curve.Rubber.easeInBounce
|
366 |
+
Bounce, easing in.
|
367 |
+
|
368 |
+
SYNTAX
|
369 |
+
.......................................................................................
|
370 |
+
curveFUNC = Uize.Curve.Rubber.easeInBounce (
|
371 |
+
bouncesINT, // number of bounces (optional)
|
372 |
+
bouncePeakCurveFUNCorFLOAT, // bounciness, essentially (optional)
|
373 |
+
bounceWidthRatioFLOAT, // ratio of current bounce width to previous (optional)
|
374 |
+
bounceCurveFUNCorFLOAT // the shape of the curve of a bounce (optional)
|
375 |
+
);
|
376 |
+
.......................................................................................
|
377 |
+
|
378 |
+
Parameters
|
379 |
+
bouncesINT
|
380 |
+
An integer, specifying the number of bounces in the curve, with the default number of bounces being =4=.
|
381 |
+
|
382 |
+
bouncePeakCurveFUNCorFLOAT
|
383 |
+
A function reference for a curve function, or a numerical value that will be resolved to a power curve function using the =Uize.Curve.resolve= method.
|
384 |
+
|
385 |
+
This paramter can be used to affect the bounciness or springiness of each bounce. Numerical values above =1= will produce progressively bouncier curves as the value of =bouncePeakCurveFUNCorFLOAT= is increased. Numerical values below =-1= will produce progressively more dampened curves as the value of =bouncePeakCurveFUNCorFLOAT= is decreased.
|
386 |
+
|
387 |
+
When determining the height of the peak of an individual bounce, a curve function specified for the =bouncePeakCurveFUNCorFLOAT= parameter will be used to obtain a value, using the position of the midpoint of the bounce along the x-axis as the input value to the bounce peak curve function. Because the specified bounce peak curve is only sampled at the bounce midpoints, bounce peak curves with high amounts of detail will not affect the shape of the bounces, but only the heights of the bounce peaks (so detail will be lost, in other words).
|
388 |
+
|
389 |
+
For a linear curve, the value =1= can be specified for this parameter. The default value for this parameter is =1.76=.
|
390 |
+
|
391 |
+
bounceWidthRatioFLOAT
|
392 |
+
A floating point number, specifying the ratio between the width of the current bounce and the width of the previous bounce.
|
393 |
+
|
394 |
+
The default value for this parameter is =2=, which means that each bounce will be twice as wide as the previous bounce. When the value =1= is specified for this parameter, all bounces will have the same width. When negative values are specified for this parameter, then ratio will be resolved to a positive number by negating it and inverting it (dividing it into =1=). In other words, the value =-2= will result in a resolved ratio of =.5=, which will result in each bounce being half the width of the previous bounce. You can think of the values in the negative scale as being the ratio of the width of the current bounce to the width of the next bounce (once negated, of course).
|
395 |
+
|
396 |
+
For values of this parameter greater than =1=, the higher the value, the less noticeable changing the number of bounces with the =bouncesINT= parameter will become. Similarly, on the opposite side of the spectrum, for values of =bounceWidthRatioFLOAT= less than =-1=, the lower the value, the less noticeable changing the number of bounces will become. If each bounce is much smaller or larger than the previous bounce, the bounces at one end of the curve will become very small and barely noticeable.
|
397 |
+
|
398 |
+
NOTE
|
399 |
+
|
400 |
+
It should be noted that for the ease-out version of this curve, and for the the ease-out phase of the ease-in-out and ease-in-the-middle versions of this curve, the bounce width ratio is actually the ratio of the width of the current bounce to the width of the next bounce. This is as a result of the curve being rotated 180 degrees.
|
401 |
+
|
402 |
+
bounceCurveFUNCorFLOAT
|
403 |
+
A function reference for a curve function, or a numerical value that will be resolved to a power curve function using the =Uize.Curve.resolve= method.
|
404 |
+
|
405 |
+
The curve specified by the =bounceCurveFUNCorFLOAT= parameter will be used to generate points along the curve of an individual bounce. The specified curve is used to produce both the left and right halves of a bounce curve, on either side of the bounce's midpoint on the x-axis. For the opposite half, the bounce curve is flipped horizontally. The default value for this parameter is =2=, which produces bounces using a quadratic ease-out power curve.
|
406 |
+
|
407 |
+
VARIATION 1
|
408 |
+
..............................................................
|
409 |
+
curveFUNC = Uize.Curve.Rubber.easeInBounce (
|
410 |
+
bouncesINT,bouncePeakCurveFUNCorFLOAT,bounceWidthRatioFLOAT
|
411 |
+
);
|
412 |
+
..............................................................
|
413 |
+
|
414 |
+
When no =bounceCurveFUNCorFLOAT= parameter is specified, its value will be defaulted to =2=, representing a quadratic ease-out curve function.
|
415 |
+
|
416 |
+
VARIATION 2
|
417 |
+
...................................................................................
|
418 |
+
curveFUNC = Uize.Curve.Rubber.easeInBounce (bouncesINT,bouncePeakCurveFUNCorFLOAT);
|
419 |
+
...................................................................................
|
420 |
+
|
421 |
+
When no =bounceWidthRatioFLOAT= parameter is specified, its value will be defaulted to =2= (each bounce will be twice the width of the previous bounce).
|
422 |
+
|
423 |
+
VARIATION 3
|
424 |
+
........................................................
|
425 |
+
curveFUNC = Uize.Curve.Rubber.easeInBounce (bouncesINT);
|
426 |
+
........................................................
|
427 |
+
|
428 |
+
When no =bouncePeakCurveFUNCorFLOAT= parameter is specified, its value will be defaulted to =1.76=.
|
429 |
+
|
430 |
+
VARIATION 4
|
431 |
+
..............................................
|
432 |
+
curveFUNC = Uize.Curve.Rubber.easeInBounce ();
|
433 |
+
..............................................
|
434 |
+
|
435 |
+
When no =bouncesINT= parameter is specified, its value will be defaulted to =4=.
|
436 |
+
|
437 |
+
NOTES
|
438 |
+
- see also the companion =Uize.Curve.Rubber.easeOutBounce=, =Uize.Curve.Rubber.easeInOutBounce=, and =Uize.Curve.Rubber.easeMiddleBounce= static methods
|
439 |
+
|
440 |
+
Uize.Curve.Rubber.easeOutBounce
|
441 |
+
Bounce, easing out.
|
442 |
+
|
443 |
+
SYNTAX
|
444 |
+
.......................................................................................
|
445 |
+
curveFUNC = Uize.Curve.Rubber.easeOutBounce (
|
446 |
+
bouncesINT, // number of bounces (optional)
|
447 |
+
bouncePeakCurveFUNCorFLOAT, // bounciness, essentially (optional)
|
448 |
+
bounceWidthRatioFLOAT, // ratio of current bounce width to next (optional)
|
449 |
+
bounceCurveFUNCorFLOAT // the shape of the curve of a bounce (optional)
|
450 |
+
);
|
451 |
+
.......................................................................................
|
452 |
+
|
453 |
+
VARIATIONS
|
454 |
+
....................................................................................
|
455 |
+
curveFUNC = Uize.Curve.Rubber.easeOutBounce (
|
456 |
+
bouncesINT,bouncePeakCurveFUNCorFLOAT,bounceWidthRatioFLOAT
|
457 |
+
);
|
458 |
+
|
459 |
+
curveFUNC = Uize.Curve.Rubber.easeOutBounce (bouncesINT,bouncePeakCurveFUNCorFLOAT);
|
460 |
+
|
461 |
+
curveFUNC = Uize.Curve.Rubber.easeOutBounce (bouncesINT);
|
462 |
+
|
463 |
+
curveFUNC = Uize.Curve.Rubber.easeOutBounce ();
|
464 |
+
....................................................................................
|
465 |
+
|
466 |
+
For a more in-depth discussion of this method's parameters and variations, consult the reference for the related =Uize.Curve.Rubber.easeInBounce= static method.
|
467 |
+
|
468 |
+
NOTES
|
469 |
+
- see also the companion =Uize.Curve.Rubber.easeInBounce=, =Uize.Curve.Rubber.easeInOutBounce=, and =Uize.Curve.Rubber.easeMiddleBounce= static methods
|
470 |
+
|
471 |
+
Uize.Curve.Rubber.easeInOutBounce
|
472 |
+
Bounce, easing in/out.
|
473 |
+
|
474 |
+
SYNTAX
|
475 |
+
.......................................................................................
|
476 |
+
curveFUNC = Uize.Curve.Rubber.easeInOutBounce (
|
477 |
+
bouncesINT, // number of bounces (optional)
|
478 |
+
bouncePeakCurveFUNCorFLOAT, // bounciness, essentially (optional)
|
479 |
+
bounceWidthRatioFLOAT, // ratio of current bounce width to previous (optional)
|
480 |
+
bounceCurveFUNCorFLOAT // the shape of the curve of a bounce (optional)
|
481 |
+
);
|
482 |
+
.......................................................................................
|
483 |
+
|
484 |
+
VARIATIONS
|
485 |
+
......................................................................................
|
486 |
+
curveFUNC = Uize.Curve.Rubber.easeInOutBounce (
|
487 |
+
bouncesINT,bouncePeakCurveFUNCorFLOAT,bounceWidthRatioFLOAT
|
488 |
+
);
|
489 |
+
|
490 |
+
curveFUNC = Uize.Curve.Rubber.easeInOutBounce (bouncesINT,bouncePeakCurveFUNCorFLOAT);
|
491 |
+
|
492 |
+
curveFUNC = Uize.Curve.Rubber.easeInOutBounce (bouncesINT);
|
493 |
+
|
494 |
+
curveFUNC = Uize.Curve.Rubber.easeInOutBounce ();
|
495 |
+
......................................................................................
|
496 |
+
|
497 |
+
For a more in-depth discussion of this method's parameters and variations, consult the reference for the related =Uize.Curve.Rubber.easeInBounce= static method.
|
498 |
+
|
499 |
+
NOTES
|
500 |
+
- see also the companion =Uize.Curve.Rubber.easeInBounce=, =Uize.Curve.Rubber.easeOutBounce=, and =Uize.Curve.Rubber.easeMiddleBounce= static methods
|
501 |
+
|
502 |
+
Uize.Curve.Rubber.easeMiddleBounce
|
503 |
+
Bounce, easing in the middle.
|
504 |
+
|
505 |
+
SYNTAX
|
506 |
+
.......................................................................................
|
507 |
+
curveFUNC = Uize.Curve.Rubber.easeMiddleBounce (
|
508 |
+
bouncesINT, // number of bounces (optional)
|
509 |
+
bouncePeakCurveFUNCorFLOAT, // bounciness, essentially (optional)
|
510 |
+
bounceWidthRatioFLOAT, // ratio of current bounce width to previous (optional)
|
511 |
+
bounceCurveFUNCorFLOAT // the shape of the curve of a bounce (optional)
|
512 |
+
);
|
513 |
+
.......................................................................................
|
514 |
+
|
515 |
+
VARIATIONS
|
516 |
+
.......................................................................................
|
517 |
+
curveFUNC = Uize.Curve.Rubber.easeMiddleBounce (
|
518 |
+
bouncesINT,bouncePeakCurveFUNCorFLOAT,bounceWidthRatioFLOAT
|
519 |
+
);
|
520 |
+
|
521 |
+
curveFUNC = Uize.Curve.Rubber.easeMiddleBounce (bouncesINT,bouncePeakCurveFUNCorFLOAT);
|
522 |
+
|
523 |
+
curveFUNC = Uize.Curve.Rubber.easeMiddleBounce (bouncesINT);
|
524 |
+
|
525 |
+
curveFUNC = Uize.Curve.Rubber.easeMiddleBounce ();
|
526 |
+
.......................................................................................
|
527 |
+
|
528 |
+
For a more in-depth discussion of this method's parameters and variations, consult the reference for the related =Uize.Curve.Rubber.easeInBounce= static method.
|
529 |
+
|
530 |
+
NOTES
|
531 |
+
- see also the companion =Uize.Curve.Rubber.easeInBounce=, =Uize.Curve.Rubber.easeOutBounce=, and =Uize.Curve.Rubber.easeInOutBounce= static methods
|
532 |
+
*/
|
533 |
+
);
|
534 |
+
|
535 |
+
return _package;
|
536 |
+
}
|
537 |
+
});
|
538 |
+
|
skin/frontend/default/customproduct/js/Uize.Curve.js
ADDED
@@ -0,0 +1,854 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Curve Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2009-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 6
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 0
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Curve= module provides a namespace and services for curve related modules, and provides a number of useful built-in curve function generators.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`, with thanks to `Robert Penner` for his easing equations work
|
25 |
+
|
26 |
+
The =Uize.Curve= module defines a namespace for other curve related modules (such as the =Uize.Curve.Rubber= and =Uize.Curve.Mod= modules), that provides some basic services that are useful for creating such curve related modules, and that also provides a number of the more commonly used curve function generators as built-ins.
|
27 |
+
|
28 |
+
In a Nutshell
|
29 |
+
The =Uize.Curve= module provides built-in curve function generators for power easing curves, "sweetened" power easing curves, sinusoidal easing curves, circular easing curves, exponential easing curves, and basic straight line curves.
|
30 |
+
|
31 |
+
This module also provides curve function modifiers for making ease-out, ease-in-out, and ease-in-the-middle curve functions from ease-in curve functions, as well as a method for making ease-in, ease-out, ease-in-out, and ease-in-the-middle curve function generators from an ease-in curve function generator. Finally, miscellaneous services are provided that are useful for other curve related modules, such as the =Uize.Curve.linear= curve function, =Uize.Curve.resolve= static method, etc.
|
32 |
+
|
33 |
+
BACKGROUND READING
|
34 |
+
|
35 |
+
For an in-depth discussion on animation in the UIZE JavaScript Framework, and for a discussion on how this module fits into the larger picture, consult the explainer [[../explainers/javascript-animation-and-effects.html][JavaScript Animation and Effects]] and read through the section `Curves`.
|
36 |
+
*/
|
37 |
+
|
38 |
+
Uize.module ({
|
39 |
+
name:'Uize.Curve',
|
40 |
+
builder:function () {
|
41 |
+
var _package = function () {};
|
42 |
+
|
43 |
+
/*** Variables for Scruncher Optimization ***/
|
44 |
+
var _undefined;
|
45 |
+
|
46 |
+
/*** Public Static Methods ***/
|
47 |
+
var
|
48 |
+
_blendFloats = _package.blendFloats = function (_valueA,_valueB,_blend) {
|
49 |
+
return _valueA + (_valueB - _valueA) * _blend
|
50 |
+
/*?
|
51 |
+
Static Methods
|
52 |
+
Uize.Curve.blendFloats
|
53 |
+
Returns a floating point number, that is the blend between the two specified floating point numbers, using the specified blend amount.
|
54 |
+
|
55 |
+
SYNTAX
|
56 |
+
...............................................................................
|
57 |
+
blendedFLOAT = Uize.Curve.blendFloats (value1FLOAT,value2FLOAT,blend0to1FLOAT);
|
58 |
+
...............................................................................
|
59 |
+
|
60 |
+
When the value =0= is specified for the =blend0to1FLOAT= parameter, the value of the =value1FLOAT= parameter will be returned. When the value =1= is specified for =blend0to1FLOAT=, then the value of =value2FLOAT= will be returned. And when the value =.5= is specified for =blend0to1FLOAT=, then the returned value will be an equal blend between the values of =value1FLOAT= and =value2FLOAT=. The blend between the values of =value1FLOAT= and =value2FLOAT=, as specified by the =blend0to1FLOAT= parameter, is a simple linear interpolation.
|
61 |
+
|
62 |
+
NOTES
|
63 |
+
- compare to the =Uize.Curve.makeBlender= static method
|
64 |
+
*/
|
65 |
+
},
|
66 |
+
_linear = _package.linear = Uize.returnX,
|
67 |
+
/*?
|
68 |
+
Static Methods
|
69 |
+
Uize.Curve.linear
|
70 |
+
A simple linear curve function (ie. *NOT* a curve function generator) that merely returns the value that is passed into it.
|
71 |
+
|
72 |
+
SYNTAX
|
73 |
+
................................................
|
74 |
+
valueANYTYPE = Uize.Curve.linear (valueANYTYPE);
|
75 |
+
................................................
|
76 |
+
|
77 |
+
This method / curve function is useful for curve function modifiers that expect curve functions as parameters. One is not likely to call this method directly, but instead supply it - by reference - as a parameter to other methods.
|
78 |
+
|
79 |
+
NOTES
|
80 |
+
- compare to the =Uize.Curve.line= static method
|
81 |
+
*/
|
82 |
+
_makeEaseOut = _package.makeEaseOut = function (_curveFunction) {
|
83 |
+
return function (_value) {return 1 - _curveFunction (1 - _value)}
|
84 |
+
/*?
|
85 |
+
Static Methods
|
86 |
+
Uize.Curve.makeEaseOut
|
87 |
+
Returns an ease-out curve function, that is the 180 degree rotated version of the specified ease-in curve function.
|
88 |
+
|
89 |
+
SYNTAX
|
90 |
+
............................................................
|
91 |
+
easeOutCurveFUNC = Uize.Curve.makeEaseOut (easeInCurveFUNC);
|
92 |
+
............................................................
|
93 |
+
|
94 |
+
Assuming that the curve function specified by the =easeInCurveFUNC= parameter is truly for an ease-in curve function, then the curve function that is returned by this method will effectively be an ease-out curve function.
|
95 |
+
|
96 |
+
NOTES
|
97 |
+
- see the related =Uize.Curve.makeEaseInOut=, =Uize.Curve.makeEaseMiddle=, and =Uize.Curve.makeEasingCurveGenerators= static methods
|
98 |
+
*/
|
99 |
+
},
|
100 |
+
_makeEaseInOut = _package.makeEaseInOut = function (_curveFunction) {
|
101 |
+
return function (_value) {
|
102 |
+
return ((_value *= 2) < 1 ? _curveFunction (_value) : 2 - _curveFunction (2 - _value)) / 2;
|
103 |
+
}
|
104 |
+
/*?
|
105 |
+
Static Methods
|
106 |
+
Uize.Curve.makeEaseInOut
|
107 |
+
Returns an ease-in-out curve function, that uses the specified ease-in curve function to produce a two phase curve that has an ease-in phase followed by an ease-out phase.
|
108 |
+
|
109 |
+
SYNTAX
|
110 |
+
................................................................
|
111 |
+
easeInOutCurveFUNC = Uize.Curve.makeEaseInOut (easeInCurveFUNC);
|
112 |
+
................................................................
|
113 |
+
|
114 |
+
Assuming that the curve function specified by the =easeInCurveFUNC= parameter is truly for an ease-in curve function, then the curve function that is returned by this method will effectively be an ease-in-out curve function.
|
115 |
+
|
116 |
+
NOTES
|
117 |
+
- see the related =Uize.Curve.makeEaseOut=, =Uize.Curve.makeEaseMiddle=, and =Uize.Curve.makeEasingCurveGenerators= static methods
|
118 |
+
*/
|
119 |
+
},
|
120 |
+
_makeEaseMiddle = _package.makeEaseMiddle = function (_curveFunction) {
|
121 |
+
return function (_value) {
|
122 |
+
return ((_value *= 2) < 1 ? 1 - _curveFunction (1 - _value) : 1 + _curveFunction (_value - 1)) / 2;
|
123 |
+
}
|
124 |
+
/*?
|
125 |
+
Static Methods
|
126 |
+
Uize.Curve.makeEaseMiddle
|
127 |
+
Returns an ease-in-the-middle curve function, that uses the specified ease-in curve function to produce a two phase curve that has an ease-out phase followed by an ease-in phase.
|
128 |
+
|
129 |
+
SYNTAX
|
130 |
+
..................................................................
|
131 |
+
easeMiddleCurveFUNC = Uize.Curve.makeEaseMiddle (easeInCurveFUNC);
|
132 |
+
..................................................................
|
133 |
+
|
134 |
+
Assuming that the curve function specified by the =easeInCurveFUNC= parameter is truly for an ease-in curve function, then the curve function that is returned by this method will effectively be an ease-in-the-middle curve function.
|
135 |
+
|
136 |
+
NOTES
|
137 |
+
- see the related =Uize.Curve.makeEaseOut=, =Uize.Curve.makeEaseInOut=, and =Uize.Curve.makeEasingCurveGenerators= static methods
|
138 |
+
*/
|
139 |
+
},
|
140 |
+
_makeEasingCurveGenerators = _package.makeEasingCurveGenerators = function (
|
141 |
+
_methodNameSuffix,_easeInCurveGenerator,_context
|
142 |
+
) {
|
143 |
+
var _paramless = {};
|
144 |
+
if (!_context) _context = _package;
|
145 |
+
_methodNameSuffix = Uize.capFirstChar (_methodNameSuffix);
|
146 |
+
|
147 |
+
function _makeCurveGenerator (_easeType,_easingCurveGeneratorMaker) {
|
148 |
+
_context ['ease' + _easeType + _methodNameSuffix] = function () {
|
149 |
+
return (
|
150 |
+
arguments.length
|
151 |
+
? _easingCurveGeneratorMaker (_easeInCurveGenerator.apply (0,arguments))
|
152 |
+
:
|
153 |
+
_paramless [_easeType] ||
|
154 |
+
(
|
155 |
+
_paramless [_easeType] =
|
156 |
+
_easingCurveGeneratorMaker (
|
157 |
+
_paramless.In || (_paramless.In = _easeInCurveGenerator ()))
|
158 |
+
)
|
159 |
+
)
|
160 |
+
};
|
161 |
+
}
|
162 |
+
_makeCurveGenerator ('In',_linear);
|
163 |
+
_makeCurveGenerator ('Out',_makeEaseOut);
|
164 |
+
_makeCurveGenerator ('InOut',_makeEaseInOut);
|
165 |
+
_makeCurveGenerator ('Middle',_makeEaseMiddle);
|
166 |
+
/*?
|
167 |
+
Static Methods
|
168 |
+
Uize.Curve.makeEasingCurveGenerators
|
169 |
+
Makes static methods for generating an ease-in curve function, ease-out curve function, ease-in-out curve function, and ease-in-the-middle curve function, using the specified ease-in curve function generator.
|
170 |
+
|
171 |
+
SYNTAX
|
172 |
+
......................................
|
173 |
+
Uize.Curve.makeEasingCurveGenerators (
|
174 |
+
methodNameSuffixSTR,
|
175 |
+
easeInCurveGeneratorFUNC,
|
176 |
+
contextOBJ
|
177 |
+
);
|
178 |
+
......................................
|
179 |
+
|
180 |
+
This method is provided as a convenience to make it easier to spawn easing curve function generators for different types of curves. The =Uize.Curve= module, itself, uses this method to create its many curve function generator methods, as does the =Uize.Curve.Rubber= module.
|
181 |
+
|
182 |
+
Parameters
|
183 |
+
The =Uize.Curve.makeEasingCurveGenerators= method supports the following parameters...
|
184 |
+
|
185 |
+
methodNameSuffixSTR
|
186 |
+
A string, specifying the suffix of the method names for the four static methods that are created.
|
187 |
+
|
188 |
+
The static methods created by this method are named with the prefixes "easeIn", "easeOut", "easeInOut", and "easeMiddle". When creating easing curve function generators in a context that will have other curve function generators, the suffix allows you to distinguish between the curve function generators for different types of curves. The first letter of the specified suffix is uppercased before appending it to the method name prefixes.
|
189 |
+
|
190 |
+
For example, with the methods =Uize.Curve.easeInSine=, =Uize.Curve.easeOutSine=, =Uize.Curve.easeInOutSine=, and =Uize.Curve.easeMiddleSine=, the value used for =methodNameSuffixSTR= would be ='Sine'= (or ='sine'=). With the methods =Uize.Curve.easeInExpo=, =Uize.Curve.easeOutExpo=, =Uize.Curve.easeInOutExpo=, and =Uize.Curve.easeMiddleExpo=, the value used for =methodNameSuffixSTR= would be ='Expo'= (or ='expo'=).
|
191 |
+
|
192 |
+
easeInCurveGeneratorFUNC
|
193 |
+
A function, being the curve function generator for the ease-in curve function from which you would like to derive the ease-in, ease-out, ease-in-out, and ease-middle curve function generator static methods.
|
194 |
+
|
195 |
+
contextOBJ
|
196 |
+
An object, specifying the context for the curve function generators.
|
197 |
+
|
198 |
+
This parameter is optional - when a value is not specified for it, its value will be defaulted to =Uize.Curve=. Using this parameter, you could assign the curve function generators to a module other than =Uize.Curve=. For example, the =Uize.Curve.Rubber= module uses the =Uize.Curve.makeEasingCurveGenerators= method to create its curve function generators and specifies a reference to =Uize.Curve.Rubber= as the value for the =contextOBJ= parameter.
|
199 |
+
|
200 |
+
TIP
|
201 |
+
|
202 |
+
If you wish to assign the curve function generators on the actual ease-in curve function generator, then you can specify the curve function generator as the value for the =contextOBJ= parameter and then specify the value =''= (empty string) for the =methodNameSuffixSTR= parameter.
|
203 |
+
|
204 |
+
Examples
|
205 |
+
The following examples illustrate different uses of the =Uize.Curve.makeEasingCurveGenerators= method...
|
206 |
+
|
207 |
+
EXAMPLE 1
|
208 |
+
..............................................................
|
209 |
+
Uize.Curve.makeEasingCurveGenerators (
|
210 |
+
'Power',
|
211 |
+
function (power) {
|
212 |
+
if (power == null) power = 2;
|
213 |
+
return function (value) {return Math.pow (value,power)};
|
214 |
+
}
|
215 |
+
);
|
216 |
+
|
217 |
+
// now you can call the newly created static methods...
|
218 |
+
|
219 |
+
Uize.Curve.easeInPower ();
|
220 |
+
Uize.Curve.easeInPower (2);
|
221 |
+
Uize.Curve.easeOutPower (3);
|
222 |
+
Uize.Curve.easeInOutPower (2.5);
|
223 |
+
Uize.Curve.easeMiddlePower (3.1);
|
224 |
+
..............................................................
|
225 |
+
|
226 |
+
In the above example, the traditional approach is being used to create easing curve function generators that are accessed off of the =Uize.Curve= module (the default context). Because the value ='Power'= is specified for the =methodNameSuffixSTR= parameter, the created methods names are =easeInPower=, =easeOutPower=, =easeInOutPower=, and =easeMiddlePower=.
|
227 |
+
|
228 |
+
EXAMPLE 2
|
229 |
+
................................................................
|
230 |
+
function powerCurve (power) {
|
231 |
+
if (power == null) power = 2;
|
232 |
+
return function (value) {return Math.pow (value,power)};
|
233 |
+
};
|
234 |
+
Uize.Curve.makeEasingCurveGenerators ('',powerCurve,powerCurve);
|
235 |
+
|
236 |
+
// now you can call the newly created static methods...
|
237 |
+
|
238 |
+
powerCurve.easeIn (); // equivalent to powerCurve (2)
|
239 |
+
powerCurve.easeIn (2); // equivalent to powerCurve (2)
|
240 |
+
powerCurve.easeOut (3);
|
241 |
+
powerCurve.eastInOut (2.5);
|
242 |
+
powerCurve.easeMiddle (3.1);
|
243 |
+
................................................................
|
244 |
+
|
245 |
+
In the above example, the ease-in curve function generator is being used as the context for the easing curve function generators. This is done by specifying the =powerCurve= function not only as the value for the =easeInCurveGeneratorFUNC= parameter, but also as the value for the =contextOBJ= parameter. Then, specifying the value =''= (empty string) for the =methodNameSuffixSTR= parameter means that the methods accessed off of =powerCurve= are named simply =easeIn=, =easeOut=, =easeInOut=, and =easeMiddle=.
|
246 |
+
|
247 |
+
Caching of Paramless Versions
|
248 |
+
As an optimization, the =Uize.Curve.makeEasingCurveGenerators= method caches the results of the paramless calls to the curve functions generators that it creates.
|
249 |
+
|
250 |
+
This means that the statement =Uize.Curve.easeOutPow ()= will always return a reference to the same curve function - for a quadratic ease-out curve. In contrast, the statement =Uize.Curve.easeOutPow (3)= will always return different curve functions - even though they will always do the same thing (ie. produce a cubic ease-out curve).
|
251 |
+
|
252 |
+
NOTES
|
253 |
+
- see the related =Uize.Curve.makeEaseOut=, =Uize.Curve.makeEaseInOut=, and =Uize.Curve.makeEaseMiddle= static methods
|
254 |
+
*/
|
255 |
+
}
|
256 |
+
;
|
257 |
+
|
258 |
+
_package.makeBlender = function (_curveFunction) {
|
259 |
+
_curveFunction = _package.resolve (_curveFunction);
|
260 |
+
return function (_valueA,_valueB,_blend) {return _blendFloats (_valueA,_valueB,_curveFunction (_blend))};
|
261 |
+
/*?
|
262 |
+
Static Methods
|
263 |
+
Uize.Curve.makeBlender
|
264 |
+
Return a blender function, that will use the specified curve function when blending between two values.
|
265 |
+
|
266 |
+
SYNTAX
|
267 |
+
........................................................
|
268 |
+
blenderFUNC = Uize.Curve.makeBlender (curveFUNCorFLOAT);
|
269 |
+
........................................................
|
270 |
+
|
271 |
+
The blender function that is returned by this method has the same signature as the =Uize.Curve.blendFloats= static method and accepts three parameters: =value1FLOAT=, =value2FLOAT=, and =blend0to1FLOAT=.
|
272 |
+
|
273 |
+
EXAMPLE
|
274 |
+
..................................................................................
|
275 |
+
var
|
276 |
+
bouncyBlender = Uize.Curve.makeBlender (Uize.Curve.Rubber.easeOutBounce (4,2)),
|
277 |
+
middleOfBounceValue = bouncyBlender (0,255,.5) // result is 90.4438142188662
|
278 |
+
;
|
279 |
+
..................................................................................
|
280 |
+
|
281 |
+
In the above example, the =middleOfBounceValue= variable will be left with the value =90.4438142188662=, being the value halfway between =0= and =255= on an extra bouncy ease-out bounce curve with four bounces.
|
282 |
+
|
283 |
+
NOTES
|
284 |
+
- compare to the =Uize.Curve.blendFloats= static method
|
285 |
+
- numerical values for the =curveFUNCorFLOAT= parameter are resolved to curve functions using the =Uize.Curve.resolve= static method
|
286 |
+
*/
|
287 |
+
};
|
288 |
+
|
289 |
+
_package.resolve = function (_curveFunction,_defaultCurveFunction,_sweet,_polarity) {
|
290 |
+
if (_curveFunction == _undefined) _curveFunction = _defaultCurveFunction;
|
291 |
+
return (
|
292 |
+
Uize.isFunction (_curveFunction) || Uize.isArray (_curveFunction)
|
293 |
+
? _curveFunction
|
294 |
+
: !_curveFunction || _curveFunction * _curveFunction == 1
|
295 |
+
? _linear
|
296 |
+
: _package [
|
297 |
+
(_curveFunction * (_polarity || 1) < 0 ? 'easeIn' : 'easeOut') + (_sweet ? 'Sweet' : '') + 'Pow'
|
298 |
+
] (
|
299 |
+
Math.abs (_curveFunction)
|
300 |
+
)
|
301 |
+
)
|
302 |
+
/*?
|
303 |
+
Static Methods
|
304 |
+
Uize.Curve.resolve
|
305 |
+
Resolves the specified curve function or power curve value to a curve function and returns it.
|
306 |
+
|
307 |
+
SYNTAX
|
308 |
+
...................................................................................
|
309 |
+
curveFUNC = Uize.Curve.resolve (
|
310 |
+
curveFUNCorFLOAT, // value to be resolved to a curve function (optional)
|
311 |
+
defaultCurveFUNCorFLOAT, // default curve function or power (optional)
|
312 |
+
sweetBOOL, // use sweetened power curve functions (optional)
|
313 |
+
polarityINT // polarity, in case negating is desired (optional)
|
314 |
+
);
|
315 |
+
...................................................................................
|
316 |
+
|
317 |
+
This method can be useful when implementing your own curve function generators - for either complex curves or for curve function modifiers - and when such curve function generators wish to support the numerical shorthand for specifying power curve functions for parameters that are curve functions.
|
318 |
+
|
319 |
+
A good example of this is the =Uize.Curve.Mod.bend= static method of the =Uize.Curve.Mod= module. This method accepts a curve and then bends it horizontally and/or vertically, using specified curves for both horizontal and vertical bending. In most simple cases, power curve functions are effective for achieving smooth / regular bending. The =Uize.Curve.Mod.bend= method supports numerical values for its =horzBendFLOATorFUNC= and =vertBendFLOATorFUNC= parameters (a convenience provided to applications that wish to use the method), and its implementation uses the =Uize.Curve.resolve= method to resolve these numerical values to actual curve functions.
|
320 |
+
|
321 |
+
Parameters
|
322 |
+
The =Uize.Curve.resolve= method supports the following parameters...
|
323 |
+
|
324 |
+
curveFUNCorFLOAT
|
325 |
+
A curve function, or a number that should be used to generate a power curve function.
|
326 |
+
|
327 |
+
Handling for different types of values is as follows...
|
328 |
+
|
329 |
+
- *function* - When a function is specified, it will simply be returned as is.
|
330 |
+
|
331 |
+
- *array* - When an array is specified, it will simply be returned as is.
|
332 |
+
|
333 |
+
- *positive number* - When a positive number is specified, then an ease-out power curve function will be returned of that power. For example, the statement =Uize.Curve.resolve (3)= would be equivalent to the statement =Uize.Curve.easeOutPow (3)= (provided the value =true= is *not* specified for the optional =sweetBOOL= parameter, and the value =-1= is *not* specified for the optional =polarityINT= parameter).
|
334 |
+
|
335 |
+
- *negative number* - When a negative number is specified, then an ease-in power curve function will be returned of the negative of that power. For example, the statement =Uize.Curve.resolve (-3)= would be equivalent to the statement =Uize.Curve.easeInPow (3)= (provided the value =true= is *not* specified for the optional =sweetBOOL= parameter, and the value =-1= is *not* specified for the optional =polarityINT= parameter).
|
336 |
+
|
337 |
+
- *-1, 0, or 1* - When either of the values =-1=, =0=, or =1= is specified, then a reference to =Uize.Curve.linear= (a linear curve function) will be returned.
|
338 |
+
|
339 |
+
- *not defined* - When either of the values =null= or =undefined= is specified, then the =curveFUNCorFLOAT= parameter will be defaulted to the value of the optional =defaultCurveFUNCorFLOAT= parameter.
|
340 |
+
|
341 |
+
defaultCurveFUNCorFLOAT
|
342 |
+
A curve function, or a number that should be used to generate a power curve function, that should be used as the default curve if the value =null= or =undefined= is specified for the =curveFUNCorFLOAT= parameter.
|
343 |
+
|
344 |
+
When the optional =defaultCurveFUNCorFLOAT= parameter is specified, a curve other than a linear curve can be used as the default. When the =defaultCurveFUNCorFLOAT= parameter is not specified, =Uize.Curve.linear= (a linear curve function) will be used as the default curve.
|
345 |
+
|
346 |
+
sweetBOOL
|
347 |
+
A boolean, specifying whether or not the "sweetened" versions of the power curve functions should be used when a number is specified for the =curveFUNCorFLOAT= parameter.
|
348 |
+
|
349 |
+
- =false= - When the value =false= is specified, the =Uize.Curve.easeInPow= static method will be used for resolving negative number values of =curveFUNCorFLOAT=, and the =Uize.Curve.easeOutPow= static method will be used for resolving positive number values of =curveFUNCorFLOAT=.
|
350 |
+
|
351 |
+
- =true= - When the value =true= is specified, the =Uize.Curve.easeInSweetPow= static method will be used for resolving negative number values of =curveFUNCorFLOAT=, and the =Uize.Curve.easeOutSweetPow= static method will be used for resolving positive number values of =curveFUNCorFLOAT=.
|
352 |
+
|
353 |
+
When the optional =sweetBOOL= parameter is not specified, its value will be defaulted to =false=.
|
354 |
+
|
355 |
+
polarityINT
|
356 |
+
An integer, specifying whether or not numerical values for the =curveFUNCorFLOAT= parameter should be negated (ie. multiplied by =-1=).
|
357 |
+
|
358 |
+
- =1= - When the value =1= is specified, numerical values for =curveFUNCorFLOAT= will be unaltered.
|
359 |
+
|
360 |
+
- =-1= - When the value =-1= is specified, numerical values for =curveFUNCorFLOAT= will be negated.
|
361 |
+
|
362 |
+
When the optional =polarityINT= parameter is not specified, its value will be defaulted to =1=.
|
363 |
+
|
364 |
+
Variations
|
365 |
+
VARIATION 1
|
366 |
+
...................................................................................
|
367 |
+
curveFUNC = Uize.Curve.resolve (curveFUNCorFLOAT,defaultCurveFUNCorFLOATsweetBOOL);
|
368 |
+
...................................................................................
|
369 |
+
|
370 |
+
When the optional =polarityINT= parameter is not specified, its value will be defaulted to =1= and there will be no polarity inversion when a number is specified for the =curveFUNCorFLOAT= parameter.
|
371 |
+
|
372 |
+
VARIATION 2
|
373 |
+
..........................................................................
|
374 |
+
curveFUNC = Uize.Curve.resolve (curveFUNCorFLOAT,defaultCurveFUNCorFLOAT);
|
375 |
+
..........................................................................
|
376 |
+
|
377 |
+
When the optional =sweetBOOL= parameter is not specified, its value will be defaulted to =false= and the standard power curve function generators =Uize.Curve.easeInPow= and =Uize.Curve.easeOutPow= will be used when a number is specified for the =curveFUNCorFLOAT= parameter.
|
378 |
+
|
379 |
+
VARIATION 3
|
380 |
+
..................................................
|
381 |
+
curveFUNC = Uize.Curve.resolve (curveFUNCorFLOAT);
|
382 |
+
..................................................
|
383 |
+
|
384 |
+
When the optional =defaultCurveFUNCorFLOAT= parameter is not specified, its value will be defaulted to =Uize.Curve.linear= and a linear curve function will be returned when the values =null= or =undefined= are specified for the =curveFUNCorFLOAT= parameter.
|
385 |
+
|
386 |
+
VARIATION 4
|
387 |
+
..................................
|
388 |
+
curveFUNC = Uize.Curve.resolve ();
|
389 |
+
..................................
|
390 |
+
|
391 |
+
When no parameters are specified, then a linear curve function (a reference to =Uize.Curve.linear=) will be returned.
|
392 |
+
*/
|
393 |
+
};
|
394 |
+
|
395 |
+
/*** Curve Function Generators ***/
|
396 |
+
var _optimizedPowerCurveMap = {
|
397 |
+
.5:Math.sqrt,
|
398 |
+
1:_linear,
|
399 |
+
2:function (_value) {return _value * _value * (_value > 0 || -1)},
|
400 |
+
3:function (_value) {return _value * _value * _value},
|
401 |
+
4:function (_value) {return _value * _value * _value * _value * (_value > 0 || -1)},
|
402 |
+
5:function (_value) {return _value * _value * _value * _value * _value}
|
403 |
+
};
|
404 |
+
_makeEasingCurveGenerators (
|
405 |
+
'pow',
|
406 |
+
function (_power) {
|
407 |
+
return (
|
408 |
+
_optimizedPowerCurveMap [_power || (_power = 2)] ||
|
409 |
+
function (_value) {return Math.pow (_value * (_value > 0 || -1),_power) * (_value > 0 || -1)}
|
410 |
+
);
|
411 |
+
},
|
412 |
+
_package
|
413 |
+
/*?
|
414 |
+
Static Methods
|
415 |
+
Uize.Curve.easeInPow
|
416 |
+
Power easing in - accelerating from zero velocity, where the power can be specified.
|
417 |
+
|
418 |
+
SYNTAX
|
419 |
+
..............................................
|
420 |
+
curveFUNC = Uize.Curve.easeInPow (powerFLOAT);
|
421 |
+
..............................................
|
422 |
+
|
423 |
+
This method returns optimized curve functions for the powers =.5= (square root), =1= (linear), =2= (squared / quadratic), =3= (cubic), =4= (quartic), and =5= (quintic).
|
424 |
+
|
425 |
+
NOTES
|
426 |
+
- compare to the =Uize.Curve.easeInSweetPow= curve function generator
|
427 |
+
- see also the companion =Uize.Curve.easeOutPow=, =Uize.Curve.easeInOutPow=, and =Uize.Curve.easeMiddlePow= static methods
|
428 |
+
|
429 |
+
Uize.Curve.easeOutPow
|
430 |
+
Power easing out - decelerating to zero velocity, where the power can be specified.
|
431 |
+
|
432 |
+
SYNTAX
|
433 |
+
...............................................
|
434 |
+
curveFUNC = Uize.Curve.easeOutPow (powerFLOAT);
|
435 |
+
...............................................
|
436 |
+
|
437 |
+
This method returns optimized curve functions for the powers =.5= (square root), =1= (linear), =2= (squared / quadratic), =3= (cubic), =4= (quartic), and =5= (quintic).
|
438 |
+
|
439 |
+
NOTES
|
440 |
+
- compare to the =Uize.Curve.easeOutSweetPow= curve function generator
|
441 |
+
- see also the companion =Uize.Curve.easeInPow=, =Uize.Curve.easeInOutPow=, and =Uize.Curve.easeMiddlePow= static methods
|
442 |
+
|
443 |
+
Uize.Curve.easeInOutPow
|
444 |
+
Power easing in/out - acceleration until halfway, then deceleration, where the power can be specified.
|
445 |
+
|
446 |
+
SYNTAX
|
447 |
+
.................................................
|
448 |
+
curveFUNC = Uize.Curve.easeInOutPow (powerFLOAT);
|
449 |
+
.................................................
|
450 |
+
|
451 |
+
This method returns optimized curve functions for the powers =.5= (square root), =1= (linear), =2= (squared / quadratic), =3= (cubic), =4= (quartic), and =5= (quintic).
|
452 |
+
|
453 |
+
NOTES
|
454 |
+
- compare to the =Uize.Curve.easeInOutSweetPow= curve function generator
|
455 |
+
- see also the companion =Uize.Curve.easeInPow=, =Uize.Curve.easeOutPow=, and =Uize.Curve.easeMiddlePow= static methods
|
456 |
+
|
457 |
+
Uize.Curve.easeMiddlePow
|
458 |
+
Power easing in the middle - deceleration until halfway, then acceleration, where the power can be specified.
|
459 |
+
|
460 |
+
SYNTAX
|
461 |
+
..................................................
|
462 |
+
curveFUNC = Uize.Curve.easeMiddlePow (powerFLOAT);
|
463 |
+
..................................................
|
464 |
+
|
465 |
+
This method returns optimized curve functions for the powers =.5= (square root), =1= (linear), =2= (squared / quadratic), =3= (cubic), =4= (quartic), and =5= (quintic).
|
466 |
+
|
467 |
+
NOTES
|
468 |
+
- compare to the =Uize.Curve.easeMiddleSweetPow= curve function generator
|
469 |
+
- see also the companion =Uize.Curve.easeInPow=, =Uize.Curve.easeOutPow=, and =Uize.Curve.easeInOutPow= static methods
|
470 |
+
*/
|
471 |
+
);
|
472 |
+
|
473 |
+
_makeEasingCurveGenerators (
|
474 |
+
'sweetPow',
|
475 |
+
function (_power) {
|
476 |
+
return function (_value) {
|
477 |
+
var
|
478 |
+
_inPow = _package.easeInPow (_power),
|
479 |
+
_inverseInPow = _package.easeInPow (1 / _power)
|
480 |
+
;
|
481 |
+
return (_inPow (_value) + 1 - _inverseInPow (1 - _value)) / 2;
|
482 |
+
}
|
483 |
+
},
|
484 |
+
_package
|
485 |
+
/*?
|
486 |
+
Static Methods
|
487 |
+
Uize.Curve.easeInSweetPow
|
488 |
+
Sweetened power easing in - accelerating from zero velocity, where the power can be specified.
|
489 |
+
|
490 |
+
SYNTAX
|
491 |
+
...................................................
|
492 |
+
curveFUNC = Uize.Curve.easeInSweetPow (powerFLOAT);
|
493 |
+
...................................................
|
494 |
+
|
495 |
+
A standard power curve is "sweetened" by blending it equally with the 180 degree rotated version of its corresponding inverse power curve, producing a curve that is closer to being circular.
|
496 |
+
|
497 |
+
NOTES
|
498 |
+
- compare to the =Uize.Curve.easeInPow= curve function generator
|
499 |
+
- see also the companion =Uize.Curve.easeOutSweetPow=, =Uize.Curve.easeInOutSweetPow=, and =Uize.Curve.easeMiddleSweetPow= static methods
|
500 |
+
|
501 |
+
Uize.Curve.easeOutSweetPow
|
502 |
+
Sweetened power easing out - decelerating to zero velocity, where the power can be specified.
|
503 |
+
|
504 |
+
SYNTAX
|
505 |
+
....................................................
|
506 |
+
curveFUNC = Uize.Curve.easeOutSweetPow (powerFLOAT);
|
507 |
+
....................................................
|
508 |
+
|
509 |
+
A standard power curve is "sweetened" by blending it equally with the 180 degree rotated version of its corresponding inverse power curve, producing a curve that is closer to being circular.
|
510 |
+
|
511 |
+
NOTES
|
512 |
+
- compare to the =Uize.Curve.easeOutPow= curve function generator
|
513 |
+
- see also the companion =Uize.Curve.easeInSweetPow=, =Uize.Curve.easeInOutSweetPow=, and =Uize.Curve.easeMiddleSweetPow= static methods
|
514 |
+
|
515 |
+
Uize.Curve.easeInOutSweetPow
|
516 |
+
Sweetened power easing in/out - acceleration until halfway, then deceleration, where the power can be specified.
|
517 |
+
|
518 |
+
SYNTAX
|
519 |
+
......................................................
|
520 |
+
curveFUNC = Uize.Curve.easeInOutSweetPow (powerFLOAT);
|
521 |
+
......................................................
|
522 |
+
|
523 |
+
A standard power curve is "sweetened" by blending it equally with the 180 degree rotated version of its corresponding inverse power curve, producing a curve that is closer to being circular.
|
524 |
+
|
525 |
+
NOTES
|
526 |
+
- compare to the =Uize.Curve.easeInOutPow= curve function generator
|
527 |
+
- see also the companion =Uize.Curve.easeInSweetPow=, =Uize.Curve.easeOutSweetPow=, and =Uize.Curve.easeMiddleSweetPow= static methods
|
528 |
+
|
529 |
+
Uize.Curve.easeMiddleSweetPow
|
530 |
+
Sweetened power easing in the middle - deceleration until halfway, then acceleration, where the power can be specified.
|
531 |
+
|
532 |
+
SYNTAX
|
533 |
+
.......................................................
|
534 |
+
curveFUNC = Uize.Curve.easeMiddleSweetPow (powerFLOAT);
|
535 |
+
.......................................................
|
536 |
+
|
537 |
+
A standard power curve is "sweetened" by blending it equally with the 180 degree rotated version of its corresponding inverse power curve, producing a curve that is closer to being circular.
|
538 |
+
|
539 |
+
NOTES
|
540 |
+
- compare to the =Uize.Curve.easeMiddlePow= curve function generator
|
541 |
+
- see also the companion =Uize.Curve.easeInSweetPow=, =Uize.Curve.easeOutSweetPow=, and =Uize.Curve.easeInOutSweetPow= static methods
|
542 |
+
*/
|
543 |
+
);
|
544 |
+
|
545 |
+
_makeEasingCurveGenerators (
|
546 |
+
'expo',
|
547 |
+
function () {return function (_value) {return _value && Math.pow (2,10 * (_value - 1))}},
|
548 |
+
_package
|
549 |
+
/*?
|
550 |
+
Static Methods
|
551 |
+
Uize.Curve.easeInExpo
|
552 |
+
Exponential easing in - accelerating from zero velocity.
|
553 |
+
|
554 |
+
SYNTAX
|
555 |
+
.....................................
|
556 |
+
curveFUNC = Uize.Curve.easeInExpo ();
|
557 |
+
.....................................
|
558 |
+
|
559 |
+
NOTES
|
560 |
+
- see also the companion =Uize.Curve.easeOutExpo=, =Uize.Curve.easeInOutExpo=, and =Uize.Curve.easeMiddleExpo= static methods
|
561 |
+
- thanks to `Robert Penner` for his original implementation
|
562 |
+
|
563 |
+
Uize.Curve.easeOutExpo
|
564 |
+
Exponential easing out - decelerating to zero velocity.
|
565 |
+
|
566 |
+
SYNTAX
|
567 |
+
......................................
|
568 |
+
curveFUNC = Uize.Curve.easeOutExpo ();
|
569 |
+
......................................
|
570 |
+
|
571 |
+
NOTES
|
572 |
+
- see also the companion =Uize.Curve.easeInExpo=, =Uize.Curve.easeInOutExpo=, and =Uize.Curve.easeMiddleExpo= static methods
|
573 |
+
- thanks to `Robert Penner` for his original implementation
|
574 |
+
|
575 |
+
Uize.Curve.easeInOutExpo
|
576 |
+
Exponential easing in/out - accelerating until halfway, then decelerating.
|
577 |
+
|
578 |
+
SYNTAX
|
579 |
+
........................................
|
580 |
+
curveFUNC = Uize.Curve.easeInOutExpo ();
|
581 |
+
........................................
|
582 |
+
|
583 |
+
NOTES
|
584 |
+
- see also the companion =Uize.Curve.easeInExpo=, =Uize.Curve.easeOutExpo=, and =Uize.Curve.easeMiddleExpo= static methods
|
585 |
+
- thanks to `Robert Penner` for his original implementation
|
586 |
+
|
587 |
+
Uize.Curve.easeMiddleExpo
|
588 |
+
Exponential easing in the middle - decelerating until halfway, then accelerating.
|
589 |
+
|
590 |
+
SYNTAX
|
591 |
+
.........................................
|
592 |
+
curveFUNC = Uize.Curve.easeMiddleExpo ();
|
593 |
+
.........................................
|
594 |
+
|
595 |
+
NOTES
|
596 |
+
- see also the companion =Uize.Curve.easeInExpo=, =Uize.Curve.easeOutExpo=, and =Uize.Curve.easeInOutExpo= static methods
|
597 |
+
- thanks to `Robert Penner` for his original implementation
|
598 |
+
*/
|
599 |
+
);
|
600 |
+
|
601 |
+
_makeEasingCurveGenerators (
|
602 |
+
'circular',
|
603 |
+
function (_power) {
|
604 |
+
return (
|
605 |
+
_power == 1
|
606 |
+
? _linear
|
607 |
+
: _power == _undefined || _power == 2
|
608 |
+
?
|
609 |
+
function (_value) {
|
610 |
+
return 1 - Math.sqrt (Math.abs (_value = 1 - _value * _value)) * (_value > 0 || -1)
|
611 |
+
}
|
612 |
+
:
|
613 |
+
function (_value) {
|
614 |
+
return 1 - Math.pow (Math.abs (_value = 1 - Math.pow (_value,_power)),1 / _power) * (_value > 0 || -1);
|
615 |
+
}
|
616 |
+
);
|
617 |
+
},
|
618 |
+
_package
|
619 |
+
/*?
|
620 |
+
Static Methods
|
621 |
+
Uize.Curve.easeInCircular
|
622 |
+
Circular easing in - accelerating from zero velocity.
|
623 |
+
|
624 |
+
SYNTAX
|
625 |
+
.........................................
|
626 |
+
curveFUNC = Uize.Curve.easeInCircular ();
|
627 |
+
.........................................
|
628 |
+
|
629 |
+
VARIATION
|
630 |
+
....................................................
|
631 |
+
curveFUNC = Uize.Curve.easeInCircular (powerFLOAT);
|
632 |
+
....................................................
|
633 |
+
|
634 |
+
When the optional =powerFLOAT= parameter is specified, a curve function can be generated that is not perfectly circular but still has the property of being symmetrical with respect to the diagonal that runs from bottom left to top right. When the =powerFLOAT= parameter is not specified, the value =2= is used as its default. Values higher than =2= will produce curves that bend down towards the bottom right corner, and positive values lower than =2= will produce curves that bend upwards towards the top left corner (=0= being the most extreme). The value =1= will produce a linear curve, and values between =1= and =2= will produce curves that are between perfectly linear and perfectly circular.
|
635 |
+
|
636 |
+
NOTES
|
637 |
+
- see also the companion =Uize.Curve.easeOutCircular=, =Uize.Curve.easeInOutCircular=, and =Uize.Curve.easeMiddleCircular= static methods
|
638 |
+
- thanks to `Robert Penner` for his original implementation
|
639 |
+
|
640 |
+
Uize.Curve.easeOutCircular
|
641 |
+
Circular easing out - decelerating to zero velocity.
|
642 |
+
|
643 |
+
SYNTAX
|
644 |
+
..........................................
|
645 |
+
curveFUNC = Uize.Curve.easeOutCircular ();
|
646 |
+
..........................................
|
647 |
+
|
648 |
+
VARIATION
|
649 |
+
....................................................
|
650 |
+
curveFUNC = Uize.Curve.easeOutCircular (powerFLOAT);
|
651 |
+
....................................................
|
652 |
+
|
653 |
+
When the optional =powerFLOAT= parameter is specified, a curve function can be generated that is not perfectly circular but still has the property of being symmetrical with respect to the diagonal that runs from bottom left to top right. When the =powerFLOAT= parameter is not specified, the value =2= is used as its default. Values higher than =2= will produce curves that bend upwards towards the top left corner, and positive values lower than =2= will produce curves that bend downwards towards the bottom right corner (=0= being the most extreme). The value =1= will produce a linear curve, and values between =1= and =2= will produce curves that are between perfectly linear and perfectly circular.
|
654 |
+
|
655 |
+
NOTES
|
656 |
+
- see also the companion =Uize.Curve.easeInCircular=, =Uize.Curve.easeInOutCircular=, and =Uize.Curve.easeMiddleCircular= static methods
|
657 |
+
- thanks to `Robert Penner` for his original implementation
|
658 |
+
|
659 |
+
Uize.Curve.easeInOutCircular
|
660 |
+
Circular easing in/out - acceleration until halfway, then deceleration.
|
661 |
+
|
662 |
+
SYNTAX
|
663 |
+
............................................
|
664 |
+
curveFUNC = Uize.Curve.easeInOutCircular ();
|
665 |
+
............................................
|
666 |
+
|
667 |
+
VARIATION
|
668 |
+
......................................................
|
669 |
+
curveFUNC = Uize.Curve.easeInOutCircular (powerFLOAT);
|
670 |
+
......................................................
|
671 |
+
|
672 |
+
When the optional =powerFLOAT= parameter is specified, a curve function can be generated that is not perfectly circular but still has the property of being symmetrical with respect to the diagonal that runs from bottom left to top right. When the =powerFLOAT= parameter is not specified, the value =2= is used as its default. Values higher than =2= and positive values lower than =2= will produce curves that bend more extremely towards the corners. The value =1= will produce a linear curve, and values between =1= and =2= will produce curves that are between perfectly linear and perfectly circular.
|
673 |
+
|
674 |
+
NOTES
|
675 |
+
- see also the companion =Uize.Curve.easeInCircular=, =Uize.Curve.easeInCircular=, and =Uize.Curve.easeMiddleCircular= static methods
|
676 |
+
- thanks to `Robert Penner` for his original implementation
|
677 |
+
|
678 |
+
Uize.Curve.easeMiddleCircular
|
679 |
+
Circular easing in the middle - deceleration until halfway, then acceleration.
|
680 |
+
|
681 |
+
SYNTAX
|
682 |
+
.............................................
|
683 |
+
curveFUNC = Uize.Curve.easeMiddleCircular ();
|
684 |
+
.............................................
|
685 |
+
|
686 |
+
VARIATION
|
687 |
+
.......................................................
|
688 |
+
curveFUNC = Uize.Curve.easeMiddleCircular (powerFLOAT);
|
689 |
+
.......................................................
|
690 |
+
|
691 |
+
When the optional =powerFLOAT= parameter is specified, a curve function can be generated that is not perfectly circular but still has the property of being symmetrical with respect to the diagonal that runs from bottom left to top right. When the =powerFLOAT= parameter is not specified, the value =2= is used as its default. Values higher than =2= and positive values lower than =2= will produce curves that bend more extremely towards the corners. The value =1= will produce a linear curve, and values between =1= and =2= will produce curves that are between perfectly linear and perfectly circular.
|
692 |
+
|
693 |
+
NOTES
|
694 |
+
- see also the companion =Uize.Curve.easeInCircular=, =Uize.Curve.easeOutCircular=, and =Uize.Curve.easeInOutCircular= static methods
|
695 |
+
- thanks to `Robert Penner` for his original implementation
|
696 |
+
*/
|
697 |
+
);
|
698 |
+
|
699 |
+
_makeEasingCurveGenerators (
|
700 |
+
'sine',
|
701 |
+
function () {
|
702 |
+
var _piDiv2 = Math.PI / 2;
|
703 |
+
return function (_value) {return 1 - Math.cos (_value * _piDiv2)};
|
704 |
+
},
|
705 |
+
_package
|
706 |
+
/*?
|
707 |
+
Static Methods
|
708 |
+
Uize.Curve.easeInSine
|
709 |
+
Sinusoidal easing in - accelerating from zero velocity.
|
710 |
+
|
711 |
+
SYNTAX
|
712 |
+
.....................................
|
713 |
+
curveFUNC = Uize.Curve.easeInSine ();
|
714 |
+
.....................................
|
715 |
+
|
716 |
+
NOTES
|
717 |
+
- see also the companion =Uize.Curve.easeOutSine=, =Uize.Curve.easeInOutSine=, and =Uize.Curve.easeMiddleSine= static methods
|
718 |
+
- thanks to `Robert Penner` for his original implementation
|
719 |
+
|
720 |
+
Uize.Curve.easeOutSine
|
721 |
+
Sinusoidal easing out - decelerating to zero velocity.
|
722 |
+
|
723 |
+
SYNTAX
|
724 |
+
......................................
|
725 |
+
curveFUNC = Uize.Curve.easeOutSine ();
|
726 |
+
......................................
|
727 |
+
|
728 |
+
NOTES
|
729 |
+
- see also the companion =Uize.Curve.easeInSine=, =Uize.Curve.easeInOutSine=, and =Uize.Curve.easeMiddleSine= static methods
|
730 |
+
- thanks to `Robert Penner` for his original implementation
|
731 |
+
|
732 |
+
Uize.Curve.easeInOutSine
|
733 |
+
Sinusoidal easing in/out - accelerating until halfway, then decelerating.
|
734 |
+
|
735 |
+
SYNTAX
|
736 |
+
........................................
|
737 |
+
curveFUNC = Uize.Curve.easeInOutSine ();
|
738 |
+
........................................
|
739 |
+
|
740 |
+
NOTES
|
741 |
+
- see also the companion =Uize.Curve.easeInSine=, =Uize.Curve.easeOutSine=, and =Uize.Curve.easeMiddleSine= static methods
|
742 |
+
- thanks to `Robert Penner` for his original implementation
|
743 |
+
|
744 |
+
Uize.Curve.easeMiddleSine
|
745 |
+
Sinusoidal easing in the middle - decelerating until halfway, then accelerating.
|
746 |
+
|
747 |
+
SYNTAX
|
748 |
+
.........................................
|
749 |
+
curveFUNC = Uize.Curve.easeMiddleSine ();
|
750 |
+
.........................................
|
751 |
+
|
752 |
+
NOTES
|
753 |
+
- see also the companion =Uize.Curve.easeInSine=, =Uize.Curve.easeOutSine=, and =Uize.Curve.easeInOutSine= static methods
|
754 |
+
- thanks to `Robert Penner` for his original implementation
|
755 |
+
*/
|
756 |
+
);
|
757 |
+
|
758 |
+
_package.line = function (_startValue,_endValue) {
|
759 |
+
if (_endValue == _undefined) {
|
760 |
+
if (_startValue == _undefined) {
|
761 |
+
_startValue = 0;
|
762 |
+
_endValue = 1;
|
763 |
+
} else {
|
764 |
+
_endValue = _startValue;
|
765 |
+
}
|
766 |
+
}
|
767 |
+
var _delta = _endValue - _startValue;
|
768 |
+
return (
|
769 |
+
!_startValue && _endValue == 1
|
770 |
+
? _linear
|
771 |
+
: _delta
|
772 |
+
? function (_value) {return _startValue + _delta * _value}
|
773 |
+
: function () {return _startValue}
|
774 |
+
|
775 |
+
);
|
776 |
+
/*?
|
777 |
+
Static Methods
|
778 |
+
Uize.Curve.line
|
779 |
+
Returns a curve function, being a linear curve between the specified start and end values.
|
780 |
+
|
781 |
+
SYNTAX
|
782 |
+
....................................................................
|
783 |
+
curveFUNC = Uize.Curve.line (startValue0to1FLOAT,endValue0to1FLOAT);
|
784 |
+
....................................................................
|
785 |
+
|
786 |
+
This method allows you to create curve functions that don't observe the `Start At 0, End At 1` rule of curve functions, so it is not always appropriate for use in controlling fades. This method is more useful for creating value ranges that can be supplied to curve function modifiers that accept value ranges for parameters. Consider the following example of using the =Uize.Curve.Mod.blend= static method...
|
787 |
+
|
788 |
+
EXAMPLE
|
789 |
+
........................................................................
|
790 |
+
Uize.Curve.Mod.blend (
|
791 |
+
Uize.Curve.easeOutPow (4), // ease-out power curve function
|
792 |
+
Uize.Curve.saw (20,.5), // sawtooth curve function with 20 teeth
|
793 |
+
Uize.Curve.line (.25,.75) // line starting at .25 and ending at .75
|
794 |
+
)
|
795 |
+
........................................................................
|
796 |
+
|
797 |
+
In the above example, a quartic ease-out power curve function is being blended with a sawtooth curve function with twenty teeth. The =Uize.Curve.line= method is being used to create a value range from =.25= to =.75= to control the blend between the two curve functions across the range of input values. At the input value of =0=, the blend between the curves will be =.25=. At the input value of =1=, the blend between the curves will be =.75=. At the input value of =.5=, the blend between the curves will be =.5= (the midpoint value of the line curve).
|
798 |
+
|
799 |
+
VARIATION 1
|
800 |
+
..................................................
|
801 |
+
curveFUNC = Uize.Curve.line (startValue0to1FLOAT);
|
802 |
+
..................................................
|
803 |
+
|
804 |
+
When no =endValue0to1FLOAT= parameter is specified (or if the same value is specified for both the =startValue0to1FLOAT= and =endValue0to1FLOAT= parameters), then the curve function returned will be for a flat line that is always at the specified start value (ie. it starts at the start value and ends at the start value).
|
805 |
+
|
806 |
+
VARIATION 2
|
807 |
+
...............................
|
808 |
+
curveFUNC = Uize.Curve.line ();
|
809 |
+
...............................
|
810 |
+
|
811 |
+
When no parameters are specified (or if the value =0= is specified for the =startValue0to1FLOAT= parameter and the value =1= is specified for the =endValue0to1FLOAT= parameter), then a reference to =Uize.Curve.linear= (a linear curve function) will be returned.
|
812 |
+
|
813 |
+
NOTES
|
814 |
+
- compare to the =Uize.Curve.linear= static method
|
815 |
+
*/
|
816 |
+
};
|
817 |
+
|
818 |
+
_package.saw = function (_repeats,_amount) {
|
819 |
+
return (
|
820 |
+
_repeats == 1 || !(_amount = Uize.toNumber (_amount,1))
|
821 |
+
? _linear
|
822 |
+
: function (_value) {
|
823 |
+
return _blendFloats (_value,_value && ((_value * _repeats) % 1 || 1),_amount)
|
824 |
+
}
|
825 |
+
);
|
826 |
+
/*?
|
827 |
+
Static Methods
|
828 |
+
Uize.Curve.saw
|
829 |
+
Returns a sawtooth curve function, where the number of teeth and the amount of the sawtooth effect can be specified.
|
830 |
+
|
831 |
+
SYNTAX
|
832 |
+
........................................................
|
833 |
+
curveFUNC = Uize.Curve.saw (repeatsINT,amount0to1FLOAT);
|
834 |
+
........................................................
|
835 |
+
|
836 |
+
PARAMETERS
|
837 |
+
|
838 |
+
- =repeatsINT= - controls the number of "teeth" in the sawtooth curve.
|
839 |
+
|
840 |
+
- =amount0to1FLOAT= - a floating point number in the range of =0= to =1=. Specifying the value =0= for this parameter will produce a curve function for a simple linear curve, specifying the value =1= will produce a curve function where each tooth reaches all the way from =0= up to =1=, and specifying the value =.5= will produce an equal blend between a linear curve and a harsh sawtooth pattern. Any other values will produce different blends between fully linear and fully sawtooth.
|
841 |
+
|
842 |
+
VARIATION
|
843 |
+
........................................
|
844 |
+
curveFUNC = Uize.Curve.saw (repeatsINT);
|
845 |
+
........................................
|
846 |
+
|
847 |
+
When no =amount0to1FLOAT= parameter is specified, the value =1= is used as the default. This produces a harsh sawtooth curve function, with each tooth using the full vertical range of =0= to =1=.
|
848 |
+
*/
|
849 |
+
};
|
850 |
+
|
851 |
+
return _package;
|
852 |
+
}
|
853 |
+
});
|
854 |
+
|
skin/frontend/default/customproduct/js/Uize.Data.Combinations.js
ADDED
@@ -0,0 +1,725 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Data.Combinations Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 1
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 100
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Data.Combinations= module provides methods for generating object or array combinations from a `combination specifier`, with support for an optional combination transformer and combination matcher.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
In a Nutshell
|
27 |
+
The methods of the =Uize.Data.Combinations= module make it easy to produce a large set of combinations in a highly performant way.
|
28 |
+
|
29 |
+
Scalable
|
30 |
+
The =Uize.Data.Combinations= module is scalable in its ability to support an arbitrary number of combination properties.
|
31 |
+
|
32 |
+
Whereas a typical approach to producing combinations might involve nested =for= loop structures, this approach can only support a fixed number of properties and does not scale well to support an arbitrary or dynamic number of properties. The =Uize.Data.Combinations= module can support an arbitrary and also very large number of combination properties without trouble.
|
33 |
+
|
34 |
+
Performant
|
35 |
+
The =Uize.Data.Combinations= module is implemented to be highly performant, avoiding the use of recursion or the repeated creation and destruction of partial results sets.
|
36 |
+
|
37 |
+
The =Uize.Data.Combinations= module uses an approach much like generating all possible numbers up to a maximum number. In this way, the module can implement combination generation using just two levels of loop nesting, regardless of how many properties there are in the `combination specifier`. No recursion is used, thereby reducing function call overhead and call stack bloat.
|
38 |
+
|
39 |
+
The Methods
|
40 |
+
The =Uize.Data.Combinations= module provides the following static methods to deal with generated combinations...
|
41 |
+
|
42 |
+
- =Uize.Data.Combinations.forEach= - lets you iterate through generated combinations, executing the specified iteration handler function for each combination
|
43 |
+
- =Uize.Data.Combinations.generate= - produces an array containing the generated combinations
|
44 |
+
|
45 |
+
How Combinations Are Generated
|
46 |
+
Combinations are generated using a `combination specifier` that provides a template for the combinations, along with an `optional combination transformer` that can be used to modify the generated combinations, and an `optional combination matcher` that can be used to filter the combinations.
|
47 |
+
|
48 |
+
Combination Specifier
|
49 |
+
The `combination specifier` lets you specify a kind of template for the generated combinations, with possible values for each property or element.
|
50 |
+
|
51 |
+
When the Combination Specifier is an Object
|
52 |
+
If the `combination specifier` is an object, then each property of the object represents a property of the generated combinations, and the value for each property specifies the possible values for that property that should be iterated through when generating the combinations.
|
53 |
+
|
54 |
+
Consider the following example of generating combinations of car specifications...
|
55 |
+
|
56 |
+
EXAMPLE
|
57 |
+
.................................................
|
58 |
+
var cars = Uize.Data.Combinations.generate ({
|
59 |
+
headlights:['regular','xenon','LED'],
|
60 |
+
tires:['regular','low profile','fatty'],
|
61 |
+
roof:['regular','sun roof','convertible'],
|
62 |
+
upholstery:['regular','micro suede','leather']
|
63 |
+
});
|
64 |
+
.................................................
|
65 |
+
|
66 |
+
With the above `combination specifier`, the =Uize.Data.Combinations.generate= method would produce combinations as follows...
|
67 |
+
|
68 |
+
COMBINATIONS
|
69 |
+
........................................................................................
|
70 |
+
[
|
71 |
+
{headlights:'regular',hubcaps:'regular',roof:'regular',upholstery:'regular'},
|
72 |
+
{headlights:'regular',hubcaps:'regular',roof:'regular',upholstery:'micro suede'},
|
73 |
+
{headlights:'regular',hubcaps:'regular',roof:'regular',upholstery:'leather'},
|
74 |
+
{headlights:'regular',hubcaps:'regular',roof:'sun roof',upholstery:'regular'},
|
75 |
+
{headlights:'regular',hubcaps:'regular',roof:'sun roof',upholstery:'micro suede'},
|
76 |
+
{headlights:'regular',hubcaps:'regular',roof:'sun roof',upholstery:'leather'},
|
77 |
+
{headlights:'regular',hubcaps:'regular',roof:'convertible',upholstery:'regular'},
|
78 |
+
{headlights:'regular',hubcaps:'regular',roof:'convertible',upholstery:'micro suede'},
|
79 |
+
{headlights:'regular',hubcaps:'regular',roof:'convertible',upholstery:'leather'},
|
80 |
+
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
|
81 |
+
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
|
82 |
+
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
|
83 |
+
]
|
84 |
+
........................................................................................
|
85 |
+
|
86 |
+
As you may notice from the above sample of the output combinations, the combinations are produced by cycling through the possible values starting from the last property in the `combination specifier` (=upholstery= in this example), and then working steadily towards the first property in the `combination specifier` as the possible values "clock over". Looking at our example `combination specifier`, we can tell that the =Uize.Data.Combinations.generate= method would produce =81= combinations: three possible values for =headlights=, times three possible values for =tires=, times three possible values for =roof=, times three possible values for =upholstery=.
|
87 |
+
|
88 |
+
When the Combination Specifier is an Array
|
89 |
+
If the `combination specifier` is an array, then each element of the array represents an element of a generated combination array, and the value for each element specifies the possible values for that element that should be iterated through when generating the combinations.
|
90 |
+
|
91 |
+
Consider the following example of generating combinations of Web safe color tuples...
|
92 |
+
|
93 |
+
EXAMPLE
|
94 |
+
.................................................................................
|
95 |
+
Uize.Data.Combinations.generate ([
|
96 |
+
['00','33','66','99','CC','FF'], // possible values for red channel element
|
97 |
+
['00','33','66','99','CC','FF'], // possible values for green channel element
|
98 |
+
['00','33','66','99','CC','FF'] // possible values for blue channel element
|
99 |
+
]);
|
100 |
+
.................................................................................
|
101 |
+
|
102 |
+
With the above `combination specifier`, the =Uize.Data.Combinations.generate= method would produce combinations as follows...
|
103 |
+
|
104 |
+
COMBINATIONS
|
105 |
+
......................
|
106 |
+
[
|
107 |
+
['00','00','00'],
|
108 |
+
['00','00','33'],
|
109 |
+
['00','00','66'],
|
110 |
+
['00','00','99'],
|
111 |
+
['00','00','CC'],
|
112 |
+
['00','00','FF'],
|
113 |
+
['00','33','00'],
|
114 |
+
['00','33','33'],
|
115 |
+
['00','33','66'],
|
116 |
+
['00','33','99'],
|
117 |
+
['00','33','CC'],
|
118 |
+
['00','33','FF'],
|
119 |
+
... ... ... ... ...
|
120 |
+
... ... ... ... ...
|
121 |
+
... ... ... ... ...
|
122 |
+
]
|
123 |
+
......................
|
124 |
+
|
125 |
+
As is the case `when the combination specifier is an object`, the combinations are produced by cycling through the possible values starting from the last element in the `combination specifier` array (the blue channel's color value in this example), and then working steadily towards the first element in the `combination specifier` as the possible values "clock over". Looking at our example `combination specifier`, we can tell that the =Uize.Data.Combinations.generate= method would produce =216= combinations: six possible values for the red channel, times six possible values for the green channel, times six possible values for the blue channel.
|
126 |
+
|
127 |
+
More on Specifying Possible Values
|
128 |
+
When the Possible Values is Not an Array
|
129 |
+
If the value of a property in the `combination specifier` is anything other than a list of possible values, then the value is treated as the single possible value for the property in the generated combinations.
|
130 |
+
|
131 |
+
EXAMPLE
|
132 |
+
..........................................
|
133 |
+
Uize.Data.Combinations.generate ({
|
134 |
+
headlights:'regular',
|
135 |
+
tires:['regular','low profile','fatty']
|
136 |
+
});
|
137 |
+
..........................................
|
138 |
+
|
139 |
+
In the above example, the value ='regular'= is the only possible value for the =headlights= property of the generated combinations. It could be specified as an array with only a single element, as in =['regular']=, but this is not necessary with the =Uize.Data.Combinations= module. The above statement would produce the following result...
|
140 |
+
|
141 |
+
RESULT
|
142 |
+
..............................................
|
143 |
+
[
|
144 |
+
{headlights:'regular',tires:'regular'},
|
145 |
+
{headlights:'regular',tires:'low profile'},
|
146 |
+
{headlights:'regular',tires:'fatty'}
|
147 |
+
]
|
148 |
+
..............................................
|
149 |
+
|
150 |
+
When There is Only One Possible Value
|
151 |
+
When there is only one possible value for a property in the generated combinations, the possible value can be specified as an array with only one element, or just the possible value can be specified.
|
152 |
+
|
153 |
+
However, if the single possible value is an array, then it must be specified wrapped inside an array. Consider the following example...
|
154 |
+
|
155 |
+
EXAMPLE
|
156 |
+
.............................................
|
157 |
+
Uize.Data.Combinations.generate ({
|
158 |
+
bodyColor:[[255,127,0]],
|
159 |
+
dashboardColor:[[245,132,0],[205,154,78]],
|
160 |
+
tires:'regular'
|
161 |
+
});
|
162 |
+
.............................................
|
163 |
+
|
164 |
+
In the above example, car configuration combinations are being generated. Colors are specified as RGB tuple arrays, and there is only one possible color for the =bodyColor= property. Therefore, the tuple must be wrapped in a possible values array, or otherwise the individual red, green, and blue color channel values would be confused for possible values. In contrast, there is only one possible value for the =tires= property, but the value is a string. Therefore, this one possible value does *not* need to be wrapped inside an array, because there is no ambiguity. The above statement would produce the following result...
|
165 |
+
|
166 |
+
RESULT
|
167 |
+
......................................................................
|
168 |
+
[
|
169 |
+
{bodyColor:[255,127,0],dashboardColor:[245,132,0],tires:'regular'},
|
170 |
+
{bodyColor:[255,127,0],dashboardColor:[205,154,78],tires:'regular'}
|
171 |
+
]
|
172 |
+
......................................................................
|
173 |
+
|
174 |
+
When There Are No Possible Values
|
175 |
+
When the possible values array for a property in the `combination specifier` contains no elements, then this is regarded as there being no possible values for the property and that property is excluded from the generated combinations.
|
176 |
+
|
177 |
+
EXAMPLE
|
178 |
+
...........................................
|
179 |
+
Uize.Data.Combinations.generate ({
|
180 |
+
headlights:'regular',
|
181 |
+
tires:['regular','low profile','fatty'],
|
182 |
+
racingStripes:[]
|
183 |
+
});
|
184 |
+
...........................................
|
185 |
+
|
186 |
+
In the above example of a combination specifier for car configuration combinations, there is only one possible value for the =headlights= property, there are two possible values for the =tires= property, and there are no possible values for the =racingStripes= property. The =headlights= property is included in the generated combinations, with the same one value for each combination. In contrast, the =racingStripes= property is excluded from the generated combinations, since there are no possible values for it. The above statement would produce the following result...
|
187 |
+
|
188 |
+
RESULT
|
189 |
+
..............................................
|
190 |
+
[
|
191 |
+
{headlights:'regular',tires:'regular'},
|
192 |
+
{headlights:'regular',tires:'low profile'},
|
193 |
+
{headlights:'regular',tires:'fatty'}
|
194 |
+
]
|
195 |
+
..............................................
|
196 |
+
|
197 |
+
Optional Combination Transformer
|
198 |
+
Both the =Uize.Data.Combinations.forEach= and =Uize.Data.Combinations.generate= static methods support an optional =combinationTransformerSTRorFUNC= parameter that lets you modify each combination.
|
199 |
+
|
200 |
+
Combination Transformer Function
|
201 |
+
When a function is specified for the optional =combinationTransformerSTRorFUNC= parameter, then the function will be executed for each generated combination.
|
202 |
+
|
203 |
+
The `combination transformer function` can expect two arguments: the combination and the combination number / index. The function can modify the combination passed to it, using the combination index if desired. The function does not need to return a value, however, if the function *does* return a value other than =undefined=, then that value will replace the generated combination. A value returned by the function does not need to be an object - it can be of any type. For example, the returned value could be the combination serialized to a string of some form (see the `Generate Web Safe Color Palette` example).
|
204 |
+
|
205 |
+
EXAMPLE
|
206 |
+
............................................
|
207 |
+
Uize.Data.Combinations.generate (
|
208 |
+
{
|
209 |
+
width:[6,9],
|
210 |
+
length:[10,15],
|
211 |
+
height:[12,21]
|
212 |
+
},
|
213 |
+
function (room,roomNo) {
|
214 |
+
room.area = room.width * room.length;
|
215 |
+
room.volume = room.area * room.height;
|
216 |
+
room.roomNo = roomNo;
|
217 |
+
}
|
218 |
+
);
|
219 |
+
............................................
|
220 |
+
|
221 |
+
In the above example, we are generating different room combinations, where there are two possible options for each of the room properties of =width=, =length=, and =height=. We have specified a custom `combination transformer function` that adds to each room combination object the computed properties =area= and =volume=, while also tagging each combination with a =roomNo= property that is based on the combination index. The above statement would produce the following result...
|
222 |
+
|
223 |
+
RESULT
|
224 |
+
...............................................................
|
225 |
+
[
|
226 |
+
{width:6,length:10,height:12,area:60,volume:720,roomNo:0},
|
227 |
+
{width:6,length:10,height:21,area:60,volume:1260,roomNo:1},
|
228 |
+
{width:6,length:15,height:12,area:90,volume:1080,roomNo:2},
|
229 |
+
{width:6,length:15,height:21,area:90,volume:1890,roomNo:3},
|
230 |
+
{width:9,length:10,height:12,area:90,volume:1080,roomNo:4},
|
231 |
+
{width:9,length:10,height:21,area:90,volume:1890,roomNo:5},
|
232 |
+
{width:9,length:15,height:12,area:135,volume:1620,roomNo:6},
|
233 |
+
{width:9,length:15,height:21,area:135,volume:2835,roomNo:7}
|
234 |
+
]
|
235 |
+
...............................................................
|
236 |
+
|
237 |
+
Combination Transformer Expression String
|
238 |
+
When an expression string is specified for the optional =combinationTransformerSTRorFUNC= parameter, then the expression will be executed for each generated combination.
|
239 |
+
|
240 |
+
The `combination transformer expression string` can expect two variables to be defined in the scope of the expression: the =value= variable which represents the generated combination, and the =key= variable which represents the index of the generated combination. The expression can use these two variables to generate a transformed combination. The result of the expression does not need to be an object - it can be of any type - and this value will be used to replace the generated combination. For example, the returned value could be the combination serialized to a string of some form (see the `Generate Web Safe Color Palette` example).
|
241 |
+
|
242 |
+
EXAMPLE
|
243 |
+
............................................................................
|
244 |
+
Uize.Data.Combinations.generate (
|
245 |
+
{
|
246 |
+
width:[6,9],
|
247 |
+
length:[10,15],
|
248 |
+
height:[12,21]
|
249 |
+
},
|
250 |
+
'value.width + "(W) x " + value.length + "(L) x " + value.height + "(H)"'
|
251 |
+
);
|
252 |
+
............................................................................
|
253 |
+
|
254 |
+
In the above example, we are generating different room combinations, where there are two possible options for each of the room properties of =width=, =length=, and =height=. We have specified a custom `combination transformer expression string` that serializes the room dimensions to a string of the form "6(W) x 10(L) x 12(H)". The above statement would produce the following result...
|
255 |
+
|
256 |
+
RESULT
|
257 |
+
..........................
|
258 |
+
[
|
259 |
+
'6(W) x 10(L) x 12(H)',
|
260 |
+
'6(W) x 10(L) x 21(H)',
|
261 |
+
'6(W) x 15(L) x 12(H)',
|
262 |
+
'6(W) x 15(L) x 21(H)',
|
263 |
+
'9(W) x 10(L) x 12(H)',
|
264 |
+
'9(W) x 10(L) x 21(H)',
|
265 |
+
'9(W) x 15(L) x 12(H)',
|
266 |
+
'9(W) x 15(L) x 21(H)'
|
267 |
+
]
|
268 |
+
..........................
|
269 |
+
|
270 |
+
Optional Combination Matcher
|
271 |
+
Both the =Uize.Data.Combinations.forEach= and =Uize.Data.Combinations.generate= static methods support an optional =combinationMatcherSTRorFUNC= parameter that lets you filter the generated combinations.
|
272 |
+
|
273 |
+
Combination Matcher Function
|
274 |
+
When a function is specified for the optional =combinationMatcherSTRorFUNC= parameter, then the function will be executed for each generated combination.
|
275 |
+
|
276 |
+
The `combination matcher function` can expect two arguments: the combination and the combination number / index. The function should return a boolean value, indicating whether or not the combination passed to it should be included in the final set of generated combinations that is returned by the =Uize.Data.Combinations.generate= method or iterated over by the =Uize.Data.Combinations.forEach= method.
|
277 |
+
|
278 |
+
EXAMPLE
|
279 |
+
...............................................
|
280 |
+
Uize.Data.Combinations.generate (
|
281 |
+
{
|
282 |
+
width:[6,9],
|
283 |
+
length:[10,15],
|
284 |
+
height:[12,21]
|
285 |
+
},
|
286 |
+
function (room,roomNo) {
|
287 |
+
room.area = room.width * room.length;
|
288 |
+
room.volume = room.area * room.height;
|
289 |
+
room.roomNo = roomNo;
|
290 |
+
},
|
291 |
+
function (room) {return room.volume >= 1500}
|
292 |
+
);
|
293 |
+
...............................................
|
294 |
+
|
295 |
+
In the above example, we are generating different room combinations, where there are two possible options for each of the room properties of =width=, =length=, and =height=. Additionally, we have specified a custom `combination matcher function` that is filtering out all rooms whose volume is less than 1500 cubic feet. One interesting thing that you'll notice in this example is that the combination matcher is executed after the `optional combination transformer` (if specified), so it gets to match using the generated combination after the transformer has had its opportunity to modify it by changing or adding properties. The above statement would produce the following result...
|
296 |
+
|
297 |
+
RESULT
|
298 |
+
...............................................................
|
299 |
+
[
|
300 |
+
{width:6,length:15,height:21,area:90,volume:1890,roomNo:3},
|
301 |
+
{width:9,length:10,height:21,area:90,volume:1890,roomNo:5},
|
302 |
+
{width:9,length:15,height:12,area:135,volume:1620,roomNo:6},
|
303 |
+
{width:9,length:15,height:21,area:135,volume:2835,roomNo:7}
|
304 |
+
]
|
305 |
+
...............................................................
|
306 |
+
|
307 |
+
Combination Matcher Expression String
|
308 |
+
When an expression string is specified for the optional =combinationMatcherSTRorFUNC= parameter, then the expression will be executed for each generated combination.
|
309 |
+
|
310 |
+
The `combination matcher expression string` can expect two variables to be defined in the scope of the expression: the =value= variable which represents the generated combination, and the =key= variable which represents the index of the generated combination. The expression can use these two variables to generate a boolean value, indicating whether or not the combination should be included in the final set of generated combinations that is returned by the =Uize.Data.Combinations.generate= method or iterated over by the =Uize.Data.Combinations.forEach= method.
|
311 |
+
|
312 |
+
EXAMPLE
|
313 |
+
............................................
|
314 |
+
Uize.Data.Combinations.generate (
|
315 |
+
{
|
316 |
+
width:[6,9],
|
317 |
+
length:[10,15],
|
318 |
+
height:[12,21]
|
319 |
+
},
|
320 |
+
function (room,roomNo) {
|
321 |
+
room.area = room.width * room.length;
|
322 |
+
room.volume = room.area * room.height;
|
323 |
+
room.roomNo = roomNo;
|
324 |
+
},
|
325 |
+
'value.volume >= 1500'
|
326 |
+
);
|
327 |
+
............................................
|
328 |
+
|
329 |
+
In the above example, we are generating different room combinations, where there are two possible options for each of the room properties of =width=, =length=, and =height=. Additionally, we have specified a custom `combination matcher expression string` that is filtering out all rooms whose volume is less than 1500 cubic feet. The combination matcher is executed after the `optional combination transformer` (if specified), so it gets to match using the generated combination after the transformer has had its opportunity to modify it by changing or adding properties.
|
330 |
+
|
331 |
+
Worth pointing out in this example is that, while the `combination transformer function` can name its value and key arguments as it sees fit (=room= and =roomNo= in this case), the `combination matcher expression string` must use the reserved variable names =value= and =key=. The above statement would produce the following result...
|
332 |
+
|
333 |
+
RESULT
|
334 |
+
...............................................................
|
335 |
+
[
|
336 |
+
{width:6,length:15,height:21,area:90,volume:1890,roomNo:3},
|
337 |
+
{width:9,length:10,height:21,area:90,volume:1890,roomNo:5},
|
338 |
+
{width:9,length:15,height:12,area:135,volume:1620,roomNo:6},
|
339 |
+
{width:9,length:15,height:21,area:135,volume:2835,roomNo:7}
|
340 |
+
]
|
341 |
+
...............................................................
|
342 |
+
|
343 |
+
Transformer, Then Matcher
|
344 |
+
When both an `optional combination transformer` and an `optional combination matcher` are specified, the combination transformer is executed first, before the combination matcher is executed.
|
345 |
+
|
346 |
+
This behavior allows each generated combination to be filtered, taking into account how the combination may have been altered or augmented by the combination transformer. Consider the following example...
|
347 |
+
|
348 |
+
EXAMPLE
|
349 |
+
..........................................................................
|
350 |
+
Uize.Data.Combinations.generate (
|
351 |
+
{
|
352 |
+
firstName: ['Christopher', 'Jan', 'Jonathan', 'Charles', 'Anthony'],
|
353 |
+
lastName: ['Smith', 'von Breugelstein', 'Daniels', 'Pickenson']
|
354 |
+
},
|
355 |
+
function (person) {
|
356 |
+
person.fullName = firstName + ' ' + lastName;
|
357 |
+
},
|
358 |
+
function (person) {
|
359 |
+
return person.fullName.length <= 20;
|
360 |
+
}
|
361 |
+
);
|
362 |
+
..........................................................................
|
363 |
+
|
364 |
+
In the above example, an array of person records is being generated by combining possible values for first name with possible values for last name. This set of person records could be used to feed as dummy data into an automated test process. In this case, we're specifying an `optional combination transformer` to add a =fullName= property to each generated combination. We're also specifying an `optional combination matcher` to filter out / exclude those generated people records where the full name that was constructed in the combination transformer is greater than twenty characters in length.
|
365 |
+
|
366 |
+
The above statement would allow the record with the full name of "Jan von Breugelstein" (exactly twenty characters long), but exclude the record with the full name of "Christopher Pickenson" (twenty one characters long). Importantly, because the `combination transformer function` is executed before the `combination matcher function`, the matcher can access and use the added =fullName= property in its determination.
|
367 |
+
|
368 |
+
Real World Examples
|
369 |
+
Generate Web Safe Color Palette
|
370 |
+
In this example, we are using the =Uize.Data.Combinations.generate= method to generate an array of hex RGB color strings for the full palette of [[http://en.wikipedia.org/wiki/Web_safe_colors#Web-safe_colors][Web safe colors]].
|
371 |
+
|
372 |
+
If we were to approach this problem the traditional way, we would write our code using three nested =for= loops - one for each of the three RGB color channels. This approach would produce code as follows...
|
373 |
+
|
374 |
+
THE TEDIOUS WAY
|
375 |
+
....................................................................................
|
376 |
+
var
|
377 |
+
channelValues = ['00','33','66','99','CC','FF'],
|
378 |
+
webSafeColors = []
|
379 |
+
;
|
380 |
+
for (var redValueNo = 0; redValueNo < channelValues.length; redValueNo++) {
|
381 |
+
for (var greenValueNo = 0; greenValueNo < channelValues.length; greenValueNo++) {
|
382 |
+
for (var blueValueNo = 0; blueValueNo < channelValues.length; blueValueNo++) {
|
383 |
+
webSafeColors.push (
|
384 |
+
'#' +
|
385 |
+
channelValues [redValueNo] +
|
386 |
+
channelValues [greenValueNo] +
|
387 |
+
channelValues [blueValueNo]
|
388 |
+
);
|
389 |
+
}
|
390 |
+
}
|
391 |
+
}
|
392 |
+
....................................................................................
|
393 |
+
|
394 |
+
If we instead use the =Uize.Data.Combinations.generate= method, we can reduce our code down to something more concise and elegant, as follows...
|
395 |
+
|
396 |
+
THE CONCISE WAY
|
397 |
+
....................................................
|
398 |
+
var
|
399 |
+
channelValues = ['00','33','66','99','CC','FF'],
|
400 |
+
webSafeColors = Uize.Data.Combinations.generate (
|
401 |
+
[channelValues,channelValues,channelValues],
|
402 |
+
'"#" + value.join ("")'
|
403 |
+
)
|
404 |
+
;
|
405 |
+
....................................................
|
406 |
+
|
407 |
+
In our solution, we create the variable =channelValues=, whose value is an array representing all the possible values for a color channel in a Web safe color. We then use this possible values array in a `combination specifier` that provides a template for an RGB color tuple. Then, to ensure that the array of generated values is an array of hex formatted RGB color strings, we specify a `combination transformer expression string` that takes a generated combination tuple and joins its three elements and adds a "#" (pound character) prefix.
|
408 |
+
|
409 |
+
Generate Style Combinations For Testing
|
410 |
+
In this example, we are generating a bunch of HTML divs to test various combinations of styling that can be applied using various CSS classes that are used by selectors in a stylesheet.
|
411 |
+
|
412 |
+
Now, given the way we have designed the CSS, we've effectively divided the styling into four different styling dimensions: any div can be styled using one of several possible CSS classes for decorating the border, the padding, the font characteristics, and the color theme. To easily preview and test all the possible styling variations that would be produced by using different combinations of values for these four styling dimensions, we could create four nested =for= loops to iterate through the possible values for each of the styling dimensions. This approach would produce code as follows...
|
413 |
+
|
414 |
+
THE TEDIOUS WAY
|
415 |
+
...........................................................................................
|
416 |
+
var
|
417 |
+
borderClasses = ['noBorder','thinBorder','thickBorder','dottedBorder','fancyBorder'],
|
418 |
+
paddingClasses = ['noPadding','smallPadding','extraPadding'],
|
419 |
+
printClasses = ['finePrint','normalPrint','easilyReadable','printForVisionImpared'],
|
420 |
+
colorClasses = ['normalColors','subduedColors','brightColors','highContrastColors'],
|
421 |
+
htmlChunks = []
|
422 |
+
;
|
423 |
+
for (var borderClassNo = 0; borderClassNo < borderClasses.length; borderClassNo++) {
|
424 |
+
for (var paddingClassNo = 0; paddingClassNo < paddingClasses.length; paddingClassNo++) {
|
425 |
+
for (var printClassNo = 0; printClassNo < printClasses.length; printClassNo++) {
|
426 |
+
for (var colorClassNo = 0; colorClassNo < colorClasses.length; colorClassNo++) {
|
427 |
+
htmlChunks.push (
|
428 |
+
'<div class="' +
|
429 |
+
borderClasses [borderClassNo] + ' ' +
|
430 |
+
paddingClasses [paddingClassNo] + ' ' +
|
431 |
+
printClasses [printClassNo] + ' ' +
|
432 |
+
colorClasses [colorClassNo] + ' ' +
|
433 |
+
'">some text</div>'
|
434 |
+
);
|
435 |
+
}
|
436 |
+
}
|
437 |
+
}
|
438 |
+
}
|
439 |
+
Uize.Node.setInnerHtml ('styleCombos',htmlChunks.join ('\n'));
|
440 |
+
...........................................................................................
|
441 |
+
|
442 |
+
Of course, if we wanted a more concise and elegant solution - one that is more easily scalable when we want to add more styling dimensions - we could use the =Uize.Data.Combinations.generate= method as follows...
|
443 |
+
|
444 |
+
THE CONCISE WAY
|
445 |
+
..............................................................................
|
446 |
+
Uize.Node.setInnerHtml (
|
447 |
+
'styleCombos',
|
448 |
+
Uize.Data.Combinations.generate (
|
449 |
+
[
|
450 |
+
['noBorder','thinBorder','thickBorder','dottedBorder','fancyBorder'],
|
451 |
+
['noPadding','smallPadding','extraPadding'],
|
452 |
+
['finePrint','normalPrint','easilyReadable','printForVisionImpared'],
|
453 |
+
['normalColors','subduedColors','brightColors','highContrastColors']
|
454 |
+
],
|
455 |
+
"'<div class=\"' + value.join (' ') + '\">some text</div>'"
|
456 |
+
).join ('\n')
|
457 |
+
);
|
458 |
+
..............................................................................
|
459 |
+
|
460 |
+
In this solution, the `combination specifier` is an array, where each element represents one of the four styling dimensions, and where the value for each element is an array of the possible CSS classes that provides different stylings for that styling dimension. Then, we are specifying a `combination transformer expression string` to take the generated CSS classes array, concatenate it with a " " (space character) delimiter, and wrap it in an HTML =div= tag prefix and suffix. As a result, the =Uize.Data.Combinations.generate= method will return an array of =div= tag strings, which we then join with a newline character to produce an HTML chunk that we insert as inner HTML into the DOM node with the =id= of "styleCombos".
|
461 |
+
|
462 |
+
With this improved approach, if we want to add a new styling dimension, all we need to do is add another element to the `combination specifier` - much cleaner than the alternative approach shown earlier.
|
463 |
+
*/
|
464 |
+
|
465 |
+
Uize.module ({
|
466 |
+
name:'Uize.Data.Combinations',
|
467 |
+
builder:function () {
|
468 |
+
/*** Variables for Scruncher Optimization ***/
|
469 |
+
var
|
470 |
+
_package = function () {},
|
471 |
+
_undefined,
|
472 |
+
_isList = Uize.isList
|
473 |
+
;
|
474 |
+
|
475 |
+
/*** Public Static Methods ***/
|
476 |
+
_package.generate = function (_combinationsSpecifier,_combinationTransformer,_combinationMatcher) {
|
477 |
+
var _combinations = [];
|
478 |
+
_package.forEach (
|
479 |
+
_combinationsSpecifier,
|
480 |
+
function (_combination) {_combinations.push (_combination)},
|
481 |
+
_combinationTransformer,
|
482 |
+
_combinationMatcher
|
483 |
+
);
|
484 |
+
return _combinations;
|
485 |
+
/*?
|
486 |
+
Static Methods
|
487 |
+
Uize.Data.Combinations.generate
|
488 |
+
Returns an array of generated combinations that are derived from a `combination specifier`, with support for optionally transforming and/or filtering the combinations.
|
489 |
+
|
490 |
+
DIFFERENT USAGES
|
491 |
+
|
492 |
+
`Generate an Array of Combinations from a Combination Specifier`
|
493 |
+
......................................................................................
|
494 |
+
combinationsARRAY = Uize.Data.Combinations.generate (combinationsSpecifierOBJorARRAY);
|
495 |
+
......................................................................................
|
496 |
+
|
497 |
+
`Generate an Array of Transformed Combinations`
|
498 |
+
.....................................................
|
499 |
+
combinationsARRAY = Uize.Data.Combinations.generate (
|
500 |
+
combinationsSpecifierOBJorARRAY,
|
501 |
+
combinationTransformerSTRorFUNC
|
502 |
+
);
|
503 |
+
.....................................................
|
504 |
+
|
505 |
+
`Generate a Filtered Array of Transformed Combinations`
|
506 |
+
.....................................................
|
507 |
+
combinationsARRAY = Uize.Data.Combinations.generate (
|
508 |
+
combinationsSpecifierOBJorARRAY,
|
509 |
+
combinationTransformerSTRorFUNC,
|
510 |
+
combinationMatcherSTRorFUNC
|
511 |
+
);
|
512 |
+
.....................................................
|
513 |
+
|
514 |
+
Generate an Array of Combinations from a Combination Specifier
|
515 |
+
In the most typical use case, an array of combinations can be generated by specifying just the =combinationsSpecifierOBJorARRAY= parameter.
|
516 |
+
|
517 |
+
SYNTAX
|
518 |
+
......................................................................................
|
519 |
+
combinationsARRAY = Uize.Data.Combinations.generate (combinationsSpecifierOBJorARRAY);
|
520 |
+
......................................................................................
|
521 |
+
|
522 |
+
The =combinationsSpecifierOBJorARRAY= parameter lets you specify the `combination specifier` from which the combinations will be generated. `When the combination specifier is an object`, an array of objects will be produced. `When the combination specifier is an array`, an array of arrays will be produced. For more information, refer to the section `How Combinations Are Generated`.
|
523 |
+
|
524 |
+
Generate an Array of Transformed Combinations
|
525 |
+
When the optional =combinationTransformerSTRorFUNC= second parameter is specified, the generated combinations can be transformed or replaced.
|
526 |
+
|
527 |
+
SYNTAX
|
528 |
+
.....................................................
|
529 |
+
combinationsARRAY = Uize.Data.Combinations.generate (
|
530 |
+
combinationsSpecifierOBJorARRAY,
|
531 |
+
combinationTransformerSTRorFUNC
|
532 |
+
);
|
533 |
+
.....................................................
|
534 |
+
|
535 |
+
For more information on combination transformers and to see examples, refer to the section `Optional Combination Transformer`.
|
536 |
+
|
537 |
+
Generate a Filtered Array of Transformed Combinations
|
538 |
+
When the optional =combinationMatcherSTRorFUNC= third parameter is specified, the generated (and optionally transformed) combinations can be filtered.
|
539 |
+
|
540 |
+
SYNTAX
|
541 |
+
.....................................................
|
542 |
+
combinationsARRAY = Uize.Data.Combinations.generate (
|
543 |
+
combinationsSpecifierOBJorARRAY,
|
544 |
+
combinationTransformerSTRorFUNC,
|
545 |
+
combinationMatcherSTRorFUNC
|
546 |
+
);
|
547 |
+
.....................................................
|
548 |
+
|
549 |
+
When a combination matcher is desired but a combination transformer is not desired, the value =null= or =undefined= can be specified for the =combinationTransformerSTRorFUNC= parameter. For more information on combination matchers and to see examples, refer to the section `Optional Combination Matcher`.
|
550 |
+
|
551 |
+
NOTES
|
552 |
+
- compare to the =Uize.Data.Combinations.forEach= static method
|
553 |
+
*/
|
554 |
+
};
|
555 |
+
|
556 |
+
_package.forEach = function (
|
557 |
+
_combinationsSpecifier,_iterationHandler,_combinationTransformer,_combinationMatcher
|
558 |
+
) {
|
559 |
+
if (Uize.isObject (_combinationsSpecifier)) {
|
560 |
+
/*** normalize parameters ***/
|
561 |
+
if (_combinationTransformer != _undefined)
|
562 |
+
_combinationTransformer = Uize.resolveTransformer (_combinationTransformer)
|
563 |
+
;
|
564 |
+
if (_combinationMatcher != _undefined)
|
565 |
+
_combinationMatcher = Uize.resolveMatcher (_combinationMatcher)
|
566 |
+
;
|
567 |
+
|
568 |
+
/*** preparation to optimize performance of iterating through combinations ***/
|
569 |
+
var
|
570 |
+
_keys = [],
|
571 |
+
_key,
|
572 |
+
_keyNo = -1,
|
573 |
+
_values,
|
574 |
+
_valuesPerKeyNo = [],
|
575 |
+
_valuesLengthPerKeyNo = [],
|
576 |
+
_valueNoPerKeyNo = [],
|
577 |
+
_combinationsAreArray = Uize.isArray (_combinationsSpecifier)
|
578 |
+
;
|
579 |
+
Uize.forEach (
|
580 |
+
_combinationsSpecifier,
|
581 |
+
function (_values,_key) {
|
582 |
+
_values = _combinationsSpecifier [_key];
|
583 |
+
if (!_isList (_values)) _values = [_values]; // treat non-list value as only one possible value
|
584 |
+
if (_values.length) { // only include property if it has at least one possible value
|
585 |
+
_keys.push (_key);
|
586 |
+
_keyNo++;
|
587 |
+
_valuesLengthPerKeyNo [_keyNo] = (_valuesPerKeyNo [_keyNo] = _values).length;
|
588 |
+
_valueNoPerKeyNo [_keyNo] = 0;
|
589 |
+
}
|
590 |
+
}
|
591 |
+
);
|
592 |
+
|
593 |
+
/*** iterate through and produce combinations ***/
|
594 |
+
var
|
595 |
+
_combinationNo = -1,
|
596 |
+
_keysLength = _keyNo + 1,
|
597 |
+
_combinationTransformerResult
|
598 |
+
;
|
599 |
+
while (_keyNo >= 0) {
|
600 |
+
_combinationNo++;
|
601 |
+
|
602 |
+
/*** build object for current combination ***/
|
603 |
+
var _combination = _combinationsAreArray ? [] : {};
|
604 |
+
for (_keyNo = -1; ++_keyNo < _keysLength;)
|
605 |
+
_combination [_keys [_keyNo]] = _valuesPerKeyNo [_keyNo] [_valueNoPerKeyNo [_keyNo]]
|
606 |
+
;
|
607 |
+
|
608 |
+
/*** use combination transformer, if specified ***/
|
609 |
+
if (
|
610 |
+
_combinationTransformer &&
|
611 |
+
(
|
612 |
+
_combinationTransformerResult = _combinationTransformer (_combination,_combinationNo)
|
613 |
+
) !== _undefined
|
614 |
+
)
|
615 |
+
_combination = _combinationTransformerResult
|
616 |
+
;
|
617 |
+
|
618 |
+
/*** call iteration handler, if combination matcher permits ***/
|
619 |
+
(!_combinationMatcher || _combinationMatcher (_combination,_combinationNo)) &&
|
620 |
+
_iterationHandler (_combination)
|
621 |
+
;
|
622 |
+
|
623 |
+
/*** advance to next combination ***/
|
624 |
+
_keyNo = _keysLength;
|
625 |
+
while (
|
626 |
+
--_keyNo >= 0 &&
|
627 |
+
!(
|
628 |
+
_valueNoPerKeyNo [_keyNo] =
|
629 |
+
(_valueNoPerKeyNo [_keyNo] + 1) % _valuesLengthPerKeyNo [_keyNo]
|
630 |
+
)
|
631 |
+
);
|
632 |
+
}
|
633 |
+
}
|
634 |
+
/*?
|
635 |
+
Static Methods
|
636 |
+
Uize.Data.Combinations.forEach
|
637 |
+
Iterates through the generated combinations, calling the specified iterator handler for each combination.
|
638 |
+
|
639 |
+
DIFFERENT USAGES
|
640 |
+
|
641 |
+
`Iterate Over a Set of Generated Combinations`
|
642 |
+
.....................................................................................
|
643 |
+
Uize.Data.Combinations.forEach (combinationsSpecifierOBJorARRAY,iteratorHandlerFUNC);
|
644 |
+
.....................................................................................
|
645 |
+
|
646 |
+
`Iterate Over a Set of Transformed Combinations`
|
647 |
+
...................................
|
648 |
+
Uize.Data.Combinations.forEach (
|
649 |
+
combinationsSpecifierOBJorARRAY,
|
650 |
+
iteratorHandlerFUNC,
|
651 |
+
combinationTransformerSTRorFUNC
|
652 |
+
);
|
653 |
+
...................................
|
654 |
+
|
655 |
+
`Iterate Over a Filtered Set of Combinations`
|
656 |
+
...................................
|
657 |
+
Uize.Data.Combinations.forEach (
|
658 |
+
combinationsSpecifierOBJorARRAY,
|
659 |
+
iteratorHandlerFUNC,
|
660 |
+
combinationTransformerSTRorFUNC,
|
661 |
+
combinationMatcherSTRorFUNC
|
662 |
+
);
|
663 |
+
...................................
|
664 |
+
|
665 |
+
Iterate Over a Set of Generated Combinations
|
666 |
+
In the most typical use case, an array of combinations can be iterated over by specifying just the =combinationsSpecifierOBJorARRAY= and =iteratorHandlerFUNC= parameters.
|
667 |
+
|
668 |
+
SYNTAX
|
669 |
+
.....................................................................................
|
670 |
+
Uize.Data.Combinations.forEach (combinationsSpecifierOBJorARRAY,iteratorHandlerFUNC);
|
671 |
+
.....................................................................................
|
672 |
+
|
673 |
+
The =combinationsSpecifierOBJorARRAY= parameter lets you specify the `combination specifier` from which the combinations will be generated. `When the combination specifier is an object`, the generated combinations will be objects. `When the combination specifier is an array`, the generated combinations will be arrays. For more information, refer to the section `How Combinations Are Generated`.
|
674 |
+
|
675 |
+
The =iteratorHandlerFUNC= parameter lets you specify the handler function that should be called for each iteration. The handler function will be called with a single argument, being the generated combination for the iteration.
|
676 |
+
|
677 |
+
EXAMPLE
|
678 |
+
.................................................................................
|
679 |
+
var channelValues = ['00','33','66','99','CC','FF'];
|
680 |
+
Uize.Data.Combinations.forEach (
|
681 |
+
[channelValues,channelValues,channelValues],
|
682 |
+
function (webSafeColorTuple) {console.log ('#' + webSafeColorTuple.join (''))}
|
683 |
+
);
|
684 |
+
.................................................................................
|
685 |
+
|
686 |
+
In the above example, the RGB hex values of all the Web safe colors are being logged to the console. In our iteration handler function, we are defining the single argument =webSafeColorTuple=. This argument is essentially the generated combination for the iteration, but we can call it whatever makes the most sense in our particular application. In this example, each generated combination is really a Web safe colo tuple, with values for the red, green, and blue color channels.
|
687 |
+
|
688 |
+
Iterate Over a Set of Transformed Combinations
|
689 |
+
When the optional =combinationTransformerSTRorFUNC= third parameter is specified, the generated combinations can be transformed before they are passed to the iteration handler.
|
690 |
+
|
691 |
+
SYNTAX
|
692 |
+
...................................
|
693 |
+
Uize.Data.Combinations.forEach (
|
694 |
+
combinationsSpecifierOBJorARRAY,
|
695 |
+
iteratorHandlerFUNC,
|
696 |
+
combinationTransformerSTRorFUNC
|
697 |
+
);
|
698 |
+
...................................
|
699 |
+
|
700 |
+
For more information on combination transformers and to see examples, refer to the section `Optional Combination Transformer`.
|
701 |
+
|
702 |
+
Iterate Over a Filtered Set of Combinations
|
703 |
+
When the optional =combinationMatcherSTRorFUNC= fourth parameter is specified, the generated (and optionally transformed) combinations can be filtered.
|
704 |
+
|
705 |
+
SYNTAX
|
706 |
+
...................................
|
707 |
+
Uize.Data.Combinations.forEach (
|
708 |
+
combinationsSpecifierOBJorARRAY,
|
709 |
+
iteratorHandlerFUNC,
|
710 |
+
combinationTransformerSTRorFUNC,
|
711 |
+
combinationMatcherSTRorFUNC
|
712 |
+
);
|
713 |
+
...................................
|
714 |
+
|
715 |
+
When a combination matcher is desired but a combination transformer is not desired, the value =null= or =undefined= can be specified for the =combinationTransformerSTRorFUNC= parameter. For more information on combination matchers and to see examples, refer to the section `Optional Combination Matcher`.
|
716 |
+
|
717 |
+
NOTES
|
718 |
+
- compare to the =Uize.Data.Combinations.generate= static method
|
719 |
+
*/
|
720 |
+
};
|
721 |
+
|
722 |
+
return _package;
|
723 |
+
}
|
724 |
+
});
|
725 |
+
|
skin/frontend/default/customproduct/js/Uize.Data.Csv.js
ADDED
@@ -0,0 +1,1190 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Data.Csv Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2009-2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 3
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 100
|
17 |
+
docCompleteness: 100
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Data.Csv= module provides support for serializing to and parsing from [[http://en.wikipedia.org/wiki/Comma-separated_values][CSV (Comma Separated Values)]] formatted data, with configurable options.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
Key Features
|
27 |
+
The versatile =Uize.Data.Csv= module supports the following key features...
|
28 |
+
|
29 |
+
Multiline Column Values
|
30 |
+
Column values that contain linebreaks (either carriage return or linefeed characters) can be serialized *and* parsed using the methods of the =Uize.Data.Csv= module.
|
31 |
+
|
32 |
+
When data is serialized where column values contain linebreak characters, those column values are always quoted in the serialized CSV data string, and the values will span multiple lines. That's because the CSV format doesn't provide a dedicated way for escaping linebreak characters. When parsing CSV formatted data, the =Uize.Data.Csv.from= method automatically reads column values across multiple lines when they are quoted and contain linebreak characters.
|
33 |
+
|
34 |
+
Header Row
|
35 |
+
The CSV format allows for an optional header row that contains the names of the columns.
|
36 |
+
|
37 |
+
The =Uize.Data.Csv= module provides support for header rows when both serializing to and parsing from CSV data strings. Support for header rows is enabled by specifying the value =true= for the =hasHeader= option, available for both the =Uize.Data.Csv.from= and =Uize.Data.Csv.to= static methods.
|
38 |
+
|
39 |
+
Header Rows and Parsing from CSV
|
40 |
+
Header rows are supported when parsing from CSV data, both to arrays of arrays and to arrays of objects.
|
41 |
+
|
42 |
+
When parsing CSV data to an array of arrays, a header row that exists in the CSV data string can either just be "gobbled" and thrown away, or it can be gathered in an empty array that you supply using the =columns= decoding option. Either way, the column names in a header row are kept from getting into the records array that is returned by the =Uize.Data.Csv.from= method, because they are not part of the data set.
|
43 |
+
|
44 |
+
When parsing CSV data to an array of objects, the header row that exists in the CSV data string can be used for the key names for the objects in the returned records array. If there is no header row in the CSV data string and the value =false= is specified for the =hasHeader= option, the column names can still be supplied to the =Uize.Data.Csv.from= method using the =columns= decoding option when parsing to an array of objects.
|
45 |
+
|
46 |
+
Header Rows and Serializing to CSV
|
47 |
+
Header rows are supported when serializing to CSV data, both from arrays of arrays and from arrays of objects.
|
48 |
+
|
49 |
+
When serializing an array of arrays to a CSV data string, the column names to be used in the header row can be supplied to the =Uize.Data.Csv.to= method using the =columns= encoding option.
|
50 |
+
|
51 |
+
When serializing an array of objects to a CSV data string, the column names to be used in the header row can be taken directly from the key names of the first object in the records array, or they can be explicitly specified to the =Uize.Data.Csv.to= method using the =columns= encoding option. Using the =columns= option allows the column order to be controlled, or a subset of the columns to be serialized (see `Column Ordering And Filtering`).
|
52 |
+
|
53 |
+
Object or Array Type Rows
|
54 |
+
The =Uize.Data.Csv= module supports serializing from and parsing to a records array, where records are represented as either arrays or objects.
|
55 |
+
|
56 |
+
When records are represented as objects, each key represents the name of a column and each value is that column's value. When records are represented as arrays, then each element of a record's array is a column value.
|
57 |
+
|
58 |
+
The row type - array or object - can be controlled using the =rowType= option, available for both the =Uize.Data.Csv.from= and =Uize.Data.Csv.to= static methods. When the value ='auto'= (the default) is used for the =rowType= option when parsing CSV data, then array or object type will be chosen based upon the value of the =hasHeader= decoding option, with object type being chosen when =hasHeader= is =true=, and array type being chosen when =hasHeader= is =false=. When ='auto'= is used for the =rowType= option when serializing CSV data, then array or object type will be chosen based upon the type of the first element of the records array being serialized.
|
59 |
+
|
60 |
+
When serializing to a CSV data string from an array of objects, the =columns= option can be used to control the column order, or to serialize only a subset of the columns (see `Column Ordering And Filtering`). When parsing from a CSV data string to an array of objects, the key names for the record objects can be taken from the header row of the CSV data string (the value =true= is specified for the =hasHeader= option), or the key names can be supplied in the =columns= decoding option.
|
61 |
+
|
62 |
+
Configurable Quoting Character
|
63 |
+
While [[http://tools.ietf.org/html/rfc4180][RFC 4180]] only addresses quoting of values using the double quote character, the =Uize.Data.Csv= module provides the flexibility to use other quoting characters - both when serializing using the =Uize.Data.Csv.to= method and parsing using the =Uize.Data.Csv.from= method.
|
64 |
+
|
65 |
+
The quoting character is specified using the =quoteChar= option, available for both the =Uize.Data.Csv.from= and =Uize.Data.Csv.to= methods. The value specified for this option should be a string, specifying the *single* character used for quoting values in the serialized CSV data string.
|
66 |
+
|
67 |
+
When serializing data to CSV format using a quoting character other than double quotes, it is important to specify that character in the =quoteChar= option when later parsing that serialized data - the =Uize.Data.Csv.from= method cannot tell automatically from the CSV data string what the quoting character is. Whatever quoting character is specified, if a value contains that quote character, then that value will be quoted. As per the RFC 4180 rules, the quoting character is escaped by doubling it.
|
68 |
+
|
69 |
+
Configurable Quoting Behavior
|
70 |
+
By default, the =Uize.Data.Csv.to= method automatically chooses whether or not to quote individual values, based upon a number of different criteria.
|
71 |
+
|
72 |
+
This behavior can be controlled, though, using the =whenToQuoteValues= encoding option. When the value ='always'= is specified for this option, all column values in the serialized CSV data string will always be quoted. When this option is left in its default state of ='auto'=, then column values will be automatically quoted, only when they contain the quoting character (see the =quoteChar= option) or the value delimiter string (see the =valueDelimiter= option), if they contain linebreaks (either carriage return or linefeed characters), if they contain whitespace padding and the value =true= is specified for the =trimPaddingOnParse= option, or if the value delimiter (see the =valueDelimiter= option) contains whitespace padding and the value =false= is specified for the =trimPaddingOnParse= option.
|
73 |
+
|
74 |
+
Configurable Value Delimiter
|
75 |
+
While [[http://tools.ietf.org/html/rfc4180][RFC 4180]] only addresses separating values using the comma character, the =Uize.Data.Csv= module provides the flexibility to use other value delimiter characters - both when serializing using the =Uize.Data.Csv.to= method and parsing using the =Uize.Data.Csv.from= method.
|
76 |
+
|
77 |
+
The value delimiter is specified using the =valueDelimiter= option, available for both the =Uize.Data.Csv.from= and =Uize.Data.Csv.to= methods. The value specified for this option should be a string, specifying the delimiter used for separating column values in rows of CSV data string.
|
78 |
+
|
79 |
+
When serializing data to CSV format using a value delimiter character other than comma, it is important to specify that delimiter in the =valueDelimiter= option when later parsing that serialized data - the =Uize.Data.Csv.from= method cannot tell automatically from the CSV data string what the value delimiter is.
|
80 |
+
|
81 |
+
Whatever value delimiter string is specified, if a value contains that string, then that value will be quoted. Also, if the value delimiter has whitespace padding, then the column values will always be quoted to ensure that later parsing doesn't result in the value delimiter's padding becoming whitespace in the parsed column values.
|
82 |
+
|
83 |
+
Column Ordering And Filtering
|
84 |
+
When serializing an array of objects to a CSV data string, the =Uize.Data.Csv= module provides support for controlling the ordering of columns in the serialized data string, as well as serializing just a subset of the columns in the data set.
|
85 |
+
|
86 |
+
Column Order
|
87 |
+
The =columns= encoding option can be used to enforce an ordering for columns in the serialized CSV data string.
|
88 |
+
|
89 |
+
If you're serializing a records array where the records are of type object and you leave it up to the =Uize.Data.Csv.to= method to determine the columns, the column order will depend entirely on the order in which the keys were assigned to the first row's object in the records array. As long as the serialized CSV data string has a header row (the value =true= is specified for the =hasHeader= option) and the data is to be later parsed to an array of objects, one may not care about the column ordering. If column ordering is important, however, then the =columns= option can be used to control this.
|
90 |
+
|
91 |
+
Subset of Columns
|
92 |
+
In some cases you may wish to serialize an array of object records, but not include all of the columns in the serialized output.
|
93 |
+
|
94 |
+
In such cases you can use the =columns= encoding option to specify just the columns that you wish to have serialized, along with the exact order in which you wish them to be arranged in the serialized CSV data string.
|
95 |
+
|
96 |
+
Trimming of Value Padding
|
97 |
+
While whitespace around value separator characters is considered significant, and while trimming such whitespace is specifically prohibited according to [[http://tools.ietf.org/html/rfc4180][RFC 4180]], the =Uize.Data.Csv= module supports trimming of value padding - both when serializing using the =Uize.Data.Csv.to= method and parsing using the =Uize.Data.Csv.from= method.
|
98 |
+
|
99 |
+
When parsing CSV data, there might be real world situations where one is dealing with CSV data that is not serialized strictly according to the rules laid out in RFC 4180, and where there might be spaces after comma value separators. In such cases, the value =true= can be specified for the =trimPaddingOnParse= decoding option, which will cause the leading and trailing whitespace padding around the first and last non-whitespace characters of non-quoted values to be trimmed (for quoted values, this option will have no effect on the result).
|
100 |
+
|
101 |
+
When serializing CSV data, the data serialized by the =Uize.Data.Csv.to= method may at some point be parsed by code that doesn't strictly observe the rules laid out in RFC 4180 and which may strip padding around comma value separators. In such cases, the value =true= can be specified for the =trimPaddingOnParse= encoding option, which will cause values that contain leading and/or trailing whitespace padding around the first and last non-whitespace characters to be quoted in order to ensure that whitespace that is part of values is not accidentally stripped by a non-compliant CSV parser.
|
102 |
+
*/
|
103 |
+
|
104 |
+
Uize.module ({
|
105 |
+
name:'Uize.Data.Csv',
|
106 |
+
required:'Uize.String',
|
107 |
+
builder:function () {
|
108 |
+
/*** Variables for Scruncher Optimization ***/
|
109 |
+
var
|
110 |
+
_package = function () {},
|
111 |
+
_true = true,
|
112 |
+
_false = false,
|
113 |
+
_undefined
|
114 |
+
;
|
115 |
+
|
116 |
+
/*** General Variables ***/
|
117 |
+
var _optionDefaults = {
|
118 |
+
columns:'all', // 'all' | an array of column names
|
119 |
+
hasHeader:false, // true | false
|
120 |
+
trimPaddingOnParse:false, // true | false
|
121 |
+
quoteChar:'"', // '"' | '\'' | any single char
|
122 |
+
rowType:'auto', // 'array' | 'object' | 'auto'
|
123 |
+
valueDelimiter:',', // ',' | ';' | '\t' | any single char
|
124 |
+
whenToQuoteValues:'auto' // 'auto' | 'always'
|
125 |
+
};
|
126 |
+
|
127 |
+
/*** Utility Functions ***/
|
128 |
+
function _getDefaultedOption (_options,_optionName) {
|
129 |
+
var _optionValue = _options ? _options [_optionName] : _undefined;
|
130 |
+
return _optionValue == _undefined ? _optionDefaults [_optionName] : _optionValue;
|
131 |
+
}
|
132 |
+
|
133 |
+
function _getEscapedQuoteChar (_options) {
|
134 |
+
return Uize.String.repeat (_getDefaultedOption (_options,'quoteChar'),2);
|
135 |
+
}
|
136 |
+
|
137 |
+
function _globalLiteralRegExp (_replaceStr) {
|
138 |
+
return new RegExp (Uize.escapeRegExpLiteral (_replaceStr),'g');
|
139 |
+
}
|
140 |
+
|
141 |
+
/*** Public Static Methods ***/
|
142 |
+
_package.from = function (_toDecode,_decodingOptions) {
|
143 |
+
var
|
144 |
+
_columns = _getDefaultedOption (_decodingOptions,'columns'),
|
145 |
+
_hasHeader = _getDefaultedOption (_decodingOptions,'hasHeader'),
|
146 |
+
_trimPaddingOnParse = _getDefaultedOption (_decodingOptions,'trimPaddingOnParse'),
|
147 |
+
_quoteChar = _getDefaultedOption (_decodingOptions,'quoteChar'),
|
148 |
+
_rowType = _getDefaultedOption (_decodingOptions,'rowType'),
|
149 |
+
_valueDelimiter = _getDefaultedOption (_decodingOptions,'valueDelimiter'),
|
150 |
+
_escapedQuoteChar = _getEscapedQuoteChar (_decodingOptions),
|
151 |
+
_escapedQuoteCharRegExp = _globalLiteralRegExp (_escapedQuoteChar),
|
152 |
+
_columnsIsArray = Uize.isArray (_columns),
|
153 |
+
_rowTypeIsObject =
|
154 |
+
_rowType == 'object' || (_rowType == 'auto' && (_hasHeader || (_columnsIsArray && _columns.length))),
|
155 |
+
_rows = [],
|
156 |
+
_currentPos = 0,
|
157 |
+
_rowNo = _hasHeader ? -1 : 0,
|
158 |
+
_columnNo = 0,
|
159 |
+
_toDecodeLength = _toDecode.length,
|
160 |
+
_toDecodeLengthMinus1 = _toDecodeLength - 1
|
161 |
+
;
|
162 |
+
_hasHeader && (_columnsIsArray ? (_columns.length = 0) : (_columns = []));
|
163 |
+
function _addColumn (_value) {
|
164 |
+
(
|
165 |
+
_rowNo < 0
|
166 |
+
? _columns
|
167 |
+
: _rows [_rowNo] || (_rows [_rowNo] = _rowTypeIsObject ? {} : [])
|
168 |
+
) [
|
169 |
+
_rowTypeIsObject && _rowNo > -1 ? _columns [_columnNo] : _columnNo
|
170 |
+
] =
|
171 |
+
_trimPaddingOnParse ? Uize.String.trim (_value) : _value
|
172 |
+
;
|
173 |
+
_columnNo++;
|
174 |
+
}
|
175 |
+
function _nextIndexOf (_char) {
|
176 |
+
var _result = _toDecode.indexOf (_char,_currentPos);
|
177 |
+
return _result < 0 ? _toDecodeLength : _result;
|
178 |
+
}
|
179 |
+
function _nextDelimiterPos () {
|
180 |
+
return Math.min (
|
181 |
+
_nextIndexOf ('\n'),
|
182 |
+
_nextIndexOf ('\r'),
|
183 |
+
_nextIndexOf (_valueDelimiter),
|
184 |
+
_nextIndexOf (_quoteChar)
|
185 |
+
);
|
186 |
+
}
|
187 |
+
var
|
188 |
+
_nextSignificantCharPos,
|
189 |
+
_nextSignificantChar,
|
190 |
+
_endFound,
|
191 |
+
_escapedQuotesFound,
|
192 |
+
_closingQuoteCharPos
|
193 |
+
;
|
194 |
+
while (_currentPos < _toDecodeLength) {
|
195 |
+
_nextSignificantChar =
|
196 |
+
_toDecode.charAt (_closingQuoteCharPos = _nextSignificantCharPos = _nextDelimiterPos ())
|
197 |
+
;
|
198 |
+
if (_nextSignificantChar == _quoteChar) {
|
199 |
+
/*** find end of value ***/
|
200 |
+
_endFound = _escapedQuotesFound = _false;
|
201 |
+
while (!_endFound) {
|
202 |
+
_closingQuoteCharPos = _toDecode.indexOf (_quoteChar,_closingQuoteCharPos + 1);
|
203 |
+
if (_closingQuoteCharPos < 0) _closingQuoteCharPos = _toDecodeLength;
|
204 |
+
_closingQuoteCharPos < _toDecodeLengthMinus1 &&
|
205 |
+
_toDecode.charAt (_closingQuoteCharPos + 1) == _quoteChar
|
206 |
+
? (_closingQuoteCharPos += (_escapedQuotesFound = _true))
|
207 |
+
: (_endFound = _true)
|
208 |
+
;
|
209 |
+
}
|
210 |
+
|
211 |
+
/*** add the column value ***/
|
212 |
+
var _columnValue = _toDecode.slice (_nextSignificantCharPos + 1,_closingQuoteCharPos);
|
213 |
+
_addColumn (
|
214 |
+
_escapedQuotesFound
|
215 |
+
? _columnValue.replace (_escapedQuoteCharRegExp,_quoteChar)
|
216 |
+
: _columnValue
|
217 |
+
);
|
218 |
+
|
219 |
+
_currentPos = _closingQuoteCharPos + 1; // update _currentPos for _nextDelimiterPos call below
|
220 |
+
_currentPos = _nextDelimiterPos (); // find next delimiter
|
221 |
+
_currentPos += _toDecode.charAt (_currentPos) == _valueDelimiter; // advance by 1, if delimiter is value delimiter
|
222 |
+
} else if (
|
223 |
+
_nextSignificantCharPos == _currentPos &&
|
224 |
+
(_nextSignificantChar == '\n' || _nextSignificantChar == '\r')
|
225 |
+
) {
|
226 |
+
_rowNo++;
|
227 |
+
_columnNo = 0;
|
228 |
+
_currentPos += 1 + (
|
229 |
+
_nextSignificantChar == '\r' &&
|
230 |
+
_currentPos < _toDecodeLengthMinus1 &&
|
231 |
+
_toDecode.charAt (_currentPos + 1) == '\n'
|
232 |
+
);
|
233 |
+
} else {
|
234 |
+
_addColumn (_toDecode.slice (_currentPos,_nextSignificantCharPos));
|
235 |
+
_currentPos = _nextSignificantCharPos + (_nextSignificantChar == _valueDelimiter);
|
236 |
+
}
|
237 |
+
}
|
238 |
+
return _rows;
|
239 |
+
/*?
|
240 |
+
Static Methods
|
241 |
+
Uize.Data.Csv.from
|
242 |
+
Returns an array, being the records parsed from the specified CSV formatted data string.
|
243 |
+
|
244 |
+
SYNTAX
|
245 |
+
...............................................
|
246 |
+
recordsARRAY = Uize.Data.Csv.from (csvDataSTR);
|
247 |
+
...............................................
|
248 |
+
|
249 |
+
VARIATION
|
250 |
+
..................................................................
|
251 |
+
recordsARRAY = Uize.Data.Csv.from (csvDataSTR,decodingOptionsOBJ);
|
252 |
+
..................................................................
|
253 |
+
|
254 |
+
When the optional =decodingOptionsOBJ= parameter is specified, then CSV data strings that have not been serialized in strict accordance with the rules laid out in RFC 4180 can be successfully parsed. If one uses the =encodingOptionsOBJ= parameter of the companion =Uize.Data.Csv.to= method to serialize data to CSV format in a way that deviates from the rules of RFC 4180, then you can specify those same options in the =decodingOptionsOBJ= parameter in order to successfully parse that non-standard serialized CSV data back into a records array.
|
255 |
+
|
256 |
+
The value of the =encodingOptionsOBJ= parameter should be an object, with properties as follows...
|
257 |
+
|
258 |
+
DECODING OPTIONS
|
259 |
+
..............................................................................
|
260 |
+
{
|
261 |
+
columns:columnsARRAY, // optional
|
262 |
+
hasHeader:hasHeaderBOOL, // optional, defaults to false
|
263 |
+
trimPaddingOnParse:trimPaddingOnParseBOOL, // optional, defaults to false
|
264 |
+
quoteChar:quoteCharSTR, // optional, defaults to '"'
|
265 |
+
rowType:rowTypeSTR, // optional, defaults to 'auto'
|
266 |
+
valueDelimiter:valueDelimiterSTR // optional, defaults to ','
|
267 |
+
}
|
268 |
+
..............................................................................
|
269 |
+
|
270 |
+
columns
|
271 |
+
An array, that will be used to store the column names for the CSV data if the value =true= is specified for the =hasHeader= option, or that can be used to supply the names of columns if the value =false= is specified for the =hasHeader= option and the value ='object'= is specified for the =rowType= option.
|
272 |
+
|
273 |
+
When Data Has Header Row
|
274 |
+
When parsing a CSV data string that contains a header row, to an array of arrays (ie. specifying the value ='array'= for the =rowType= option), and specifying the value =true= for the =hasHeader= option, the column names row doesn't make its way into the returned records array.
|
275 |
+
|
276 |
+
This is by design, because the column names are not part of the data set. In such cases, specifying an array value for the =columns= option provides a way for you to obtain the column names. Even when parsing such a CSV data string to an array of objects, where each record object has key names that reflect the column names obtained from the header row, it still may be useful to get back a separate array of the column names - especially for the occasional case where the CSV data string has no data, but just the column names header row.
|
277 |
+
|
278 |
+
NOTE
|
279 |
+
|
280 |
+
The contents of an array specified for the =columns= option will be replaced with the column names from the CSV data string's header row. Typically, you would supply an empty array, but you could reuse an array with existing contents.
|
281 |
+
|
282 |
+
When Data Doesn't Have Header Row
|
283 |
+
When parsing a CSV data string that doesn't contain a header row, to an array of objects (ie. specifying the value ='object'= for the =rowType= option), then the =columns= option lets you specify the names of the columns.
|
284 |
+
|
285 |
+
Column names supplied by the =columns= option will be used as the key names for the objects of the returned records array. In this case, the contents of the specified column names array will not be altered.
|
286 |
+
|
287 |
+
NOTES
|
288 |
+
- the default value for this option is ='all'= (not meaningful for the =Uize.Data.Csv.from= method)
|
289 |
+
|
290 |
+
hasHeader
|
291 |
+
A boolean, specifying whether or not the CSV data string to be parsed has a header row for the column names.
|
292 |
+
|
293 |
+
When the value =true= is specified for this option, the first row of CSV data will be used for the column names and will be "gobbled" (ie. won't make its way into the returned records array). If an array reference is specified as a value for the =columns= option, then the column names read from the header row will be populated into the specified array. If the value ='object'= is specified for the =rowType= option, then the column names obtained from the header row will be used as the key names for the objects of the returned records array.
|
294 |
+
|
295 |
+
NOTES
|
296 |
+
- the default value for this option is =false=
|
297 |
+
|
298 |
+
trimPaddingOnParse
|
299 |
+
A boolean, specifying whether or not padding around non-quoted values should be trimmed away.
|
300 |
+
|
301 |
+
While whitespace around value separator characters is considered significant, and while trimming such whitespace is specifically prohibited according to [[http://tools.ietf.org/html/rfc4180][RFC 4180]], there might be real world situations where one is dealing with CSV data that is not serialized strictly according to the rules laid out in RFC 4180, and where there might be spaces after comma value separators.
|
302 |
+
|
303 |
+
In such cases, the value =true= can be specified for the =trimPaddingOnParse= option, which will cause the leading and trailing whitespace padding around the first and last non-whitespace characters of non-quoted values to be trimmed (for quoted values, this option will have no effect on the result). Use this option with caution.
|
304 |
+
|
305 |
+
NOTES
|
306 |
+
- the default value for this option is =false=
|
307 |
+
|
308 |
+
quoteChar
|
309 |
+
A string, specifying the *single* character used for quoting values in the CSV data string to be parsed.
|
310 |
+
|
311 |
+
While [[http://tools.ietf.org/html/rfc4180][RFC 4180]] only addresses quoting of values using the double quote character, the =Uize.Data.Csv= module provides the flexibility to use other quoting characters - both when parsing using the =Uize.Data.Csv.from= method and serializing using the =Uize.Data.Csv.to= method.
|
312 |
+
|
313 |
+
If you are dealing with CSV formatted data that has not been serialized in strict compliance with the rules of RFC 4180 and a quoting character other than the double quote was used when serializing it, then you can specify that character for the =quoteChar= option in order to parse that data.
|
314 |
+
|
315 |
+
NOTES
|
316 |
+
- the value of the =quoteChar= option may not be the same as the =valueDelimiter= option
|
317 |
+
- the default value for this option is ='"'= (the double quote character)
|
318 |
+
|
319 |
+
rowType
|
320 |
+
A string, specifying the type for the records in the returned records array.
|
321 |
+
|
322 |
+
- ='array'= - Each row's record is represented by an array of values for the various columns.
|
323 |
+
|
324 |
+
- ='object'= - Each row's record is represented by an object, with keys named according to the column names.
|
325 |
+
|
326 |
+
- ='auto'= (default) - Array or object type will be chosen based upon the value of the =hasHeader= option, with object type being chosen when =hasHeader= is =true=, and array type being chosen when =hasHeader= is =false=.
|
327 |
+
|
328 |
+
If the value ='object'= is specified for the =rowType= option and the value =false= is specified for the =hasHeader= option, then the column names should be supplied in the =columns= option.
|
329 |
+
|
330 |
+
NOTES
|
331 |
+
- the default value for this option is ='auto'=
|
332 |
+
|
333 |
+
valueDelimiter
|
334 |
+
A string, specifying the delimiter that separates column values in rows of the CSV data string to be parsed.
|
335 |
+
|
336 |
+
While [[http://tools.ietf.org/html/rfc4180][RFC 4180]] only addresses separating values using the comma character, the =Uize.Data.Csv= module provides the flexibility to use other value delimiter characters - both when parsing using the =Uize.Data.Csv.from= method and serializing using the =Uize.Data.Csv.to= method.
|
337 |
+
|
338 |
+
If you are dealing with CSV formatted data that has not been serialized in strict compliance with the rules of RFC 4180 and a value delimiter string other than a single comma was used when serializing it, then you can specify that delimiter string for the =valueDelimiter= option in order to parse that data.
|
339 |
+
|
340 |
+
NOTES
|
341 |
+
- the value of the =valueDelimiter= option may not be the same as the =quoteChar= option, and may not contain the quoting character if it is a multi-character delimiter
|
342 |
+
- the default value for this option is =','= (the comma character)
|
343 |
+
|
344 |
+
Examples
|
345 |
+
Default Decoding Options
|
346 |
+
In this example, the CSV data string being parsed has been serialized in strict accordance to the rules laid out in RFC 4180, and is being parsed by the =Uize.Data.Csv.from= method using all the decoding option defaults (ie. no =decodingOptionsOBJ= parameter is being specified).
|
347 |
+
|
348 |
+
INPUT
|
349 |
+
............................................
|
350 |
+
"John ""Willy""",Wilkey,(650) 123-4567
|
351 |
+
Marie, Stevenson ,"(415) 456-7890, Ext. 214"
|
352 |
+
Craig,Pollack,"(310) 987-6543
|
353 |
+
(650) 303-1000"
|
354 |
+
............................................
|
355 |
+
|
356 |
+
PARSE
|
357 |
+
...........................
|
358 |
+
Uize.Data.Csv.from (input);
|
359 |
+
...........................
|
360 |
+
|
361 |
+
OUTPUT
|
362 |
+
.......................................................
|
363 |
+
[
|
364 |
+
['John "Willy"','Wilkey','(650) 123-4567'],
|
365 |
+
['Marie',' Stevenson ','(415) 456-7890, Ext. 214'],
|
366 |
+
['Craig','Pollack','(310) 987-6543\n(650) 303-1000']
|
367 |
+
]
|
368 |
+
.......................................................
|
369 |
+
|
370 |
+
Looking at the CSV data string, you'll notice a few things...
|
371 |
+
|
372 |
+
- The value ="John ""Willy"""= is quoted because it contains the double quote quoting character, and the double quotes in the value are escaped by doubling them up (ie. two double quotes for each double quote being escaped).
|
373 |
+
- The value ="(415) 456-7890, Ext. 214"= is quoted because it contains the comma value delimiter character.
|
374 |
+
- The phone number column for the last row is quoted because it contains a linebreak and spans two lines.
|
375 |
+
|
376 |
+
None of the above factors are a problem for the =Uize.Data.Csv.from= method, since all these behaviors comply with the rules of RFC 4180.
|
377 |
+
|
378 |
+
Padding After Value Separator Comma, Trim Padding On Parse
|
379 |
+
In this example, the CSV data string was originally serialized with a cosmetic space after the comma value delimiter.
|
380 |
+
|
381 |
+
We happen to know this about the source material, so we specify the value =true= for the =trimPaddingOnParse= option. This results in the whitespace padding around values being trimmed away. In the returned records array, therefore, the column values do not contain padding.
|
382 |
+
|
383 |
+
INPUT
|
384 |
+
................................
|
385 |
+
John, Wilkey, (650) 123-4567
|
386 |
+
Marie, Stevenson, (415) 456-7890
|
387 |
+
Craig, Pollack, (310) 987-6543
|
388 |
+
................................
|
389 |
+
|
390 |
+
PARSE
|
391 |
+
.....................................................
|
392 |
+
Uize.Data.Csv.from (input,{trimPaddingOnParse:true});
|
393 |
+
.....................................................
|
394 |
+
|
395 |
+
OUTPUT
|
396 |
+
..........................................
|
397 |
+
[
|
398 |
+
['John','Wilkey','(650) 123-4567'],
|
399 |
+
['Marie','Stevenson','(415) 456-7890'],
|
400 |
+
['Craig','Pollack','(310) 987-6543']
|
401 |
+
]
|
402 |
+
..........................................
|
403 |
+
|
404 |
+
No Header Row, Column Names Explicitly Specified
|
405 |
+
In this example, we're parsing a CSV data string to an array of records and supplying the column names.
|
406 |
+
|
407 |
+
INPUT
|
408 |
+
..............................
|
409 |
+
John,Wilkey,(650) 123-4567
|
410 |
+
Marie,Stevenson,(415) 456-7890
|
411 |
+
Craig,Pollack,(310) 987-6543
|
412 |
+
..............................
|
413 |
+
|
414 |
+
PARSE
|
415 |
+
......................................................................
|
416 |
+
Uize.Data.Csv.from (input,{columns:['firstName','lastName','phone']});
|
417 |
+
......................................................................
|
418 |
+
|
419 |
+
OUTPUT
|
420 |
+
..................................................................
|
421 |
+
[
|
422 |
+
{firstName:'John',lastName:'Wilkey',phone:'(650) 123-4567'},
|
423 |
+
{firstName:'Marie',lastName:'Stevenson',phone:'(415) 456-7890'},
|
424 |
+
{firstName:'Craig',lastName:'Pollack',phone:'(310) 987-6543'}
|
425 |
+
]
|
426 |
+
..................................................................
|
427 |
+
|
428 |
+
As you'll notice from the CSV data string, there is no header row to indicate the column names. Therefore, when we parse the string we provide the column names using the =columns= option. Now, because we're specifying an array for the =columns= option, and because we're not specifying a value for the =rowType= option (so it defaults to ='auto'=), the =Uize.Data.Csv.from= method chooses object type for the records. The column names that we've provided are used as the keys for the record objects.
|
429 |
+
|
430 |
+
With Header Row
|
431 |
+
In this example, the CSV data string contains a header row and we're parsing the string to an array of objects.
|
432 |
+
|
433 |
+
INPUT
|
434 |
+
..............................
|
435 |
+
firstName,lastName,phone
|
436 |
+
John,Wilkey,(650) 123-4567
|
437 |
+
Marie,Stevenson,(415) 456-7890
|
438 |
+
Craig,Pollack,(310) 987-6543
|
439 |
+
..............................
|
440 |
+
|
441 |
+
PARSE
|
442 |
+
............................................
|
443 |
+
Uize.Data.Csv.from (input,{hasHeader:true});
|
444 |
+
............................................
|
445 |
+
|
446 |
+
OUTPUT
|
447 |
+
..................................................................
|
448 |
+
[
|
449 |
+
{firstName:'John',lastName:'Wilkey',phone:'(650) 123-4567'},
|
450 |
+
{firstName:'Marie',lastName:'Stevenson',phone:'(415) 456-7890'},
|
451 |
+
{firstName:'Craig',lastName:'Pollack',phone:'(310) 987-6543'}
|
452 |
+
]
|
453 |
+
..................................................................
|
454 |
+
|
455 |
+
The =Uize.Data.Csv.from= method doesn't know that the CSV data string has a header row unless we tell it, so we specify the value =true= for the =hasHeader= option. Now, because we're specifying =true= for the =hasHeader= option, and because we're not specifying a value for the =rowType= option (so it defaults to ='auto'=), the =Uize.Data.Csv.from= method chooses object type for the records. The column names are obtained from the first row of the CSV data string and are used as the keys for the record objects.
|
456 |
+
|
457 |
+
With Header Row, Rows Are Arrays
|
458 |
+
In this example, the CSV data string contains a header row, but we want to parse the string to an array of arrays and don't want the column names in the data set.
|
459 |
+
|
460 |
+
INPUT
|
461 |
+
..............................
|
462 |
+
firstName,lastName,phone
|
463 |
+
John,Wilkey,(650) 123-4567
|
464 |
+
Marie,Stevenson,(415) 456-7890
|
465 |
+
Craig,Pollack,(310) 987-6543
|
466 |
+
..............................
|
467 |
+
|
468 |
+
PARSE
|
469 |
+
............................................................
|
470 |
+
Uize.Data.Csv.from (input,{hasHeader:true,rowType:'array'});
|
471 |
+
............................................................
|
472 |
+
|
473 |
+
OUTPUT
|
474 |
+
..........................................
|
475 |
+
[
|
476 |
+
['John','Wilkey','(650) 123-4567'],
|
477 |
+
['Marie','Stevenson','(415) 456-7890'],
|
478 |
+
['Craig','Pollack','(310) 987-6543']
|
479 |
+
]
|
480 |
+
..........................................
|
481 |
+
|
482 |
+
First off, the =Uize.Data.Csv.from= method doesn't know that the CSV data string has a header row unless we tell it, so we specify the value =true= for the =hasHeader= option. If we don't expicitly specify a value for the =rowType= option, this option will default to ='auto'=, and the =Uize.Data.Csv.from= method will decide to parse the CSV data string to an array of objects because we're specifying =true= for the =hasHeader= option. By specifying the value ='array'= for =rowType=, we override this automatic behavior. This results in the header row being "gobbled" up - it's not getting used as the keys for object records, and it doesn't belong in the data set.
|
483 |
+
|
484 |
+
With Header Row, Rows Are Arrays, Get Back Column Names
|
485 |
+
In this example, the CSV data string contains a header row, we want to parse the string to an array of arrays and don't want the column names in the data set, but we would like to know what the column names are.
|
486 |
+
|
487 |
+
INPUT
|
488 |
+
..............................
|
489 |
+
firstName,lastName,phone
|
490 |
+
John,Wilkey,(650) 123-4567
|
491 |
+
Marie,Stevenson,(415) 456-7890
|
492 |
+
Craig,Pollack,(310) 987-6543
|
493 |
+
..............................
|
494 |
+
|
495 |
+
PARSE
|
496 |
+
................................................................................
|
497 |
+
var columnNames = [];
|
498 |
+
Uize.Data.Csv.from (input,{hasHeader:true,rowType:'array',columns:columnNames});
|
499 |
+
................................................................................
|
500 |
+
|
501 |
+
OUTPUT
|
502 |
+
..........................................
|
503 |
+
[
|
504 |
+
['John','Wilkey','(650) 123-4567'],
|
505 |
+
['Marie','Stevenson','(415) 456-7890'],
|
506 |
+
['Craig','Pollack','(310) 987-6543']
|
507 |
+
]
|
508 |
+
..........................................
|
509 |
+
|
510 |
+
First off, the =Uize.Data.Csv.from= method doesn't know that the CSV data string has a header row unless we tell it, so we specify the value =true= for the =hasHeader= option. We specify the value ='array'= for the =rowType= option to override the automatic behaviour in this case of parsing the CSV data string to an array of objects. Finally, we specify a reference to an empty array for the =columns= option. This empty array will be populated with the column names obtained from the CSV data string's header row. We can then use these column names later in other code.
|
511 |
+
|
512 |
+
Values Quoted Using Single Quotes
|
513 |
+
In this example, the CSV data string was originally serialized using a single quote character for quoting values, rather than the standard double quote character.
|
514 |
+
|
515 |
+
We happen to know this about the source material, so we specify the value ='\''= for the =quoteChar= option. Our CSV data string parses correctly and life is good.
|
516 |
+
|
517 |
+
INPUT
|
518 |
+
....................................
|
519 |
+
'John','Wilkey','(650) 123-4567'
|
520 |
+
'Marie','Stevenson','(415) 456-7890'
|
521 |
+
'Craig','Pollack','(310) 987-6543'
|
522 |
+
....................................
|
523 |
+
|
524 |
+
PARSE
|
525 |
+
............................................
|
526 |
+
Uize.Data.Csv.from (input,{quoteChar:'\''});
|
527 |
+
............................................
|
528 |
+
|
529 |
+
OUTPUT
|
530 |
+
..........................................
|
531 |
+
[
|
532 |
+
['John','Wilkey','(650) 123-4567'],
|
533 |
+
['Marie','Stevenson','(415) 456-7890'],
|
534 |
+
['Craig','Pollack','(310) 987-6543']
|
535 |
+
]
|
536 |
+
..........................................
|
537 |
+
|
538 |
+
Pipe Used As a Value Delimiter
|
539 |
+
In this example, the (obviously) eccentric software that originally serialized the CSV data string used a "|" (pipe) character for separating column values.
|
540 |
+
|
541 |
+
Fortunately, we happen to know this about the source material, so we specify the value ='|'= for the =valueDelimiter= option and the =Uize.Data.Csv.from= method saves the day.
|
542 |
+
|
543 |
+
INPUT
|
544 |
+
..............................
|
545 |
+
John|Wilkey|(650) 123-4567
|
546 |
+
Marie|Stevenson|(415) 456-7890
|
547 |
+
Craig|Pollack|(310) 987-6543
|
548 |
+
..............................
|
549 |
+
|
550 |
+
PARSE
|
551 |
+
................................................
|
552 |
+
Uize.Data.Csv.from (input,{valueDelimiter:'|'});
|
553 |
+
................................................
|
554 |
+
|
555 |
+
OUTPUT
|
556 |
+
..........................................
|
557 |
+
[
|
558 |
+
['John','Wilkey','(650) 123-4567'],
|
559 |
+
['Marie','Stevenson','(415) 456-7890'],
|
560 |
+
['Craig','Pollack','(310) 987-6543']
|
561 |
+
]
|
562 |
+
..........................................
|
563 |
+
|
564 |
+
Space As Value Delimiter, Values Quoted Using Hash
|
565 |
+
To one-up the software that serialized a CSV data string using a "|" (pipe) character for separating column values, some even crazier software decided to use the "#" (pound / hash) character for quoting column values and a single space for separating values.
|
566 |
+
|
567 |
+
We suspect as much about the source material, based upon our deep-seated suspicions of the provider of the data, so we specify the value ='#'= for the =quoteChar= option and the value =' '= (space) for the =valueDelimiter= option. Everything checks out, and we've dodged another bullet.
|
568 |
+
|
569 |
+
INPUT
|
570 |
+
....................................
|
571 |
+
#John# #Wilkey# #(650) 123-4567#
|
572 |
+
#Marie# #Stevenson# #(415) 456-7890#
|
573 |
+
#Craig# #Pollack# #(310) 987-6543#
|
574 |
+
....................................
|
575 |
+
|
576 |
+
PARSE
|
577 |
+
..............................................................
|
578 |
+
Uize.Data.Csv.from (input,{quoteChar:'#',valueDelimiter:' '});
|
579 |
+
..............................................................
|
580 |
+
|
581 |
+
OUTPUT
|
582 |
+
..........................................
|
583 |
+
[
|
584 |
+
['John','Wilkey','(650) 123-4567'],
|
585 |
+
['Marie','Stevenson','(415) 456-7890'],
|
586 |
+
['Craig','Pollack','(310) 987-6543']
|
587 |
+
]
|
588 |
+
..........................................
|
589 |
+
|
590 |
+
NOTES
|
591 |
+
- see the companion =Uize.Data.Csv.to= static method
|
592 |
+
*/
|
593 |
+
};
|
594 |
+
|
595 |
+
_package.to = function (_toEncode,_encodingOptions) {
|
596 |
+
var
|
597 |
+
_csvChunks = [],
|
598 |
+
_firstRow = _toEncode [0],
|
599 |
+
_alwaysQuote = _getDefaultedOption (_encodingOptions,'whenToQuoteValues') == 'always',
|
600 |
+
_columns = _getDefaultedOption (_encodingOptions,'columns'),
|
601 |
+
_hasHeader = _getDefaultedOption (_encodingOptions,'hasHeader'),
|
602 |
+
_trimPaddingOnParse = _getDefaultedOption (_encodingOptions,'trimPaddingOnParse'),
|
603 |
+
_quoteChar = _getDefaultedOption (_encodingOptions,'quoteChar'),
|
604 |
+
_rowType = _getDefaultedOption (_encodingOptions,'rowType'),
|
605 |
+
_valueDelimiter = _getDefaultedOption (_encodingOptions,'valueDelimiter'),
|
606 |
+
_valueDelimiterHasPadding = Uize.String.hasPadding (_valueDelimiter),
|
607 |
+
_escapedQuoteChar = _getEscapedQuoteChar (_encodingOptions),
|
608 |
+
_quoteRegExp = _globalLiteralRegExp (_quoteChar),
|
609 |
+
_rowTypeIsObject = _rowType == 'object' || (_rowType == 'auto' && _firstRow && !Uize.isArray (_firstRow))
|
610 |
+
;
|
611 |
+
if (_columns == 'all')
|
612 |
+
_columns = !_firstRow
|
613 |
+
? []
|
614 |
+
: _rowTypeIsObject
|
615 |
+
? Uize.keys (_firstRow)
|
616 |
+
: Uize.map (_firstRow.length,'key')
|
617 |
+
;
|
618 |
+
var _totalColumns = _columns.length;
|
619 |
+
for (var _rowNo = -1 - _hasHeader, _totalRows = _toEncode.length; ++_rowNo < _totalRows;) {
|
620 |
+
var _row = _rowNo < 0 ? _columns : _toEncode [_rowNo];
|
621 |
+
for (var _columnNo = -1; ++_columnNo < _totalColumns;) {
|
622 |
+
var
|
623 |
+
_columnValue = _row [_rowNo < 0 || !_rowTypeIsObject ? _columnNo : _columns [_columnNo]] + '',
|
624 |
+
_valueHasQuoteChar = _columnValue.indexOf (_quoteChar) > -1,
|
625 |
+
_quoteCharForValue =
|
626 |
+
_valueHasQuoteChar ||
|
627 |
+
_alwaysQuote ||
|
628 |
+
(_trimPaddingOnParse ? Uize.String.hasPadding (_columnValue) : _valueDelimiterHasPadding) ||
|
629 |
+
_columnValue.indexOf (_valueDelimiter) > -1 ||
|
630 |
+
_columnValue.indexOf ('\n') > -1 ||
|
631 |
+
_columnValue.indexOf ('\r') > -1
|
632 |
+
? _quoteChar
|
633 |
+
: ''
|
634 |
+
;
|
635 |
+
_csvChunks.push (
|
636 |
+
(_columnNo ? _valueDelimiter : '') +
|
637 |
+
_quoteCharForValue +
|
638 |
+
(_valueHasQuoteChar ? _columnValue.replace (_quoteRegExp,_escapedQuoteChar) : _columnValue) +
|
639 |
+
_quoteCharForValue
|
640 |
+
);
|
641 |
+
}
|
642 |
+
_rowNo < _totalRows - 1 && _csvChunks.push ('\n');
|
643 |
+
}
|
644 |
+
return _csvChunks.join ('');
|
645 |
+
/*?
|
646 |
+
Static Methods
|
647 |
+
Uize.Data.Csv.to
|
648 |
+
Returns a string, being the specified array of records serialized to a CSV formatted data string.
|
649 |
+
|
650 |
+
SYNTAX
|
651 |
+
.............................................
|
652 |
+
csvDataSTR = Uize.Data.Csv.to (recordsARRAY);
|
653 |
+
.............................................
|
654 |
+
|
655 |
+
VARIATION
|
656 |
+
................................................................
|
657 |
+
csvDataSTR = Uize.Data.Csv.to (recordsARRAY,encodingOptionsOBJ);
|
658 |
+
................................................................
|
659 |
+
|
660 |
+
When the optional =encodingOptionsOBJ= parameter is specified, then the way in which the records array is serialized to CSV data format can be configured to produce wide ranging results - even non-standard serialized CSV data that is not in strict accordance with the rules laid out in RFC 4180. If you use this parameter to produce serialized data that deviates from the rules of RFC 4180, then you should specify the same options in the =decodingOptionsOBJ= parameter of the companion =Uize.Data.Csv.from= method in order to successfully parse the non-standard serialized CSV data back into a records array.
|
661 |
+
|
662 |
+
The value of the =encodingOptionsOBJ= parameter should be an object, with properties as follows...
|
663 |
+
|
664 |
+
ENCODING OPTIONS
|
665 |
+
..............................................................................
|
666 |
+
{
|
667 |
+
columns:columnsSTRorARRAY, // optional, defaults to 'all'
|
668 |
+
hasHeader:hasHeaderBOOL, // optional, defaults to false
|
669 |
+
trimPaddingOnParse:trimPaddingOnParseBOOL, // optional, defaults to false
|
670 |
+
quoteChar:quoteCharSTR, // optional, defaults to '"'
|
671 |
+
rowType:rowTypeSTR, // optional, defaults to 'auto'
|
672 |
+
valueDelimiter:valueDelimiterSTR, // optional, defaults to ','
|
673 |
+
whenToQuoteValues:whenToQuoteValuesSTR // optional, defaults to 'auto'
|
674 |
+
}
|
675 |
+
..............................................................................
|
676 |
+
|
677 |
+
columns
|
678 |
+
An array, that can be used to supply column names when the value of the =hasHeader= option is =true= and the records to be serialized are of type array, or that can be used to specify the order of columns or to specify a subset of columns when the records to be serialized are of type object, or a string with the value ='all'= specifying that all columns should be serialized.
|
679 |
+
|
680 |
+
If the value ='all'= is specified for the =columns= option, then the column names will be the keys from the first record if the records to be serialized are of type object, or the indices of the columns if the records to be serialized are of type array.
|
681 |
+
|
682 |
+
When serializing an array of objects to a CSV data string, the =Uize.Data.Csv.to= method provides support for controlling the ordering of columns in the serialized data string, as well as serializing just a subset of the columns in the data set. For more info, see the section `Column Ordering And Filtering`.
|
683 |
+
|
684 |
+
NOTES
|
685 |
+
- the default value for this option is ='all'=
|
686 |
+
|
687 |
+
hasHeader
|
688 |
+
A boolean, specifying whether or not the serialized CSV data string should contain a header row.
|
689 |
+
|
690 |
+
When the value =true= is specified for this option, the first row of the serialized CSV data will contain the names of the columns. This allows the CSV formatted data to be parsed later by code that may not know the column names for the data - the column names can be obtained from the serialized data. The column names for the first row will be obtained from the =columns= option.
|
691 |
+
|
692 |
+
NOTES
|
693 |
+
- the default value for this option is =false=
|
694 |
+
|
695 |
+
trimPaddingOnParse
|
696 |
+
A boolean, specifying whether or not padding around non-quoted values will be trimmed away when the serialized CSV data string is parsed at a later stage.
|
697 |
+
|
698 |
+
While whitespace around value separator characters is considered significant, and while trimming such whitespace is specifically prohibited according to [[http://tools.ietf.org/html/rfc4180][RFC 4180]], data serialized by the =Uize.Data.Csv.to= method may at some point be parsed by code that doesn't strictly observe the rules laid out in RFC 4180 and which may strip padding around comma value separators.
|
699 |
+
|
700 |
+
In such cases, the value =true= can be specified for the =trimPaddingOnParse= option, which will cause values that contain leading and/or trailing whitespace padding around the first and last non-whitespace characters to be quoted in order to ensure that whitespace that is part of values is not accidentally stripped by a non-compliant CSV parser.
|
701 |
+
|
702 |
+
NOTES
|
703 |
+
- the default value for this option is =false=
|
704 |
+
|
705 |
+
quoteChar
|
706 |
+
A string, specifying the *single* character that should be used for quoting values in the serialized CSV data string.
|
707 |
+
|
708 |
+
While [[http://tools.ietf.org/html/rfc4180][RFC 4180]] only addresses quoting of values using the double quote character, the =Uize.Data.Csv= module provides the flexibility to use other quoting characters - both when serializing using the =Uize.Data.Csv.to= method and parsing using the =Uize.Data.Csv.from= method.
|
709 |
+
|
710 |
+
When serializing data to CSV format using a quoting character other than double quotes, it is important to specify that character in the =quoteChar= option when later parsing that serialized data - the =Uize.Data.Csv.from= method cannot tell automatically from the CSV data string what the quoting character is. Whatever quoting character is specified, if a value contains that quote character, then that value will be quoted. As per the RFC 4180 rules, the quoting character is escaped by doubling it.
|
711 |
+
|
712 |
+
NOTES
|
713 |
+
- the value of the =quoteChar= option may not be the same as the =valueDelimiter= option
|
714 |
+
- the default value for this option is ='"'= (the double quote character)
|
715 |
+
|
716 |
+
rowType
|
717 |
+
A string, specifying the type for the records in the records array to be serialized to a CSV data string.
|
718 |
+
|
719 |
+
- ='array'= - Each row's record is represented by an array of values for the various columns.
|
720 |
+
|
721 |
+
- ='object'= - Each row's record is represented by an object, with key/value pairs for the various columns, where the key is the column name and the value is the column value.
|
722 |
+
|
723 |
+
- ='auto'= (default) - Array or object type will be chosen based upon the type of the first element of the records array being serialized.
|
724 |
+
|
725 |
+
If the row type is ='array'= and the value =true= is specified for the =hasHeader= option, then the column names should be supplied in the =columns= option.
|
726 |
+
|
727 |
+
IMPORTANT
|
728 |
+
|
729 |
+
Specifying ='array'= or ='object'= for this encoding option of the =Uize.Data.Csv.to= method has less meaning than specifying ='array'= or ='object'= for the companion decoding option of the =Uize.Data.Csv.from= method. When parsing a CSV data string, the =rowType= option lets you control the type of the generated records array. When specifying ='array'= or ='object'= for the =rowType= option with the =Uize.Data.Csv.to= method, the serialization could produce faulty results if the specified row type does not match the actual type of the elements of the records array. Therefore, one will generally not specify an explicit value for this encoding option of the =Uize.Data.Csv.to= method.
|
730 |
+
|
731 |
+
NOTES
|
732 |
+
- the default value for this option is ='auto'=
|
733 |
+
|
734 |
+
valueDelimiter
|
735 |
+
A string, specifying the delimiter that should be used to separate column values in rows of the serialized CSV data string.
|
736 |
+
|
737 |
+
While [[http://tools.ietf.org/html/rfc4180][RFC 4180]] only addresses separating values using the comma character, the =Uize.Data.Csv= module provides the flexibility to use other value delimiter characters - both when serializing using the =Uize.Data.Csv.to= method and parsing using the =Uize.Data.Csv.from= method.
|
738 |
+
|
739 |
+
When serializing data to CSV format using a value delimiter character other than comma, it is important to specify that delimiter in the =valueDelimiter= option when later parsing that serialized data - the =Uize.Data.Csv.from= method cannot tell automatically from the CSV data string what the value delimiter is.
|
740 |
+
|
741 |
+
Whatever value delimiter string is specified, if a value contains that string, then that value will be quoted. Also, if the value delimiter has whitespace padding, then the column values will always be quoted to ensure that later parsing doesn't result in the value delimiter's padding becoming whitespace in the parsed column values.
|
742 |
+
|
743 |
+
NOTES
|
744 |
+
- the value of the =valueDelimiter= option may not be the same as the =quoteChar= option, and may not contain the quoting character if it is a multi-character delimiter
|
745 |
+
- the default value for this option is =','= (the comma character)
|
746 |
+
|
747 |
+
whenToQuoteValues
|
748 |
+
A boolean, specifying the quoting behavior when serializing column values.
|
749 |
+
|
750 |
+
- ='always'= - Column values will always be quoted. When this value is specified for the =whenToQuoteValues= option, all column values in the serialized CSV data string will be quoted.
|
751 |
+
|
752 |
+
- ='auto'= (default) - Column values will be automatically quoted, only when necessary. When this value is specified for the =whenToQuoteValues= option, column values will be quoted if they contain the quoting character (see the =quoteChar= option) or the value delimiter string (see the =valueDelimiter= option), if they contain linebreaks (either carriage return or linefeed characters), if they contain whitespace padding and the value =true= is specified for the =trimPaddingOnParse= option, or if the value delimiter (see the =valueDelimiter= option) contains whitespace padding and the value =false= is specified for the =trimPaddingOnParse= option.
|
753 |
+
|
754 |
+
NOTES
|
755 |
+
- the default value for this option is ='auto'=
|
756 |
+
|
757 |
+
Examples
|
758 |
+
Default Encoding Options
|
759 |
+
In this example, we have some very plain vanilla data - in the form of an array of arrays - and we're serializing this data to a CSV data string in strict accordance with the rules laid out in RFC 4180.
|
760 |
+
|
761 |
+
INPUT
|
762 |
+
..........................................
|
763 |
+
[
|
764 |
+
['John','Wilkey','(650) 123-4567'],
|
765 |
+
['Marie','Stevenson','(415) 456-7890'],
|
766 |
+
['Craig','Pollack','(310) 987-6543']
|
767 |
+
]
|
768 |
+
..........................................
|
769 |
+
|
770 |
+
SERIALIZE
|
771 |
+
.........................
|
772 |
+
Uize.Data.Csv.to (input);
|
773 |
+
.........................
|
774 |
+
|
775 |
+
OUTPUT
|
776 |
+
..............................
|
777 |
+
John,Wilkey,(650) 123-4567
|
778 |
+
Marie,Stevenson,(415) 456-7890
|
779 |
+
Craig,Pollack,(310) 987-6543
|
780 |
+
..............................
|
781 |
+
|
782 |
+
There is nothing particulatly challenging about the source records array - none of the values have special characters that would cause them to need quoting. To serialize to strict CSV format, we don't need to specify any encoding options in the optional =encodingOptionsOBJ= parameter. Sometimes life is just too easy.
|
783 |
+
|
784 |
+
Default Encoding Options, Values Needing Quotes
|
785 |
+
In this example, we're serializing data to a CSV data string in strict accordance with the rules laid out in RFC 4180, but some of the column values contain special characters that require them to be quoted.
|
786 |
+
|
787 |
+
INPUT
|
788 |
+
.......................................................
|
789 |
+
[
|
790 |
+
['John "Willy"','Wilkey','(650) 123-4567'],
|
791 |
+
['Marie','Stevenson','(415) 456-7890, Ext. 214'],
|
792 |
+
['Craig','Pollack','(310) 987-6543\n(650) 303-1000']
|
793 |
+
]
|
794 |
+
.......................................................
|
795 |
+
|
796 |
+
SERIALIZE
|
797 |
+
.........................
|
798 |
+
Uize.Data.Csv.to (input);
|
799 |
+
.........................
|
800 |
+
|
801 |
+
OUTPUT
|
802 |
+
..........................................
|
803 |
+
"John ""Willy""",Wilkey,(650) 123-4567
|
804 |
+
Marie,Stevenson,"(415) 456-7890, Ext. 214"
|
805 |
+
Craig,Pollack,"(310) 987-6543
|
806 |
+
(650) 303-1000"
|
807 |
+
..........................................
|
808 |
+
|
809 |
+
Comparing the source records array to the serialized CSV data string, you'll notice a few things...
|
810 |
+
|
811 |
+
- The value ='John "Willy"'= had to be quoted as ="John ""Willy"""=, because it contains the double quote quoting character. Therefore, the serialized value has double quotes around it, and the double quotes in the value are escaped by doubling them up (ie. two double quotes for each double quote being escaped).
|
812 |
+
- The value ='(415) 456-7890, Ext. 214'= had to be quoted because it contains the comma value delimiter character.
|
813 |
+
- The value ='(650) 123-4567\n(650) 303-1000'= had to be quoted because it contains a linebreak and spans two lines.
|
814 |
+
|
815 |
+
None of the above factors are a problem for the =Uize.Data.Csv.to= method, since all these behaviors comply with the rules of RFC 4180, and no special encoding options needed to be specified.
|
816 |
+
|
817 |
+
Default Encoding Options, Values With Padding
|
818 |
+
In this example, we're serializing data to a CSV data string in strict accordance with the rules laid out in RFC 4180, where some of the column values contain whitespace padding.
|
819 |
+
|
820 |
+
INPUT
|
821 |
+
............................................
|
822 |
+
[
|
823 |
+
['John',' Wilkey ','(650) 123-4567'],
|
824 |
+
['Marie',' Stevenson ','(415) 456-7890'],
|
825 |
+
['Craig',' Pollack ','(310) 987-6543']
|
826 |
+
]
|
827 |
+
............................................
|
828 |
+
|
829 |
+
SERIALIZE
|
830 |
+
.........................
|
831 |
+
Uize.Data.Csv.to (input);
|
832 |
+
.........................
|
833 |
+
|
834 |
+
OUTPUT
|
835 |
+
................................
|
836 |
+
John, Wilkey ,(650) 123-4567
|
837 |
+
Marie, Stevenson ,(415) 456-7890
|
838 |
+
Craig, Pollack ,(310) 987-6543
|
839 |
+
................................
|
840 |
+
|
841 |
+
Because we're serializing to strict CSV format, none of the values that contain padding need to be quoted. This is because whitespace around the value separator is considered significant according to RFC 4180 and should not be stripped. Therefore, no special encoding options need to be specified when calling the =Uize.Data.Csv.to= method in this case.
|
842 |
+
|
843 |
+
Values With Padding, Trim Padding On Parse
|
844 |
+
In this example, we're serializing an array of arrays to a CSV data string, some of the values contain whitespace padding, and we know that the serialized CSV data string may at some point be parsed by code that trims padding around values.
|
845 |
+
|
846 |
+
In order to protect against the padding in our values being stripped out later, we let the =Uize.Data.Csv.to= method know that padding will be trimmed, by some parser in the future, by specifying the value =true= for the =trimPaddingOnParse= option. This results in the =Uize.Data.Csv.to= method quoting those values that contain padding.
|
847 |
+
|
848 |
+
INPUT
|
849 |
+
............................................
|
850 |
+
[
|
851 |
+
['John',' Wilkey ','(650) 123-4567'],
|
852 |
+
['Marie',' Stevenson ','(415) 456-7890'],
|
853 |
+
['Craig',' Pollack ','(310) 987-6543']
|
854 |
+
]
|
855 |
+
............................................
|
856 |
+
|
857 |
+
SERIALIZE
|
858 |
+
...................................................
|
859 |
+
Uize.Data.Csv.to (input,{trimPaddingOnParse:true});
|
860 |
+
...................................................
|
861 |
+
|
862 |
+
OUTPUT
|
863 |
+
..................................
|
864 |
+
John," Wilkey ",(650) 123-4567
|
865 |
+
Marie," Stevenson ",(415) 456-7890
|
866 |
+
Craig," Pollack ",(310) 987-6543
|
867 |
+
..................................
|
868 |
+
|
869 |
+
With Header Row, Column Names Explicitly Specified
|
870 |
+
In this example, we're serializing an array of arrays to a CSV data string that has a header row, so we're supplying the column names explicitly.
|
871 |
+
|
872 |
+
To make sure that the serialized CSV data string has a header row, we specify the value =true= for the =hasHeader= option. Problem is, the records array does not contain the column names. This is normal, since the column names really aren't part of the data set. To remedy this, we explicitly provide the =Uize.Data.Csv.to= method with the column names using the =columns= option.
|
873 |
+
|
874 |
+
INPUT
|
875 |
+
..........................................
|
876 |
+
[
|
877 |
+
['John','Wilkey','(650) 123-4567'],
|
878 |
+
['Marie','Stevenson','(415) 456-7890'],
|
879 |
+
['Craig','Pollack','(310) 987-6543']
|
880 |
+
]
|
881 |
+
..........................................
|
882 |
+
|
883 |
+
SERIALIZE
|
884 |
+
..............................................
|
885 |
+
Uize.Data.Csv.to (
|
886 |
+
input,
|
887 |
+
{
|
888 |
+
hasHeader:true,
|
889 |
+
columns:['firstName','lastName','phone']
|
890 |
+
}
|
891 |
+
);
|
892 |
+
..............................................
|
893 |
+
|
894 |
+
OUTPUT
|
895 |
+
..............................
|
896 |
+
firstName,lastName,phone
|
897 |
+
John,Wilkey,(650) 123-4567
|
898 |
+
Marie,Stevenson,(415) 456-7890
|
899 |
+
Craig,Pollack,(310) 987-6543
|
900 |
+
..............................
|
901 |
+
|
902 |
+
With Header Row, Rows Are Objects, Column Names From Object Keys
|
903 |
+
In this example, we're serializing an array of objects to a CSV data string that has a header row, where the keys of the first record object are used as the column names.
|
904 |
+
|
905 |
+
As you'll notice from the records array, the first record has the object keys defined in a different order to the other records. The =phone= key is first, followed by =lastName= and =firstName=. Because we're not explicitly specifying a column order, the columns' names and their ordering is all determined by the first record. If you're parsing the serialized CSV data string back to an array of objects later, then this shouldn't matter. If you care about the order, then refer to the example `With Header Row, Rows Are Objects, Column Order Specified`. To get the header row in the serialized CSV data string, we're specifying the value =true= for the =hasHeader= option.
|
906 |
+
|
907 |
+
INPUT
|
908 |
+
...................................................................
|
909 |
+
[
|
910 |
+
{phone:'(650) 123-4567',lastName:'Wilkey',firstName:'John'},
|
911 |
+
{firstName:'Marie',lastName:'Stevenson',phone:'(415) 456-7890'},
|
912 |
+
{firstName:'Craig',lastName:'Pollack',phone:'(310) 987-6543'}
|
913 |
+
]
|
914 |
+
...................................................................
|
915 |
+
|
916 |
+
SERIALIZE
|
917 |
+
..........................................
|
918 |
+
Uize.Data.Csv.to (input,{hasHeader:true});
|
919 |
+
..........................................
|
920 |
+
|
921 |
+
OUTPUT
|
922 |
+
..............................
|
923 |
+
phone,lastName,firstName
|
924 |
+
(650) 123-4567,Wilkey,John
|
925 |
+
(415) 456-7890,Stevenson,Marie
|
926 |
+
(310) 987-6543,Pollack,Craig
|
927 |
+
..............................
|
928 |
+
|
929 |
+
With Header Row, Rows Are Objects, Column Order Specified
|
930 |
+
In this example, we're serializing an array of objects to a CSV data string that has a header row, and we're explicitly specifying the column order using the =columns= option.
|
931 |
+
|
932 |
+
Unlike the example `With Header Row, Rows Are Objects, Column Names From Object Keys`, here we actually care about the order of the columns in the serialized CSV data string. Therefore, we are using the =columns= option to control the ordering. If we didn't do this, the ordering would be determined by the order of the keys in the first record object.
|
933 |
+
|
934 |
+
To get the header row in the serialized CSV data string, we're specifying the value =true= for the =hasHeader= option. You could argue that controlling the column ordering would be even more important if the serialized CSV data string were to *not* contain a header row and was expected to be parsed at some later stage to an array of arrays, where there was an expected column ordering.
|
935 |
+
|
936 |
+
INPUT
|
937 |
+
...................................................................
|
938 |
+
[
|
939 |
+
{phone:'(650) 123-4567',lastName:'Wilkey',firstName:'John'},
|
940 |
+
{firstName:'Marie',lastName:'Stevenson',phone:'(415) 456-7890'},
|
941 |
+
{firstName:'Craig',lastName:'Pollack',phone:'(310) 987-6543'}
|
942 |
+
]
|
943 |
+
...................................................................
|
944 |
+
|
945 |
+
SERIALIZE
|
946 |
+
..............................................
|
947 |
+
Uize.Data.Csv.to (
|
948 |
+
input,
|
949 |
+
{
|
950 |
+
hasHeader:true,
|
951 |
+
columns:['firstName','lastName','phone']
|
952 |
+
}
|
953 |
+
);
|
954 |
+
..............................................
|
955 |
+
|
956 |
+
OUTPUT
|
957 |
+
..............................
|
958 |
+
firstName,lastName,phone
|
959 |
+
John,Wilkey,(650) 123-4567
|
960 |
+
Marie,Stevenson,(415) 456-7890
|
961 |
+
Craig,Pollack,(310) 987-6543
|
962 |
+
..............................
|
963 |
+
|
964 |
+
With Header Row, Rows Are Objects, Subset of Columns
|
965 |
+
In this example, we're serializing an array of objects to a CSV data string that has a header row, and we're specifying a subset of the columns in the data set to be serialized.
|
966 |
+
|
967 |
+
Not only does the =columns= option let us control the ordering of columns in the serialized CSV data string (see the example `With Header Row, Rows Are Objects, Column Order Specified`), it also lets us specify just a subset of columns to serialize. In this example we're serializing just the =firstName= and =lastName= columns. To get the header row in the serialized CSV data string, we're specifying the value =true= for the =hasHeader= option.
|
968 |
+
|
969 |
+
INPUT
|
970 |
+
...................................................................
|
971 |
+
[
|
972 |
+
{phone:'(650) 123-4567',lastName:'Wilkey',firstName:'John'},
|
973 |
+
{firstName:'Marie',lastName:'Stevenson',phone:'(415) 456-7890'},
|
974 |
+
{firstName:'Craig',lastName:'Pollack',phone:'(310) 987-6543'}
|
975 |
+
]
|
976 |
+
...................................................................
|
977 |
+
|
978 |
+
SERIALIZE
|
979 |
+
......................................
|
980 |
+
Uize.Data.Csv.to (
|
981 |
+
input,
|
982 |
+
{
|
983 |
+
hasHeader:true,
|
984 |
+
columns:['firstName','lastName']
|
985 |
+
}
|
986 |
+
);
|
987 |
+
......................................
|
988 |
+
|
989 |
+
OUTPUT
|
990 |
+
..................
|
991 |
+
firstName,lastName
|
992 |
+
John,Wilkey
|
993 |
+
Marie,Stevenson
|
994 |
+
Craig,Pollack
|
995 |
+
..................
|
996 |
+
|
997 |
+
With Header Row, Columns Are Indices
|
998 |
+
In this example, we're serializing an array of arrays to a CSV data string that has a header row, and since we're not explicitly specifying the column names using the =columns= option, the column indices are used instead.
|
999 |
+
|
1000 |
+
To get the header row in the serialized CSV data string, we're specifying the value =true= for the =hasHeader= option. To have the array indices be used for the column names, we simply don't specify a value for the =columns= option. The default value of ='all'= when the row type is array causes the column indices to be used as the column names. This may be an unusual and atypical case, but it illustrates the behavior when this combination of options is used.
|
1001 |
+
|
1002 |
+
INPUT
|
1003 |
+
..........................................
|
1004 |
+
[
|
1005 |
+
['John','Wilkey','(650) 123-4567'],
|
1006 |
+
['Marie','Stevenson','(415) 456-7890'],
|
1007 |
+
['Craig','Pollack','(310) 987-6543']
|
1008 |
+
]
|
1009 |
+
..........................................
|
1010 |
+
|
1011 |
+
SERIALIZE
|
1012 |
+
..........................................
|
1013 |
+
Uize.Data.Csv.to (input,{hasHeader:true});
|
1014 |
+
..........................................
|
1015 |
+
|
1016 |
+
OUTPUT
|
1017 |
+
..............................
|
1018 |
+
0,1,2
|
1019 |
+
John,Wilkey,(650) 123-4567
|
1020 |
+
Marie,Stevenson,(415) 456-7890
|
1021 |
+
Craig,Pollack,(310) 987-6543
|
1022 |
+
..............................
|
1023 |
+
|
1024 |
+
Always Quote Values
|
1025 |
+
In this example, we're serializing an array of arrays to a CSV data string and forcing all values to be quoted by specifying the value ='always'= for the =whenToQuoteValues= option.
|
1026 |
+
|
1027 |
+
If we didn't specify a value for the =whenToQuoteValues= option in this example, then none of the values would be quoted. That's because none of the values contain special characters that would require them to be quoted. If it is anticipated that the CSV data string may be parsed by an inferior or non-RFC 4180 compliant parser that requires all values to be quoted, then we can used this facility. Alternatively, if the data set would likely cause a mix of quoting and not quoting, and we have an aesthetic preference for a consistent look / treatment, then we can force all values to be quoted using this option.
|
1028 |
+
|
1029 |
+
INPUT
|
1030 |
+
..........................................
|
1031 |
+
[
|
1032 |
+
['John','Wilkey','(650) 123-4567'],
|
1033 |
+
['Marie','Stevenson','(415) 456-7890'],
|
1034 |
+
['Craig','Pollack','(310) 987-6543']
|
1035 |
+
]
|
1036 |
+
..........................................
|
1037 |
+
|
1038 |
+
SERIALIZE
|
1039 |
+
......................................................
|
1040 |
+
Uize.Data.Csv.to (input,{whenToQuoteValues:'always'});
|
1041 |
+
......................................................
|
1042 |
+
|
1043 |
+
OUTPUT
|
1044 |
+
....................................
|
1045 |
+
"John","Wilkey","(650) 123-4567"
|
1046 |
+
"Marie","Stevenson","(415) 456-7890"
|
1047 |
+
"Craig","Pollack","(310) 987-6543"
|
1048 |
+
....................................
|
1049 |
+
|
1050 |
+
Always Quote Values, Using Single Quotes
|
1051 |
+
In this example, we're serializing an array of arrays to a CSV data string and forcing all values to be quoted using a single quote character.
|
1052 |
+
|
1053 |
+
We force all values to be quoted by specifying the value ='always'= for the =whenToQuoteValues= option, and we force single quotes to be used by specifying the value ='/''= for the =quoteChar= option. It is important, when serializing data using encoding options that don't conform to RFC 4180, that you specify the same options upon decoding data serialized in this way using the =Uize.Data.Csv.from= method. Compare this example to the example `Always Quote Values`, where all values are quoted, but using the RFC 4180 compliant double quote character.
|
1054 |
+
|
1055 |
+
INPUT
|
1056 |
+
..........................................
|
1057 |
+
[
|
1058 |
+
['John','Wilkey','(650) 123-4567'],
|
1059 |
+
['Marie','Stevenson','(415) 456-7890'],
|
1060 |
+
['Craig','Pollack','(310) 987-6543']
|
1061 |
+
]
|
1062 |
+
..........................................
|
1063 |
+
|
1064 |
+
SERIALIZE
|
1065 |
+
.....................................................................
|
1066 |
+
Uize.Data.Csv.to (input,{whenToQuoteValues:'always',quoteChar:'\''});
|
1067 |
+
.....................................................................
|
1068 |
+
|
1069 |
+
OUTPUT
|
1070 |
+
....................................
|
1071 |
+
'John','Wilkey','(650) 123-4567'
|
1072 |
+
'Marie','Stevenson','(415) 456-7890'
|
1073 |
+
'Craig','Pollack','(310) 987-6543'
|
1074 |
+
....................................
|
1075 |
+
|
1076 |
+
Use Pipe As a Value Delimiter
|
1077 |
+
In this example, we're serializing an array of arrays to a CSV data string, using a non-standard "|" (pipe) character as a value delimiter.
|
1078 |
+
|
1079 |
+
This is an unusual case, but not quite as unusual as the example `Space As Value Delimiter, Quote Values Using Hash`. The =Uize.Data.Csv.to= method provides the flexibility to do some unusual things. It is important, when serializing data using encoding options that don't conform to RFC 4180, that you specify the same options upon decoding data serialized in this way using the =Uize.Data.Csv.from= method.
|
1080 |
+
|
1081 |
+
INPUT
|
1082 |
+
..........................................
|
1083 |
+
[
|
1084 |
+
['John','Wilkey','(650) 123-4567'],
|
1085 |
+
['Marie','Stevenson','(415) 456-7890'],
|
1086 |
+
['Craig','Pollack','(310) 987-6543']
|
1087 |
+
]
|
1088 |
+
..........................................
|
1089 |
+
|
1090 |
+
SERIALIZE
|
1091 |
+
..............................................
|
1092 |
+
Uize.Data.Csv.to (input,{valueDelimiter:'|'});
|
1093 |
+
..............................................
|
1094 |
+
|
1095 |
+
OUTPUT
|
1096 |
+
..............................
|
1097 |
+
John|Wilkey|(650) 123-4567
|
1098 |
+
Marie|Stevenson|(415) 456-7890
|
1099 |
+
Craig|Pollack|(310) 987-6543
|
1100 |
+
..............................
|
1101 |
+
|
1102 |
+
Space As Value Delimiter, Quote Values Using Hash
|
1103 |
+
In this example, a space is being used as a value delimiter and a "#" (pound / hash) character is being used as a quoting character.
|
1104 |
+
|
1105 |
+
This is a rather unusual case, and who's to say why this choice of options would be made. This example demonstrates, however, that the =Uize.Data.Csv.to= method provides the flexibility to do some unusual things. It is important, when serializing data using encoding options that don't conform to RFC 4180, that you specify the same options upon decoding data serialized in this way using the =Uize.Data.Csv.from= method.
|
1106 |
+
|
1107 |
+
INPUT
|
1108 |
+
..........................................
|
1109 |
+
[
|
1110 |
+
['John','Wilkey','(650) 123-4567'],
|
1111 |
+
['Marie','Stevenson','(415) 456-7890'],
|
1112 |
+
['Craig','Pollack','(310) 987-6543']
|
1113 |
+
]
|
1114 |
+
..........................................
|
1115 |
+
|
1116 |
+
SERIALIZE
|
1117 |
+
............................................................
|
1118 |
+
Uize.Data.Csv.to (input,{quoteChar:'#',valueDelimiter:' '});
|
1119 |
+
............................................................
|
1120 |
+
|
1121 |
+
OUTPUT
|
1122 |
+
....................................
|
1123 |
+
#John# #Wilkey# #(650) 123-4567#
|
1124 |
+
#Marie# #Stevenson# #(415) 456-7890#
|
1125 |
+
#Craig# #Pollack# #(310) 987-6543#
|
1126 |
+
....................................
|
1127 |
+
|
1128 |
+
Value Delimiter Contains Whitespace
|
1129 |
+
In this example, the value delimiter being specified in the =valueDelimiter= option is a comma with a trailing space.
|
1130 |
+
|
1131 |
+
This makes for a prettier CSV data string. We're not specifying a value for the =trimPaddingOnParse= option here, so it gets its default value of =false=. This means that the spaces introduced by the value delimiter could find their way into the column values when the CSV data string is parsed at a later stage. Therefore, the =Uize.Data.Csv.to= automatically quotes all the column values (as you'll see from the output) so that it is clear what's really inside the values and what's outside the values.
|
1132 |
+
|
1133 |
+
INPUT
|
1134 |
+
..........................................
|
1135 |
+
[
|
1136 |
+
['John','Wilkey','(650) 123-4567'],
|
1137 |
+
['Marie','Stevenson','(415) 456-7890'],
|
1138 |
+
['Craig','Pollack','(310) 987-6543']
|
1139 |
+
]
|
1140 |
+
..........................................
|
1141 |
+
|
1142 |
+
SERIALIZE
|
1143 |
+
...............................................
|
1144 |
+
Uize.Data.Csv.to (input,{valueDelimiter:', '});
|
1145 |
+
...............................................
|
1146 |
+
|
1147 |
+
OUTPUT
|
1148 |
+
......................................
|
1149 |
+
"John", "Wilkey", "(650) 123-4567"
|
1150 |
+
"Marie", "Stevenson", "(415) 456-7890"
|
1151 |
+
"Craig", "Pollack", "(310) 987-6543"
|
1152 |
+
......................................
|
1153 |
+
|
1154 |
+
Value Delimiter Contains Whitespace, Trim Padding on Parse
|
1155 |
+
In this example, the value delimiter being specified in the =valueDelimiter= option is a comma with a trailing space.
|
1156 |
+
|
1157 |
+
This makes for a prettier CSV data string. We don't mind that there appears to be an extra leading space before the second and third column values, because we know that the code that will parse this CSV data string later will trim whitespace padding around values, and we specify that fact using the =trimPaddingOnParse= option.
|
1158 |
+
|
1159 |
+
INPUT
|
1160 |
+
..........................................
|
1161 |
+
[
|
1162 |
+
['John','Wilkey','(650) 123-4567'],
|
1163 |
+
['Marie','Stevenson','(415) 456-7890'],
|
1164 |
+
['Craig',' Pollack ','(310) 987-6543']
|
1165 |
+
]
|
1166 |
+
..........................................
|
1167 |
+
|
1168 |
+
SERIALIZE
|
1169 |
+
.......................................................................
|
1170 |
+
Uize.Data.Csv.to (input,{valueDelimiter:', ',trimPaddingOnParse:true});
|
1171 |
+
.......................................................................
|
1172 |
+
|
1173 |
+
OUTPUT
|
1174 |
+
..................................
|
1175 |
+
John, Wilkey, (650) 123-4567
|
1176 |
+
Marie, Stevenson, (415) 456-7890
|
1177 |
+
Craig, " Pollack ", (310) 987-6543
|
1178 |
+
..................................
|
1179 |
+
|
1180 |
+
Notice in the output how the value =' Pollack '= is quoted, while all the other values aren't. This is because the value itself contains padding, and the =true= value for =trimPaddingOnParse= indicates that values containing padding should be quoted or there padding might be trimmed away in error during parsing at a later stage.
|
1181 |
+
|
1182 |
+
NOTES
|
1183 |
+
- see the companion =Uize.Data.Csv.from= static method
|
1184 |
+
*/
|
1185 |
+
};
|
1186 |
+
|
1187 |
+
return _package;
|
1188 |
+
}
|
1189 |
+
});
|
1190 |
+
|
skin/frontend/default/customproduct/js/Uize.Data.Matches.js
ADDED
@@ -0,0 +1,527 @@
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
|
Â
|
1 |
+
/*______________
|
2 |
+
| ______ | U I Z E J A V A S C R I P T F R A M E W O R K
|
3 |
+
| / / | ---------------------------------------------------
|
4 |
+
| / O / | MODULE : Uize.Data.Matches Package
|
5 |
+
| / / / |
|
6 |
+
| / / / /| | ONLINE : http://www.uize.com
|
7 |
+
| /____/ /__/_| | COPYRIGHT : (c)2012 UIZE
|
8 |
+
| /___ | LICENSE : Available under MIT License or GNU General Public License
|
9 |
+
|_______________| http://www.uize.com/license.html
|
10 |
+
*/
|
11 |
+
|
12 |
+
/* Module Meta Data
|
13 |
+
type: Package
|
14 |
+
importance: 2
|
15 |
+
codeCompleteness: 100
|
16 |
+
testCompleteness: 100
|
17 |
+
docCompleteness: 5
|
18 |
+
*/
|
19 |
+
|
20 |
+
/*?
|
21 |
+
Introduction
|
22 |
+
The =Uize.Data.Matches= module provides methods for finding matching elements in arrays or matching properties in objects.
|
23 |
+
|
24 |
+
*DEVELOPERS:* `Chris van Rensburg`
|
25 |
+
|
26 |
+
In a Nutshell
|
27 |
+
The =Uize.Data.Matches= module provides methods for performing the following types of matching operations...
|
28 |
+
|
29 |
+
- `iterating over matches`
|
30 |
+
- `removing or retaining matches`
|
31 |
+
- `counting matches`
|
32 |
+
- `getting the keys or values for all matches`
|
33 |
+
- `getting the key or value of the first match`
|
34 |
+
|
35 |
+
Iterating Over Matches
|
36 |
+
To make it easy to iterate over matches in a source array, object, or range, the =Uize.Data.Matches= module provides the =Uize.Data.Matches.forEach= static method.
|
37 |
+
|
38 |
+
The =Uize.Data.Matches.forEach= method can be used to `iterate over matching elements of an array`, `iterate over matching properties of an object`, or `iterate over matching values of a range`. In its most basic usage, the =Uize.Data.Matches.forEach= method lets you specify a source, a matcher, and an iterator.
|
39 |
+
|
40 |
+
TYPICAL USAGE
|
41 |
+
..............................................................................................
|
42 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC);
|
43 |
+
..............................................................................................
|
44 |
+
|
45 |
+
EXAMPLE
|
46 |
+
...
|
47 |
+
Uize.Data.Matches.forEach (
|
48 |
+
);
|
49 |
+
...
|
50 |
+
|
51 |
+
The =Uize.Data.Matches.forEach= method is versatile and supports a number of different usages. For more in-depth info, consult the method's [[Uize.Data.Matches.forEach][reference documentation]].
|
52 |
+
|
53 |
+
Removing or Retaining Matches
|
54 |
+
The =Uize.Data.Matches= module offers methods for processing an array, object, or range, and either removing or retaining matches.
|
55 |
+
|
56 |
+
The =Uize.Data.Matches.remove= method can be used to remove matches, while the =Uize.Data.Matches.retain= method can be used to retain matches.
|
57 |
+
|
58 |
+
Both of these methods support...
|
59 |
+
|
60 |
+
- processing a source array, object, or range (see `Specifying a Source`)
|
61 |
+
- finding matches by value and/or key/index (see `Specifying a Matcher`)
|
62 |
+
- removing or retaining a maximum number of matches (see `Limiting the Number of Matches`)
|
63 |
+
- modifying the original source or outputting the result to a newly created or specified target (see `Specifying a Target`)
|
64 |
+
|
65 |
+
Removing Matches
|
66 |
+
Matches can be removed from an array, object, or number range, using the =Uize.Data.Matches.remove= method.
|
67 |
+
|
68 |
+
TYPICAL USAGE
|
69 |
+
.............................................................................................
|
70 |
+
var result = Uize.Data.Matches.remove (sourceARRAYorOBJorINT,matcherFUNCorSTRorREGEXPorBOOL);
|
71 |
+
.............................................................................................
|
72 |
+
|
73 |
+
EXAMPLE
|
74 |
+
..............................................................................
|
75 |
+
var sparseArray = [];
|
76 |
+
sparseArray [1] = 'orange';
|
77 |
+
sparseArray [5] = 'peach';
|
78 |
+
sparseArray [8] = 'apple';
|
79 |
+
sparseArray [11] = 'pear';
|
80 |
+
|
81 |
+
var denseArray = Uize.Data.Matches.remove (sparseArray,'value === undefined'};
|
82 |
+
alert (denseArray.join ('|')); // alerts the text "orange|peach|apple|pear"
|
83 |
+
..............................................................................
|
84 |
+
|
85 |
+
In the above example, the sparsely populated array named =sparseArray= is being created and populated with four elements. There are gaps between the assigned elements of =sparseArray=, and the elements in these gaps will all have the value =undefined=. The =Uize.Data.Matches.remove= method is being used to produce a densely populated array from the =sparseArray= by removing every element whose value is =undefined=. You'll notice that we're `matching items using a value matcher regular expression` rather than a function. This is nice and concise.
|
86 |
+
|
87 |
+
The =Uize.Data.Matches.remove= method is versatile and supports a number of different usages. For more in-depth info, consult the method's [[Uize.Data.Matches.remove][reference documentation]].
|
88 |
+
|
89 |
+
Retaining Matches
|
90 |
+
document...
|
91 |
+
|
92 |
+
EXAMPLE
|
93 |
+
...
|
94 |
+
...
|
95 |
+
|
96 |
+
Counting Matches
|
97 |
+
document...
|
98 |
+
|
99 |
+
EXAMPLE
|
100 |
+
...
|
101 |
+
...
|
102 |
+
|
103 |
+
Getting the Keys or Values of All Matches
|
104 |
+
documnt...
|
105 |
+
|
106 |
+
EXAMPLE
|
107 |
+
...
|
108 |
+
...
|
109 |
+
|
110 |
+
Getting the Key or Value of the First Match
|
111 |
+
document...
|
112 |
+
|
113 |
+
EXAMPLE
|
114 |
+
...
|
115 |
+
...
|
116 |
+
|
117 |
+
Specifying a Source
|
118 |
+
document...
|
119 |
+
|
120 |
+
Specifying an Array Source
|
121 |
+
document...
|
122 |
+
|
123 |
+
Specifying an Object Source
|
124 |
+
document...
|
125 |
+
|
126 |
+
Specifying a Range Source
|
127 |
+
document...
|
128 |
+
|
129 |
+
Specifying a Matcher
|
130 |
+
document...
|
131 |
+
|
132 |
+
Matching Items Using a Matcher Function
|
133 |
+
document...
|
134 |
+
|
135 |
+
Matching Items Using a Matcher Expression String
|
136 |
+
document...
|
137 |
+
|
138 |
+
Matching Items Using a Value Matcher Regular Expression
|
139 |
+
document...
|
140 |
+
|
141 |
+
Matching All Items
|
142 |
+
document...
|
143 |
+
|
144 |
+
Matching No Items
|
145 |
+
document...
|
146 |
+
|
147 |
+
Matching by Value
|
148 |
+
document...
|
149 |
+
|
150 |
+
Matching by Key / Index
|
151 |
+
document...
|
152 |
+
|
153 |
+
Matching by Key and Value
|
154 |
+
document...
|
155 |
+
|
156 |
+
Limiting the Number of Matches
|
157 |
+
document...
|
158 |
+
|
159 |
+
Specifying a Target
|
160 |
+
document...
|
161 |
+
*/
|
162 |
+
|
163 |
+
Uize.module ({
|
164 |
+
name:'Uize.Data.Matches',
|
165 |
+
builder:function () {
|
166 |
+
/*** Variables for Scruncher Optimization ***/
|
167 |
+
var
|
168 |
+
_package = function () {},
|
169 |
+
_true = true,
|
170 |
+
_false = false,
|
171 |
+
_undefined,
|
172 |
+
_Uize = Uize,
|
173 |
+
_resolveMatcher = _Uize.resolveMatcher
|
174 |
+
;
|
175 |
+
|
176 |
+
/*** Public Static Methods ***/
|
177 |
+
_package.forEach = function (_source,_matcher,_iterator,_maxMatches) {
|
178 |
+
if (_maxMatches == _undefined)
|
179 |
+
_maxMatches = Infinity
|
180 |
+
;
|
181 |
+
if (_maxMatches > 0) {
|
182 |
+
_matcher = _resolveMatcher (_matcher);
|
183 |
+
var _totalMatches = 0;
|
184 |
+
_Uize.forEach (
|
185 |
+
_source,
|
186 |
+
function (_value,_key) {
|
187 |
+
if (_totalMatches < _maxMatches && _matcher (_value,_key)) {
|
188 |
+
_totalMatches++;
|
189 |
+
_iterator (_value,_key);
|
190 |
+
}
|
191 |
+
},
|
192 |
+
0,
|
193 |
+
_true
|
194 |
+
);
|
195 |
+
}
|
196 |
+
/*?
|
197 |
+
Static Methods
|
198 |
+
Uize.Data.Matches.forEach
|
199 |
+
Iterates over elements in the specified source array, or properties in the specified source object, or values in the specified source range, that match the specified matching criteria.
|
200 |
+
|
201 |
+
DIFFERENT USAGES
|
202 |
+
|
203 |
+
`Iterate Over Matching Elements of an Array`
|
204 |
+
....................................................................................
|
205 |
+
Uize.Data.Matches.forEach (sourceARRAY,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC);
|
206 |
+
....................................................................................
|
207 |
+
|
208 |
+
`Iterate Over Matching Properties of an Object`
|
209 |
+
..................................................................................
|
210 |
+
Uize.Data.Matches.forEach (sourceOBJ,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC);
|
211 |
+
..................................................................................
|
212 |
+
|
213 |
+
`Iterate Over Matching Values of a Range`
|
214 |
+
..................................................................................
|
215 |
+
Uize.Data.Matches.forEach (sourceINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC);
|
216 |
+
..................................................................................
|
217 |
+
|
218 |
+
`Iterate Over up to a Maximum Number of Matches`
|
219 |
+
..................................................................................
|
220 |
+
Uize.Data.Matches.forEach (
|
221 |
+
sourceARRAYorOBJorINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC,maxMatchesINT
|
222 |
+
);
|
223 |
+
..................................................................................
|
224 |
+
|
225 |
+
`Iterate Over All of the Items of a Source`
|
226 |
+
.........................................................................................
|
227 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,true,iteratorFUNC);
|
228 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,null,iteratorFUNC);
|
229 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,undefined,iteratorFUNC);
|
230 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,function () {return true},iteratorFUNC);
|
231 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,Uize.returnTrue,iteratorFUNC);
|
232 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,'true',iteratorFUNC);
|
233 |
+
.........................................................................................
|
234 |
+
|
235 |
+
`Iterate Over None of the Items of a Source`
|
236 |
+
..........................................................................................
|
237 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,false,iteratorFUNC);
|
238 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,function () {return false},iteratorFUNC);
|
239 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,Uize.returnFalse,iteratorFUNC);
|
240 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,'false',iteratorFUNC);
|
241 |
+
..........................................................................................
|
242 |
+
|
243 |
+
Iterate Over Matching Elements of an Array
|
244 |
+
In a typical use case, this method can be used to iterate over matching elements of an array by specifying an array as the first parameter.
|
245 |
+
|
246 |
+
SYNTAX
|
247 |
+
....................................................................................
|
248 |
+
Uize.Data.Matches.forEach (sourceARRAY,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC);
|
249 |
+
....................................................................................
|
250 |
+
|
251 |
+
Iterate Over Matching Properties of an Object
|
252 |
+
SYNTAX
|
253 |
+
..................................................................................
|
254 |
+
Uize.Data.Matches.forEach (sourceOBJ,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC);
|
255 |
+
..................................................................................
|
256 |
+
|
257 |
+
Iterate Over Matching Values of a Range
|
258 |
+
SYNTAX
|
259 |
+
..................................................................................
|
260 |
+
Uize.Data.Matches.forEach (sourceINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC);
|
261 |
+
..................................................................................
|
262 |
+
|
263 |
+
Iterate Over up to a Maximum Number of Matches
|
264 |
+
SYNTAX
|
265 |
+
..................................................................................
|
266 |
+
Uize.Data.Matches.forEach (
|
267 |
+
sourceARRAYorOBJorINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC,maxMatchesINT
|
268 |
+
);
|
269 |
+
..................................................................................
|
270 |
+
|
271 |
+
Iterate Over All of the Items of a Source
|
272 |
+
SYNTAX
|
273 |
+
.........................................................................................
|
274 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,true,iteratorFUNC);
|
275 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,null,iteratorFUNC);
|
276 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,undefined,iteratorFUNC);
|
277 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,function () {return true},iteratorFUNC);
|
278 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,Uize.returnTrue,iteratorFUNC);
|
279 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,'true',iteratorFUNC);
|
280 |
+
.........................................................................................
|
281 |
+
|
282 |
+
Iterate Over None of the Items of a Source
|
283 |
+
SYNTAX
|
284 |
+
..........................................................................................
|
285 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,false,iteratorFUNC);
|
286 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,function () {return false},iteratorFUNC);
|
287 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,Uize.returnFalse,iteratorFUNC);
|
288 |
+
Uize.Data.Matches.forEach (sourceARRAYorOBJorINT,'false',iteratorFUNC);
|
289 |
+
..........................................................................................
|
290 |
+
|
291 |
+
*/
|
292 |
+
};
|
293 |
+
|
294 |
+
function _filter (_source,_matcher,_maxMatches,_target,_remove) {
|
295 |
+
var
|
296 |
+
_sourceIsNumber = typeof _source == 'number',
|
297 |
+
_sourceActsLikeArray = _sourceIsNumber || _Uize.isArray (_source)
|
298 |
+
;
|
299 |
+
if (_maxMatches == _undefined)
|
300 |
+
_maxMatches = Infinity
|
301 |
+
;
|
302 |
+
if (typeof _target != 'object')
|
303 |
+
_target = _sourceIsNumber
|
304 |
+
? []
|
305 |
+
: _target === _false
|
306 |
+
? _source
|
307 |
+
: _sourceActsLikeArray ? [] : {}
|
308 |
+
;
|
309 |
+
var
|
310 |
+
_targetIsArray = _Uize.isArray (_target),
|
311 |
+
_totalRemoved = 0,
|
312 |
+
_targetLength = 0
|
313 |
+
;
|
314 |
+
if (!_targetIsArray) {
|
315 |
+
if (_target == _source)
|
316 |
+
_source = _Uize.copyInto ({},_target)
|
317 |
+
;
|
318 |
+
_Uize.emptyOut (_target);
|
319 |
+
}
|
320 |
+
if (_remove) {
|
321 |
+
var _resolvedMatcher = _resolveMatcher (_matcher);
|
322 |
+
_matcher = function (_value,_key) {
|
323 |
+
var _mustRemove = _totalRemoved < _maxMatches && _resolvedMatcher (_value,_key);
|
324 |
+
_mustRemove && _totalRemoved++;
|
325 |
+
return !_mustRemove;
|
326 |
+
};
|
327 |
+
}
|
328 |
+
_package.forEach (
|
329 |
+
_source,
|
330 |
+
_matcher,
|
331 |
+
function (_value,_key) {_target [_sourceActsLikeArray ? _targetLength++ : _key] = _value},
|
332 |
+
_remove ? _undefined : _maxMatches
|
333 |
+
);
|
334 |
+
if (_sourceActsLikeArray || _targetIsArray)
|
335 |
+
_target.length = _targetLength
|
336 |
+
;
|
337 |
+
return _target;
|
338 |
+
}
|
339 |
+
|
340 |
+
_package.remove = function (_source,_matcher,_maxMatches,_target) {
|
341 |
+
return _filter (_source,_matcher,_maxMatches,_target,_true);
|
342 |
+
/*?
|
343 |
+
Static Methods
|
344 |
+
Uize.Data.Matches.remove
|
345 |
+
Removes elements in the specified source array, or properties in the specified source object, or values in the specified source range, that match the specified matching criteria.
|
346 |
+
|
347 |
+
DIFFERENT USAGES
|
348 |
+
|
349 |
+
`Remove All Matching Elements of an Array`
|
350 |
+
....................................................................................
|
351 |
+
Uize.Data.Matches.remove (sourceARRAY,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC);
|
352 |
+
....................................................................................
|
353 |
+
|
354 |
+
`Remove All Matching Properties of an Object`
|
355 |
+
..................................................................................
|
356 |
+
Uize.Data.Matches.remove (sourceOBJ,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC);
|
357 |
+
..................................................................................
|
358 |
+
|
359 |
+
`Remove All Matching Values of a Range`
|
360 |
+
..................................................................................
|
361 |
+
Uize.Data.Matches.remove (sourceINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC);
|
362 |
+
..................................................................................
|
363 |
+
|
364 |
+
`Remove up to a Maximum Number of Matches`
|
365 |
+
..................................................................................
|
366 |
+
Uize.Data.Matches.remove (
|
367 |
+
sourceARRAYorOBJorINT,matcherFUNCorSTRorREGEXPorBOOL,iteratorFUNC,maxMatchesINT
|
368 |
+
);
|
369 |
+
.................
|