first commit
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 boynet
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,42 @@
|
||||
Framework7 Indexed List Plugin
|
||||
=============================
|
||||
Demo: https://boynet.github.io/boynet/
|
||||
|
||||
|
||||
This plugin is for Indexed-List scroll like iOS and Android have, currently works only with Contacts List
|
||||
|
||||

|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
Just grab plugin files from `dist/` folder or using bower:
|
||||
|
||||
```
|
||||
bower install framework7-indexed-list-plugin
|
||||
```
|
||||
|
||||
And link them to your app's right AFTER Framework7's scripts and styles:
|
||||
|
||||
```
|
||||
<link rel="stylesheet" href="path/to/framework7.min.css">
|
||||
<link rel="stylesheet" href="path/to/framework7.indexed-list.css">
|
||||
...
|
||||
<script src="path/to/framework7.min.js"></script>
|
||||
<script src="path/to/framework7.indexed-list.js"></script>
|
||||
```
|
||||
|
||||
## Usage
|
||||
put this html code inside .page
|
||||
````
|
||||
<ul class="list-index"></ul>
|
||||
````
|
||||
|
||||
## Demo:
|
||||
https://boynet.github.io/boynet/
|
||||
|
||||
OR:
|
||||
|
||||
Plugin comes with demo example to see how it works and looks. To make demo works you need:
|
||||
|
||||
* install bower dependencies. Go to `demo/` folder and execute in terminal `bower install`
|
||||
@@ -0,0 +1,50 @@
|
||||
.list-index {
|
||||
color: #057bf7;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position:absolute;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
position:absolute;
|
||||
z-index:199;
|
||||
top:0%;
|
||||
height: 100%;
|
||||
right: 0;
|
||||
background: #fff;
|
||||
width: 15px;
|
||||
text-align: center;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
-webkit-justify-content: center;
|
||||
justify-content: center;
|
||||
-webkit-box-orient: vertical;
|
||||
-moz-box-orient: vertical;
|
||||
-ms-flex-direction: column;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
}
|
||||
.list-index li{
|
||||
position: relative;
|
||||
z-index: 10;
|
||||
}
|
||||
.list-index li:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 100%;
|
||||
width: 10px;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
}
|
||||
html[dir="rtl"] .list-index {
|
||||
right: auto;
|
||||
left: 0;
|
||||
}
|
||||
html[dir="rtl"] .list-index li:before {
|
||||
right: auto;
|
||||
left: 100%;
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Framework7 Indexed List 0.2.0
|
||||
* Framework7 plugin to add Alphabet indexed list
|
||||
*
|
||||
* https://github.com/boynet/Framework7-Indexed-List-plugin
|
||||
*
|
||||
* Copyright 2015, boynet
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
* Released on: 17 Sep, 2014
|
||||
*/
|
||||
Framework7.prototype.plugins.indexedlist = function (app, params) {
|
||||
var $ = window.Dom7;
|
||||
|
||||
|
||||
function initIndexedList(page) {
|
||||
var eventsTarget = $(page.container).find('.list-index');
|
||||
if (eventsTarget.length === 0) return;
|
||||
|
||||
var pageContent = $(page.container).find('.page-content');
|
||||
buildLetters();
|
||||
var isTouched, isMoved;
|
||||
var letterToScroll;
|
||||
var elementHover;
|
||||
var fixedNavbar = pageContent.parents('.navbar-fixed').length > 0 || pageContent.parents('.navbar-through').length > 0;
|
||||
var searchBar = $(page.container).find('.searchbar').length > 0;
|
||||
|
||||
if (searchBar) {
|
||||
eventsTarget.css('margin-top', '52px');
|
||||
}
|
||||
|
||||
function handleTouchStart(e) {
|
||||
e.preventDefault();
|
||||
isTouched = true;
|
||||
|
||||
var target = $(e.target);
|
||||
if (!target.is('li')) target = target.parents('li');
|
||||
if (target.length > 0) {
|
||||
scrollToLetter(target.eq(0).data('index-letter'));
|
||||
}
|
||||
}
|
||||
|
||||
function handleTouchMove(e) {
|
||||
if (!isTouched) return;
|
||||
e.preventDefault();
|
||||
var target;
|
||||
if (e.type === 'mousemove') {
|
||||
target = $(e.target);
|
||||
}
|
||||
else {
|
||||
target = $(document.elementFromPoint(e.touches[0].pageX, e.touches[0].pageY));
|
||||
}
|
||||
if (!target.is('li')) target = target.parents('li');
|
||||
|
||||
if (target.length === 0) return;
|
||||
if (target.length > 0 && !target.is('.list-index li')) return;
|
||||
|
||||
scrollToLetter(target.eq(0).data('index-letter'));
|
||||
}
|
||||
|
||||
function handleTouchEnd(e) {
|
||||
isTouched = isMoved = false;
|
||||
}
|
||||
|
||||
$(page.container).on('click', '.list-index li', function (e) {
|
||||
var target = $(e.target);
|
||||
if (!target.is('li')) target = target.parents('li');
|
||||
if (target.length > 0) {
|
||||
scrollToLetter(target.eq(0).data('index-letter'));
|
||||
}
|
||||
});
|
||||
|
||||
function buildLetters() {
|
||||
var _letters = [];
|
||||
var lettersHtml = '';
|
||||
pageContent.find('.list-group').each(function () {
|
||||
var _letterDiv = $(this).find('ul .list-group-title');
|
||||
var _letter = _letterDiv.html().trim().charAt(0).toUpperCase();
|
||||
_letterDiv.attr('data-index-letter', _letter);
|
||||
lettersHtml += '<li data-index-letter="' + _letter + '">' + _letter + '</li>';
|
||||
_letters.push(_letter);
|
||||
});
|
||||
eventsTarget.html(lettersHtml);
|
||||
return _letters;
|
||||
}
|
||||
|
||||
function scrollToLetter(letter) {
|
||||
var scrollToEl = pageContent.find('.list-group ul li[data-index-letter="' + letter + '"]').parent();
|
||||
if (!scrollToEl.length) return;
|
||||
var scrollTop = scrollToEl.offset().top + pageContent.scrollTop() - (fixedNavbar ? 52 : 0) - (searchBar ? 52 : 0);
|
||||
pageContent.scrollTop(scrollTop);
|
||||
}
|
||||
|
||||
eventsTarget.on(app.touchEvents.start, handleTouchStart);
|
||||
eventsTarget.on(app.touchEvents.move, handleTouchMove);
|
||||
eventsTarget.on(app.touchEvents.end, handleTouchEnd);
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
hooks: {
|
||||
pageInit: initIndexedList,
|
||||
}
|
||||
};
|
||||
};
|
||||
+1
@@ -0,0 +1 @@
|
||||
.list-index{color:#057bf7;list-style:none;margin:0;padding:0;font-size:11px;font-weight:700;position:absolute;z-index:199;top:0;height:100%;right:0;background:#fff;width:15px;text-align:center;display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-orient:vertical;-moz-box-orient:vertical;-ms-flex-direction:column;-webkit-flex-direction:column;flex-direction:column}.list-index li{position:relative;z-index:10}.list-index li:before{content:'';position:absolute;right:100%;width:10px;height:100%;top:0}html[dir=rtl] .list-index{right:auto;left:0}html[dir=rtl] .list-index li:before{right:auto;left:100%}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Framework7 Indexed List 0.2.0
|
||||
* Framework7 plugin to add Alphabet indexed list
|
||||
*
|
||||
* https://github.com/boynet/Framework7-Indexed-List-plugin
|
||||
*
|
||||
* Copyright 2015, boynet
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
* Released on: 17 Sep, 2014
|
||||
*/
|
||||
Framework7.prototype.plugins.indexedlist=function(t,e){function n(e){function n(t){t.preventDefault(),c=!0;var e=i(t.target);e.is("li")||(e=e.parents("li")),e.length>0&&o(e.eq(0).data("index-letter"))}function a(t){if(c){t.preventDefault();var e;(e=i("mousemove"===t.type?t.target:document.elementFromPoint(t.touches[0].pageX,t.touches[0].pageY))).is("li")||(e=e.parents("li")),0!==e.length&&(e.length>0&&!e.is(".list-index li")||o(e.eq(0).data("index-letter")))}}function r(t){c=d=!1}function o(t){var e=s.find('.list-group ul li[data-index-letter="'+t+'"]').parent();if(e.length){var n=e.offset().top+s.scrollTop()-(p?52:0)-(u?52:0);s.scrollTop(n)}}var l=i(e.container).find(".list-index");if(0!==l.length){var s=i(e.container).find(".page-content");!function(){var t=[],e="";s.find(".list-group").each(function(){var n=i(this).find("ul .list-group-title"),a=n.html().trim().charAt(0).toUpperCase();n.attr("data-index-letter",a),e+='<li data-index-letter="'+a+'">'+a+"</li>",t.push(a)}),l.html(e)}();var c,d,p=s.parents(".navbar-fixed").length>0||s.parents(".navbar-through").length>0,u=i(e.container).find(".searchbar").length>0;u&&l.css("margin-top","52px"),i(e.container).on("click",".list-index li",function(t){var e=i(t.target);e.is("li")||(e=e.parents("li")),e.length>0&&o(e.eq(0).data("index-letter"))}),l.on(t.touchEvents.start,n),l.on(t.touchEvents.move,a),l.on(t.touchEvents.end,r)}}var i=window.Dom7;return{hooks:{pageInit:n}}};
|
||||
@@ -0,0 +1,226 @@
|
||||
/**
|
||||
* Framework7 Keypad 1.0.3
|
||||
* Keypad plugin extends Framework7 with additional custom keyboards
|
||||
*
|
||||
* http://www.idangero.us/framework7/plugins/
|
||||
*
|
||||
* Copyright 2015, Vladimir Kharlampidi
|
||||
* The iDangero.us
|
||||
* http://www.idangero.us/
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
* Released on: August 22, 2015
|
||||
*/
|
||||
.picker-keypad.picker-modal-inline {
|
||||
height: 200px;
|
||||
}
|
||||
.picker-keypad.picker-modal-inline.picker-keypad-type-calculator {
|
||||
height: 260px;
|
||||
}
|
||||
@media (orientation: landscape) and (max-height: 415px) {
|
||||
.picker-keypad:not(.picker-modal-inline) {
|
||||
height: 200px;
|
||||
}
|
||||
}
|
||||
.picker-keypad .picker-modal-inner:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background-color: rgba(92, 94, 96, 0.35);
|
||||
display: block;
|
||||
z-index: 15;
|
||||
-webkit-transform-origin: 50% 0%;
|
||||
transform-origin: 50% 0%;
|
||||
}
|
||||
html.ios-gt-6.pixel-ratio-2 .picker-keypad .picker-modal-inner:before {
|
||||
-webkit-transform: scaleY(0.5);
|
||||
transform: scaleY(0.5);
|
||||
}
|
||||
html.ios-gt-6.pixel-ratio-3 .picker-keypad .picker-modal-inner:before {
|
||||
-webkit-transform: scaleY(0.33);
|
||||
transform: scaleY(0.33);
|
||||
}
|
||||
.picker-keypad.picker-modal-inline .picker-modal-inner:before,
|
||||
.popover.popover-picker-keypad .picker-keypad .picker-modal-inner:before {
|
||||
display: none;
|
||||
}
|
||||
i.icon-keypad-delete {
|
||||
width: 22px;
|
||||
height: 16px;
|
||||
background-size: 22px 16px;
|
||||
background-image: url("data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 16'><path d='M18,0h-8C8.9,0,7.9,0.5,7.1,1.2c0,0,0,0,0,0L1,7.2C0.6,7.7,0.6,8.4,1,8.8l4.9,4.7L7,14.6c0,0,0,0,0,0c0.7,0.9,1.8,1.4,3,1.4 h8c2.2,0,4-1.8,4-4V4C22,1.8,20.2,0,18,0z M17.3,11.2l-0.7,0.7l-3.2-3.2l-3.2,3.2l-0.7-0.7L12.8,8L9.6,4.8l0.7-0.7l3.2,3.2l3.2-3.2 l0.7,0.7L14.2,8L17.3,11.2z' fill='%23000000'/></svg>");
|
||||
}
|
||||
.picker-keypad-buttons {
|
||||
color: #000;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-box-lines: multiple;
|
||||
-moz-box-lines: multiple;
|
||||
-webkit-flex-wrap: wrap;
|
||||
-ms-flex-wrap: wrap;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.picker-keypad-button {
|
||||
background: #fcfcfd;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
width: 33.33333333%;
|
||||
width: -webkit-calc(100% / 3);
|
||||
width: calc(100% / 3);
|
||||
height: 25%;
|
||||
display: -webkit-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
-webkit-box-orient: vertical;
|
||||
-moz-box-orient: vertical;
|
||||
-ms-flex-direction: column;
|
||||
-webkit-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-box-pack: center;
|
||||
-ms-flex-pack: center;
|
||||
-webkit-justify-content: center;
|
||||
justify-content: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
-webkit-align-items: center;
|
||||
align-items: center;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.picker-keypad-button:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
width: 1px;
|
||||
height: 100%;
|
||||
background-color: rgba(92, 94, 96, 0.35);
|
||||
display: block;
|
||||
z-index: 15;
|
||||
-webkit-transform-origin: 100% 50%;
|
||||
transform-origin: 100% 50%;
|
||||
}
|
||||
html.ios-gt-6.pixel-ratio-2 .picker-keypad-button:after {
|
||||
-webkit-transform: scaleX(0.5);
|
||||
transform: scaleX(0.5);
|
||||
}
|
||||
html.ios-gt-6.pixel-ratio-3 .picker-keypad-button:after {
|
||||
-webkit-transform: scaleX(0.33);
|
||||
transform: scaleX(0.33);
|
||||
}
|
||||
.picker-keypad-button:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
height: 1px;
|
||||
width: 100%;
|
||||
background-color: rgba(92, 94, 96, 0.35);
|
||||
display: block;
|
||||
z-index: 15;
|
||||
-webkit-transform-origin: 50% 0%;
|
||||
transform-origin: 50% 0%;
|
||||
}
|
||||
html.ios-gt-6.pixel-ratio-2 .picker-keypad-button:before {
|
||||
-webkit-transform: scaleY(0.5);
|
||||
transform: scaleY(0.5);
|
||||
}
|
||||
html.ios-gt-6.pixel-ratio-3 .picker-keypad-button:before {
|
||||
-webkit-transform: scaleY(0.33);
|
||||
transform: scaleY(0.33);
|
||||
}
|
||||
html:not(.watch-active-state) .picker-keypad-button:not(.picker-keypad-dummy-button):active,
|
||||
.picker-keypad-button:not(.picker-keypad-dummy-button).active-state {
|
||||
background: #bcc0c5;
|
||||
}
|
||||
.picker-keypad-button.picker-keypad-button-dark {
|
||||
background: #bcc0c5;
|
||||
}
|
||||
html:not(.watch-active-state) .picker-keypad-button.picker-keypad-button-dark:not(.picker-keypad-dummy-button):active,
|
||||
.picker-keypad-button.picker-keypad-button-dark:not(.picker-keypad-dummy-button).active-state {
|
||||
background: #fcfcfd;
|
||||
}
|
||||
.picker-keypad-button.picker-keypad-dummy-button {
|
||||
cursor: default;
|
||||
}
|
||||
.picker-keypad-type-numpad .picker-keypad-button:nth-child(3n):after {
|
||||
display: none;
|
||||
}
|
||||
.picker-keypad-type-numpad .picker-keypad-button:nth-child(-n + 3):before {
|
||||
display: none;
|
||||
}
|
||||
.picker-keypad-type-numpad .picker-keypad-button.picker-keypad-button-double {
|
||||
width: 66.66666667%;
|
||||
width: -webkit-calc(100% / 3 * 2);
|
||||
width: calc(100% / 3 * 2);
|
||||
}
|
||||
.picker-keypad-type-calculator .picker-keypad-button {
|
||||
width: 25%;
|
||||
height: 20%;
|
||||
font-weight: 300;
|
||||
}
|
||||
.picker-keypad-type-calculator .picker-keypad-button:nth-child(4n):after {
|
||||
display: none;
|
||||
}
|
||||
.picker-keypad-type-calculator .picker-keypad-button:nth-child(-n + 4):before {
|
||||
display: none;
|
||||
}
|
||||
.picker-keypad-type-calculator .picker-keypad-button.picker-keypad-button-double {
|
||||
width: 50%;
|
||||
}
|
||||
.picker-keypad-button.calc-operator-button {
|
||||
color: #fff;
|
||||
background: #ff9500;
|
||||
}
|
||||
html:not(.watch-active-state) .picker-keypad-button.calc-operator-button:active,
|
||||
.picker-keypad-button.calc-operator-button.active-state {
|
||||
background: #e0750e;
|
||||
}
|
||||
.picker-keypad-button.calc-operator-button.calc-operator-active {
|
||||
border: 1px solid rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
.picker-keypad-button-number,
|
||||
.picker-keypad-button-letters {
|
||||
display: block;
|
||||
}
|
||||
.picker-keypad-button-number {
|
||||
font-size: 28px;
|
||||
line-height: 1;
|
||||
}
|
||||
.picker-keypad-button-letters {
|
||||
font-size: 11px;
|
||||
line-height: 15px;
|
||||
height: 15px;
|
||||
}
|
||||
.list-block input[type="numpad"],
|
||||
.list-block input[type="calculator"] {
|
||||
-webkit-appearance: none;
|
||||
-moz-appearance: none;
|
||||
-ms-appearance: none;
|
||||
appearance: none;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
background: none;
|
||||
border-radius: 0 0 0 0;
|
||||
-webkit-box-shadow: none;
|
||||
box-shadow: none;
|
||||
display: block;
|
||||
padding: 0 0 0 5px;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 43px;
|
||||
color: #000;
|
||||
font-size: 17px;
|
||||
font-family: inherit;
|
||||
}
|
||||
@@ -0,0 +1,648 @@
|
||||
/**
|
||||
* Framework7 Keypad 1.0.3
|
||||
* Keypad plugin extends Framework7 with additional custom keyboards
|
||||
*
|
||||
* http://www.idangero.us/framework7/plugins/
|
||||
*
|
||||
* Copyright 2015, Vladimir Kharlampidi
|
||||
* The iDangero.us
|
||||
* http://www.idangero.us/
|
||||
*
|
||||
* Licensed under MIT
|
||||
*
|
||||
* Released on: August 22, 2015
|
||||
*/
|
||||
Framework7.prototype.plugins.keypad = function (app) {
|
||||
'use strict';
|
||||
var $ = window.Dom7;
|
||||
var t7 = window.Template7;
|
||||
|
||||
var Keypad = function (params) {
|
||||
var p = this;
|
||||
|
||||
var defaults = {
|
||||
type: 'numpad', //or 'calculator' or 'custom',
|
||||
valueMaxLength: null,
|
||||
dotButton: true,
|
||||
dotCharacter: '.',
|
||||
buttons: (function () {
|
||||
var dotCharacter = params.dotCharacter || '.';
|
||||
if (typeof params.type === 'undefined' || params.type === 'numpad') {
|
||||
// numpad
|
||||
var dotButton = params.dotButton === undefined ? true : params.dotButton;
|
||||
return [
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">1</span><span class="picker-keypad-button-letters"></span>',
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">2</span><span class="picker-keypad-button-letters">ABC</span>',
|
||||
value: 2
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">3</span><span class="picker-keypad-button-letters">DEF</span>',
|
||||
value: 3
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">4</span><span class="picker-keypad-button-letters">GHI</span>',
|
||||
value: 4
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">5</span><span class="picker-keypad-button-letters">JKL</span>',
|
||||
value: 5
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">6</span><span class="picker-keypad-button-letters">MNO</span>',
|
||||
value: 6
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">7</span><span class="picker-keypad-button-letters">PQRS</span>',
|
||||
value: 7
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">8</span><span class="picker-keypad-button-letters">TUV</span>',
|
||||
value: 8
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">9</span><span class="picker-keypad-button-letters">WXYZ</span>',
|
||||
value: 9
|
||||
},
|
||||
{
|
||||
html: dotButton ? '<span class="picker-keypad-button-number">' + dotCharacter + '</span>' : '',
|
||||
value: dotButton ? dotCharacter : undefined,
|
||||
dark: true,
|
||||
cssClass: dotButton ? '' : 'picker-keypad-dummy-button'
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">0</span>',
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
html: '<i class="icon icon-keypad-delete"></i>',
|
||||
cssClass: 'picker-keypad-delete',
|
||||
dark: true
|
||||
},
|
||||
];
|
||||
}
|
||||
else if (params.type === 'calculator') {
|
||||
// calculator
|
||||
return [
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">C</span>',
|
||||
value: 'C',
|
||||
dark:true,
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">±</span>',
|
||||
value: '±',
|
||||
dark:true,
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">%</span>',
|
||||
value: '%',
|
||||
dark:true,
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">÷</span>',
|
||||
value: '÷',
|
||||
cssClass: 'calc-operator-button'
|
||||
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">7</span>',
|
||||
value: 7
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">8</span>',
|
||||
value: 8
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">9</span>',
|
||||
value: 9
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">×</span>',
|
||||
value: '×',
|
||||
cssClass: 'calc-operator-button'
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">4</span>',
|
||||
value: 4
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">5</span>',
|
||||
value: 5
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">6</span>',
|
||||
value: 6
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">-</span>',
|
||||
value: '-',
|
||||
cssClass: 'calc-operator-button'
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">1</span>',
|
||||
value: 1
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">2</span>',
|
||||
value: 2
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">3</span>',
|
||||
value: 3
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">+</span>',
|
||||
value: '+',
|
||||
cssClass: 'calc-operator-button'
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">0</span>',
|
||||
value: 0,
|
||||
cssClass: 'picker-keypad-button-double'
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">.</span>',
|
||||
value: dotCharacter
|
||||
},
|
||||
{
|
||||
html: '<span class="picker-keypad-button-number">=</span>',
|
||||
value: '=',
|
||||
cssClass: 'calc-operator-button calc-operator-button-equal'
|
||||
},
|
||||
];
|
||||
}
|
||||
else {
|
||||
// custom
|
||||
return [];
|
||||
}
|
||||
})(),
|
||||
// Common settings
|
||||
closeByOutsideClick: true,
|
||||
scrollToInput: true,
|
||||
inputReadOnly: true,
|
||||
convertToPopover: true,
|
||||
onlyInPopover: false,
|
||||
toolbar: true,
|
||||
toolbarCloseText: 'Done',
|
||||
toolbarTemplate:
|
||||
'<div class="toolbar">' +
|
||||
'<div class="toolbar-inner">' +
|
||||
'<div class="left"></div>' +
|
||||
'<div class="right">' +
|
||||
'<a href="#" class="link close-picker">{{closeText}}</a>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>'
|
||||
};
|
||||
params = params || {};
|
||||
for (var def in defaults) {
|
||||
if (typeof params[def] === 'undefined') {
|
||||
params[def] = defaults[def];
|
||||
}
|
||||
}
|
||||
p.params = params;
|
||||
p.cols = [];
|
||||
p.initialized = false;
|
||||
|
||||
// Inline flag
|
||||
p.inline = p.params.container ? true : false;
|
||||
|
||||
// 3D Transforms origin bug, only on safari
|
||||
var originBug = app.device.ios || (navigator.userAgent.toLowerCase().indexOf('safari') >= 0 && navigator.userAgent.toLowerCase().indexOf('chrome') < 0) && !app.device.android;
|
||||
|
||||
// Should be converted to popover
|
||||
function isPopover() {
|
||||
var toPopover = false;
|
||||
if (!p.params.convertToPopover && !p.params.onlyInPopover) return toPopover;
|
||||
if (!p.inline && p.params.input) {
|
||||
if (p.params.onlyInPopover) toPopover = true;
|
||||
else {
|
||||
if (app.device.ios) {
|
||||
toPopover = app.device.ipad ? true : false;
|
||||
}
|
||||
else {
|
||||
if ($(window).width() >= 768) toPopover = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return toPopover;
|
||||
}
|
||||
function inPopover() {
|
||||
if (p.opened && p.container && p.container.length > 0 && p.container.parents('.popover').length > 0) return true;
|
||||
else return false;
|
||||
}
|
||||
// Calculator
|
||||
var calcValues = [];
|
||||
var calcOperations = [];
|
||||
var lastWasNumber = false;
|
||||
p.calculator = function (value) {
|
||||
var operators = ('+ - = × ÷ ± %').split(' ');
|
||||
var numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, '.'];
|
||||
var reset = 'C';
|
||||
var invert = '±';
|
||||
var perc = '%';
|
||||
function calc () {
|
||||
var toEval = '';
|
||||
for (var i = 0; i < calcOperations.length; i++) {
|
||||
var operation = calcOperations[i];
|
||||
if (i === calcOperations.length - 1 && operators.indexOf(operation) >= 0) {
|
||||
|
||||
}
|
||||
else if (operation) {
|
||||
if (operation === '.') {
|
||||
operation = 0;
|
||||
}
|
||||
toEval += (operation.toString() + '')
|
||||
.replace('×', '*')
|
||||
.replace('÷', '/');
|
||||
}
|
||||
}
|
||||
toEval = toEval.replace(/--/g, '+');
|
||||
p.setValue(eval.call(window, toEval));
|
||||
}
|
||||
if (!p.value) p.value = 0;
|
||||
if (value === reset) {
|
||||
p.setValue(0);
|
||||
calcValues = [];
|
||||
calcOperations = [];
|
||||
return;
|
||||
}
|
||||
if (numbers.indexOf(value) >= 0) {
|
||||
if (value === '.') {
|
||||
if (lastWasNumber && p.value.toString().indexOf('.') >= 0) return;
|
||||
}
|
||||
if (operators.indexOf(calcValues[calcValues.length - 1]) >= 0) {
|
||||
p.setValue(value);
|
||||
}
|
||||
else {
|
||||
p.setValue(p.value ? p.value + '' + value : value);
|
||||
}
|
||||
lastWasNumber = true;
|
||||
}
|
||||
if (operators.indexOf(value) >= 0) {
|
||||
if (value === invert) {
|
||||
if (p.value === '.') return;
|
||||
p.setValue(-1 * p.value);
|
||||
lastWasNumber = true;
|
||||
}
|
||||
else if (value === perc) {
|
||||
if (calcOperations[calcOperations.length - 2]) {
|
||||
var percents = p.value / 100;
|
||||
p.setValue(calcOperations[calcOperations.length - 2] * percents);
|
||||
}
|
||||
lastWasNumber = true;
|
||||
}
|
||||
else {
|
||||
var lastOperation = calcOperations[calcOperations.length - 1];
|
||||
if (value === '=') {
|
||||
if (calcOperations[calcOperations.length - 1] === '=') {
|
||||
if (calcOperations.length < 2) return;
|
||||
calcOperations.pop();
|
||||
var val1 = calcOperations[calcOperations.length - 2];
|
||||
var val2 = calcOperations[calcOperations.length - 1];
|
||||
calcOperations.push(val1);
|
||||
calcOperations.push(val2);
|
||||
}
|
||||
else {
|
||||
calcOperations.push(p.value);
|
||||
}
|
||||
calcOperations.push('=');
|
||||
calc();
|
||||
}
|
||||
else if (['-', '+', '×', '÷', '='].indexOf(lastOperation) >= 0) {
|
||||
if (lastOperation === '=') {
|
||||
calcOperations = [p.value, value];
|
||||
}
|
||||
if (['-', '+', '×', '÷'].indexOf(lastOperation) >= 0) {
|
||||
if (lastWasNumber) {
|
||||
if (['-', '+'].indexOf(lastOperation) >= 0 && ['×', '÷'].indexOf(value) >= 0) {
|
||||
calcOperations.push(p.value);
|
||||
calcOperations.push(value);
|
||||
}
|
||||
else {
|
||||
calcOperations.push(p.value);
|
||||
calcOperations.push(value);
|
||||
calc();
|
||||
}
|
||||
}
|
||||
else {
|
||||
calcOperations[calcOperations.length - 1] = value;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
calcOperations.push(p.value);
|
||||
calcOperations.push(value);
|
||||
calc();
|
||||
}
|
||||
lastWasNumber = false;
|
||||
}
|
||||
}
|
||||
if (value !== invert && value !== perc) calcValues.push(value);
|
||||
};
|
||||
// Value
|
||||
p.setValue = function (value) {
|
||||
p.updateValue(value);
|
||||
};
|
||||
p.updateValue = function (newValue) {
|
||||
p.value = newValue;
|
||||
if (p.params.valueMaxLength && p.value.length > p.params.valueMaxLength) {
|
||||
p.value = p.value.substring(0, p.params.valueMaxLength);
|
||||
}
|
||||
if (p.params.onChange) {
|
||||
p.params.onChange(p, p.value);
|
||||
}
|
||||
if (p.input && p.input.length > 0) {
|
||||
$(p.input).val(p.params.formatValue ? p.params.formatValue(p, p.value) : p.value);
|
||||
$(p.input).trigger('change');
|
||||
}
|
||||
};
|
||||
|
||||
// Columns Handlers
|
||||
p.initKeypadEvents = function () {
|
||||
var buttonsContainer = p.container.find('.picker-keypad-buttons');
|
||||
|
||||
function handleClick(e) {
|
||||
var buttonContainer = $(e.target);
|
||||
if (!buttonContainer.hasClass('picker-keypad-button')) {
|
||||
buttonContainer = buttonContainer.parents('.picker-keypad-button');
|
||||
}
|
||||
if (buttonContainer.length === 0) return;
|
||||
var button = p.params.buttons[buttonContainer.index()];
|
||||
var buttonValue = button.value;
|
||||
var currentValue = p.value;
|
||||
|
||||
if (p.params.type === 'numpad') {
|
||||
if (typeof currentValue === 'undefined') currentValue = '';
|
||||
if (buttonContainer.hasClass('picker-keypad-delete')) {
|
||||
currentValue = currentValue.substring(0, currentValue.length - 1);
|
||||
}
|
||||
else {
|
||||
if (typeof buttonValue !== 'undefined') {
|
||||
if (buttonValue === '.' && currentValue.indexOf('.') >= 0) {
|
||||
buttonValue = '';
|
||||
}
|
||||
currentValue += buttonValue;
|
||||
}
|
||||
}
|
||||
if (typeof currentValue !== 'undefined') p.setValue(currentValue);
|
||||
}
|
||||
if (p.params.type === 'calculator') {
|
||||
p.calculator(button.value);
|
||||
buttonsContainer.find('.calc-operator-active').removeClass('calc-operator-active');
|
||||
if (buttonContainer.hasClass('calc-operator-button') && !buttonContainer.hasClass('calc-operator-button-equal')) {
|
||||
buttonContainer.addClass('calc-operator-active');
|
||||
}
|
||||
}
|
||||
if (p.params.type === 'custom') {
|
||||
|
||||
}
|
||||
if (button.onClick) {
|
||||
button.onClick(p, button);
|
||||
}
|
||||
}
|
||||
|
||||
buttonsContainer.on('click', handleClick);
|
||||
|
||||
p.container[0].f7DestroyKeypadEvents = function () {
|
||||
buttonsContainer.off('click', handleClick);
|
||||
};
|
||||
|
||||
};
|
||||
p.destroyKeypadEvents = function (colContainer) {
|
||||
if ('f7DestroyKeypadEvents' in p.container[0]) p.container[0].f7DestroyKeypadEvents();
|
||||
};
|
||||
|
||||
// HTML Layout
|
||||
p.buttonsHTML = function () {
|
||||
var buttonsHTML = '', buttonClass, button;
|
||||
for (var i = 0; i < p.params.buttons.length; i++) {
|
||||
button = p.params.buttons[i];
|
||||
buttonClass = 'picker-keypad-button';
|
||||
if (button.dark) buttonClass += ' picker-keypad-button-dark';
|
||||
if (button.cssClass) buttonClass += ' ' + button.cssClass;
|
||||
buttonsHTML += '<span class="' + buttonClass + '">' + (button.html || '') + '</span>';
|
||||
}
|
||||
return buttonsHTML;
|
||||
};
|
||||
p.layout = function () {
|
||||
var pickerHTML = '';
|
||||
var pickerClass = '';
|
||||
var i;
|
||||
var buttonsHTML = p.buttonsHTML();
|
||||
pickerClass = 'picker-modal picker-keypad picker-keypad-type-' + p.params.type + ' ' + (p.params.cssClass || '');
|
||||
pickerHTML =
|
||||
'<div class="' + (pickerClass) + '">' +
|
||||
(p.params.toolbar ? p.params.toolbarTemplate.replace(/{{closeText}}/g, p.params.toolbarCloseText) : '') +
|
||||
'<div class="picker-modal-inner picker-keypad-buttons">' +
|
||||
buttonsHTML +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
|
||||
p.pickerHTML = pickerHTML;
|
||||
};
|
||||
|
||||
// Input Events
|
||||
function openOnInput(e) {
|
||||
e.preventDefault();
|
||||
if (p.opened) return;
|
||||
p.open();
|
||||
if (p.params.scrollToInput && !isPopover()) {
|
||||
var pageContent = p.input.parents('.page-content');
|
||||
if (pageContent.length === 0) return;
|
||||
|
||||
var paddingTop = parseInt(pageContent.css('padding-top'), 10),
|
||||
paddingBottom = parseInt(pageContent.css('padding-bottom'), 10),
|
||||
pageHeight = pageContent[0].offsetHeight - paddingTop - p.container.height(),
|
||||
pageScrollHeight = pageContent[0].scrollHeight - paddingTop - p.container.height(),
|
||||
newPaddingBottom;
|
||||
var inputTop = p.input.offset().top - paddingTop + p.input[0].offsetHeight;
|
||||
if (inputTop > pageHeight) {
|
||||
var scrollTop = pageContent.scrollTop() + inputTop - pageHeight;
|
||||
if (scrollTop + pageHeight > pageScrollHeight) {
|
||||
newPaddingBottom = scrollTop + pageHeight - pageScrollHeight + paddingBottom;
|
||||
if (pageHeight === pageScrollHeight) {
|
||||
newPaddingBottom = p.container.height();
|
||||
}
|
||||
pageContent.css({'padding-bottom': (newPaddingBottom) + 'px'});
|
||||
}
|
||||
pageContent.scrollTop(scrollTop, 300);
|
||||
}
|
||||
}
|
||||
}
|
||||
function closeOnHTMLClick(e) {
|
||||
if (inPopover()) return;
|
||||
if (p.input && p.input.length > 0) {
|
||||
if (e.target !== p.input[0] && $(e.target).parents('.picker-modal').length === 0) {
|
||||
p.close();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($(e.target).parents('.picker-modal').length === 0) p.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (p.params.input) {
|
||||
p.input = $(p.params.input);
|
||||
if (p.input.length > 0) {
|
||||
if (p.params.inputReadOnly) p.input.prop('readOnly', true);
|
||||
if (!p.inline) {
|
||||
p.input.on('click', openOnInput);
|
||||
}
|
||||
if (p.params.inputReadOnly) {
|
||||
p.input.on('focus mousedown', function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!p.inline && p.params.closeByOutsideClick) $('html').on('click', closeOnHTMLClick);
|
||||
|
||||
// Open
|
||||
function onPickerClose() {
|
||||
p.opened = false;
|
||||
if (p.input && p.input.length > 0) {
|
||||
p.input.parents('.page-content').css({'padding-bottom': ''});
|
||||
if (app.params.material) p.input.trigger('blur');
|
||||
}
|
||||
if (p.params.onClose) p.params.onClose(p);
|
||||
|
||||
// Destroy events
|
||||
p.container.find('.picker-items-col').each(function () {
|
||||
p.destroyPickerCol(this);
|
||||
});
|
||||
}
|
||||
|
||||
p.opened = false;
|
||||
p.open = function () {
|
||||
var toPopover = isPopover();
|
||||
|
||||
if (!p.opened) {
|
||||
|
||||
// Layout
|
||||
p.layout();
|
||||
|
||||
// Append
|
||||
if (toPopover) {
|
||||
p.pickerHTML = '<div class="popover popover-picker-keypad"><div class="popover-inner">' + p.pickerHTML + '</div></div>';
|
||||
p.popover = app.popover(p.pickerHTML, p.params.input, true);
|
||||
p.container = $(p.popover).find('.picker-modal');
|
||||
$(p.popover).on('close', function () {
|
||||
onPickerClose();
|
||||
});
|
||||
}
|
||||
else if (p.inline) {
|
||||
p.container = $(p.pickerHTML);
|
||||
p.container.addClass('picker-modal-inline');
|
||||
$(p.params.container).append(p.container);
|
||||
}
|
||||
else {
|
||||
p.container = $(app.pickerModal(p.pickerHTML));
|
||||
$(p.container)
|
||||
.on('close', function () {
|
||||
onPickerClose();
|
||||
});
|
||||
}
|
||||
|
||||
// Store picker instance
|
||||
p.container[0].f7Keypad = p;
|
||||
|
||||
// Init Events
|
||||
p.initKeypadEvents();
|
||||
|
||||
// Set value
|
||||
if (!p.initialized) {
|
||||
if (p.params.value) {
|
||||
p.setValue(p.params.value);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (p.value) p.setValue(p.value);
|
||||
}
|
||||
|
||||
// Material Focus
|
||||
if (p.input && p.input.length > 0 && app.params.material) {
|
||||
p.input.trigger('focus');
|
||||
}
|
||||
}
|
||||
|
||||
// Set flag
|
||||
p.opened = true;
|
||||
p.initialized = true;
|
||||
|
||||
if (p.params.onOpen) p.params.onOpen(p);
|
||||
};
|
||||
|
||||
// Close
|
||||
p.close = function () {
|
||||
if (!p.opened || p.inline) return;
|
||||
if (inPopover()) {
|
||||
app.closeModal(p.popover);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
app.closeModal(p.container);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Destroy
|
||||
p.destroy = function () {
|
||||
p.close();
|
||||
if (p.params.input && p.input.length > 0) {
|
||||
p.input.off('click focus', openOnInput);
|
||||
}
|
||||
$('html').off('click', closeOnHTMLClick);
|
||||
};
|
||||
|
||||
if (p.inline) {
|
||||
p.open();
|
||||
}
|
||||
|
||||
return p;
|
||||
};
|
||||
|
||||
app.keypad = function (params) {
|
||||
return new Keypad(params);
|
||||
};
|
||||
function pageInit(page) {
|
||||
$(page.container).find('input[type="numpad"], input[type="calculator"]').each(function () {
|
||||
var input = $(this);
|
||||
input[0].f7Keypad = new Keypad({
|
||||
input: input,
|
||||
type: input.attr('type'),
|
||||
value: input.val() || 0,
|
||||
valueMaxLength: input.attr('maxlength') || undefined,
|
||||
toolbar: input.attr('data-toolbar') === 'false' ? false : true,
|
||||
toolbarCloseText: input.attr('data-toolbarCloseText') || undefined
|
||||
});
|
||||
});
|
||||
$(page.container).find('.numpad-init, .calculator-init').each(function () {
|
||||
var inline = $(this);
|
||||
var type;
|
||||
if (inline.hasClass('calculator-init')) type = 'calculator';
|
||||
if (inline.hasClass('numpad-init')) type = 'numpad';
|
||||
inline[0].f7Keypad = new Keypad({
|
||||
input: inline.attr('data-input') || undefined,
|
||||
type: type,
|
||||
value: inline.attr('data-value') || undefined,
|
||||
valueMaxLength: input.attr('maxlength') || undefined,
|
||||
toolbar: input.attr('data-toolbar') === 'false' ? false : true,
|
||||
toolbarCloseText: input.attr('data-toolbarCloseText') || undefined
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
hooks : {
|
||||
pageInit: pageInit,
|
||||
}
|
||||
};
|
||||
};
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,86 @@
|
||||
# Toast for Framework7
|
||||
|
||||
A plugin for Framwork7 to show little black toasts iOS-style
|
||||
|
||||
## Screenshot
|
||||
|
||||

|
||||
|
||||
## Video
|
||||
|
||||
https://www.youtube.com/watch?v=1qCRmpyQCuw&feature=youtu.be
|
||||
|
||||
## Live demo
|
||||
|
||||
http://www.timo-ernst.net/misc/toastdemo/
|
||||
|
||||
## How to use
|
||||
|
||||
### 1. Add the script to your project (after Framework7 script!) and also add CSS reference:
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="toast.css">
|
||||
<script src="toast.js"></script>
|
||||
```
|
||||
|
||||
### 2. Create a new toast
|
||||
|
||||
You can create a new toast with a icon:
|
||||
|
||||
```javascript
|
||||
var app = new Framework7();
|
||||
var options = {};
|
||||
var toast = app.toast('Marked star', '<div>☆</div>', options);
|
||||
```
|
||||
|
||||
As first parameter you set the message which gets displayed at the bottom of the toast. As 2nd parameter you have to set the icon. You can use free HTML here so set what ever you want (ASCii, Font-Icon, Images, SVG...). Third is reserved for options.
|
||||
|
||||
If you just want to show a message, let 2nd parameter empty:
|
||||
|
||||
```javascript
|
||||
var app = new Framework7();
|
||||
var options = {};
|
||||
var toast = app.toast('A long long message', '', options);
|
||||
```
|
||||
|
||||
### 3. Now you can show or hide the box:
|
||||
|
||||
```javascript
|
||||
// show
|
||||
toast.show();
|
||||
|
||||
// hide
|
||||
toast.hide();
|
||||
```
|
||||
|
||||
***Note:*** *In older versions of this plugin these methods were `toast.show(true)` and `toast.show(false)` but these were replaced by `toast.show()` and `toast.hide()` which is a little more convenient. You might have to change this in your code though if you upgrade from an older version.*
|
||||
|
||||
You can also change what message is displayed **after** initialization:
|
||||
|
||||
```javascript
|
||||
toast.show("message");
|
||||
```
|
||||
|
||||
### 4. Options & Callbacks
|
||||
|
||||
You can set the following options:
|
||||
|
||||
```javascript
|
||||
var app = new Framework7();
|
||||
var options = {
|
||||
// Callback gets called when toast is hidden
|
||||
onHide: function () {
|
||||
console.log('hidden');
|
||||
},
|
||||
duration: 2000 // Hide toast after 2 seconds
|
||||
};
|
||||
var toast = app.toast('Marked star', '<div>☆</div>', options);
|
||||
```
|
||||
|
||||
You're done :D
|
||||
|
||||
Made with <3 by www.timo-ernst.net
|
||||
|
||||
## License
|
||||
|
||||
MIT - Do what ever you want ;-)
|
||||
@@ -0,0 +1,34 @@
|
||||
.toast-container {
|
||||
position: fixed;
|
||||
width: 150px;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
padding: 16px;
|
||||
background-color: rgba(0, 0, 0, 0.7);
|
||||
border-radius: 16px;
|
||||
z-index: 11800;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
font-weight: normal;
|
||||
display: none;
|
||||
opacity: 0;
|
||||
transition: opacity 0.8s;
|
||||
}
|
||||
|
||||
.toast-container.show {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.toast-container.fadein {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.toast-icon {
|
||||
font-size: 48px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.toast-msg {
|
||||
text-align: center;
|
||||
font-weight: normal;
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* A plugin for Framework7 to show black little toasts
|
||||
*
|
||||
* @author www.timo-ernst.net
|
||||
* @license MIT
|
||||
*/
|
||||
Framework7.prototype.plugins.toast = function (app, globalPluginParams) {
|
||||
'use strict';
|
||||
|
||||
var Toast = function (text, iconhtml, options) {
|
||||
var self = this,
|
||||
$$ = Dom7,
|
||||
$box;
|
||||
|
||||
function hideBox($curbox) {
|
||||
if ($curbox) {
|
||||
$curbox.removeClass('fadein').transitionEnd(function () {
|
||||
$curbox.remove();
|
||||
if (options && typeof options.onHide == 'function') options.onHide();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function isString(obj) {
|
||||
return toString.call(obj) === '[object String]';
|
||||
}
|
||||
|
||||
this.show = function (message) {
|
||||
var clientLeft,
|
||||
$curbox,
|
||||
html = [];
|
||||
|
||||
// Remove old toasts first if there are still any
|
||||
$$('.toast-container').off('click').off('transitionEnd').remove();
|
||||
$box = $$('<div class="toast-container show">');
|
||||
|
||||
// Add content
|
||||
if (isString(iconhtml) && iconhtml.length > 0) {
|
||||
html.push(
|
||||
'<div class="toast-icon">' +
|
||||
iconhtml +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
|
||||
if (isString(message) && message.length > 0) {
|
||||
text = message;
|
||||
}
|
||||
|
||||
if (isString(text) && text.length > 0) {
|
||||
html.push(
|
||||
'<div class="toast-msg">' +
|
||||
text +
|
||||
'</div>'
|
||||
);
|
||||
}
|
||||
|
||||
$box.html(
|
||||
html.join('')
|
||||
);
|
||||
|
||||
// Add to DOM
|
||||
clientLeft = $box[0].clientLeft;
|
||||
$$('body').append($box);
|
||||
|
||||
$box.css('margin-top', $box.outerHeight() / -2 + 'px')
|
||||
.css('margin-left', $box.outerWidth() / -2 + 'px');
|
||||
|
||||
// Hide box on click
|
||||
$box.click(function () {
|
||||
hideBox($box);
|
||||
});
|
||||
|
||||
// Dirty hack to cause relayout xD
|
||||
clientLeft = $box[0].clientLeft;
|
||||
|
||||
// Fade in toast
|
||||
$box.addClass('fadein');
|
||||
|
||||
var duration = options && options.duration ? options.duration : 1500;
|
||||
|
||||
// Automatically hide box after few seconds
|
||||
$curbox = $box;
|
||||
setTimeout(function () {
|
||||
hideBox($curbox);
|
||||
}, duration);
|
||||
};
|
||||
|
||||
this.hide = function() {
|
||||
hideBox($box);
|
||||
};
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
app.toast = function (text, iconhtml, options) {
|
||||
return new Toast(text, iconhtml, options);
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,105 @@
|
||||
# Framework7 Plugin Tour Guide
|
||||
|
||||
## Brief description
|
||||
A plugin that takes advantage of Framework7 Popover elements to display a tour guide through your application.
|
||||
|
||||
## Screenshots
|
||||
|
||||
### Main Screen
|
||||
<img src="https://github.com/razekteixeira/Framework7-Plugin-Tour-Guide/blob/master/example/assets/screens/Main%20Screen.png" width="250">
|
||||
|
||||
### First Step
|
||||
<img src="https://github.com/razekteixeira/Framework7-Plugin-Tour-Guide/blob/master/example/assets/screens/First%20Step.png" width="250">
|
||||
|
||||
### Second Step
|
||||
<img src="https://github.com/razekteixeira/Framework7-Plugin-Tour-Guide/blob/master/example/assets/screens/Second%20Step.png" width="250">
|
||||
|
||||
### Last Step
|
||||
<img src="https://github.com/razekteixeira/Framework7-Plugin-Tour-Guide/blob/master/example/assets/screens/Last%20Step.png" width="250">
|
||||
|
||||
## Setup
|
||||
|
||||
1) Copy tourguide.css and tourguide.js to your project and reference them:
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="tourguide.css">
|
||||
<script src="tourguide.js"></script>
|
||||
```
|
||||
2) Define tour steps
|
||||
|
||||
```javascript
|
||||
var tourSteps = [
|
||||
{
|
||||
step: 0,
|
||||
header: '1st Tour Step',
|
||||
message: 'This is our first tour step.<br />Please click "next" or "back" to move forward and backwards respectively',
|
||||
element: "body > div.views > div > div.toolbar > div > a:nth-child(1)",
|
||||
action: function ()
|
||||
{
|
||||
console.log('Started guided tour');
|
||||
console.log('Step 0');
|
||||
}
|
||||
},
|
||||
{
|
||||
step: 1,
|
||||
header: '2nd Tour Step',
|
||||
message: 'This is our seconds tour step.<br />You can use icons and images too! Wow!<br /><br /> F7 Icon:<br /> <i class="icon icon-back"></i><br /><br />Image:<br /> <div style="background-image: url(http://cdn.framework7.io/i/logo-new.png); width: 100px; height: 100px; background-size: cover; margin: 0 auto";></div><br />Please click "next" or "back" to move forward and backwards respectively',
|
||||
element: "body > div.views > div > div.navbar > div > div.right > a",
|
||||
action: function ()
|
||||
{
|
||||
console.log('Step 1');
|
||||
}
|
||||
},
|
||||
{
|
||||
step: 2,
|
||||
header: '3rd and Final Step',
|
||||
message: 'Congratulations! You have finished your Tour Guide tutorial. Enjoy it :D',
|
||||
element: "body > div.views > div > div.navbar > div > div.right > a",
|
||||
action: function ()
|
||||
{
|
||||
console.log('Step 2');
|
||||
console.log('Last step on guided tour');
|
||||
}
|
||||
}];
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
- *step* Set a step id for this tour step
|
||||
- *header* Set the tour step header (plain text, HTML, ...)
|
||||
- *message* Set the tour step message (plain text, HTML, ...)
|
||||
- *element* Set the element where you want to point the tour step (CSS Selector)
|
||||
- *action* Define a function to execute some code snippet on current tour step or null if you don't want to do anything
|
||||
|
||||
3) Initialize & options
|
||||
|
||||
```javascript
|
||||
var myApp = new Framework7();
|
||||
var options = {...};
|
||||
|
||||
var tourguide = myApp.tourguide(tourSteps, options);
|
||||
```
|
||||
|
||||
Available options (if not set, default will be used)
|
||||
|
||||
- **previousButton** // optional, defaults to false
|
||||
- **nextButtonText** // optional next button text, defaults to 'Next'
|
||||
- **endTourButtonText** // optional endTourButtonText, defaults to 'Done'
|
||||
- **previousButtonText** // optional previousButtonText, defaults to 'Previous'
|
||||
- **template** // optional template for tour step, defaults to the defaultTourGuideTemplate
|
||||
- **customCSS** // optional css class, defaults to 'tour-guide-popover'
|
||||
|
||||
## API
|
||||
|
||||
The following methods are available on a tourguide instance
|
||||
|
||||
```javascript
|
||||
tourguide.moveForward(); // moves to next step
|
||||
tourguide.moveBackward(); // moves to previous step if allowed
|
||||
```
|
||||
|
||||
## Credits
|
||||
|
||||
Developed by www.cesarteixeira.pt
|
||||
|
||||
Please contribute ;)
|
||||
@@ -0,0 +1,15 @@
|
||||
.tour-guide-popover {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.tour-guide-popover .tour-guide-header-wrapper {
|
||||
padding: 0 14px;
|
||||
}
|
||||
|
||||
.tour-guide-popover .tour-guide-message-wrapper {
|
||||
padding: 0 14px;
|
||||
}
|
||||
|
||||
.tour-guide-popover .tour-guide-buttons-row {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -0,0 +1,289 @@
|
||||
/*jslint browser: true*/
|
||||
/*global console, Framework7, alert, Dom7, Template7*/
|
||||
|
||||
/**
|
||||
* A plugin for Framework7 to help you with a tour guide within your app
|
||||
*
|
||||
* @module Framework7/prototype/plugins/tourguide
|
||||
* @author www.timo-ernst.net
|
||||
* @license MIT
|
||||
*/
|
||||
Framework7.prototype.plugins.tourguide = function (app) {
|
||||
'use strict';
|
||||
// Variables in module scope
|
||||
var $$ = Dom7,
|
||||
t7 = Template7,
|
||||
defaultTourGuideTemplate,
|
||||
TourGuide;
|
||||
|
||||
/**
|
||||
* Represents the tour guide
|
||||
*
|
||||
* @class
|
||||
* @memberof module:Framework7/prototype/plugins/tourguide
|
||||
*/
|
||||
TourGuide = function (tourSteps, options, currentStep) {
|
||||
|
||||
// Private properties
|
||||
var self = this,
|
||||
defaults = {
|
||||
previousButton: false,
|
||||
nextButtonText: 'Next',
|
||||
endTourButtonText: 'Done',
|
||||
previousButtonText: 'Previous',
|
||||
template: defaultTourGuideTemplate,
|
||||
customCSS: 'tour-guide-popover'
|
||||
},
|
||||
template,
|
||||
options = options || {},
|
||||
tourSteps = tourSteps || [],
|
||||
currentStep = currentStep || 0;
|
||||
|
||||
function setDefaultTemplate () {
|
||||
defaultTourGuideTemplate = '<div class="popover popover-step-tutorial {{#if options.customCSS}}{{options.customCSS}}{{/if}}">' +
|
||||
'<div class="popover-angle"></div>' +
|
||||
'<div class="popover-inner">' +
|
||||
'<div class="tour-guide-container-wrapper">' +
|
||||
'<div class="tour-guide-header-wrapper"><p class="tour-guide-header">{{header}}</p></div>' +
|
||||
'<div class="tour-guide-message-wrapper"><p class="tour-guide-message">{{message}}</p></div>' +
|
||||
'</div>' +
|
||||
'<div class="tour-guide-toolbar-wrapper">' +
|
||||
'<div class="toolbar">' +
|
||||
'<div class="toolbar-inner">' +
|
||||
'<div class="row tour-guide-buttons-row">' +
|
||||
'{{#if options.previousButton}}' +
|
||||
'<div class="col-50">' +
|
||||
'<a href="#" class="button tour-guide-button tour-guide-previous-button" {{#unless options.enablePreviousButton}}disabled="disabled"{{/unless}}>{{options.previousButtonText}}</a>' +
|
||||
'</div>' +
|
||||
'{{/if}}' +
|
||||
'<div class="col-{{#if options.previousButton}}50{{else}}100{{/if}}">' +
|
||||
'<a href="#" class="button tour-guide-button tour-guide-next-button">{{#if options.lastStep}}{{options.endTourButtonText}}{{else}}{{options.nextButtonText}}{{/if}}</a>' +
|
||||
'</div>' +
|
||||
'</div> ' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
};
|
||||
|
||||
self.setMoveForwardAction = function () {
|
||||
// Click handler to move forward on tour
|
||||
$$(document).on('click', '.tour-guide-next-button', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
|
||||
currentStep++;
|
||||
|
||||
if (tourSteps.length === currentStep) {
|
||||
console.log('No more steps');
|
||||
}
|
||||
else {
|
||||
console.log('Next step');
|
||||
}
|
||||
|
||||
self.showTour(tourSteps, currentStep);
|
||||
});
|
||||
};
|
||||
|
||||
self.setMoveBackwardAction = function () {
|
||||
// Click handler to move forward on tour
|
||||
$$(document).on('click', '.tour-guide-previous-button', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
e.stopPropagation();
|
||||
console.log('previous step');
|
||||
|
||||
currentStep--;
|
||||
|
||||
self.showTour(tourSteps, currentStep);
|
||||
});
|
||||
};
|
||||
|
||||
self.moveFoward = function ()
|
||||
{
|
||||
if (+currentStep === tourSteps.length)
|
||||
{
|
||||
console.log('Last step, cannot move forward.');
|
||||
return;
|
||||
}
|
||||
|
||||
currentStep++;
|
||||
|
||||
if (tourSteps.length === currentStep) {
|
||||
console.log('No more steps');
|
||||
}
|
||||
else {
|
||||
console.log('Next step');
|
||||
}
|
||||
|
||||
self.showTour(tourSteps, currentStep);
|
||||
};
|
||||
|
||||
self.moveBackward = function ()
|
||||
{
|
||||
if (+currentStep === 0)
|
||||
{
|
||||
console.log('First step, cannot move backwards.');
|
||||
return;
|
||||
}
|
||||
|
||||
currentStep--;
|
||||
|
||||
if (tourSteps.length === currentStep) {
|
||||
console.log('No more steps');
|
||||
}
|
||||
else {
|
||||
console.log('Next step');
|
||||
}
|
||||
|
||||
self.showTour(tourSteps, currentStep);
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows the tour guide
|
||||
*
|
||||
* @public
|
||||
* @memberof module:Framework7/prototype/plugins/tourguide
|
||||
*/
|
||||
self.showTour = function () {
|
||||
setTimeout(function () {
|
||||
try {
|
||||
// close previous modal if exists
|
||||
app.closeModal();
|
||||
|
||||
// terminate tour
|
||||
if (currentStep === (tourSteps.length)) {
|
||||
if (typeof tourSteps[currentStep] !== 'undefined' &&
|
||||
tourSteps[currentStep] !== null &&
|
||||
typeof tourSteps[currentStep].action !== "undefined" &&
|
||||
tourSteps[currentStep].action !== null &&
|
||||
typeof tourSteps[currentStep].action === "function") {
|
||||
tourSteps[currentStep].action();
|
||||
}
|
||||
|
||||
currentStep = 0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof tourSteps[currentStep].action !== "undefined" &&
|
||||
tourSteps[currentStep].action !== null &&
|
||||
typeof tourSteps[currentStep].action === "function") {
|
||||
tourSteps[currentStep].action();
|
||||
}
|
||||
|
||||
/*
|
||||
* popover arguments:
|
||||
* - tourStep html
|
||||
* - tourStep element
|
||||
* - removeOnClose
|
||||
* - animated
|
||||
* - closeByOutside
|
||||
*/
|
||||
app.popover(tourSteps[currentStep].html, tourSteps[currentStep].element, true, true, false);
|
||||
}
|
||||
catch (framework7NotReadyException) {
|
||||
console.log("Framework7 is not ready yet");
|
||||
console.log(framework7NotReadyException);
|
||||
}
|
||||
}, 100);
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the options that were required
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function applyOptions() {
|
||||
var def;
|
||||
options = options || {};
|
||||
for (def in defaults) {
|
||||
if (typeof options[def] === 'undefined') {
|
||||
options[def] = defaults[def];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compiles the template
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function compileTemplate() {
|
||||
if (!options.template) {
|
||||
// Cache compiled templates
|
||||
if (!app._compiledTemplates.tourguide) {
|
||||
app._compiledTemplates.tourguide = t7.compile(defaultTourGuideTemplate);
|
||||
}
|
||||
template = app._compiledTemplates.tourguide;
|
||||
} else {
|
||||
template = t7.compile(options.template);
|
||||
}
|
||||
}
|
||||
|
||||
self.prepareSteps = function () {
|
||||
for (var step in tourSteps) {
|
||||
var context = {};
|
||||
|
||||
if (tourSteps[step].header) {
|
||||
context.header = tourSteps[step].header;
|
||||
}
|
||||
|
||||
if (tourSteps[step].message) {
|
||||
context.message = tourSteps[step].message;
|
||||
}
|
||||
|
||||
if (options.previousButton &&
|
||||
step > 0) {
|
||||
options.enablePreviousButton = true;
|
||||
}
|
||||
|
||||
if (+step === tourSteps.length-1)
|
||||
{
|
||||
options.lastStep = true;
|
||||
}
|
||||
|
||||
context.options = options;
|
||||
|
||||
try {
|
||||
tourSteps[step].html = template(context);
|
||||
}
|
||||
catch (TemplateNotDefinedException) {
|
||||
console.log('Failed to compile template with context');
|
||||
console.log(TemplateNotDefinedException);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the instance
|
||||
*
|
||||
* @method init
|
||||
*/
|
||||
(function () {
|
||||
// define default template
|
||||
setDefaultTemplate();
|
||||
// Compile template
|
||||
compileTemplate();
|
||||
// apply options
|
||||
applyOptions();
|
||||
// Prepare steps
|
||||
self.prepareSteps();
|
||||
// set move forward action
|
||||
self.setMoveForwardAction();
|
||||
// set move backwards action
|
||||
self.setMoveBackwardAction();
|
||||
|
||||
}());
|
||||
|
||||
// Return instance
|
||||
return self;
|
||||
};
|
||||
|
||||
app.tourguide = function (tourSteps, options, currentStep) {
|
||||
return new TourGuide(tourSteps, options, currentStep);
|
||||
};
|
||||
|
||||
};
|
||||
Reference in New Issue
Block a user