Interim synchronization with internal repository
This is an intermir commit to share what is going on with the development of the new /delta version.
This commit is contained in:
		| @@ -117,4 +117,4 @@ Once the index.html files have been built (one for each frontend) and a backend | ||||
| This application has not been fully tested, so there may be still problems due to the new build script or to the new repository structure. So, for the moment, **use it at your own risk!** | ||||
|  | ||||
|  | ||||
| [pog]: http://www.phpobjectgenerator.com/ | ||||
| [pog]: http://www.phpobjectgenerator.com/ | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										431
									
								
								frontend/delta/fonts/IcoMoon/Clipperz Icon font.json
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										431
									
								
								frontend/delta/fonts/IcoMoon/Clipperz Icon font.json
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,431 @@ | ||||
| { | ||||
| 	"IcoMoonType": "selection", | ||||
| 	"icons": [ | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M2.259 734.824h279.462v286.917h-279.462v-286.917z", | ||||
| 					"M2.259 2.259h279.462v286.917h-279.462v-286.917z", | ||||
| 					"M2.259 368.519h279.462v286.917h-279.462v-286.917z" | ||||
| 				], | ||||
| 				"width": 284, | ||||
| 				"grid": 0, | ||||
| 				"tags": [ | ||||
| 					"commands" | ||||
| 				] | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"order": 22, | ||||
| 				"id": 0, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58894, | ||||
| 				"name": "commands", | ||||
| 				"ligatures": "commands" | ||||
| 			}, | ||||
| 			"setIdx": 0, | ||||
| 			"iconIdx": 0 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M667.586 345.635v-338.544h-268.055v338.544l-299.967-121.263-90.486 257.986 310.037 104.527-198.134 262.808 224.514 164.237 184.802-279.685 203.382 279.685 221.11-164.237-203.382-262.808 319.397-107.080-90.486-257.986zM1220.574 2319.317z" | ||||
| 				], | ||||
| 				"width": 1080, | ||||
| 				"grid": 0, | ||||
| 				"tags": [ | ||||
| 					"logo" | ||||
| 				] | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"order": 4, | ||||
| 				"id": 0, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58884, | ||||
| 				"name": "logo", | ||||
| 				"ligatures": "clipperz" | ||||
| 			}, | ||||
| 			"setIdx": 1, | ||||
| 			"iconIdx": 0 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M96.188 0h288.562c52.906 0 126.796 30.606 164.204 68.014l446.99 446.99c37.408 37.408 37.408 98.624 0 136.032l-344.91 344.906c-37.408 37.41-98.622 37.41-136.030 0l-446.99-446.988c-37.408-37.41-68.014-111.302-68.014-164.204v-288.562c0-52.904 43.286-96.188 96.188-96.188zM224 320c53.020 0 96-42.98 96-96s-42.98-96-96-96-96 42.98-96 96 42.98 96 96 96z" | ||||
| 				], | ||||
| 				"tags": [ | ||||
| 					"tag", | ||||
| 					"price" | ||||
| 				], | ||||
| 				"grid": 16 | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"id": 48, | ||||
| 				"order": 6, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58885, | ||||
| 				"name": "tag", | ||||
| 				"ligatures": "tag" | ||||
| 			}, | ||||
| 			"setIdx": 2, | ||||
| 			"iconIdx": 49 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M96 64h224c52.8 0 126.546 30.546 163.882 67.882l376.236 376.236c37.334 37.334 37.334 98.428 0 135.764l-280.236 280.234c-37.334 37.336-98.428 37.336-135.764 0l-376.234-376.234c-37.338-37.336-67.884-111.082-67.884-163.882v-224c0-52.8 43.2-96 96-96zM224 384c53.020 0 96-42.98 96-96s-42.98-96-96-96-96 42.98-96 96 42.98 96 96 96zM1001.374 598.626l-342.378 342.378c36.264 19.16 82.462 13.538 112.886-16.888l280.236-280.234c37.334-37.336 37.334-98.43 0-135.764l-376.236-376.236c-37.336-37.336-111.082-67.882-163.882-67.882l489.374 489.372c12.444 12.446 12.444 32.808 0 45.254z" | ||||
| 				], | ||||
| 				"width": 1088, | ||||
| 				"tags": [ | ||||
| 					"tags", | ||||
| 					"prices" | ||||
| 				], | ||||
| 				"grid": 16 | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"id": 49, | ||||
| 				"order": 1, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58880, | ||||
| 				"name": "tags", | ||||
| 				"ligatures": "tags" | ||||
| 			}, | ||||
| 			"setIdx": 2, | ||||
| 			"iconIdx": 50 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M928 128h-832c-52.8 0-96 43.2-96 96v640c0 52.8 43.2 96 96 96h832c52.8 0 96-43.2 96-96v-640c0-52.8-43.2-96-96-96zM398.74 550.372l-270.74 210.892v-501.642l270.74 290.75zM176.38 256h671.24l-335.62 252-335.62-252zM409.288 561.698l102.712 110.302 102.71-110.302 210.554 270.302h-626.528l210.552-270.302zM625.26 550.372l270.74-290.75v501.642l-270.74-210.892z" | ||||
| 				], | ||||
| 				"tags": [ | ||||
| 					"envelope", | ||||
| 					"mail", | ||||
| 					"email", | ||||
| 					"contact", | ||||
| 					"letter" | ||||
| 				], | ||||
| 				"grid": 16 | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"id": 64, | ||||
| 				"order": 8, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58888, | ||||
| 				"name": "envelope", | ||||
| 				"ligatures": "email" | ||||
| 			}, | ||||
| 			"setIdx": 2, | ||||
| 			"iconIdx": 65 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M658.744 749.256l-210.744-210.746v-282.51h128v229.49l173.256 173.254zM512 0c-282.77 0-512 229.23-512 512s229.23 512 512 512 512-229.23 512-512-229.23-512-512-512zM512 896c-212.078 0-384-171.922-384-384s171.922-384 384-384c212.078 0 384 171.922 384 384 0 212.078-171.922 384-384 384z" | ||||
| 				], | ||||
| 				"tags": [ | ||||
| 					"clock", | ||||
| 					"time", | ||||
| 					"schedule" | ||||
| 				], | ||||
| 				"grid": 16 | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"id": 72, | ||||
| 				"order": 7, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58887, | ||||
| 				"name": "clock", | ||||
| 				"ligatures": "recent" | ||||
| 			}, | ||||
| 			"setIdx": 2, | ||||
| 			"iconIdx": 73 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M384 128c0-70.692 57.308-128 128-128 70.692 0 128 57.308 128 128 0 70.692-57.308 128-128 128-70.692 0-128-57.308-128-128zM655.53 240.47c0-70.692 57.308-128 128-128s128 57.308 128 128c0 70.692-57.308 128-128 128-70.692 0-128-57.308-128-128zM832 512c0-35.346 28.654-64 64-64s64 28.654 64 64c0 35.346-28.654 64-64 64-35.346 0-64-28.654-64-64zM719.53 783.53c0-35.346 28.654-64 64-64s64 28.654 64 64c0 35.346-28.654 64-64 64-35.346 0-64-28.654-64-64zM448.002 896c-0-0-0-0-0-0 0-35.346 28.654-64 64-64 35.346 0 64 28.654 64 64 0 0 0 0 0 0 0 35.346-28.654 64-64 64-35.346 0-64-28.654-64-64zM176.472 783.53c-0-0-0-0-0-0 0-35.346 28.654-64 64-64 35.346 0 64 28.654 64 64 0 0 0 0 0 0 0 35.346-28.654 64-64 64-35.346 0-64-28.654-64-64zM144.472 240.47c-0-0-0-0-0-0 0-53.019 42.981-96 96-96 53.019 0 96 42.981 96 96 0 0 0 0 0 0 0 53.019-42.981 96-96 96-53.019 0-96-42.981-96-96zM56 512c0-39.765 32.235-72 72-72s72 32.235 72 72c0 39.765-32.235 72-72 72-39.765 0-72-32.235-72-72z" | ||||
| 				], | ||||
| 				"tags": [ | ||||
| 					"spinner", | ||||
| 					"loading", | ||||
| 					"busy", | ||||
| 					"wait", | ||||
| 					"wheel" | ||||
| 				], | ||||
| 				"grid": 16 | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"id": 120, | ||||
| 				"order": 11, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58891, | ||||
| 				"name": "spinner", | ||||
| 				"ligatures": "loading" | ||||
| 			}, | ||||
| 			"setIdx": 2, | ||||
| 			"iconIdx": 121 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M992.262 871.396l-242.552-206.294c-25.074-22.566-51.89-32.926-73.552-31.926 57.256-67.068 91.842-154.078 91.842-249.176 0-212.078-171.922-384-384-384-212.076 0-384 171.922-384 384 0 212.078 171.922 384 384 384 95.098 0 182.108-34.586 249.176-91.844-1 21.662 9.36 48.478 31.926 73.552l206.294 242.552c35.322 39.246 93.022 42.554 128.22 7.356s31.892-92.898-7.354-128.22zM384 640c-141.384 0-256-114.616-256-256s114.616-256 256-256 256 114.616 256 256-114.614 256-256 256z" | ||||
| 				], | ||||
| 				"tags": [ | ||||
| 					"search", | ||||
| 					"magnifier", | ||||
| 					"lookup", | ||||
| 					"find" | ||||
| 				], | ||||
| 				"grid": 16 | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"id": 127, | ||||
| 				"order": 5, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58886, | ||||
| 				"name": "search", | ||||
| 				"ligatures": "search" | ||||
| 			}, | ||||
| 			"setIdx": 2, | ||||
| 			"iconIdx": 128 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M832 448h-64v-192c0-141.384-114.616-256-256-256s-256 114.616-256 256v192h-64c-35.2 0-64 28.8-64 64v448c0 35.2 28.8 64 64 64h640c35.2 0 64-28.8 64-64v-448c0-35.2-28.8-64-64-64zM512 832c-35.346 0-64-28.654-64-64s28.654-64 64-64 64 28.654 64 64-28.654 64-64 64zM640 448h-256v-192c0-70.58 57.42-128 128-128s128 57.42 128 128v192z" | ||||
| 				], | ||||
| 				"tags": [ | ||||
| 					"lock", | ||||
| 					"secure", | ||||
| 					"private", | ||||
| 					"encrypted" | ||||
| 				], | ||||
| 				"grid": 16 | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"id": 136, | ||||
| 				"order": 9, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58889, | ||||
| 				"name": "lock", | ||||
| 				"ligatures": "password" | ||||
| 			}, | ||||
| 			"setIdx": 2, | ||||
| 			"iconIdx": 137 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M64 192h896v192h-896zM64 448h896v192h-896zM64 704h896v192h-896z" | ||||
| 				], | ||||
| 				"tags": [ | ||||
| 					"menu", | ||||
| 					"list", | ||||
| 					"items", | ||||
| 					"lines", | ||||
| 					"options" | ||||
| 				], | ||||
| 				"grid": 16 | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"id": 184, | ||||
| 				"order": 14, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58881, | ||||
| 				"name": "menu2", | ||||
| 				"ligatures": "menu" | ||||
| 			}, | ||||
| 			"setIdx": 2, | ||||
| 			"iconIdx": 185 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M1014.662 822.66c-0.004-0.004-0.008-0.008-0.012-0.010l-310.644-310.65 310.644-310.65c0.004-0.004 0.008-0.006 0.012-0.010 3.344-3.346 5.762-7.254 7.312-11.416 4.246-11.376 1.824-24.682-7.324-33.83l-146.746-146.746c-9.148-9.146-22.45-11.566-33.828-7.32-4.16 1.55-8.070 3.968-11.418 7.31 0 0.004-0.004 0.006-0.008 0.010l-310.648 310.652-310.648-310.65c-0.004-0.004-0.006-0.006-0.010-0.010-3.346-3.342-7.254-5.76-11.414-7.31-11.38-4.248-24.682-1.826-33.83 7.32l-146.748 146.748c-9.148 9.148-11.568 22.452-7.322 33.828 1.552 4.16 3.97 8.072 7.312 11.416 0.004 0.002 0.006 0.006 0.010 0.010l310.65 310.648-310.65 310.652c-0.002 0.004-0.006 0.006-0.008 0.010-3.342 3.346-5.76 7.254-7.314 11.414-4.248 11.376-1.826 24.682 7.322 33.83l146.748 146.746c9.15 9.148 22.452 11.568 33.83 7.322 4.16-1.552 8.070-3.97 11.416-7.312 0.002-0.004 0.006-0.006 0.010-0.010l310.648-310.65 310.648 310.65c0.004 0.002 0.008 0.006 0.012 0.008 3.348 3.344 7.254 5.762 11.414 7.314 11.378 4.246 24.684 1.826 33.828-7.322l146.746-146.748c9.148-9.148 11.57-22.454 7.324-33.83-1.552-4.16-3.97-8.068-7.314-11.414z" | ||||
| 				], | ||||
| 				"tags": [ | ||||
| 					"close", | ||||
| 					"cancel", | ||||
| 					"quit", | ||||
| 					"remove", | ||||
| 					"cross" | ||||
| 				], | ||||
| 				"grid": 16 | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"id": 253, | ||||
| 				"order": 3, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58882, | ||||
| 				"name": "close", | ||||
| 				"ligatures": "failure, failed" | ||||
| 			}, | ||||
| 			"setIdx": 2, | ||||
| 			"iconIdx": 254 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M864 128l-480 480-224-224-160 160 384 384 640-640z" | ||||
| 				], | ||||
| 				"tags": [ | ||||
| 					"checkmark", | ||||
| 					"tick", | ||||
| 					"correct", | ||||
| 					"accept", | ||||
| 					"ok" | ||||
| 				], | ||||
| 				"grid": 16 | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"id": 254, | ||||
| 				"order": 2, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58883, | ||||
| 				"name": "checkmark", | ||||
| 				"ligatures": "done, ok" | ||||
| 			}, | ||||
| 			"setIdx": 2, | ||||
| 			"iconIdx": 255 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M819.2 102.4h-410.624c-56.32 0-101.376 45.056-101.376 101.376v410.624c0 56.32 46.080 102.4 102.4 102.4h409.6c56.32 0 102.4-46.080 102.4-102.4v-409.6c0-56.32-46.080-102.4-102.4-102.4zM819.2 614.4h-409.6v-409.6h409.6v409.6zM204.8 512h-102.4v307.2c0 56.32 46.080 102.4 102.4 102.4h307.2v-102.4h-307.2v-307.2z" | ||||
| 				], | ||||
| 				"tags": [ | ||||
| 					"popup", | ||||
| 					"popout", | ||||
| 					"new window" | ||||
| 				], | ||||
| 				"grid": 20 | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"id": 35, | ||||
| 				"order": 10, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58890, | ||||
| 				"name": "popup", | ||||
| 				"ligatures": "url" | ||||
| 			}, | ||||
| 			"setIdx": 5, | ||||
| 			"iconIdx": 35 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M512 81.92c-237.568 0-430.080 192.614-430.080 430.080 0 237.568 192.563 430.080 430.080 430.080 237.517 0 430.080-192.563 430.080-430.080 0-237.517-192.563-430.080-430.080-430.080zM564.326 564.326v206.182h-104.653v-206.182h-206.234v-104.653h206.182v-206.234h104.704v206.182h206.182v104.704h-206.182z" | ||||
| 				], | ||||
| 				"tags": [ | ||||
| 					"plus", | ||||
| 					"add", | ||||
| 					"sum" | ||||
| 				], | ||||
| 				"grid": 20 | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"id": 125, | ||||
| 				"order": 16, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58895, | ||||
| 				"name": "plus", | ||||
| 				"ligatures": "add card" | ||||
| 			}, | ||||
| 			"setIdx": 5, | ||||
| 			"iconIdx": 125 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M585.574 231.219c-21.402 20.89-230.502 240.435-230.502 240.435-11.418 11.162-17.101 25.754-17.101 40.346s5.683 29.184 17.101 40.346c0 0 209.101 219.546 230.502 240.384 21.402 20.89 59.904 22.323 82.739 0 22.784-22.272 24.576-53.35-0.051-80.64l-191.846-200.090 191.846-200.090c24.627-27.341 22.835-58.419 0.051-80.691-22.886-22.272-61.389-20.89-82.739-0z" | ||||
| 				], | ||||
| 				"tags": [ | ||||
| 					"arrow-left", | ||||
| 					"left", | ||||
| 					"previous" | ||||
| 				], | ||||
| 				"grid": 20 | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"id": 205, | ||||
| 				"order": 12, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58892, | ||||
| 				"name": "arrow-left", | ||||
| 				"ligatures": "back" | ||||
| 			}, | ||||
| 			"setIdx": 5, | ||||
| 			"iconIdx": 205 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"icon": { | ||||
| 				"paths": [ | ||||
| 					"M438.426 231.219c21.402 20.89 230.502 240.435 230.502 240.435 11.469 11.162 17.152 25.754 17.152 40.346s-5.683 29.184-17.152 40.346c0 0-209.101 219.546-230.502 240.384-21.402 20.89-59.853 22.323-82.739 0-22.835-22.272-24.627-53.35 0-80.64l191.898-200.090-191.846-200.090c-24.627-27.341-22.835-58.419 0-80.691 22.835-22.272 61.338-20.89 82.688-0z" | ||||
| 				], | ||||
| 				"tags": [ | ||||
| 					"arrow-right", | ||||
| 					"right", | ||||
| 					"next" | ||||
| 				], | ||||
| 				"grid": 20 | ||||
| 			}, | ||||
| 			"properties": { | ||||
| 				"id": 208, | ||||
| 				"order": 13, | ||||
| 				"prevSize": 32, | ||||
| 				"code": 58893, | ||||
| 				"name": "arrow-right", | ||||
| 				"ligatures": "show detail" | ||||
| 			}, | ||||
| 			"setIdx": 5, | ||||
| 			"iconIdx": 208 | ||||
| 		} | ||||
| 	], | ||||
| 	"height": 1024, | ||||
| 	"metadata": { | ||||
| 		"name": "clipperz-icons" | ||||
| 	}, | ||||
| 	"preferences": { | ||||
| 		"fontPref": { | ||||
| 			"prefix": "icon-", | ||||
| 			"metadata": { | ||||
| 				"fontFamily": "clipperz-icons", | ||||
| 				"majorVersion": 1, | ||||
| 				"minorVersion": 0 | ||||
| 			}, | ||||
| 			"showGlyphs": true, | ||||
| 			"metrics": { | ||||
| 				"emSize": 512, | ||||
| 				"baseline": 6.25, | ||||
| 				"whitespace": 50 | ||||
| 			}, | ||||
| 			"resetPoint": 58880, | ||||
| 			"showQuickUse": true, | ||||
| 			"quickUsageToken": false, | ||||
| 			"showMetrics": true, | ||||
| 			"showMetadata": false, | ||||
| 			"autoHost": false, | ||||
| 			"embed": true, | ||||
| 			"showVersion": true | ||||
| 		}, | ||||
| 		"imagePref": { | ||||
| 			"color": 0, | ||||
| 			"height": 32, | ||||
| 			"columns": 16, | ||||
| 			"margin": 16, | ||||
| 			"png": false, | ||||
| 			"sprites": true | ||||
| 		}, | ||||
| 		"historySize": 100, | ||||
| 		"showCodes": false, | ||||
| 		"gridSize": 16, | ||||
| 		"showLiga": true, | ||||
| 		"showGrid": true, | ||||
| 		"showGlyphs": true, | ||||
| 		"showQuickUse": true, | ||||
| 		"search": "", | ||||
| 		"quickUsageToken": { | ||||
| 			"UntitledProject1": "YzBlN2I0ZDQ5YTQyY2NjYjgwNGRkYzNhYzU4NDZhMDcjMiMxNDAzMTA2OTk5IyMj" | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -21,11 +21,8 @@ refer to http://www.clipperz.com. | ||||
|  | ||||
| */ | ||||
|  | ||||
| //Clipperz.Async = MochiKit.Async; | ||||
|  | ||||
|  | ||||
| if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } | ||||
| if (typeof(Clipperz.Async) == 'undefined') { Clipperz.Async = {}; } | ||||
| "use strict"; | ||||
| Clipperz.Base.module('Clipperz.Async'); | ||||
|  | ||||
| Clipperz.Async.VERSION = "0.1"; | ||||
| Clipperz.Async.NAME = "Clipperz.Async"; | ||||
| @@ -276,6 +273,12 @@ Clipperz.Base.extend(Clipperz.Async.Deferred, MochiKit.Async.Deferred, { | ||||
| 		}, this)); | ||||
| 	}, | ||||
|  | ||||
| 	'values': function () { | ||||
| 		this.addCallback(MochiKit.Base.bind(function () { | ||||
| 			return this.vars(); | ||||
| 		}, this)); | ||||
| 	}, | ||||
|  | ||||
| 	//============================================================================= | ||||
|  | ||||
| 	'wait': function (someSeconds) { | ||||
| @@ -702,6 +705,6 @@ MochiKit.Base.update(Clipperz.Async, { | ||||
|  | ||||
| //############################################################################# | ||||
|  | ||||
| CLIPPERZ_DEFERRED_LOGGING_ENABLED = true; | ||||
| CLIPPERZ_DEFERRED_TRACING_ENABLED = false; | ||||
| CLIPPERZ_DEFERRED_CALL_LOGGING_ENABLED = false; | ||||
| var CLIPPERZ_DEFERRED_LOGGING_ENABLED = true; | ||||
| var CLIPPERZ_DEFERRED_TRACING_ENABLED = false; | ||||
| var CLIPPERZ_DEFERRED_CALL_LOGGING_ENABLED = false; | ||||
|   | ||||
| @@ -21,6 +21,8 @@ refer to http://www.clipperz.com. | ||||
|  | ||||
| */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } | ||||
| if (typeof(Clipperz.Base) == 'undefined') { Clipperz.Base = {}; } | ||||
|  | ||||
| @@ -189,6 +191,10 @@ MochiKit.Base.update(Clipperz.Base, { | ||||
| 		return Clipperz.Base.removeObjectFromArray(anObject, anArray); | ||||
| 	}, | ||||
|  | ||||
| 	'arrayWithUniqueValues': function (anArray) { | ||||
| 		return anArray.filter(function (value, index, self) { return self.indexOf(value) === index; }); | ||||
| 	}, | ||||
| 	 | ||||
| 	//------------------------------------------------------------------------- | ||||
|  | ||||
| 	'splitStringAtFixedTokenSize': function(aString, aTokenSize) { | ||||
|   | ||||
| @@ -21,6 +21,7 @@ refer to http://www.clipperz.com. | ||||
|  | ||||
| */ | ||||
|  | ||||
| "use strict"; | ||||
| if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } | ||||
|  | ||||
| //============================================================================= | ||||
|   | ||||
| @@ -21,7 +21,8 @@ refer to http://www.clipperz.com. | ||||
|  | ||||
| */ | ||||
|  | ||||
| if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } | ||||
| "use strict"; | ||||
| Clipperz.Base.module('Clipperz'); | ||||
|  | ||||
|  | ||||
| Clipperz.CSVProcessor = function(args) { | ||||
| @@ -32,9 +33,9 @@ Clipperz.CSVProcessor = function(args) { | ||||
| //	this._string		= undefined; | ||||
| //	this._fields		= undefined; | ||||
|  | ||||
| 	this._quoteChar		= args['quoteChar'] 	||	"\042"; | ||||
| 	this._quoteChar		= args['quoteChar'] 	||	"\0x42"; | ||||
| 	this._eol			= args['eol']			||	""; | ||||
| 	this._escapeChar	= args['escapeChar']	||	"\042"; | ||||
| 	this._escapeChar	= args['escapeChar']	||	"\0x42"; | ||||
| 	this._separatorChar	= args['separatorChar']	||	","; | ||||
| 	this._binary		= args['binary']		||	false; | ||||
| 	this._alwaysQuote	= args['alwaysQuote']	||	false; | ||||
|   | ||||
| @@ -293,7 +293,7 @@ Clipperz.Crypto.PRNG.MouseRandomnessSource.prototype = MochiKit.Base.update(new | ||||
| Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource = function(args) { | ||||
| 	args = args || {}; | ||||
|  | ||||
| 	this._intervalTime = args.intervalTime || 1000; | ||||
| 	this._intervalTime = args.intervalTime || 500; | ||||
| 	this._browserCrypto = args.browserCrypto; | ||||
| 	 | ||||
| 	Clipperz.Crypto.PRNG.RandomnessSource.call(this, args); | ||||
| @@ -318,7 +318,7 @@ Clipperz.Crypto.PRNG.CryptoRandomRandomnessSource.prototype = MochiKit.Base.upda | ||||
| 		var	bytesToCollect; | ||||
|  | ||||
| 		if (this.boostMode() == true) { | ||||
| 			bytesToCollect = 64; | ||||
| 			bytesToCollect = 256; | ||||
| 		} else { | ||||
| 			bytesToCollect = 8; | ||||
| 		} | ||||
|   | ||||
| @@ -56,7 +56,7 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, { | ||||
| 		return Clipperz.Crypto.SRP._n; | ||||
| 	}, | ||||
|  | ||||
| 	//------------------------------------------------------------------------- | ||||
| 	//......................................................................... | ||||
|  | ||||
| 	'g': function() { | ||||
| 		if (Clipperz.Crypto.SRP._g == null) { | ||||
| @@ -66,6 +66,8 @@ MochiKit.Base.update(Clipperz.Crypto.SRP, { | ||||
| 		return Clipperz.Crypto.SRP._g; | ||||
| 	}, | ||||
|  | ||||
| 	//......................................................................... | ||||
|  | ||||
| 	'k': function() { | ||||
| 		if (Clipperz.Crypto.SRP._k == null) { | ||||
| //			Clipperz.Crypto.SRP._k = new Clipperz.Crypto.BigInt(this.stringHash(this.n().asString() + this.g().asString()), 16); | ||||
|   | ||||
| @@ -21,8 +21,8 @@ refer to http://www.clipperz.com. | ||||
|  | ||||
| */ | ||||
|  | ||||
| if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } | ||||
| if (typeof(Clipperz.DOM) == 'undefined') { Clipperz.DOM = {}; } | ||||
| "use strict"; | ||||
| Clipperz.Base.module('Clipperz.DOM'); | ||||
|  | ||||
| Clipperz.DOM.VERSION = "0.1"; | ||||
| Clipperz.DOM.NAME = "Clipperz.DOM"; | ||||
|   | ||||
| @@ -21,8 +21,8 @@ refer to http://www.clipperz.com. | ||||
|  | ||||
| */ | ||||
|  | ||||
| if (typeof(Clipperz) == 'undefined') { Clipperz = {}; } | ||||
| if (typeof(Clipperz.Date) == 'undefined') { Clipperz.Date = {}; } | ||||
| "use strict"; | ||||
| Clipperz.Base.module('Clipperz.Date'); | ||||
|  | ||||
| Clipperz.Date.VERSION = "0.1"; | ||||
| Clipperz.Date.NAME = "Clipperz.Date"; | ||||
|   | ||||
| @@ -30,6 +30,7 @@ Clipperz.PM.DataModel.Record = function(args) { | ||||
| 	Clipperz.PM.DataModel.Record.superclass.constructor.apply(this, arguments); | ||||
|  | ||||
| 	this._updateDate				= (args.updateDate ? Clipperz.PM.Date.parse(args.updateDate) : Clipperz.Base.exception.raise('MandatoryParameter')); | ||||
| 	this._accessDate				= (args.accessDate ? Clipperz.PM.Date.parse(args.accessDate) : Clipperz.Base.exception.raise('MandatoryParameter')); | ||||
|  | ||||
| 	this._retrieveIndexDataFunction	= args.retrieveIndexDataFunction	|| Clipperz.Base.exception.raise('MandatoryParameter'); | ||||
| 	this._updateIndexDataFunction	= args.updateIndexDataFunction		|| Clipperz.Base.exception.raise('MandatoryParameter'); | ||||
| @@ -40,6 +41,8 @@ Clipperz.PM.DataModel.Record = function(args) { | ||||
|  | ||||
| 	this._createNewDirectLoginFunction			= args.createNewDirectLoginFunction			|| null; | ||||
| 	 | ||||
| 	this._tags = []; | ||||
|  | ||||
| 	this._directLogins = {}; | ||||
|  | ||||
| 	this._versions = {}; | ||||
| @@ -128,22 +131,109 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
| 	//============================================================================ | ||||
| /* | ||||
| 	'key': function () { | ||||
| 		return this.getIndexDataForKey('key'); | ||||
| 	}, | ||||
| */ | ||||
| 	//========================================================================= | ||||
| 	//============================================================================ | ||||
|  | ||||
| 	'fullLabel': function () { | ||||
| 		return this.getIndexDataForKey('label'); | ||||
| 	}, | ||||
|  | ||||
| 	'updateFullLabelWithTags': function (someTags) { | ||||
| 		return Clipperz.Async.callbacks("Record.updateFullLabelWithTags", [ | ||||
| 			MochiKit.Base.method(this, 'label'), | ||||
| 			function (aLabel) { | ||||
| 				return aLabel + ' ' + MochiKit.Base.map(function (aTag) { return Clipperz.PM.DataModel.Record.tagChar + aTag; }, MochiKit.Base.keys(someTags)).join(' '); | ||||
| 			}, | ||||
| 			MochiKit.Base.method(this, 'setIndexDataForKey', 'label') | ||||
| 		], {trace:false}); | ||||
| 	}, | ||||
|  | ||||
| 	//............................................................................ | ||||
|  | ||||
| 	'tagChar': function () { | ||||
| 		return Clipperz.PM.DataModel.Record.tagChar; | ||||
| 	}, | ||||
|  | ||||
| 	'tagRegExp': function () { | ||||
| 		return new RegExp('\\' + this.tagChar() + '(\\w+)', 'g'); | ||||
| 	}, | ||||
|  | ||||
| 	'trimSpacesRegExp': function () { | ||||
| 		return new RegExp('^\\s+|\\s+$', 'g'); | ||||
| 	}, | ||||
|  | ||||
| 	//............................................................................ | ||||
|  | ||||
| 	'filterOutTags': function (aValue) { | ||||
| 		var value; | ||||
|  | ||||
| 		value = aValue; | ||||
| 		value = value.replace(this.tagRegExp(), ''); | ||||
| 		value = value.replace(this.trimSpacesRegExp(), ''); | ||||
|  | ||||
| 		return value; | ||||
| 	}, | ||||
|  | ||||
| 	'label': function () { | ||||
| 		return this.getIndexDataForKey('label'); | ||||
| 		return Clipperz.Async.callbacks("Record.label", [ | ||||
| 			MochiKit.Base.method(this, 'fullLabel'), | ||||
| 			MochiKit.Base.method(this, 'filterOutTags') | ||||
| 		], {trace:false}); | ||||
| 	}, | ||||
|  | ||||
| 	'setLabel': function (aValue) { | ||||
| 		return this.setIndexDataForKey('label', aValue);	//	[???] | ||||
| 	}, | ||||
|  | ||||
| 	//......................................................................... | ||||
|  | ||||
| 	'setLabel': function (aValue) { | ||||
| 		return this.setIndexDataForKey('label', aValue); | ||||
| 	'extractTags': function (aLabel) { | ||||
| 		var	tagRegEx; | ||||
| 		var	result; | ||||
| 		var	match; | ||||
| 		 | ||||
| 		result = {}; | ||||
| 		tagRegEx = this.tagRegExp(); | ||||
| 		match = tagRegEx.exec(aLabel); | ||||
| 		while (match != null) { | ||||
| 			result[match[1]] = true; | ||||
| 		    match = tagRegEx.exec(aLabel); | ||||
| 		}		 | ||||
| 		 | ||||
| 		return result; | ||||
| 	}, | ||||
| 	 | ||||
| 	'tags': function () { | ||||
| 		return Clipperz.Async.callbacks("Record.label", [ | ||||
| 			MochiKit.Base.method(this, 'fullLabel'), | ||||
| 			MochiKit.Base.method(this, 'extractTags'), | ||||
| 			MochiKit.Base.keys | ||||
| 		], {trace:false}); | ||||
| 	}, | ||||
|  | ||||
| 	'addTag': function (aNewTag) { | ||||
| //console.log("ADD TAG", aNewTag); | ||||
| 		return Clipperz.Async.callbacks("Record.addTag", [ | ||||
| 			MochiKit.Base.method(this, 'fullLabel'), | ||||
| 			MochiKit.Base.method(this, 'extractTags'), | ||||
| 			function (someTags) { someTags[aNewTag] = true; console.log("UPDATED TAGS", someTags); return someTags; }, | ||||
| 			MochiKit.Base.method(this, 'updateFullLabelWithTags') | ||||
| 		], {trace:false}); | ||||
| 	}, | ||||
|  | ||||
| 	'removeTag': function (aTag) { | ||||
| //console.log("ADD TAG", aNewTag); | ||||
| 		return Clipperz.Async.callbacks("Record.removeTag", [ | ||||
| 			MochiKit.Base.method(this, 'fullLabel'), | ||||
| 			MochiKit.Base.method(this, 'extractTags'), | ||||
| 			function (someTags) { delete someTags[aTag]; return someTags; }, | ||||
| 			MochiKit.Base.method(this, 'updateFullLabelWithTags') | ||||
| 		], {trace:false}); | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
| @@ -183,6 +273,10 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt | ||||
| 		return MochiKit.Async.succeed(this._updateDate); | ||||
| 	}, | ||||
|  | ||||
| 	'accessDate': function () { | ||||
| 		return MochiKit.Async.succeed(this._accessDate); | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	'favicon': function () { | ||||
| @@ -208,7 +302,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt | ||||
| 		deferredResult = new Clipperz.Async.Deferred("Record.searchableContent", {trace:false}); | ||||
| 		 | ||||
| 		deferredResult.collectResults({ | ||||
| 			'recordLabel': MochiKit.Base.method(this, 'label'), | ||||
| 			'recordLabel': MochiKit.Base.method(this, 'fullLabel'), | ||||
| 			'directLoginLabels': [ | ||||
| 				MochiKit.Base.method(this, 'directLoginReferences'), | ||||
| 				MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.itemgetter('label')) | ||||
| @@ -889,3 +983,20 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.Record, Clipperz.PM.DataModel.Encrypt | ||||
| }); | ||||
|  | ||||
|  | ||||
| Clipperz.PM.DataModel.Record.defaultCardInfo = { | ||||
| 	'_rowObject':			MochiKit.Async.succeed, | ||||
| 	'_reference':			MochiKit.Base.methodcaller('reference'), | ||||
| 	'_searchableContent':	MochiKit.Base.methodcaller('searchableContent'), | ||||
| 	'_accessDate':			MochiKit.Base.methodcaller('accessDate'), | ||||
| 	'label':				MochiKit.Base.methodcaller('label'), | ||||
| 	'favicon':				MochiKit.Base.methodcaller('favicon') | ||||
| }; | ||||
| Clipperz.PM.DataModel.Record.defaultSearchField = '_searchableContent'; | ||||
|  | ||||
| Clipperz.PM.DataModel.Record.tagChar = '#'; | ||||
| Clipperz.PM.DataModel.Record.regExpForTag = function (aTag) { | ||||
| 	return new RegExp('\\' + Clipperz.PM.DataModel.Record.tagChar + aTag, 'g'); | ||||
| }; | ||||
| Clipperz.PM.DataModel.Record.regExpForSearch = function (aSearch) { | ||||
| 	return new RegExp(aSearch.replace(/[^A-Za-z0-9]/g, '\\$&'), 'i'); | ||||
| }; | ||||
|   | ||||
| @@ -25,26 +25,26 @@ try { if (typeof(Clipperz.PM.DataModel.User) == 'undefined') { throw ""; }} catc | ||||
| 	throw "Clipperz.PM.DataModel.User.Subscription depends on Clipperz.PM.DataModel.User!"; | ||||
| }   | ||||
| 
 | ||||
| Clipperz.PM.DataModel.User.Subscription = function(args) { | ||||
| Clipperz.PM.DataModel.User.AccountInfo = function(args) { | ||||
| 	this._attributes = args; | ||||
| 	return this; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| Clipperz.Base.extend(Clipperz.PM.DataModel.User.Subscription, Object, { | ||||
| Clipperz.Base.extend(Clipperz.PM.DataModel.User.AccountInfo, Object, { | ||||
| 
 | ||||
| 	'features': function () { | ||||
| 		return this._attributes['features']; | ||||
| 	}, | ||||
| 
 | ||||
| 	'type': function () { | ||||
| 		return this._attributes['type']; | ||||
| 	'featureSet': function () { | ||||
| 		return this._attributes['featureSet']; | ||||
| 	}, | ||||
| 
 | ||||
| 	'validity': function () { | ||||
| 		return { | ||||
| 			'from':	this._attributes['fromDate'], | ||||
| 			'to':	this._attributes['toDate'] | ||||
| //			'from':	this._attributes['fromDate'],
 | ||||
| 			'to':	this._attributes['expirationDate'] | ||||
| 		}; | ||||
| 	}, | ||||
| 
 | ||||
| @@ -133,6 +133,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.Legacy, Clipperz.PM.DataM | ||||
| 							'retrieveIndexDataFunction':	MochiKit.Base.method(this, 'getRecordIndexData'), | ||||
| 							'updateIndexDataFunction':		MochiKit.Base.method(this, 'updateRecordIndexData'), | ||||
| 							'updateDate':					someObjectData['recordsStats'][reference]['updateDate'], | ||||
| 							'accessDate':					someObjectData['recordsStats'][reference]['accessDate'], | ||||
|  | ||||
| 							'retrieveDirectLoginIndexDataFunction':	MochiKit.Base.method(this, 'getDirectLoginIndexData'), | ||||
| 							'setDirectLoginIndexDataFunction':		MochiKit.Base.method(this, 'setDirectLoginIndexData'), | ||||
|   | ||||
| @@ -29,7 +29,7 @@ if (typeof(Clipperz.PM.DataModel.User.Header) == 'undefined') { Clipperz.PM.Data | ||||
|  | ||||
| Clipperz.PM.DataModel.User.Header.RecordIndex = function(args) { | ||||
| 	Clipperz.PM.DataModel.User.Header.RecordIndex.superclass.constructor.apply(this, arguments); | ||||
|  | ||||
| //console.log("RECORD INDEX ARGS", args); | ||||
| 	this._recordsData = new Clipperz.PM.DataModel.EncryptedRemoteObject({ | ||||
| 		'name':	'recordsData', | ||||
| 		'retrieveKeyFunction': args.retrieveKeyFunction, | ||||
| @@ -37,9 +37,7 @@ Clipperz.PM.DataModel.User.Header.RecordIndex = function(args) { | ||||
| 			'data': args.recordsData['data'], | ||||
| 			'version': args.encryptedDataVersion, | ||||
| 			'recordsStats': args.recordsStats | ||||
| 		}//, | ||||
| //		'encryptedDataKeypath':			'data', | ||||
| //		'encryptedVersionKeypath':		'version' | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	this._directLoginsData = new Clipperz.PM.DataModel.EncryptedRemoteObject({ | ||||
| @@ -48,11 +46,10 @@ Clipperz.PM.DataModel.User.Header.RecordIndex = function(args) { | ||||
| 		'remoteData': { | ||||
| 			'data': args.directLoginsData['data'], | ||||
| 			'version': args.encryptedDataVersion | ||||
| 		}//, | ||||
| //		'encryptedDataKeypath':			'data', | ||||
| //		'encryptedVersionKeypath':		'version' | ||||
| 		} | ||||
| 	}); | ||||
|  | ||||
| 	this._tagsData =  | ||||
| 	this._lock = new MochiKit.Async.DeferredLock(); | ||||
| 	this._transientState = null; | ||||
|  | ||||
| @@ -154,9 +151,6 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, { | ||||
| 	}, | ||||
|  | ||||
| 	'setDirectLoginIndexData': function (aDirectLoginReference, aKey, aValue) { | ||||
| //if (MochiKit.Base.isUndefinedOrNull(this.directLoginsIndex()[aDirectLoginReference])) { | ||||
| //	throw "PIPPO"; | ||||
| //} | ||||
| 		return this.directLoginsData().setValue(this.directLoginsIndex()[aDirectLoginReference] + '.' + aKey, aValue); | ||||
| 	}, | ||||
|  | ||||
| @@ -182,8 +176,6 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, { | ||||
| 				innerDeferredResult = new Clipperz.Async.Deferred("User.Header.RecordIndex.records <inner deferred>", {trace:false}); | ||||
| 				innerDeferredResult.collectResults({ | ||||
| 					'records': [ | ||||
| //						MochiKit.Base.method(this.recordsData(), 'getObjectDataStore'), | ||||
| //						MochiKit.Base.methodcaller('values') | ||||
| 						MochiKit.Base.method(this.recordsData(), 'values') | ||||
| 					], | ||||
| 					'recordsStats': [ | ||||
| @@ -191,8 +183,6 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, { | ||||
| 						MochiKit.Base.itemgetter('recordsStats') | ||||
| 					], | ||||
| 					'directLogins': [ | ||||
| //						MochiKit.Base.method(this.directLoginsData(), 'getObjectDataStore'), | ||||
| //						MochiKit.Base.methodcaller('values') | ||||
| 						MochiKit.Base.method(this.directLoginsData(), 'values') | ||||
| 					] | ||||
| 				}) | ||||
| @@ -210,11 +200,13 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, { | ||||
| 						var	record; | ||||
| 						var reference; | ||||
| 						var updateDate; | ||||
| 						var accessDate; | ||||
|  | ||||
| 						reference = recordsInvertedIndex[indexReference]; | ||||
| 						 | ||||
| 						if (typeof(someData['recordsStats'][reference]) != 'undefined') { | ||||
| 							updateDate = someData['recordsStats'][reference]['updateDate']; | ||||
| 							accessDate = someData['recordsStats'][reference]['accessDate']; | ||||
| 						 | ||||
| 							record = new Clipperz.PM.DataModel.Record({ | ||||
| 								'reference':					reference, | ||||
| @@ -224,6 +216,7 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, { | ||||
| 								'retrieveIndexDataFunction':	MochiKit.Base.method(this, 'getRecordIndexData'), | ||||
| 								'updateIndexDataFunction':		MochiKit.Base.method(this, 'updateRecordIndexData'), | ||||
| 								'updateDate':					updateDate, | ||||
| 								'accessDate':					accessDate, | ||||
|  | ||||
| 								'retrieveDirectLoginIndexDataFunction':	MochiKit.Base.method(this, 'getDirectLoginIndexData'), | ||||
| 								'setDirectLoginIndexDataFunction':		MochiKit.Base.method(this, 'setDirectLoginIndexData'), | ||||
| @@ -235,13 +228,10 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User.Header.RecordIndex, Object, { | ||||
| 							this._records[reference] = record; | ||||
| 						} else { | ||||
| Clipperz.log("SKIPPING record " + reference + " as there are no stas associated - " + Clipperz.Base.serializeJSON(someData['records'][reference])); | ||||
| 							//	# skip the record, as it seems it is not present in the DB | ||||
| 							//	updateDate = Clipperz.PM.Date.formatDateWithUTCFormat(new Date()); | ||||
| 						} | ||||
| 					} | ||||
|  | ||||
| 					for (indexReference in someData['directLogins']) { | ||||
| //						var	directLogin; | ||||
| 						var reference; | ||||
| 						var record; | ||||
|  | ||||
| @@ -249,7 +239,6 @@ Clipperz.log("SKIPPING record " + reference + " as there are no stas associated | ||||
| 						record = this._records[recordsInvertedIndex[someData['directLogins'][indexReference]['record']]]; | ||||
|  | ||||
| 						if (record != null) { | ||||
| //							directLogin = new Clipperz.PM.DataModel.DirectLogin({ | ||||
| 							new Clipperz.PM.DataModel.DirectLogin({ | ||||
| 								'reference':					reference, | ||||
| 								'record':						record | ||||
| @@ -301,6 +290,7 @@ Clipperz.log("SKIPPING record " + reference + " as there are no stas associated | ||||
| 			'retrieveIndexDataFunction':	MochiKit.Base.method(this, 'getRecordIndexData'), | ||||
| 			'updateIndexDataFunction':		MochiKit.Base.method(this, 'updateRecordIndexData'), | ||||
| 			'updateDate':					Clipperz.PM.Date.formatDateWithUTCFormat(new Date()), | ||||
| 			'accessDate':					Clipperz.PM.Date.formatDateWithUTCFormat(new Date()), | ||||
|  | ||||
| 			'retrieveDirectLoginIndexDataFunction':	MochiKit.Base.method(this, 'getDirectLoginIndexData'), | ||||
| 			'setDirectLoginIndexDataFunction':		MochiKit.Base.method(this, 'setDirectLoginIndexData'), | ||||
| @@ -384,10 +374,6 @@ Clipperz.log("SKIPPING record " + reference + " as there are no stas associated | ||||
|  | ||||
| 	'deleteAllCleanTextData': function () { | ||||
| 		return Clipperz.Async.callbacks("User.Header.RecordIndex.deleteAllCleanTextData", [ | ||||
| //			MochiKit.Base.method(this, 'records'), | ||||
| //			MochiKit.Base.values, | ||||
| //			MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('deleteAllCleanTextData')), | ||||
|  | ||||
| 			MochiKit.Base.method(this, 'recordsData'), | ||||
| 			MochiKit.Base.methodcaller('deleteAllCleanTextData'), | ||||
| 			MochiKit.Base.method(this, 'directLoginsData'), | ||||
| @@ -410,21 +396,9 @@ Clipperz.log("SKIPPING record " + reference + " as there are no stas associated | ||||
| 				MochiKit.Base.method(this, 'directLoginsData'), | ||||
| 				MochiKit.Base.methodcaller('hasAnyCleanTextData') | ||||
| 			], | ||||
| //			'records': [ | ||||
| //				MochiKit.Base.method(this, 'records'), | ||||
| //				MochiKit.Base.values, | ||||
| //				MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('hasAnyCleanTextData')), | ||||
| //				Clipperz.Async.collectAll | ||||
| //			] | ||||
| 		}); | ||||
|  | ||||
| //		deferredResult.addCallback(MochiKit.Base.values); | ||||
| //		deferredResult.addCallback(MochiKit.Base.flattenArguments); | ||||
| //		deferredResult.addCallback(function(someValues) { | ||||
| //			return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); | ||||
| //		}); | ||||
| 		deferredResult.addCallback(Clipperz.Async.or); | ||||
| 		 | ||||
| 		deferredResult.callback(); | ||||
| 		 | ||||
| 		return deferredResult; | ||||
| @@ -447,11 +421,6 @@ Clipperz.log("SKIPPING record " + reference + " as there are no stas associated | ||||
| 			] | ||||
| 		}); | ||||
| 		deferredResult.addCallback(Clipperz.Async.or); | ||||
| //		deferredResult.addCallback(MochiKit.Base.values); | ||||
| //		deferredResult.addCallback(MochiKit.Base.flattenArguments); | ||||
| //		deferredResult.addCallback(function(someValues) { | ||||
| //			return MochiKit.Iter.some(someValues, MochiKit.Base.operator.identity); | ||||
| //		}); | ||||
| 		deferredResult.callback(); | ||||
|  | ||||
| 		return deferredResult; | ||||
| @@ -482,9 +451,6 @@ Clipperz.log("SKIPPING record " + reference + " as there are no stas associated | ||||
| 			MochiKit.Base.method(this, 'recordsData'), | ||||
| 			MochiKit.Base.methodcaller('revertChanges'), | ||||
|  | ||||
| //			MochiKit.Base.method(this, 'directLoginsData'), | ||||
| //			MochiKit.Base.methodcaller('revertChanges'), | ||||
|  | ||||
| 			MochiKit.Base.method(this, 'records'), | ||||
| 			MochiKit.Base.bind(function (someRecords) { | ||||
| 				var	recordReference; | ||||
| @@ -500,22 +466,10 @@ Clipperz.log("SKIPPING record " + reference + " as there are no stas associated | ||||
| 				} | ||||
| 			}, this), | ||||
|  | ||||
| //			MochiKit.Base.method(this, 'directLogins'), | ||||
| 			MochiKit.Base.bind(function () { | ||||
| 				var	directLoginReference; | ||||
|  | ||||
| //	this.transientState().setValue('newDirectLoginReferences' + '.' + newDirectLogin.reference(), newDirectLogin); | ||||
| // | ||||
| //	this.directLoginsIndex()[newDirectLogin.reference()] = newDirectLoginIndexValue; | ||||
| //	this.directLoginsData().setValue(this.directLoginsIndex()[newDirectLogin.reference()], {'record': this.recordsIndex()[aRecord.reference()]}); | ||||
|  | ||||
| 				 | ||||
| //				for (directLoginReference in this.transientState().getValue('deleteDirectLoginReferences')) { | ||||
| //					someDirectLogins[directLoginReference] = this.transientState().getValue('deleteDirectLoginReferences' + '.' + recordReference); | ||||
| //				} | ||||
|  | ||||
| 				for (directLoginReference in this.transientState().getValue('newDirectLoginReferences')) { | ||||
| //					this.directLoginsData().removeValue(this.directLoginsIndex()[directLoginReference]); | ||||
| 					delete this.directLoginsIndex()[directLoginReference]; | ||||
| 				} | ||||
| 			}, this), | ||||
|   | ||||
| @@ -41,7 +41,7 @@ Clipperz.PM.DataModel.User = function (args) { | ||||
| 	this._connection = null; | ||||
| 	this._connectionVersion = 'current'; | ||||
|  | ||||
| 	this._subscription = null; | ||||
| 	this._accountInfo = null; | ||||
| 	this._serverData = null; | ||||
| //	this._serverLockValue = null; | ||||
| 	this._transientState = null; | ||||
| @@ -78,12 +78,12 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { | ||||
| 	//------------------------------------------------------------------------- | ||||
|  | ||||
| //	this.setSubscription(new Clipperz.PM.DataModel.User.Subscription(someServerData['subscription'])); | ||||
| 	'subscription': function () { | ||||
| 		return this._subscription; | ||||
| 	'accountInfo': function () { | ||||
| 		return this._accountInfo; | ||||
| 	}, | ||||
|  | ||||
| 	'setSubscription': function (aValue) { | ||||
| 		this._subscription = aValue; | ||||
| 	'setAccountInfo': function (aValue) { | ||||
| 		this._accountInfo = aValue; | ||||
| 	}, | ||||
|  | ||||
| 	//------------------------------------------------------------------------- | ||||
| @@ -247,19 +247,16 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { | ||||
| 		var deferredResult; | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred("User.login", {trace:false}); | ||||
| //		deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':3}); | ||||
| 		deferredResult.addMethod(this, 'getPassphrase'); | ||||
| 		deferredResult.addCallback(Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue); | ||||
| 		deferredResult.addCallback(Clipperz.Async.deferredIf("Is the passphrase an OTP", [ | ||||
| //			MochiKit.Base.partial(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'updateProgress', {'extraSteps':1}), | ||||
| 			MochiKit.Base.method(this, 'getCredentials'), | ||||
| 			MochiKit.Base.method(this.connection(), 'redeemOneTimePassword'), | ||||
| 			MochiKit.Base.method(this.data(), 'setValue', 'passphrase') | ||||
| 		], [])); | ||||
| 		deferredResult.addErrback(MochiKit.Base.method(this, 'getPassphrase')); | ||||
| 		deferredResult.addMethod(this.connection(), 'login', false); | ||||
| 		deferredResult.addMethod(this, 'setupConnectionInfo'); | ||||
| //		deferredResult.addCallbackPass(MochiKit.Signal.signal,	Clipperz.Signal.NotificationCenter, 'userSuccessfullyLoggedIn'); | ||||
| 		deferredResult.addMethod(this, 'setupAccountInfo'); | ||||
| 		deferredResult.addErrback (MochiKit.Base.method(this, 'handleConnectionFallback')); | ||||
|  | ||||
| 		deferredResult.callback(); | ||||
| @@ -295,9 +292,10 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { | ||||
|  | ||||
| 	//------------------------------------------------------------------------- | ||||
|  | ||||
| 	'setupConnectionInfo': function (aValue) { | ||||
| 	'setupAccountInfo': function (aValue) { | ||||
| //console.log("User.setupAccountInfo", aValue, aValue['accountInfo']); | ||||
| //		this.setLoginInfo(aValue['loginInfo']); | ||||
| 		this.setSubscription(new Clipperz.PM.DataModel.User.Subscription(aValue['subscription'])); | ||||
| 		this.setAccountInfo(new Clipperz.PM.DataModel.User.AccountInfo(aValue['accountInfo'])); | ||||
| 	}, | ||||
|  | ||||
| 	//------------------------------------------------------------------------- | ||||
| @@ -511,6 +509,19 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	'getTags': function () { | ||||
| 		return Clipperz.Async.callbacks("User.getTags", [ | ||||
| 			MochiKit.Base.method(this, 'getRecords'), | ||||
| 			MochiKit.Base.partial(MochiKit.Base.map, MochiKit.Base.methodcaller('tags')), | ||||
| 			Clipperz.Async.collectAll, | ||||
| 			MochiKit.Base.flattenArray, | ||||
| 			Clipperz.Base.arrayWithUniqueValues | ||||
| 			 | ||||
| 		], {trace:false}); | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	'getRecords': function () { | ||||
| 		return Clipperz.Async.callbacks("User.getRecords", [ | ||||
| 			MochiKit.Base.method(this, 'getHeaderIndex', 'recordsIndex'), | ||||
| @@ -519,6 +530,36 @@ Clipperz.Base.extend(Clipperz.PM.DataModel.User, Object, { | ||||
| 		], {trace:false}); | ||||
| 	}, | ||||
|  | ||||
| 	'getRecordsInfo': function (someInfo, shouldIncludeArchivedCards) { | ||||
| 		return Clipperz.Async.callbacks("User.getRecordsInfo", [ | ||||
| 			MochiKit.Base.method(this, 'getRecords'), | ||||
| 			MochiKit.Base.partial(MochiKit.Base.map, Clipperz.Async.collectResults("collectResults", someInfo, {trace:false})), | ||||
| 			Clipperz.Async.collectAll | ||||
| 		], {trace:false}); | ||||
| 	}, | ||||
| /* | ||||
| 	'filterRecordsInfo': function (someArgs) { | ||||
| 		var	info			= (someArgs.info			? someArgs.info				: Clipperz.PM.DataModel.Record.defaultCardInfo); | ||||
| 		var	searchField		= (someArgs.searchField		? someArgs.searchField		: Clipperz.PM.DataModel.Record.defaultSearchField); | ||||
| 		var	includeArchived	= (someArgs.includeArchived	? someArgs.includeArchived	: false); | ||||
| 		var	regExp			= (someArgs.regExp			? someArgs.regExp			: Clipperz.PM.DataModel.Record.regExpForSearch('')); | ||||
| 		 | ||||
| 		if (someArgs.regExp) { | ||||
| 			regExp = regExp; | ||||
| 		} else if (someArgs.search) { | ||||
| 			regExp = Clipperz.PM.DataModel.Record.regExpForSearch(someArgs.search); | ||||
| 		} else if (someArgs.tag) { | ||||
| 			regExp = Clipperz.PM.DataModel.Record.regExpForTag(someArgs.tag); | ||||
| 		} else { | ||||
| 			regExp = Clipperz.PM.DataModel.Record.regExpForSearch(''); | ||||
| 		}; | ||||
| 		 | ||||
| 		return Clipperz.Async.callbacks("User.filterRecordsInfo", [ | ||||
| 			MochiKit.Base.method(this, 'getRecordsInfo', info, includeArchived), | ||||
| 			MochiKit.Base.partial(MochiKit.Base.filter, function (aCardInfo) { regExp.lastIndex = 0; return regExp.test(aCardInfo[searchField]);}) | ||||
| 		], {trace:false}); | ||||
| 	}, | ||||
| */ | ||||
| 	'recordWithLabel': function (aLabel) { | ||||
| 		return Clipperz.Async.callbacks("User.recordWithLabel", [ | ||||
| 			MochiKit.Base.method(this, 'getRecords'), | ||||
|   | ||||
| @@ -152,7 +152,7 @@ Clipperz.PM.Proxy.prototype = MochiKit.Base.update(null, { | ||||
| 	'sendMessage': function (aFunctionName, someParameters) { | ||||
| 		var deferredResult; | ||||
|  | ||||
| console.log("PROXY.sendMessage", aFunctionName, someParameters); | ||||
| //console.log("PROXY.sendMessage", aFunctionName, someParameters); | ||||
| //	TODO: read actual application version for a property set at build time | ||||
| 		deferredResult = new Clipperz.Async.Deferred("Proxy.sendMessage", {trace:false}); | ||||
| 		deferredResult.addMethod(this, '_sendMessage', aFunctionName, 'fake-app-version'); | ||||
|   | ||||
| @@ -57,7 +57,7 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.JSON, Clipperz.PM.Proxy, { | ||||
| 			version: aVersion, | ||||
| 			parameters: Clipperz.Base.serializeJSON(someParameters) | ||||
| 		}; | ||||
| console.log("PROXY.JSON._sendMessage", parameters); | ||||
| //console.log("PROXY.JSON._sendMessage", parameters); | ||||
| 		deferredResult = new Clipperz.Async.Deferred("Proxy.JSON._sendMessage", {trace:false}); | ||||
| 		deferredResult.addCallbackPass(MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'remoteRequestSent'); | ||||
| 		deferredResult.addCallback(MochiKit.Async.doXHR, this.url(), { | ||||
|   | ||||
| @@ -36,7 +36,7 @@ Clipperz.PM.Proxy.Offline.DataStore = function(args) { | ||||
|  | ||||
| 	this._tolls = {}; | ||||
| 	this._currentStaticConnection = null; | ||||
| 	 | ||||
|  | ||||
| 	return this; | ||||
| } | ||||
|  | ||||
| @@ -47,7 +47,7 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, { | ||||
| 	'isReadOnly': function () { | ||||
| 		return this._isReadOnly; | ||||
| 	}, | ||||
|  | ||||
| 	 | ||||
| 	'canRegisterNewUsers': function () { | ||||
| 		return false; | ||||
| 	}, | ||||
| @@ -296,14 +296,14 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, { | ||||
| 				throw "user already exists"; | ||||
| 			} | ||||
| 		} else { | ||||
| 			throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly; | ||||
| 		throw Clipperz.PM.Proxy.Offline.DataStore.exception.ReadOnly; | ||||
| 		} | ||||
|  | ||||
| 		result = { | ||||
| 			result: { | ||||
| 				'lock':		this.data()['users'][someParameters['credentials']['C']]['lock'], | ||||
| 				'result':	'done' | ||||
| 			}, | ||||
| 	}, | ||||
| 			toll:   this.getTollForRequestType('CONNECT') | ||||
| 		} | ||||
|  | ||||
| @@ -334,7 +334,7 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, { | ||||
| 			randomBytes = Clipperz.Crypto.Base.generateRandomSeed(); | ||||
| 			aConnection['b'] = new Clipperz.Crypto.BigInt(randomBytes, 16); | ||||
| 			v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16); | ||||
| 			aConnection['B'] = v.add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n())); | ||||
| 			aConnection['B'] = (Clipperz.Crypto.SRP.k().multiply(v)).add(Clipperz.Crypto.SRP.g().powerModule(aConnection['b'], Clipperz.Crypto.SRP.n())); | ||||
| 			 | ||||
| 			aConnection['A'] = someParameters.parameters.A; | ||||
| 			 | ||||
| @@ -343,21 +343,65 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, { | ||||
| 			 | ||||
| 			nextTollRequestType = 'CONNECT'; | ||||
| 		} else if (someParameters.message == "credentialCheck") { | ||||
| 			var v, u, S, A, K, M1; | ||||
| 			 | ||||
| 			var v, u, s, S, A, K, M1; | ||||
| 			var stringHash = function (aValue) { | ||||
| 				return Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aValue)).toHexString().substring(2); | ||||
| 			}; | ||||
|  | ||||
| 			v = new Clipperz.Crypto.BigInt(aConnection['userData']['v'], 16); | ||||
| 			u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(aConnection['B'].asString(10))).toHexString(), 16); | ||||
| 			A = new Clipperz.Crypto.BigInt(aConnection['A'], 16); | ||||
| 			u = new Clipperz.Crypto.BigInt(Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10))).toHexString(), 16); | ||||
| 			s = new Clipperz.Crypto.BigInt(aConnection['userData']['s'], 16); | ||||
| 			S = (A.multiply(v.powerModule(u, Clipperz.Crypto.SRP.n()))).powerModule(aConnection['b'], Clipperz.Crypto.SRP.n()); | ||||
|  | ||||
| 			K = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(S.asString(10))).toHexString().slice(2); | ||||
| 			K = stringHash(S.asString(10)); | ||||
|  | ||||
| 			M1 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + aConnection['B'].asString(10) + K)).toHexString().slice(2); | ||||
| 			M1 = stringHash( | ||||
| 				"597626870978286801440197562148588907434001483655788865609375806439877501869636875571920406529" + | ||||
| 				stringHash(aConnection['C']) + | ||||
| 				s.asString(10) + | ||||
| 				A.asString(10) + | ||||
| 				aConnection['B'].asString(10) + | ||||
| 				K | ||||
| 			); | ||||
| 			if (someParameters.parameters.M1 == M1) { | ||||
| 				var M2; | ||||
| 				 | ||||
| 				M2 = Clipperz.PM.Crypto.encryptingFunctions.versions[someParameters.version].hash(new Clipperz.ByteArray(A.asString(10) + someParameters.parameters.M1 + K)).toHexString().slice(2); | ||||
| 				M2 = stringHash( | ||||
| 					A.asString(10) + | ||||
| 					someParameters.parameters.M1 + | ||||
| 					K | ||||
| 				); | ||||
| 				result['M2'] = M2; | ||||
| 				result['accountInfo'] = { | ||||
| 					'currentSubscriptionType': "FAN", | ||||
| 					'expirationDate': "Tue, 21 April 2015 11:59:12 UTC", | ||||
| 					'featureSet': "FULL", | ||||
| 					'features': [ | ||||
| 						'UPDATE_CREDENTIALS', | ||||
| 						'EDIT_CARD', | ||||
| 						'CARD_DETAILS', | ||||
| 						'ADD_CARD', | ||||
| 						'DELETE_CARD', | ||||
| 						'OFFLINE_COPY', | ||||
| 						'LIST_CARDS' | ||||
| 					], | ||||
| 					'isExpired': false, | ||||
| 					'isExpiring': false, | ||||
| 					'latestActiveLevel': "PAYING", | ||||
| 					'latestActiveThreshold': "5.00000000", | ||||
| 					'paymentVerificationPending': false, | ||||
| 					'payments': [ | ||||
| 						{		 | ||||
| 							'amount': "0.08500000", | ||||
| 							'currency': "BTC", | ||||
| 							'date': "Mon, 21 April 2014 12:11:12 UTC", | ||||
| 							'reference': "cad577106f8747ae1b0fad3f139f4b4644301a0608dd931f758ad18c1766cabe", | ||||
| 							'value': "5.23730000" | ||||
| 						} | ||||
| 					], | ||||
| 					'referenceDate': "Tue, 22 July 2014 15:47:08 UTC" | ||||
| 				}; | ||||
| 			} else { | ||||
| 				throw new Error("Client checksum verification failed! Expected <" + M1 + ">, received <" + someParameters.parameters.M1 + ">.", "Error"); | ||||
| 			} | ||||
| @@ -426,6 +470,7 @@ Clipperz.Base.extend(Clipperz.PM.Proxy.Offline.DataStore, Object, { | ||||
| 			recordsStats = {}; | ||||
| 			for (recordReference in aConnection['userData']['records']) { | ||||
| 				recordsStats[recordReference] = { | ||||
| 					'accessDate': aConnection['userData']['records'][recordReference]['accessDate'], | ||||
| 					'updateDate': aConnection['userData']['records'][recordReference]['updateDate'] | ||||
| 				} | ||||
| 			} | ||||
|   | ||||
							
								
								
									
										56
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/AccountStatus.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/AccountStatus.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components'); | ||||
|  | ||||
| Clipperz.PM.UI.Components.AccountStatus = React.createClass({ | ||||
|  | ||||
| 	propTypes: { | ||||
| 		'currentSubscriptionType':		React.PropTypes.oneOf(['EARLY_ADOPTER', 'FRIEND', 'FAN', 'DEVOTEE', 'PATRON', 'TRIAL', 'TRIAL_EXPIRED', 'PAYMENT_FAILED_2', 'EXPIRED', 'PAYMENT_FAILED', 'VERIFYING_PAYMENT', 'VERIFYING_PAYMENT_2']).isRequired, | ||||
| 		'expirationDate':				React.PropTypes.string.isRequired, | ||||
| 		'featureSet':					React.PropTypes.oneOf(['TRIAL', 'EXPIRED', 'FULL']).isRequired, | ||||
| 		'isExpired':					React.PropTypes.bool.isRequired, | ||||
| 		'isExpiring':					React.PropTypes.bool.isRequired, | ||||
| 		'paymentVerificationPending':	React.PropTypes.bool.isRequired, | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	render: function () { | ||||
| //console.log("AccountStatus props", this.props); | ||||
| 		var	classes = { | ||||
| 			'accountStatus':	true, | ||||
| 			'isExpiring':		this.props['isExpiring'], | ||||
| 			'isExpired':		this.props['isExpired'], | ||||
| 		}; | ||||
| 		 | ||||
| 		classes[this.props['featureSet']] = true; | ||||
|  | ||||
| 		return	React.DOM.div({'className':React.addons.classSet(classes)}, [ | ||||
| 			React.DOM.span({'className': 'level'}, this.props['featureSet']), | ||||
| 			React.DOM.span({'className': 'expirationDate'}, this.props['expirationDate']) | ||||
| 		]); | ||||
| 	} | ||||
|  | ||||
| 	//========================================================================= | ||||
| }); | ||||
							
								
								
									
										53
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/Button.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/Button.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components'); | ||||
|  | ||||
| Clipperz.PM.UI.Components.Button = React.createClass({ | ||||
|  | ||||
| 	propTypes: { | ||||
| 		'eventName':	React.PropTypes.string.isRequired, | ||||
| 		'label':		React.PropTypes.string.isRequired, | ||||
| 		'handler':		React.PropTypes.func.isRequired, | ||||
| 		'className':	React.PropTypes.string | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	render: function () { | ||||
| 		var	classes = { | ||||
| 			'button': true | ||||
| 		}; | ||||
| 		if (typeof(this.props['className']) != 'undefined') { | ||||
| 			classes[this.props['className']] = true; | ||||
| 		}; | ||||
| 	 | ||||
| 		return	React.DOM.div({className:React.addons.classSet(classes), onClick:this.props['handler']}, [ | ||||
| 			React.DOM.div({className:this.props['eventName']}, [ | ||||
| 				React.DOM.h3({className:'label'}, this.props['label']) | ||||
| 			]) | ||||
| 		]); | ||||
| 	} | ||||
|  | ||||
| 	//========================================================================= | ||||
| }); | ||||
| @@ -1,195 +0,0 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| Clipperz.PM.UI.Components.CardDetail = React.createClass({ | ||||
|  | ||||
| 	getDefaultProps: function () { | ||||
| 		return { | ||||
| //			searchDelay: 0.3 | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	propTypes: { | ||||
| 		card: React.PropTypes.object.isRequired | ||||
| 	}, | ||||
|  | ||||
| 	getInitialState: function () { | ||||
| 		return { | ||||
| //			showSearch: false, | ||||
| //			searchTimer: null, | ||||
| 			unmaskedFields: new Clipperz.Set(), | ||||
| 			starred: false | ||||
| 		}; | ||||
| 	}, | ||||
|  | ||||
| 	handleDirectLoginClick: function (aDirectLoginReference, anEvent) { | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'runDirectLogin', {record:this.props.card['reference'], directLogin:aDirectLoginReference}); | ||||
| 	}, | ||||
|  | ||||
| 	toggleFieldVisibility: function (aField, anEvent) { | ||||
| 		var unmaskedFields; | ||||
| 		var fieldReference; | ||||
|  | ||||
| 		unmaskedFields = this.state['unmaskedFields']; | ||||
| 		fieldReference = aField['reference'] | ||||
| 		if (unmaskedFields.contains(fieldReference)) { | ||||
| 			unmaskedFields.remove(fieldReference) | ||||
| 		} else { | ||||
| 			unmaskedFields.add(fieldReference) | ||||
| 		} | ||||
|  | ||||
| 		this.setState({'unmaskedFields': unmaskedFields}); | ||||
| 	}, | ||||
|  | ||||
| 	handleGoAction: function (aField, anEvent) { | ||||
| 		var newWindow; | ||||
|  | ||||
| 		newWindow = MochiKit.DOM.currentWindow().open(aField['value'], '_blank'); | ||||
| 		newWindow.focus(); | ||||
| 	}, | ||||
|  | ||||
| 	handleEmailAction: function (aField, anEvent) { | ||||
| 		MochiKit.DOM.currentWindow().location = 'mailto:' + aField['value']; | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	normalizeFieldValue: function (aValue) { | ||||
| 		var	result = []; | ||||
| 		var	rows = aValue.split('\n'); | ||||
|  | ||||
| 		for (var i = 0; i < rows.length; i++) { | ||||
| 			if (i > 0) { | ||||
| 				result.push(React.DOM.br()); | ||||
| 			} | ||||
| 			result.push(rows[i].replace(/[\s]/g, '\u00A0')); | ||||
| 		} | ||||
|  | ||||
| 		return result; | ||||
| 	}, | ||||
|  | ||||
| 	renderFieldActionButton: function (aField) { | ||||
| //		var	actionLabel; | ||||
| 		var result; | ||||
|  | ||||
| 		if (aField['actionType'] == 'URL') { | ||||
| 			result = 	React.DOM.div({className:'actionWrapper', onClick:MochiKit.Base.method(this, 'handleGoAction', aField)}, [ | ||||
| 							React.DOM.a({className:aField['actionType']}, "go") | ||||
| 						]); | ||||
| 		} else if (aField['actionType'] == 'PASSWORD') { | ||||
| 			var icon; | ||||
|  | ||||
| 			if (this.state['unmaskedFields'].contains(aField['reference'])) { | ||||
| 				icon = "unlocked"; | ||||
| 			} else { | ||||
| 				icon = "locked"; | ||||
| 			} | ||||
| 			result =	React.DOM.div({className:'actionWrapper', onClick:MochiKit.Base.method(this, 'toggleFieldVisibility', aField)}, [ | ||||
| 							React.DOM.a({className:aField['actionType']}, icon) | ||||
| 						]); | ||||
| 		} else if (aField['actionType'] == 'EMAIL') { | ||||
| 			result =	React.DOM.div({className:'actionWrapper', onClick:MochiKit.Base.method(this, 'handleEmailAction', aField)}, [ | ||||
| 							React.DOM.a({className:aField['actionType']}, "email") | ||||
| 						]); | ||||
| 		} else { | ||||
| 			result = null; | ||||
| 		} | ||||
|  | ||||
| 		return result; | ||||
| 	}, | ||||
|  | ||||
| 	renderField: function (aField) { | ||||
| //console.log("FIELD", aField); | ||||
| 		var fieldExtraClass; | ||||
|  | ||||
| 		fieldExtraClass = aField['actionType']; | ||||
| 		if (this.state['unmaskedFields'].contains(aField['reference'])) { | ||||
| 			fieldExtraClass = fieldExtraClass + ' unlocked'; | ||||
| 		} | ||||
|  | ||||
| 		return	React.DOM.div({className:'listItem ' + fieldExtraClass, key:aField['reference']}, [ | ||||
| 					React.DOM.div({className:'fieldWrapper'}, [ | ||||
| 						React.DOM.div({className:'fieldInnerWrapper'}, [ | ||||
| 							React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aField['label'])), | ||||
| 							React.DOM.div({className:'valueWrapper'}, React.DOM.span({className:'value ' + fieldExtraClass}, this.normalizeFieldValue(aField['value']))) | ||||
| 						]) | ||||
| 					]), | ||||
| 					this.renderFieldActionButton(aField) | ||||
| //					React.DOM.div({className:'actionWrapper'}, [ | ||||
| //						React.DOM.div({className:aField['actionType']}, actionLabel) | ||||
| //					]) | ||||
| 				]); | ||||
| 	}, | ||||
|  | ||||
| 	renderDirectLogin: function (aDirectLogin) { | ||||
| //console.log("DIRECT LOGIN", aDirectLogin); | ||||
| 		return	React.DOM.div({className:'listItem', onClick:MochiKit.Base.method(this, 'handleDirectLoginClick', aDirectLogin['reference'])}, [ | ||||
| 					React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aDirectLogin['label'])), | ||||
| 					React.DOM.div({className:'faviconWrapper'}, React.DOM.img({className:'favicon', src:aDirectLogin['favicon']})), | ||||
| 					React.DOM.div({className:'directLoginLinkWrapper'}, React.DOM.span({className:'directLoginLink'}, "go")) | ||||
| 				]); | ||||
| 	}, | ||||
|  | ||||
| 	handleBackClick: function (anEvent) { | ||||
| //		window.history.back(); | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'goBack'); | ||||
| 	}, | ||||
|  | ||||
| 	handleStarClick: function (anEvent) { | ||||
| 		this.setState({starred: !this.state['starred']}); | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	render: function () { | ||||
| 		var card = this.props.card; | ||||
| //		var starredStatus = (this.state['starred'] ? "starred" : "unstarred"); | ||||
|  | ||||
| 		if ((typeof(card['fields']) != 'undefined') && (card['notes'] != '')) { | ||||
| 			card['fields'].push({ 'actionType': 'NOTES', 'isHidden': false, 'label': "notes", 'reference': "notes", 'value': card['notes'] }) | ||||
| 		} | ||||
|  | ||||
| 		return	React.DOM.div({className:'cardDetail'}, [ | ||||
| 			React.DOM.div({className:'header'}, [ | ||||
| 				React.DOM.div({className:'titleWrapper'}, React.DOM.div({className:'title'}, card.title)), | ||||
| 				React.DOM.div({className:'backWrapper'},  React.DOM.a({className:'button back', onClick:this.handleBackClick}, "back")), | ||||
| //				React.DOM.div({className:'starWrapper'},  React.DOM.a({className:'star', onClick:this.handleStarClick}, starredStatus)) | ||||
| 			]), | ||||
| 			React.DOM.div({className:'content'}, [ | ||||
| 				card.fields			? React.DOM.div({className:'fields'},		MochiKit.Base.map(this.renderField,			card.fields)) : null, | ||||
| 				card.directLogins	? React.DOM.div({className:'directLogins'},	MochiKit.Base.map(this.renderDirectLogin,	card.directLogins)): null | ||||
| 			]), | ||||
| 			React.DOM.div({className:'footer'}, [ | ||||
| /*				 | ||||
| //				React.DOM.a({className:'cancel'}, "cancel"), | ||||
| //				React.DOM.a({className:'save'},   "save") | ||||
|  | ||||
| 				React.DOM.a({className:'cancel button'}, "failed"), | ||||
| 				React.DOM.a({className:'save button'},   "done") | ||||
| */ | ||||
| 			]) | ||||
| 		]); | ||||
| 	} | ||||
|  | ||||
| 	//========================================================================= | ||||
| }); | ||||
| @@ -1,168 +0,0 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| Clipperz.PM.UI.Components.CardList = React.createClass({ | ||||
|  | ||||
| 	getDefaultProps: function () { | ||||
| 		return { | ||||
| 			selectedCard: null, | ||||
| 			searchDelay: 0.3 | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	propTypes: { | ||||
| 		searchDelay: React.PropTypes.number | ||||
| 	}, | ||||
|  | ||||
| 	getInitialState: function () { | ||||
| 		return { | ||||
| 			showSearch: false, | ||||
| 			searchTimer: null, | ||||
| 			searchText: '', | ||||
| //			passphrase: '', | ||||
| //			pin: '' | ||||
| 		}; | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	toggleSearch: function (anEvent) { | ||||
| 		var	showSearchBox; | ||||
|  | ||||
| 		showSearchBox = !this.state.showSearch; | ||||
|  | ||||
| 		this.setState({showSearch: showSearchBox}); | ||||
|  | ||||
| 		if (showSearchBox) { | ||||
| 			MochiKit.Async.callLater(0.1, MochiKit.Base.method(this, 'focusOnSearchField')); | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	updateSearchText: function (anEvent) { | ||||
| 		var	searchText; | ||||
|  | ||||
| 		searchText = anEvent.target.value; | ||||
| //console.log(">>> updateSearchText", searchText); | ||||
|  | ||||
| 		if ((this.state['searchTimer'] != null) && (searchText != this.state['searchText'])) { | ||||
| 			this.state['searchTimer'].cancel(); | ||||
| 		} | ||||
|  | ||||
| 		if (searchText != this.state['searchText']) { | ||||
| 			this.state['searchText'] = searchText; | ||||
| 			this.state['searchTimer'] = MochiKit.Async.callLater(this.props['searchDelay'], MochiKit.Signal.signal, Clipperz.Signal.NotificationCenter, 'searchCards', searchText); | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	focusOnSearchField: function () { | ||||
| console.log("focusOnSearchField", this.refs['searchField']); | ||||
| 		this.refs['searchField'].getDOMNode.focus(); | ||||
| 	}, | ||||
|  | ||||
| 	searchBox: function () { | ||||
| 		var result; | ||||
|  | ||||
| 		if (this.state.showSearch) { | ||||
| 			result =	React.DOM.div({className:'searchBox'}, [ | ||||
| 							React.DOM.div(null, [ | ||||
| 								React.DOM.input({type:'search', placeholder:"search", ref:'searchField', onChange:this.updateSearchText}) | ||||
| 							]) | ||||
| 						]); | ||||
| 		} else { | ||||
| 			result = null; | ||||
| 		} | ||||
|  | ||||
| 		return result; | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	showPreferences: function (anEvent) { | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'showPreferences', anEvent); | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	cardItem: function (aRecordReference) { | ||||
| 		var	reference = aRecordReference['_reference']; | ||||
| 		var	selectedCard = (reference == this.props.selectedCard); | ||||
|  | ||||
| 		//	TODO: verify if it is possible to put the onClick handler on the container 'div', instead of adding it to each 'div' item. | ||||
| 		return	React.DOM.div({className:'listItem', key:reference, onClick:MochiKit.Base.method(this, 'handleClickOnCardDetail', reference)}, [ | ||||
| 					React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aRecordReference.label)), | ||||
| //					React.DOM.div({className:'labelWrapper'}, React.DOM.span({className:'label'}, aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label + ' ' + aRecordReference.label)), | ||||
| 					React.DOM.div({className:'faviconWrapper'}, aRecordReference.favicon ? React.DOM.img({className:'favicon', src:aRecordReference.favicon}) : React.DOM.div({className:'favicon'}, '\u00A0')), | ||||
| 					React.DOM.div({className:'detailLinkWrapper'}, React.DOM.span({className:'detailLink ' + (selectedCard ? 'icon-spin' : '')}, (selectedCard ? "loading" : "detail"))) | ||||
| 				]); | ||||
| 	}, | ||||
|  | ||||
| 	handleClickOnCardDetail: function (aRecordReference, anEvent) { | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'showRecord', aRecordReference); | ||||
| 	}, | ||||
|  | ||||
| 	cardListItems: function () { | ||||
| 		var	list; | ||||
| 		var	result; | ||||
|  | ||||
| 		list = this.props['cardList']; | ||||
|  | ||||
| 		if (typeof(list) != 'undefined') { | ||||
| 			result = MochiKit.Base.map(MochiKit.Base.method(this, 'cardItem'), list); | ||||
| 		} else { | ||||
| 			result = null; | ||||
| 		} | ||||
|  | ||||
| 		return result; | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	handleChange: function (anEvent) { | ||||
| //		var	refs = this.refs; | ||||
| //		var refName = MochiKit.Base.filter(function (aRefName) { return refs[aRefName].getDOMNode() == anEvent.target}, MochiKit.Base.keys(this.refs))[0]; | ||||
| //		var newState = {}; | ||||
| // | ||||
| //		newState[refName] = event.target.value; | ||||
| //	    this.setState(newState); | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	render: function() { | ||||
| 		return	React.DOM.div(null, [ | ||||
| 					React.DOM.div({className:'header'}, [ | ||||
| 						React.DOM.a({className:'account'}, 'clipperz'), | ||||
| 						React.DOM.div({className:'features'}, [ | ||||
| //							React.DOM.a({className:'addCard'}, 'add'), | ||||
| 							React.DOM.a({className:'search ' + (this.state.showSearch ? 'selected' : ''), onClick:this.toggleSearch}, 'search'), | ||||
| 							React.DOM.a({className:'settings', onClick:this.showPreferences}, 'settings') | ||||
| 						]), | ||||
| //						this.searchBox() | ||||
| 					]), | ||||
| 					this.searchBox(), | ||||
| 					React.DOM.div({className:'content cardList'}, this.cardListItems()), | ||||
| 				]); | ||||
| 	} | ||||
|  | ||||
| 	//========================================================================= | ||||
| }); | ||||
							
								
								
									
										101
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/CardToolbar.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/CardToolbar.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components'); | ||||
|  | ||||
| Clipperz.PM.UI.Components.CardToolbar = React.createClass({ | ||||
|  | ||||
| 	propTypes: { | ||||
| //		'style':			React.PropTypes.oneOf(['extra-short', 'narrow', 'wide', 'extra-wide']).isRequired, | ||||
| 		'style':			React.PropTypes.oneOf(Clipperz_PM_UI_availableStyles).isRequired, | ||||
| 		'enableSidePanels':	React.PropTypes.bool.isRequired, | ||||
| 		'accountStatus':	React.PropTypes.object.isRequired, | ||||
| 		'messageBox':		React.PropTypes.object.isRequired, | ||||
| 		'filter':			React.PropTypes.object.isRequired | ||||
| 	}, | ||||
|  | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	selectionToggleHandler: function (anEvent) { | ||||
| //console.log("selectionToggleHandler"); | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'toggleSelectionPanel'); | ||||
| 		 | ||||
| 	}, | ||||
| 	 | ||||
| 	settingsToggleHandler: function (anEvent) { | ||||
| //console.log("settingsToggleHandler"); | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'toggleSettingsPanel'); | ||||
| 	}, | ||||
| 	 | ||||
| 	//============================================================================ | ||||
|  | ||||
| 	renderWithSidePanels: function () { | ||||
| 		return [ | ||||
| 			React.DOM.div({className:'selectionToggle'}, [ | ||||
| 				Clipperz.PM.UI.Components.Button({eventName:'selectionToggleButton', label:"tags", handler:this.selectionToggleHandler}) | ||||
| 			]), | ||||
| 			this.renderWithoutSidePanels(), | ||||
| 			React.DOM.div({className:'settingsToggle'}, [ | ||||
| 				Clipperz.PM.UI.Components.Button({eventName:'settingsToggleButton', label:"menu", handler:this.settingsToggleHandler}) | ||||
| 			]) | ||||
| 		]; | ||||
| 	}, | ||||
| 	 | ||||
| 	renderWithoutSidePanels: function () { | ||||
| 		var	result; | ||||
| 		 | ||||
| 		if (this.props['filter']) { | ||||
| 			if (this.props['filter']['type'] == 'RECENT') { | ||||
| 				result = [React.DOM.div({className:'clipperz'}, [React.DOM.span({className:'logo recent'}, "recent")])]; | ||||
| 			} else if (this.props['filter']['type'] == 'TAG') { | ||||
| 				result = [React.DOM.div({className:'clipperz'}, [ | ||||
| 					React.DOM.span({className:'logo tag'}, "tag"), | ||||
| 					React.DOM.span({className:'value'}, this.props['filter']['value']) | ||||
| 				])]; | ||||
| 			} else if (this.props['filter']['type'] == 'SEARCH') { | ||||
| 				result = [React.DOM.div({className:'clipperz'}, [ | ||||
| 					React.DOM.span({className:'logo search'}, "search"), | ||||
| 					React.DOM.span({className:'value'}, this.props['filter']['value']) | ||||
| 					])]; | ||||
| 			} else { | ||||
| 				result = [React.DOM.div({className:'clipperz'}, [React.DOM.span({className:'logo clipperz'}, "clipperz")])]; | ||||
| 			} | ||||
| 		} else { | ||||
| 			result = [React.DOM.div({className:'clipperz'}, [React.DOM.span({className:'logo clipperz'}, "clipperz")])]; | ||||
| 		} | ||||
| 		 | ||||
| 		return result; | ||||
| 	}, | ||||
|  | ||||
| 	render: function () { | ||||
| //console.log("CardToolbar props", this.props); | ||||
| 		return	React.DOM.div({className:'cardToolbar ' + this.props['style']}, [ | ||||
| //			React.DOM.div({className:'header'}, this.props['enableSidePanels'] ? this.renderWithSidePanels() : this.renderWithoutSidePanels()), | ||||
| 			React.DOM.header({}, this.props['enableSidePanels'] ? this.renderWithSidePanels() : this.renderWithoutSidePanels()), | ||||
| 			Clipperz.PM.UI.Components.AccountStatus(this.props['accountStatus']), | ||||
| 			Clipperz.PM.UI.Components.MessageBox(this.props['messageBox']), | ||||
| 		]); | ||||
| 	} | ||||
|  | ||||
| 	//============================================================================ | ||||
| }); | ||||
							
								
								
									
										66
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/Cards/List.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/Cards/List.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| 'use strict'; | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components.Cards'); | ||||
|  | ||||
| Clipperz.PM.UI.Components.Cards.List = React.createClass({ | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	propTypes: { | ||||
| 		'cards':		React.PropTypes.array, | ||||
| 		'selectedCard':	React.PropTypes.string | ||||
| 	}, | ||||
|  | ||||
| 	handleClick: function (anEvent) { | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'cardSelected', {'reference':anEvent.currentTarget.dataset.reference, 'label':anEvent.currentTarget.dataset.label}); | ||||
| 	}, | ||||
| 	 | ||||
| 	renderItem: function (anItem) { | ||||
| 		var	classes = { | ||||
| 			'selected':	this.props['selectedCard'] ? this.props['selectedCard']['_reference'] == anItem['_reference'] : false | ||||
| 		};		 | ||||
|  | ||||
| 		return	React.DOM.li({'className':React.addons.classSet(classes), 'onClick': this.handleClick, 'key':anItem['_reference'], 'data-reference':anItem['_reference'], 'data-label':anItem['label']}, [ | ||||
| 			React.DOM.span({'className':'favicon'}, [ React.DOM.img({src:anItem['favicon']})]), | ||||
| 			React.DOM.span({'className':'label'}, anItem['label']), | ||||
| //			React.DOM.span({'className':'action'}, 'show detail') | ||||
| 		]); | ||||
| 	}, | ||||
|  | ||||
| 	render: function () { | ||||
| 		var	cards = this.props['cards'] ? this.props['cards'] : []; | ||||
| 		var	classes = { | ||||
| 			'cardList':		true, | ||||
| 			'loadingCard':	this.props['selectedCard'] && this.props['selectedCard']['_reference'] && this.props['selectedCard']['loading'] | ||||
| 		};		 | ||||
| 		classes[this.props['style']] = true; | ||||
|  | ||||
| 		return	React.DOM.div({'key':'cardList', 'className':React.addons.classSet(classes)}, [ | ||||
| 					React.DOM.ul({}, MochiKit.Base.map(this.renderItem, cards)) | ||||
| 				]); | ||||
| 	}, | ||||
| 	 | ||||
| 	//========================================================================= | ||||
| }); | ||||
							
								
								
									
										133
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/Cards/Toolbar.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/Cards/Toolbar.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| 'use strict'; | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components.Cards'); | ||||
|  | ||||
| Clipperz.PM.UI.Components.Cards.Toolbar = React.createClass({ | ||||
|  | ||||
| 	//============================================================================ | ||||
|  | ||||
| 	propTypes: { | ||||
| //		'label':	React.PropTypes.string.isRequired, | ||||
| //		'loading':	React.PropTypes.bool, | ||||
| 	}, | ||||
|  | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	getInitialState: function() { | ||||
| 		return {'showCommandMenu': false }; | ||||
| 	}, | ||||
| 	 | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	commands: function () { | ||||
| 		return { | ||||
| 			'delete': { | ||||
| 				'label': "delete", | ||||
| 				'broadcastEvent': 'deleteCard' | ||||
| 			}, | ||||
| 			'archive': { | ||||
| 				'label': "archive", | ||||
| 				'broadcastEvent': 'archiveCard' | ||||
| 			}, | ||||
| //			'share': { | ||||
| //				'label': "share", | ||||
| //				'broadcastEvent': 'shareCard' | ||||
| //			}, | ||||
| 			'edit': { | ||||
| 				'label': "edit", | ||||
| 				'broadcastEvent': 'editCard' | ||||
| 			} | ||||
| 		}; | ||||
| 	}, | ||||
|  | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	exit: function (anEvent) { | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'goBackToMainPage', {'reference':this.props['_reference']}); | ||||
| 	}, | ||||
| 	 | ||||
| 	toggleMenu: function (anEvent) { | ||||
| 		this.setState({'showCommandMenu': !this.state['showCommandMenu'] }); | ||||
| 	}, | ||||
| 	 | ||||
| 	selectCommandItem: function (anEvent) { | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, anEvent.target.dataset['broadcastEvent'], {'reference':this.props['_reference']}); | ||||
| 	}, | ||||
|  | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	renderCommands: function () { | ||||
| 		var	commandHandler = this.selectCommandItem; | ||||
| 		 | ||||
| 		return	React.DOM.ul({}, MochiKit.Base.map(function (aCommand) { | ||||
| 					return React.DOM.li({}, [React.DOM.span({'onClick':commandHandler, 'data-broadcast-event':aCommand['broadcastEvent']}, aCommand['label'])]); | ||||
| 				}, MochiKit.Base.values(this.commands()))); | ||||
| 	}, | ||||
|  | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	renderNarrow: function () { | ||||
| 		return [ | ||||
| 			React.DOM.div({}, [ | ||||
| 				React.DOM.div({'className':'back', 'onClick': this.exit}, 'back'), | ||||
| 				React.DOM.div({'className':'cardMenuOptions', 'onClick':this.toggleMenu}, 'commands'), | ||||
| 				React.DOM.div({'className':React.addons.classSet({'commandMenu':true, 'show':this.state['showCommandMenu']})}, [ | ||||
| 					React.DOM.div({'className':'commandMenuMask', 'onClick':this.toggleMenu}), | ||||
| 					React.DOM.div({'className':'commandMenu'}, this.renderCommands()) | ||||
| 				]) | ||||
| 			]) | ||||
| 		] | ||||
| 	}, | ||||
| 	 | ||||
| 	renderOther: function () { | ||||
| 		return [this.renderCommands()]; | ||||
| 	}, | ||||
|  | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	renderLayout: function (aLayout) { | ||||
| 		var	result; | ||||
| 		 | ||||
| 		if (aLayout == 'narrow') { | ||||
| 			result = this.renderNarrow(); | ||||
| 		} else { | ||||
| 			result = this.renderOther(); | ||||
| 		} | ||||
| 		 | ||||
| 		return result; | ||||
| 	}, | ||||
|  | ||||
| 	render: function () { | ||||
| 		var style = this.props['style']; | ||||
| 		var	classes = { | ||||
| 			'cardDetailToolbar':	true, | ||||
| 		}; | ||||
| 		classes[style] = true; | ||||
|  | ||||
| 		return React.DOM.div({'className':React.addons.classSet(classes)}, this.renderLayout(style)); | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
| }); | ||||
							
								
								
									
										161
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/Cards/View.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/Cards/View.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,161 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| 'use strict'; | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components.Cards'); | ||||
|  | ||||
| Clipperz.PM.UI.Components.Cards.View = React.createClass({ | ||||
|  | ||||
| 	//============================================================================ | ||||
|  | ||||
| 	propTypes: { | ||||
| 		'label':	React.PropTypes.string.isRequired, | ||||
| 		'loading':	React.PropTypes.bool, | ||||
| 	}, | ||||
|  | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	renderEmpty: function () { | ||||
| 		return	React.DOM.h4({}, "EMPTY"); | ||||
| 	}, | ||||
| 	 | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	renderLoading: function () { | ||||
| 		return	React.DOM.div({className:'loading'},[ | ||||
| 			this.renderLabel(), | ||||
| 			React.DOM.h5({className:'message'}, "loading") | ||||
| /* | ||||
| 			React.DOM.div({className:'overlay'}, [ | ||||
| 				React.DOM.div({className:'spinner'}, [ | ||||
| 					React.DOM.div({className:'bar01'}), | ||||
| 					React.DOM.div({className:'bar02'}), | ||||
| 					React.DOM.div({className:'bar03'}), | ||||
| 					React.DOM.div({className:'bar04'}), | ||||
| 					React.DOM.div({className:'bar05'}), | ||||
| 					React.DOM.div({className:'bar06'}), | ||||
| 					React.DOM.div({className:'bar07'}), | ||||
| 					React.DOM.div({className:'bar08'}), | ||||
| 					React.DOM.div({className:'bar09'}), | ||||
| 					React.DOM.div({className:'bar10'}), | ||||
| 					React.DOM.div({className:'bar11'}), | ||||
| 					React.DOM.div({className:'bar12'}) | ||||
| 				]) | ||||
| 			]) | ||||
| */ | ||||
| 		]); | ||||
| 	}, | ||||
| 	 | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	renderLabel: function (aLabel) { | ||||
| 		return	React.DOM.h3({'className':'cardLabel'}, aLabel); | ||||
| 	}, | ||||
| 	 | ||||
| 	renderNotes: function (someNotes) { | ||||
| 		return	React.DOM.div({'className':'cardNotes'}, someNotes); | ||||
| 	}, | ||||
|  | ||||
| 	//............................................................................ | ||||
|  | ||||
| 	renderTag: function (aTag) { | ||||
| 		return	React.DOM.div({'className':'cardTag'}, aTag); | ||||
| 	}, | ||||
| 	 | ||||
| 	renderTags: function (someTags) { | ||||
| 		return	React.DOM.div({'className':'cardTags'}, MochiKit.Base.map(this.renderTag, someTags)); | ||||
| 	}, | ||||
|  | ||||
| 	//............................................................................ | ||||
|  | ||||
| 	renderField: function (aField) { | ||||
| 		var	cardFieldClasses = {}; | ||||
| 		var	cardFieldValueClasses = {}; | ||||
| 		 | ||||
| 		cardFieldClasses['cardField'] = true; | ||||
| 		cardFieldClasses[aField['actionType']] = true; | ||||
| 		cardFieldClasses['hidden'] = aField['isHidden']; | ||||
| 		 | ||||
| 		cardFieldValueClasses['fieldValue'] = true; | ||||
| 		cardFieldValueClasses[aField['actionType']] = true; | ||||
| 		cardFieldValueClasses['hidden'] = aField['isHidden']; | ||||
| 		 | ||||
| 		return	React.DOM.div({'className':React.addons.classSet(cardFieldClasses)}, [ | ||||
| 			React.DOM.div({'className':'fieldValues'}, [ | ||||
| 				React.DOM.div({'className':'fieldLabel'}, aField['label']), | ||||
| 				React.DOM.div({'className':React.addons.classSet(cardFieldValueClasses)}, aField['value']), | ||||
| 			]), | ||||
| 			React.DOM.div({'className':'fieldAction action'}, aField['actionType'].toLowerCase()) | ||||
| 		]); | ||||
| 	}, | ||||
|  | ||||
| 	renderFields: function (someFields) { | ||||
| 		return	React.DOM.div({'className':'cardFields'}, MochiKit.Base.map(this.renderField, someFields)); | ||||
| 	}, | ||||
|  | ||||
| 	//............................................................................ | ||||
|  | ||||
| 	renderDirectLogin: function (aDirectLogin) { | ||||
| 		return	React.DOM.div({'className':'cardDirectLogin'}, [ | ||||
| 			React.DOM.span({'className':'directLoginLabel'}, aDirectLogin['label']), | ||||
| 			React.DOM.div({'className':'directLoginAction action'}, 'DIRECT LOGIN') | ||||
| 		]); | ||||
| 	}, | ||||
| 	 | ||||
| 	renderDirectLogins: function (someDirectLogins) { | ||||
| 		return	React.DOM.div({'className':'cardDirectLogins'}, MochiKit.Base.map(this.renderDirectLogin, someDirectLogins)); | ||||
| 	}, | ||||
| 	 | ||||
| 	//............................................................................ | ||||
|  | ||||
| 	renderCard: function () { | ||||
| 		return	React.DOM.div({'className':'view'},[ | ||||
| 			Clipperz.PM.UI.Components.Cards.Toolbar(this.props), | ||||
| 			React.DOM.div({'className':'content'}, [ | ||||
| 				this.renderLabel(this.props['label']), | ||||
| 				this.renderTags(this.props['tags']), | ||||
| 				this.renderNotes(this.props['notes']), | ||||
| 				this.renderFields(this.props['fields']), | ||||
| 				this.renderDirectLogins(this.props['directLogins']) | ||||
| 			]) | ||||
| 		]); | ||||
| 	}, | ||||
| 	 | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	render: function () { | ||||
| 		var	result; | ||||
|  | ||||
| 		if (this.props['loading'] == true) { | ||||
| 			result = this.renderLoading(); | ||||
| 		} else if (this.props['label']) { | ||||
| 			result = this.renderCard(); | ||||
| 		} else { | ||||
| 			result = this.renderEmpty(); | ||||
| 		} | ||||
| 		 | ||||
| 		return result; | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
| }); | ||||
| @@ -21,6 +21,8 @@ refer to http://www.clipperz.com. | ||||
|  | ||||
| */ | ||||
|  | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components'); | ||||
|  | ||||
| Clipperz.PM.UI.Components.Checkbox = React.createClass({ | ||||
| //	http://development.tobypitman.com/iphoneCheckboxes/iphoneCheckboxes2.html | ||||
|  | ||||
|   | ||||
							
								
								
									
										40
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/ExpiredPanel.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/ExpiredPanel.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components'); | ||||
|  | ||||
| Clipperz.PM.UI.Components.ExpiredPanel = React.createClass({ | ||||
|  | ||||
| 	propTypes: { | ||||
| //		featureSet:			React.PropTypes.oneOf(['FULL', 'EXPIRED', 'TRIAL']).isRequired, | ||||
| //		'level':	React.PropTypes.oneOf(['hide', 'info', 'warning', 'error']).isRequired | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	render: function () { | ||||
| 		return	React.DOM.div({className:'expiredPanel'}, "EXPIRED PANEL"); | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
| }); | ||||
							
								
								
									
										47
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/MessageBox.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/MessageBox.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components'); | ||||
|  | ||||
| Clipperz.PM.UI.Components.MessageBox = React.createClass({ | ||||
|  | ||||
| 	propTypes: { | ||||
| 		'level':	React.PropTypes.oneOf(['HIDE', 'INFO', 'WARNING', 'ERROR']).isRequired, | ||||
| 		'message':	React.PropTypes.string.isRequired | ||||
| 	}, | ||||
|  | ||||
| 	getDefaultProps: function () { | ||||
| 		return { | ||||
| 			level: 'HIDE', | ||||
| 			message: '' | ||||
| 		}; | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	render: function () { | ||||
| 		return	React.DOM.div({className:'messageBox ' + this.props['level']}, this.props['message']); | ||||
| 	} | ||||
|  | ||||
| 	//========================================================================= | ||||
| }); | ||||
| @@ -21,13 +21,13 @@ refer to http://www.clipperz.com. | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| Clipperz.PM.UI.Components.PageTemplate = React.createClass({ | ||||
| 	render: function() { | ||||
| 		return	React.DOM.div(null, [ | ||||
| 					React.DOM.div({'className': 'header'}, [ | ||||
| 						React.DOM.h1(null, "clipperz") | ||||
| 					]), | ||||
| 					React.DOM.div({'className': 'content'}, this.props.innerComponent) | ||||
| 				]) | ||||
| 	} | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components.Pages'); | ||||
| 
 | ||||
| Clipperz.PM.UI.Components.Pages.CardDetailPage = React.createClass({ | ||||
| 
 | ||||
| 	render: function () { | ||||
| //		return	React.DOM.header({'className':''})
 | ||||
| 		return	Clipperz.PM.UI.Components.Cards.View(this.props['selectedCard']); | ||||
| 
 | ||||
| 	}, | ||||
| }); | ||||
| @@ -21,11 +21,13 @@ refer to http://www.clipperz.com. | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| Clipperz.PM.UI.Components.ErrorPage = React.createClass({ | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components.Pages'); | ||||
| 
 | ||||
| Clipperz.PM.UI.Components.Pages.ErrorPage = React.createClass({ | ||||
| 
 | ||||
| 	getDefaultProps: function () { | ||||
| 		return { | ||||
| 			template: Clipperz.PM.UI.Components.PageTemplate | ||||
| //			template: Clipperz.PM.UI.Components.PageTemplate
 | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| @@ -36,11 +38,11 @@ Clipperz.PM.UI.Components.ErrorPage = React.createClass({ | ||||
| 	}, | ||||
| 
 | ||||
| 
 | ||||
| 	_render: function () { | ||||
| 	render: function () { | ||||
| 		return	React.DOM.div({className:'error-message'}, this.props.message); | ||||
| 	}, | ||||
| 
 | ||||
| 	render: function () { | ||||
| 		return	new this.props.template({'innerComponent': this._render()}); | ||||
| 	} | ||||
| //	render: function () {
 | ||||
| //		return	new this.props.template({'innerComponent': this._render()});
 | ||||
| //	}
 | ||||
| }); | ||||
| @@ -21,24 +21,26 @@ refer to http://www.clipperz.com. | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| Clipperz.PM.UI.Components.LoginForm = React.createClass({ | ||||
| "use strict"; | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components.Pages'); | ||||
| 
 | ||||
| Clipperz.PM.UI.Components.Pages.LoginPage = React.createClass({ | ||||
| 
 | ||||
| 	propTypes: { | ||||
| 		mode:							React.PropTypes.oneOf(['CREDENTIALS','PIN']).isRequired, | ||||
| 		isNewUserRegistrationAvailable:	React.PropTypes.bool.isRequired, | ||||
| 		disabled:						React.PropTypes.bool.isRequired | ||||
| 	}, | ||||
| /* | ||||
| 	getDefaultProps: function () { | ||||
| 		return { | ||||
| 			mode: 'CREDENTIALS', | ||||
| 			isNewUserRegistrationAvailable: false, | ||||
| 			disabled: false, | ||||
| 			template: Clipperz.PM.UI.Components.PageTemplate | ||||
| //			template: Clipperz.PM.UI.Components.PageTemplate
 | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| 	propTypes: { | ||||
| 		mode:							React.PropTypes.oneOf(['CREDENTIALS','PIN']), | ||||
| 		isNewUserRegistrationAvailable:	React.PropTypes.bool, | ||||
| 		disabled:						React.PropTypes.bool, | ||||
| 		template:						React.PropTypes.func | ||||
| 	}, | ||||
| 
 | ||||
| */ | ||||
| 	getInitialState: function () { | ||||
| 		return { | ||||
| 			username: '', | ||||
| @@ -54,7 +56,7 @@ Clipperz.PM.UI.Components.LoginForm = React.createClass({ | ||||
| 		var refName = MochiKit.Base.filter(function (aRefName) { return refs[aRefName].getDOMNode() == anEvent.target}, MochiKit.Base.keys(this.refs))[0]; | ||||
| 		var newState = {}; | ||||
| 
 | ||||
| 		newState[refName] = event.target.value; | ||||
| 		newState[refName] = anEvent.target.value; | ||||
| 	    this.setState(newState); | ||||
| 	}, | ||||
| 
 | ||||
| @@ -86,25 +88,21 @@ Clipperz.PM.UI.Components.LoginForm = React.createClass({ | ||||
| 					((this.state['username'] != '') && (this.state['passphrase'] != ''))  | ||||
| 					|| | ||||
| 					(this.state['pin'] != '') | ||||
| 				) && !this.props['disabled']; | ||||
| 				) | ||||
| 				&& | ||||
| 				!this.props['disabled']; | ||||
| 	}, | ||||
| 
 | ||||
| 
 | ||||
| 	loginForm: function () { | ||||
| 		registrationLink =	React.DOM.div({'className':'registrationLink'}, [ | ||||
| 								React.DOM.a({'onClick':this.handleRegistrationLinkClick}, "Sign up") | ||||
| 							]); | ||||
| 		return	React.DOM.div({'className':'loginForm credentials'},[ | ||||
| 					React.DOM.form({onChange: this.handleChange, onSubmit:this.handleCredentialSubmit}, [ | ||||
| 						React.DOM.div(null,[ | ||||
| 							React.DOM.label({'for' :'name'}, "username"), | ||||
| 							React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'}), | ||||
| 							React.DOM.label({'for' :'passphrase'}, "passphrase"), | ||||
| 							React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'}) | ||||
| 						]), | ||||
| 						React.DOM.button({'type':'submit', 'disabled':!this.shouldEnableLoginButton(), 'className':'button'}, "login") | ||||
| 		return	React.DOM.form({'className':'loginForm credentials', 'onChange':this.handleChange, 'onSubmit':this.handleCredentialSubmit}, [ | ||||
| 					React.DOM.div(null,[ | ||||
| 						React.DOM.label({'htmlFor' :'name'}, "username"), | ||||
| 						React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'}), | ||||
| 						React.DOM.label({'htmlFor' :'passphrase'}, "passphrase"), | ||||
| 						React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'}) | ||||
| 					]), | ||||
| 					this.props.isNewUserRegistrationAvailable ? registrationLink : null | ||||
| 					React.DOM.button({'type':'submit', 'disabled':!this.shouldEnableLoginButton(), 'className':'button'}, "login") | ||||
| 				]); | ||||
| 	}, | ||||
| 
 | ||||
| @@ -121,14 +119,12 @@ Clipperz.PM.UI.Components.LoginForm = React.createClass({ | ||||
| 	}, | ||||
| 
 | ||||
| 	pinForm: function () { | ||||
| 		return	React.DOM.div({'className':'loginForm pin'},[ | ||||
| 					React.DOM.form({onChange: this.handleChange, onSubmit:this.handlePINSubmit}, [ | ||||
| 						React.DOM.div(null,[ | ||||
| 							React.DOM.label({'for':'pin'}, "pin"), | ||||
| 							React.DOM.input({'type':'text', 'name':'pin', 'ref':'pin', placeholder:"PIN", 'key':'pin', 'autocapitalize':'none'}) | ||||
| 						]), | ||||
| 						React.DOM.button({'type':'submit', 'disabled':this.props.disabled, 'className':'button'}, "login") | ||||
| 					]) | ||||
| 		return	React.DOM.form({'className':'loginForm pin', 'onChange':this.handleChange, 'onSubmit':this.handlePINSubmit}, [ | ||||
| 					React.DOM.div(null,[ | ||||
| 						React.DOM.label({'for':'pin'}, "pin"), | ||||
| 						React.DOM.input({'type':'text', 'name':'pin', 'ref':'pin', placeholder:"PIN", 'key':'pin', 'autocapitalize':'none'}) | ||||
| 					]), | ||||
| 					React.DOM.button({'type':'submit', 'disabled':this.props.disabled, 'className':'button'}, "login") | ||||
| 				]); | ||||
| 	}, | ||||
| 
 | ||||
| @@ -145,6 +141,16 @@ Clipperz.PM.UI.Components.LoginForm = React.createClass({ | ||||
| 	}, | ||||
| 
 | ||||
| 	render: function() { | ||||
| 		return	new this.props.template({'innerComponent': this.props.mode == 'PIN' ? this.pinForm() : this.loginForm()}); | ||||
| 		var registrationLink =	React.DOM.div({'className':'registrationLink'}, [ | ||||
| 									React.DOM.a({'onClick':this.handleRegistrationLinkClick}, "Sign up") | ||||
| 								]); | ||||
| 
 | ||||
| 		return React.DOM.div({'className':'loginForm ' + this.props['style']}, [ | ||||
| 			React.DOM.header({}, 'clipperz'), | ||||
| 			React.DOM.div({'className':'form'}, [ | ||||
| 				this.props.mode == 'PIN' ? this.pinForm() : this.loginForm(), | ||||
| 			]), | ||||
| 			this.props.isNewUserRegistrationAvailable ? registrationLink : null | ||||
| 		]); | ||||
| 	} | ||||
| }); | ||||
| @@ -0,0 +1,66 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| 'use strict'; | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components.Pages'); | ||||
|  | ||||
| Clipperz.PM.UI.Components.Pages.MainPage = React.createClass({ | ||||
|  | ||||
| 	getDefaultProps: function () { | ||||
| 		return { | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	propTypes: { | ||||
| 		'messageBox':		React.PropTypes.object.isRequired, | ||||
| //		'featureSet':		React.PropTypes.oneOf(['FULL', 'EXPIRED', 'TRIAL']), | ||||
| 		'accountStatus':	React.PropTypes.object.isRequired, | ||||
| //		'mediaQueryStyle':	React.PropTypes.oneOf(['extra-short', 'narrow', 'wide', 'extra-wide']).isRequired, | ||||
| 		'style':			React.PropTypes.oneOf(Clipperz_PM_UI_availableStyles).isRequired, | ||||
| 		//		'cards':			React.PropTypes.deferred.isRequired | ||||
| 	}, | ||||
|  | ||||
| 	getInitialState: function () { | ||||
| 		return { | ||||
| //			shouldStoreDataLocally: false | ||||
| 		}; | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	render: function () { | ||||
| 		var	classes = { | ||||
| 			'mainPage': true | ||||
| 		}; | ||||
| 		classes[this.props['style']] = true; | ||||
| //console.log("MainPage.cards", this.props['cards'], this.props['cards'].state()); | ||||
|  | ||||
| 		return	React.DOM.div({className:React.addons.classSet(classes)}, [ | ||||
| 			this.props['style'] != 'extra-wide' ? Clipperz.PM.UI.Components.Panels.SelectionPanel(this.props) : null, | ||||
| 			Clipperz.PM.UI.Components.Panels.MainPanel(this.props), | ||||
| 			Clipperz.PM.UI.Components.Panels.ExtraFeaturesPanel(this.props) | ||||
| 		]); | ||||
| 	} | ||||
|  | ||||
| 	//========================================================================= | ||||
| }); | ||||
| @@ -21,7 +21,9 @@ refer to http://www.clipperz.com. | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({ | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components.Pages'); | ||||
| 
 | ||||
| Clipperz.PM.UI.Components.Pages.RegistrationPage = React.createClass({ | ||||
| 
 | ||||
| 	getDefaultProps: function () { | ||||
| 		return { | ||||
| @@ -31,7 +33,7 @@ Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({ | ||||
| 				{name:'TERMS_OF_SERVICE',		label:'registration',	_label:'terms',			description:"Check our terms of service"} | ||||
| 			], | ||||
| 			disabled: false, | ||||
| 			template: Clipperz.PM.UI.Components.PageTemplate | ||||
| //			template: Clipperz.PM.UI.Components.PageTemplate
 | ||||
| 		} | ||||
| 	}, | ||||
| 
 | ||||
| @@ -166,16 +168,16 @@ Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({ | ||||
| 
 | ||||
| 	render_CREDENTIALS: function () { | ||||
| 		return	React.DOM.div(null,[ | ||||
| 					React.DOM.label({'for':'name'}, "username"), | ||||
| 					React.DOM.label({'htmlFor':'name'}, "username"), | ||||
| 					React.DOM.input({'type':'text', 'name':'name', 'ref':'username', 'placeholder':"username", 'key':'username', 'autoCapitalize':'none'/*, value:this.state.username*/}), | ||||
| 					React.DOM.label({'for':'passphrase'}, "passphrase"), | ||||
| 					React.DOM.label({'htmlFor':'passphrase'}, "passphrase"), | ||||
| 					React.DOM.input({'type':'password', 'name':'passphrase', 'ref':'passphrase', 'placeholder':"passphrase", 'key':'passphrase'/*, value:this.state.passphrase*/}) | ||||
| 				]); | ||||
| 	}, | ||||
| 
 | ||||
| 	render_PASSWORD_VERIFICATION: function () { | ||||
| 		return	React.DOM.div(null,[ | ||||
| 					React.DOM.label({'for':'verify_passphrase'}, "passphrase"), | ||||
| 					React.DOM.label({'htmlFor':'verify_passphrase'}, "passphrase"), | ||||
| 					React.DOM.input({'type':'password', 'name':'verify_passphrase', 'ref':'verify_passphrase', 'placeholder':"verify passphrase", 'key':'verify_passphrase'}) | ||||
| 				]); | ||||
| 	}, | ||||
| @@ -183,12 +185,12 @@ Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({ | ||||
| 	render_TERMS_OF_SERVICE: function () { | ||||
| 		return	React.DOM.div(null, [ | ||||
| 					React.DOM.div({className:'checkboxBlock'}, [ | ||||
| 						React.DOM.label({'for':'no_password_recovery'}, "I understand that Clipperz will not be able to recover a lost passphrase."), | ||||
| 						React.DOM.label({'htmlFor':'no_password_recovery'}, "I understand that Clipperz will not be able to recover a lost passphrase."), | ||||
| 						React.DOM.input({'type':'checkbox', 'name':'no_password_recovery', 'ref':'no_password_recovery', 'key':'no_password_recovery'}), | ||||
| 						React.DOM.p(null, "I understand that Clipperz will not be able to recover a lost passphrase.") | ||||
| 					]), | ||||
| 					React.DOM.div({className:'checkboxBlock'}, [ | ||||
| 						React.DOM.label({'for':'agree_terms_of_service'}, "I have read and agreed to the Terms of Service."), | ||||
| 						React.DOM.label({'htmlFor':'agree_terms_of_service'}, "I have read and agreed to the Terms of Service."), | ||||
| 						React.DOM.input({'type':'checkbox', 'name':'agree_terms_of_service', 'ref':'agree_terms_of_service', 'key':'agree_terms_of_service'}), | ||||
| 						React.DOM.p(null, [ | ||||
| 							"I have read and agreed to the ", | ||||
| @@ -208,7 +210,7 @@ Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({ | ||||
| 				]); | ||||
| 	}, | ||||
| 
 | ||||
| 	_render: function () { | ||||
| 	render: function () { | ||||
| 		return	React.DOM.div({'className':'registrationForm'},[ | ||||
| 					React.DOM.form({onChange: this.handleChange}, [ | ||||
| 						React.DOM.div({'className':'steps'}, MochiKit.Base.map(this.renderStep, this.props['steps'])) | ||||
| @@ -216,9 +218,9 @@ Clipperz.PM.UI.Components.RegistrationWizard = React.createClass({ | ||||
| 				]); | ||||
| 	}, | ||||
| 
 | ||||
| 	render: function () { | ||||
| 		return	new this.props.template({'innerComponent': this._render()}); | ||||
| 	}, | ||||
| //	render: function () {
 | ||||
| //		return	new this.props.template({'innerComponent': this._render()});
 | ||||
| //	},
 | ||||
| 
 | ||||
| 	//=========================================================================
 | ||||
| 
 | ||||
| @@ -0,0 +1,78 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components.Panels'); | ||||
|  | ||||
| Clipperz.PM.UI.Components.Panels.ExtraFeaturesPanel = React.createClass({ | ||||
|  | ||||
| 	settingsToggleHandler: function (anEvent) { | ||||
| //console.log("settingsToggleHandler"); | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'toggleSettingsPanel'); | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	render: function () { | ||||
| 		var	classes = { | ||||
| 			'panel': true, | ||||
| 			'right': true, | ||||
| 			'open': this.props['settingsPanelStatus'] == 'OPEN' | ||||
| 		} | ||||
|  | ||||
| 		return	React.DOM.div({key:'extraFeaturesPanel', id:'extraFeaturesPanel', className:React.addons.classSet(classes)}, [ | ||||
| 			React.DOM.header({}, [ | ||||
| 				React.DOM.div({className:'settingsToggle'}, [ | ||||
| 					Clipperz.PM.UI.Components.Button({eventName:'settingsToggleButton', label:"menu", handler:this.settingsToggleHandler}) | ||||
| 				]) | ||||
| 			]), | ||||
| 			React.DOM.h2({}, "Extra features") | ||||
| 		]); | ||||
| /* | ||||
| 		<div id="extraFeaturesPanel" class="panel extraFeatures"> | ||||
|  | ||||
| 			<div class="warnings"> | ||||
| 				<ul> | ||||
| 					<li>Synchronize local data</li> | ||||
| 				</ul> | ||||
| 			</div> | ||||
|  | ||||
| 			<ul> | ||||
| 				<li>Account</li> | ||||
| 				<li>Subscription</li> | ||||
| 			</ul> | ||||
|  | ||||
| 			<ul> | ||||
| 				<li>Local Data</li> | ||||
| 				<li>OTP</li> | ||||
| 			</ul> | ||||
|  | ||||
| 			<div class="donation"> | ||||
| 				<a>Make a donation</a> | ||||
| 			</div> | ||||
| 		</div> | ||||
| */ | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	//========================================================================= | ||||
| }); | ||||
							
								
								
									
										193
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/Panels/MainPanel.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										193
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/Panels/MainPanel.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,193 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| 'use strict'; | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components.Panels'); | ||||
|  | ||||
| Clipperz.PM.UI.Components.Panels.MainPanel = React.createClass({ | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	propTypes: { | ||||
| 		'messageBox':		React.PropTypes.object.isRequired, | ||||
| 		'featureSet':		React.PropTypes.oneOf(['FULL', 'EXPIRED', 'TRIAL']).isRequired, | ||||
| 		'style':			React.PropTypes.oneOf(Clipperz_PM_UI_availableStyles).isRequired, | ||||
| 	}, | ||||
|  | ||||
| 	getDefaultProps: function () { | ||||
| 		return { | ||||
| 			featureSet: 'FULL' | ||||
| 		}; | ||||
| 	}, | ||||
|  | ||||
| 	style: function () { | ||||
| 		return this.props['style']; | ||||
| 	}, | ||||
|  | ||||
| 	featureSet: function () { | ||||
| 		return this.props['featureSet']; | ||||
| 	}, | ||||
|  | ||||
| 	handleMaskClick: function () { | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'maskClick'); | ||||
| 	}, | ||||
|  | ||||
| 	handleAddCardClick: function () { | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'addCardClick'); | ||||
| 	}, | ||||
|  | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	renderToolbarFrame: function (anInnerComponent) { | ||||
| 		return React.DOM.div({'className':'cardToolbarFrame'}, [ | ||||
| 			this.renderToolbar(), | ||||
| 			anInnerComponent | ||||
| 		]); | ||||
| 	}, | ||||
|  | ||||
| 	renderCardFrame: function (firstColumnComponents, secondColumnComponents) { | ||||
| 		var	addCardButton = React.DOM.div({'className': 'addCardButton', 'onClick':this.handleAddCardClick}, 'add card'); | ||||
|  | ||||
| 		return React.DOM.div({'key':'cardContent', 'className':'cardContent'}, [ | ||||
| 			React.DOM.div({'className':'cardListColumn column'}, [addCardButton, firstColumnComponents]), | ||||
| 			React.DOM.div({'className':'cardDetail column right'}, secondColumnComponents) | ||||
| 		]) | ||||
| 	}, | ||||
|  | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	renderToolbar: function () { | ||||
| 		var	cardToolbarProps; | ||||
| 		 | ||||
| 		cardToolbarProps = MochiKit.Base.merge(this.props, { | ||||
| 			'key':				'toolbar', | ||||
| 			'style':			this.style(), | ||||
| 			'enableSidePanels':	(this.props['featureSet'] != 'EXPIRED') | ||||
| 		}); | ||||
| 		 | ||||
| 		return Clipperz.PM.UI.Components.CardToolbar(cardToolbarProps); | ||||
| 	}, | ||||
|  | ||||
| 	renderExpiredPanel: function () { | ||||
| 		return this.featureSet() == 'EXPIRED' ? Clipperz.PM.UI.Components.ExpiredPanel(this.props) : null; | ||||
| 	}, | ||||
|  | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	viewComponentProps: function () { | ||||
| 		var	result; | ||||
| 		 | ||||
| 		result = this.props['selectedCard']; | ||||
| 		if (result) { | ||||
| 			result['style'] = this.props['style']; | ||||
| 		} | ||||
| 		 | ||||
| 		return result; | ||||
| 	}, | ||||
| 	 | ||||
| 	renderExtraWide: function () { | ||||
| 		return [ | ||||
| 			React.DOM.div({'className':'selection subpanel'}, [Clipperz.PM.UI.Components.Selections(this.props)]), | ||||
| 			React.DOM.div({'className':'cardContent subpanel'}, [ | ||||
| 				this.renderToolbarFrame( | ||||
| 					this.renderCardFrame( | ||||
| 						[Clipperz.PM.UI.Components.Cards.List(this.props)], | ||||
| 						[ | ||||
| 							this.renderExpiredPanel(), | ||||
| 							Clipperz.PM.UI.Components.Cards.View(this.viewComponentProps()) | ||||
| 						] | ||||
| 					) | ||||
| 				) | ||||
| 			]) | ||||
| 		] | ||||
| 	}, | ||||
|  | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	renderWide: function () { | ||||
| 		return [ | ||||
| 			this.renderToolbarFrame( | ||||
| 				this.renderCardFrame( | ||||
| 					[Clipperz.PM.UI.Components.Cards.List(this.props)], | ||||
| 					[ | ||||
| 						this.renderExpiredPanel(), | ||||
| 						Clipperz.PM.UI.Components.Cards.View(this.viewComponentProps()) | ||||
| 					] | ||||
| 				) | ||||
| 			) | ||||
| 		]; | ||||
| 	}, | ||||
|  | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	renderNarrow: function () { | ||||
| 		return this.renderCardFrame( | ||||
| 			this.renderToolbarFrame([ | ||||
| 				this.renderExpiredPanel(), | ||||
| 				Clipperz.PM.UI.Components.Cards.List(this.props), | ||||
| 			]), | ||||
| 			[Clipperz.PM.UI.Components.Cards.View(this.viewComponentProps())] | ||||
| 		); | ||||
| 	}, | ||||
| 	 | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	renderLayout: function (aLayout) { | ||||
| 		var	result; | ||||
| 		 | ||||
| 		if (aLayout == 'extra-wide') { | ||||
| 			result = this.renderExtraWide(); | ||||
| 		} else if (aLayout == 'wide') { | ||||
| 			result = this.renderWide(); | ||||
| 		} else if (aLayout == 'narrow') { | ||||
| 			result = this.renderNarrow(); | ||||
| 		} else if (aLayout == 'extra-short') { | ||||
| 			result = this.renderNarrow(); | ||||
| 		} else { | ||||
| 			Clipperz.Base.exception.raise('UnknownType'); | ||||
| 		} | ||||
| 		 | ||||
| 		return result; | ||||
| 	}, | ||||
|  | ||||
| 	render: function () { | ||||
| //console.log("MainPanel.cards", this.props['cards']); | ||||
| 		var	classes = { | ||||
| 			'panel':	true, | ||||
| 			'left':		this.props['selectionPanelStatus'] == 'OPEN', | ||||
| 			'right':	this.props['settingsPanelStatus']  == 'OPEN', | ||||
| 			'open':		this.props['selectionPanelStatus'] == 'OPEN' || this.props['settingsPanelStatus']  == 'OPEN' | ||||
| 		}; | ||||
| 		classes[this.style()] = true; | ||||
|  | ||||
| 		return	React.DOM.div({'key':'mainPanel', 'id':'mainPanel', 'className':React.addons.classSet(classes)}, [ | ||||
| 			React.DOM.div({'className':'mask', 'onClick': this.handleMaskClick}), | ||||
| 			React.DOM.div({'className':'container'}, | ||||
| //				this.style() == 'extra-wide' ?  this.renderExtraWide() : this.renderOther() | ||||
| 				this.renderLayout(this.style()) | ||||
| 			) | ||||
| 		]); | ||||
| 	} | ||||
|  | ||||
| 	//========================================================================= | ||||
| }); | ||||
| @@ -0,0 +1,49 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| 'use strict'; | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components.Panels'); | ||||
|  | ||||
| Clipperz.PM.UI.Components.Panels.SelectionPanel = React.createClass({ | ||||
|  | ||||
| 	propTypes: { | ||||
| 		selectionPanelStatus:	React.PropTypes.oneOf(['OPEN', 'CLOSED']).isRequired | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	render: function () { | ||||
| //console.log("SelectionPanel", this.props); | ||||
| 		var	classes = React.addons.classSet({ | ||||
| 			'panel': true, | ||||
| 			'left': true, | ||||
| 			'open': this.props['selectionPanelStatus'] == 'OPEN' | ||||
| 		}); | ||||
|  | ||||
| 		return	React.DOM.div({'key':'selectionPanel', 'id':'selectionPanel', 'className':classes}, [ | ||||
| 			Clipperz.PM.UI.Components.Selections(this.props), | ||||
| 		]); | ||||
| 	} | ||||
|  | ||||
| 	//========================================================================= | ||||
| }); | ||||
| @@ -1,88 +0,0 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| Clipperz.PM.UI.Components.PreferencePage = React.createClass({ | ||||
|  | ||||
| 	getDefaultProps: function () { | ||||
| 		return { | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	propTypes: { | ||||
| //		card: React.PropTypes.object.isRequired | ||||
| //		checked: React.PropTypes.boolean.isRequired | ||||
| 	}, | ||||
|  | ||||
| 	getInitialState: function () { | ||||
| //		return { | ||||
| //			shouldStoreDataLocally: false | ||||
| //		}; | ||||
| 	}, | ||||
|  | ||||
| 	handleBackClick: function (anEvent) { | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'goBack'); | ||||
| 	}, | ||||
|  | ||||
| 	toggleShouldStoreDataLocally: function (anEvent) { | ||||
| //		this.setState({shouldStoreDataLocally: !this.state['shouldStoreDataLocally']}); | ||||
| 		Clipperz.PM.DataModel.devicePreferences.setShouldStoreDataLocally(!Clipperz.PM.DataModel.devicePreferences.shouldStoreDataLocally()); | ||||
| 		this.setState({}); | ||||
| 	}, | ||||
|  | ||||
| 	shouldStoreDataLocally: function () { | ||||
| 		return Clipperz.PM.DataModel.devicePreferences.shouldStoreDataLocally(); | ||||
| 	}, | ||||
|  | ||||
| 	syncNow: function (anEvent) { | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'synchronizeLocalData'); | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	render: function () { | ||||
| 		return	React.DOM.div({className:'preferences'}, [ | ||||
| 			React.DOM.div({className:'header'}, [ | ||||
| 				React.DOM.div({className:'titleWrapper'}, React.DOM.div({className:'title'}, "Preferences")), | ||||
| 				React.DOM.div({className:'backWrapper'},  React.DOM.a({className:'button back', onClick:this.handleBackClick}, "back")), | ||||
| 			]), | ||||
| 			React.DOM.div({className:'content'}, [ | ||||
| 				React.DOM.form(null, [ | ||||
| 					React.DOM.div({className:'section'}, [ | ||||
| 						React.DOM.h4(null, "Local storage"), | ||||
| 						React.DOM.p(null, "Store you account data locally for offline viewing"), | ||||
| 						new Clipperz.PM.UI.Components.Checkbox({'id':'shouldStoreLocally_checkbox', 'checked':this.shouldStoreDataLocally(), 'eventHandler':this.toggleShouldStoreDataLocally}), | ||||
| 						this.shouldStoreDataLocally() ? React.DOM.div({className:'syncInfo'}, [ | ||||
| //							React.DOM.h5(null, "data were never synchronized before"), | ||||
| 							React.DOM.a({className:'button', onClick:this.syncNow}, "Sync now") | ||||
| 						]) : null | ||||
| 					]) | ||||
| 				]) | ||||
| 			]), | ||||
| 			React.DOM.div({className:'footer'}, [ | ||||
|  | ||||
| 			]) | ||||
| 		]); | ||||
| 	} | ||||
|  | ||||
| 	//========================================================================= | ||||
| }); | ||||
							
								
								
									
										57
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/Selections.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/Selections.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| 'use strict'; | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components'); | ||||
|  | ||||
| Clipperz.PM.UI.Components.Selections = React.createClass({ | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	selectAll: function (anEvent) { | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'selectAllCards'); | ||||
| 	}, | ||||
| 	 | ||||
| 	selectRecent: function (anEvent) { | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'selectRecentCards'); | ||||
| 	}, | ||||
|  | ||||
| 	render: function () { | ||||
| //console.log("Selections", this.props); | ||||
| 		return	React.DOM.div({'key':'selections', 'id':'selections'}, [ | ||||
| 			React.DOM.ul({'className':'defaultSet'}, [ | ||||
| 				React.DOM.li({'className':'allCards', onClick: this.selectAll}, "All"), | ||||
| 				React.DOM.li({'className':'recentCards', onClick: this.selectRecent},  "Recent") | ||||
| 			]), | ||||
| 			React.DOM.div({'className':'search'}, [ | ||||
| 				React.DOM.form({'className':'searchForm'}, [ | ||||
| 					React.DOM.label({'htmlFor':'searchValue'}, 'search'), | ||||
| 					React.DOM.input({'type':'text', 'id':'searchValue', 'name':'search'}) | ||||
| 				]) | ||||
| 			]), | ||||
| 			React.DOM.ul({'className':'tagList'}, MochiKit.Base.map(function (aTag) { return Clipperz.PM.UI.Components.TagIndexItem({'label':aTag}); }, this.props['tags'] ? this.props['tags'] : [])) | ||||
| 		]); | ||||
| 	} | ||||
|  | ||||
| 	//========================================================================= | ||||
| }); | ||||
							
								
								
									
										45
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/TagIndexItem.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								frontend/delta/js/Clipperz/PM/UI/Components/TagIndexItem.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| 'use strict'; | ||||
| Clipperz.Base.module('Clipperz.PM.UI.Components'); | ||||
|  | ||||
| Clipperz.PM.UI.Components.TagIndexItem = React.createClass({ | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	propTypes: { | ||||
| 		'label':	React.PropTypes.string.isRequired, | ||||
| 	}, | ||||
|  | ||||
| 	handleClick: function (anEvent) { | ||||
| //console.log("TAG INDEX ITEM - handle click TAG", anEvent.target.dataset.tag); | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'tagSelected', anEvent.target.dataset.tag); | ||||
| 	}, | ||||
| 	 | ||||
| 	render: function () { | ||||
| 		return	React.DOM.li({onClick: this.handleClick, 'data-tag':this.props['label']}, this.props['label']); | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
| }); | ||||
| @@ -23,17 +23,17 @@ refer to http://www.clipperz.com. | ||||
|  | ||||
| Clipperz.Base.module('Clipperz.PM.UI'); | ||||
|  | ||||
| Clipperz.PM.UI.DirectLoginRunner = function(args) { | ||||
| Clipperz.PM.UI.DirectLoginController = function(args) { | ||||
| 	this._directLogin	= args['directLogin']		|| Clipperz.Base.exception.raise('MandatoryParameter'); | ||||
| 	this._target		= Clipperz.PM.Crypto.randomKey(); | ||||
|  | ||||
| 	return this; | ||||
| } | ||||
|  | ||||
| MochiKit.Base.update(Clipperz.PM.UI.DirectLoginRunner.prototype, { | ||||
| MochiKit.Base.update(Clipperz.PM.UI.DirectLoginController.prototype, { | ||||
|  | ||||
| 	'toString': function() { | ||||
| 		return "Clipperz.PM.UI.DirectLoginRunner"; | ||||
| 		return "Clipperz.PM.UI.DirectLoginController"; | ||||
| 	}, | ||||
|  | ||||
| 	//----------------------------------------------------------------------------- | ||||
| @@ -237,19 +237,19 @@ MochiKit.Base.update(Clipperz.PM.UI.DirectLoginRunner.prototype, { | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| Clipperz.PM.UI.DirectLoginRunner.openDirectLogin = function (aDirectLogin) { | ||||
| Clipperz.PM.UI.DirectLoginController.openDirectLogin = function (aDirectLogin) { | ||||
| 	var	runner; | ||||
| 	 | ||||
| 	runner = new Clipperz.PM.UI.DirectLoginRunner({directLogin:aDirectLogin}); | ||||
| 	runner = new Clipperz.PM.UI.DirectLoginController({directLogin:aDirectLogin}); | ||||
| 	return runner.run(); | ||||
| }; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| Clipperz.PM.UI.DirectLoginRunner.testDirectLogin = function (aDirectLogin) { | ||||
| Clipperz.PM.UI.DirectLoginController.testDirectLogin = function (aDirectLogin) { | ||||
| 	var	runner; | ||||
|  | ||||
| 	runner = new Clipperz.PM.UI.DirectLoginRunner({directLogin:aDirectLogin}); | ||||
| 	runner = new Clipperz.PM.UI.DirectLoginController({directLogin:aDirectLogin}); | ||||
| 	return runner.test(); | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -21,31 +21,65 @@ refer to http://www.clipperz.com. | ||||
|  | ||||
| */ | ||||
|  | ||||
| "use strict"; | ||||
| Clipperz.Base.module('Clipperz.PM.UI'); | ||||
|  | ||||
| Clipperz.PM.UI.MainController = function() { | ||||
| 	var pages; | ||||
| 	var	genericPageProperties; | ||||
|  | ||||
| //	this._proxy		= null; | ||||
| 	this._mediaQueryStyle = "narrow"; | ||||
| 	this._user		= null; | ||||
| 	this._filter	= ''; | ||||
|  | ||||
| //	this._currentPage = 'loadingPage'; | ||||
| 	this._filter	= {'type':'ALL'}; | ||||
|  | ||||
| 	this._isSelectionPanelOpen = false; | ||||
| 	this._isSettingsPanelOpen = false; | ||||
| 	 | ||||
| 	this._pageStack = ['loadingPage']; | ||||
| 	this._overlay =  new Clipperz.PM.UI.Components.Overlay(); | ||||
| 	pages = { | ||||
| 		'loginPage':		new Clipperz.PM.UI.Components.LoginForm(), | ||||
| 		'registrationPage':	new Clipperz.PM.UI.Components.RegistrationWizard(), | ||||
| 		'cardListPage':		new Clipperz.PM.UI.Components.CardList(), | ||||
| 		'cardDetailPage':	new Clipperz.PM.UI.Components.CardDetail({card: {}}), | ||||
| 		'preferencePage':	new Clipperz.PM.UI.Components.PreferencePage(), | ||||
| 		'errorPage':		new Clipperz.PM.UI.Components.ErrorPage({message:''}) | ||||
| 	}; | ||||
|  | ||||
| 	MochiKit.Base.map(function (anId) {React.renderComponent(pages[anId], MochiKit.DOM.getElement(anId))}, MochiKit.Base.keys(pages)); | ||||
| 	this._pages = pages; | ||||
| 	this.registerForNotificationCenterEvents(); | ||||
| 	this._isTouchDevice = ('ontouchstart' in window || 'onmsgesturechange' in window); | ||||
| 	this._isDesktop = window.screenX != 0 && !this._isTouchDevice; | ||||
| 	this._hasKeyboard = this._isDesktop; | ||||
| 	 | ||||
| 	this._closeMaskAction = null; | ||||
| 	 | ||||
| 	this._pages = {}; | ||||
| 	this.renderPages([ | ||||
| 		'loginPage', | ||||
| 		'registrationPage', | ||||
| 		'mainPage', | ||||
| 		'cardDetailPage', | ||||
| 		'errorPage', | ||||
| 	]); | ||||
|  | ||||
| 	this.registerForNotificationCenterEvents([ | ||||
| 		'doLogin', | ||||
| 		'registerNewUser', | ||||
| 		'showRegistrationForm', | ||||
| 		'goBack', | ||||
| 			 | ||||
| 		'toggleSelectionPanel', | ||||
| 		'toggleSettingsPanel', | ||||
| 			 | ||||
| 		'matchMediaQuery', | ||||
| 		'unmatchMediaQuery', | ||||
| 		 | ||||
| 		'selectAllCards', | ||||
| 		'selectRecentCards', | ||||
| 		'tagSelected', | ||||
| 		 | ||||
| 		'cardSelected', | ||||
| 		 | ||||
| 		'addCardClick', | ||||
| 		'deleteCard', | ||||
| 		'archiveCard', | ||||
| 		'editCard', | ||||
| 		 | ||||
| 		'goBackToMainPage', | ||||
| 		'maskClick', | ||||
| 	]); | ||||
|  | ||||
| 	MochiKit.Signal.connect(MochiKit.DOM.currentDocument(), 'onselectionchange', this, 'selectionChangeHandler'); | ||||
|  | ||||
| 	return this; | ||||
| @@ -125,26 +159,30 @@ console.log("THE BROWSER IS OFFLINE"); | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	registerForNotificationCenterEvents: function () { | ||||
| 		var	events	= [ | ||||
| 			'doLogin', | ||||
| 			'registerNewUser', | ||||
| 			'showRegistrationForm', | ||||
| 			'goBack', | ||||
| 			'showRecord', | ||||
| 			'searchCards', | ||||
| 			'showPreferences', | ||||
| 			'runDirectLogin', | ||||
| 			'synchronizeLocalData' | ||||
| 		]; | ||||
| 		var	self	= this; | ||||
| 	capitaliseFirstLetter: function (aValue) { | ||||
| 	    return aValue.charAt(0).toUpperCase() + aValue.slice(1); | ||||
| 	}, | ||||
| 	 | ||||
| 	renderPages: function (pages) { | ||||
| 		var self = this; | ||||
| 		MochiKit.Iter.forEach(pages, function (aPageName) { | ||||
| //console.log("RENDERING", aPageName); | ||||
| 			self._pages[aPageName] = React.renderComponent( | ||||
| 				Clipperz.PM.UI.Components.Pages[self.capitaliseFirstLetter(aPageName)](self.pageProperties(aPageName)), | ||||
| 				MochiKit.DOM.getElement(aPageName) | ||||
| 			); | ||||
| 		}); | ||||
| 	}, | ||||
|  | ||||
| 		MochiKit.Base.map(function (anEvent) { | ||||
| 			MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, anEvent, MochiKit.Base.method(self, anEvent)); | ||||
| 		}, events); | ||||
| 	registerForNotificationCenterEvents: function (events) { | ||||
| 		var	self = this; | ||||
|  | ||||
| 		MochiKit.Iter.forEach(events, function (anEvent) { | ||||
| 			MochiKit.Signal.connect(Clipperz.Signal.NotificationCenter, anEvent, MochiKit.Base.method(self, anEvent + '_handler')); | ||||
| 		}); | ||||
|  | ||||
| //		MochiKit.Signal.connect(window, 'onpopstate',		MochiKit.Base.method(this, 'historyGoBack')); | ||||
| 		MochiKit.Signal.connect(window, 'onbeforeunload',	MochiKit.Base.method(this, 'shouldExitApp')); | ||||
| //		MochiKit.Signal.connect(window, 'onbeforeunload',	MochiKit.Base.method(this, 'shouldExitApp')); | ||||
| 	}, | ||||
|  | ||||
| 	//------------------------------------------------------------------------- | ||||
| @@ -198,11 +236,13 @@ console.log("THE BROWSER IS OFFLINE"); | ||||
| 		this.pages()['loginPage'].setProps({'mode':this.loginMode(), 'isNewUserRegistrationAvailable':canRegisterNewUsers}); | ||||
|  | ||||
| 		if (shouldShowRegistrationForm) { | ||||
| 			this.showRegistrationForm(); | ||||
| 			this.showRegistrationForm_handler(); | ||||
| 		} else { | ||||
| 			this.showLoginForm(); | ||||
| 		} | ||||
| 		this.overlay().done("", 0.5); | ||||
|  | ||||
| //		this.overlay().done("", 0.5); | ||||
| 		this.overlay().hide(); | ||||
| 	}, | ||||
|  | ||||
| 	//------------------------------------------------------------------------- | ||||
| @@ -216,7 +256,7 @@ console.log("THE BROWSER IS OFFLINE"); | ||||
| 		MochiKit.Async.callLater(0.5, MochiKit.Base.method(loginFormPage, 'setInitialFocus')); | ||||
| 	}, | ||||
|  | ||||
| 	showRegistrationForm: function () { | ||||
| 	showRegistrationForm_handler: function () { | ||||
| 		var currentPage; | ||||
| 		var	registrationPage; | ||||
|  | ||||
| @@ -230,7 +270,12 @@ console.log("THE BROWSER IS OFFLINE"); | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	doLogin: function (event) { | ||||
| 	doLogin_handler: function (event) { | ||||
| 		return this.doLogin(event); | ||||
| 	}, | ||||
| 	 | ||||
| 	doLogin: function (someCredentials) { | ||||
| 		var deferredResult; | ||||
| 		var	credentials; | ||||
| 		var getPassphraseDelegate; | ||||
| 		var	user; | ||||
| @@ -240,10 +285,10 @@ console.log("THE BROWSER IS OFFLINE"); | ||||
| 		this.overlay().show("logging in"); | ||||
| 		this.pages()['loginPage'].setProps({disabled:true}); | ||||
|  | ||||
| 		if ('pin' in event) { | ||||
| 			credentials = Clipperz.PM.PIN.credentialsWithPIN(event['pin']); | ||||
| 		if ('pin' in someCredentials) { | ||||
| 			credentials = Clipperz.PM.PIN.credentialsWithPIN(someCredentials['pin']); | ||||
| 		} else { | ||||
| 			credentials = event; | ||||
| 			credentials = someCredentials; | ||||
| 		} | ||||
| 		getPassphraseDelegate = MochiKit.Base.partial(MochiKit.Async.succeed, credentials.passphrase); | ||||
| 		user = new Clipperz.PM.DataModel.User({'username':credentials.username, 'getPassphraseFunction':getPassphraseDelegate}); | ||||
| @@ -254,18 +299,16 @@ console.log("THE BROWSER IS OFFLINE"); | ||||
| 		deferredResult.addMethod(user, 'login'); | ||||
| 		deferredResult.addMethod(Clipperz.PM.PIN, 'resetFailedAttemptCount'); | ||||
| 		deferredResult.addMethod(this, 'setUser', user); | ||||
|  | ||||
| //		deferredResult.addMethod(this, 'setupApplication'); | ||||
| 		deferredResult.addMethod(this, 'runApplication'); | ||||
| 		deferredResult.addMethod(this.overlay(), 'done', "", 1); | ||||
| 		deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', event)); | ||||
| 		deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', someCredentials)); | ||||
| 		deferredResult.addErrback(MochiKit.Base.bind(function (anEvent, anError) { | ||||
| 			if (anError['isPermanent'] != true) { | ||||
| 				this.pages()['loginPage'].setProps({disabled:false, 'mode':this.loginMode()}); | ||||
| 				this.pages()['loginPage'].setInitialFocus(); | ||||
| 			} | ||||
| 			return anError; | ||||
| 		}, this, event)) | ||||
| 		}, this, someCredentials)) | ||||
| 		deferredResult.callback(); | ||||
|  | ||||
| 		return deferredResult; | ||||
| @@ -273,19 +316,19 @@ console.log("THE BROWSER IS OFFLINE"); | ||||
|  | ||||
| 	//------------------------------------------------------------------------- | ||||
|  | ||||
| 	registerNewUser: function (credentials) { | ||||
| 	registerNewUser_handler: function (credentials) { | ||||
| 		var	deferredResult; | ||||
|  | ||||
| 		this.overlay().show("creating user"); | ||||
|  | ||||
| 		this.pages()['registrationPage'].setProps({disabled:true}); | ||||
| 		deferredResult = new Clipperz.Async.Deferred('MainController.registerNewUser', {trace:false}); | ||||
| 		deferredResult = new Clipperz.Async.Deferred('MainController.registerNewUser', {trace:true}); | ||||
| 		deferredResult.addCallback(Clipperz.PM.DataModel.User.registerNewAccount, | ||||
| 			credentials['username'], | ||||
| 			MochiKit.Base.partial(MochiKit.Async.succeed, credentials['passphrase']) | ||||
| 		); | ||||
| 		deferredResult.addMethod(this, 'doLogin', credentials); | ||||
| 		deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', event)); | ||||
| 		deferredResult.addErrback(MochiKit.Base.method(this, 'genericErrorHandler', credentials)); | ||||
| 		deferredResult.addErrback(MochiKit.Base.bind(function (anError) { | ||||
| 			if (anError['isPermanent'] != true) { | ||||
| 				this.pages()['registrationPage'].setProps({disabled:false}); | ||||
| @@ -307,109 +350,222 @@ console.log("THE BROWSER IS OFFLINE"); | ||||
| 	}, | ||||
|  | ||||
| 	setUser: function (aUser) { | ||||
| console.log("SET USER", aUser); | ||||
| 		this._user = aUser; | ||||
| 		return this._user; | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	allCardInfo: function () { | ||||
| 		var deferredResult; | ||||
| 		var	cardInfo; | ||||
|  | ||||
| 		cardInfo = { | ||||
| 			'_rowObject':			MochiKit.Async.succeed, | ||||
| 			'_reference':			MochiKit.Base.methodcaller('reference'), | ||||
| 			'_searchableContent':	MochiKit.Base.methodcaller('searchableContent'), | ||||
| 			'label':				MochiKit.Base.methodcaller('label'), | ||||
| 			'favicon':				MochiKit.Base.methodcaller('favicon') | ||||
| 		}; | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred('MainController.allCardInfo', {trace:false}); | ||||
| 		deferredResult.addMethod(this.user(), 'getRecords'); | ||||
| 		deferredResult.addCallback(MochiKit.Base.map, Clipperz.Async.collectResults("CardList.value - collectResults", cardInfo, {trace:false})); | ||||
| 		deferredResult.addCallback(Clipperz.Async.collectAll); | ||||
| 		deferredResult.callback(); | ||||
|  | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
| 	filterCards: function (someCardInfo) { | ||||
| 		var filter; | ||||
| 		var	filterRegExp; | ||||
| 		var	result; | ||||
|  | ||||
| 		filter = this.filter().replace(/[^A-Za-z0-9]/g, "\\$&"); | ||||
| 		filterRegExp = new RegExp(filter, "i"); | ||||
| 		result = MochiKit.Base.filter(function (aCardInfo) { return filterRegExp.test(aCardInfo['_searchableContent'])}, someCardInfo); | ||||
|  | ||||
| 		return result; | ||||
| 	}, | ||||
|  | ||||
| 	sortCards: function (someCardInfo) { | ||||
| 		return someCardInfo.sort(Clipperz.Base.caseInsensitiveKeyComparator('label')); | ||||
| 	}, | ||||
|  | ||||
| 	showRecordList: function () { | ||||
| 		var deferredResult; | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred('MainController.showRecordList', {trace:false}); | ||||
| 		deferredResult.addMethod(this, 'allCardInfo'); | ||||
| 		deferredResult.addMethod(this, 'filterCards'); | ||||
| 		deferredResult.addMethod(this, 'sortCards'); | ||||
| 		deferredResult.addCallback(MochiKit.Base.bind(function (someRecordInfo) { | ||||
| 			this.pages()['cardListPage'].setProps({cardList: someRecordInfo}); | ||||
| 		}, this)); | ||||
| 		deferredResult.callback(); | ||||
|  | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
| 	filter: function ()	{ | ||||
| 		return this._filter; | ||||
| 	}, | ||||
|  | ||||
| 	setFilter: function (aValue) { | ||||
| 		this._filter = aValue; | ||||
| 	setFilter: function (aType, aValue) { | ||||
| 		this._filter = {'type':aType, 'value':aValue}; | ||||
| 		return this._filter; | ||||
| 	}, | ||||
|  | ||||
| 	searchCards: function (someParameters) { | ||||
| //console.log("SEARCH CARDS", someParameters); | ||||
| 		this.setFilter(someParameters); | ||||
| 		this.showRecordList(); | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	collectFieldInfo: function (aField) { | ||||
| 		var deferredResult; | ||||
| 		 | ||||
| 		deferredResult = new Clipperz.Async.Deferred('MainController.collectFieldInfo', {trace:false}); | ||||
| 		deferredResult.addMethod(aField, 'reference'); | ||||
| 		deferredResult.setValue('_reference'); | ||||
| 		deferredResult.addMethod(aField, 'label'); | ||||
| 		deferredResult.setValue('label'); | ||||
| 		deferredResult.addMethod(aField, 'value'); | ||||
| 		deferredResult.setValue('value'); | ||||
| 		deferredResult.addMethod(aField, 'actionType'); | ||||
| 		deferredResult.setValue('actionType'); | ||||
| 		deferredResult.addMethod(aField, 'isHidden'); | ||||
| 		deferredResult.setValue('isHidden'); | ||||
| 		deferredResult.values(); | ||||
|  | ||||
| 		deferredResult.callback(); | ||||
| 		 | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
| 	collectDirectLoginInfo: function (aDirectLogin) { | ||||
| 		var deferredResult; | ||||
| 		 | ||||
| 		deferredResult = new Clipperz.Async.Deferred('MainController.collectDirectLoginInfo', {trace:false}); | ||||
| 		deferredResult.addMethod(aDirectLogin, 'reference'); | ||||
| 		deferredResult.setValue('_reference'); | ||||
| 		deferredResult.addMethod(aDirectLogin, 'label'); | ||||
| 		deferredResult.setValue('label'); | ||||
| 		deferredResult.addMethod(aDirectLogin, 'favicon'); | ||||
| 		deferredResult.setValue('favicon'); | ||||
| 		deferredResult.values(); | ||||
|  | ||||
| 	runApplication: function () { | ||||
| 		MochiKit.Signal.connect(window, 'onpopstate',	MochiKit.Base.method(this, 'historyGoBack')); | ||||
| ///		TODO: remove this TEST HACK | ||||
| 		this.moveInPage(this.currentPage(), 'cardListPage'); | ||||
| 		return this.showRecordList(); | ||||
| 		deferredResult.callback(); | ||||
| 		 | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
| 	 | ||||
| 	collectRecordInfo: function (aRecord) { | ||||
| 		var deferredResult; | ||||
| 		 | ||||
| 		deferredResult = new Clipperz.Async.Deferred('MainController.collectRecordInfo', {trace:false}); | ||||
| 		deferredResult.addMethod(aRecord, 'reference'); | ||||
| 		deferredResult.setValue('_reference'); | ||||
| 		deferredResult.addMethod(aRecord, 'label'); | ||||
| 		deferredResult.setValue('label'); | ||||
| 		deferredResult.addMethod(aRecord, 'notes'); | ||||
| 		deferredResult.setValue('notes'); | ||||
| 		deferredResult.addMethod(aRecord, 'tags'); | ||||
| 		deferredResult.setValue('tags'); | ||||
|  | ||||
| //		this.moveInPage(this.currentPage(), 'preferencePage'); | ||||
| 		deferredResult.addMethod(aRecord, 'fields'); | ||||
| 		deferredResult.addCallback(MochiKit.Base.values); | ||||
| 		deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'collectFieldInfo')); | ||||
| 		deferredResult.addCallback(Clipperz.Async.collectAll); | ||||
| 		deferredResult.setValue('fields'); | ||||
|  | ||||
| 		deferredResult.addMethod(aRecord, 'directLogins'); | ||||
| 		deferredResult.addCallback(MochiKit.Base.values); | ||||
| 		deferredResult.addCallback(MochiKit.Base.map, MochiKit.Base.method(this, 'collectDirectLoginInfo')); | ||||
| 		deferredResult.addCallback(Clipperz.Async.collectAll); | ||||
| 		deferredResult.setValue('directLogins'); | ||||
|  | ||||
| 		deferredResult.values(); | ||||
|  | ||||
| 		deferredResult.callback(); | ||||
| 		 | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
| 	showRecord: function (aRecordReference) { | ||||
| //console.log("Show Record", aRecordReference); | ||||
| 		var	deferredResult; | ||||
| 	updateSelectedCard: function (someInfo) { | ||||
| 		var deferredResult; | ||||
|  | ||||
| 		this.pages()['cardListPage'].setProps({selectedCard:aRecordReference}); | ||||
| 		deferredResult = new Clipperz.Async.Deferred('MainController.runApplication', {trace:false}); | ||||
| 		deferredResult.addMethod(this.user(), 'getRecord', aRecordReference); | ||||
| 		deferredResult.addMethodcaller('content'); | ||||
| 		deferredResult.addCallback(MochiKit.Base.bind(function (aCard) { | ||||
| //console.log("CARD DETAILS", aCard); | ||||
| 			this.pages()['cardDetailPage'].setProps({card: aCard}); | ||||
| 			this.pages()['cardListPage'].setProps({selectedCard: null}); | ||||
| 		if (someInfo == null) { | ||||
| 			this.setPageProperties('mainPage', 'selectedCard', {}); | ||||
| 			deferredResult = MochiKit.Async.succeed(); | ||||
| 		} else { | ||||
| 			this.setPageProperties('mainPage', 'selectedCard', {'loading':true, 'label':someInfo['label'], '_reference':someInfo['reference']}); | ||||
|  | ||||
| 			deferredResult = new Clipperz.Async.Deferred('MainController.updateSelectedCard', {trace:false}); | ||||
| 			deferredResult.addMethod(this.user(), 'getRecord', someInfo['reference']); | ||||
| 			deferredResult.addMethod(this, 'collectRecordInfo'); | ||||
|  | ||||
| //console.log("MEDIA QUERY STYLE", this.mediaQueryStyle()); | ||||
| 			deferredResult.addMethod(this, 'setPageProperties', 'mainPage', 'selectedCard'); | ||||
| 			if (this.mediaQueryStyle() == 'narrow') { | ||||
| 				deferredResult.addMethod(this, 'setPageProperties', 'cardDetailPage', 'selectedCard'); | ||||
| 				deferredResult.addMethod(this, 'moveInPage', this.currentPage(), 'cardDetailPage'); | ||||
| //				deferredResult.addCallback(function (aValue) { console.log("SHOULD SLIDE IN PAGE DETAIL"); return aValue; }); | ||||
| //console.log("SHOULD SLIDE IN PAGE DETAIL"); | ||||
| 			} | ||||
| 		 | ||||
| 			MochiKit.Async.callLater(0.1, MochiKit.Base.method(deferredResult, 'callback')); | ||||
| 		} | ||||
|  | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
| 	//............................................................................ | ||||
|  | ||||
| 	regExpFilterGenerator: function (aRegExp, aSearchField) { | ||||
| 		var	searchField = aSearchField ? aSearchField : Clipperz.PM.DataModel.Record.defaultSearchField; | ||||
| 		 | ||||
| 		return function (aCardInfo) { | ||||
| 			aRegExp.lastIndex = 0; | ||||
| 			return aRegExp.test(aCardInfo[searchField]); | ||||
| 		} | ||||
| 	}, | ||||
| 	 | ||||
| 	selectedCardReference: function () { | ||||
| 		return	this.pages()['mainPage'].props &&  | ||||
| 				this.pages()['mainPage'].props['selectedCard'] && | ||||
| 				this.pages()['mainPage'].props['selectedCard'] && | ||||
| 				this.pages()['mainPage'].props['selectedCard']['_reference'] | ||||
| 			?	this.pages()['mainPage'].props['selectedCard']['_reference'] | ||||
| 			:	''; | ||||
| 	}, | ||||
|  | ||||
| 	isSelectedCardStillVisible: function (someCards) { | ||||
| 		var	result; | ||||
| 		var	reference; | ||||
| 		 | ||||
| 		reference = this.selectedCardReference(); | ||||
| 		result = MochiKit.Iter.some(someCards, function (aCardInfo) { | ||||
| 			return aCardInfo['_reference'] == reference; | ||||
| 		}); | ||||
| 		 | ||||
| 		return result; | ||||
| 	}, | ||||
|  | ||||
| 	updateSelectedCards: function (shouldIncludeArchivedCards, aFilter) { | ||||
| 		var deferredResult; | ||||
| 		var	sortCriteria; | ||||
|  | ||||
| 		sortCriteria = Clipperz.Base.caseInsensitiveKeyComparator('label'); | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred('MainController.setFilter', {trace:false}); | ||||
| 		deferredResult.addMethod(this.user(), 'getRecordsInfo', Clipperz.PM.DataModel.Record.defaultCardInfo, shouldIncludeArchivedCards); | ||||
|  | ||||
| 		if (aFilter['type'] == 'ALL') { | ||||
| 			deferredResult.addMethodcaller('sort', sortCriteria); | ||||
| 		} else if (aFilter['type'] == 'RECENT') { | ||||
| 			deferredResult.addMethodcaller('sort', Clipperz.Base.reverseComparator(MochiKit.Base.keyComparator('accessDate'))); | ||||
| 			deferredResult.addCallback(function (someCards) { return someCards.slice(0, 9)}); | ||||
| 		} else if (aFilter['type'] == 'SEARCH') { | ||||
| 			deferredResult.addCallback(MochiKit.Base.filter, this.regExpFilterGenerator(Clipperz.PM.DataModel.Record.regExpForSearch(aFilter['value']))); | ||||
| 			deferredResult.addMethodcaller('sort', sortCriteria); | ||||
| 		} else if (aFilter['type'] == 'TAG') { | ||||
| 			deferredResult.addCallback(MochiKit.Base.filter, this.regExpFilterGenerator(Clipperz.PM.DataModel.Record.regExpForTag(aFilter['value']))); | ||||
| 			deferredResult.addMethodcaller('sort', sortCriteria); | ||||
| 		} | ||||
|  | ||||
| 		deferredResult.addMethod(this, 'setPageProperties', 'mainPage', 'cards'); | ||||
| 		deferredResult.addCallback(MochiKit.Base.bind(function (someCards) { | ||||
| 			if (!this.isSelectedCardStillVisible(someCards)) { | ||||
| 				this.updateSelectedCard(null); | ||||
| 			}; | ||||
| 		}, this)); | ||||
| 		deferredResult.addMethod(this, 'moveInPage', this.currentPage(), 'cardDetailPage', true); | ||||
| 		deferredResult.addMethod(this, 'setPageProperties', 'mainPage', 'filter', this.filter()); | ||||
|  | ||||
| 		deferredResult.callback(); | ||||
|  | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
| 	 | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	setPageProperties: function (aPageName, aKey, aValue) { | ||||
| 		var	props = {}; | ||||
| 		props[aKey] = aValue; | ||||
| 		this.pages()[aPageName].setProps(props); | ||||
| 		 | ||||
| 		return aValue; | ||||
| 	}, | ||||
|  | ||||
| 	renderAccountData: function () { | ||||
| 		var deferredResult; | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred('MainController.renderAccountData', {trace:false}); | ||||
| 		deferredResult.addMethod(this, 'setFilter', 'ALL'); | ||||
| 		deferredResult.addMethod(this, 'updateSelectedCards', false); | ||||
| 		 | ||||
| 		deferredResult.addMethod(this.user(), 'getTags'); | ||||
| 		deferredResult.addMethodcaller('sort', Clipperz.Base.caseInsensitiveCompare); | ||||
| 		deferredResult.addMethod(this, 'setPageProperties', 'mainPage', 'tags'); | ||||
| 		deferredResult.callback(); | ||||
|  | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
| 	runDirectLogin: function (someParameters) { | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	runApplication: function (anUser) { | ||||
| 		this.moveInPage(this.currentPage(), 'mainPage'); | ||||
| 		return this.renderAccountData(); | ||||
| 	}, | ||||
| /* | ||||
| 	runDirectLogin_handler: function (someParameters) { | ||||
| //console.log("RUN DIRECT LOGIN", someParameters); | ||||
| 		var	deferredResult; | ||||
|  | ||||
| @@ -427,10 +583,18 @@ console.log("THE BROWSER IS OFFLINE"); | ||||
| 		anEvent.preventDefault(); | ||||
| 		anEvent.stopPropagation(); | ||||
| 	}, | ||||
|  | ||||
| */ | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	showPreferences: function (anEvent) { | ||||
| /* | ||||
| 	searchCards_handler: function (someParameters) { | ||||
| //console.log("SEARCH CARDS", someParameters); | ||||
| 		this.setFilter(someParameters); | ||||
| 		this.renderAccountData(); | ||||
| 	}, | ||||
| */ | ||||
| 	//========================================================================= | ||||
| /* | ||||
| 	showPreferences_handler: function (anEvent) { | ||||
| 		var	deferredResult; | ||||
|  | ||||
| 		this.pages()['preferencePage'].setProps({}); | ||||
| @@ -440,7 +604,7 @@ console.log("THE BROWSER IS OFFLINE"); | ||||
|  | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
| */ | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	genericErrorHandler: function (anEvent, anError) { | ||||
| @@ -471,39 +635,35 @@ console.log("THE BROWSER IS OFFLINE"); | ||||
|  | ||||
| 	slidePage: function (fromPage, toPage, direction) { | ||||
| 		var	fromPosition; | ||||
| 		var toPosition; | ||||
| 		var	toPosition; | ||||
| 		var	itemToTransition; | ||||
|  | ||||
| 		if (direction == "LEFT") { | ||||
| 			fromPosition = 'right'; | ||||
| 			toPosition = 'left' | ||||
| 			toPosition = 'left'; | ||||
| 			itemToTransition = toPage; | ||||
| 		} else { | ||||
| 			fromPosition = 'left'; | ||||
| 			toPosition = 'right' | ||||
| 			toPosition = 'right'; | ||||
| 			itemToTransition = fromPage; | ||||
| 		} | ||||
|  | ||||
| 		MochiKit.DOM.addElementClass(fromPage, toPosition + ' transition'); | ||||
| 		MochiKit.DOM.addElementClass(itemToTransition, 'transition'); | ||||
|  | ||||
| 		MochiKit.DOM.addElementClass(toPage, fromPosition); | ||||
| 		MochiKit.DOM.removeElementClass(toPage, toPosition); | ||||
| 		MochiKit.DOM.addElementClass(toPage, 'transition'); | ||||
| 		MochiKit.Async.callLater(0.1, function () { | ||||
| 		MochiKit.Async.callLater(0, function () { | ||||
| 			MochiKit.DOM.addElementClass(fromPage, toPosition); | ||||
| 			MochiKit.DOM.removeElementClass(toPage, fromPosition); | ||||
| 		}) | ||||
|  | ||||
| 		MochiKit.Async.callLater(0.5, function () { | ||||
| 			MochiKit.DOM.removeElementClass(fromPage, 'transition'); | ||||
| 			MochiKit.DOM.removeElementClass(toPage, 'transition'); | ||||
| 			MochiKit.DOM.removeElementClass(itemToTransition, 'transition'); | ||||
| 		}) | ||||
| 	}, | ||||
|  | ||||
| 	rotateInPage: function (fromPage, toPage) { | ||||
| 		//	Broken! :( | ||||
| 		MochiKit.DOM.addElementClass(MochiKit.DOM.getElement('mainDiv'), 'show-right'); | ||||
| 	}, | ||||
|  | ||||
| 	//......................................................................... | ||||
|  | ||||
| 	goBack: function () { | ||||
| 	goBack_handler: function () { | ||||
| 		var	fromPage; | ||||
| 		var toPage; | ||||
|  | ||||
| @@ -525,6 +685,7 @@ console.log("THE BROWSER IS OFFLINE"); | ||||
|  | ||||
| 	setCurrentPage: function (aPage) { | ||||
| 		this.pageStack().unshift(aPage); | ||||
| 		this.refreshCurrentPage(); | ||||
| 	}, | ||||
|  | ||||
| 	moveInPage: function (fromPage, toPage, addToHistory) { | ||||
| @@ -552,12 +713,108 @@ console.log("THE BROWSER IS OFFLINE"); | ||||
| 		this.setCurrentPage(toPage); | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
| 	//------------------------------------------------------------------------- | ||||
|  | ||||
| 	synchronizeLocalData: function (anEvent) { | ||||
| 	messageBoxContent: function () { | ||||
| 		var	message; | ||||
| 		var	level; | ||||
| 		 | ||||
| 		message = ""; | ||||
| 		level = 'HIDE'; | ||||
| 		 | ||||
| //console.log("messageBox - this.user()", this.user()); | ||||
| 		if (this.user() != null && this.user().accountInfo() != null && this.user().accountInfo().featureSet() == 'EXPIRED') { | ||||
| 			message = "Exprired subscription"; | ||||
| 			level = 'ERROR'; | ||||
| 		} | ||||
|  | ||||
| 		return { | ||||
| 			'message': message, | ||||
| 			'level': level | ||||
| 		}; | ||||
| 	}, | ||||
|  | ||||
| 	userAccountInfo: function () { | ||||
| 		var	result; | ||||
| 		 | ||||
| 		result = {}; | ||||
| 		 | ||||
| 		if (this.user() != null) { | ||||
| 			var	usefulFields = [ | ||||
| 				'currentSubscriptionType', | ||||
| 				'expirationDate', | ||||
| 				'featureSet', | ||||
| 				'isExpired', | ||||
| 				'isExpiring', | ||||
| 				'paymentVerificationPending' | ||||
| 			]; | ||||
| 			 | ||||
| 			var	attributes = this.user().accountInfo()._attributes; | ||||
| 			MochiKit.Iter.forEach(usefulFields, function (aFieldName) { | ||||
| 				result[aFieldName] = attributes[aFieldName]; | ||||
| 			}) | ||||
| 		}; | ||||
| 		 | ||||
| 		return result; | ||||
| 	}, | ||||
| 	 | ||||
| 	genericPageProperties: function () { | ||||
| 		return { | ||||
| 			'style':			this.mediaQueryStyle(), | ||||
| 		    'isTouchDevice':	this.isTouchDevice(), | ||||
| 		    'isDesktop':		this.isDesktop(), | ||||
| 			'hasKeyboard':		this.hasKeyboard() | ||||
| 		}; | ||||
| 	}, | ||||
| 	 | ||||
| 	pageProperties: function (aPageName) { | ||||
| 		var	result; | ||||
| 		var	extraProperties = null; | ||||
| 		 | ||||
| 		result = this.genericPageProperties(); | ||||
|  | ||||
| 		if (aPageName == 'loginPage') { | ||||
| 			extraProperties = { | ||||
| 				'mode':								'CREDENTIALS', | ||||
| 				'isNewUserRegistrationAvailable':	true, | ||||
| 				'disabled':							false, | ||||
| 			}; | ||||
| 		} else if (aPageName == 'registrationPage') { | ||||
| 		} else if (aPageName == 'mainPage') { | ||||
| 			extraProperties = { | ||||
| 				'messageBox':			this.messageBoxContent(), | ||||
| 				'accountStatus':		this.userAccountInfo(), | ||||
| 				'selectionPanelStatus':	this.isSelectionPanelOpen()	? 'OPEN' : 'CLOSED', | ||||
| 				'settingsPanelStatus':	this.isSettingsPanelOpen()	? 'OPEN' : 'CLOSED', | ||||
| //				'cards':				…, | ||||
| //				'tags':					…, | ||||
| //				'selectedCard':			…, | ||||
| 			}; | ||||
| 		} else if (aPageName == 'errorPage') { | ||||
| 			extraProperties = { | ||||
| 				'message': '' | ||||
| 			}; | ||||
| 		} | ||||
| 		 | ||||
| 		if (extraProperties != null) { | ||||
| 			result = MochiKit.Base.update(result, extraProperties); | ||||
| 		} | ||||
| //console.log("MainController.pageProperties", result); | ||||
| 		return result; | ||||
| 	}, | ||||
| 	 | ||||
| 	refreshCurrentPage: function () { | ||||
| 		if (this.pages()[this.currentPage()] != null) { | ||||
| 			this.pages()[this.currentPage()].setProps(this.pageProperties(this.currentPage())); | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	//========================================================================= | ||||
| /* | ||||
| 	synchronizeLocalData_handler: function (anEvent) { | ||||
| 		var	deferredResult; | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred('MainController.synchronizeLocalData', {trace:true}); | ||||
| 		deferredResult = new Clipperz.Async.Deferred('MainController.synchronizeLocalData', {trace:false}); | ||||
| //		deferredResult.addMethod(this.proxy(), 'message', 'downloadAccountData', {}); | ||||
| 		deferredResult.addMethod(this.user().connection(), 'message', 'downloadAccountData', {}); | ||||
| 		deferredResult.addCallback(function (aResult) { | ||||
| @@ -570,8 +827,126 @@ console.log("THE BROWSER IS OFFLINE"); | ||||
|  | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
| */ | ||||
| 	 | ||||
| 	//========================================================================= | ||||
|  | ||||
| 	resetPanels: function () { | ||||
| 		this._isSelectionPanelOpen = false; | ||||
| 		this._isSettingsPanelOpen = false; | ||||
| 	}, | ||||
|  | ||||
| 	isSelectionPanelOpen: function () { | ||||
| 		return this._isSelectionPanelOpen; | ||||
| 	}, | ||||
| 	 | ||||
| 	 | ||||
| 	toggleSelectionPanel_handler: function (anEvent) { | ||||
| 		this._isSelectionPanelOpen = !this._isSelectionPanelOpen; | ||||
| 		this.setCloseMaskAction(MochiKit.Base.method(this, 'toggleSelectionPanel_handler')); | ||||
| 		this.refreshCurrentPage(); | ||||
| 	}, | ||||
| 	 | ||||
|  | ||||
| 	isSettingsPanelOpen: function () { | ||||
| 		return this._isSettingsPanelOpen; | ||||
| 	}, | ||||
| 	 | ||||
| 	toggleSettingsPanel_handler: function (anEvent) { | ||||
| 		this._isSettingsPanelOpen = !this._isSettingsPanelOpen; | ||||
| 		this.setCloseMaskAction(MochiKit.Base.method(this, 'toggleSettingsPanel_handler')); | ||||
| 		this.refreshCurrentPage(); | ||||
| 	}, | ||||
|  | ||||
| 	cardSelected_handler: function (aReference) { | ||||
| 		this.updateSelectedCard(aReference); | ||||
| 	}, | ||||
|  | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	addCardClick_handler: function () { | ||||
| console.log("ADD CARD CLICK"); | ||||
| 	}, | ||||
|  | ||||
| 	deleteCard_handler: function (anEvent) { | ||||
| console.log("DELETE CARD", anEvent['reference']); | ||||
| 	}, | ||||
| 	 | ||||
| 	archiveCard_handler: function (anEvent) { | ||||
| console.log("ARCHIVE CARD", anEvent['reference']); | ||||
| 	}, | ||||
|  | ||||
| 	editCard_handler: function (anEvent) { | ||||
| console.log("EDIT CARD", anEvent['reference']); | ||||
| 	}, | ||||
|  | ||||
| 	goBackToMainPage_handler: function (anEvent) { | ||||
| 		this.updateSelectedCard(); | ||||
| 		this.moveOutPage(this.currentPage(), 'mainPage'); | ||||
| 	}, | ||||
|  | ||||
| 	//============================================================================ | ||||
|  | ||||
| 	selectAllCards_handler: function () { | ||||
| 		this.setFilter('ALL'); | ||||
| 		this.updateSelectedCards(false, this.filter()); | ||||
| 	}, | ||||
| 	 | ||||
| 	selectRecentCards_handler: function () { | ||||
| 		this.setFilter('RECENT'); | ||||
| 		this.updateSelectedCards(false, this.filter()); | ||||
| 	}, | ||||
|  | ||||
| 	tagSelected_handler: function (aTag) { | ||||
| 		this.setFilter('TAG', aTag); | ||||
| 		this.updateSelectedCards(false, this.filter()); | ||||
| 	}, | ||||
| 	 | ||||
| 	//---------------------------------------------------------------------------- | ||||
| 	 | ||||
| 	setCloseMaskAction: function (aFunction) { | ||||
| 		this._closeMaskAction = aFunction; | ||||
| 	}, | ||||
| 	 | ||||
| 	maskClick_handler: function () { | ||||
| 		this._closeMaskAction.apply(this); | ||||
| 		this._closeMaskAction = null; | ||||
| 	}, | ||||
|  | ||||
| 	//============================================================================ | ||||
|  | ||||
| 	matchMediaQuery_handler: function (newQueryStyle) { | ||||
| 		this._mediaQueryStyle = newQueryStyle; | ||||
|  | ||||
| 		if (this.currentPage() == 'cardDetailPage') { | ||||
| 			this.moveOutPage(this.currentPage(), 'mainPage'); | ||||
| 		} | ||||
| 		this.resetPanels(); | ||||
| 		this.refreshCurrentPage(); | ||||
| 	}, | ||||
|  | ||||
| 	unmatchMediaQuery_handler: function (queryStyle) { | ||||
| 	}, | ||||
|  | ||||
| 	mediaQueryStyle: function () { | ||||
| 		return this._mediaQueryStyle; | ||||
| 	}, | ||||
|  | ||||
| 	//---------------------------------------------------------------------------- | ||||
|  | ||||
| 	isTouchDevice: function () { | ||||
| 		return this._isTouchDevice; | ||||
| 	}, | ||||
| 	 | ||||
| 	isDesktop: function () { | ||||
| 		return this._isDesktop; | ||||
| 	}, | ||||
|  | ||||
| 	hasKeyboard: function () { | ||||
| 		return this._hasKeyboard; | ||||
| 	}, | ||||
| 	 | ||||
| 	//============================================================================ | ||||
| /* | ||||
| 	wrongAppVersion: function (anError) { | ||||
| //		this.pages()['errorPage'].setProps({message:anError.message}); | ||||
|   | ||||
							
								
								
									
										261
									
								
								frontend/delta/js/OnMediaQuery/onmediaquery-0.2.0.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										261
									
								
								frontend/delta/js/OnMediaQuery/onmediaquery-0.2.0.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,261 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| /* | ||||
|  * onMediaQuery | ||||
|  * http://springload.co.nz/love-the-web/ | ||||
|  * | ||||
|  * Copyright 2012, Springload | ||||
|  * Released under the MIT license. | ||||
|  * http://www.opensource.org/licenses/mit-license.php | ||||
|  * | ||||
|  * Date: Fri 24 October, 2012 | ||||
|  */ | ||||
|  | ||||
| ;(function (root, factory) { | ||||
|     if (typeof define === 'function' && define.amd) { | ||||
|         // AMD. Register as an anonymous module. | ||||
|         define(function () { | ||||
|             // Also create a global in case some scripts | ||||
|             // that are loaded still are looking for | ||||
|             // a global even when an AMD loader is in use. | ||||
|             return (root.MQ = factory(root, root.MQ || {})); | ||||
|         }); | ||||
|     } else { | ||||
|         // Browser globals | ||||
|         root.MQ = factory(root, root.MQ || {}); | ||||
|     } | ||||
| }(this, function(mq) { | ||||
|     /** | ||||
|      * Initialises the MQ object and sets the initial media query callbacks | ||||
|      * @returns Void(0) | ||||
|      */ | ||||
|     mq.init = function(query_array) { | ||||
|  | ||||
|          // Container for all callbacks registered with the plugin | ||||
|         this.callbacks = []; | ||||
|         this.context = ''; //current active query | ||||
|         this.new_context = ''; //current active query to be read inside callbacks, as this.context won't be set when they're called! | ||||
|  | ||||
|         if (typeof(query_array) !== 'undefined' ) { | ||||
|             for (i = 0; i < query_array.length; i++) { | ||||
|                 var r = this.addQuery(query_array[i]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Add a listener to the window.resize event, pass mq/self as the scope. | ||||
|         this.addEvent(window, 'resize', mq.listenForChange, mq); | ||||
|  | ||||
|         // Figure out which query is active on load. | ||||
|         this.listenForChange(); | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Binds to the window.onResize and checks for media query changes | ||||
|      * @returns Void(0) | ||||
|      */ | ||||
|     mq.listenForChange = function() { | ||||
|         var query_string; | ||||
|  | ||||
|         // Get the value of html { font-family } from the element style. | ||||
|         if (document.documentElement.currentStyle) { | ||||
|             query_string = document.documentElement.currentStyle["fontFamily"]; | ||||
|         } | ||||
|  | ||||
|         if (window.getComputedStyle) { | ||||
|             query_string = window.getComputedStyle(document.documentElement,null).getPropertyValue('font-family'); | ||||
|         } | ||||
|  | ||||
|         // No support for CSS enumeration? Return and avoid errors. | ||||
|         if (query_string === null) return; | ||||
|  | ||||
|         // Android browsers place a "," after an item in the font family list. | ||||
|         // Most browsers either single or double quote the string. | ||||
|         query_string = query_string.replace(/['",]/g, ''); | ||||
|  | ||||
|         if (query_string !== this.context) { | ||||
|             this.new_context = query_string; | ||||
|             this.triggerCallbacks(this.context, 'unmatch'); | ||||
|             this.triggerCallbacks(this.new_context, 'match'); | ||||
|         } | ||||
|  | ||||
|         this.context = this.new_context; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Attach a new query to test. | ||||
|      * @param query_object { | ||||
|      *     context: ['some_media_query','some_other_media_query'], | ||||
|      *     call_for_each_context: true, | ||||
|      *     callback: function() { | ||||
|      *         //something awesome | ||||
|      *     } | ||||
|      * } | ||||
|      * @returns A reference to the query_object that was added | ||||
|      */ | ||||
|     mq.addQuery = function(query_object) { | ||||
|         if (query_object === null || query_object === undefined) return; | ||||
|  | ||||
|         this.callbacks.push(query_object); | ||||
|          | ||||
|         // If the context is passed as a string, turn it into an array (for unified approach elsewhere in the code) | ||||
|         if (typeof(query_object.context) == "string") { | ||||
|             query_object.context = [query_object.context]; | ||||
|         } | ||||
|          | ||||
|         // See if "call_for_each_context" is set, if not, set a default (for unified approach elsewhere in the code) | ||||
|         if (typeof(query_object.call_for_each_context) !== "boolean") { | ||||
|             query_object.call_for_each_context = true; // Default | ||||
|         } | ||||
|          | ||||
|         // Fire the added callback if it matches the current context | ||||
|         if (this.context !== '' && this._inArray(this.context, query_object.context)) { | ||||
|             query_object.match(); | ||||
|         } | ||||
|          | ||||
|         return this.callbacks[ this.callbacks.length - 1]; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Remove a query_object by reference. | ||||
|      * @returns Void(0) | ||||
|      */ | ||||
|     mq.removeQuery = function(query_object) { | ||||
|         if (query_object === null || query_object === undefined) return; | ||||
|  | ||||
|         var match = -1; | ||||
|  | ||||
|         while ((match = mq._indexOf(query_object,this.callbacks)) > -1) { | ||||
|             this.callbacks.splice(match, 1); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Loop through the stored callbacks and execute | ||||
|      * the ones that are bound to the current context. | ||||
|      * @returns Void(0) | ||||
|      */ | ||||
|     mq.triggerCallbacks = function(size, key) { | ||||
|         var i, callback_function, call_for_each_context; | ||||
|  | ||||
|         for (i = 0; i < this.callbacks.length; i++) { | ||||
|  | ||||
|             // Don't call for each context? | ||||
|             if(this.callbacks[i].call_for_each_context === false) { | ||||
|                 if ((key === 'match' && this._inArray(this.context, this.callbacks[i].context)) || | ||||
|                     (key === 'unmatch' && this._inArray(this.new_context, this.callbacks[i].context))) { | ||||
|                     // Was previously called, and we don't want to call it for each context | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             callback_function = this.callbacks[i][key]; | ||||
|             if (this._inArray(size, this.callbacks[i].context) && callback_function !== undefined) { | ||||
|                 callback_function(); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Swiss Army Knife event binding, in lieu of jQuery. | ||||
|      * @returns Void(0) | ||||
|      */ | ||||
|     mq.addEvent = function(elem, type, eventHandle, eventContext) { | ||||
|         if (elem === null || elem === undefined) return; | ||||
|         // If the browser supports event listeners, use them. | ||||
|         if (elem.addEventListener) { | ||||
|             elem.addEventListener(type, function() { eventHandle.call(eventContext); }, false); | ||||
|         } else if (elem.attachEvent ) { | ||||
|             elem.attachEvent("on" + type, function() {  eventHandle.call(eventContext); }); | ||||
|              | ||||
|         // Otherwise, replace the current thing bound to on[whatever]! Consider refactoring. | ||||
|         } else { | ||||
|             elem["on" + type] = function() { eventHandle.call(eventContext); }; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Function to return the mediaquery's previous context | ||||
|      * @returns String returns the current mediaquery's context | ||||
|      */ | ||||
|     mq.getPreviousContext = function() | ||||
|     { | ||||
|         return this.context; | ||||
|     }; | ||||
|  | ||||
|     /** | ||||
|      * Function to return the mediaquery's current context | ||||
|      * @returns String returns the current mediaquery's context | ||||
|      */ | ||||
|     mq.getContext = function() | ||||
|     { | ||||
|         return this.new_context; | ||||
|     }; | ||||
|      | ||||
|     /** | ||||
|      * Internal helper function that checks wether "needle" occurs in "haystack" | ||||
|      * @param needle Mixed Value to look for in haystack array | ||||
|      * @param haystack Array Haystack array to search in | ||||
|      * @returns Boolan True if the needle occurs, false otherwise | ||||
|      */ | ||||
|     mq._inArray = function(needle, haystack) | ||||
|     { | ||||
|         var length = haystack.length; | ||||
|         for(var i = 0; i < length; i++) { | ||||
|             if(haystack[i] == needle) return true; | ||||
|         } | ||||
|         return false; | ||||
|     }; | ||||
|      | ||||
|     /** | ||||
|      * IE8 do not supports Array.properties.indexOf | ||||
|      * copy from jQuery. | ||||
|      * in lieu of jQuery. | ||||
|      * @returns int | ||||
|      */ | ||||
|     mq._indexOf = function( elem, arr, i )  | ||||
|     { | ||||
|         var len; | ||||
|         if ( arr ) { | ||||
|             if ( arr.indexOf ) { | ||||
|                 return arr.indexOf( elem, i ); | ||||
|             } | ||||
|              | ||||
|             len = arr.length; | ||||
|             i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; | ||||
|              | ||||
|             for ( ; i < len; i++ ) { | ||||
|                 // Skip accessing in sparse arrays | ||||
|                 if ( i in arr && arr[ i ] === elem ) { | ||||
|                     return i; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     // Expose the functions. | ||||
|     return mq; | ||||
| })); | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										20258
									
								
								frontend/delta/js/React/react-with-addons-0.11.0.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										20258
									
								
								frontend/delta/js/React/react-with-addons-0.11.0.js
									
									
									
									
									
										Executable file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										948
									
								
								frontend/delta/js/TestData/User.data.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										948
									
								
								frontend/delta/js/TestData/User.data.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -44,12 +44,27 @@ MochiKit.Logging.logError("## MainController - GENERIC ERROR" + "\n" + "==>> " + | ||||
| React.initializeTouchEvents(true); | ||||
|  | ||||
| Clipperz.PM.RunTime = {}; | ||||
| function run() { | ||||
|  | ||||
| function initOnMediaQuery () { | ||||
| 	MQ.init(MochiKit.Base.map(function (queryStyle) { | ||||
| 		return { | ||||
| 			context: queryStyle, | ||||
| 			match: function () { | ||||
| 				MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'matchMediaQuery', queryStyle); | ||||
| 			}, | ||||
| 			unmatch: function () { | ||||
| 				MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'unmatchMediaQuery', queryStyle); | ||||
| 			}, | ||||
| 		} | ||||
| //	}, ['extra-short', 'narrow', 'wide', 'extra-wide'])); | ||||
| 	}, Clipperz_PM_UI_availableStyles)); | ||||
| } | ||||
|  | ||||
| function run () { | ||||
| 	var parameters = {}; | ||||
|  | ||||
| 	Clipperz.PM.Strings.Languages.initSetup(); | ||||
|  | ||||
|  | ||||
| 	if ((window.location.search.indexOf('registration') != -1) || (window.location.hash.indexOf('registration') != -1)) { | ||||
| 		parameters['shouldShowRegistrationForm'] = true; | ||||
| 	} else { | ||||
| @@ -59,7 +74,29 @@ function run() { | ||||
| 	Clipperz.PM.DataModel.devicePreferences = new Clipperz.PM.DataModel.DevicePreferences({}); | ||||
|  | ||||
| 	Clipperz.PM.RunTime.mainController = new Clipperz.PM.UI.MainController(); | ||||
| 	initOnMediaQuery(); | ||||
| 	Clipperz.PM.RunTime.mainController.run(parameters); | ||||
| } | ||||
|  | ||||
| MochiKit.DOM.addLoadEvent(run); | ||||
|  | ||||
| /* * / | ||||
| MochiKit.DOM.addLoadEvent(simulateLogin); | ||||
| function simulateLogin () { | ||||
| 	var getURLParameter = function (name) { | ||||
| 		return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search)||[,""])[1].replace(/\+/g, '%20'))||null; | ||||
| 	} | ||||
| 	 | ||||
| 	Clipperz.Crypto.PRNG.defaultRandomGenerator().fastEntropyAccumulationForTestingPurpose(); | ||||
| 	 | ||||
| //	MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'doLogin', {username:'joe', passphrase:'clipperz'});	//	FULL | ||||
| //	http://localhost:8888/delta/index.html?username=joe&passphrase=clipperz | ||||
|  | ||||
| //	MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'doLogin', {username:';', passphrase:';'});			//	EXPIRED | ||||
| //	http://localhost:8888/delta/index.html?username=%3B&passphrase=%3B | ||||
|  | ||||
| 	if ((getURLParameter('u') != null) && (getURLParameter('p'))) { | ||||
| 		MochiKit.Signal.signal(Clipperz.Signal.NotificationCenter, 'doLogin', {username:getURLParameter('u'), passphrase:getURLParameter('p')}); | ||||
| 	} | ||||
| } | ||||
| / * */ | ||||
| @@ -7,7 +7,7 @@ | ||||
| # MochiKit (http://www.mochikit.com) | ||||
| 	- repository: @mochikit.repository@ (version: @mochikit.version@ - commit: @mochikit.commit@) | ||||
|  | ||||
| 	* Software licence: https://github.com/mochi/mochikit/blob/master/LICENSE.txt | ||||
| 	* Software license: https://github.com/mochi/mochikit/blob/master/LICENSE.txt | ||||
|  | ||||
| 	|	MochiKit is dual-licensed software.  It is available under the terms of the | ||||
| 	|	MIT License, or the Academic Free License version 2.1.  The full text of | ||||
| @@ -207,7 +207,7 @@ | ||||
| # React.js (http://facebook.github.io/react/) | ||||
| 	- repository: @reactjs.repository@ (version: @reactjs.version@ - commit: @reactjs.commit@) | ||||
|  | ||||
| 	* Software licence: https://github.com/facebook/react/blob/master/LICENSE | ||||
| 	* Software license: https://github.com/facebook/react/blob/master/LICENSE | ||||
|  | ||||
| 	|	                              Apache License | ||||
| 	|	                        Version 2.0, January 2004 | ||||
| @@ -413,10 +413,61 @@ | ||||
|  | ||||
|  | ||||
|  | ||||
| # Modernizr (http://modernizr.com) | ||||
| 	- repository: @modernizr.repository@ (version: @modernizr.version@ - commit: @modernizr.commit@) | ||||
|  | ||||
| 	* Software license: http://modernizr.com/license/ | ||||
|  | ||||
| 	|	Copyright (c) 2009–2013 | ||||
| 	|	Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| 	|	of this software and associated documentation files (the "Software"), to deal | ||||
| 	|	in the Software without restriction, including without limitation the rights | ||||
| 	|	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| 	|	copies of the Software, and to permit persons to whom the Software is | ||||
| 	|	furnished to do so, subject to the following conditions: | ||||
| 	|	The above copyright notice and this permission notice shall be included in | ||||
| 	|	all copies or substantial portions of the Software. | ||||
| 	|	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| 	|	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| 	|	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| 	|	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| 	|	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| 	|	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| 	|	THE SOFTWARE. | ||||
|  | ||||
|  | ||||
| # OnMediaQuery (https://github.com/JoshBarr/on-media-query) | ||||
| 	- repository: @onmediaquery.repository@ (version: @onmediaquery.version@ - commit: @onmediaquery.commit@) | ||||
|  | ||||
| 	* Software license: http://opensource.org/licenses/mit-license.php | ||||
|  | ||||
| 	|	The MIT License (MIT) | ||||
| 	|	 | ||||
| 	|	Copyright (c) <year> <copyright holders> | ||||
| 	|	 | ||||
| 	|	Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
| 	|	of this software and associated documentation files (the "Software"), to deal | ||||
| 	|	in the Software without restriction, including without limitation the rights | ||||
| 	|	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
| 	|	copies of the Software, and to permit persons to whom the Software is | ||||
| 	|	furnished to do so, subject to the following conditions: | ||||
| 	|	 | ||||
| 	|	The above copyright notice and this permission notice shall be included in | ||||
| 	|	all copies or substantial portions of the Software. | ||||
| 	|	 | ||||
| 	|	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
| 	|	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
| 	|	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
| 	|	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
| 	|	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
| 	|	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
| 	|	THE SOFTWARE. | ||||
|  | ||||
|  | ||||
| # Add to Home Screen (http://cubiq.org/add-to-home-screen) | ||||
| 	- repository: @addtohomescreen.repository@ (version: @addtohomescreen.version@ - commit: @addtohomescreen.commit@) | ||||
|  | ||||
| 	* Software licence: https://github.com/facebook/react/blob/master/LICENSE | ||||
| 	* Software license: https://github.com/facebook/react/blob/master/LICENSE | ||||
|  | ||||
| 	|	This software is released under the MIT License. | ||||
| 	|	 | ||||
| @@ -447,7 +498,7 @@ | ||||
| 	 | ||||
| 	Copyright © 2005-2006 Yahoo! Inc. All rights reserved | ||||
| 	* Copyright notes:  http://docs.yahoo.com/info/copyright/copyright.html | ||||
| 	* Software licence: http://developer.yahoo.com/yui/license.txt | ||||
| 	* Software license: http://developer.yahoo.com/yui/license.txt | ||||
|  | ||||
| 	|	Software License Agreement (BSD License) | ||||
| 	| | ||||
| @@ -485,7 +536,7 @@ | ||||
| # YUI-ext (http://www.yui-ext.com) | ||||
| 	- repository: http://yui-ext.googlecode.com/svn/trunk/ (revision: 120) | ||||
|  | ||||
| 	* Software licence: http://yui-ext.googlecode.com/svn/trunk/src/licence.txt | ||||
| 	* Software license: http://yui-ext.googlecode.com/svn/trunk/src/licence.txt | ||||
|  | ||||
| 	|	yui-ext | ||||
| 	|	Copyright (c) 2006, Jack Slocum | ||||
|   | ||||
| @@ -5,9 +5,17 @@ | ||||
| 		"mochikit.commit":				"6f26f745d5d915540aa0fc6c34fda24952891a9d", | ||||
|  | ||||
| 		"reactjs.repository":			"https://github.com/facebook/react.git", | ||||
| 		"reactjs.version":				"0.4.1", | ||||
| 		"reactjs.commit":				"0cac12d375264a8a232a426d6d6cc8074a94000a", | ||||
| 		"reactjs.version":				"0.11.0", | ||||
| 		"reactjs.commit":				"95d82cacd6e9cc6a2fe6366d79510cc9133886cb", | ||||
|  | ||||
| 		"modernizr.repository":			"https://github.com/Modernizr/Modernizr", | ||||
| 		"modernizr.version":			"2.8.2", | ||||
| 		"modernizr.commit":				"99c09fa23a83f160a021c98b3644628aaec5e37a", | ||||
|  | ||||
| 		"onmediaquery.repository":		"https://github.com/JoshBarr/on-media-query", | ||||
| 		"onmediaquery.version":			"0.2.0", | ||||
| 		"onmediaquery.commit":			"5080914636d392781ac858fb8eca9c0d99e5d35c", | ||||
| 		 | ||||
| 		"addtohomescreen.repository":	"https://github.com/cubiq/add-to-homescreen.git", | ||||
| 		"addtohomescreen.version":		"2.0.8", | ||||
| 		"addtohomescreen.commit":		"4d375840079bcea994cc5795a568802400c7a793" | ||||
| @@ -31,13 +39,14 @@ | ||||
| 		"MochiKit/Selector.js", | ||||
| 		"-- MochiKit/Visual.js", | ||||
|  | ||||
| 		"-- React/react-0.4.1.js", | ||||
| 		"React/react-0.5.0-alpha.js", | ||||
| 		"React/react-with-addons-0.11.0.js", | ||||
|  | ||||
| 		"-- Hammer/hammer-1.0.5.js", | ||||
| 		 | ||||
| 		"Cubiq/add2home.js", | ||||
| 		"-- Cubiq/add2home.js", | ||||
| 		"-- Modernizr/modernizr-2.8.2.js", | ||||
| 		"OnMediaQuery/onmediaquery-0.2.0.js", | ||||
|  | ||||
| 		"-- IT WOULD BE NICE TO BE ABLE TO GET RID OF THESE IMPORTS", | ||||
| 		"Clipperz/YUI/Utils.js", | ||||
| 		"Clipperz/YUI/DomHelper.js", | ||||
|  | ||||
| @@ -45,14 +54,14 @@ | ||||
| 		"Clipperz/Base.js", | ||||
| 		"Clipperz/Async.js", | ||||
| 		"Clipperz/CSVProcessor.js", | ||||
| 		"Clipperz/KeePassExportProcessor.js", | ||||
| 		"-- Clipperz/KeePassExportProcessor.js", | ||||
| 		"Clipperz/Date.js", | ||||
| 		"Clipperz/DOM.js", | ||||
| 		"-- Clipperz/DOM.js", | ||||
| 		"Clipperz/Logging.js", | ||||
| 		"Clipperz/Signal.js", | ||||
| 		"-- Clipperz/Style.js", | ||||
| 		"-- Clipperz/Visual.js", | ||||
| 		"Clipperz/Set.js", | ||||
| 		"-- Clipperz/Set.js", | ||||
| 		"-- Clipperz/Profile.js", | ||||
| 		"Clipperz/KeyValueObjectStore.js", | ||||
|  | ||||
| @@ -104,7 +113,7 @@ | ||||
| 		"Clipperz/PM/DataModel/User.Header.RecordIndex.js", | ||||
| 		"Clipperz/PM/DataModel/User.Header.Preferences.js", | ||||
| 		"Clipperz/PM/DataModel/User.Header.OneTimePasswords.js", | ||||
| 		"Clipperz/PM/DataModel/User.Subscription.js", | ||||
| 		"Clipperz/PM/DataModel/User.AccountInfo.js", | ||||
| 		"Clipperz/PM/DataModel/Record.js", | ||||
| 		"Clipperz/PM/DataModel/Record.Version.js", | ||||
| 		"Clipperz/PM/DataModel/Record.Version.Field.js", | ||||
| @@ -124,21 +133,42 @@ | ||||
| 		"-- Clipperz/PM/UI/Web/Controllers/MainController.js", | ||||
|  | ||||
| 		"Clipperz/PM/UI/Components/Overlay.js", | ||||
| 		"Clipperz/PM/UI/Components/Button.js", | ||||
| 		"Clipperz/PM/UI/Components/Checkbox.js", | ||||
| 		"Clipperz/PM/UI/Components/PageTemplate.js", | ||||
| 		"Clipperz/PM/UI/Components/LoginForm.js", | ||||
| 		"Clipperz/PM/UI/Components/RegistrationWizard.js", | ||||
| 		"Clipperz/PM/UI/Components/CardList.js", | ||||
| 		"Clipperz/PM/UI/Components/CardDetail.js", | ||||
| 		"Clipperz/PM/UI/Components/PreferencePage.js", | ||||
| 		"Clipperz/PM/UI/Components/ErrorPage.js", | ||||
| 		"Clipperz/PM/UI/Components/CardToolbar.js", | ||||
| 		"Clipperz/PM/UI/Components/MessageBox.js", | ||||
| 		"Clipperz/PM/UI/Components/Selections.js", | ||||
| 		"Clipperz/PM/UI/Components/TagIndexItem.js", | ||||
|  | ||||
| 		"Clipperz/PM/UI/Components/ExpiredPanel.js", | ||||
|  | ||||
| 		"Clipperz/PM/UI/Components/Pages/LoginPage.js", | ||||
| 		"Clipperz/PM/UI/Components/Pages/RegistrationPage.js", | ||||
| 		"Clipperz/PM/UI/Components/Pages/MainPage.js", | ||||
| 		"Clipperz/PM/UI/Components/Pages/CardDetailPage.js", | ||||
| 		"Clipperz/PM/UI/Components/Pages/ErrorPage.js", | ||||
|  | ||||
| 		"Clipperz/PM/UI/Components/Panels/SelectionPanel.js", | ||||
| 		"Clipperz/PM/UI/Components/Panels/MainPanel.js", | ||||
| 		"Clipperz/PM/UI/Components/Panels/ExtraFeaturesPanel.js", | ||||
|  | ||||
| 		"Clipperz/PM/UI/Components/Cards/List.js", | ||||
| 		"Clipperz/PM/UI/Components/Cards/View.js", | ||||
| 		"Clipperz/PM/UI/Components/Cards/Toolbar.js", | ||||
|  | ||||
| 		"Clipperz/PM/UI/Components/AccountStatus.js", | ||||
|  | ||||
| 		"Clipperz/PM/UI/MainController.js", | ||||
| 		"-- Clipperz/PM/UI/MainDesktopController.js", | ||||
| 		"Clipperz/PM/UI/DirectLoginController.js", | ||||
| 		"main.js" | ||||
| 	], | ||||
|  | ||||
| 	"css": [ | ||||
| 		"web.css" | ||||
| 		"clipperz.css" | ||||
| 	], | ||||
|  | ||||
| 	"scss": [ | ||||
| 		"clipperz.scss" | ||||
| 	] | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| CACHE MANIFEST | ||||
| # 2013-10-01:v0.0.1 | ||||
| # @application.version@ | ||||
|  | ||||
| CACHE: | ||||
| # - Explicitly cached 'master entries'. | ||||
| index.html | ||||
| #index.html | ||||
|  | ||||
| NETWORK: | ||||
| # - Resources that require the user to be online. | ||||
|   | ||||
							
								
								
									
										35
									
								
								frontend/delta/scss/clipperz.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								frontend/delta/scss/clipperz.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| @import "core/reset"; | ||||
| @import "core/palette"; | ||||
| @import "core/parameters"; | ||||
| @import "core/fonts"; | ||||
| @import "core/flex"; | ||||
| @import "core/overlay"; | ||||
| @import "core/behavior"; | ||||
| @import "core/layout"; | ||||
|  | ||||
| @import "style/loadingPage"; | ||||
| @import "style/loginPage"; | ||||
| @import "style/registrationPage"; | ||||
| @import "style/selectionPanel"; | ||||
| @import "style/settingsPanel"; | ||||
| @import "style/accountStatus"; | ||||
| @import "style/card"; | ||||
|  | ||||
| //---------------------------------------------------------------------------- | ||||
|  | ||||
| body { | ||||
| 	font-family: "clipperz-font"; | ||||
| 	margin: 0; | ||||
| 	padding: 0; | ||||
| } | ||||
|  | ||||
| body:after { | ||||
| 	display: none; | ||||
| } | ||||
|  | ||||
| @import "core/sizes"; | ||||
|  | ||||
| //@import "sizes/narrow"; | ||||
| //@import "sizes/wide"; | ||||
| //@import "sizes/extra-wide"; | ||||
| //@import "sizes/extra-short"; | ||||
							
								
								
									
										205
									
								
								frontend/delta/scss/core/behavior.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										205
									
								
								frontend/delta/scss/core/behavior.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,205 @@ | ||||
| //	https://github.com/h5bp/Effeckt.css | ||||
| //	http://coenraets.org/blog/2013/03/hardware-accelerated-page-transitions-for-mobile-web-apps-phonegap-apps/ | ||||
|  | ||||
| $transition-duration: 0.5s; | ||||
|  | ||||
| @mixin pageElement () { | ||||
| 	position: absolute; | ||||
|  | ||||
| 	top: 0; | ||||
| 	left: 0; | ||||
| 	width: 100%; | ||||
| 	height: 100%; | ||||
| 	overflow: hidden; | ||||
|  | ||||
| 	@include transform3d(0, 0, 0); | ||||
| 	@include transition-duration($transition-duration); | ||||
|  | ||||
| 	&.left { | ||||
| 		@include transform3d(-100%, 0, 0); | ||||
| 	} | ||||
|  | ||||
| 	&.right { | ||||
| 		@include transform3d(100%, 0, 0); | ||||
| 		visibility: hidden; | ||||
| 		display: none; | ||||
| 		 | ||||
| 		&.transition { | ||||
| 			visibility: visible; | ||||
| 			display: block; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| //============================================================================= | ||||
|  | ||||
| @mixin sliding-panel-left ($size) { | ||||
| //	background-color: yellow; | ||||
|  | ||||
| 	width: $size; | ||||
| 	height: 100%; | ||||
| 	 | ||||
| 	top: 0; | ||||
| 	left: -$size; | ||||
| } | ||||
|  | ||||
| @mixin sliding-panel-right ($size) { | ||||
| //	background-color: green; | ||||
|  | ||||
| 	width: $size; | ||||
| 	height: 100%; | ||||
|  | ||||
| 	top: 0; | ||||
| 	right: -$size; | ||||
| } | ||||
|  | ||||
| @mixin sliding-panel ($side, $size) { | ||||
| 	position: fixed; | ||||
| 	z-index: 20; | ||||
| 	overflow: scroll; | ||||
|  | ||||
| 	@if $side == left { | ||||
| 		@include sliding-panel-left($size); | ||||
| 	} | ||||
|  | ||||
| 	@if $side == right { | ||||
| 		@include sliding-panel-right($size); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| //............................................................................. | ||||
|  | ||||
| @mixin sliding-panel-open ($side, $size) { | ||||
| 	@if $side == left { | ||||
| 		left: 0px; | ||||
| 	} | ||||
|  | ||||
| 	@if $side == right { | ||||
| 		right: 0px; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| //............................................................................. | ||||
|  | ||||
| @mixin sliding-panel-wrapper-open-left ($size) { | ||||
| 	top: 0; | ||||
| 	left: $size; | ||||
| } | ||||
|  | ||||
| @mixin sliding-panel-wrapper-open-right ($size) { | ||||
| 	top: 0; | ||||
| 	right: $size; | ||||
| } | ||||
|  | ||||
| @mixin sliding-panel-wrapper-open ($side, $size) { | ||||
| 	@include sliding-panel-wrapper(); | ||||
| 	 | ||||
| 	@if $side == left { | ||||
| 		@include sliding-panel-wrapper-open-left($size); | ||||
| 	} | ||||
|  | ||||
| 	@if $side == right { | ||||
| 		@include sliding-panel-wrapper-open-right($size); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| //............................................................................. | ||||
|  | ||||
| @mixin sliding-panel-wrapper () { | ||||
| 	width: 100%; | ||||
| 	margin: 0 auto; | ||||
| 	position: relative; | ||||
| 	z-index: 10; | ||||
| //	top: 0; | ||||
| //	left: 0; | ||||
| //	@include transition(all, $transition_time); | ||||
| } | ||||
|  | ||||
| @mixin sliding-panel-container () { | ||||
| 	width: 100%; | ||||
| 	height: 100%; | ||||
| 	margin: 0 auto; | ||||
| } | ||||
|  | ||||
| //############################################################################# | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| /* | ||||
| .registrationForm { | ||||
| 	.steps { | ||||
| 		.step { | ||||
| 			position: absolute; | ||||
|  | ||||
| //			top: 0; | ||||
| //			left: 0; | ||||
| //			width: 100%; | ||||
| //			height: 100%; | ||||
|  | ||||
| 			.slide(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| */ | ||||
|  | ||||
| //---------------------------------------------------------------------- | ||||
| //	tentative 3D transformations | ||||
| /* | ||||
| .page { | ||||
| 	transform: rotateY(   0deg) translateZ( 100px); | ||||
|  | ||||
| 	&.left { | ||||
|  		transform: rotateY( -90deg) translateZ( 100px); | ||||
| 	} | ||||
|  | ||||
| 	&.center { | ||||
| 		transform: rotateY(   0deg) translateZ( 100px); | ||||
| 	} | ||||
|  | ||||
| 	&.right { | ||||
|  		transform: rotateY(  90deg) translateZ( 100px); | ||||
|  	} | ||||
| } | ||||
|  | ||||
| #mainDiv { | ||||
| 	width: 100%; | ||||
| 	height: 100%; | ||||
| 	position: absolute; | ||||
| 	transform-style: preserve-3d; | ||||
|  | ||||
| 	transition: transform 3s; | ||||
|  | ||||
| 	&.show-front  { transform: translateZ( -100px ) rotateY(    0deg ); } | ||||
| 	&.show-back   { transform: translateZ( -100px ) rotateX( -180deg ); } | ||||
| 	&.show-right  { transform: translateZ( -100px ) rotateY(  -90deg ); } | ||||
| 	&.show-left   { transform: translateZ( -100px ) rotateY(   90deg ); } | ||||
| 	&.show-top    { transform: translateZ( -100px ) rotateX(  -90deg ); } | ||||
| 	&.show-bottom { transform: translateZ( -100px ) rotateX(   90deg ); } | ||||
| } | ||||
| */ | ||||
| //======================================================================= | ||||
|  | ||||
|  | ||||
| //======================================================================= | ||||
|  | ||||
|  | ||||
| //======================================================================= | ||||
							
								
								
									
										395
									
								
								frontend/delta/scss/core/flex.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										395
									
								
								frontend/delta/scss/core/flex.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,395 @@ | ||||
| //	Downloaded on June 8, 2014 from https://raw.githubusercontent.com/mastastealth/sass-flex-mixin/master/flex.scss | ||||
|  | ||||
| // Flexbox Mixins | ||||
| // http://philipwalton.github.io/solved-by-flexbox/ | ||||
| // https://github.com/philipwalton/solved-by-flexbox | ||||
| //  | ||||
| // Copyright (c) 2013 Brian Franco | ||||
| // | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a | ||||
| // copy of this software and associated documentation files (the | ||||
| // "Software"), to deal in the Software without restriction, including | ||||
| // without limitation the rights to use, copy, modify, merge, publish, | ||||
| // distribute, sublicense, and/or sell copies of the Software, and to | ||||
| // permit persons to whom the Software is furnished to do so, subject to | ||||
| // the following conditions: | ||||
| // The above copyright notice and this permission notice shall be included | ||||
| // in all copies or substantial portions of the Software. | ||||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | ||||
| // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
| // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | ||||
| // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | ||||
| // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | ||||
| // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | ||||
| // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
| // | ||||
| // This is a set of mixins for those who want to mess around with flexbox | ||||
| // using the native support of current browsers. For full support table | ||||
| // check: http://caniuse.com/flexbox | ||||
| // | ||||
| // Basically this will use: | ||||
| // | ||||
| // * Fallback, old syntax (IE10, Safari, mobile webkit browsers) | ||||
| // * Prefixed standard syntax (Chrome) | ||||
| // * Final standards syntax (FF, IE11, Opera 12.1) | ||||
| // | ||||
| // This was inspired by: | ||||
| //  | ||||
| // * http://dev.opera.com/articles/view/advanced-cross-browser-flexbox/ | ||||
| //  | ||||
| // With help from: | ||||
| //  | ||||
| // * http://w3.org/tr/css3-flexbox/ | ||||
| // * http://the-echoplex.net/flexyboxes/ | ||||
| // * http://msdn.microsoft.com/en-us/library/ie/hh772069(v=vs.85).aspx | ||||
| // * http://css-tricks.com/using-flexbox/ | ||||
| // * http://dev.opera.com/articles/view/advanced-cross-browser-flexbox/ | ||||
| // * https://developer.mozilla.org/en-us/docs/web/guide/css/flexible_boxes | ||||
|  | ||||
| //---------------------------------------------------------------------- | ||||
|  | ||||
| // Flexbox Containers | ||||
| // | ||||
| // The 'flex' value causes an element to generate a block-level flex | ||||
| // container box. | ||||
| // | ||||
| // The 'inline-flex' value causes an element to generate a inline-level | ||||
| // flex container box.  | ||||
| // | ||||
| // display: flex | inline-flex | ||||
| // | ||||
| // http://w3.org/tr/css3-flexbox/#flex-containers | ||||
| // | ||||
| // (Placeholder selectors for each type, for those who rather @extend) | ||||
|  | ||||
| @mixin flexbox { | ||||
| 	display: -webkit-box; | ||||
| 	display: -webkit-flex; | ||||
| 	display: -moz-flex; | ||||
| 	display: -ms-flexbox; | ||||
| 	display: flex; | ||||
| } | ||||
|  | ||||
| %flexbox { @include flexbox; } | ||||
|  | ||||
| //---------------------------------- | ||||
|  | ||||
| @mixin inline-flex { | ||||
| 	display: -webkit-inline-box; | ||||
| 	display: -webkit-inline-flex; | ||||
| 	display: -moz-inline-flex; | ||||
| 	display: -ms-inline-flexbox; | ||||
| 	display: inline-flex; | ||||
| } | ||||
|  | ||||
| %inline-flex { @include inline-flex; } | ||||
|  | ||||
| //---------------------------------------------------------------------- | ||||
|  | ||||
| // Flexbox Direction | ||||
| // | ||||
| // The 'flex-direction' property specifies how flex items are placed in | ||||
| // the flex container, by setting the direction of the flex container's | ||||
| // main axis. This determines the direction that flex items are laid out in.  | ||||
| // | ||||
| // Values: row | row-reverse | column | column-reverse | ||||
| // Default: row | ||||
| // | ||||
| // http://w3.org/tr/css3-flexbox/#flex-direction-property | ||||
|  | ||||
| @mixin flex-direction($value: row) { | ||||
| 	@if $value == row-reverse { | ||||
| 		-webkit-box-direction: reverse; | ||||
| 		-webkit-box-orient: horizontal; | ||||
| 	} @else if $value == column { | ||||
| 		-webkit-box-direction: normal; | ||||
| 		-webkit-box-orient: vertical; | ||||
| 	} @else if $value == column-reverse { | ||||
| 		-webkit-box-direction: reverse; | ||||
| 		-webkit-box-orient: vertical; | ||||
| 	} @else { | ||||
| 		-webkit-box-direction: normal; | ||||
| 		-webkit-box-orient: horizontal; | ||||
| 	} | ||||
| 	-webkit-flex-direction: $value; | ||||
| 	-moz-flex-direction: $value; | ||||
| 	-ms-flex-direction: $value; | ||||
| 	flex-direction: $value; | ||||
| } | ||||
| 	// Shorter version: | ||||
| 	@mixin flex-dir($value: false) { @include flex-direction($value); } | ||||
|  | ||||
| //---------------------------------------------------------------------- | ||||
|  | ||||
| // Flexbox Wrap | ||||
| // | ||||
| // The 'flex-wrap' property controls whether the flex container is single-line | ||||
| // or multi-line, and the direction of the cross-axis, which determines | ||||
| // the direction new lines are stacked in.  | ||||
| // | ||||
| // Values: nowrap | wrap | wrap-reverse | ||||
| // Default: nowrap | ||||
| // | ||||
| // http://w3.org/tr/css3-flexbox/#flex-wrap-property | ||||
|  | ||||
| @mixin flex-wrap($value: nowrap) { | ||||
| 	// No Webkit Box fallback. | ||||
| 	-webkit-flex-wrap: $value; | ||||
| 	-moz-flex-wrap: $value; | ||||
| 	@if $value == nowrap { | ||||
| 		-ms-flex-wrap: none; | ||||
| 	} @else {  | ||||
| 		-ms-flex-wrap: $value;  | ||||
| 	} | ||||
| 	flex-wrap: $value; | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------------- | ||||
|  | ||||
| // Flexbox Flow (shorthand) | ||||
| // | ||||
| // The 'flex-flow' property is a shorthand for setting the 'flex-direction' | ||||
| // and 'flex-wrap' properties, which together define the flex container's | ||||
| // main and cross axes. | ||||
| // | ||||
| // Values: <flex-direction> | <flex-wrap>  | ||||
| // Default: row nowrap | ||||
| // | ||||
| // http://w3.org/tr/css3-flexbox/#flex-flow-property | ||||
|  | ||||
| @mixin flex-flow($values: (row nowrap)) { | ||||
| 	// No Webkit Box fallback. | ||||
| 	-webkit-flex-flow: $values; | ||||
| 	-moz-flex-flow: $values; | ||||
| 	-ms-flex-flow: $values; | ||||
| 	flex-flow: $values; | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------------- | ||||
|  | ||||
| // Flexbox Order | ||||
| // | ||||
| // The 'order' property controls the order in which flex items appear within | ||||
| // their flex container, by assigning them to ordinal groups. | ||||
| // | ||||
| // Default: 0 | ||||
| // | ||||
| // http://w3.org/tr/css3-flexbox/#order-property | ||||
|  | ||||
| @mixin order($int: 0) { | ||||
| 	-webkit-box-ordinal-group: $int + 1; | ||||
| 	-webkit-order: $int; | ||||
| 	-moz-order: $int; | ||||
| 	-ms-flex-order: $int; | ||||
| 	order: $int; | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------------- | ||||
|  | ||||
| // Flexbox Grow | ||||
| // | ||||
| // The 'flex-grow' property sets the flex grow factor. Negative numbers | ||||
| // are invalid. | ||||
| // | ||||
| // Default: 0 | ||||
| // | ||||
| // http://w3.org/tr/css3-flexbox/#flex-grow-property | ||||
|  | ||||
| @mixin flex-grow($int: 0) { | ||||
| 	-webkit-box-flex: $int; | ||||
| 	-webkit-flex-grow: $int; | ||||
| 	-moz-flex-grow: $int; | ||||
| 	-ms-flex-positive: $int; | ||||
| 	flex-grow: $int; | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------------- | ||||
|  | ||||
| // Flexbox Shrink | ||||
| // | ||||
| // The 'flex-shrink' property sets the flex shrink factor. Negative numbers | ||||
| // are invalid. | ||||
| // | ||||
| // Default: 1 | ||||
| // | ||||
| // http://w3.org/tr/css3-flexbox/#flex-shrink-property | ||||
|  | ||||
| @mixin flex-shrink($int: 1) { | ||||
| 	-webkit-flex-shrink: $int; | ||||
| 	-moz-flex-shrink: $int; | ||||
| 	-ms-flex-negative: $int; | ||||
| 	flex-shrink: $int; | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------------- | ||||
|  | ||||
| // Flexbox Basis | ||||
| // | ||||
| // The 'flex-basis' property sets the flex basis. Negative lengths are invalid.  | ||||
| // | ||||
| // Values: Like "width"  | ||||
| // Default: auto | ||||
| // | ||||
| // http://www.w3.org/TR/css3-flexbox/#flex-basis-property | ||||
|  | ||||
| @mixin flex-basis($value: auto) { | ||||
| 	-webkit-flex-basis: $value; | ||||
| 	-moz-flex-basis: $value; | ||||
| 	-ms-flex-preferred-size: $value; | ||||
| 	flex-basis: $value; | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------------- | ||||
|  | ||||
| // Flexbox "Flex" (shorthand) | ||||
| // | ||||
| // The 'flex' property specifies the components of a flexible length: the | ||||
| // flex grow factor and flex shrink factor, and the flex basis. When an | ||||
| // element is a flex item, 'flex' is consulted instead of the main size | ||||
| // property to determine the main size of the element. If an element is | ||||
| // not a flex item, 'flex' has no effect. | ||||
| // | ||||
| // Values: none | <flex-grow> <flex-shrink> || <flex-basis> | ||||
| // Default: See individual properties (1 1 0). | ||||
| // | ||||
| // http://w3.org/tr/css3-flexbox/#flex-property | ||||
|  | ||||
| @mixin flex($fg: 1, $fs: null, $fb: null) { | ||||
|      | ||||
| 	// Set a variable to be used by box-flex properties | ||||
| 	$fg-boxflex: $fg; | ||||
|  | ||||
| 	// Box-Flex only supports a flex-grow value so let's grab the | ||||
| 	// first item in the list and just return that. | ||||
| 	@if type-of($fg) == 'list' { | ||||
| 		$fg-boxflex: nth($fg, 1); | ||||
| 	} | ||||
|  | ||||
| 	-webkit-box-flex: $fg-boxflex; | ||||
| 	-webkit-flex: $fg $fs $fb; | ||||
| 	-moz-box-flex: $fg-boxflex; | ||||
| 	-moz-flex: $fg $fs $fb; | ||||
| 	-ms-flex: $fg $fs $fb; | ||||
| 	flex: $fg $fs $fb; | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------------- | ||||
|  | ||||
| // Flexbox Justify Content | ||||
| // | ||||
| // The 'justify-content' property aligns flex items along the main axis | ||||
| // of the current line of the flex container. This is done after any flexible | ||||
| // lengths and any auto margins have been resolved. Typically it helps distribute | ||||
| // extra free space leftover when either all the flex items on a line are | ||||
| // inflexible, or are flexible but have reached their maximum size. It also | ||||
| // exerts some control over the alignment of items when they overflow the line. | ||||
| // | ||||
| // Note: 'space-*' values not supported in older syntaxes. | ||||
| // | ||||
| // Values: flex-start | flex-end | center | space-between | space-around | ||||
| // Default: flex-start | ||||
| // | ||||
| // http://w3.org/tr/css3-flexbox/#justify-content-property | ||||
|  | ||||
| @mixin justify-content($value: flex-start) { | ||||
| 	@if $value == flex-start { | ||||
| 		-webkit-box-pack: start; | ||||
| 		-ms-flex-pack: start; | ||||
| 	} @else if $value == flex-end { | ||||
| 		-webkit-box-pack: end; | ||||
| 		-ms-flex-pack: end; | ||||
| 	} @else if $value == space-between { | ||||
| 		-webkit-box-pack: justify; | ||||
| 		-ms-flex-pack: justify; | ||||
| 	} @else { | ||||
| 		-webkit-box-pack: $value; | ||||
| 		-ms-flex-pack: $value; | ||||
| 	} | ||||
| 	-webkit-justify-content: $value; | ||||
| 	-moz-justify-content: $value; | ||||
| 	justify-content: $value; | ||||
| } | ||||
| 	// Shorter version: | ||||
| 	@mixin flex-just($value: flex-start) { @include justify-content($value); } | ||||
|  | ||||
| //---------------------------------------------------------------------- | ||||
|  | ||||
| // Flexbox Align Items | ||||
| // | ||||
| // Flex items can be aligned in the cross axis of the current line of the | ||||
| // flex container, similar to 'justify-content' but in the perpendicular | ||||
| // direction. 'align-items' sets the default alignment for all of the flex | ||||
| // container's items, including anonymous flex items. 'align-self' allows | ||||
| // this default alignment to be overridden for individual flex items. (For | ||||
| // anonymous flex items, 'align-self' always matches the value of 'align-items' | ||||
| // on their associated flex container.)  | ||||
| // | ||||
| // Values: flex-start | flex-end | center | baseline | stretch | ||||
| // Default: stretch | ||||
| // | ||||
| // http://w3.org/tr/css3-flexbox/#align-items-property | ||||
|  | ||||
| @mixin align-items($value: stretch) { | ||||
| 	@if $value == flex-start { | ||||
| 		-webkit-box-align: start; | ||||
| 		-ms-flex-align: start; | ||||
| 	} @else if $value == flex-end { | ||||
| 		-webkit-box-align: end; | ||||
| 		-ms-flex-align: end; | ||||
| 	} @else { | ||||
| 		-webkit-box-align: $value; | ||||
| 		-ms-flex-align: $value; | ||||
| 	} | ||||
| 	-webkit-align-items: $value; | ||||
| 	-moz-align-items: $value; | ||||
| 	align-items: $value; | ||||
| } | ||||
|  | ||||
| //---------------------------------- | ||||
|  | ||||
| // Flexbox Align Self | ||||
| // | ||||
| // Values: auto | flex-start | flex-end | center | baseline | stretch | ||||
| // Default: auto | ||||
|  | ||||
| @mixin align-self($value: auto) { | ||||
| 	// No Webkit Box Fallback. | ||||
| 	-webkit-align-self: $value; | ||||
| 	-moz-align-self: $value; | ||||
| 	@if $value == flex-start { | ||||
| 		-ms-flex-item-align: start; | ||||
| 	} @else if $value == flex-end { | ||||
| 		-ms-flex-item-align: end; | ||||
| 	} @else { | ||||
| 		-ms-flex-item-align: $value; | ||||
| 	} | ||||
| 	align-self: $value; | ||||
| } | ||||
|  | ||||
| //---------------------------------------------------------------------- | ||||
|  | ||||
| // Flexbox Align Content | ||||
| // | ||||
| // The 'align-content' property aligns a flex container's lines within the | ||||
| // flex container when there is extra space in the cross-axis, similar to | ||||
| // how 'justify-content' aligns individual items within the main-axis. Note, | ||||
| // this property has no effect when the flexbox has only a single line. | ||||
| // | ||||
| // Values: flex-start | flex-end | center | space-between | space-around | stretch | ||||
| // Default: stretch | ||||
| // | ||||
| // http://w3.org/tr/css3-flexbox/#align-content-property | ||||
|  | ||||
| @mixin align-content($value: stretch) { | ||||
| 	// No Webkit Box Fallback. | ||||
| 	-webkit-align-content: $value; | ||||
| 	-moz-align-content: $value; | ||||
| 	@if $value == flex-start { | ||||
| 		-ms-flex-line-pack: start; | ||||
| 	} @else if $value == flex-end { | ||||
| 		-ms-flex-line-pack: end; | ||||
| 	} @else { | ||||
| 		-ms-flex-line-pack: $value; | ||||
| 	} | ||||
| 	align-content: $value; | ||||
| } | ||||
							
								
								
									
										103
									
								
								frontend/delta/scss/core/fonts.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								frontend/delta/scss/core/fonts.scss
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										289
									
								
								frontend/delta/scss/core/layout.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								frontend/delta/scss/core/layout.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,289 @@ | ||||
| @import "parameters"; | ||||
|  | ||||
| .page { | ||||
| 	@include pageElement(); | ||||
| } | ||||
|  | ||||
| .mainPage { | ||||
| //	background-color: yellow; | ||||
| } | ||||
|  | ||||
| .mainPage > #selectionPanel { | ||||
| 	@include sliding-panel(left, $selectionPanelWidth); | ||||
| 	 | ||||
| 	&.open { | ||||
| 		@include sliding-panel-open(left, $selectionPanelWidth); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| #mainPanel { | ||||
| //	background-color: $yellow; | ||||
|  | ||||
| 	&.extra-wide { | ||||
| 		@include sliding-panel-container(); | ||||
| 		 | ||||
| 		.container { | ||||
| 			@include flexbox; | ||||
| 		} | ||||
| 		 | ||||
| 		.subpanel { | ||||
| 			 | ||||
| 			&.selection { | ||||
| 				@include flex($selectionPanelWidth, 0); | ||||
| //				height: 100%; | ||||
| 				overflow-y: scroll; | ||||
| 			} | ||||
| 			 | ||||
| 			&.cardContent { | ||||
| 				@include flex($cardContentPanelWidth); | ||||
| 				@include flexbox; | ||||
| 				@include flex-direction(column); | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		.selectionToggle { | ||||
| 			.button { | ||||
| 				display: none; | ||||
| 				visibility: hidden; | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 	} | ||||
|  | ||||
| 	&.wide, &.narrow { | ||||
| 		.container { | ||||
| 			@include sliding-panel-container(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	&.narrow { | ||||
| 		.column { | ||||
| 			@include pageElement(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	&.open.left { | ||||
| 		@include sliding-panel-wrapper-open (left, $selectionPanelWidth); | ||||
| 		@include mask(); | ||||
| 	} | ||||
|  | ||||
| 	&.open.right { | ||||
| //		@include sliding-panel-wrapper-open (right, $settingsPanelWidth); | ||||
| 		@include mask(); | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| #extraFeaturesPanel { | ||||
| 	@include sliding-panel(right, $settingsPanelWidth); | ||||
| 	 | ||||
| 	&.open { | ||||
| 		@include sliding-panel-open(right, $settingsPanelWidth); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| .container { | ||||
| 	height: 100%; | ||||
| 	width: 100%; | ||||
| } | ||||
|  | ||||
| .cardToolbarFrame { | ||||
| 	height: 100%; | ||||
| 	 | ||||
| 	@include flexbox; | ||||
| 	@include flex-direction(column); | ||||
|  | ||||
| 	.cardToolbar { | ||||
| 		@include flex(none); | ||||
| 		 | ||||
| 	} | ||||
| 	 | ||||
| 	.cardContent { | ||||
| 	} | ||||
| } | ||||
|  | ||||
| div.cardToolbar { | ||||
| //	background-color: $orange; | ||||
| 	 | ||||
| 	header { | ||||
| 		@include flexbox; | ||||
| 		height: $mainCardToolbarHeight; | ||||
| 		line-height: $mainCardToolbarHeight; | ||||
| 		 | ||||
| 		background-color: $clipperz-orange; | ||||
| 		color: white; | ||||
| 		font-size: 24pt; | ||||
|  | ||||
| 		div { | ||||
| 			 | ||||
| 			&.clipperz { | ||||
| 				 | ||||
| 				span.logo { | ||||
| 					@include icon-font(); | ||||
|  | ||||
| 					@include align-self(center); | ||||
| 					@include flex(4); | ||||
| 					text-align: center; | ||||
| 					 | ||||
| 					&.tag, &.search { | ||||
| 						font-size: 14pt; | ||||
| 					} | ||||
| 				} | ||||
| 				 | ||||
| 				span.value { | ||||
| 					display: inline-block; | ||||
| 					padding-left: 5px; | ||||
| 					font-size: 18pt; | ||||
| 				} | ||||
| 			} | ||||
| 		 | ||||
| 			&.selectionToggle { | ||||
| 				@include flex(1); | ||||
|  | ||||
| 				.button { | ||||
| 					text-align: left; | ||||
|  | ||||
| 					.label { | ||||
| 						padding-left: 8px; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| //			&.logo { | ||||
| //				@include align-self(center); | ||||
| //				@include flex(4); | ||||
| //				text-align: center; | ||||
| //			} | ||||
|  | ||||
| 			&.settingsToggle { | ||||
| 				@include flex(1); | ||||
|  | ||||
| 				.button { | ||||
| 					text-align: right; | ||||
|  | ||||
| 					.label { | ||||
| 						padding-right: 8px; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 			.button { | ||||
| 				overflow: hidden; | ||||
| 				font-size: 24pt; | ||||
| 				@include icon-font(); | ||||
| 				vertical-align: center; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| div.cardContent { | ||||
| //	@include flex(flex-grow);	//	??? | ||||
|  | ||||
| 	@include flexbox(); | ||||
| 	@include flex-direction(row); | ||||
| 	 | ||||
| 	div.cardListColumn.column { | ||||
| 		@include flex($cardListWidth, 0); | ||||
| 		overflow-y: scroll; | ||||
|  | ||||
| 		div.cardToolbar.narrow { | ||||
| 		} | ||||
| 		 | ||||
| 		div.cardList { | ||||
| 			overflow-y: scroll; | ||||
| 			padding-bottom: 120px; | ||||
|  | ||||
| 			ul { | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		div.addCardButton { | ||||
| 			@include icon-font(); | ||||
| 			@include border-radius(50px); | ||||
| 			@include radial-gradient (white, rgba(0, 0, 0, 0)); | ||||
| 			 | ||||
| 			position: relative; | ||||
| 			bottom: 0px; | ||||
| 			font-size: 75pt; | ||||
| 			color: blue; | ||||
|  | ||||
| 			width: 100px; | ||||
| 			height: 100px; | ||||
| 			 | ||||
| 			float: right; | ||||
| 			position: absolute; | ||||
| 			margin-left: 100px; | ||||
| 			margin-bottom: 10px; | ||||
| 			 | ||||
| 			cursor: pointer; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	div.cardDetail.column { | ||||
| 		@include flex($cardDetailWidth); | ||||
|  | ||||
| 		@include flexbox(); | ||||
|  | ||||
| 		div.view { | ||||
| 			@include flex(auto); | ||||
|  | ||||
| 			@include flexbox; | ||||
| 			@include flex-direction(column); | ||||
|  | ||||
| 			.cardDetailToolbar { | ||||
| 				@include flex(none); | ||||
| 				height: $mainCardToolbarHeight; | ||||
| 				line-height: $mainCardToolbarHeight; | ||||
| 			} | ||||
|  | ||||
| 			.content { | ||||
| 				@include flex(auto); | ||||
| 				overflow-y: scroll; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| #cardDetailPage { | ||||
| 	.view { | ||||
| 		@include flexbox(); | ||||
| 		@include flex-direction(column); | ||||
| 		height: 100%; | ||||
| 		 | ||||
| 		.cardDetailToolbar { | ||||
| 			@include flex(none); | ||||
| 			height: $mainCardToolbarHeight; | ||||
| 			line-height: $mainCardToolbarHeight; | ||||
| 			 | ||||
| 			& > div { | ||||
| 				@include flexbox(); | ||||
| 				@include flex-direction(row); | ||||
| 				font-size: 24pt; | ||||
|  | ||||
| 				.back { | ||||
| 					@include flex(auto); | ||||
| 					cursor: pointer; | ||||
| 				} | ||||
| 			 | ||||
| 				.cardMenuOptions { | ||||
| 					@include flex(auto); | ||||
| 					cursor: pointer; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		 | ||||
| 		.content { | ||||
| 			@include flex(auto); | ||||
| 			overflow-y: scroll; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| .button { | ||||
| 	cursor: pointer; | ||||
| } | ||||
|  | ||||
| @@ -1,10 +1,19 @@ | ||||
| @mixin border-radius ($radius) { | ||||
| 	border-radius: $radius; | ||||
| 	-moz-border-radius: $radius; | ||||
| 	-webkit-border-radius: $radius; | ||||
| 	   -moz-border-radius: $radius; | ||||
| 	        border-radius: $radius; | ||||
| } | ||||
| 
 | ||||
| @mixin font-feature-settings($foo, $bar) { | ||||
| @mixin radial-gradient ($inner-color, $outer-color) { | ||||
| 	background-image:     -ms-radial-gradient(center, circle farthest-corner, $inner-color 0%, $outer-color 100%);		/* IE10 */  | ||||
| 	background-image:    -moz-radial-gradient(center, circle farthest-corner, $inner-color 0%, $outer-color 100%);		/* Mozilla Firefox */  | ||||
| 	background-image:      -o-radial-gradient(center, circle farthest-corner, $inner-color 0%, $outer-color 100%);		/* Opera */  | ||||
| 	background-image: -webkit-radial-gradient(center, circle farthest-corner, $inner-color 0%, $outer-color 100%);		/* Webkit (Chrome 11+) */  | ||||
| 	background-image:         radial-gradient(center, circle farthest-corner, $inner-color 0%, $outer-color 100%);		/* Proposed W3C Markup */  | ||||
| 	background-image:        -webkit-gradient(radial, center center, 0, center center, 495, color-stop(0, $inner-color), color-stop(1, $outer-color));	/* Webkit (Safari/Chrome 10) */  | ||||
| } | ||||
| 
 | ||||
| @mixin font-feature-settings ($foo, $bar) { | ||||
| 	-webkit-font-feature-settings:"$foo","$bar"; | ||||
| 	-moz-font-feature-settings:"$foo=1, $bar=1"; | ||||
| 	-moz-font-feature-settings:"$foo","$bar"; | ||||
| @@ -13,14 +22,14 @@ | ||||
| 	font-feature-settings:"$foo","$bar"; | ||||
| } | ||||
| 
 | ||||
| @mixin icon-font() { | ||||
| @mixin icon-font () { | ||||
| 	font-family: 'clipperz-icons'; | ||||
| 	@include font-feature-settings("liga", "dlig"); | ||||
| 	-webkit-font-smoothing: antialiased; | ||||
| 	text-rendering:optimizeLegibility; | ||||
| } | ||||
| 
 | ||||
| @mixin password-font() { | ||||
| @mixin password-font () { | ||||
| 	font-family: 'clipperz-password'; | ||||
| 	-webkit-font-smoothing: antialiased; | ||||
| 	text-rendering:optimizeLegibility; | ||||
| @@ -60,10 +69,10 @@ | ||||
| 
 | ||||
| @mixin transition ($item, $time, $function) { | ||||
| 	-webkit-transition: $item $time $function; | ||||
| 	-moz-transition: $item $time $function; | ||||
| 	-o-transition: $item $time $function; | ||||
| 	-ms-transition: $item $time $function; | ||||
| 	transition: $item $time $function; | ||||
| 	   -moz-transition: $item $time $function; | ||||
| 	     -o-transition: $item $time $function; | ||||
| 	    -ms-transition: $item $time $function; | ||||
| 	        transition: $item $time $function; | ||||
| } | ||||
| 
 | ||||
| @mixin transform ($rotateAngle, $translateX, $translateY) { | ||||
| @@ -74,6 +83,16 @@ | ||||
| 	        transform: rotate(  $rotateAngle) translate($translateX, $translateY); | ||||
| } | ||||
| 
 | ||||
| @mixin transform3d ($tx, $ty, $tz) { | ||||
| 	-webkit-transform: translate3d($tx, $ty, $tz); | ||||
| 	        transform: translate3d($tx, $ty, $tz); | ||||
| } | ||||
| 
 | ||||
| @mixin transition-duration ($duration) { | ||||
| 	-webkit-transition-duration: $duration; | ||||
| 	        transition-duration: $duration; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| @mixin animation-delay ($delay) { | ||||
| 	-webkit-animation-delay: $delay; | ||||
| @@ -91,7 +110,7 @@ | ||||
| 	        box-shadow: $xOffset $yOffset $size $color;	 | ||||
| } | ||||
| 
 | ||||
| @mixin keyframes($name) { | ||||
| @mixin keyframes ($name) { | ||||
| 	@-webkit-keyframes #{$name} { | ||||
| 		@content;  | ||||
| 	} | ||||
| @@ -104,4 +123,21 @@ | ||||
| 	@keyframes #{$name} { | ||||
| 		@content; | ||||
| 	}  | ||||
| } | ||||
| } | ||||
| 
 | ||||
| @mixin mask () { | ||||
| 	.mask { | ||||
| 		position: absolute; | ||||
| 		top: 0; | ||||
| 		left: 0; | ||||
| 		width: 100%; | ||||
| 		height: 100%; | ||||
| 		z-index: 10; | ||||
| 		background-color: rgba(0, 0, 0, 0.5); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| @include keyframes(spin) { | ||||
| 	0% { @include transform(0deg, 0, 0); } | ||||
| 	100% { @include transform(359deg, 0, 0); } | ||||
| } | ||||
| @@ -14,7 +14,7 @@ div.overlay { | ||||
| 
 | ||||
| 	.title { | ||||
| 		color: #FFF; | ||||
| 		font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;  | ||||
| //		font-family: "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;  | ||||
| 		font-weight: bold; | ||||
| 		text-align: center; | ||||
| 		display: block; | ||||
							
								
								
									
										44
									
								
								frontend/delta/scss/core/palette.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								frontend/delta/scss/core/palette.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| // | ||||
| //	SOLARIZED palette | ||||
| //	http://ethanschoonover.com/solarized | ||||
| // | ||||
| $solarize-Background-15: #002b36; | ||||
| $solarize-Background-20: #073642; | ||||
|  | ||||
| $solarize-Content-45: #586375; | ||||
| $solarize-Content-50: #657b83; | ||||
| $solarize-Content-60: #839496; | ||||
| $solarize-Content-65: #93a1a1; | ||||
|  | ||||
| $solarize-Background-92:	#eee8d5; | ||||
| $solarize-Background-97:	#fdf6e3; | ||||
|  | ||||
| $solarize-Accent-Yellow:	#b58900; | ||||
| $solarize-Accent-Orange:	#cb4b16; | ||||
| $solarize-Accent-Red:		#dc322f; | ||||
| $solarize-Accent-Magenta:	#d33682; | ||||
| $solarize-Accent-Violet:	#6c71c4; | ||||
| $solarize-Accent-Blue:		#268bd2; | ||||
| $solarize-Accent-Cyan:		#2aa198; | ||||
| $solarize-Accent-Green:		#859900; | ||||
|  | ||||
| //	$yellow:	$solarize-Accent-Yellow; | ||||
| //	$orange:	$solarize-Accent-Orange; | ||||
| //	$red:		$solarize-Accent-Red; | ||||
| //	$magenta:	$solarize-Accent-Magenta; | ||||
| //	$violete:	$solarize-Accent-Violet; | ||||
| //	$blue:		$solarize-Accent-Blue; | ||||
| //	$cyan:		$solarize-Accent-Cyan; | ||||
| //	$green:		$solarize-Accent-Green; | ||||
|  | ||||
| $clipperz-orange:	#ff9900; | ||||
| $clipperz-blue:		#1863a1; | ||||
| $terminal-green:	#23ff18; | ||||
|  | ||||
|  | ||||
|  | ||||
| $main-color: $clipperz-orange; | ||||
| $main-text-color: black; | ||||
|  | ||||
| $main-alternate-color: black; | ||||
| $main-alternate-text-color: white; | ||||
							
								
								
									
										15
									
								
								frontend/delta/scss/core/parameters.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								frontend/delta/scss/core/parameters.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| //$selectionPanelWidth: 200px; | ||||
| //$cardListWidth: 200px; | ||||
|  | ||||
| $selectionPanelWidth: 1; | ||||
| $cardContentPanelWidth: 4; | ||||
|  | ||||
| $mainCardToolbarHeight: 48px; | ||||
|  | ||||
| $cardListWidth: 1; | ||||
| $cardDetailWidth: 2; | ||||
|  | ||||
| $selectionPanelWidth: 300px; | ||||
| $settingsPanelWidth: 300px; | ||||
|  | ||||
|  | ||||
							
								
								
									
										43
									
								
								frontend/delta/scss/core/reset.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								frontend/delta/scss/core/reset.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| //	Downloaded on June 11, 2014 from: https://gist.github.com/hcatlin/1027867 | ||||
|  | ||||
| /* http://meyerweb.com/eric/tools/css/reset/  | ||||
|    v2.0 | 20110126 | ||||
|    License: none (public domain) | ||||
| */ | ||||
|   | ||||
| html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video { | ||||
| 	margin: 0; | ||||
| 	padding: 0; | ||||
| 	border: 0; | ||||
| 	font-size: 100%; | ||||
| 	font: inherit; | ||||
| 	vertical-align: baseline; | ||||
| } | ||||
|   | ||||
| /* HTML5 display-role reset for older browsers */ | ||||
|   | ||||
| article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { | ||||
| 	display: block; | ||||
| } | ||||
|   | ||||
| body { | ||||
| 	line-height: 1; | ||||
| } | ||||
|   | ||||
| ol, ul { | ||||
| 	list-style: none; | ||||
| } | ||||
|  | ||||
| blockquote, q { | ||||
| 	quotes: none; | ||||
|  | ||||
| 	&:before, &:after, { | ||||
| 		content: ''; | ||||
| 		content: none; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| table { | ||||
| 	border-collapse: collapse; | ||||
| 	border-spacing: 0; | ||||
| } | ||||
							
								
								
									
										52
									
								
								frontend/delta/scss/core/sizes.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								frontend/delta/scss/core/sizes.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| /* | ||||
|  | ||||
| Bootstrap CSS suggests these size breakpoints: | ||||
|  | ||||
| - Extra small devices Phones (<768px) | ||||
| - Small devices Tablets (≥768px) | ||||
| - Medium devices Desktops (≥992px) | ||||
| - Large devices Desktops (≥1200px) | ||||
|  | ||||
|  | ||||
| # ATTENTION | ||||
| When adding a new 'size', remember to update also MQ.init invocation in main.js. | ||||
| This configuration is now located in the first script included in the index_template.html file. | ||||
|  | ||||
| */ | ||||
|  | ||||
| @media only screen and (min-width: 100px) { | ||||
| 	html { | ||||
| 		font-family: "narrow"; | ||||
| 	} | ||||
| 	body:after { | ||||
| 		content: "narrow"; | ||||
| 	} | ||||
| } | ||||
|  | ||||
|  | ||||
| @media only screen and (min-width: 700px) { | ||||
| 	html { | ||||
| 		font-family: "wide"; | ||||
| 	} | ||||
| 	body:after { | ||||
| 		content: "wide"; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @media only screen and (min-width: 1100px) { | ||||
| 	html { | ||||
| 		font-family: "extra-wide"; | ||||
| 	} | ||||
| 	body:after { | ||||
| 		content: "extra-wide"; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @media only screen and (min-width: 100px) and (max-height: 450px) { | ||||
| 	html { | ||||
| 		font-family: "extra-short"; | ||||
| 	} | ||||
| 	body:after { | ||||
| 		content: "extra-short"; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										27
									
								
								frontend/delta/scss/style/accountStatus.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								frontend/delta/scss/style/accountStatus.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| .accountStatus { | ||||
| 	background-color: green; | ||||
| 	 | ||||
| 	&.FULL { | ||||
| 		display: none; | ||||
| 		visibility: hidden; | ||||
| 		 | ||||
| 		&.isExpiring { | ||||
| 			display: block; | ||||
| 			visibility: visible; | ||||
| 			 | ||||
| 			background-color: yellow; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	&.TRIAL { | ||||
| 		background-color: orange; | ||||
|  | ||||
| 		&.isExpiring { | ||||
| 			background-color: red; | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	&.EXPIRED { | ||||
| 		background-color: red; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										270
									
								
								frontend/delta/scss/style/card.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										270
									
								
								frontend/delta/scss/style/card.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,270 @@ | ||||
| $cardListHeight: 48px; | ||||
| $faviconSize: 32px; | ||||
| $padding: ($cardListHeight - $faviconSize) / 2; | ||||
|  | ||||
| $cardToolbarBackgroundColor: brown; | ||||
|  | ||||
| div.cardList { | ||||
| //	background-color: $yellow; | ||||
|  | ||||
| 	&.loadingCard { | ||||
| 		li.selected { | ||||
| 			background-color: gray; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	ul { | ||||
| 		li.selected { | ||||
| 			background-color: yellow; | ||||
| 		} | ||||
|  | ||||
| 		li { | ||||
| 			cursor: pointer; | ||||
|  | ||||
| 			border-bottom: 1px solid #eee; | ||||
|  | ||||
| 			@include flexbox(); | ||||
| 			@include flex-direction(row); | ||||
|  | ||||
| 			.favicon { | ||||
| 				width: $cardListHeight; | ||||
| 				@include flex(none); | ||||
|  | ||||
| 				img { | ||||
| 					width: $faviconSize; | ||||
| 					height: $faviconSize; | ||||
| 					padding: $padding; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			.label { | ||||
| 				@include flex(auto); | ||||
|  | ||||
| 				font-size: 18pt; | ||||
|  | ||||
| 				padding-top: 0.5em; | ||||
| 				padding-bottom: 0.5em; | ||||
| 				padding-left: $padding; | ||||
| 				padding-right: $padding; | ||||
| 			} | ||||
| 			 | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| div.cardList.narrow { | ||||
| 	&.loadingCard { | ||||
| 		li.selected { | ||||
| //			background-color: gray; | ||||
|  | ||||
| 			&:after { | ||||
| 				color: white; | ||||
| 				margin-right: 10px; | ||||
| 				content: "loading"; | ||||
| 				@include animation(spin, 1s, linear, infinite); | ||||
| 			} | ||||
| 			 | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	ul { | ||||
| 		li { | ||||
| 			 | ||||
| 			&:after { | ||||
| 				content: "show detail"; | ||||
| 				@include flex(none); | ||||
| 				@include icon-font(); | ||||
| 				height: 48px; | ||||
| 				font-size: 24pt; | ||||
| 				line-height: 48px; | ||||
| 				margin-right: 25px; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| $cardViewBasePadding: 10px; | ||||
|  | ||||
| #cardDetailPage, .cardDetail { | ||||
| 	.loading { | ||||
| //		height: 100%; | ||||
| //		width: 100%; | ||||
| //		background-color: rgba(0,0,0,0.5); | ||||
| 	} | ||||
|  | ||||
| 	.view { | ||||
| 		 | ||||
| 		.cardDetailToolbar { | ||||
| 			 | ||||
| 			ul { | ||||
| 				@include flexbox(); | ||||
| 				@include flex-direction(row); | ||||
| 		 | ||||
| 				li { | ||||
| 					@include flex(auto); | ||||
| 					text-align: center; | ||||
| 			 | ||||
| 					span { | ||||
| 						cursor: pointer; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 			&.narrow { | ||||
| 				.back { | ||||
| 					@include icon-font(); | ||||
| 				} | ||||
| 				 | ||||
| 				.cardMenuOptions { | ||||
| 					@include icon-font(); | ||||
| 					text-align: right; | ||||
| 					font-size: 18pt; | ||||
| 					padding-right: 10px; | ||||
| 					 | ||||
| 				} | ||||
|  | ||||
| 				.commandMenu { | ||||
| //					display: none; | ||||
| 					.commandMenuMask { | ||||
| 						display: none; | ||||
| 					} | ||||
| 					 | ||||
| 					.commandMenu { | ||||
| 						display: none; | ||||
| 					} | ||||
| 					 | ||||
| 					&.show { | ||||
|  | ||||
| 						.commandMenuMask { | ||||
| 							display: block; | ||||
| 							position: absolute; | ||||
| 							top: 0; | ||||
| 							left: 0; | ||||
| 							width: 100%; | ||||
| 							height: 100%; | ||||
| 							background-color: rgba(0, 0, 0, 0); | ||||
| 						} | ||||
|  | ||||
| 						.commandMenu { | ||||
| 							display: block; | ||||
| 							float: right; | ||||
| 							position: absolute; | ||||
| 							min-width: 200px; | ||||
| 							top: 48px; | ||||
| 							right: 5px; | ||||
| 							color: black; | ||||
| 							background-color: white; | ||||
| 							@include box-shadow(0px, 2px, 5px, rgba(50, 50, 50, 0.75)); | ||||
| 					 | ||||
| 							ul { | ||||
| 								@include flex-direction(column); | ||||
| 						 | ||||
| 								li { | ||||
| 									text-align: left; | ||||
| 									font-size: 18pt; | ||||
| 									padding: 5px 10px; | ||||
| 									border-bottom: 1px solid black; | ||||
| 							 | ||||
| 								} | ||||
| 							} | ||||
| 						} | ||||
| 					} | ||||
| 					 | ||||
| 				} | ||||
| 			} | ||||
| 		}		 | ||||
| 	} | ||||
| }	 | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| .cardDetailToolbar { | ||||
| 	background-color: $cardToolbarBackgroundColor; | ||||
| 	color: white; | ||||
| 	 | ||||
| 	&.narrow { | ||||
| 		 | ||||
| 		.cardMenuOptions { | ||||
| 			margin-right: 5px; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| .content { | ||||
| 	.cardLabel { | ||||
| 		font-size: 24pt; | ||||
| 		padding: $cardViewBasePadding; | ||||
| 	} | ||||
|  | ||||
| 	.cardTags { | ||||
| 		@include flexbox(); | ||||
| 		@include flex-direction(row); | ||||
| 		@include align-items(flex-start); | ||||
| 		 | ||||
| 		padding: $cardViewBasePadding; | ||||
|  | ||||
| 		.cardTag { | ||||
| 			@include flex(none); | ||||
| 			font-size: 14pt; | ||||
| 			padding-right: 10px; | ||||
| 			 | ||||
| 			&:before { | ||||
| 				content: 'tag'; | ||||
| 				@include icon-font(); | ||||
| 				font-size: 10pt; | ||||
| 				padding-right: 4px; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	.cardNotes { | ||||
| 		padding: $cardViewBasePadding; | ||||
| 	} | ||||
|  | ||||
| 	.cardField { | ||||
| 		@include flexbox; | ||||
| 		@include flex-direction(row); | ||||
|  | ||||
| 		.fieldValues { | ||||
| 			@include flex(1); | ||||
| 			padding: $cardViewBasePadding; | ||||
|  | ||||
| 			.fieldLabel { | ||||
| 				color: gray; | ||||
| 			} | ||||
|  | ||||
| 			.fieldValue { | ||||
| 				font-size: 18pt; | ||||
|  | ||||
| 				&.hidden { | ||||
| 					font-family: clipperz-password; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 		 | ||||
| 		} | ||||
|  | ||||
| 		.fieldAction { | ||||
| 			@include flex(none); | ||||
| 			@include align-self(center); | ||||
| 		} | ||||
| 	 | ||||
| 		.action { | ||||
| 			width: 32px; | ||||
| 			height: 32px; | ||||
| 			@include icon-font(); | ||||
| 			font-size: 20pt; | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	.cardDirectLogin { | ||||
| 		font-size: 18pt; | ||||
| 		padding: $cardViewBasePadding; | ||||
| 		background-color: pink; | ||||
| 		cursor: pointer; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										32
									
								
								frontend/delta/scss/style/loadingPage.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								frontend/delta/scss/style/loadingPage.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| //	$Loading_outer_color: $main-color; | ||||
| //	$Loading_inner-color: lighten($Loading_outer-color, 30%); | ||||
| //	 | ||||
| //	$Loading_h1-color:			lighten($Loading_inner-color, 70%); | ||||
| //	$Loading_h3-color:			darken($Loading_outer-color, 20%); | ||||
|  | ||||
| #loadingPage { | ||||
| //	@include radial-gradient($Loading_inner-color, $Loading_outer-color); | ||||
| 	background-color: $main-color; | ||||
|  | ||||
| 	div { | ||||
| 		vertical-align: middle; | ||||
| 		width: 100%; | ||||
| 		text-align: center; | ||||
|  | ||||
| 		h1 { | ||||
| 			font-size: 40pt; | ||||
| 			font-weight: bold; | ||||
| //			color: $Loading_h1-color; | ||||
| 			color: $main-alternate-text-color; | ||||
| 			margin-top: 10%; | ||||
| 			margin-bottom: 5px; | ||||
| 		} | ||||
|  | ||||
| 		h3 { | ||||
| 			font-size: 18pt; | ||||
| //			color: $Loading_h3-color; | ||||
| 			color: $main-text-color; | ||||
| 			margin: 0px; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										151
									
								
								frontend/delta/scss/style/loginPage.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								frontend/delta/scss/style/loginPage.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,151 @@ | ||||
| #loginPage { | ||||
| 	overflow: scroll; | ||||
| 	 | ||||
| 	div.loginForm { | ||||
| 		@include flexbox; | ||||
| 		@include flex-direction(column); | ||||
| 		@include align-items(stretch); | ||||
|  | ||||
| 		height: 100%; | ||||
| 		 | ||||
| 		text-align: center; | ||||
| 		background-color: $main-color; | ||||
|  | ||||
| 		header { | ||||
| 			@include flex(1); | ||||
| 			@include icon-font(); | ||||
|  | ||||
| 			font-size: 48pt; | ||||
| 			color: $main-alternate-text-color; | ||||
| 		} | ||||
|  | ||||
| 		div.form { | ||||
| 			@include flex(4); | ||||
| 			margin-left: auto; | ||||
| 			margin-right: auto; | ||||
|  | ||||
| 			form { | ||||
| 				position: relative; | ||||
| 				background: $main-alternate-text-color; | ||||
|  | ||||
| //				@include border-radius(10px); | ||||
| 				padding: 20px; | ||||
| 				margin-bottom: 50px; | ||||
| /*			 | ||||
| 				&:after { | ||||
| 					content: ""; | ||||
| 					position: absolute; | ||||
| 					top: -15px; | ||||
| 					margin-left: 50%; | ||||
| 					left: -15px; | ||||
| 					border-style: solid; | ||||
| 					border-width: 0 15px 15px; | ||||
| 					border-color: $main-alternate-text-color transparent; | ||||
| 					display: block; | ||||
| 					width: 0; | ||||
| 					z-index: 1; | ||||
| 				}			 | ||||
| */ | ||||
| 				label { | ||||
| 					display: none; | ||||
| 				} | ||||
|  | ||||
| 				input { | ||||
| 					font-family: "clipperz-font"; | ||||
| 					display: block; | ||||
| //					@include border-radius(4px); | ||||
| 					padding: 5px; | ||||
| 					margin-top: 5px; | ||||
| 					margin-bottom: 10px; | ||||
| 					font-size: 100%; | ||||
| //					box-shadow:inset 0 0 0; | ||||
| 					font-size: 24pt; | ||||
| 					width: 100%; | ||||
| 				} | ||||
|  | ||||
| 				button { | ||||
| 					font-family: "clipperz-font"; | ||||
| 					min-height: 48px; | ||||
| 					min-width: 48px; | ||||
|  | ||||
| 					color: white; | ||||
| 					font-size: 24pt; | ||||
| 					font-weight: 500; | ||||
| 					border: 0px; | ||||
|  | ||||
| 					padding: 10px 25px; | ||||
|  | ||||
| 					border: 1px solid white; | ||||
| 					background-color: $main-color; | ||||
| 					@include transition(background-color font-weight, 0.2s, linear); | ||||
|  | ||||
| 					&:hover { | ||||
| 					}; | ||||
|  | ||||
| 					&:disabled { | ||||
| 						font-weight: 100; | ||||
| 						background-color: #c0c0c0; | ||||
| 						cursor: default; | ||||
|  | ||||
| 						&:hover { | ||||
| 						}; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		div.registrationLink { | ||||
| 			@include flex(1); | ||||
|  | ||||
| 			color: $main-alternate-text-color; | ||||
| 			background-color: $main-alternate-color; | ||||
| 			cursor: pointer; | ||||
| 			font-size: 24pt; | ||||
|  | ||||
| 			&:before { | ||||
| 				content: "> "; | ||||
| 			}; | ||||
|  | ||||
| 			a { | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	div.loginForm.extra-short { | ||||
| 		header { | ||||
| //			@include flex(1); | ||||
| 			font-size: 18pt; | ||||
| 		} | ||||
|  | ||||
| 		div.form { | ||||
| //			@include flex(6); | ||||
| 			form { | ||||
| 				padding: 10px; | ||||
| 				margin-bottom: 20px; | ||||
|  | ||||
| 				input { | ||||
| 					padding: 3px; | ||||
| 					margin-top: 3px; | ||||
| 					margin-bottom: 5px; | ||||
| 					font-size: 16pt; | ||||
| 				} | ||||
|  | ||||
| 				button { | ||||
| 					min-height: 20px; | ||||
|  | ||||
| 					font-size: 12pt; | ||||
| 					padding: 3px 10px; | ||||
| 					border: 1px solid white; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		div.registrationLink { | ||||
| //			@include flex(2); | ||||
| 			font-size: 14pt; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
							
								
								
									
										111
									
								
								frontend/delta/scss/style/registrationPage.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								frontend/delta/scss/style/registrationPage.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| #registrationPage { | ||||
| 	background-color: $main-alternate-color; | ||||
| 	color: $main-alternate-text-color; | ||||
|  | ||||
| 	label { | ||||
| 		display: none; | ||||
| 	} | ||||
|  | ||||
| 	input { | ||||
| 		display: block; | ||||
| 		border: 1px solid $solarize-Background-92; | ||||
| 		@include border-radius(6px); | ||||
| 		padding: 5px; | ||||
| 		margin-top: 5px; | ||||
| 		margin-bottom: 10px; | ||||
| 		font-size: 100%; | ||||
| 		box-shadow:inset 0 0 0; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	.steps { | ||||
| 		.step { | ||||
| 			display: none; | ||||
|  | ||||
| 			&.center { | ||||
| 				display: block; | ||||
| 			} | ||||
|  | ||||
| 			h1 { | ||||
| 				color: $solarize-Accent-Blue; | ||||
| 				font-size: 24pt; | ||||
| 				font-weight: 700; | ||||
| 				margin: 0px; | ||||
| 			} | ||||
| 			p { | ||||
| 				color: $solarize-Content-50; | ||||
| 				font-size: 14pt; | ||||
| 				font-weight: 100; | ||||
| 				margin: 0px; | ||||
| 			} | ||||
|  | ||||
| 			&.TERMS_OF_SERVICE { | ||||
| 				.checkboxBlock { | ||||
| 					margin-top: 10px; | ||||
| 					margin-bottom: 10px; | ||||
| 					clear: both; | ||||
|  | ||||
| 					input { | ||||
| 						display: block; | ||||
| 						float: left; | ||||
| 						margin: 5px; | ||||
| 						width: 30px; | ||||
| 					} | ||||
|  | ||||
| 					p { | ||||
| 						font-size: 12pt; | ||||
| 						font-weight: 500; | ||||
| 						display: block; | ||||
|  | ||||
| 						a { | ||||
| 							color: $solarize-Accent-Red; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			.stepIndex { | ||||
| 				text-align: center; | ||||
| 				.stepIndexItem { | ||||
| 					font-weight: 900; | ||||
| 					font-size: 28pt; | ||||
| 					display: inline; | ||||
| 					color: lightgrey; | ||||
|  | ||||
| 					&.center { | ||||
| 						color: gray; | ||||
| 					} | ||||
| 				} | ||||
| 			}	 | ||||
| 			.buttons { | ||||
| 				text-align: center; | ||||
| 				margin-top: 10px; | ||||
|  | ||||
| 				.button { | ||||
| 					margin: 10px; | ||||
| 					text-align: center; | ||||
| 					vertical-align: middle; | ||||
| 					display: inline-block; | ||||
| 					width: 80px; | ||||
|  | ||||
| 					font-weight: 900; | ||||
| 					line-height: 45px; | ||||
| 					font-size: 24px; | ||||
|  | ||||
| 					&.back { | ||||
|  | ||||
| 						background-color: lightgrey; | ||||
|  | ||||
| //						&.step_-1 { | ||||
| //							visibility: hidden; | ||||
| //						} | ||||
| 					} | ||||
|  | ||||
| 					&.disabled { | ||||
| 						background-color: #c0c0c0; | ||||
| 						cursor: default; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										69
									
								
								frontend/delta/scss/style/selectionPanel.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								frontend/delta/scss/style/selectionPanel.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| #selections { | ||||
| 	background-color: $main-alternate-color; | ||||
| 	color: $main-alternate-text-color; | ||||
| 	font-size: 18pt; | ||||
| 	overflow: scroll; | ||||
| 	height: 100%; | ||||
|  | ||||
| 	$iconColumnWidth: 40px; | ||||
|  | ||||
| 	ul.defaultSet { | ||||
| 		font-weight: bold; | ||||
| 		padding-top: 10px; | ||||
| 		padding-bottom: 10px; | ||||
|  | ||||
| 		li { | ||||
| 			&.allCards:before { | ||||
| 				content: "clipperz"; | ||||
| 			} | ||||
| 			 | ||||
| 			&.recentCards:before { | ||||
| 				content: "recent"; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	.search { | ||||
| 		label { | ||||
| 			@include icon-font(); | ||||
| 			font-size: 18pt; | ||||
| 			padding-left: 5px; | ||||
| 			padding-right:5px; | ||||
| 		} | ||||
| 		 | ||||
| 		input { | ||||
| 			font-family: "clipperz-font"; | ||||
| 			color: #999; | ||||
| 			font-size: 18pt; | ||||
| 			width: $selectionPanelWidth - $iconColumnWidth - 10px; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	ul.tagList { | ||||
| 		padding-top: 10px; | ||||
|  | ||||
| 		li { | ||||
| 			&:before { | ||||
| 				content: "tag"; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	 | ||||
| 	li { | ||||
| 		padding-left: 35px; | ||||
| 		text-indent: -35px; | ||||
|  | ||||
| 		padding-top: 7px; | ||||
| 		padding-bottom: 7px; | ||||
|  | ||||
| 		cursor: pointer; | ||||
|  | ||||
| 		&:before { | ||||
| 			@include icon-font(); | ||||
| 			font-weight: normal; | ||||
| 			padding-left: 8px; | ||||
| 			padding-right: 8px; | ||||
| 			font-size: 14pt; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										19
									
								
								frontend/delta/scss/style/settingsPanel.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								frontend/delta/scss/style/settingsPanel.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| #extraFeaturesPanel { | ||||
| 	background-color: $main-alternate-color; | ||||
| 	color: $main-alternate-text-color; | ||||
| 	 | ||||
| 	header { | ||||
| 		text-align: right; | ||||
| 		height: 48px; | ||||
| 		font-size: 24pt; | ||||
|  | ||||
| 		.button { | ||||
| 			@include icon-font(); | ||||
|  | ||||
| 			.label { | ||||
| 				padding-top: 8px; | ||||
| 				padding-right: 8px; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,10 +0,0 @@ | ||||
| @import "web/fonts"; | ||||
| @import "web/overlay"; | ||||
| @import "web/behavior"; | ||||
| @import "web/style"; | ||||
| @import "web/checkbox"; | ||||
| @import "web/480"; | ||||
| @import "web/768"; | ||||
| @import "web/992"; | ||||
|  | ||||
| @import "web/add2home"; | ||||
| @@ -1,11 +0,0 @@ | ||||
| @media only screen and (min-width: 480px) { | ||||
| 	.loginForm { | ||||
| 		font-size: 1.2em; | ||||
|  | ||||
| 		input { | ||||
| 		} | ||||
| 		button { | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -1,3 +0,0 @@ | ||||
| @media only screen and (min-width: 768px) { | ||||
| 	 | ||||
| } | ||||
| @@ -1,2 +0,0 @@ | ||||
| @media only screen and (min-width: 992px) { | ||||
| } | ||||
| @@ -1,160 +0,0 @@ | ||||
| /** | ||||
|  * | ||||
|  * Main container | ||||
|  * | ||||
|  */ | ||||
| #addToHomeScreen { | ||||
| 	z-index:9999; | ||||
| 	-webkit-user-select:none; | ||||
| 	user-select:none; | ||||
| 	-webkit-box-sizing:border-box; | ||||
| 	box-sizing:border-box; | ||||
| 	-webkit-touch-callout:none; | ||||
| 	touch-callout:none; | ||||
| 	width:240px; | ||||
| 	font-size:15px; | ||||
| 	padding:12px 14px; | ||||
| 	text-align:left; | ||||
| 	font-family:helvetica; | ||||
| 	background-image:-webkit-gradient(linear,0 0,0 100%,color-stop(0,#fff),color-stop(0.02,#eee),color-stop(0.98,#ccc),color-stop(1,#a3a3a3)); | ||||
| 	border:1px solid #505050; | ||||
| 	-webkit-border-radius:8px; | ||||
| 	-webkit-background-clip:padding-box; | ||||
| 	color:#333; | ||||
| 	text-shadow:0 1px 0 rgba(255,255,255,0.75); | ||||
| 	line-height:130%; | ||||
| 	-webkit-box-shadow:0 0 4px rgba(0,0,0,0.5); | ||||
| } | ||||
|  | ||||
| #addToHomeScreen.addToHomeIpad { | ||||
| 	width:268px; | ||||
| 	font-size:18px; | ||||
| 	padding:14px; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * The 'wide' class is added when the popup contains the touch icon | ||||
|  * | ||||
|  */ | ||||
| #addToHomeScreen.addToHomeWide { | ||||
| 	width:296px; | ||||
| } | ||||
|  | ||||
| #addToHomeScreen.addToHomeIpad.addToHomeWide { | ||||
| 	width:320px; | ||||
| 	font-size:18px; | ||||
| 	padding:14px; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * The balloon arrow | ||||
|  * | ||||
|  */ | ||||
| #addToHomeScreen .addToHomeArrow { | ||||
| 	position:absolute; | ||||
| 	background-image:-webkit-gradient(linear,0 0,100% 100%,color-stop(0,rgba(204,204,204,0)),color-stop(0.4,rgba(204,204,204,0)),color-stop(0.4,#ccc)); | ||||
| 	border-width:0 1px 1px 0; | ||||
| 	border-style:solid; | ||||
| 	border-color:#505050; | ||||
| 	width:16px; height:16px; | ||||
| 	-webkit-transform:rotateZ(45deg); | ||||
| 	bottom:-9px; left:50%; | ||||
| 	margin-left:-8px; | ||||
| 	-webkit-box-shadow:inset -1px -1px 0 #a9a9a9; | ||||
| 	-webkit-border-bottom-right-radius:2px; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * The balloon arrow for iPad | ||||
|  * | ||||
|  */ | ||||
| #addToHomeScreen.addToHomeIpad .addToHomeArrow { | ||||
| 	-webkit-transform:rotateZ(-135deg); | ||||
| 	background-image:-webkit-gradient(linear,0 0,100% 100%,color-stop(0,rgba(238,238,238,0)),color-stop(0.4,rgba(238,238,238,0)),color-stop(0.4,#eee)); | ||||
| 	-webkit-box-shadow:inset -1px -1px 0 #fff; | ||||
| 	top:-9px; bottom:auto; left:50%; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * Close button | ||||
|  * | ||||
|  */ | ||||
| #addToHomeScreen .addToHomeClose { | ||||
| 	-webkit-box-sizing:border-box; | ||||
| 	position:absolute; | ||||
| 	right:4px; | ||||
| 	top:4px; | ||||
| 	width:18px; | ||||
| 	height:18px; line-height:14px; | ||||
| 	text-align:center; | ||||
| 	text-indent:1px; | ||||
| 	-webkit-border-radius:9px; | ||||
| 	background:rgba(0,0,0,0.12); | ||||
| 	color:#707070; | ||||
| 	-webkit-box-shadow:0 1px 0 #fff; | ||||
| 	font-size:16px; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * The '+' icon, displayed only on iOS < 4.2 | ||||
|  * | ||||
|  */ | ||||
| #addToHomeScreen .addToHomePlus { | ||||
| 	font-weight:bold; | ||||
| 	font-size:1.3em; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * The 'share' icon, displayed only on iOS >= 4.2 | ||||
|  * | ||||
|  */ | ||||
| #addToHomeScreen .addToHomeShare { | ||||
| 	display:inline-block; | ||||
| 	width:18px; | ||||
| 	height:15px; | ||||
| 	background-repeat:no-repeat; | ||||
| 	background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACQAAAAeCAQAAADu6HTYAAADPElEQVR4Xq3TX2gcRRzA8e/M7mVv2+TSNpc/TZtrY6jUGqgaSAmEChKLrYK0YH0RFC2CSCkEfCghiKU04J8qNigq6os+iQV98MHWFwVBrQQRWs21lBw5cw3NNb1/udu72RGG5Y77IzXW77D7sAwf5scyYoL6BGXSDKFZwaGpLvIUaeoCkvX1MmsM0Ny6oRSQYOLuIS+YZOpfQdqslpUxcZrzTVAz4qPwW2O3CeIwC/RSzeY6Ow1QhUrkr+YOWfEKDkEP8Rij7CHKJmrFSDHBdwGEE5wiGChPN+PnT8VdRtEIl1d4gRj/1EVe5ZSBKGh8iqQpo/Fo5+3C/gz0MYg4zgwbqday1/Q4B8BGQ45d/Hi54lakCrU5obOcidJpu1+Lg9whjabyaOYLnrIBFFaRD+xe2ybMDWY66GmP/WA9cGfGp0CWhy0wkMN8inepFiH2rV1j0NQSNQbFLRQnS8/8YSDBBpadfv4CYDub2fmeHDNAsL1MBWUel0iA+Xik6eHcyvD3vAMSU1TGuA/YRS+dD7ovCQN43GKRFCU20Kd3V/avDVVyAZ5niTEuLA5/zBGWg9EEEhfJKN200Tat8CmRAQb9+wv7soPlHt2tQorsz1uPbr0HTY4sJwrH47zJZwABBAKLMBoQXepwgTwdHCo+fXMkQ4lrxEmQ5AaXipPqDY9V2vn09tgvTPI71EEGYxM+/uMJLJ4svpgaWGKOi/xKgmqLSUGSUd5f2vIVJ/CgBaTIUsZ7ZBsn0+NzfMOXLFCXQyTcybN6ep5ZZgUOHn7jpfUpsZshdugPGf+E5zjbyHTSRyQ8xfRPPM/s63RHeuknSoT22mjmmnAOIMkUZ6D1xSfPPAfd1WFKM3sO2CMaHx8M1NjnXKHaAGGkOW0C02WeYHUz4qMtx+w5gUDS8NckYe5lHsMYwCZEPyEEmjLDZFmAS7CDviMdxyTkMNVBKEmYLvbiQQBIBBbCQG04bGQvFWz6CfsCQLWCigILFwcfkGYBiOpbYuOizTAyYyDdCtrGaRG1LCkIgMYEFhI0WqQZoSlbGRyHKe4qOx7iv2bVQW9dp4dlM/x6kmwnWQcd/Q3FCqwTEiT5s+6D5v/pb0SSHyg7uhMWAAAAAElFTkSuQmCC); | ||||
| 	background-size:18px 15px; | ||||
| 	text-indent:-9999em; | ||||
| 	overflow:hidden; | ||||
| } | ||||
|  | ||||
| #addToHomeScreen .addToHomeShare.addToHomeShareOS7 { | ||||
| 	width:11px; | ||||
| 	background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACoAAAA8CAYAAAAQTCjdAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAASCQAAEgkB80sG3AAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAKjSURBVGiB7dpPiFVVHMDxz7m9NCtMyI2bEJEC25WrEkzHUXCRraIwdNE8ZxfYIlcis1ZEbGEzT1QCF4XgH1CyWhUoJKIWNRGEiCNKmkSiYTzfcfGuOokx77x3ZlS8382959zfn+/invvn3RdijHIRBrwkOINCYXEcdjpb7VyiYdBsLScwt5y6IloYdzqXo36Ro0gY9IKWo+5JwmzBt2HQnBw9ehYNazyn5TBee8Dh+Vq+CWu92GufnkTDR6ab7gDeBNHouMM/l9tXTXM0fGBmL726Fg1Dam74EsvKqR8VNowL2Yzj5f7rnnE4DHq2235diYYhhTGfC94up35T0y+6di/ITU0rKVd+sEi0P7xr2pSJOu8zvF+OzqEv7vDH/WFxt7/cshy/ticsN8sXYUht0kXDOlsF9XJ4UaEvNoz9X3zc5bKaZThbyr5jzJ4wlNY7KTgM+ES0vhz+KeiPw36fKC/ucAF9uFBOrTZm26SJCtaV27+xIo7cXdkTEhvOoh+XyxprU1qnim7CQdGK2HAyKRexYVShT3RItDElN+mkjiP2Ym+S3f01hv2EVal5WW6hU0ElmptaqJuBpXg6MbeFH2LDpU6CQ93zWIKnEvs0cayGU3glMfkOo1jQYewZzOuyz7FC95Jwo5OgUFfgeg993hh/eTqCTxOSm/iuk8DY0Ap1b2GhtHXxsfZN4j/X0fOx4auEIknEhqv4OiUn1L13Z/+xWfWVaG4q0dxUormpRHNTieamEs1NJZqbJ1Q0jHvdiJo5S2cVjSNOCHZhn3/SnuYnIvl3yomIIz7MXZMn9hydRCrR3FSiualEc1OJ5qYSzU0lmptKNDePjWgwcPePT7/g+4cp8wCW4GXaryK3tL+mLdD5x62ppllgu7bso8q/2HIbzGWdNmWnSJwAAAAASUVORK5CYII=); | ||||
| 	background-size:11px 15px; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * | ||||
|  * The touch icon (if available) | ||||
|  * | ||||
|  */ | ||||
| #addToHomeScreen .addToHomeTouchIcon { | ||||
| 	display:block; | ||||
| 	float:left; | ||||
| 	-webkit-border-radius:6px; | ||||
| 	border-radius:6px; | ||||
| 	-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.5), | ||||
| 		inset 0 0 2px rgba(255,255,255,0.9); | ||||
| 	box-shadow:0 1px 3px rgba(0,0,0,0.5), | ||||
| 		inset 0 0 2px rgba(255,255,255,0.9); | ||||
| 	background-repeat:no-repeat; | ||||
| 	width:57px; height:57px; | ||||
| 	-webkit-background-size:57px 57px; | ||||
| 	background-size:57px 57px; | ||||
| 	margin:0 12px 0 0; | ||||
| 	border:1px solid #333; | ||||
| 	-webkit-background-clip:padding-box; | ||||
| 	background-clip:padding-box; | ||||
| } | ||||
| @@ -1,111 +0,0 @@ | ||||
| //	https://github.com/h5bp/Effeckt.css | ||||
|  | ||||
|  | ||||
| @mixin slide () { | ||||
| 	-webkit-transform: translate3d(0, 0, 0); | ||||
| 	transform: translate3d(0, 0, 0); | ||||
|  | ||||
| 	&.left { | ||||
| 		-webkit-transform: translate3d(-100%, 0, 0); | ||||
| 		transform: translate3d(-100%, 0, 0); | ||||
| 	} | ||||
|  | ||||
| 	&.center { | ||||
| 		-webkit-transform: translate3d(0, 0, 0); | ||||
| 		transform: translate3d(0, 0, 0); | ||||
| 	} | ||||
|  | ||||
| 	&.right { | ||||
| 		-webkit-transform: translate3d(100%, 0, 0); | ||||
| 		transform: translate3d(100%, 0, 0); | ||||
| 		visibility: hidden; | ||||
| 		display: none; | ||||
| 		 | ||||
| 		&.transition { | ||||
| 			visibility: visible; | ||||
| 			display: block; | ||||
| 		} | ||||
|  	} | ||||
|  | ||||
| 	&.transition { | ||||
| 		-webkit-transition-duration: .25s; | ||||
| 		transition-duration: .25s; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| //	http://coenraets.org/blog/2013/03/hardware-accelerated-page-transitions-for-mobile-web-apps-phonegap-apps/ | ||||
| .page { | ||||
| 	position: absolute; | ||||
|  | ||||
| 	top: 0; | ||||
| 	left: 0; | ||||
| 	width: 100%; | ||||
| 	height: 100%; | ||||
|  | ||||
| 	@include slide(); | ||||
| } | ||||
|  | ||||
| /* | ||||
| .registrationForm { | ||||
| 	.steps { | ||||
| 		.step { | ||||
| 			position: absolute; | ||||
|  | ||||
| //			top: 0; | ||||
| //			left: 0; | ||||
| //			width: 100%; | ||||
| //			height: 100%; | ||||
|  | ||||
| 			.slide(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| */ | ||||
|  | ||||
| //---------------------------------------------------------------------- | ||||
| //	tentative 3D transformations | ||||
| /* | ||||
| .page { | ||||
| 	transform: rotateY(   0deg) translateZ( 100px); | ||||
|  | ||||
| 	&.left { | ||||
|  		transform: rotateY( -90deg) translateZ( 100px); | ||||
| 	} | ||||
|  | ||||
| 	&.center { | ||||
| 		transform: rotateY(   0deg) translateZ( 100px); | ||||
| 	} | ||||
|  | ||||
| 	&.right { | ||||
|  		transform: rotateY(  90deg) translateZ( 100px); | ||||
|  	} | ||||
| } | ||||
|  | ||||
| #mainDiv { | ||||
| 	width: 100%; | ||||
| 	height: 100%; | ||||
| 	position: absolute; | ||||
| 	transform-style: preserve-3d; | ||||
|  | ||||
| 	transition: transform 3s; | ||||
|  | ||||
| 	&.show-front  { transform: translateZ( -100px ) rotateY(    0deg ); } | ||||
| 	&.show-back   { transform: translateZ( -100px ) rotateX( -180deg ); } | ||||
| 	&.show-right  { transform: translateZ( -100px ) rotateY(  -90deg ); } | ||||
| 	&.show-left   { transform: translateZ( -100px ) rotateY(   90deg ); } | ||||
| 	&.show-top    { transform: translateZ( -100px ) rotateX(  -90deg ); } | ||||
| 	&.show-bottom { transform: translateZ( -100px ) rotateX(   90deg ); } | ||||
| } | ||||
| */ | ||||
| //======================================================================= | ||||
|  | ||||
|  | ||||
| //======================================================================= | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| //======================================================== | ||||
| @@ -1,96 +0,0 @@ | ||||
| div.checkbox { | ||||
| 	display: block; | ||||
| 	margin-bottom: 20px; | ||||
| 	@include border-radius(4px); | ||||
| 	border: 2px solid white; | ||||
| 	background-color: white; | ||||
| 	width: 80px; | ||||
| 	position: relative; | ||||
| 	height: 32px; | ||||
|  | ||||
| 	&:before { | ||||
| 		content: "ON"; | ||||
| 		padding-left: 9px; | ||||
| 		line-height: 32px; | ||||
| 		color: $solarize-Accent-Cyan; | ||||
| 		font-size: 14px; | ||||
| 		font-weight: 600; | ||||
|  | ||||
| 	} | ||||
|  | ||||
| 	&:after { | ||||
| 		content: "OFF"; | ||||
| //		padding-left: 12px; | ||||
| 		padding-left: 25px; | ||||
| 		line-height: 32px; | ||||
| 		color: $solarize-Accent-Cyan; | ||||
| 		font-size: 14px; | ||||
| 		font-weight: 600; | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
| 	label.check {  | ||||
| 		display: block; | ||||
| 		width: 40px; | ||||
| 		height: 30px; | ||||
| 		@include border-radius(3px); | ||||
| 		background-color: $solarize-Accent-Magenta; | ||||
| 		border: 1px solid $solarize-Accent-Magenta; | ||||
| 		position: absolute; | ||||
| 		top: 0px; | ||||
| 		left: 0px; | ||||
| 	} | ||||
|  | ||||
|  | ||||
|  | ||||
| 	input[type=checkbox] { | ||||
| 		display: none; | ||||
| 	} | ||||
|  | ||||
| 	input[type=checkbox]:checked + label.check { | ||||
| 		top: 0px; | ||||
| 		left: 38px; | ||||
| 		@include animation(labelON, .2s, ease-in, 1); | ||||
| 	} | ||||
|  | ||||
| 	input[type=checkbox] + label.check { | ||||
| 		top: 0px; | ||||
| 		left: 0px; | ||||
| 		@include animation(labelOFF, .2s, ease-in, 1); | ||||
| 	} | ||||
|  | ||||
| 	label.info { | ||||
| 		position: absolute; | ||||
| 		color: white; | ||||
| 		top: 0px; | ||||
| 		left: 100px; | ||||
| 		line-height: 32px; | ||||
| 		width: 200px; | ||||
| 		font-size: 16pt; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @include keyframes(labelON) { | ||||
| 	0% { | ||||
| 		top: 0px; | ||||
| 		left: 0px; | ||||
| 	} | ||||
| 	 | ||||
| 	100% {  | ||||
| 		top: 0px; | ||||
| 		left: 38px; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @include keyframes(labelOFF) { | ||||
| 	0% { | ||||
| 		top: 0px; | ||||
| 		left: 38px; | ||||
| 	} | ||||
| 	 | ||||
| 	100% {  | ||||
| 		top: 0px; | ||||
| 		left: 0px; | ||||
| 	} | ||||
| } | ||||
| @@ -1,138 +0,0 @@ | ||||
| // -------------------------------------------------- | ||||
| //	Flexbox LESS mixins | ||||
| //	The spec: http://www.w3.org/TR/css3-flexbox | ||||
| // | ||||
| //	Other info: | ||||
| //	- http://philipwalton.github.io/solved-by-flexbox/ | ||||
| // -------------------------------------------------- | ||||
|   | ||||
| // Flexbox display | ||||
| // flex or inline-flex | ||||
| .flex-display(@display: flex) { | ||||
| 	display: ~"-webkit-@{display}"; | ||||
| 	display: ~"-moz-@{display}"; | ||||
| 	display: ~"-ms-@{display}box"; // IE10 uses -ms-flexbox | ||||
| 	display: ~"-ms-@{display}"; // IE11 | ||||
| 	display: @display; | ||||
| } | ||||
|   | ||||
| // The 'flex' shorthand | ||||
| // - applies to: flex items | ||||
| // <positive-number>, initial, auto, or none | ||||
| .flex(@columns: initial) { | ||||
| 	-webkit-flex: @columns; | ||||
| 	   -moz-flex: @columns; | ||||
| 	    -ms-flex: @columns; | ||||
| 	        flex: @columns; | ||||
| } | ||||
|   | ||||
| // Flex Flow Direction | ||||
| // - applies to: flex containers | ||||
| // row | row-reverse | column | column-reverse | ||||
| .flex-direction(@direction: row) { | ||||
| 	-webkit-flex-direction: @direction; | ||||
| 	   -moz-flex-direction: @direction; | ||||
| 	    -ms-flex-direction: @direction; | ||||
| 	        flex-direction: @direction; | ||||
| } | ||||
|   | ||||
| // Flex Line Wrapping | ||||
| // - applies to: flex containers | ||||
| // nowrap | wrap | wrap-reverse | ||||
| .flex-wrap(@wrap: nowrap) { | ||||
| 	-webkit-flex-wrap: @wrap; | ||||
| 	   -moz-flex-wrap: @wrap; | ||||
| 	    -ms-flex-wrap: @wrap; | ||||
| 	        flex-wrap: @wrap; | ||||
| } | ||||
|   | ||||
| // Flex Direction and Wrap | ||||
| // - applies to: flex containers | ||||
| // <flex-direction> || <flex-wrap> | ||||
| .flex-flow(@flow) { | ||||
| 	-webkit-flex-flow: @flow; | ||||
| 	   -moz-flex-flow: @flow; | ||||
| 	    -ms-flex-flow: @flow; | ||||
| 	        flex-flow: @flow; | ||||
| } | ||||
|   | ||||
| // Display Order | ||||
| // - applies to: flex items | ||||
| // <integer> | ||||
| .flex-order(@order: 0) { | ||||
| 	-webkit-order: @order; | ||||
| 	   -moz-order: @order; | ||||
| 	    -ms-order: @order; | ||||
| 	        order: @order; | ||||
| } | ||||
|   | ||||
| // Flex grow factor | ||||
| // - applies to: flex items | ||||
| // <number> | ||||
| .flex-grow(@grow: 0) { | ||||
| 	-webkit-flex-grow: @grow; | ||||
| 	   -moz-flex-grow: @grow; | ||||
| 	    -ms-flex-grow: @grow; | ||||
| 	        flex-grow: @grow; | ||||
| } | ||||
|   | ||||
| // Flex shr | ||||
| // - applies to: flex itemsink factor | ||||
| // <number>  | ||||
| .flex-shrink(@shrink: 1) { | ||||
| 	-webkit-flex-shrink: @shrink; | ||||
| 	   -moz-flex-shrink: @shrink; | ||||
| 	    -ms-flex-shrink: @shrink; | ||||
| 	        flex-shrink: @shrink; | ||||
| } | ||||
|   | ||||
| // Flex basis | ||||
| // - the initial main size of the flex item | ||||
| // - applies to: flex itemsnitial main size of the flex item | ||||
| // <width>  | ||||
| .flex-basis(@width: auto) { | ||||
| 	-webkit-flex-basis: @width; | ||||
| 	   -moz-flex-basis: @width; | ||||
| 	    -ms-flex-basis: @width; | ||||
| 	        flex-basis: @width; | ||||
| } | ||||
|   | ||||
| // Axis Alignment | ||||
| // - applies to: flex containers | ||||
| // flex-start | flex-end | center | space-between | space-around  | ||||
| .justify-content(@justify: flex-start) { | ||||
| 	-webkit-justify-content: @justify; | ||||
| 	   -moz-justify-content: @justify; | ||||
| 	    -ms-justify-content: @justify; | ||||
| 	        justify-content: @justify; | ||||
| } | ||||
|   | ||||
| // Packing Flex Lines | ||||
| // - applies to: multi-line flex containers | ||||
| // flex-start | flex-end | center | space-between | space-around | stretch  | ||||
| .align-content(@align: stretch) { | ||||
| 	-webkit-align-content: @align; | ||||
| 	   -moz-align-content: @align; | ||||
| 	    -ms-align-content: @align; | ||||
| 	        align-content: @align; | ||||
| } | ||||
|   | ||||
| // Cross-axis Alignment | ||||
| // - applies to: flex containers | ||||
| // flex-start | flex-end | center | baseline | stretch  | ||||
| .align-items(@align: stretch) { | ||||
| 	-webkit-align-items: @align; | ||||
| 	   -moz-align-items: @align; | ||||
| 	    -ms-align-items: @align; | ||||
| 	        align-items: @align; | ||||
| } | ||||
|   | ||||
| // Cross-axis Alignment | ||||
| // - applies to: flex items | ||||
| // auto | flex-start | flex-end | center | baseline | stretch  | ||||
| .align-self(@align: auto) { | ||||
| 	-webkit-align-self: @align; | ||||
| 	   -moz-align-self: @align; | ||||
| 	    -ms-align-self: @align; | ||||
| 	        align-self: @align; | ||||
| } | ||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										164
									
								
								frontend/delta/tests/SimpleTest/SimpleTest.Async.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								frontend/delta/tests/SimpleTest/SimpleTest.Async.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,164 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| MochiKit.Base.update(Clipperz.Async.Deferred.prototype, { | ||||
| /* | ||||
| 	'_addTest': function(anExpectedValue, aDescription, isDeep, aResult) { | ||||
| 		if (isDeep) { | ||||
| 			SimpleTest.isDeeply(aResult, anExpectedValue, aDescription); | ||||
| 		} else { | ||||
| 			SimpleTest.is(aResult, anExpectedValue, aDescription); | ||||
| 		} | ||||
|  | ||||
| 		return aResult; | ||||
| 	}, | ||||
| */ | ||||
| 	'addTest': function (anExpectedValue, aDescription, isDeep) { | ||||
| //		this.addMethod(this, '_addTest', anExpectedValue, aDescription, isDeep); | ||||
| //		this.addCallback(Clipperz.Async.test, anExpectedValue, aDescription, isDeep); | ||||
|  | ||||
| 		if (isDeep) { | ||||
| //			SimpleTest.isDeeply(aResult, anExpectedValue, aDescription); | ||||
| 			this.addCallback(Clipperz.Async.Test.isDeeply(anExpectedValue, aDescription)); | ||||
| 		} else { | ||||
| //			SimpleTest.is(aResult, anExpectedValue, aDescription); | ||||
| 			this.addCallback(Clipperz.Async.Test.is(anExpectedValue, aDescription)); | ||||
| 		} | ||||
| 	}, | ||||
|  | ||||
| 	//------------------------------------------------------------------------- | ||||
|  | ||||
| 	'shouldSucceed': function (aDescription) { | ||||
| 		this.addCallbackPass(SimpleTest.ok, true,  aDescription); | ||||
| 		this.addErrbackPass (SimpleTest.ok, false, aDescription); | ||||
| 		this.addBoth(MochiKit.Async.succeed, null); | ||||
| 	}, | ||||
|  | ||||
| 	'shouldFail': function (aDescription) { | ||||
| 		this.addCallbackPass(SimpleTest.ok, false, aDescription); | ||||
| 		this.addErrbackPass (SimpleTest.ok, true,  aDescription); | ||||
| 		this.addBoth(MochiKit.Async.succeed, null); | ||||
| 	}, | ||||
|  | ||||
| 	//------------------------------------------------------------------------- | ||||
|  | ||||
| }); | ||||
|  | ||||
|  | ||||
| Clipperz.Async.Test = {}; | ||||
| MochiKit.Base.update(Clipperz.Async.Test, { | ||||
|  | ||||
| 	'is': function (anExpectedResult, aDescription) { | ||||
| 		return MochiKit.Base.partial(function (anExpectedResult, aDescription, aResult) { | ||||
| 			SimpleTest.is(aResult, anExpectedResult, aDescription); | ||||
| 		 | ||||
| 			return aResult; | ||||
| 		}, anExpectedResult, aDescription); | ||||
| 	}, | ||||
|  | ||||
| 	//------------------------------------------------------------------------- | ||||
|  | ||||
| 	'ok': function (aDescription) { | ||||
| 		return MochiKit.Base.partial(function (aDescription, aResult) { | ||||
| 			SimpleTest.ok(aResult, aDescription); | ||||
| 		 | ||||
| 			return aResult; | ||||
| 		}, aDescription); | ||||
| 	}, | ||||
|  | ||||
| 	//------------------------------------------------------------------------- | ||||
|  | ||||
| 	'fail': function(aDescription) { | ||||
| 		return MochiKit.Base.partial(function (aDescription, aResult) { | ||||
| 			SimpleTest.ok(!aResult, aDescription); | ||||
| 		 | ||||
| 			return aResult; | ||||
| 		}, aDescription); | ||||
| 	}, | ||||
|  | ||||
| 	//------------------------------------------------------------------------- | ||||
|  | ||||
| 	'isDeeply': function (anExpectedResult, aDescription) { | ||||
| 		return MochiKit.Base.partial(function (anExpectedResult, aDescription, aResult) { | ||||
| 			SimpleTest.isDeeply(aResult, anExpectedResult, aDescription); | ||||
| 		 | ||||
| 			return aResult; | ||||
| 		}, anExpectedResult, aDescription); | ||||
| 	}, | ||||
| 	 | ||||
| 	//------------------------------------------------------------------------- | ||||
| 	__syntaxFix__: "syntax fix" | ||||
| }); | ||||
|  | ||||
|  | ||||
| SimpleTest.runDeferredTests = function (aName, aTestSet, aTestArguments) { | ||||
| 	try { | ||||
| 		var deferredTests; | ||||
| 		var aTestName; | ||||
| 		var title; | ||||
| 		 | ||||
| 		deferredTests = new Clipperz.Async.Deferred(aName + " <deferred test set>", aTestArguments); | ||||
|  | ||||
| 		title = aName; | ||||
|  | ||||
| 		aTestName = window.location.href.match(/#.*/); | ||||
| 		if (aTestName && (aTestName != '#')) { | ||||
| 			aTestName = aTestName[0].slice(1); | ||||
| 			if (aTestName in aTestSet) { | ||||
| 	//Clipperz.log("single test execution, via fragment identifier", aTestName); | ||||
| 				title += ' [' + aTestName + ']'; | ||||
| 				deferredTests.addCallback(aTestSet[aTestName], aTestArguments); | ||||
| 				deferredTests.addErrback(SimpleTest.ok, false, aTestName); | ||||
| 			} else { | ||||
| 				title = 'WRONG TEST NAME' | ||||
| 				deferredTests.addBoth(is, aTestName, null, "Wrong test name selected to run"); | ||||
| 			} | ||||
| 		} else { | ||||
| 			for (aTestName in aTestSet) { | ||||
| 				deferredTests.addCallback(aTestSet[aTestName], aTestArguments); | ||||
| 				deferredTests.addErrback(SimpleTest.ok, false, aTestName); | ||||
| 				deferredTests.addBoth(MochiKit.Async.wait, 0.5); | ||||
| 			} | ||||
| 			deferredTests.addBoth(is, true, true, "FINISH: completed the full stack of tests"); | ||||
| 		} | ||||
|  | ||||
| 		MochiKit.DOM.currentDocument().title = title; | ||||
|  | ||||
| 		deferredTests.addBoth(SimpleTest.finish); | ||||
| 		deferredTests.callback(); | ||||
|  | ||||
| 		SimpleTest.waitForExplicitFinish(); | ||||
| 	} catch (err) { | ||||
| 		var s = "test suite failure!\n"; | ||||
| 		var o = {}; | ||||
| 		var k = null; | ||||
| 		for (k in err) { | ||||
| 			// ensure unique keys?! | ||||
| 			if (!o[k]) { | ||||
| 				s +=  k + ": " + err[k] + "\n"; | ||||
| 				o[k] = err[k]; | ||||
| 			} | ||||
| 		} | ||||
| 		ok ( false, s ); | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										447
									
								
								frontend/delta/tests/SimpleTest/SimpleTest.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										447
									
								
								frontend/delta/tests/SimpleTest/SimpleTest.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,447 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| /** | ||||
|  * SimpleTest, a partial Test.Simple/Test.More API compatible test library. | ||||
|  * | ||||
|  * Why? | ||||
|  * | ||||
|  * Test.Simple doesn't work on IE < 6. | ||||
|  * TODO: | ||||
|  *  * Support the Test.Simple API used by MochiKit, to be able to test MochiKit  | ||||
|  * itself against IE 5.5 | ||||
|  * | ||||
| **/ | ||||
|  | ||||
| if (typeof(SimpleTest) == "undefined") { | ||||
|     var SimpleTest = {}; | ||||
| } | ||||
|  | ||||
| // Check to see if the TestRunner is present and has logging | ||||
| if (typeof(parent) != "undefined" && parent.TestRunner) { | ||||
|     SimpleTest._logEnabled = parent.TestRunner.logEnabled; | ||||
| } | ||||
|  | ||||
| SimpleTest._tests = []; | ||||
| SimpleTest._stopOnLoad = true; | ||||
| SimpleTest._scopeCopy = {}; | ||||
|  | ||||
| /** | ||||
|  * Saves a copy of the specified scope variables. | ||||
|  */ | ||||
| SimpleTest.saveScope = function (scope) { | ||||
|     SimpleTest._scopeCopy = {}; | ||||
|     for (var k in scope) { | ||||
|         SimpleTest._scopeCopy[k] = scope[k]; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Verifies the specified scope against the stored copy and reports | ||||
|  * any differences as test failures. | ||||
|  */ | ||||
| SimpleTest.verifyScope = function (scope) { | ||||
|     var filter = ['test', '_firebug','_FirebugConsole','XMLHttpRequest','Audio', | ||||
|                   'XSLTProcessor','Option','Image','scrollMaxX','scrollMaxY', | ||||
|                   'clipboardData']; | ||||
|     for (var k in scope) { | ||||
|         if (MochiKit.Base.findValue(filter, k) < 0) { | ||||
|             var v = scope[k]; | ||||
|             var old = SimpleTest._scopeCopy[k]; | ||||
|             if (v !== old && typeof(old) === "undefined") { | ||||
|                 SimpleTest.ok(false, "scope modified, variable " + k + " was added"); | ||||
|             } else if (v !== old) { | ||||
|                 SimpleTest.ok(false, "scope modified, variable " + k + " changed from: " + old + ", to: " + v); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     for (var k in SimpleTest._scopeCopy) { | ||||
|         if (!(k in scope)) { | ||||
|             SimpleTest.ok(false, "scope modified, variable " + k + " has been removed"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Something like assert. | ||||
|  */ | ||||
| SimpleTest.ok = function (condition, name, diag) { | ||||
|     var test = {'result': !!condition, 'name': name, 'diag': diag || ""}; | ||||
|     if (SimpleTest._logEnabled) { | ||||
|         var msg = test.result ? "PASS" : "FAIL"; | ||||
|         msg += " | " + test.name; | ||||
|         if (test.result) { | ||||
|             parent.TestRunner.logger.log(msg); | ||||
|         } else { | ||||
|             msg += " | " + test.diag; | ||||
|             parent.TestRunner.logger.error(msg); | ||||
|         } | ||||
|     } | ||||
|     SimpleTest._tests.push(test); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Roughly equivalent to ok(a==b, name) | ||||
|  */ | ||||
| SimpleTest.is = function (a, b, name) { | ||||
|     var repr = MochiKit.Base.repr; | ||||
|     SimpleTest.ok(a == b, name, "got " + repr(a) + ", expected " + repr(b)); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Roughly equivalent to ok(compare(a,b)==0, name) | ||||
|  */ | ||||
| SimpleTest.eq = function (a, b, name) { | ||||
|     var base = MochiKit.Base; | ||||
|     var repr = base.repr; | ||||
|     try { | ||||
|         SimpleTest.ok(base.compare(a, b) == 0, name, "got " + repr(a) + ", expected " + repr(b)); | ||||
|     } catch (e) { | ||||
|         SimpleTest.ok(false, name, "exception in compare: " + repr(e)); | ||||
|     } | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Makes a test report, returns it as a DIV element. | ||||
| **/ | ||||
| SimpleTest.report = function () { | ||||
|     var DIV = MochiKit.DOM.DIV; | ||||
|     var passed = 0; | ||||
|     var failed = 0; | ||||
|     var results = MochiKit.Base.map( | ||||
|         function (test) { | ||||
|             var cls, msg; | ||||
|             if (test.result) { | ||||
|                 passed++; | ||||
|                 cls = "test_ok"; | ||||
|                 msg = "ok - " + test.name; | ||||
|             } else { | ||||
|                 failed++; | ||||
|                 cls = "test_not_ok"; | ||||
|                 msg = "not ok - " + test.name; | ||||
|                 if (test.diag != null && test.diag != "") { | ||||
|                     msg += ": " + test.diag; | ||||
|                 } | ||||
|             } | ||||
|             return DIV({"class": cls}, msg); | ||||
|         }, | ||||
|         SimpleTest._tests | ||||
|     ); | ||||
|     var summary_class = ((failed == 0) ? 'all_pass' : 'some_fail'); | ||||
|     return DIV({'class': 'tests_report'}, | ||||
|         DIV({'class': 'tests_summary ' + summary_class}, | ||||
|             DIV({'class': 'tests_passed'}, "Passed: " + passed), | ||||
|             DIV({'class': 'tests_failed'}, "Failed: " + failed)), | ||||
|         results | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Toggle element visibility | ||||
| **/ | ||||
| SimpleTest.toggle = function(el) { | ||||
|     if (MochiKit.Style.getStyle(el, 'display') == 'block') { | ||||
|         el.style.display = 'none'; | ||||
|     } else { | ||||
|         el.style.display = 'block'; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Toggle visibility for divs with a specific class. | ||||
| **/ | ||||
| SimpleTest.toggleByClass = function (cls) { | ||||
|     var elems = MochiKit.DOM.getElementsByTagAndClassName('div', cls); | ||||
|     MochiKit.Base.map(SimpleTest.toggle, elems); | ||||
| 	return false; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Shows the report in the browser | ||||
| **/ | ||||
|  | ||||
| SimpleTest.showReport = function() { | ||||
|     var base = MochiKit.Base; | ||||
|     var dom = MochiKit.DOM; | ||||
|     var togglePassed = dom.A({'href': '#'}, "Toggle passed tests"); | ||||
|     var toggleFailed = dom.A({'href': '#'}, "Toggle failed tests"); | ||||
|     togglePassed.onclick = base.partial(SimpleTest.toggleByClass, 'test_ok'); | ||||
|     toggleFailed.onclick = base.partial(SimpleTest.toggleByClass, 'test_not_ok'); | ||||
|     var body = document.getElementsByTagName("body")[0]; | ||||
|     var firstChild = body.childNodes[0]; | ||||
|     var addNode; | ||||
|     if (firstChild) { | ||||
|         addNode = function (el) { | ||||
|             body.insertBefore(el, firstChild); | ||||
|         }; | ||||
|     } else { | ||||
|         addNode = function (el) { | ||||
|             body.appendChild(el) | ||||
|         }; | ||||
|     } | ||||
|     addNode(togglePassed); | ||||
|     addNode(dom.SPAN(null, " ")); | ||||
|     addNode(toggleFailed); | ||||
|     addNode(SimpleTest.report()); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Tells SimpleTest to don't finish the test when the document is loaded, | ||||
|  * useful for asynchronous tests. | ||||
|  * | ||||
|  * When SimpleTest.waitForExplicitFinish is called, | ||||
|  * explicit SimpleTest.finish() is required. | ||||
| **/ | ||||
| SimpleTest.waitForExplicitFinish = function () { | ||||
|     SimpleTest._stopOnLoad = false; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Talks to the TestRunner if being ran on a iframe and the parent has a  | ||||
|  * TestRunner object. | ||||
| **/ | ||||
| SimpleTest.talkToRunner = function () { | ||||
|     if (typeof(parent) != "undefined" && parent.TestRunner) { | ||||
|         parent.TestRunner.testFinished(document); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Finishes the tests. This is automatically called, except when  | ||||
|  * SimpleTest.waitForExplicitFinish() has been invoked. | ||||
| **/ | ||||
| SimpleTest.finish = function () { | ||||
|     SimpleTest.showReport(); | ||||
|     SimpleTest.talkToRunner(); | ||||
| }; | ||||
|  | ||||
|  | ||||
| MochiKit.DOM.addLoadEvent(function() { | ||||
|     if (SimpleTest._stopOnLoad) { | ||||
|         SimpleTest.finish(); | ||||
|     } | ||||
| }); | ||||
|  | ||||
| //  --------------- Test.Builder/Test.More isDeeply() ----------------- | ||||
|  | ||||
|  | ||||
| SimpleTest.DNE = {dne: 'Does not exist'}; | ||||
| SimpleTest.LF = "\r\n"; | ||||
| SimpleTest._isRef = function (object) { | ||||
|     var type = typeof(object); | ||||
|     return type == 'object' || type == 'function'; | ||||
| }; | ||||
|  | ||||
|  | ||||
| SimpleTest._deepCheck = function (e1, e2, stack, seen) { | ||||
|     var ok = false; | ||||
|     // Either they're both references or both not. | ||||
|     var sameRef = !(!SimpleTest._isRef(e1) ^ !SimpleTest._isRef(e2)); | ||||
|     if (e1 == null && e2 == null) { | ||||
|         ok = true; | ||||
|     } else if (e1 != null ^ e2 != null) { | ||||
|         ok = false; | ||||
|     } else if (e1 == SimpleTest.DNE ^ e2 == SimpleTest.DNE) { | ||||
|         ok = false; | ||||
|     } else if (sameRef && e1 == e2) { | ||||
|         // Handles primitives and any variables that reference the same | ||||
|         // object, including functions. | ||||
|         ok = true; | ||||
|     } else if (SimpleTest.isa(e1, 'Array') && SimpleTest.isa(e2, 'Array')) { | ||||
|         ok = SimpleTest._eqArray(e1, e2, stack, seen); | ||||
|     } else if (typeof e1 == "object" && typeof e2 == "object") { | ||||
|         ok = SimpleTest._eqAssoc(e1, e2, stack, seen); | ||||
|     } else { | ||||
|         // If we get here, they're not the same (function references must | ||||
|         // always simply rererence the same function). | ||||
|         stack.push({ vals: [e1, e2] }); | ||||
|         ok = false; | ||||
|     } | ||||
|     return ok; | ||||
| }; | ||||
|  | ||||
| SimpleTest._eqArray = function (a1, a2, stack, seen) { | ||||
|     // Return if they're the same object. | ||||
|     if (a1 == a2) return true; | ||||
|  | ||||
|     // JavaScript objects have no unique identifiers, so we have to store | ||||
|     // references to them all in an array, and then compare the references | ||||
|     // directly. It's slow, but probably won't be much of an issue in | ||||
|     // practice. Start by making a local copy of the array to as to avoid | ||||
|     // confusing a reference seen more than once (such as [a, a]) for a | ||||
|     // circular reference. | ||||
|     for (var j = 0; j < seen.length; j++) { | ||||
|         if (seen[j][0] == a1) { | ||||
|             return seen[j][1] == a2; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // If we get here, we haven't seen a1 before, so store it with reference | ||||
|     // to a2. | ||||
|     seen.push([ a1, a2 ]); | ||||
|  | ||||
|     var ok = true; | ||||
|     // Only examines enumerable attributes. Only works for numeric arrays! | ||||
|     // Associative arrays return 0. So call _eqAssoc() for them, instead. | ||||
|     var max = a1.length > a2.length ? a1.length : a2.length; | ||||
|     if (max == 0) return SimpleTest._eqAssoc(a1, a2, stack, seen); | ||||
|     for (var i = 0; i < max; i++) { | ||||
|         var e1 = i > a1.length - 1 ? SimpleTest.DNE : a1[i]; | ||||
|         var e2 = i > a2.length - 1 ? SimpleTest.DNE : a2[i]; | ||||
|         stack.push({ type: 'Array', idx: i, vals: [e1, e2] }); | ||||
|         if (ok = SimpleTest._deepCheck(e1, e2, stack, seen)) { | ||||
|             stack.pop(); | ||||
|         } else { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     return ok; | ||||
| }; | ||||
|  | ||||
| SimpleTest._eqAssoc = function (o1, o2, stack, seen) { | ||||
|     // Return if they're the same object. | ||||
|     if (o1 == o2) return true; | ||||
|  | ||||
|     // JavaScript objects have no unique identifiers, so we have to store | ||||
|     // references to them all in an array, and then compare the references | ||||
|     // directly. It's slow, but probably won't be much of an issue in | ||||
|     // practice. Start by making a local copy of the array to as to avoid | ||||
|     // confusing a reference seen more than once (such as [a, a]) for a | ||||
|     // circular reference. | ||||
|     seen = seen.slice(0); | ||||
|     for (var j = 0; j < seen.length; j++) { | ||||
|         if (seen[j][0] == o1) { | ||||
|             return seen[j][1] == o2; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // If we get here, we haven't seen o1 before, so store it with reference | ||||
|     // to o2. | ||||
|     seen.push([ o1, o2 ]); | ||||
|  | ||||
|     // They should be of the same class. | ||||
|  | ||||
|     var ok = true; | ||||
|     // Only examines enumerable attributes. | ||||
|     var o1Size = 0; for (var i in o1) o1Size++; | ||||
|     var o2Size = 0; for (var i in o2) o2Size++; | ||||
|     var bigger = o1Size > o2Size ? o1 : o2; | ||||
|     for (var i in bigger) { | ||||
|         var e1 = o1[i] == undefined ? SimpleTest.DNE : o1[i]; | ||||
|         var e2 = o2[i] == undefined ? SimpleTest.DNE : o2[i]; | ||||
|         stack.push({ type: 'Object', idx: i, vals: [e1, e2] }); | ||||
|         if (ok = SimpleTest._deepCheck(e1, e2, stack, seen)) { | ||||
|             stack.pop(); | ||||
|         } else { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     return ok; | ||||
| }; | ||||
|  | ||||
| SimpleTest._formatStack = function (stack) { | ||||
|     var variable = '$Foo'; | ||||
|     for (var i = 0; i < stack.length; i++) { | ||||
|         var entry = stack[i]; | ||||
|         var type = entry['type']; | ||||
|         var idx = entry['idx']; | ||||
|         if (idx != null) { | ||||
|             if (/^\d+$/.test(idx)) { | ||||
|                 // Numeric array index. | ||||
|                 variable += '[' + idx + ']'; | ||||
|             } else { | ||||
|                 // Associative array index. | ||||
|                 idx = idx.replace("'", "\\'"); | ||||
|                 variable += "['" + idx + "']"; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     var vals = stack[stack.length-1]['vals'].slice(0, 2); | ||||
|     var vars = [ | ||||
|         variable.replace('$Foo',     'got'), | ||||
|         variable.replace('$Foo',     'expected') | ||||
|     ]; | ||||
|  | ||||
|     var out = "Structures begin differing at:" + SimpleTest.LF; | ||||
|     for (var i = 0; i < vals.length; i++) { | ||||
|         var val = vals[i]; | ||||
|         if (val == null) { | ||||
|             val = 'undefined'; | ||||
|         } else { | ||||
|              val == SimpleTest.DNE ? "Does not exist" : "'" + val + "'"; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     out += vars[0] + ' = ' + vals[0] + SimpleTest.LF; | ||||
|     out += vars[1] + ' = ' + vals[1] + SimpleTest.LF; | ||||
|      | ||||
|     return '    ' + out; | ||||
| }; | ||||
|  | ||||
|  | ||||
| SimpleTest.isDeeply = function (it, as, name) { | ||||
|     var ok; | ||||
|     // ^ is the XOR operator. | ||||
|     if (SimpleTest._isRef(it) ^ SimpleTest._isRef(as)) { | ||||
|         // One's a reference, one isn't. | ||||
|         ok = false; | ||||
|     } else if (!SimpleTest._isRef(it) && !SimpleTest._isRef(as)) { | ||||
|         // Neither is an object. | ||||
|         ok = SimpleTest.is(it, as, name); | ||||
|     } else { | ||||
|         // We have two objects. Do a deep comparison. | ||||
|         var stack = [], seen = []; | ||||
|         if ( SimpleTest._deepCheck(it, as, stack, seen)) { | ||||
|             ok = SimpleTest.ok(true, name); | ||||
|         } else { | ||||
|             ok = SimpleTest.ok(false, name, SimpleTest._formatStack(stack)); | ||||
|         } | ||||
|     } | ||||
|     return ok; | ||||
| }; | ||||
|  | ||||
| SimpleTest.typeOf = function (object) { | ||||
|     var c = Object.prototype.toString.apply(object); | ||||
|     var name = c.substring(8, c.length - 1); | ||||
|     if (name != 'Object') return name; | ||||
|     // It may be a non-core class. Try to extract the class name from | ||||
|     // the constructor function. This may not work in all implementations. | ||||
|     if (/function ([^(\s]+)/.test(Function.toString.call(object.constructor))) { | ||||
|         return RegExp.$1; | ||||
|     } | ||||
|     // No idea. :-( | ||||
|     return name; | ||||
| }; | ||||
|  | ||||
| SimpleTest.isa = function (object, clas) { | ||||
|     return SimpleTest.typeOf(object) == clas; | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| // Global symbols: | ||||
| var ok = SimpleTest.ok; | ||||
| var is = SimpleTest.is; | ||||
| var isDeeply = SimpleTest.isDeeply; | ||||
							
								
								
									
										256
									
								
								frontend/delta/tests/SimpleTest/TestRunner.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										256
									
								
								frontend/delta/tests/SimpleTest/TestRunner.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,256 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| /** | ||||
|  * TestRunner: A test runner for SimpleTest | ||||
|  * TODO: | ||||
|  *  | ||||
|  *  * Avoid moving iframes: That causes reloads on mozilla and opera. | ||||
|  * | ||||
|  * | ||||
| **/ | ||||
| var TestRunner = {}; | ||||
| TestRunner.logEnabled = false; | ||||
| TestRunner._iframes = {}; | ||||
| TestRunner._iframeDocuments = {}; | ||||
| TestRunner._iframeRows = {}; | ||||
| TestRunner._currentTest = 0; | ||||
| TestRunner._urls = []; | ||||
| TestRunner._testsDiv = DIV(); | ||||
| TestRunner._progressDiv = DIV(); | ||||
| TestRunner._summaryDiv = DIV(null,  | ||||
|     H1(null, "Tests Summary"), | ||||
|     TABLE(null,  | ||||
|         THEAD(null,  | ||||
|             TR(null, | ||||
|                 TH(null, "Test"),  | ||||
|                 TH(null, "Passed"),  | ||||
|                 TH(null, "Failed") | ||||
|             ) | ||||
|         ), | ||||
| 		TFOOT(/*null, TR(null, TH(null, "-"), TH(null, "--"), TH(null, "---"))*/), | ||||
|         TBODY() | ||||
|     ) | ||||
| ); | ||||
|  | ||||
| /** | ||||
|  * This function is called after generating the summary. | ||||
| **/ | ||||
| TestRunner.onComplete = null; | ||||
|  | ||||
| /** | ||||
|  * If logEnabled is true, this is the logger that will be used. | ||||
| **/ | ||||
| TestRunner.logger = MochiKit.Logging.logger; | ||||
|  | ||||
| /** | ||||
|  * Toggle element visibility | ||||
| **/ | ||||
| TestRunner._toggle = function(el) { | ||||
|     if (el.className == "noshow") { | ||||
|         el.className = ""; | ||||
|         el.style.cssText = ""; | ||||
|     } else { | ||||
|         el.className = "noshow"; | ||||
|         el.style.cssText = "width:0px; height:0px; border:0px;"; | ||||
|     } | ||||
| }; | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Creates the iframe that contains a test | ||||
| **/ | ||||
| TestRunner._makeIframe = function (url) { | ||||
|     var iframe = document.createElement('iframe'); | ||||
|     iframe.src = url; | ||||
|     iframe.name = url; | ||||
|     iframe.width = "500"; | ||||
|     var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0]; | ||||
|     var tr = TR(null, TD({'colspan': '3'}, iframe)); | ||||
|     iframe._row = tr; | ||||
|     tbody.appendChild(tr); | ||||
|     return iframe; | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * TestRunner entry point. | ||||
|  * | ||||
|  * The arguments are the URLs of the test to be ran. | ||||
|  * | ||||
| **/ | ||||
| TestRunner.runTests = function (/*url...*/) { | ||||
|     if (TestRunner.logEnabled) | ||||
|         TestRunner.logger.log("SimpleTest START"); | ||||
|    | ||||
|     var body = document.getElementsByTagName("body")[0]; | ||||
|     appendChildNodes(body, | ||||
|         TestRunner._testsDiv, | ||||
|         TestRunner._progressDiv, | ||||
|         TestRunner._summaryDiv | ||||
|     ); | ||||
|     for (var i = 0; i < arguments.length; i++) { | ||||
|         TestRunner._urls.push(arguments[i]);  | ||||
|     } | ||||
|  | ||||
|     TestRunner.runNextTest(); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Run the next test. If no test remains, calls makeSummary | ||||
| **/ | ||||
| TestRunner.runNextTest = function() { | ||||
|     if (TestRunner._currentTest < TestRunner._urls.length) { | ||||
|         var url = TestRunner._urls[TestRunner._currentTest]; | ||||
|         var progress = SPAN(null, | ||||
|             "Running ", A({href:url}, url), "..." | ||||
|         ); | ||||
|          | ||||
|         if (TestRunner.logEnabled) | ||||
|             TestRunner.logger.log(scrapeText(progress)); | ||||
|          | ||||
|         TestRunner._progressDiv.appendChild(progress); | ||||
|         TestRunner._iframes[url] = TestRunner._makeIframe(url); | ||||
|     }  else { | ||||
|         TestRunner.makeSummary(); | ||||
|         if (TestRunner.onComplete) { | ||||
|             TestRunner.onComplete(); | ||||
| 		} | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * This stub is called by SimpleTest when a test is finished. | ||||
| **/ | ||||
| TestRunner.testFinished = function (doc) { | ||||
|     appendChildNodes(TestRunner._progressDiv, SPAN(null, "Done"), BR()); | ||||
|     var finishedURL = TestRunner._urls[TestRunner._currentTest]; | ||||
|      | ||||
|     if (TestRunner.logEnabled) | ||||
|         TestRunner.logger.debug("SimpleTest finished " + finishedURL); | ||||
|      | ||||
|     TestRunner._iframeDocuments[finishedURL] = doc; | ||||
|     // TestRunner._iframes[finishedURL].style.display = "none"; | ||||
| 	if (finishedURL != null) { | ||||
|     	TestRunner._toggle(TestRunner._iframes[finishedURL]); | ||||
|     	TestRunner._currentTest++; | ||||
|     	TestRunner.runNextTest(); | ||||
| 	} | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Display the summary in the browser | ||||
| **/ | ||||
| /* | ||||
| TestRunner.makeSummary = function() { | ||||
|     if (TestRunner.logEnabled) | ||||
|         TestRunner.logger.log("SimpleTest FINISHED"); | ||||
|     var rows = []; | ||||
|     for (var url in TestRunner._iframeDocuments) { | ||||
|         var doc = TestRunner._iframeDocuments[url]; | ||||
|         var nOK = withDocument(doc, | ||||
|             partial(getElementsByTagAndClassName, 'div', 'test_ok') | ||||
|         ).length; | ||||
|         var nNotOK = withDocument(doc, | ||||
|             partial(getElementsByTagAndClassName, 'div', 'test_not_ok') | ||||
|         ).length; | ||||
|         var toggle = partial(TestRunner._toggle, TestRunner._iframes[url]); | ||||
|         var jsurl = "TestRunner._toggle(TestRunner._iframes['" + url + "'])"; | ||||
|         var row = TR( | ||||
|             {'style': {'backgroundColor': nNotOK > 0 ? "#f00":"#0f0"}},  | ||||
|             TD(null, url), | ||||
|             TD(null, nOK), | ||||
|             TD(null, nNotOK) | ||||
|         ); | ||||
|         row.onclick = toggle; | ||||
|         var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0]; | ||||
|         tbody.insertBefore(row, TestRunner._iframes[url]._row) | ||||
|     } | ||||
| }; | ||||
| */ | ||||
|  | ||||
| TestRunner.makeSummary = function() { | ||||
|     var base = MochiKit.Base; | ||||
|     var dom = MochiKit.DOM; | ||||
|     var iter = MochiKit.Iter; | ||||
| 	var	total_Ok, total_not_Ok; | ||||
| 	 | ||||
| 	total_Ok = 0; | ||||
| 	total_not_Ok = 0; | ||||
| 	 | ||||
|     if (TestRunner.logEnabled) | ||||
|         TestRunner.logger.log("SimpleTest FINISHED"); | ||||
|     var rows = []; | ||||
|     for (var url in TestRunner._iframeDocuments) { | ||||
|         var doc = TestRunner._iframeDocuments[url]; | ||||
|         var nOK = withDocument(doc, | ||||
|             partial(getElementsByTagAndClassName, 'div', 'test_ok') | ||||
|         ).length; | ||||
|         var nNotOK = withDocument(doc, | ||||
|             partial(getElementsByTagAndClassName, 'div', 'test_not_ok') | ||||
|         ).length; | ||||
|         var toggle = partial(TestRunner._toggle, TestRunner._iframes[url]); | ||||
|         var jsurl = "TestRunner._toggle(TestRunner._iframes['" + url + "'])"; | ||||
|         var row = TR( | ||||
|             {'style': {'backgroundColor': nNotOK > 0 ? "#f00":"#0f0"}},  | ||||
|             TD(null, url), | ||||
|             TD(null, nOK), | ||||
|             TD(null, nNotOK) | ||||
|         ); | ||||
|         row.onclick = toggle; | ||||
|         var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0]; | ||||
|         tbody.insertBefore(row, TestRunner._iframes[url]._row); | ||||
|  | ||||
| 		total_Ok += nOK; | ||||
| 		total_not_Ok += nNotOK; | ||||
|     } | ||||
|  | ||||
| 	{ | ||||
|         var tfoot = TestRunner._summaryDiv.getElementsByTagName("tfoot")[0]; | ||||
|         tfoot.appendChild(TR(null, | ||||
|                 TH(null, ""),  | ||||
|                 TH({'style':"color:green;"}, total_Ok),  | ||||
|                 TH({'style':"color:" + ((total_not_Ok == 0) ? 'black' : 'red') + ";"}, total_not_Ok) | ||||
| 		)); | ||||
| 	} | ||||
|  | ||||
| 	var testRunnerResults; | ||||
| 	var i, c; | ||||
| 	 | ||||
| 	testRunnerResults = dom.DIV({'style': 'display:none; visibility:hidden;'}, null); | ||||
|  | ||||
| 	c = total_Ok; | ||||
| 	for (i=0; i<c; i++) { | ||||
| 		dom.appendChildNodes(testRunnerResults, dom.DIV({'class': 'test_ok'}, "ok")); | ||||
| 	} | ||||
| 	 | ||||
| 	c = total_not_Ok; | ||||
| 	for (i=0; i<c; i++) { | ||||
| 		dom.appendChildNodes(testRunnerResults, dom.DIV({'class': 'test_not_ok'}, "fail")); | ||||
| 	} | ||||
|  | ||||
| 	document.getElementsByTagName("body")[0].appendChild(testRunnerResults); | ||||
|  | ||||
|     if (typeof(parent) != "undefined" && parent.TestRunner) { | ||||
|         parent.TestRunner.testFinished(document); | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										51
									
								
								frontend/delta/tests/SimpleTest/test.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								frontend/delta/tests/SimpleTest/test.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it  | ||||
|   under the terms of the GNU Affero General Public License as published  | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| .test_ok { | ||||
| 	color: green; | ||||
| 	display: none; | ||||
| } | ||||
| .test_not_ok { | ||||
| 	color: red; | ||||
| 	display: block; | ||||
| } | ||||
|  | ||||
| .test_ok, .test_not_ok { | ||||
|    border-bottom-width: 2px; | ||||
|    border-bottom-style: solid; | ||||
|    border-bottom-color: black; | ||||
| } | ||||
|  | ||||
| .all_pass { | ||||
|     background-color: lime; | ||||
| } | ||||
|  | ||||
| .some_fail { | ||||
|     background-color: red; | ||||
| } | ||||
|  | ||||
| .tests_report { | ||||
| 	border-width: 2px; | ||||
| 	border-style: solid; | ||||
| 	width: 20em; | ||||
| } | ||||
| @@ -0,0 +1,100 @@ | ||||
| <!-- | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it  | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| --> | ||||
|  | ||||
| <html> | ||||
| <head> | ||||
| 	<title>Clipperz.PM.DataModel.DirectLogin - test</title> | ||||
| 	<script>Clipperz = {}</script> | ||||
|     <script type="text/javascript" src="../../../../../js/MochiKit/MochiKit.js"></script> | ||||
| 	<script type="text/javascript" src="../../../../../js/React/react-with-addons-0.10.0.js"></script> | ||||
|     <script type="text/javascript" src="../../../../SimpleTest/SimpleTest.js"></script> | ||||
|     <link rel="stylesheet" type="text/css" href="../../../../SimpleTest/test.css"> | ||||
|  | ||||
|  | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/YUI/Utils.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Base.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Date.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/ByteArray.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Logging.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Async.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Signal.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/KeyValueObjectStore.js'></script> | ||||
|  | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/Base.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/BigInt.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES_2.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SHA.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/PRNG.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SRP.js'></script> | ||||
|  | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Toll.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Test.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js'></script> | ||||
|  | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Connection.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Crypto.js'></script> | ||||
|  | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings/Strings_en-US.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Date.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/EncryptedRemoteObject.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.Field.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLogin.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginInput.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginBinding.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Legacy.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.RecordIndex.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Preferences.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/OneTimePassword.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.AccountInfo.js'></script> | ||||
|  | ||||
|     <script type="text/javascript" src="../../../../SimpleTest/SimpleTest.Async.js"></script> | ||||
| <script> | ||||
| 	Clipperz_IEisBroken = false; | ||||
| </script> | ||||
|  | ||||
| <!--[if IE]><script> | ||||
| Clipperz_IEisBroken = true; | ||||
| Clipperz_normalizedNewLine = '\x0d\x0a'; | ||||
| </script><![endif]--> | ||||
|  | ||||
| </head> | ||||
| <body> | ||||
|  | ||||
| <pre id="test"> | ||||
| <script> | ||||
| 	Clipperz.PM.Strings.Languages.setSelectedLanguage('en-us'); | ||||
| </script> | ||||
| <script type="text/javascript" src="User.data.js"></script> | ||||
| <script type="text/javascript" src="User.data.old.js"></script> | ||||
| <script type="text/javascript" src="DirectLogin.test.js"></script> | ||||
| </pre> | ||||
| </body> | ||||
| </html> | ||||
| @@ -0,0 +1,190 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| Clipperz.Crypto.PRNG.defaultRandomGenerator().fastEntropyAccumulationForTestingPurpose(); | ||||
|  | ||||
| var tests = { | ||||
|  | ||||
| /* | ||||
| 		user = new Clipperz.PM.DataModel.User({username:'test', getPassphraseFunction:function () { return 'test';}}); | ||||
| 		... | ||||
| 		deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['test_test_offline_copy_data']); | ||||
| 		deferredResult.addMethod(user, 'getRecord', '8280842f41162b673335b63860637e8472e8bbff0efa2bc78b0dbc5e09712e13');	 | ||||
|  | ||||
|  | ||||
| 		user = new Clipperz.PM.DataModel.User({username:'joe', getPassphraseFunction:function () { return 'clipperz';}}); | ||||
| 		... | ||||
| 		deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['joe_clipperz_offline_copy_data']); | ||||
| 		deferredResult.addMethod(user, 'getRecord', '5cdac63b317f3942da38f3a3de3b7f0e5d6678200951c6216230295550f63fb4');	//	WEB PASSWORD (0) | ||||
| 		deferredResult.addMethod(user, 'getRecord', '36ec1a41118813ced3553534fa2607d781cba687768db305beed368a8e06e113');	//	DIGG  (1) | ||||
| 		deferredResult.addMethod(user, 'getRecord', 'c0ce9130ca365bb02418d4305ea1d29e49c3f0e96d44b9d3cb6b4b6843d25065');	//	SAP   (2) | ||||
| 		deferredResult.addMethod(user, 'getRecord', 'd5f700b9c3367c39551ea49e00a9ab20dae09dd79d46047b983fc7c4bfaa050d');	//	YAHOO (4) | ||||
| 			DirectLogin references | ||||
| 			- dba0db679802f0e6aa6d0b7a6aaf42350aabc5f057409edd99a268a92ebb6496	//	Yahoo! Mail | ||||
| 			- aa18149164302d5dbe7e2d3724565b9550e00887b49978559783b2e38c625584	//	(Yahoo! Groups) | ||||
| 			- 6f7bbc4e42ea462b5246e6f51c3f86056bec50601ce2de6067c8c1d26f21c07f	//	(Flickr) | ||||
| 			- a7b32e72502804bf2946a2a8856139cbbb759c5777e6b3e673db1fdf7e3bd06e	//	(My Yahoo!) | ||||
| */ | ||||
|     //------------------------------------------------------------------------- | ||||
|  | ||||
| 	'editDirectLoginLabel_test': function (someTestArgs) { | ||||
| 		var deferredResult; | ||||
| 		var proxy; | ||||
| 		var user; | ||||
|  | ||||
| 		proxy = new Clipperz.PM.Proxy.Test({shouldPayTolls:true, isDefault:true, readOnly:false}); | ||||
| 		user = new Clipperz.PM.DataModel.User({username:'joe', getPassphraseFunction:function () { return 'clipperz';}}); | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred("editDirectLoginLabel_test", someTestArgs); | ||||
| 		deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['joe_clipperz_offline_copy_data']); | ||||
| 		deferredResult.addMethod(user, 'login'); | ||||
| 		deferredResult.addMethod(user, 'getRecord', 'd5f700b9c3367c39551ea49e00a9ab20dae09dd79d46047b983fc7c4bfaa050d');	//	YAHOO (4) | ||||
| 		deferredResult.addMethodcaller('directLogins'); | ||||
| 		deferredResult.addCallback(MochiKit.Base.itemgetter('dba0db679802f0e6aa6d0b7a6aaf42350aabc5f057409edd99a268a92ebb6496')); | ||||
| 		deferredResult.addCallback(function (aDirectLogin) { | ||||
| 			var innerDeferredResult; | ||||
| 			var updatedLabel; | ||||
| 			 | ||||
| 			updatedLabel = "updated Yahoo! Mail label"; | ||||
| 			 | ||||
| 			innerDeferredResult = new Clipperz.Async.Deferred("editDirectLoginLabel_test <inner>", someTestArgs); | ||||
| 			innerDeferredResult.addMethod(aDirectLogin, 'label'); | ||||
| 			innerDeferredResult.addTest("Yahoo! Mail", "The label of the selected direct login is correct."); | ||||
| 			innerDeferredResult.addMethod(aDirectLogin, 'setLabel', updatedLabel); | ||||
| 			 | ||||
| 			innerDeferredResult.addMethod(aDirectLogin, 'label'); | ||||
| 			innerDeferredResult.addTest(updatedLabel, "The DirectLogin returns the correct label even before committing data."); | ||||
|  | ||||
| 			innerDeferredResult.addMethod(user, 'hasPendingChanges'); | ||||
| 			innerDeferredResult.addTest(true, "When changing the label of a DirectLogin, the user should report pending changes."); | ||||
|  | ||||
| //innerDeferredResult.addCallback(function () { console.log("+_+_+_+_+_+_+_+_+_+_+_+ >>>")}); | ||||
| 			innerDeferredResult.addMethod(user, 'saveChanges'); | ||||
| //innerDeferredResult.addCallback(function () { console.log("+_+_+_+_+_+_+_+_+_+_+_+ <<<")}); | ||||
| 			innerDeferredResult.addMethod(user, 'hasPendingChanges'); | ||||
| 			innerDeferredResult.addTest(false, "After saving changes there should be no pending changes left."); | ||||
|  | ||||
| 			innerDeferredResult.addMethod(aDirectLogin, 'label'); | ||||
| 			innerDeferredResult.addTest(updatedLabel, "The DirectLogin returns the correct label even after committing data."); | ||||
| 			 | ||||
| 			innerDeferredResult.callback(); | ||||
| 			 | ||||
| 			return innerDeferredResult; | ||||
| 		}) | ||||
|  | ||||
| 		deferredResult.callback(); | ||||
|  | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
|     //------------------------------------------------------------------------- | ||||
|  | ||||
| 	'editDirectLoginLabel_thanResetItToThePreviousValue_test': function (someTestArgs) { | ||||
| 		var deferredResult; | ||||
| 		var proxy; | ||||
| 		var user; | ||||
|  | ||||
| 		proxy = new Clipperz.PM.Proxy.Test({shouldPayTolls:true, isDefault:true, readOnly:false}); | ||||
| 		user = new Clipperz.PM.DataModel.User({username:'joe', getPassphraseFunction:function () { return 'clipperz';}}); | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred("editDirectLoginLabel_thanResetItToThePreviousValue_test", someTestArgs); | ||||
| 		deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['joe_clipperz_offline_copy_data']); | ||||
| 		deferredResult.addMethod(user, 'login'); | ||||
| 		deferredResult.addMethod(user, 'getRecord', 'd5f700b9c3367c39551ea49e00a9ab20dae09dd79d46047b983fc7c4bfaa050d');	//	YAHOO (4) | ||||
| 		deferredResult.addMethodcaller('directLogins'); | ||||
| 		deferredResult.addCallback(MochiKit.Base.itemgetter('dba0db679802f0e6aa6d0b7a6aaf42350aabc5f057409edd99a268a92ebb6496')); | ||||
| 		deferredResult.addCallback(function (aDirectLogin) { | ||||
| 			var innerDeferredResult; | ||||
| 			var originalLabel; | ||||
| 			var updatedLabel; | ||||
| 			 | ||||
| 			originalLabel = "Yahoo! Mail"; | ||||
| 			updatedLabel  = "updated Yahoo! Mail label"; | ||||
| 			 | ||||
| 			innerDeferredResult = new Clipperz.Async.Deferred("editDirectLoginLabel_thanResetItToThePreviousValue_test <inner>", someTestArgs); | ||||
| 			innerDeferredResult.addMethod(aDirectLogin, 'label'); | ||||
| 			innerDeferredResult.addTest(originalLabel, "The label of the selected direct login is correct."); | ||||
| 			innerDeferredResult.addMethod(aDirectLogin, 'setLabel', updatedLabel); | ||||
| 			 | ||||
| 			innerDeferredResult.addMethod(aDirectLogin, 'label'); | ||||
| 			innerDeferredResult.addTest(updatedLabel, "The DirectLogin returns the correct label even before committing data."); | ||||
|  | ||||
| 			innerDeferredResult.addMethod(user, 'hasPendingChanges'); | ||||
| 			innerDeferredResult.addTest(true, "When changing the label of a DirectLogin, the user should report pending changes [2]."); | ||||
|  | ||||
| 			innerDeferredResult.addMethod(aDirectLogin, 'setLabel', originalLabel); | ||||
|  | ||||
| 			innerDeferredResult.addMethod(aDirectLogin, 'hasPendingChanges'); | ||||
| 			innerDeferredResult.addTest(false, "Restoring the original label, the directLogin should report no pending changes."); | ||||
| 			 | ||||
| 			innerDeferredResult.addMethod(aDirectLogin.record(), 'hasPendingChanges'); | ||||
| 			innerDeferredResult.addTest(false, "Restoring the original label, the record should report no pending changes."); | ||||
|  | ||||
| 			innerDeferredResult.addMethod(user, 'hasPendingChanges'); | ||||
| 			innerDeferredResult.addTest(false, "Restoring the original label, the user should report no pending changes."); | ||||
| 			 | ||||
| 			innerDeferredResult.callback(); | ||||
| 			 | ||||
| 			return innerDeferredResult; | ||||
| 		}) | ||||
|  | ||||
| 		deferredResult.callback(); | ||||
|  | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
|     //------------------------------------------------------------------------- | ||||
| /* | ||||
| 	'bindingValues_test': function (someTestArgs) { | ||||
| 		var deferredResult; | ||||
| 		var proxy; | ||||
| 		var user; | ||||
|  | ||||
| 		proxy = new Clipperz.PM.Proxy.Test({shouldPayTolls:true, isDefault:true, readOnly:false}); | ||||
| 		user = new Clipperz.PM.DataModel.User({username:'joe', getPassphraseFunction:function () { return 'clipperz';}}); | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred("DirectLogin.bindingValues_test", someTestArgs); | ||||
| 		deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['joe_clipperz_offline_copy_data']); | ||||
| 		deferredResult.addMethod(user, 'login'); | ||||
| 		deferredResult.addMethod(user, 'getRecord', 'd5f700b9c3367c39551ea49e00a9ab20dae09dd79d46047b983fc7c4bfaa050d');	//	YAHOO (4) | ||||
| 		deferredResult.addMethodcaller('directLogins'); | ||||
| 		deferredResult.addCallback(MochiKit.Base.itemgetter('dba0db679802f0e6aa6d0b7a6aaf42350aabc5f057409edd99a268a92ebb6496')); | ||||
| 		deferredResult.addMethodcaller('bindingValues'); | ||||
| 		deferredResult.addCallback(function (someBindingValues) { | ||||
| 			SimpleTest.is(MochiKit.Base.keys(someBindingValues).length, 2, "there should be 2 bindings for this direct login"); | ||||
| 			SimpleTest.is(someBindingValues['login'], 'joe.clipperz', "the login field should be filled with 'joe.clipperz'"); | ||||
| 			SimpleTest.is(someBindingValues['passwd'], 'enfvDG1RxAsl', "the passwd field should be filled with 'enfvDG1RxAsl'"); | ||||
| 		}) | ||||
|  | ||||
| 		deferredResult.callback(); | ||||
|  | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
| */ | ||||
|     //------------------------------------------------------------------------- | ||||
|     'syntaxFix': MochiKit.Base.noop | ||||
| }; | ||||
|  | ||||
| //############################################################################# | ||||
|  | ||||
| SimpleTest.runDeferredTests("Clipperz.PM.DataModel.DirectLogin", tests, {trace:false}); | ||||
| @@ -0,0 +1,28 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| directLoginConfigurations = { | ||||
| 	'Yahoo! Mail':	'{\n  "page": {\n    "title": "Yahoo! Mail"\n  },\n  "form": {\n    "attributes": {\n      "action": "https://login.yahoo.com/config/login?",\n      "method": "post"\n    },\n    "inputs": [\n      {\n        "type": "hidden",\n        "name": ".tries",\n        "value": "1"\n      },\n      {\n        "type": "hidden",\n        "name": ".src",\n        "value": "ym"\n      },\n      {\n        "type": "hidden",\n        "name": ".md5",\n        "value": ""\n      },\n      {\n        "type": "hidden",\n        "name": ".hash",\n        "value": ""\n      },\n      {\n        "type": "hidden",\n        "name": ".js",\n        "value": ""\n      },\n      {\n        "type": "hidden",\n        "name": ".last",\n        "value": ""\n      },\n      {\n        "type": "hidden",\n        "name": "promo",\n        "value": ""\n      },\n      {\n        "type": "hidden",\n        "name": ".intl",\n        "value": "us"\n      },\n      {\n        "type": "hidden",\n        "name": ".bypass",\n        "value": ""\n      },\n      {\n        "type": "hidden",\n        "name": ".partner",\n        "value": ""\n      },\n      {\n        "type": "hidden",\n        "name": ".u",\n        "value": "5gp62cl2vg3ov"\n      },\n      {\n        "type": "hidden",\n        "name": ".v",\n        "value": "0"\n      },\n      {\n        "type": "hidden",\n        "name": ".challenge",\n        "value": "iBEY0IK6k3t9Uals32mrTos8s48p"\n      },\n      {\n        "type": "hidden",\n        "name": ".yplus",\n        "value": ""\n      },\n      {\n        "type": "hidden",\n        "name": ".emailCode",\n        "value": ""\n      },\n      {\n        "type": "hidden",\n        "name": "pkg",\n        "value": ""\n      },\n      {\n        "type": "hidden",\n        "name": "stepid",\n        "value": ""\n      },\n      {\n        "type": "hidden",\n        "name": ".ev",\n        "value": ""\n      },\n      {\n        "type": "hidden",\n        "name": "hasMsgr",\n        "value": "0"\n      },\n      {\n        "type": "hidden",\n        "name": ".chkP",\n        "value": "Y"\n      },\n      {\n        "type": "hidden",\n        "name": ".done",\n        "value": "http://mail.yahoo.com"\n      },\n      {\n        "type": "hidden",\n        "name": ".pd",\n        "value": "ym_ver%3d0%26c="\n      },\n      {\n        "type": "text",\n        "name": "login",\n        "value": ""\n      },\n      {\n        "type": "password",\n        "name": "passwd",\n        "value": ""\n      },\n      {\n        "type": "checkbox",\n        "name": ".persistent",\n        "value": "y"\n      },\n      {\n        "type": "submit",\n        "name": ".save",\n        "value": "Sign In"\n      }\n    ]\n  },\n  "version": "0.2"\n}', | ||||
| 	'Parallels':	'{"page": {"title": "Parallels Account"},\n"form": {"attributes": {"action": "https://www.parallels.com/account/",\n"method": "post"},\n"inputs": [{"type": "text",\n"name": "Email",\n"value": ""},\n{"type": "password",\n"name": "Password",\n"value": ""}]},\n"version": "0.2.3"}', | ||||
| 	__syntaxFix__: "syntax fix" | ||||
| }; | ||||
| @@ -0,0 +1,60 @@ | ||||
| <!-- | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it  | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| --> | ||||
|  | ||||
| <html> | ||||
| <head> | ||||
| 	<title>Clipperz.PM.DataModel.EncryptedRemoteObject - test</title> | ||||
| 	<script>Clipperz = {}</script> | ||||
|     <script type="text/javascript" src="../../../../../js/MochiKit/MochiKit.js"></script> | ||||
|     <script type="text/javascript" src="../../../../SimpleTest/SimpleTest.js"></script> | ||||
|     <link rel="stylesheet" type="text/css" href="../../../../SimpleTest/test.css"> | ||||
|  | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/YUI/Utils.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Base.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/ByteArray.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Logging.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Async.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Signal.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/KeyValueObjectStore.js'></script> | ||||
|  | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/Base.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/BigInt.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES_2.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SHA.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/PRNG.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SRP.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Connection.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Crypto.js'></script> | ||||
|  | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/EncryptedRemoteObject.js'></script> | ||||
|     <script type="text/javascript" src="../../../../SimpleTest/SimpleTest.Async.js"></script> | ||||
| </head> | ||||
| <body> | ||||
|  | ||||
| <pre id="test"> | ||||
| <script type="text/javascript" src="EncryptedRemoteObject.test.js"></script> | ||||
| </pre> | ||||
| </body> | ||||
| </html> | ||||
| @@ -0,0 +1,220 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| Clipperz.Crypto.PRNG.defaultRandomGenerator().fastEntropyAccumulationForTestingPurpose(); | ||||
|  | ||||
| var tests = { | ||||
|  | ||||
|     //------------------------------------------------------------------------- | ||||
|  | ||||
| 	'simple_tests': function(someTestArgs) { | ||||
| 		var	deferredResult; | ||||
| 		var	encryptedRemoteObject; | ||||
|  | ||||
| 		var	key; | ||||
| 		var version; | ||||
| 		var rawData; | ||||
| 		 | ||||
| 		key = "just a random key"; | ||||
| 		version = Clipperz.PM.Crypto.encryptingFunctions.currentVersion; | ||||
| 		rawData = "just a random text to encrypt"; | ||||
| 		 | ||||
| 		encryptedRemoteObject = new Clipperz.PM.DataModel.EncryptedRemoteObject({ | ||||
| 			'retrieveKeyFunction':			MochiKit.Base.noop, | ||||
| 			'retrieveRemoteDataFunction':	function () { return  "--"}, | ||||
| 			'encryptedDataKeypath':			'--', | ||||
| 			'encryptedVersionKeypath':		'--' | ||||
| 		}); | ||||
| 		SimpleTest.ok(encryptedRemoteObject != null, "create an encryptedRemoteObject"); | ||||
| 		 | ||||
| 		deferredResult = Clipperz.Async.callbacks("EncryptedRemoteObject.test - simple_tests", [ | ||||
| 			MochiKit.Base.method(encryptedRemoteObject, 'getRemoteData'), | ||||
| 			function(aResult) { | ||||
| 				SimpleTest.is(aResult, "--", "setting and getting serverData works"); | ||||
| 			} | ||||
| 		], someTestArgs); | ||||
|  | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
|     //------------------------------------------------------------------------- | ||||
|  | ||||
| 	'decrypt_test': function (someTestArgs) { | ||||
| 		var	deferredResult; | ||||
| 		var	encryptedRemoteObject; | ||||
| 		var	key; | ||||
| 		var version; | ||||
| 		var rawData; | ||||
| 		 | ||||
| 		key = "just a random key"; | ||||
| 		version = Clipperz.PM.Crypto.encryptingFunctions.currentVersion; | ||||
| 		rawData = "just a random text to encrypt"; | ||||
|  | ||||
| 		encryptedRemoteObject = new Clipperz.PM.DataModel.EncryptedRemoteObject({ | ||||
| 			'retrieveKeyFunction':			MochiKit.Base.partial(MochiKit.Async.succeed, key), | ||||
| 			'retrieveRemoteDataFunction':	MochiKit.Base.partial(Clipperz.Async.callbacks, "EncryptedRemoteObject.test - decrypt_test <encrypt data>", [ | ||||
| 				MochiKit.Base.partial(Clipperz.PM.Crypto.deferredEncrypt, {key:key, value:rawData, version:version}), | ||||
| 				function (someEncryptedData) { | ||||
| 					return { | ||||
| 						'data': someEncryptedData, | ||||
| 						'version': version | ||||
| 					} | ||||
| 				} | ||||
| 			], someTestArgs)//, | ||||
| //			'encryptedDataKeypath':			'data', | ||||
| //			'encryptedVersionKeypath':		'version' | ||||
| 		}); | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred("decrypt_test", someTestArgs); | ||||
| 		deferredResult.addMethod(encryptedRemoteObject, 'getDecryptedData'); | ||||
| 		deferredResult.addCallback(function (aResult) { | ||||
| 			SimpleTest.is(aResult, rawData, "encrypt and decrypt works"); | ||||
| 		}) | ||||
| 		deferredResult.callback(); | ||||
| 		 | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
|     //------------------------------------------------------------------------- | ||||
|  | ||||
| 	'getValue_test': function (someTestArgs) { | ||||
| 		var	deferredResult; | ||||
| 		var	encryptedRemoteObject; | ||||
| 		var	key; | ||||
| 		var version; | ||||
| 		var rawData; | ||||
| 		 | ||||
| 		key = "just a random key"; | ||||
| 		version = Clipperz.PM.Crypto.encryptingFunctions.currentVersion; | ||||
| 		rawData = { | ||||
| 			key1: 'value1', | ||||
| 			key2: 'value2' | ||||
| 		}; | ||||
|  | ||||
| 		encryptedRemoteObject = new Clipperz.PM.DataModel.EncryptedRemoteObject({ | ||||
| 			'reference':					"testReference", | ||||
| 			'retrieveKeyFunction':			MochiKit.Base.partial(MochiKit.Async.succeed, key), | ||||
| 			'retrieveRemoteDataFunction':	MochiKit.Base.partial(Clipperz.Async.callbacks, "EncryptedRemoteObject.test - decrypt_test <encrypt data>", [ | ||||
| 				MochiKit.Base.partial(Clipperz.PM.Crypto.deferredEncrypt, {key:key, value:rawData, version:version}), | ||||
| 				function (someEncryptedData) { | ||||
| 					return { | ||||
| 						'data': someEncryptedData, | ||||
| 						'version': version | ||||
| 					} | ||||
| 				} | ||||
| 			], someTestArgs)//, | ||||
| //			'encryptedDataKeypath':			'data', | ||||
| //			'encryptedVersionKeypath':		'version' | ||||
| 		}); | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred("decrypt_test", someTestArgs); | ||||
|  | ||||
| 		deferredResult.addMethod(encryptedRemoteObject, 'getValue', 'key1'); | ||||
| 		deferredResult.addTest('value1', "getting 'key1' works"); | ||||
| 		deferredResult.addMethod(encryptedRemoteObject, 'hasAnyCleanTextData'); | ||||
| 		deferredResult.addTest(true, "After accessing a value, hasAnyCleanTextData returns false"); | ||||
|  | ||||
| 		deferredResult.addMethod(encryptedRemoteObject, 'hasPendingChanges'); | ||||
| 		deferredResult.addTest(false, "if nothing has changed, the object should return not pending changes"); | ||||
|  | ||||
| 		deferredResult.addMethod(encryptedRemoteObject, 'deleteAllCleanTextData'); | ||||
| 		deferredResult.addMethod(encryptedRemoteObject, 'hasAnyCleanTextData'); | ||||
| 		deferredResult.addTest(false, "After deleting all cleanTextData, hasAnyCleanTextData returns false"); | ||||
| 		 | ||||
| 		deferredResult.addMethod(encryptedRemoteObject, 'getValue', 'key1'); | ||||
| 		deferredResult.addTest('value1', "getting 'key1' (also after a lock) works correctly"); | ||||
|  | ||||
| 		deferredResult.addMethod(encryptedRemoteObject, 'setValue', 'key1', 'new value1'); | ||||
| 		deferredResult.addMethod(encryptedRemoteObject, 'getValue', 'key1'); | ||||
| 		deferredResult.addTest('new value1', "after setting a new value, it is correctly returned"); | ||||
|  | ||||
| 		deferredResult.addMethod(encryptedRemoteObject, 'values'); | ||||
| 		deferredResult.addCallback(function (someValues) { | ||||
| 			SimpleTest.is(someValues['key1'], 'new value1', "the value got straight from the objectStore is correct"); | ||||
| 		}); | ||||
|  | ||||
| 		deferredResult.addMethod(encryptedRemoteObject, 'hasPendingChanges'); | ||||
| 		deferredResult.addTest(true, "once a value has been changed, the object should return that there're some pending changes"); | ||||
|  | ||||
| 		deferredResult.addMethod(encryptedRemoteObject, 'revertChanges'); | ||||
| 		deferredResult.addMethod(encryptedRemoteObject, 'hasPendingChanges'); | ||||
| 		deferredResult.addTest(false, "reverting the changes should return the object to its initial state, without any peding changes"); | ||||
|  | ||||
| 		deferredResult.addMethod(encryptedRemoteObject, 'getValue', 'key1'); | ||||
| 		deferredResult.addTest('value1', "also the value of the changed item has been restored"); | ||||
|  | ||||
| 		deferredResult.callback(); | ||||
| 		 | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
|     //------------------------------------------------------------------------- | ||||
|  | ||||
| 	'encrypt_with_new_object_test': function (someTestArgs) { | ||||
| 		var	deferredResult; | ||||
| 		var	encryptedRemoteObject; | ||||
| 		var	key; | ||||
| //		var version; | ||||
| //		var rawData; | ||||
| 		 | ||||
| 		key = "just a random key"; | ||||
| //		version = Clipperz.PM.Crypto.encryptingFunctions.currentVersion; | ||||
| //		rawData = "just a random text to encrypt"; | ||||
|  | ||||
| 		encryptedRemoteObject = new Clipperz.PM.DataModel.EncryptedRemoteObject({ | ||||
| 			'retrieveRemoteDataFunction':	MochiKit.Base.noop | ||||
| 		}); | ||||
|  | ||||
| 		encryptedRemoteObject.setValue('key1', "value1"); | ||||
| 		encryptedRemoteObject.setValue('key2', "value2"); | ||||
| 		encryptedRemoteObject.setValue('key3', "value3"); | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred("encrypt_with_new_object_test", someTestArgs); | ||||
| 		deferredResult.addMethod(encryptedRemoteObject, 'prepareRemoteDataWithKey', key); | ||||
| 		deferredResult.addCallback(MochiKit.Base.itemgetter('data')); | ||||
| 		deferredResult.collectResults({ | ||||
| 			'key':		MochiKit.Base.partial(MochiKit.Async.succeed, key), | ||||
| 			'value':	MochiKit.Async.succeed, | ||||
| 			'version':	MochiKit.Base.partial(MochiKit.Async.succeed, Clipperz.PM.Crypto.encryptingFunctions.currentVersion) | ||||
| 		}); | ||||
| 		deferredResult.addCallback(Clipperz.PM.Crypto.deferredDecrypt); | ||||
| 		deferredResult.addCallback(function (aResult) { | ||||
| 			SimpleTest.is(aResult['key1'], "value1", "encrypt and decrypt works for first element"); | ||||
| 			SimpleTest.is(aResult['key2'], "value2", "encrypt and decrypt works for second element"); | ||||
| 			SimpleTest.is(aResult['key3'], "value3", "encrypt and decrypt works for third element"); | ||||
| 		}) | ||||
| 		deferredResult.callback(); | ||||
| 		 | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
|     //------------------------------------------------------------------------- | ||||
|     //------------------------------------------------------------------------- | ||||
|     //------------------------------------------------------------------------- | ||||
|     //------------------------------------------------------------------------- | ||||
|     'syntaxFix': MochiKit.Base.noop | ||||
| }; | ||||
|  | ||||
| //############################################################################# | ||||
|  | ||||
| SimpleTest.runDeferredTests("Clipperz.PM.DataModel.EncryptedRemoteObject", tests, {trace:false}); | ||||
| @@ -0,0 +1,99 @@ | ||||
| <!-- | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it  | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| --> | ||||
|  | ||||
| <html> | ||||
| <head> | ||||
| 	<title>Clipperz.PM.DataModel.User - test</title> | ||||
| 	<script>Clipperz = {}</script> | ||||
|     <script type="text/javascript" src="../../../../../js/MochiKit/MochiKit.js"></script> | ||||
|     <script type="text/javascript" src="../../../../SimpleTest/SimpleTest.js"></script> | ||||
|     <link rel="stylesheet" type="text/css" href="../../../../SimpleTest/test.css"> | ||||
|  | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/YUI/Utils.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Base.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Date.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/ByteArray.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Logging.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Async.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Signal.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/KeyValueObjectStore.js'></script> | ||||
|  | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/Base.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/BigInt.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SHA.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/PRNG.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SRP.js'></script> | ||||
|  | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Toll.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Test.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js'></script> | ||||
|  | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Connection.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Crypto.js'></script> | ||||
|  | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/UI/DirectLoginController.js'></script> | ||||
|  | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings/Strings_en-US.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/Date.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/EncryptedRemoteObject.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.Field.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLogin.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginInput.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginBinding.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginFormValue.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Legacy.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.RecordIndex.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Preferences.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js'></script> | ||||
|     <script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/OneTimePassword.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.AccountInfo.js'></script> | ||||
|  | ||||
|     <script type="text/javascript" src="../../../../SimpleTest/SimpleTest.Async.js"></script> | ||||
| <script> | ||||
| 	Clipperz_IEisBroken = false; | ||||
| </script> | ||||
|  | ||||
| <!--[if IE]><script> | ||||
| Clipperz_IEisBroken = true; | ||||
| Clipperz_normalizedNewLine = '\x0d\x0a'; | ||||
| </script><![endif]--> | ||||
|  | ||||
| </head> | ||||
| <body> | ||||
|  | ||||
| <pre id="test"> | ||||
| <script> | ||||
| 	Clipperz.PM.Strings.Languages.setSelectedLanguage('en-us'); | ||||
| </script> | ||||
| <script type="text/javascript" src="User.data.js"></script> | ||||
| <script type="text/javascript" src="OneTimePassword.test.js"></script> | ||||
| </pre> | ||||
| </body> | ||||
| </html> | ||||
| @@ -0,0 +1,193 @@ | ||||
| /* | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| */ | ||||
|  | ||||
| Clipperz.Crypto.PRNG.defaultRandomGenerator().fastEntropyAccumulationForTestingPurpose(); | ||||
|  | ||||
| var tests = { | ||||
|  | ||||
|     //------------------------------------------------------------------------- | ||||
|  | ||||
| 	'isValidOneTimePasswordValue_test': function (someTestArgs) { | ||||
| 		var otp; | ||||
| 		var notOTP; | ||||
|  | ||||
| 		otp = 'yaxx k7ww - f8y6 tqz5 - 58b6 th44 - 9cwv q0fg'; | ||||
| 		SimpleTest.is(Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue(otp), true, "isValidOneTimePasswordValue [expect true] - test 1"); | ||||
|  | ||||
| 		notOTP = 'trustno1'; | ||||
| 		SimpleTest.is(Clipperz.PM.DataModel.OneTimePassword.isValidOneTimePasswordValue(notOTP), false, "isValidOneTimePasswordValue [expect false] - test 1"); | ||||
|  | ||||
| 		return MochiKit.Async.succeed('done'); | ||||
| 	}, | ||||
|  | ||||
|     //------------------------------------------------------------------------- | ||||
|  | ||||
| 	'loginUsingOtp_test': function (someTestArgs) { | ||||
| 		var deferredResult; | ||||
| 		var proxy; | ||||
| 		var user, user2; | ||||
| 		var username; | ||||
| 		var passphrase; | ||||
| 		 | ||||
| 		username = "test"; | ||||
| 		passphrase = "yaxx k7ww - f8y6 tqz5 - 58b6 th44 - 9cwv q0fg";	//	OTP | ||||
|  | ||||
| 		proxy =	new Clipperz.PM.Proxy.Test({shouldPayTolls:true, isDefault:true, readOnly:false}); | ||||
| 		user =	new Clipperz.PM.DataModel.User({username:username, getPassphraseFunction:function () { return passphrase;}}); | ||||
| 		user2 =	new Clipperz.PM.DataModel.User({username:username, getPassphraseFunction:function () { return passphrase;}}); | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred("loginUsingOtp_test", someTestArgs); | ||||
| 		deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['test_test_with_otps']); | ||||
|  | ||||
| 		deferredResult.addMethod(user, 'login'); | ||||
| 		deferredResult.addMethod(user, 'getRecords'); | ||||
| 		deferredResult.addCallback(MochiKit.Base.itemgetter('length')); | ||||
| 		deferredResult.addTest(1, "This account has one single card"); | ||||
|  | ||||
| 		deferredResult.addMethod(user, 'getOneTimePasswords'); | ||||
| 		deferredResult.addCallback(MochiKit.Base.itemgetter('length')); | ||||
| 		deferredResult.addTest(1, "This account has one OTP"); | ||||
|  | ||||
| 		deferredResult.addMethod(user, 'getOneTimePasswords'); | ||||
| 		deferredResult.addCallback(MochiKit.Base.itemgetter(0)); | ||||
| 		deferredResult.addCallback(MochiKit.Base.methodcaller('status')); | ||||
| 		deferredResult.addTest('USED', "The available OTP has been unsed to login, and should be marked accordingly"); | ||||
|  | ||||
| 		deferredResult.addMethod(user2, 'login'); | ||||
| 		deferredResult.shouldFail("trying to login using the same OTP twice"); | ||||
|  | ||||
| 		deferredResult.callback(); | ||||
| 		 | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
|     //------------------------------------------------------------------------- | ||||
|  | ||||
| 	'changePassphraseAndLoginUsingOtp_test': function (someTestArgs) { | ||||
| 		var deferredResult; | ||||
| 		var proxy; | ||||
| 		var user; | ||||
| 		var user2; | ||||
| 		var user3; | ||||
| 		var otp; | ||||
| 		 | ||||
| 		otp = "yaxx k7ww - f8y6 tqz5 - 58b6 th44 - 9cwv q0fg";	//	OTP | ||||
|  | ||||
| 		newPassphrase = 'tset'; | ||||
| 		proxy = new Clipperz.PM.Proxy.Test({shouldPayTolls:true, isDefault:true, readOnly:false}); | ||||
| 		user = new Clipperz.PM.DataModel.User({username:'test', getPassphraseFunction:function () { return 'test';}}); | ||||
| 		user2 = new Clipperz.PM.DataModel.User({username:'test', getPassphraseFunction:function () { return otp;}}); | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred("changePassphraseAndLoginUsingOtp_test", someTestArgs); | ||||
| 		deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['test_test_with_otps']); | ||||
|  | ||||
| 		deferredResult.addMethod(user, 'login'); | ||||
|  | ||||
| 		deferredResult.addMethod(user, 'getRecords'); | ||||
| 		deferredResult.addCallback(MochiKit.Base.itemgetter('length')); | ||||
| 		deferredResult.addTest(1, "This account has only a single card"); | ||||
|  | ||||
| 		deferredResult.addMethod(user, 'changePassphrase', newPassphrase); | ||||
| 		deferredResult.addMethod(user, 'logout'); | ||||
|  | ||||
| 		deferredResult.addMethod(user2, 'login'); | ||||
| 		deferredResult.addMethod(user2, 'getRecords'); | ||||
| 		deferredResult.addCallback(MochiKit.Base.itemgetter('length')); | ||||
| 		deferredResult.addTest(1, "This account has oly a single card"); | ||||
| 		deferredResult.addMethod(user2, 'logout'); | ||||
|  | ||||
| 		deferredResult.callback(); | ||||
| 		 | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
|     //------------------------------------------------------------------------- | ||||
|  | ||||
| 	'loginUsingOtpAndWrongUsername_test': function (someTestArgs) { | ||||
| 		var deferredResult; | ||||
| 		var proxy; | ||||
| 		var user, user2; | ||||
| 		var username; | ||||
| 		var wrongUsername; | ||||
| 		var passphrase; | ||||
| 		 | ||||
| 		username = "test"; | ||||
| 		wrongUsername = "tset"; | ||||
| 		passphrase = "yaxx k7ww - f8y6 tqz5 - 58b6 th44 - 9cwv q0fg";	//	OTP | ||||
|  | ||||
| 		proxy =	new Clipperz.PM.Proxy.Test({shouldPayTolls:true, isDefault:true, readOnly:false}); | ||||
| 		user =	new Clipperz.PM.DataModel.User({username:wrongUsername, getPassphraseFunction:function () { return passphrase;}}); | ||||
| 		user2 =	new Clipperz.PM.DataModel.User({username:username, getPassphraseFunction:function () { return passphrase;}}); | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred("loginUsingOtpAndWrongUsername_test", someTestArgs); | ||||
| 		deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['test_test_with_otps']); | ||||
|  | ||||
| 		deferredResult.addMethod(user, 'login'); | ||||
| 		deferredResult.shouldFail("login in using the wrong username with the OTP should fail"); | ||||
|  | ||||
| 		deferredResult.addMethod(user2, 'login'); | ||||
| 		deferredResult.shouldFail("trying to reuse the same OTP should fail, even if now it is used with the correct username"); | ||||
|  | ||||
| 		deferredResult.callback(); | ||||
| 		 | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
|     //------------------------------------------------------------------------- | ||||
|  | ||||
| 	'loginUserWithAPassphraseLookingExactlyLikeAnOTP_test': function (someTestArgs) { | ||||
| 		var deferredResult; | ||||
| 		var proxy; | ||||
| 		var user; | ||||
| 		var username; | ||||
| 		var passphrase; | ||||
| 		 | ||||
| 		username = "otp_user"; | ||||
| 		passphrase = "yaxx k7ww - f8y6 tqz5 - 58b6 th44 - 9cwv q0fg";	//	passphrase | ||||
|  | ||||
| 		proxy =	new Clipperz.PM.Proxy.Test({shouldPayTolls:true, isDefault:true, readOnly:false}); | ||||
| 		user =	new Clipperz.PM.DataModel.User({username:username, getPassphraseFunction:function () { return passphrase;}}); | ||||
|  | ||||
| 		deferredResult = new Clipperz.Async.Deferred("loginUserWithAPassphraseLookingExactlyLikeAnOTP_test", someTestArgs); | ||||
| 		deferredResult.addMethod(proxy.dataStore(), 'setupWithEncryptedData', testData['otp_user_test']); | ||||
|  | ||||
| 		deferredResult.addMethod(user, 'login'); | ||||
| 		deferredResult.addMethod(user, 'getRecords'); | ||||
| 		deferredResult.addCallback(MochiKit.Base.itemgetter('length')); | ||||
| 		deferredResult.addTest(1, "This account has one single card"); | ||||
|  | ||||
| 		deferredResult.callback(); | ||||
| 		 | ||||
| 		return deferredResult; | ||||
| 	}, | ||||
|  | ||||
|     //------------------------------------------------------------------------- | ||||
|     //------------------------------------------------------------------------- | ||||
|     'syntaxFix': MochiKit.Base.noop | ||||
| }; | ||||
|  | ||||
|  | ||||
|  | ||||
| //############################################################################# | ||||
|  | ||||
| SimpleTest.runDeferredTests("Clipperz.PM.DataModel.OneTimePassword", tests, {trace:false}); | ||||
							
								
								
									
										94
									
								
								frontend/delta/tests/tests/Clipperz/PM/DataModel/Record.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								frontend/delta/tests/tests/Clipperz/PM/DataModel/Record.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| <!-- | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it  | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| --> | ||||
|  | ||||
| <html> | ||||
| <head> | ||||
| 	<title>Clipperz.PM.DataModel.Record - test</title> | ||||
| 	<script>Clipperz = {}</script> | ||||
| 	<script type="text/javascript" src="../../../../../js/MochiKit/MochiKit.js"></script> | ||||
| 	<script type="text/javascript" src="../../../../SimpleTest/SimpleTest.js"></script> | ||||
| 	<link rel="stylesheet" type="text/css" href="../../../../SimpleTest/test.css"> | ||||
|  | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/YUI/Utils.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Base.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Date.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/ByteArray.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Logging.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Async.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Signal.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Set.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/KeyValueObjectStore.js'></script> | ||||
|  | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/Base.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/BigInt.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES_2.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SHA.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/PRNG.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SRP.js'></script> | ||||
|  | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Toll.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings/Strings_en-US.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Date.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Test.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js'></script> | ||||
|  | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Connection.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Crypto.js'></script> | ||||
|  | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings/Strings_en-US.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Date.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/EncryptedRemoteObject.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.Field.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLogin.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginInput.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginBinding.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginFormValue.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Legacy.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.RecordIndex.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Preferences.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/OneTimePassword.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.AccountInfo.js'></script> | ||||
|  | ||||
| 	<script type="text/javascript" src="../../../../SimpleTest/SimpleTest.Async.js"></script> | ||||
| </head> | ||||
| <body> | ||||
|  | ||||
| <pre id="test"> | ||||
| <script> | ||||
| 	Clipperz.PM.Strings.Languages.setSelectedLanguage('en-us'); | ||||
| </script> | ||||
| <script type="text/javascript" src="DirectLoginConfigurations.data.js"></script> | ||||
| <script type="text/javascript" src="User.data.js"></script> | ||||
| <script type="text/javascript" src="Record.test.js"></script> | ||||
| </pre> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										1513
									
								
								frontend/delta/tests/tests/Clipperz/PM/DataModel/Record.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1513
									
								
								frontend/delta/tests/tests/Clipperz/PM/DataModel/Record.test.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2068
									
								
								frontend/delta/tests/tests/Clipperz/PM/DataModel/User.data.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2068
									
								
								frontend/delta/tests/tests/Clipperz/PM/DataModel/User.data.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										102
									
								
								frontend/delta/tests/tests/Clipperz/PM/DataModel/User.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								frontend/delta/tests/tests/Clipperz/PM/DataModel/User.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,102 @@ | ||||
| <!-- | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it  | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| --> | ||||
|  | ||||
| <html> | ||||
| <head> | ||||
| 	<title>Clipperz.PM.DataModel.User - test</title> | ||||
| 	<script>Clipperz = {}</script> | ||||
| 	<script type="text/javascript" src="../../../../../js/MochiKit/MochiKit.js"></script> | ||||
| 	<script type="text/javascript" src="../../../../SimpleTest/SimpleTest.js"></script> | ||||
| 	<link rel="stylesheet" type="text/css" href="../../../../SimpleTest/test.css"> | ||||
|  | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/YUI/Utils.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Base.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Date.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/ByteArray.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Logging.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Async.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Signal.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/KeyValueObjectStore.js'></script> | ||||
|  | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/Base.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/BigInt.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/AES_2.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SHA.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/PRNG.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/Crypto/SRP.js'></script> | ||||
|  | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Toll.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Test.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Proxy/Proxy.Offline.DataStore.js'></script> | ||||
|  | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Connection.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Crypto.js'></script> | ||||
|  | ||||
| 	<!-- script type='text/javascript' src='../../../../../js/Clipperz/PM/UI/Common/Controllers/DirectLoginRunner.js'></script --> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/UI/DirectLoginController.js'></script> | ||||
|  | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Strings/Strings_en-US.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/Date.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/EncryptedRemoteObject.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/Record.Version.Field.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLogin.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginInput.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginBinding.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/DirectLoginFormValue.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Legacy.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.RecordIndex.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.Preferences.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.Header.OneTimePasswords.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/OneTimePassword.js'></script> | ||||
| 	<script type='text/javascript' src='../../../../../js/Clipperz/PM/DataModel/User.AccountInfo.js'></script> | ||||
|  | ||||
| 	<script type="text/javascript" src="../../../../SimpleTest/SimpleTest.Async.js"></script> | ||||
| <script> | ||||
| 	Clipperz_IEisBroken = false; | ||||
| </script> | ||||
|  | ||||
| <!--[if IE]><script> | ||||
| Clipperz_IEisBroken = true; | ||||
| Clipperz_normalizedNewLine = '\x0d\x0a'; | ||||
| </script><![endif]--> | ||||
|  | ||||
| </head> | ||||
| <body> | ||||
|  | ||||
| <pre id="test"> | ||||
| <script> | ||||
| 	Clipperz.PM.Strings.Languages.setSelectedLanguage('en-us'); | ||||
| </script> | ||||
| <script type="text/javascript" src="User.data.js"></script> | ||||
| <script type="text/javascript" src="User.data.old.js"></script> | ||||
| <script type="text/javascript" src="User.test.js"></script> | ||||
| </pre> | ||||
| </body> | ||||
| </html> | ||||
							
								
								
									
										2083
									
								
								frontend/delta/tests/tests/Clipperz/PM/DataModel/User.test.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2083
									
								
								frontend/delta/tests/tests/Clipperz/PM/DataModel/User.test.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										42
									
								
								frontend/delta/tests/tests/Clipperz/PM/DataModel/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								frontend/delta/tests/tests/Clipperz/PM/DataModel/index.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| <!-- | ||||
|  | ||||
| Copyright 2008-2013 Clipperz Srl | ||||
|  | ||||
| This file is part of Clipperz, the online password manager. | ||||
| For further information about its features and functionalities please | ||||
| refer to http://www.clipperz.com. | ||||
|  | ||||
| * Clipperz is free software: you can redistribute it and/or modify it  | ||||
|   under the terms of the GNU Affero General Public License as published | ||||
|   by the Free Software Foundation, either version 3 of the License, or  | ||||
|   (at your option) any later version. | ||||
|  | ||||
| * Clipperz is distributed in the hope that it will be useful, but  | ||||
|   WITHOUT ANY WARRANTY; without even the implied warranty of  | ||||
|   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||||
|   See the GNU Affero General Public License for more details. | ||||
|  | ||||
| * You should have received a copy of the GNU Affero General Public | ||||
|   License along with Clipperz. If not, see http://www.gnu.org/licenses/. | ||||
|  | ||||
| --> | ||||
|  | ||||
| <html> | ||||
| <head> | ||||
| 	<title>Clipperz.PM.DataModel.* - tests</title> | ||||
|  | ||||
| 	<script type="text/javascript" src="../../../../../js/MochiKit/MochiKit.js"></script> | ||||
| 	<script type="text/javascript" src="../../../../SimpleTest/TestRunner.js"></script> | ||||
| </head> | ||||
| <body> | ||||
| <script> | ||||
| TestRunner.runTests( | ||||
| 	'DirectLogin.html', | ||||
| 	'EncryptedRemoteObject.html', | ||||
| 	'OneTimePassword.html', | ||||
| 	'Record.html', | ||||
| 	'User.html' | ||||
| ); | ||||
| </script> | ||||
| </body> | ||||
| </html> | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	 Giulio Cesare Solaroli
					Giulio Cesare Solaroli